diff --git a/.agents/skills/db-migrations/SKILL.md b/.agents/skills/db-migrations/SKILL.md index 884ad5a92a0..e980a8e2207 100644 --- a/.agents/skills/db-migrations/SKILL.md +++ b/.agents/skills/db-migrations/SKILL.md @@ -110,6 +110,7 @@ Run through this before requesting review. Each item is a real, recurring review - [ ] Identifiers go through **`escape.tableName(...)` / `escape.columnName(...)`**. Never hand-write `n8n_table` prefixes. — [Always escape identifiers](#always-escape-identifiers) - [ ] **Match column type to value semantics.** Native `uuid` for UUIDs, `timestampTimezone()` for timestamps, a numeric type for numbers, `bool` for booleans, `json` for structured data. Never `varchar` as a catch-all. — [Column types](#column-types) - [ ] **Pick the narrowest sane type within that category:** `int`/`smallint` not `bigint` when range allows; `text` not `varchar(255)` for unbounded strings; never `double` for version numbers. — [Column types](#column-types) +- [ ] **A generated `id` key is an integer** (`int.primary.autoGenerate2`). A UUID key is a UUIDv7. For a UUID or string key, write the reason in the PR description. A join table uses its foreign-key columns as the key, not an `id` column. — [Primary Keys](#primary-keys) - [ ] **Default `notNull`**, relax only when justified. PK is implicitly NOT NULL. Migration's `notNull` matches the entity's nullability. — [NOT NULL and entity parity](#not-null-and-entity-parity) - [ ] **Enum-like columns** carry `.withEnumCheck([...])` AND `.comment('explains values')`. Opaque IDs / unix timestamps / JSON shapes also get `.comment()`. — [Constrain enum-like strings](#constrain-enum-like-strings), [Add comments on columns](#add-comments-on-columns) - [ ] **Every reference column has an explicit FK** with deliberate `onDelete`. Name FKs explicitly when SQLite recreate cycles risk duplicating them. Avoid polymorphic `(typeCol, idCol)` patterns. — [Foreign Key Constraints](#foreign-key-constraints), [General Design Guidance](#general-design-guidance) @@ -439,11 +440,32 @@ Don't set the default of a `status` column to a terminal value — `"running"` m ### Primary Keys -Every table needs a primary key. Choose the type in this order: +Every table needs a primary key. **Use an integer key by default.** Read the options below in order. Use the first option that fits. Do not skip an option only because you like a later one better. -1. **Integer** — `column('id').int.primary.autoGenerate2`. Preferred for new tables: compact, fast joins, no ordering surprises. `autoGenerate2` uses Postgres `IDENTITY` (preferred over the deprecated `serial`-based `autoGenerate`). -2. **UUID** — `column('id').uuid.primary`. Use when IDs are generated client-side, exposed in URLs, or need to be unguessable. Generate UUIDs in application code via `randomUUID()` from `node:crypto`; do **not** chain `.autoGenerate2` on `.uuid` (the DSL throws — `DEFAULT uuid_generate_v4()` fails on managed Postgres like Supabase because it needs the `uuid-ossp` extension in `public`). Use `.uuid` instead of `.varchar(36)`. -3. **String** — `column('id').varchar(36).primary` for IDs whose format isn't a UUID (e.g. nanoid-style IDs). Convention: nanoid length 16 for entity IDs. +1. **Integer (default)** — `column('id').int.primary.autoGenerate2`. Use this for every new table. Use a different option only when one of its conditions is true. Integer keys are small and make joins fast. `autoGenerate2` uses Postgres `IDENTITY`. Do not use `autoGenerate`. It uses `serial`, which is deprecated. +2. **UUID** — `column('id').uuid.primary`. Use this only when one of these conditions is true: + - The application must know the ID before the insert. For example, the client makes the ID. + - The ID is in a URL or a public API. Users must not see how many rows exist or guess other IDs. + + **You must use UUIDv7.** Make the ID in application code with the `uuid` package: `import { v7 as uuidv7 } from 'uuid'`. + + Why: a UUIDv7 starts with a timestamp. Thus, new rows go near the end of the index. A UUIDv4 is random, for example `randomUUID()` from `node:crypto`. New rows go to random positions in the index. This splits index pages and makes the index larger. + + A UUIDv7 does not give an exact creation order. Two IDs made in the same millisecond can sort in the wrong order. Clock differences between hosts can also cause this. If you need the exact order, sort by a timestamp column. + + Do **not** chain `.autoGenerate2` on `.uuid`. The DSL throws an error. The database default makes a UUIDv4. Also, `uuid_generate_v4()` needs the `uuid-ossp` extension. Some managed Postgres services, such as Supabase, do not have it. Use `.uuid`, not `.varchar(36)`. +3. **String** — `column('id').varchar(36).primary`. Use this only when one of these conditions is true: + - The entity already uses IDs in a format that is not a UUID. For example, the public API or the UI already shows nanoid IDs for this entity. + - The UI shows the ID to users. A UUID is too long to read, copy, or type. + + Entity IDs are usually nanoids with 16 characters. + +**Give a reason for every key that is not an integer.** Write the reason in the PR description. Reviewers will ask for it. These reasons are not sufficient: +- "Other tables use string IDs." +- "This module already does it this way." +- "We might need it later." + +**These options apply to a generated `id` column only.** A join table that only links other tables does not need an `id` column. Use its foreign-key columns as a composite key (see below). A foreign-key column always has the same type as the key that it refers to. **Keep ID-column types consistent across related tables.** Mixing `uuid` and `varchar(36)` for what is "the same kind of ID" creates JOIN footguns. @@ -696,7 +718,7 @@ If only Postgres needs the change, just put the file in `postgresdb/`; don't wri ### Postgres-version-aware UUID generation -`gen_random_uuid()` requires Postgres ≥ 13. n8n dropped Postgres 12 — prefer it over `uuid_generate_v4()` (which needs the `uuid-ossp` extension and breaks on managed services like Supabase). For UUID PKs, generate at the application level with `randomUUID()` — see [Primary Keys](#primary-keys). +`gen_random_uuid()` requires Postgres ≥ 13. n8n dropped Postgres 12 — prefer it over `uuid_generate_v4()` (which needs the `uuid-ossp` extension and breaks on managed services like Supabase). For UUID PKs, make a UUIDv7 in application code — see [Primary Keys](#primary-keys). ### SQLite doesn't enforce `varchar(N)` length diff --git a/.agents/skills/env-var-docs/SKILL.md b/.agents/skills/env-var-docs/SKILL.md new file mode 100644 index 00000000000..4734f55fd01 --- /dev/null +++ b/.agents/skills/env-var-docs/SKILL.md @@ -0,0 +1,158 @@ +--- +name: n8n:env-var-docs +description: >- + Writes and reviews the JSDoc on `@Env(...)` config properties. The docs team + extracts these comments from source into the public environment variable + reference, so they are user documentation, not code comments. Use when adding + or changing an `@Env` property, a config class, or reviewing a PR that touches + one. +--- + +# Environment variable docs + +The JSDoc above every `@Env('...')` property is exported almost verbatim into +the [environment variables reference](https://docs.n8n.io/deploy/host-n8n/configure-n8n/basic-configuration/use-environment-variables) +on docs.n8n.io. The generated table has four columns: variable name, +description, data type, default. Your JSDoc is the description column. The +reader is a self-hosting operator, not an n8n developer. + +Follow the [n8n docs style guide](https://docs.n8n.io/contribute/contribution-guide-for-n8n-docs/style-guide-for-n8n-docs) +for these comments. It overrides the ASD-STE100 rule in `AGENTS.md` for this +one case. The rules below are the parts of that guide that matter for a +one-paragraph description. + +## Rules + +- **Every `@Env` property has a JSDoc.** No exceptions. A missing comment + ships as an empty description cell. +- **Write for the operator.** Say what the setting does, when to change it, + and what happens when it's unset or wrong. Don't explain why the code is + written the way it is. +- **No code references.** No file names, class names, function names, + constants, license keys, or other internals the reader can't open. Values + the operator types into the variable are fine and often needed, for example + a credential type ID like `googleOAuth2Api` or a mode like `postgresdb`. + The test: would the operator paste this into a config file, or would they + need the source to know what it means? Details for developers go in a + regular `//` comment on the implementation, not in the JSDoc. +- **No attack scenarios.** Say what the setting protects, not how an + attacker would exploit it. This is a public page. +- **Don't repeat the default.** The default renders in its own column. Don't + write "Defaults to true" or "Default: 1 hour". Do say what the unset state + means when it's not obvious, for example "When unset, n8n uses the Redis + host". +- **State units and formats.** Say "in milliseconds", "in bytes", "a + comma-separated list", "a JSON object". The data type column only says + `Number` or `String`. +- **Use allowed values when the set is small.** "One of `sqlite`, + `postgresdb`." For a list, show one inline example in the sentence. +- **No JSDoc tags.** No `@example`, `@default`, `@see`, `@deprecated`. The + exporter copies the tag name into the docs. Put the example or the + deprecation notice in a sentence instead. +- **Product names:** "Gateway credits", not "n8n Connect" or "AI Gateway". + "Publish a workflow", not "activate". `n8n` is always lowercase. +- **Style:** present tense, active voice, second person. Use contractions. + No em dashes, use a comma or a new sentence. No "e.g." or "i.e.", write + "for example" and "that is". Spell out zero to nine, numerals from 10. + Values the operator types stay numerals, for example "Set to 0". + Sentence case. One idea per sentence. End every sentence with a period. +- **Plain words:** "use" not "utilize", "lets you" not "allows you to", cut + "powerful", "seamless", "simply", "it's important to note". +- **Length:** one to three sentences. If the setting needs more, the extra + belongs in a docs page the comment can't link to yet; keep the comment to + what fits a table cell. + +## Examples + +Bad, as found in the generated docs: + +```ts +/** + * Instance-level enablement for n8n Connect (AI Gateway). Licensed instances + * are enabled by default; false opts out. Budget / free allowance still comes + * from the license (`quota:aiGatewayBudget`). + */ +``` + +Wrong product name, a restated default, and an internal license key. Good: + +```ts +/** + * Whether Gateway credits are available on this instance. Set to false to + * turn them off on a licensed instance. The credit allowance comes from your + * license. + */ +``` + +Bad: + +```ts +/** + * Time to live in milliseconds for Redis cache entries. Set to 0 to disable + * expiry. Default: 1 hour. + */ +``` + +The default is already in the table. Good: + +```ts +/** + * Time to live in milliseconds for Redis cache entries. Set to 0 to keep + * entries until Redis evicts them. + */ +``` + +Bad: + +```ts +/** + * Comma-separated list of credential types for which overwrites are skipped + * when the credential has been customized. + * @example `N8N_SKIP_CREDENTIAL_OVERWRITE=zohoOAuth2Api,salesforceOAuth2Api` + */ +``` + +The `@example` tag lands in the description as literal text. Good: + +```ts +/** + * Comma-separated list of credential types to skip when applying credential + * overwrites, for example `zohoOAuth2Api,salesforceOAuth2Api`. n8n skips an + * overwrite only when a user has already changed one of its fields. + */ +``` + +Bad: + +```ts +/** + * Bind OAuth credential callbacks to the browser that initiated the flow. + * When enabled, a session-scoped `n8n-oauth-binding` cookie is set on flow + * initiation and verified on callback. Defeats phishing attacks where an + * attacker injects an OAuth authorize URL into a victim's browser to land + * tokens on the attacker's credential. + */ +``` + +Attack narrative and an internal cookie name on a public page. Good: + +```ts +/** + * Whether an OAuth credential connection must finish in the same browser + * that started it. When enabled, n8n rejects the callback if it arrives + * from a different browser. + */ +``` + +## Review checklist + +When you review a PR that adds or changes an `@Env` property, check each +comment against this list and quote the fix in the review: + +1. JSDoc present. +2. No code identifiers, file names, or internal keys. +3. No default restated. +4. Units, format, or allowed values stated. +5. No JSDoc tags. +6. No em dashes, Latin abbreviations, or filler words. +7. Reads correctly as a sentence in a table cell with no surrounding context. diff --git a/.agents/skills/public-api/SKILL.md b/.agents/skills/public-api/SKILL.md index 66c6e02ff3a..c2c10d2e912 100644 --- a/.agents/skills/public-api/SKILL.md +++ b/.agents/skills/public-api/SKILL.md @@ -21,8 +21,7 @@ check the code, not license to drop a team default. ## Non-negotiable rules - New endpoints are `@PublicApiController` classes under `v1/controllers/`, one - `*.public.controller.ts` per feature. A controller is a class — never - `export =` (the legacy tuple style; `require-public-api-controller` flags it). + `*.public.controller.ts` per feature. - Public API and internal REST are separate HTTP surfaces. A public controller never calls an internal controller/endpoint; both reuse the same service. - Controllers and handlers delegate to a service — never import a repository or @@ -31,7 +30,6 @@ check the code, not license to drop a team default. `@ApiResponse(Dto)`. - Register each controller via a side-effect import in `v1/controllers/index.ts` (`public-api-controllers.test.ts` fails otherwise). -- Don't add business logic to legacy `express-openapi-validator` (EOV) handlers. - Migrating a legacy endpoint must not change its public contract. These are `n8n-local-rules` ESLint rules (see `packages/cli/eslint.config.mjs`) @@ -200,6 +198,5 @@ existing tests. - [Test-before-save endpoints](reference.md#test-before-save-endpoints) - [Errors](reference.md#errors) - [Testing matrix](reference.md#testing-matrix) -- [Migrating legacy EOV endpoints](reference.md#migrating-legacy-eov-endpoints) - [Verifying a migration](reference.md#verifying-a-migration) - [CI and merging](reference.md#ci-and-merging) diff --git a/.agents/skills/public-api/reference.md b/.agents/skills/public-api/reference.md index 52a3760546e..5d309dabf92 100644 --- a/.agents/skills/public-api/reference.md +++ b/.agents/skills/public-api/reference.md @@ -122,11 +122,10 @@ app-wide `bodyParser` before the registry sees it. Declaring - An unknown field (one the DTO doesn't declare, on a `{ strict: true }` DTO) fails with `Unexpected form field ""` — not the default "unrecognized keys" wording. -- Multer's own parsing errors map to the same statuses express-openapi-validator - used: `413` for a size/count limit, `400` for any other multer error, `500` - — unmasked, since this is a `ResponseError` — for anything else (a - malformed body; a missing boundary gives `400` with `multipart file(s) - required`). +- Multer parsing errors map to these statuses: `413` for a size or count limit, + `500` for `LIMIT_UNEXPECTED_FILE`, `400` for any other multer error, and `500` + for anything else (a malformed body). The `500` is not masked, because it is a + `ResponseError`. A missing boundary gives `400` with `multipart file(s) required`. - The body is parsed **after** every auth/scope/license/quota gate and **before** controller/route middlewares — a caller those gates would reject never has their (possibly huge) body read off the socket, and a middleware @@ -175,58 +174,6 @@ example an `application/gzip` stream. The framework treats options whose The runtime part is `sendBinaryResponse` in `packages/cli/src/public-api/media-types/binary-response.ts`. -## Migrating legacy EOV endpoints - -Legacy `express-openapi-validator` endpoints live under -`v1/handlers/`, wired through `openapi.yml` with `x-eov-operation-*` and request -types in `packages/cli/src/public-api/types.ts`. Treat these as migration targets, -not templates. - -- Prefer migrating to `@PublicApiController` over extending the handler. -- Preserve the public contract: path, method, scopes, status codes, response - shape, and pagination. -- Move HTTP concerns into the controller and business orchestration into the - shared service; keep the controller a thin HTTP boundary. If the legacy - handler was itself already just a thin wrapper around an internal - `@RestController` (calling its methods directly, e.g. - `Container.get(SomeController).createThing(req, res, payload)`), the new - public controller can call that same internal controller directly — no need - to duplicate its validation/business logic. -- A route must be served by either the EOV handler or a controller, not both — - the build's `mergeDecoratorDocument` (`v1/openapi-gen/generate.ts`) throws on - a path+method declared by both sides. Remove the legacy wiring (its path's - `$ref` entry in `openapi.yml`, the `x-eov-operation-*` handler, and its - `handler.ts`) only after the new controller is registered, `pnpm build` - regenerates the spec cleanly, and tests are updated. -- Fully delete the migrated legacy files: the handler's `.ts`, its - `spec/paths/*.yml` and `spec/schemas/*.yml`, and any now-dead request type - in `packages/cli/src/public-api/types.ts`. Then check - `v1/shared/spec/schemas/_index.yml` and `v1/shared/spec/parameters/_index.yml` - for entries that `$ref` one of the deleted schema/parameter files — those are - separate from the path's own `$ref` in `openapi.yml` and are easy to miss; - left dangling, the next bundle fails on a broken `$ref`. -- If the legacy handler gated on a license (`isLicensed('feat:x')` middleware), - `@Licensed('feat:x')` now replicates that for a controller route (see the - decorator table in [SKILL.md](SKILL.md#declaring-a-controller)) — but only for - a single feature. If the legacy check was an any-of/all-of over several flags - (e.g. `LicenseState.isProvisioningLicensed()`), `@Licensed` can't express - that; replicate it manually in the controller instead, don't drop it - this - is exactly what the internal `provisioning.controller.ee.ts` and - `role-mapping-rule.controller.ee.ts` already do, since neither uses - `@Licensed` for that reason. -- As a legacy file drops repository access / the `export =` tuple, remove its - entry from the `off` allowlists for `no-repository-in-public-api-handler` and - `require-public-api-controller` in `packages/cli/eslint.config.mjs` (shrink-only - — never extend them). -- A `multipart/form-data` legacy endpoint migrates onto `@Body({ mediaType: - 'multipart/form-data', uploadLimits })` — see - [Request body media types](#request-body-media-types). For any other - non-standard endpoint, study the nearest existing handler first. -- Keep each field in its original position when you extract a request shape shared - by two routes, and destructure out the ones a route doesn't take. The generator - emits properties in shape order, so a moved field rewrites the `*.generated.yml` - of a route the PR wasn't changing. - ## Verifying a migration Tests are written against the new code, so they can't show that the old behavior diff --git a/.claude/plugins/n8n/skills/env-var-docs b/.claude/plugins/n8n/skills/env-var-docs new file mode 120000 index 00000000000..e3b86bbce60 --- /dev/null +++ b/.claude/plugins/n8n/skills/env-var-docs @@ -0,0 +1 @@ +../../../../.agents/skills/env-var-docs \ No newline at end of file diff --git a/.github/CI-TELEMETRY.md b/.github/CI-TELEMETRY.md index ed8379b27bb..723250eb78e 100644 --- a/.github/CI-TELEMETRY.md +++ b/.github/CI-TELEMETRY.md @@ -85,6 +85,7 @@ return 'blacksmith'; | Accessibility buckets | `packages/quality/testing/playwright/reporters/a11y-reporter.ts` | Per-bucket axe score, violated rules, violating elements | | Build stats | `.github/scripts/send-build-stats.mjs` | Per-package build duration, cache hit/miss, run total | | Docker stats | `.github/scripts/send-docker-stats.mjs` | Image size per platform, docker build duration | +| Dive image efficiency | `packages/quality/efficiency/images/image-efficiency.spec.ts` | Layer content size, estimated waste, efficiency score, and layer count through the shared Playwright reporter | | Container stack | `packages/quality/environments/containers/telemetry.ts` | E2E stack startup times per service | ## Secrets diff --git a/.github/WORKFLOWS.md b/.github/WORKFLOWS.md index e06bc7a3fff..a989cff6c1e 100644 --- a/.github/WORKFLOWS.md +++ b/.github/WORKFLOWS.md @@ -411,6 +411,7 @@ Run-workflow dropdown, which only a user with write access can pick. |-----------------------------|---------------------------------------------------------| | `util-codespace-preview.yml`| Wake, re-serve or delete a PR preview instance by hand | | `util-data-tooling.yml` | SQLite/PostgreSQL export/import validation (manual) | +| `test-image-efficiency.yml` | Measure n8n and runners image size and layer waste with Dive | | `util-probe-registry.yml` | Diagnose slow npm metadata fetches (temporary) | | `sec-sync-bundle-branches.yml` | Sync both bundle branches on demand, including before a bundle cut | @@ -586,7 +587,7 @@ Push to master | Daily 03:00 | `sec-sync-bundle-branches.yml` | Merge the base into `bundle/*` | | Daily 00:00 | `docker-build-push.yml` | Nightly Docker images | | Daily 00:00 | `test-db.yml` | Database compatibility | -| Daily 00:00 | `test-e2e-performance-reusable.yml`| Performance E2E | +| Daily 00:00 | `test-e2e-performance-reusable.yml`| Browser performance and idle memory baselines | | Daily 00:00 | `release-storybook.yml` | Storybook deploy | | Daily 00:00 | `release-chromatic.yml` | Visual regression | | Daily 00:00 | `util-check-docs-urls.yml` | Doc link validation | @@ -599,6 +600,7 @@ Push to master | Daily 08:00 | `build-v3-nightly.yml` | Nightly v3 Docker images | | Monday 00:00 | `util-update-node-popularity.yml` | Node usage stats | | Monday 02:00 | `test-e2e-coverage-weekly.yml` | Weekly E2E coverage | +| Wednesday 04:00 | `util-update-get-n8n-versions.yml` | get-n8n stable versions | | Saturday 22:00 | `test-evals-ai.yml` | AI workflow evals | | 1st of month 04:00 | `util-refresh-cubic-schema.yml` | Refresh vendored cubic schema | diff --git a/.github/test-metrics/e2e-impact-map.json b/.github/test-metrics/e2e-impact-map.json index 791307a2582..f189ddac465 100644 --- a/.github/test-metrics/e2e-impact-map.json +++ b/.github/test-metrics/e2e-impact-map.json @@ -1 +1 @@ -{"specs":["tests/e2e/ai/ai-2505-pdf-embed.spec.ts","tests/e2e/ai/langchain-agents.spec.ts","tests/e2e/ai/langchain-chains.spec.ts","tests/e2e/ai/langchain-vectorstores.spec.ts","tests/e2e/chat-hub/chat-hub-attachment.spec.ts","tests/e2e/chat-hub/chat-hub-chat-user.spec.ts","tests/e2e/chat-hub/chat-hub-tools.spec.ts","tests/e2e/ai/rag-callout.spec.ts","tests/e2e/api/publish-unreachable-node.spec.ts","tests/e2e/credentials/crud.spec.ts","tests/e2e/dynamic-credentials/mcp-trigger-credential-gate.spec.ts","tests/e2e/mcp-registry/mcp-registry.spec.ts","tests/e2e/nodes/mcp-trigger.spec.ts","tests/e2e/regression/AI-1401-sub-nodes-input-panel.spec.ts","tests/e2e/regression/ado-5599-from-ai-button-alignment.spec.ts","tests/e2e/workflows/editor/ndv/ndv-floating-nodes.spec.ts","tests/e2e/workflows/editor/ndv/ndv-parameters.spec.ts","tests/e2e/chat-hub/chat-hub-workflow-agent.spec.ts","tests/e2e/workflows/editor/execution/logs.spec.ts","tests/e2e/instance-ai/instance-ai-artifacts.spec.ts","tests/e2e/instance-ai/instance-ai-attachments.spec.ts","tests/e2e/instance-ai/instance-ai-mentions.spec.ts","tests/e2e/instance-ai/instance-ai-workflow-execution.spec.ts","tests/e2e/agents/agent-builder-write-lock.spec.ts","tests/e2e/agents/agent-preview-layout.spec.ts","tests/e2e/agents/agent-sessions.spec.ts","tests/e2e/agents/background-workflow-stop.spec.ts","tests/e2e/ai/assistant-basic.spec.ts","tests/e2e/ai/assistant-code-help.spec.ts","tests/e2e/ai/assistant-credential-help.spec.ts","tests/e2e/ai/assistant-support-chat.spec.ts","tests/e2e/ai/builder-setup-wizard.spec.ts","tests/e2e/ai/chat-session.spec.ts","tests/e2e/ai/workflow-builder.spec.ts","tests/e2e/api/binary-data-xss.spec.ts","tests/e2e/api/manual-run-outcome.spec.ts","tests/e2e/api/wait-webhook-deadline.spec.ts","tests/e2e/api/webhook-isolate-skip.spec.ts","tests/e2e/api/workflow-publication-service.spec.ts","tests/e2e/app-config/security-notifications.spec.ts","tests/e2e/auth/oidc.spec.ts","tests/e2e/building-blocks/canvas-actions.spec.ts","tests/e2e/building-blocks/credential-mismatch.spec.ts","tests/e2e/building-blocks/credentials.spec.ts","tests/e2e/building-blocks/workflow-entry-points.spec.ts","tests/e2e/credentials/global.spec.ts","tests/e2e/credentials/oauth.spec.ts","tests/e2e/data-tables/details.spec.ts","tests/e2e/instance-ai/instance-ai-confirmations.spec.ts","tests/e2e/instance-ai/instance-ai-remediation-guard.spec.ts","tests/e2e/instance-ai/instance-ai-workflow-preview.spec.ts","tests/e2e/journeys/admin-views-executions-list.spec.ts","tests/e2e/nodes/code-node-api.spec.ts","tests/e2e/nodes/email-send-node.spec.ts","tests/e2e/nodes/form-trigger-node.spec.ts","tests/e2e/nodes/kafka-nodes.spec.ts","tests/e2e/nodes/webhook.spec.ts","tests/e2e/projects/folders-basic.spec.ts","tests/e2e/projects/project-settings.spec.ts","tests/e2e/projects/projects-move-resources.spec.ts","tests/e2e/projects/projects.spec.ts","tests/e2e/push/sse-push-backend.spec.ts","tests/e2e/redaction-enforcement/redaction-enforcement.spec.ts","tests/e2e/regression/ADO-5630-execute-button-layout.spec.ts","tests/e2e/scheduling/schedule-trigger-timezone.spec.ts","tests/e2e/settings/external-secrets/secret-providers-connections-ui.spec.ts","tests/e2e/settings/log-streaming/log-streaming-delivery.spec.ts","tests/e2e/settings/log-streaming/log-streaming-observability.spec.ts","tests/e2e/settings/log-streaming/log-streaming.spec.ts","tests/e2e/settings/users/users.spec.ts","tests/e2e/sharing/credential-visibility.spec.ts","tests/e2e/type-availability-policies/credential-type-policy-worker.spec.ts","tests/e2e/type-availability-policies/credential-type-policy.spec.ts","tests/e2e/type-availability-policies/node-type-policy.spec.ts","tests/e2e/workflow-reviews/review-round-trip.spec.ts","tests/e2e/workflows/checklist/production-checklist.spec.ts","tests/e2e/workflows/editor/canvas/actions.spec.ts","tests/e2e/workflows/editor/canvas/canvas-nodes.spec.ts","tests/e2e/workflows/editor/canvas/node-groups.spec.ts","tests/e2e/workflows/editor/execution/executions-list-infinite-scroll.spec.ts","tests/e2e/workflows/editor/expressions/env-access.spec.ts","tests/e2e/workflows/editor/expressions/inline.spec.ts","tests/e2e/workflows/editor/expressions/mapping.spec.ts","tests/e2e/workflows/editor/expressions/quickjs-engine.spec.ts","tests/e2e/workflows/editor/ndv/ndv-data-display.spec.ts","tests/e2e/workflows/editor/ndv/paired-item.spec.ts","tests/e2e/workflows/editor/routing.spec.ts","tests/e2e/workflows/editor/subworkflows/workflow-selector.spec.ts","tests/e2e/workflows/editor/viewer-permissions.spec.ts","tests/e2e/workflows/templates/credentials-setup.spec.ts","tests/e2e/api/wait-form-resume.spec.ts","tests/e2e/app-config/versions.spec.ts","tests/e2e/auth/token-exchange.spec.ts","tests/e2e/building-blocks/user-service.spec.ts","tests/e2e/capabilities/task-runner.spec.ts","tests/e2e/cloud/cloud.spec.ts","tests/e2e/instance-ai/instance-ai-onboarding.spec.ts","tests/e2e/regression/ADO-4462-template-setup-experiment.spec.ts","tests/e2e/sentry/sentry-baseline.spec.ts","tests/e2e/settings/environments/source-control.spec.ts","tests/e2e/settings/personal/two-factor-authentication.spec.ts","tests/e2e/ai/eval-collections-compare.spec.ts","tests/e2e/ai/workflow-builder-smoke.spec.ts","tests/e2e/api/waiting-endpoint-security.spec.ts","tests/e2e/app-config/demo-reimport.spec.ts","tests/e2e/app-config/demo.spec.ts","tests/e2e/auth/admin-smoke.spec.ts","tests/e2e/auth/authenticated.spec.ts","tests/e2e/auth/signin.spec.ts","tests/e2e/building-blocks/node-details-configuration.spec.ts","tests/e2e/capabilities/proxy-server.spec.ts","tests/e2e/chat-hub/chat-hub-basic.spec.ts","tests/e2e/chat-hub/chat-hub-personal-agent.spec.ts","tests/e2e/chat-hub/chat-hub-settings.spec.ts","tests/e2e/data-tables/tables.spec.ts","tests/e2e/dynamic-credentials/form-trigger-submit-gate-client.spec.ts","tests/e2e/instance-ai/instance-ai-background-lifecycle.spec.ts","tests/e2e/instance-ai/instance-ai-chat-basics.spec.ts","tests/e2e/instance-ai/instance-ai-out-of-credits.spec.ts","tests/e2e/instance-ai/instance-ai-oversized-attachments.spec.ts","tests/e2e/instance-ai/instance-ai-sidebar.spec.ts","tests/e2e/instance-ai/open-by-default.spec.ts","tests/e2e/instance-ai/thread-launcher.spec.ts","tests/e2e/mcp/mcp-copy-button-hover.spec.ts","tests/e2e/node-creator/actions.spec.ts","tests/e2e/node-creator/navigation.spec.ts","tests/e2e/node-creator/special-nodes.spec.ts","tests/e2e/node-creator/vector-stores.spec.ts","tests/e2e/node-creator/workflows.spec.ts","tests/e2e/nodes/community-nodes.spec.ts","tests/e2e/nodes/http-request-node.spec.ts","tests/e2e/nodes/if-node.spec.ts","tests/e2e/nodes/pdf-node.spec.ts","tests/e2e/nodes/schedule-trigger-node.spec.ts","tests/e2e/nodes/send-and-wait.spec.ts","tests/e2e/projects/folders-advanced.spec.ts","tests/e2e/projects/folders-operations.spec.ts","tests/e2e/regression/ADO-1338-ndv-missing-input-panel.spec.ts","tests/e2e/regression/ADO-2230-ndv-reset-data-pagination.spec.ts","tests/e2e/regression/ADO-2372-prevent-clipping-params.spec.ts","tests/e2e/regression/ADO-2929-can-load-old-switch-node-workflows.spec.ts","tests/e2e/regression/ADO-5808-stale-node-execution-data.spec.ts","tests/e2e/regression/AI-2795-chat-panel-header-height.spec.ts","tests/e2e/regression/AI-716-correctly-set-up-agent-model-shows-error.spec.ts","tests/e2e/regression/AI-812-partial-execs-broken-when-using-chat-trigger.spec.ts","tests/e2e/regression/CAT-2395-node-spacing.spec.ts","tests/e2e/regression/CAT-726-canvas-node-connectors-not-rendered-when-nodes-inserted.spec.ts","tests/e2e/regression/PAY-4367-node-shifting-cyclic.spec.ts","tests/e2e/regression/SUG-121-fields-reset-after-closing-ndv.spec.ts","tests/e2e/regression/SUG-38-inline-expression-preview.spec.ts","tests/e2e/settings/community-nodes/community-nodes.spec.ts","tests/e2e/settings/community-nodes/node-api-version-guard.spec.ts","tests/e2e/settings/environments/variables.spec.ts","tests/e2e/settings/log-streaming/log-streaming-ui-e2e.spec.ts","tests/e2e/settings/personal/personal.spec.ts","tests/e2e/settings/workers/workers.spec.ts","tests/e2e/sharing/access-control.spec.ts","tests/e2e/sharing/credential-picker-scope.spec.ts","tests/e2e/sharing/credential-sharing.spec.ts","tests/e2e/sharing/workflow-sharing.spec.ts","tests/e2e/workflows/demo-diff.spec.ts","tests/e2e/workflows/demo-executable-chat-trigger.spec.ts","tests/e2e/workflows/editor/canvas/canvas-zoom.spec.ts","tests/e2e/workflows/editor/canvas/focus-panel.spec.ts","tests/e2e/workflows/editor/canvas/stickies.spec.ts","tests/e2e/workflows/editor/canvas/undo-redo.spec.ts","tests/e2e/workflows/editor/code/code-node.spec.ts","tests/e2e/workflows/editor/code/editors.spec.ts","tests/e2e/workflows/editor/editor-after-route-changes.spec.ts","tests/e2e/workflows/editor/execution/debug.spec.ts","tests/e2e/workflows/editor/execution/execution.spec.ts","tests/e2e/workflows/editor/execution/inject-previous.spec.ts","tests/e2e/workflows/editor/execution/partial.spec.ts","tests/e2e/workflows/editor/expressions/modal.spec.ts","tests/e2e/workflows/editor/expressions/transformation.spec.ts","tests/e2e/workflows/editor/ndv/io-filter.spec.ts","tests/e2e/workflows/editor/ndv/ndv-core.spec.ts","tests/e2e/workflows/editor/ndv/pinning.spec.ts","tests/e2e/workflows/editor/ndv/resource-locator.spec.ts","tests/e2e/workflows/editor/ndv/resource-mapper.spec.ts","tests/e2e/workflows/editor/ndv/schema-preview.spec.ts","tests/e2e/workflows/editor/subworkflows/debugging.spec.ts","tests/e2e/workflows/editor/subworkflows/extraction.spec.ts","tests/e2e/workflows/editor/tags.spec.ts","tests/e2e/workflows/editor/workflow-actions/archive.spec.ts","tests/e2e/workflows/editor/workflow-actions/publish.spec.ts","tests/e2e/workflows/executions/filter.spec.ts","tests/e2e/workflows/executions/list.spec.ts","tests/e2e/workflows/executions/preview-isolation.spec.ts","tests/e2e/workflows/list/import.spec.ts","tests/e2e/workflows/list/workflows.spec.ts","tests/e2e/workflows/templates/templates.spec.ts","tests/e2e/api/form-endpoint-isolation.spec.ts","tests/e2e/capabilities/process-internals.spec.ts","tests/e2e/dynamic-credentials/execution-status.spec.ts","tests/e2e/nodes/n8n-trigger.spec.ts","tests/e2e/scheduling/poll-trigger-backoff.spec.ts","tests/e2e/scheduling/poll-trigger-cursor-unmigrated.spec.ts","tests/e2e/scheduling/poll-trigger-durable.spec.ts","tests/e2e/scheduling/poll-trigger-legacy.spec.ts","tests/e2e/scheduling/poll-trigger-misfire-skip.spec.ts","tests/e2e/scheduling/schedule-trigger-durable.spec.ts","tests/e2e/scheduling/schedule-trigger-misfire-coalesce.spec.ts","tests/e2e/api/discovery.spec.ts","tests/e2e/auth/password-reset.spec.ts","tests/e2e/dynamic-credentials/resolver-deletion.spec.ts","tests/e2e/instance-ai/instance-ai-multimain.spec.ts","tests/e2e/mcp/mcp-oauth.spec.ts","tests/e2e/mcp/mcp-service.spec.ts","tests/e2e/settings/external-secrets/aws-secrets-manager.spec.ts","tests/e2e/settings/external-secrets/vault.spec.ts","tests/e2e/dynamic-credentials/form-trigger-end-user-credential-shell.spec.ts","tests/e2e/api/webhook-isolation.spec.ts","tests/e2e/credentials/api-operations.spec.ts","tests/e2e/api/engine-v2-binary-data.spec.ts","tests/e2e/dynamic-credentials/external-user-trigger.spec.ts","tests/e2e/workflows/editor/subworkflows/output.spec.ts","tests/e2e/webhooks/webhook-trigger-oauth2.spec.ts","tests/e2e/dynamic-credentials/webhook-trigger-private-credential.spec.ts","tests/e2e/scheduling/poll-trigger-cursor-migrated.spec.ts","tests/e2e/scheduling/schedule-trigger-multimain.spec.ts","tests/e2e/workflows/editor/execution/subworkflow-stop.spec.ts","tests/e2e/api/webhook-external.spec.ts","tests/e2e/workflows/editor/subworkflows/wait.spec.ts","tests/e2e/workflows/editor/subworkflows/subworkflow-version-resolution.spec.ts","tests/e2e/a11y/a11y-landmark-structure.spec.ts","tests/e2e/app-config/env-feature-flags.spec.ts","tests/e2e/scheduling/schedule-trigger-legacy.spec.ts"],"files":{"packages/@n8n/ai-utilities/src/guards.ts":{"7":[0,1,2,3,4,5,6],"9":[0,1,2,3,4,5,6],"17":[0,1,2,3,4,5,6],"21":[0,1,2,3,4,5,6],"25":[0,1,2,3,4,5,6],"31":[0,1,2,3,4,5,6]},"packages/@n8n/ai-utilities/src/index.ts":{"8":[0,1,2,3,7,8,4,5,6,9,10,11,12,13,14,15,16],"13":[0,1,2,3,7,8,4,5,6,9,10,11,12,13,14,15,16],"14":[0,1,2,3,7,8,4,5,6,9,10,11,12,13,14,15,16],"15":[0,1,2,3,7,8,4,5,6,9,10,11,12,13,14,15,16],"17":[0,1,2,3,7,8,4,5,6,9,10,11,12,13,14,15,16],"53":[0,1,2,3,7,8,4,5,6,9,10,11,12,13,14,15,16],"90":[0,1,2,3,7,8,4,5,6,9,10,11,12,13,14,15,16],"99":[0,1,2,3,7,8,4,5,6,9,10,11,12,13,14,15,16],"100":[0,1,2,3,7,8,4,5,6,9,10,11,12,13,14,15,16],"129":[0,1,2,3,7,8,4,5,6,9,10,11,12,13,14,15,16],"130":[0,1,2,3,7,8,4,5,6,9,10,11,12,13,14,15,16],"134":[0,1,2,3,7,8,4,5,6,9,10,11,12,13,14,15,16]},"packages/@n8n/ai-utilities/src/model-discovery/index.ts":{"45":[1,4,5,6],"49":[1,4,5,6],"74":[1,4,5,6],"87":[1,4,5,6]},"packages/@n8n/ai-utilities/src/model-discovery/providers/openai.ts":{"6":[1],"23":[1],"49":[1],"57":[1]},"packages/@n8n/ai-utilities/src/model-discovery/request.ts":{"6":[1,4,5,6],"25":[1,4,5,6],"34":[1,4,5,6],"45":[1,4,5,6],"64":[1,4,5,6],"68":[1,4,5,6],"77":[1,4,5,6],"79":[1,4,5,6],"80":[1,4,5,6],"87":[1,4,5,6],"88":[1,4,5,6]},"packages/@n8n/ai-utilities/src/utils/failed-attempt-handler/n8nDefaultFailedAttemptHandler.ts":{"20":[1,2,6,17]},"packages/@n8n/ai-utilities/src/utils/failed-attempt-handler/n8nLlmFailedAttemptHandler.ts":{"13":[1,2,4,5,6,17],"17":[1,2,4,5,6,17]},"packages/@n8n/ai-utilities/src/utils/helpers.ts":{"3":[0,1,2,3,4,5,6],"17":[0,1,2,3,4,5,6],"37":[0,1,2,3,4,5,6]},"packages/@n8n/ai-utilities/src/utils/http-proxy-agent.ts":{"63":[1,2,4,5,6],"74":[1,2,4,5,6],"105":[1,2,4,5,6],"130":[1,2,4,5,6],"175":[1,2,4,5,6],"216":[1,2,4,5,6],"228":[1,2,4,5,6],"244":[1,2,4,5,6],"247":[1,2,4,5,6],"255":[1,2,4,5,6],"257":[1,2,4,5,6]},"packages/@n8n/ai-utilities/src/utils/log-ai-event.ts":{"6":[0,1,2,3,4,5,6,10,12]},"packages/@n8n/ai-utilities/src/utils/n8n-llm-tracing.ts":{"37":[1,2,4,5,6,17,18],"78":[1,2,4,5,6,17,18],"116":[1,2,4,5,6,17,18],"131":[1,2,4,5,6,17,18],"134":[1,2,4,5,6,17,18],"146":[1,2,4,5,6,17,18],"147":[1,2,4,5,6,17,18],"151":[1,2,4,5,6,17,18],"156":[1,2,4,5,6,17,18],"161":[1,2,4,5,6,17,18],"162":[1,2,4,5,6,17,18],"212":[1,2,4,5,6,17,18],"237":[1,2,4,5,6,17,18],"273":[1,2,4,5,6,17,18],"304":[1,2,4,5,6,17,18],"308":[1,2,4,5,6,17,18]},"packages/@n8n/ai-utilities/src/utils/redact-headers.ts":{"12":[1,2,4,5,6],"28":[1,2,4,5,6],"31":[1,2,4,5,6],"57":[1,2,4,5,6],"63":[1,2,4,5,6]},"packages/@n8n/ai-utilities/src/utils/shared-fields.ts":{"37":[0,1,2,3,7,8,4,5,6,9,10,11,12,13,14,15,16],"46":[0,1,2,3,7,8,4,5,6,9,10,11,12,13,14,15,16],"110":[0,1,2,3,7,8,4,5,6,9,10,11,12,13,14,15,16],"115":[0,1,2,3,7,8,4,5,6,9,10,11,12,13,14,15,16],"120":[0,1,2,3,7,8,4,5,6,9,10,11,12,13,14,15,16],"125":[0,1,2,3,7,8,4,5,6,9,10,11,12,13,14,15,16],"132":[0,1,2,3,7,8,4,5,6,9,10,11,12,13,14,15,16],"158":[0,1,2,3,7,8,4,5,6,9,10,11,12,13,14,15,16],"164":[0,1,2,3,7,8,4,5,6,9,10,11,12,13,14,15,16]},"packages/@n8n/ai-utilities/src/utils/strip-non-x-headers.ts":{"4":[1,2,6,17]},"packages/@n8n/ai-utilities/src/utils/tokenizer/tiktoken.ts":{"9":[1,2,4,5,6,19,20,21,22],"15":[1,2,4,5,6,19,20,21,22],"18":[1,2,4,5,6,19,20,21,22],"34":[1,2,4,5,6,19,20,21,22],"43":[1,2,4,5,6,19,20,21,22]},"packages/@n8n/ai-utilities/src/utils/tokenizer/token-estimator.ts":{"33":[1,2,4,5,6],"70":[1,2,4,5,6],"129":[1,2,4,5,6],"141":[1,2,4,5,6],"169":[1,2,4,5,6]},"packages/@n8n/api-types/src/dto/index.ts":{"1":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","3":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","4":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","12":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","16":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","42":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","43":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","46":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","57":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","67":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","74":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","76":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","78":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","82":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","84":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","87":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","89":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","95":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","96":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","143":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","145":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","146":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","147":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","149":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","150":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","154":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","160":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","162":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","164":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","165":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","167":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","170":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","171":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","183":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","184":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","197":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","201":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","206":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","212":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","214":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","222":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","223":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","231":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","232":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","233":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","234":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","236":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","238":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","239":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","277":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","308":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","332":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","339":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","340":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","414":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","416":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","433":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","458":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","492":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","502":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","505":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","506":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","508":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","558":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","580":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","581":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","583":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","584":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","625":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","626":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA=","644":"b:j47u//////////8DAAAAAAAAAAAAAAAAAAAAAAA="},"packages/@n8n/api-types/src/dto/pagination/pagination.dto.ts":{"11":"b:jwr++wNrontCvgn/HwAAAAAAAAAAAAAAAAAAAAA=","12":"b:jwr++wNrontCvgn/HwAAAAAAAAAAAAAAAAAAAAA=","15":"b:jwr++wNrontCvgn/HwAAAAAAAAAAAAAAAAAAAAA=","20":"b:/+r/+4P/5/92/v//////////////////AAAAAAA=","28":"b:jwr++wNrontCvgn/HwAAAAAAAAAAAAAAAAAAAAA=","29":"b:jwr++wNrontCvgn/HwAAAAAAAAAAAAAAAAAAAAA=","32":[46],"33":"b:jwr++wMrontCvgn/HwAAAAAAAAAAAAAAAAAAAAA=","41":"b:jwr++wNrontCvgn/HwAAAAAAAAAAAAAAAAAAAAA=","53":"b:jwr++wNrontCvgn/HwAAAAAAAAAAAAAAAAAAAAA=","54":"b:jwr++wNrontCvgn/HwAAAAAAAAAAAAAAAAAAAAA=","57":"b:jwr++wNrontCvgn/HwAAAAAAAAAAAAAAAAAAAAA=","61":"b:/+r/+4P/5/92/v//////////////////AAAAAAA=","65":"b:jwr++wNrontCvgn/HwAAAAAAAAAAAAAAAAAAAAA=","66":"b:jwr++wNrontCvgn/HwAAAAAAAAAAAAAAAAAAAAA=","69":"b:jwr++wNrontCvgn/HwAAAAAAAAAAAAAAAAAAAAA=","72":"b:jwr++wNrontCvgn/HwAAAAAAAAAAAAAAAAAAAAA="},"packages/@n8n/api-types/src/dto/user/users-list-filter.dto.ts":{"51":"b:jwr++wNrontCvgnPHwAAAAAAAAAAAAAAAAAAAAA="},"packages/@n8n/api-types/src/dto/workflows/base-workflow.dto.ts":{"26":"b:jw9m/n96oXvJv0lDAAAAABAAAAAAAgAc/wcAAAA=","30":[46],"31":"b:jw9m/n86oXvJv0lDAAAAABAAAAAAAgAc/wcAAAA=","42":"b:jw9m/n96oXvJv0lDAAAAABAAAAAAAgAc/wcAAAA=","53":[46],"54":"b:jw9m/n86oXvJv0lDAAAAABAAAAAAAgAc/wcAAAA=","55":"b:jw9m/n96oXvJv0lDAAAAABAAAAAAAgAc/wcAAAA=","69":[46],"70":"b:jw9m/n86oXvJv0lDAAAAABAAAAAAAgAc/wcAAAA=","124":"b:jw9m/n96oXvJv0lDAAAAABAAAAAAAgAc/wcAAAA=","127":"b:jw9m/n96oXvJv0lDAAAAABAAAAAAAgAc/wcAAAA="},"packages/@n8n/api-types/src/dto/workflows/manual-run.dto.ts":{"5":"b:DwBEWhVg7GEAsz4AAAAAAAAAAAAAAAAAAAAAAAA=","64":"b:DwBEWhVg7GEAsz4AAAAAAAAAAAAAAAAAAAAAAAA=","69":"b:DwBEWhUg7GEAsz4AAAAAAAAAAAAAAAAAAAAAAAA=","86":"b:DwBEWhUg7GEAsz4AAAAAAAAAAAAAAAAAAAAAAAA="},"packages/@n8n/api-types/src/index.ts":{"104":"b:/wv+/1cvq3/b/ynfHwiwABAAgEAAAAAA//8HAAA=","125":"b:/wv+/1cvq3/b/ynfHwiwABAAgEAAAAAA//8HAAA=","155":"b:/wv+/1cvq3/b/ynfHwiwABAAgEAAAAAA//8HAAA=","185":"b:/wv+/1cvq3/b/ynfHwiwABAAgEAAAAAA//8HAAA=","206":"b:/wv+/1cvq3/b/ynfHwiwABAAgEAAAAAA//8HAAA=","236":"b:/wv+/1cvq3/b/ynfHwiwABAAgEAAAAAA//8HAAA=","924":"b:/wv+/1cvq3/b/ynfHwiwABAAgEAAAAAA//8HAAA=","954":"b:/wv+/1cvq3/b/ynfHwiwABAAgEAAAAAA//8HAAA=","965":"b:/wv+/1cvq3/b/ynfHwiwABAAgEAAAAAA//8HAAA="},"packages/@n8n/api-types/src/schemas/boolean-from-string.ts":{"3":"b:/wr4+wNrontTtwnfHwAAAAAAgAIAAAAAAIAIAAA="},"packages/@n8n/api-types/src/schemas/node-version.schema.ts":{"6":[46],"7":[1,41,60,72,73,176,16,178,179,182]},"packages/@n8n/backend-common/src/index.ts":{"5":"b:fwNp/tXp83/Duz4LHQgAABAAAAAAAAAABAAYAAA=","6":"b:fwNp/tXp83/Duz4LHQgAABAAAAAAAAAABAAYAAA=","7":"b:fwNp/tXp83/Duz4LHQgAABAAAAAAAAAABAAYAAA=","10":"b:fwNp/tXp83/Duz4LHQgAABAAAAAAAAAABAAYAAA=","21":"b:fwNp/tXp83/Duz4LHQgAABAAAAAAAAAABAAYAAA="},"packages/@n8n/backend-common/src/license-state.ts":{"9":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","15":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","18":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","22":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","33":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","47":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","57":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","61":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","65":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","69":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","73":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","77":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","81":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","85":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","89":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","93":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","97":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","101":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","105":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","109":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","113":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","117":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","121":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","125":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","129":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","133":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","137":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","141":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","145":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","149":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","153":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","157":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","161":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","165":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","169":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","173":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","177":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","181":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","185":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","189":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","193":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","197":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","201":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","205":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","209":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","213":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","217":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","221":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","225":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","233":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","237":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","241":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","245":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","249":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","253":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","257":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","261":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","265":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","269":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","274":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA=","287":"b:/wv8//f743/7v8n/HxgGCIAAgBMAAARI/6cpAAA="},"packages/@n8n/backend-common/src/logging/logger.ts":{"20":"b:RhFAHyACAECKAwAWGAOBBAAAgAAABASAAwDEAQA=","30":"b:RhFAHyACAECKAwAWGAOBBAAAgAAABASAAwDEAQA=","41":"b:RhFAHyACAECKAwAWGAOBBAAAgAAABASAAwDEAQA=","71":"b:RhFAHyACAECKAwAWGAOBBAAAgAAABASAAwDEAQA=","76":"b:RhFAHyACAECKAwAWGAOBBAAAgAAABASAAwDEAQA=","88":"b:RhFAHyACAECKAwAWGAOBBAAAgAAABASAAwDEAQA=","109":"b:RhFAHyACAECKAwAWGAOBBAAAgAAABASAAwDEAQA=","130":"b:RhFAHyACAECKAwAWGAOBBAAAgAAABASAAwDEAQA=","142":"b:RhFAHyACAECKAwAWGAOBBAAAgAAABASAAwDEAQA=","151":"b:RhFAHyACAECKAwAWGAOBBAAAgAAABASAAwDEAQA=","159":"b:RhFAHyACAECKAwAWGAOBBAAAgAAABASAAwDEAQA=","163":"b:RhFAHyACAECKAwAWGAOBBAAAgAAABASAAwDEAQA=","169":"b:RhFAHyACAECKAwAWGAOBBAAAgAAABASAAwDEAQA=","170":"b:RhFAHyACAECKAwAWGAOBBAAAgAAABASAAwDEAQA=","176":"b:RhFAHyACAECKAwAWGAOBBAAAgAAABASAAwDEAQA=","182":"b:RhFAHyACAECKAwAWGAOBBAAAgAAABASAAwDEAQA=","192":"b:RhFAHyACAECKAwAWGAOBBAAAgAAABASAAwDEAQA=","195":"b:RhFAHyACAECKAwAWGAOBBAAAgAAABASAAwDEAQA=","198":"b:RhFAHyACAECKAwAWGAOBBAAAgAAABASAAwDEAQA=","208":"b:RhFAHyACAECKAwAWGAOBBAAAgAAABASAAwDEAQA=","214":"b:RhFAHyACAECKAwAWGAOBBAAAgAAABASAAwDEAQA=","221":"b:RhFAHyACAECKAwAWGAOBBAAAgAAABASAAwDEAQA=","223":"b:RhFAHyACAECKAwAWGAOBBAAAgAAABASAAwDEAQA=","231":"b:RhFAHyACAECKAwAWGAOBBAAAgAAABASAAwDEAQA=","245":"b:RhFAHyACAECKAwAWGAOBBAAAgAAABASAAwDEAQA=","264":"b:RhFAHyACAECKAwAWGAOBBAAAgAAABASAAwDEAQA=","268":"b:RhFAHyACAECKAwAWGAOBBAAAgAAABASAAwDEAQA=","272":"b:RhFAHyACAECKAwAWGAOBBAAAgAAABASAAwDEAQA=","276":"b:RhFAHyACAECKAwAWGAOBBAAAgAAABASAAwDEAQA=","284":"b:RhFAHyACAECKAwAWGAOBBAAAgAAABASAAwDEAQA="},"packages/@n8n/backend-common/src/utils/parse-flatted.ts":{"15":"b:fwBIXlUg8WGBsz4AAAAAAAAAAAAAAAAAAAAIAAA="},"packages/@n8n/backend-network/src/egress.ts":{"9":[1,2,4,5,6]},"packages/@n8n/backend-network/src/http/axios/config.ts":{"16":"b:jwp4+AMqonNAvgnHAiAAAAAAgAAAAAAA9AEEAAA=","27":"b:jwp4+AMqonNAvgnHAiAAAAAAgAAAAAAA9AEEAAA=","38":"b:jwp4+AMqonNAvgnHAiAAAAAAgAAAAAAA9AEEAAA=","52":"b:jwp4+AMqonNAvgnHAiAAAAAAgAAAAAAA9AEEAAA=","53":"b:jwp4+AMqonNAvgnHAiAAAAAAgAAAAAAA9AEEAAA="},"packages/@n8n/backend-network/src/http/axios/invoke.ts":{"6":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AEEAAA="},"packages/@n8n/backend-network/src/http/axios/redirect.ts":{"50":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AEEAAA=","68":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AEEAAA=","73":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AEEAAA=","81":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AEEAAA=","96":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AEEAAA=","108":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AEEAAA=","114":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AEEAAA=","120":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AEEAAA=","135":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AEEAAA=","151":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AEEAAA=","183":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AEEAAA=","206":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AEEAAA=","219":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AEEAAA=","227":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AEEAAA=","234":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AEEAAA=","238":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AEEAAA="},"packages/@n8n/backend-network/src/http/axios/request.ts":{"28":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AEEAAA=","78":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AEEAAA=","129":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AEEAAA=","133":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AEEAAA=","145":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AEEAAA=","160":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AEEAAA=","184":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AEEAAA="},"packages/@n8n/backend-network/src/http/axios/user-agent.ts":{"11":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AEEAAA=","28":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AEEAAA=","40":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AEEAAA=","54":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AEEAAA="},"packages/@n8n/backend-network/src/http/axios/utils.ts":{"21":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","36":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","45":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","57":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","64":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","73":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","86":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","106":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","125":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","133":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","173":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","180":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","185":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","188":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","191":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","224":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","234":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","237":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","241":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","257":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","273":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","293":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","300":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","310":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","318":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","325":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","326":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","341":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","377":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","389":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","410":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","425":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","445":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA=","451":"b:jwoA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGEAAA="},"packages/@n8n/backend-network/src/http/client-default-headers.ts":{"18":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AEEAAA="},"packages/@n8n/backend-network/src/http/client-request-error.ts":{"13":"b:RgBAGAAAAAAAAAACAACBBAAgAAAABAAEEAAEAAA=","53":"b:RgBAGAAAAAAAAAACAACBBAAgAAAABAAEEAAEAAA=","65":"b:RgBAGAAAAAAAAAACAACBBAAgAAAABAAEEAAEAAA=","69":"b:RgBAGAAAAAAAAAACAACBBAAgAAAABAAEEAAEAAA=","99":"b:RgBAGAAAAAAAAAACAACBBAAgAAAABAAEEAAEAAA=","110":"b:RgBAGAAAAAAAAAACAACBBAAgAAAABAAEEAAEAAA=","141":"b:RgBAGAAAAAAAAAACAACBBAAgAAAABAAEEAAEAAA=","157":"b:RgBAGAAAAAAAAAACAACBBAAgAAAABAAEEAAEAAA="},"packages/@n8n/backend-network/src/http/env-proxy-https-agent.ts":{"18":"b:jwp4+AMqonNAvgnHAiAAAAAAgAAAAAAABAAGAAA=","20":"b:jwp4+AMqonNAvgnHAiAAAAAAgAAAAAAABAAGAAA=","25":"b:jwp4+AMqonNAvgnHAiAAAAAAgAAAAAAABAAGAAA="},"packages/@n8n/backend-network/src/http/env-proxy-router.ts":{"22":"b:jwp4+AMqonNAvgnHAiAAAAAAgAAAAAAA9AEGAAA=","31":"b:jwp4+AMqonNAvgnHAiAAAAAAgAAAAAAA9AEGAAA=","51":"b:jwp4+AMqonNAvgnHAiAAAAAAgAAAAAAA9AEGAAA=","64":"b:jwp4+AMqonNAvgnHAiAAAAAAgAAAAAAA9AEGAAA="},"packages/@n8n/backend-network/src/http/index.ts":{"9":"b:fwFIXnUi4WGJvC4AAACBBEAgAAAABAUE+wfUAAA=","10":"b:fwFIXnUi4WGJvC4AAACBBEAgAAAABAUE+wfUAAA=","11":"b:fwFIXnUi4WGJvC4AAACBBEAgAAAABAUE+wfUAAA=","12":"b:fwFIXnUi4WGJvC4AAACBBEAgAAAABAUE+wfUAAA="},"packages/@n8n/backend-network/src/http/node-agents.ts":{"23":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AEGAAA=","88":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AEGAAA=","137":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AEGAAA="},"packages/@n8n/backend-network/src/http/outbound-http.ts":{"175":"b:/woA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGGAAA=","185":"b:/woA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGGAAA=","189":"b:/woA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGGAAA=","201":"b:/woA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGGAAA=","212":"b:/woA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGGAAA=","227":"b:/woA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGGAAA=","237":"b:/woA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGGAAA=","240":"b:/woA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGGAAA=","241":"b:/woA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGGAAA=","242":"b:/woA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGGAAA=","253":"b:/woA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGGAAA=","263":"b:/woA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGGAAA=","274":"b:/woA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGGAAA=","276":"b:/woA+AMqoHNAvgnHAmAAAAQAgAAAEgAA9AGGAAA="},"packages/@n8n/backend-network/src/http/undici/transport.ts":{"110":[26,1,2,40,4,5,6,19,20,21,49,22],"125":[26,1,2,40,4,5,6,19,20,21,49,22],"154":[26,1,2,40,4,5,6,19,20,21,49,22],"162":[26,1,2,40,4,5,6,19,20,21,49,22],"176":[26,1,2,40,4,5,6,19,20,21,49,22],"189":[26,1,2,40,4,5,6,19,20,21,49,22],"197":[26,1,2,40,4,5,6,19,20,21,49,22],"214":[26,1,2,40,4,5,6,19,20,21,49,22],"223":[26,1,2,40,4,5,6,19,20,21,49,22],"229":[26,1,2,40,4,5,6,19,20,21,49,22],"231":[26,1,2,40,4,5,6,19,20,21,49,22],"235":[26,1,2,40,4,5,6,19,20,21,49,22],"237":[26,1,2,40,4,5,6,19,20,21,49,22],"246":[26,1,2,40,4,5,6,19,20,21,49,22],"264":[26,1,2,40,4,5,6,19,20,21,49,22],"267":[26,1,2,40,4,5,6,19,20,21,49,22],"271":[26,1,2,40,4,5,6,19,20,21,49,22],"278":[26,1,2,40,4,5,6,19,20,21,49,22],"298":[26,1,2,40,4,5,6,19,20,21,49,22],"301":[26,1,2,40,4,5,6,19,20,21,49,22],"305":[26,1,2,40,4,5,6,19,20,21,49,22],"306":[26,1,2,40,4,5,6,19,20,21,49,22],"329":[26,1,2,40,4,5,6,19,20,21,49,22],"340":[26,1,2,40,4,5,6,19,20,21,49,22],"362":[26,1,2,40,4,5,6,19,20,21,49,22],"371":[26,1,2,40,4,5,6,19,20,21,49,22],"377":[26,1,2,40,4,5,6,19,20,21,49,22],"391":[26,1,2,40,4,5,6,19,20,21,49,22],"410":[26,1,2,40,4,5,6,19,20,21,49,22]},"packages/@n8n/backend-network/src/proxy/index.ts":{"20":[1,2,4,5,6,194]},"packages/@n8n/backend-network/src/proxy/proxied-agents.ts":{"37":"b:DgB4AAIAAgAAAAAAAEAAAAAAAAAAAAAA8AEAAAA=","38":"b:DgB4AAIAAgAAAAAAAEAAAAAAAAAAAAAA8AEAAAA=","41":"b:DgB4AAIAAgAAAAAAAEAAAAAAAAAAAAAA8AEAAAA=","42":"b:DgB4AAIAAgAAAAAAAEAAAAAAAAAAAAAA8AEAAAA=","45":"b:DgB4AAIAAgAAAAAAAEAAAAAAAAAAAAAA8AEAAAA=","49":"b:DgB4AAIAAgAAAAAAAEAAAAAAAAAAAAAA8AEAAAA=","56":"b:DgB4AAIAAgAAAAAAAEAAAAAAAAAAAAAA8AEAAAA=","61":"b:DgB4AAIAAgAAAAAAAEAAAAAAAAAAAAAA8AEAAAA=","73":"b:DgB4AAIAAgAAAAAAAEAAAAAAAAAAAAAA8AEAAAA=","87":"b:DgB4AAIAAgAAAAAAAEAAAAAAAAAAAAAA8AEAAAA="},"packages/@n8n/backend-network/src/proxy/proxy-resolution.ts":{"20":[1,2,4,5,6,194],"32":[1,2,4,5,6,194],"44":[1,2,4,5,6,194],"66":[1,2,4,5,6,194],"81":[1,2,4,5,6,194],"89":[1,2,4,5,6,194]},"packages/@n8n/backend-network/src/ssrf/index.ts":{"1":[1,2,4,5,6],"3":[1,2,4,5,6]},"packages/@n8n/backend-services/src/credentials/credentials-finder.service.ts":{"38":"b:/xvv/QNu43vAvwnHAqACAEAAAHAAAAQABAAoAAA=","46":"b:/xvv/QNu43vAvwnHAqACAEAAAHAAAAQABAAoAAA=","50":"b:/xvv/QNu43vAvwnHAqACAEAAAHAAAAQABAAoAAA=","55":"b:/xvv/QNu43vAvwnHAqACAEAAAHAAAAQABAAoAAA=","64":"b:/xvv/QNu43vAvwnHAqACAEAAAHAAAAQABAAoAAA=","87":"b:/xvv/QNu43vAvwnHAqACAEAAAHAAAAQABAAoAAA=","89":"b:/xvv/QNu43vAvwnHAqACAEAAAHAAAAQABAAoAAA=","97":"b:/xvv/QNu43vAvwnHAqACAEAAAHAAAAQABAAoAAA=","106":"b:/xvv/QNu43vAvwnHAqACAEAAAHAAAAQABAAoAAA=","113":"b:/xvv/QNu43vAvwnHAqACAEAAAHAAAAQABAAoAAA=","123":"b:/xvv/QNu43vAvwnHAqACAEAAAHAAAAQABAAoAAA=","140":"b:/xvv/QNu43vAvwnHAqACAEAAAHAAAAQABAAoAAA=","145":"b:/xvv/QNu43vAvwnHAqACAEAAAHAAAAQABAAoAAA=","147":"b:/xvv/QNu43vAvwnHAqACAEAAAHAAAAQABAAoAAA=","149":"b:/xvv/QNu43vAvwnHAqACAEAAAHAAAAQABAAoAAA=","161":"b:/xvv/QNu43vAvwnHAqACAEAAAHAAAAQABAAoAAA=","181":"b:/xvv/QNu43vAvwnHAqACAEAAAHAAAAQABAAoAAA=","222":"b:/xvv/QNu43vAvwnHAqACAEAAAHAAAAQABAAoAAA=","240":"b:/xvv/QNu43vAvwnHAqACAEAAAHAAAAQABAAoAAA=","242":"b:/xvv/QNu43vAvwnHAqACAEAAAHAAAAQABAAoAAA=","276":"b:/xvv/QNu43vAvwnHAqACAEAAAHAAAAQABAAoAAA=","293":"b:/xvv/QNu43vAvwnHAqACAEAAAHAAAAQABAAoAAA=","305":"b:/xvv/QNu43vAvwnHAqACAEAAAHAAAAQABAAoAAA=","314":"b:/xvv/QNu43vAvwnHAqACAEAAAHAAAAQABAAoAAA=","321":"b:/xvv/QNu43vAvwnHAqACAEAAAHAAAAQABAAoAAA=","323":"b:/xvv/QNu43vAvwnHAqACAEAAAHAAAAQABAAoAAA=","334":"b:/xvv/QNu43vAvwnHAqACAEAAAHAAAAQABAAoAAA=","373":"b:/xvv/QNu43vAvwnHAqACAEAAAHAAAAQABAAoAAA=","385":"b:/xvv/QNu43vAvwnHAqACAEAAAHAAAAQABAAoAAA=","393":"b:/xvv/QNu43vAvwnHAqACAEAAAHAAAAQABAAoAAA="},"packages/@n8n/backend-services/src/errors/rest-error-classifier.ts":{"5":"b:AhEBByACAECIAwAWGAMFAEAAgAAAAAWAAwDAAQA=","40":"b:AhEBByACAECIAwAWGAMFAEAAgAAAAAWAAwDAAQA=","62":"b:AhEBByACAECIAwAWGAMFAEAAgAAAAAWAAwDAAQA=","120":"b:AhEBByACAECIAwAWGAMFAEAAgAAAAAWAAwDAAQA=","132":"b:AhEBByACAECIAwAWGAMFAEAAgAAAAAWAAwDAAQA="},"packages/@n8n/backend-services/src/errors/rest-error-response.ts":{"18":"b:AhEBByACAECIAwAWGAMBAEAAgAAAAASAAwDAAQA=","85":"b:AhEBByACAECIAwAWGAMBAEAAgAAAAASAAwDAAQA="},"packages/@n8n/backend-services/src/executions/is-billable-execution.ts":{"30":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA="},"packages/@n8n/backend-services/src/services/cache/cache.service.ts":{"24":"b:fxvu/3c+43nJ/20HgAAIAEABAAACAwLK/wfQAwA=","31":"b:fxvu/3c+43nJ/20HgAAIAEABAAACAwLK/wfQAwA=","68":"b:fxvu/3c+43nJ/20HgAAIAEABAAACAwLK/wfQAwA=","78":"b:fxvu/3c+43nJ/20HgAAIAEABAAACAwLK/wfQAwA=","82":"b:fxvu/3c+43nJ/20HgAAIAEABAAACAwLK/wfQAwA=","86":"b:fxvu/3c+43nJ/20HgAAIAEABAAACAwLK/wfQAwA=","90":"b:fxvu/3c+43nJ/20HgAAIAEABAAACAwLK/wfQAwA=","102":"b:fxvu/3c+43nJ/20HgAAIAEABAAACAwLK/wfQAwA=","114":"b:fxvu/3c+43nJ/20HgAAIAEABAAACAwLK/wfQAwA=","120":"b:fxvu/3c+43nJ/20HgAAIAEABAAACAwLK/wfQAwA=","138":"b:fxvu/3c+43nJ/20HgAAIAEABAAACAwLK/wfQAwA=","159":"b:fxvu/3c+43nJ/20HgAAIAEABAAACAwLK/wfQAwA=","179":"b:fxvu/3c+43nJ/20HgAAIAEABAAACAwLK/wfQAwA=","222":"b:fxvu/3c+43nJ/20HgAAIAEABAAACAwLK/wfQAwA=","233":"b:fxvu/3c+43nJ/20HgAAIAEABAAACAwLK/wfQAwA=","257":"b:fxvu/3c+43nJ/20HgAAIAEABAAACAwLK/wfQAwA=","295":"b:fxvu/3c+43nJ/20HgAAIAEABAAACAwLK/wfQAwA=","339":"b:fxvu/3c+43nJ/20HgAAIAEABAAACAwLK/wfQAwA=","347":"b:fxvu/3c+43nJ/20HgAAIAEABAAACAwLK/wfQAwA=","359":"b:fxvu/3c+43nJ/20HgAAIAEABAAACAwLK/wfQAwA=","378":"b:fxvu/3c+43nJ/20HgAAIAEABAAACAwLK/wfQAwA=","394":"b:fxvu/3c+43nJ/20HgAAIAEABAAACAwLK/wfQAwA="},"packages/@n8n/backend-services/src/services/instance-write-access.service.ts":{"10":"b:DwB8WhUg6mEAsz4AAAAAAAAAAAAAAAAAAAAAAAA=","13":"b:DwB8WhUg6mEAsz4AAAAAAAAAAAAAAAAAAAAAAAA=","17":"b:DwB8WhUg6mEAsz4AAAAAAAAAAAAAAAAAAAAAAAA="},"packages/@n8n/backend-services/src/services/role-cache.service.ts":{"38":"b:IhHsBOSxg17JjEARHIgACMAAAAAEBAAA+wfQAAA=","47":"b:IhHsBOSxg17JjEARHIgACMAAAAAEBAAA+wfQAAA=","55":"b:IhHsBOSxg17JjEARHIgACMAAAAAEBAAA+wfQAAA=","69":"b:IhHsBOSxg17JjEARHIgACMAAAAAEBAAA+wfQAAA=","78":"b:IhHsBOSxg17JjEARHIgACMAAAAAEBAAA+wfQAAA=","94":"b:IhHsBOSxg17JjEARHIgACMAAAAAEBAAA+wfQAAA=","106":"b:IhHsBOSxg17JjEARHIgACMAAAAAEBAAA+wfQAAA=","113":"b:IhHsBOSxg17JjEARHIgACMAAAAAEBAAA+wfQAAA="},"packages/@n8n/backend-services/src/services/role.service.ts":{"52":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","62":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","65":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","72":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","80":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","84":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","92":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","99":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","117":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","130":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","143":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","192":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","208":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","230":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","234":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","236":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","238":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","248":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","298":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","327":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","332":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","341":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","368":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","424":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","434":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","438":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","448":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","457":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","471":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","495":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","506":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","507":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","517":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","519":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","524":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","530":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","534":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA=","544":"b:/xv///f/o3/7v8n/H5gECsAAgEIEBAAA/4/YBAA="},"packages/@n8n/backend-services/src/services/workflow-project.service.ts":{"7":"b:fwNK/vUk432pvywBAAAEAAABAAAAAABB+wfAAAA=","12":"b:fwNK/vUk432pvywBAAAEAAABAAAAAABB+wfAAAA=","17":"b:fwNK/vUk432pvywBAAAEAAABAAAAAABB+wfAAAA=","40":"b:fwNK/vUk432pvywBAAAEAAABAAAAAABB+wfAAAA=","48":"b:fwNK/vUk432pvywBAAAEAAABAAAAAABB+wfAAAA=","53":"b:fwNK/vUk432pvywBAAAEAAABAAAAAABB+wfAAAA=","56":"b:fwNK/vUk432pvywBAAAEAAABAAAAAABB+wfAAAA=","59":"b:fwNK/vUk432pvywBAAAEAAABAAAAAABB+wfAAAA="},"packages/@n8n/backend-services/src/services/workflow-sharing.service.ts":{"21":"b:DxFGfvW5/X3Lv34NHBgEAkAAAFAEBkDO+wfQAQA=","38":"b:DxFGfvW5/X3Lv34NHBgEAkAAAFAEBkDO+wfQAQA=","66":"b:DxFGfvW5/X3Lv34NHBgEAkAAAFAEBkDO+wfQAQA=","90":"b:DxFGfvW5/X3Lv34NHBgEAkAAAFAEBkDO+wfQAQA=","106":"b:DxFGfvW5/X3Lv34NHBgEAkAAAFAEBkDO+wfQAQA=","122":"b:DxFGfvW5/X3Lv34NHBgEAkAAAFAEBkDO+wfQAQA=","126":"b:DxFGfvW5/X3Lv34NHBgEAkAAAFAEBkDO+wfQAQA=","134":"b:DxFGfvW5/X3Lv34NHBgEAkAAAFAEBkDO+wfQAQA=","137":"b:DxFGfvW5/X3Lv34NHBgEAkAAAFAEBkDO+wfQAQA=","143":"b:DxFGfvW5/X3Lv34NHBgEAkAAAFAEBkDO+wfQAQA=","150":"b:DxFGfvW5/X3Lv34NHBgEAkAAAFAEBkDO+wfQAQA=","158":"b:DxFGfvW5/X3Lv34NHBgEAkAAAFAEBkDO+wfQAQA="},"packages/@n8n/config/src/configs/ai.config.ts":{"6":[1,2],"56":[1,2]},"packages/@n8n/db/src/entities/index.ts":{"12":"b:fgMBhAFsoBnCAwACAAAAAAAAAQACAAQABAAgCAA=","17":"b:fgMBhAFsoBnCAwACAAAAAAAAAQACAAQABAAgCAA=","33":"b:fgMBhAFsoBnCAwACAAAAAAAAAQACAAQABAAgCAA=","34":"b:fgMBhAFsoBnCAwACAAAAAAAAAQACAAQABAAgCAA=","45":"b:fgMBhAFsoBnCAwACAAAAAAAAAQACAAQABAAgCAA=","48":"b:fgMBhAFsoBnCAwACAAAAAAAAAQACAAQABAAgCAA=","52":"b:fgMBhAFsoBnCAwACAAAAAAAAAQACAAQABAAgCAA=","61":"b:fgMBhAFsoBnCAwACAAAAAAAAAQACAAQABAAgCAA=","69":"b:fgMBhAFsoBnCAwACAAAAAAAAAQACAAQABAAgCAA=","72":"b:fgMBhAFsoBnCAwACAAAAAAAAAQACAAQABAAgCAA=","76":"b:fgMBhAFsoBnCAwACAAAAAAAAAQACAAQABAAgCAA=","78":"b:fgMBhAFsoBnCAwACAAAAAAAAAQACAAQABAAgCAA=","81":"b:fgMBhAFsoBnCAwACAAAAAAAAAQACAAQABAAgCAA=","82":"b:fgMBhAFsoBnCAwACAAAAAAAAAQACAAQABAAgCAA=","87":"b:fgMBhAFsoBnCAwACAAAAAAAAAQACAAQABAAgCAA="},"packages/@n8n/db/src/entities/types-db.ts":{"330":"b:/wv4/1cronvZtwmDHwAAAAAAgAAAAAAA/88GAAA=","342":"b:/wv4/1cronvZtwmDHwAAAAAAgAAAAAAA/88GAAA=","480":"b:/wv4/1cronvZtwmDHwAAAAAAgAAAAAAA/88GAAA="},"packages/@n8n/db/src/entities/user.ts":{"60":"b:Dwrs+QMvo1FAvilHAAAAABAAAAAAAAAAAAAAAAA=","84":"b:Dwrs+QMvo1FAvilHAAAAABAAAAAAAAAAAAAAAAA=","115":"b:Dwrs+QMvo1FAvilHAAAAABAAAAAAAAAAAAAAAAA=","117":"b:Dwrs+QMvo1FAvilHAAAAABAAAAAAAAAAAAAAAAA=","124":"b:Dwrs+QMvo1FAvilHAAAAABAAAAAAAAAAAAAAAAA=","129":"b:Dwrs+QMvo1FAvilHAAAAABAAAAAAAAAAAAAAAAA=","139":"b:Dwrs+QMvo1FAvilHAAAAABAAAAAAAAAAAAAAAAA="},"packages/@n8n/db/src/index.ts":{"14":"b:f4dt//Wv5//7/35bXPsnCsgAgFEAFAXI/yfgAAA=","15":"b:f4dt//Wv5//7/35bXPsnCsgAgFEAFAXI/yfgAAA=","18":"b:f4dt//Wv5//7/35bXPsnCsgAgFEAFAXI/yfgAAA=","19":"b:f4dt//Wv5//7/35bXPsnCsgAgFEAFAXI/yfgAAA=","20":"b:f4dt//Wv5//7/35bXPsnCsgAgFEAFAXI/yfgAAA=","24":"b:f4dt//Wv5//7/35bXPsnCsgAgFEAFAXI/yfgAAA=","26":"b:f4dt//Wv5//7/35bXPsnCsgAgFEAFAXI/yfgAAA=","27":"b:f4dt//Wv5//7/35bXPsnCsgAgFEAFAXI/yfgAAA=","28":"b:f4dt//Wv5//7/35bXPsnCsgAgFEAFAXI/yfgAAA=","43":"b:f4dt//Wv5//7/35bXPsnCsgAgFEAFAXI/yfgAAA=","53":"b:f4dt//Wv5//7/35bXPsnCsgAgFEAFAXI/yfgAAA=","63":"b:f4dt//Wv5//7/35bXPsnCsgAgFEAFAXI/yfgAAA="},"packages/@n8n/db/src/repositories/base-repository.ts":{"17":"b:/wt4/ncqonvLvwkTAAAAAAAAAAAAAAAA/wcAAAA=","30":"b:/wt4/ncqonvLvwkTAAAAAAAAAAAAAAAA/wcAAAA=","49":"b:/wt4/ncqonvLvwkTAAAAAAAAAAAAAAAA/wcAAAA=","53":"b:/wt4/ncqonvLvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/@n8n/db/src/repositories/credential-access.repository.ts":{"18":"b:/xvv/QNu43vAvwnHAiACAEAAADAAAAQABAAoAAA=","22":"b:/xvv/QNu43vAvwnHAiACAEAAADAAAAQABAAoAAA=","26":"b:/xvv/QNu43vAvwnHAiACAEAAADAAAAQABAAoAAA=","37":"b:/xvv/QNu43vAvwnHAiACAEAAADAAAAQABAAoAAA=","48":"b:/xvv/QNu43vAvwnHAiACAEAAADAAAAQABAAoAAA=","62":"b:/xvv/QNu43vAvwnHAiACAEAAADAAAAQABAAoAAA=","72":"b:/xvv/QNu43vAvwnHAiACAEAAADAAAAQABAAoAAA=","99":"b:/xvv/QNu43vAvwnHAiACAEAAADAAAAQABAAoAAA=","127":"b:/xvv/QNu43vAvwnHAiACAEAAADAAAAQABAAoAAA=","149":"b:/xvv/QNu43vAvwnHAiACAEAAADAAAAQABAAoAAA=","152":"b:/xvv/QNu43vAvwnHAiACAEAAADAAAAQABAAoAAA=","183":"b:/xvv/QNu43vAvwnHAiACAEAAADAAAAQABAAoAAA=","200":"b:/xvv/QNu43vAvwnHAiACAEAAADAAAAQABAAoAAA=","205":"b:/xvv/QNu43vAvwnHAiACAEAAADAAAAQABAAoAAA=","214":"b:/xvv/QNu43vAvwnHAiACAEAAADAAAAQABAAoAAA=","217":"b:/xvv/QNu43vAvwnHAiACAEAAADAAAAQABAAoAAA=","228":"b:/xvv/QNu43vAvwnHAiACAEAAADAAAAQABAAoAAA=","244":"b:/xvv/QNu43vAvwnHAiACAEAAADAAAAQABAAoAAA=","261":"b:/xvv/QNu43vAvwnHAiACAEAAADAAAAQABAAoAAA="},"packages/@n8n/db/src/repositories/credential-dependency.repository.ts":{"25":"b:dgMBhABsoBnCAwACAAACAAAAAEAAAAQABAAgAAA=","64":"b:dgMBhABsoBnCAwACAAACAAAAAEAAAAQABAAgAAA=","68":"b:dgMBhABsoBnCAwACAAACAAAAAEAAAAQABAAgAAA=","77":"b:dgMBhABsoBnCAwACAAACAAAAAEAAAAQABAAgAAA=","80":"b:dgMBhABsoBnCAwACAAACAAAAAEAAAAQABAAgAAA=","95":"b:dgMBhABsoBnCAwACAAACAAAAAEAAAAQABAAgAAA=","105":"b:dgMBhABsoBnCAwACAAACAAAAAEAAAAQABAAgAAA=","118":"b:dgMBhABsoBnCAwACAAACAAAAAEAAAAQABAAgAAA=","119":"b:dgMBhABsoBnCAwACAAACAAAAAEAAAAQABAAgAAA=","120":"b:dgMBhABsoBnCAwACAAACAAAAAEAAAAQABAAgAAA=","140":"b:dgMBhABsoBnCAwACAAACAAAAAEAAAAQABAAgAAA=","151":"b:dgMBhABsoBnCAwACAAACAAAAAEAAAAQABAAgAAA="},"packages/@n8n/db/src/repositories/credentials.repository.ts":{"33":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","67":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","76":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","87":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","111":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","121":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","129":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","139":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","147":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","151":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","159":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","163":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","190":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","203":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","209":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","217":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","233":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","241":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","258":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","277":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","299":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","307":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","327":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","339":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","378":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","407":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","422":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","429":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","434":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","509":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","547":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","566":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","581":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","595":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","608":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","616":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","625":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","633":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","669":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","756":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","758":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA=","762":"b:/8vv//f/8//f///PH7gGAgKBAHIAAAQA/wfwAAA="},"packages/@n8n/db/src/repositories/execution-metadata.repository.ts":{"8":[32,1,2,3,4,5,6,144,161]},"packages/@n8n/db/src/repositories/execution.repository.ts":{"74":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","123":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","154":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","188":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","221":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","241":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","246":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","253":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","260":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","266":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","272":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","278":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","285":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","290":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","330":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","393":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","403":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","427":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","434":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","445":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","453":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","486":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","512":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","517":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","520":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","537":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","540":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","569":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","593":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","620":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","660":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","671":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","672":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","679":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","685":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","688":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","700":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","704":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","724":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","736":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","744":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","755":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","762":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","766":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","791":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","804":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","807":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","841":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","931":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","943":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","953":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","967":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","992":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","1003":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","1009":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","1022":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","1029":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","1069":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","1110":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","1126":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","1130":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","1157":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","1193":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","1197":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","1217":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","1236":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","1357":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","1359":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","1367":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","1404":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","1412":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","1415":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","1423":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","1427":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","1432":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","1435":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","1444":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","1447":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","1453":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","1461":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","1468":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","1476":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA=","1493":"b:fwBOXnUg6WGJsz4AAAAAAEAAAAAEBgAF+wfRAQA="},"packages/@n8n/db/src/repositories/index.ts":{"11":"b:jwvu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","12":"b:jwvu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","17":"b:jwvu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","20":"b:jwvu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","21":"b:jwvu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","22":"b:jwvu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","44":"b:jwvu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","47":"b:jwvu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","56":"b:jwvu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","59":"b:jwvu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","60":"b:jwvu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","69":"b:jwvu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","95":"b:jwvu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","97":"b:jwvu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","100":"b:jwvu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","101":"b:jwvu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","103":"b:jwvu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","109":"b:jwvu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","110":"b:jwvu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","138":"b:jwvu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","139":"b:jwvu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","144":"b:jwvu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","151":"b:jwvu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","152":"b:jwvu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/@n8n/db/src/repositories/project-relation.repository.ts":{"14":"b:/xv4/3cr6n/btwmnH4gIAAAAgEAAAAIA/4fQAQA=","18":"b:/xv4/3cr6n/btwmnH4gIAAAAgEAAAAIA/4fQAQA=","33":"b:/xv4/3cr6n/btwmnH4gIAAAAgEAAAAIA/4fQAQA=","48":"b:/xv4/3cr6n/btwmnH4gIAAAAgEAAAAIA/4fQAQA=","67":"b:/xv4/3cr6n/btwmnH4gIAAAAgEAAAAIA/4fQAQA=","75":"b:/xv4/3cr6n/btwmnH4gIAAAAgEAAAAIA/4fQAQA=","78":"b:/xv4/3cr6n/btwmnH4gIAAAAgEAAAAIA/4fQAQA=","83":"b:/xv4/3cr6n/btwmnH4gIAAAAgEAAAAIA/4fQAQA=","89":"b:/xv4/3cr6n/btwmnH4gIAAAAgEAAAAIA/4fQAQA=","96":"b:/xv4/3cr6n/btwmnH4gIAAAAgEAAAAIA/4fQAQA=","102":"b:/xv4/3cr6n/btwmnH4gIAAAAgEAAAAIA/4fQAQA=","110":"b:/xv4/3cr6n/btwmnH4gIAAAAgEAAAAIA/4fQAQA=","116":"b:/xv4/3cr6n/btwmnH4gIAAAAgEAAAAIA/4fQAQA=","130":"b:/xv4/3cr6n/btwmnH4gIAAAAgEAAAAIA/4fQAQA=","143":"b:/xv4/3cr6n/btwmnH4gIAAAAgEAAAAIA/4fQAQA=","144":"b:/xv4/3cr6n/btwmnH4gIAAAAgEAAAAIA/4fQAQA=","151":"b:/xv4/3cr6n/btwmnH4gIAAAAgEAAAAIA/4fQAQA=","162":"b:/xv4/3cr6n/btwmnH4gIAAAAgEAAAAIA/4fQAQA="},"packages/@n8n/db/src/repositories/project.repository.ts":{"14":"b:/0v4//d743/7/6nfHwAWAAABgHIAAABA/6coAAA=","21":"b:/0v4//d743/7/6nfHwAWAAABgHIAAABA/6coAAA=","29":"b:/0v4//d743/7/6nfHwAWAAABgHIAAABA/6coAAA=","38":"b:/0v4//d743/7/6nfHwAWAAABgHIAAABA/6coAAA=","68":"b:/0v4//d743/7/6nfHwAWAAABgHIAAABA/6coAAA=","80":"b:/0v4//d743/7/6nfHwAWAAABgHIAAABA/6coAAA=","92":"b:/0v4//d743/7/6nfHwAWAAABgHIAAABA/6coAAA=","98":"b:/0v4//d743/7/6nfHwAWAAABgHIAAABA/6coAAA=","102":"b:/0v4//d743/7/6nfHwAWAAABgHIAAABA/6coAAA=","110":"b:/0v4//d743/7/6nfHwAWAAABgHIAAABA/6coAAA=","120":"b:/0v4//d743/7/6nfHwAWAAABgHIAAABA/6coAAA=","124":"b:/0v4//d743/7/6nfHwAWAAABgHIAAABA/6coAAA=","128":"b:/0v4//d743/7/6nfHwAWAAABgHIAAABA/6coAAA=","152":"b:/0v4//d743/7/6nfHwAWAAABgHIAAABA/6coAAA=","167":"b:/0v4//d743/7/6nfHwAWAAABgHIAAABA/6coAAA=","184":"b:/0v4//d743/7/6nfHwAWAAABgHIAAABA/6coAAA=","194":"b:/0v4//d743/7/6nfHwAWAAABgHIAAABA/6coAAA=","206":"b:/0v4//d743/7/6nfHwAWAAABgHIAAABA/6coAAA=","222":"b:/0v4//d743/7/6nfHwAWAAABgHIAAABA/6coAAA=","231":"b:/0v4//d743/7/6nfHwAWAAABgHIAAABA/6coAAA=","247":"b:/0v4//d743/7/6nfHwAWAAABgHIAAABA/6coAAA=","260":"b:/0v4//d743/7/6nfHwAWAAABgHIAAABA/6coAAA=","274":"b:/0v4//d743/7/6nfHwAWAAABgHIAAABA/6coAAA=","284":"b:/0v4//d743/7/6nfHwAWAAABgHIAAABA/6coAAA=","291":"b:/0v4//d743/7/6nfHwAWAAABgHIAAABA/6coAAA=","297":"b:/0v4//d743/7/6nfHwAWAAABgHIAAABA/6coAAA=","308":"b:/0v4//d743/7/6nfHwAWAAABgHIAAABA/6coAAA="},"packages/@n8n/db/src/repositories/role.repository.ts":{"11":"b:/wr6+wMron9ytgn/HwAAAAAAgEIAAAAAAIgIBAA=","15":"b:/wr6+wMron9ytgn/HwAAAAAAgEIAAAAAAIgIBAA=","20":"b:/wr6+wMron9ytgn/HwAAAAAAgEIAAAAAAIgIBAA=","38":"b:/wr6+wMron9ytgn/HwAAAAAAgEIAAAAAAIgIBAA=","54":"b:/wr6+wMron9ytgn/HwAAAAAAgEIAAAAAAIgIBAA=","65":"b:/wr6+wMron9ytgn/HwAAAAAAgEIAAAAAAIgIBAA=","74":"b:/wr6+wMron9ytgn/HwAAAAAAgEIAAAAAAIgIBAA=","82":"b:/wr6+wMron9ytgn/HwAAAAAAgEIAAAAAAIgIBAA=","108":"b:/wr6+wMron9ytgn/HwAAAAAAgEIAAAAAAIgIBAA=","111":"b:/wr6+wMron9ytgn/HwAAAAAAgEIAAAAAAIgIBAA=","114":"b:/wr6+wMron9ytgn/HwAAAAAAgEIAAAAAAIgIBAA=","128":"b:/wr6+wMron9ytgn/HwAAAAAAgEIAAAAAAIgIBAA=","131":"b:/wr6+wMron9ytgn/HwAAAAAAgEIAAAAAAIgIBAA=","151":"b:/wr6+wMron9ytgn/HwAAAAAAgEIAAAAAAIgIBAA=","180":"b:/wr6+wMron9ytgn/HwAAAAAAgEIAAAAAAIgIBAA=","187":"b:/wr6+wMron9ytgn/HwAAAAAAgEIAAAAAAIgIBAA=","194":"b:/wr6+wMron9ytgn/HwAAAAAAgEIAAAAAAIgIBAA=","205":"b:/wr6+wMron9ytgn/HwAAAAAAgEIAAAAAAIgIBAA=","206":"b:/wr6+wMron9ytgn/HwAAAAAAgEIAAAAAAIgIBAA=","230":"b:/wr6+wMron9ytgn/HwAAAAAAgEIAAAAAAIgIBAA=","263":"b:/wr6+wMron9ytgn/HwAAAAAAgEIAAAAAAIgIBAA=","267":"b:/wr6+wMron9ytgn/HwAAAAAAgEIAAAAAAIgIBAA="},"packages/@n8n/db/src/repositories/secrets-provider-connection.repository.ee.ts":{"8":"b:dgMDpIBsoB3CAwADAAAGAAKAABAAAARABAAgAAA=","12":"b:dgMDpIBsoB3CAwADAAAGAAKAABAAAARABAAgAAA=","16":"b:dgMDpIBsoB3CAwADAAAGAAKAABAAAARABAAgAAA=","25":"b:dgMDpIBsoB3CAwADAAAGAAKAABAAAARABAAgAAA=","33":"b:dgMDpIBsoB3CAwADAAAGAAKAABAAAARABAAgAAA=","36":"b:dgMDpIBsoB3CAwADAAAGAAKAABAAAARABAAgAAA=","55":"b:dgMDpIBsoB3CAwADAAAGAAKAABAAAARABAAgAAA=","89":"b:dgMDpIBsoB3CAwADAAAGAAKAABAAAARABAAgAAA=","119":"b:dgMDpIBsoB3CAwADAAAGAAKAABAAAARABAAgAAA=","125":"b:dgMDpIBsoB3CAwADAAAGAAKAABAAAARABAAgAAA=","140":"b:dgMDpIBsoB3CAwADAAAGAAKAABAAAARABAAgAAA=","164":"b:dgMDpIBsoB3CAwADAAAGAAKAABAAAARABAAgAAA=","182":"b:dgMDpIBsoB3CAwADAAAGAAKAABAAAARABAAgAAA=","190":"b:dgMDpIBsoB3CAwADAAAGAAKAABAAAARABAAgAAA=","200":"b:dgMDpIBsoB3CAwADAAAGAAKAABAAAARABAAgAAA=","210":"b:dgMDpIBsoB3CAwADAAAGAAKAABAAAARABAAgAAA=","222":"b:dgMDpIBsoB3CAwADAAAGAAKAABAAAARABAAgAAA="},"packages/@n8n/db/src/repositories/shared-credentials.repository.ts":{"13":"b:dgMBpABtoFniAwADAIgAAAAAAEAAAAQABACgAAA=","17":"b:dgMBpABtoFniAwADAIgAAAAAAEAAAAQABACgAAA=","28":"b:dgMBpABtoFniAwADAIgAAAAAAEAAAAQABACgAAA=","36":"b:dgMBpABtoFniAwADAIgAAAAAAEAAAAQABACgAAA=","39":"b:dgMBpABtoFniAwADAIgAAAAAAEAAAAQABACgAAA=","51":"b:dgMBpABtoFniAwADAIgAAAAAAEAAAAQABACgAAA=","61":"b:dgMBpABtoFniAwADAIgAAAAAAEAAAAQABACgAAA=","66":"b:dgMBpABtoFniAwADAIgAAAAAAEAAAAQABACgAAA=","77":"b:dgMBpABtoFniAwADAIgAAAAAAEAAAAQABACgAAA=","86":"b:dgMBpABtoFniAwADAIgAAAAAAEAAAAQABACgAAA=","98":"b:dgMBpABtoFniAwADAIgAAAAAAEAAAAQABACgAAA=","101":"b:dgMBpABtoFniAwADAIgAAAAAAEAAAAQABACgAAA=","110":"b:dgMBpABtoFniAwADAIgAAAAAAEAAAAQABACgAAA=","119":"b:dgMBpABtoFniAwADAIgAAAAAAEAAAAQABACgAAA=","124":"b:dgMBpABtoFniAwADAIgAAAAAAEAAAAQABACgAAA=","137":"b:dgMBpABtoFniAwADAIgAAAAAAEAAAAQABACgAAA=","153":"b:dgMBpABtoFniAwADAIgAAAAAAEAAAAQABACgAAA=","181":"b:dgMBpABtoFniAwADAIgAAAAAAEAAAAQABACgAAA=","190":"b:dgMBpABtoFniAwADAIgAAAAAAEAAAAQABACgAAA=","191":"b:dgMBpABtoFniAwADAIgAAAAAAEAAAAQABACgAAA=","206":"b:dgMBpABtoFniAwADAIgAAAAAAEAAAAQABACgAAA=","207":"b:dgMBpABtoFniAwADAIgAAAAAAEAAAAQABACgAAA=","217":"b:dgMBpABtoFniAwADAIgAAAAAAEAAAAQABACgAAA="},"packages/@n8n/db/src/repositories/shared-workflow.repository.ts":{"28":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","36":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","41":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","44":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","61":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","64":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","77":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","80":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","93":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","96":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","133":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","158":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","166":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","170":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","182":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","185":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","206":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","216":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","222":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","234":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","246":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","258":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","261":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","270":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","277":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","284":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","290":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","303":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","312":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","321":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","330":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","335":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","348":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA=","401":"b:r59v/ve7/3/tv38fnIwECMABAMAEBklP/wfQEQA="},"packages/@n8n/db/src/repositories/user.repository.ts":{"21":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","25":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","42":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","56":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","60":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","67":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","74":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","80":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","104":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","114":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","119":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","146":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","156":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","160":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","164":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","171":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","175":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","186":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","193":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","204":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","211":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","215":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","262":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","295":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","317":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","325":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","346":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","359":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","367":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","372":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","431":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","457":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","476":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","498":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA=","509":"b:/x/+/+N/q3/rv63/HyAAAFgDAFAgAEFK+x/QBQA="},"packages/@n8n/db/src/repositories/workflow-content-write-context.ts":{"7":"b:/wto/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","10":"b:/wto/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/@n8n/db/src/repositories/workflow-dependency.repository.ts":{"37":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAABB/wcAAAA=","43":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAABB/wcAAAA=","62":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAABB/wcAAAA=","77":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAABB/wcAAAA=","109":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAABB/wcAAAA=","122":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAABB/wcAAAA=","137":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAABB/wcAAAA=","156":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAABB/wcAAAA=","171":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAABB/wcAAAA=","198":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAABB/wcAAAA=","202":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAABB/wcAAAA=","207":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAABB/wcAAAA=","254":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAABB/wcAAAA=","279":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAABB/wcAAAA=","280":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAABB/wcAAAA=","291":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAABB/wcAAAA=","317":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAABB/wcAAAA="},"packages/@n8n/db/src/repositories/workflow-history.repository.ts":{"20":"b:ggJMtEAEAxEALyQAAAAAAAAEAQBAGAEECAAAAAA=","24":"b:ggJMtEAEAxEALyQAAAAAAAAEAQBAGAEECAAAAAA=","39":"b:ggJMtEAEAxEALyQAAAAAAAAEAQBAGAEECAAAAAA=","62":"b:ggJMtEAEAxEALyQAAAAAAAAEAQBAGAEECAAAAAA=","66":"b:ggJMtEAEAxEALyQAAAAAAAAEAQBAGAEECAAAAAA=","83":"b:ggJMtEAEAxEALyQAAAAAAAAEAQBAGAEECAAAAAA=","105":"b:ggJMtEAEAxEALyQAAAAAAAAEAQBAGAEECAAAAAA=","159":"b:ggJMtEAEAxEALyQAAAAAAAAEAQBAGAEECAAAAAA=","160":"b:ggJMtEAEAxEALyQAAAAAAAAEAQBAGAEECAAAAAA=","164":"b:ggJMtEAEAxEALyQAAAAAAAAEAQBAGAEECAAAAAA=","178":"b:ggJMtEAEAxEALyQAAAAAAAAEAQBAGAEECAAAAAA=","184":"b:ggJMtEAEAxEALyQAAAAAAAAEAQBAGAEECAAAAAA=","220":"b:ggJMtEAEAxEALyQAAAAAAAAEAQBAGAEECAAAAAA=","235":"b:ggJMtEAEAxEALyQAAAAAAAAEAQBAGAEECAAAAAA="},"packages/@n8n/db/src/repositories/workflow-publication-outbox.repository.ts":{"24":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","36":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","44":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","66":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","72":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","82":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","94":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","113":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","139":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","153":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","182":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","195":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","233":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","265":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","287":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","313":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","334":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","363":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","375":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","383":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","425":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","428":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","446":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","453":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","484":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","502":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","517":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","533":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","553":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","573":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","598":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","607":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","629":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","638":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","650":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","660":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA=","672":"b:Dxtu+GM+o3PJvglHAAAAAFAAAAAAAEBK+wfRAQA="},"packages/@n8n/db/src/repositories/workflow-publication-trigger-status.repository.ts":{"30":"b:Dxtu+OO/o3/JvklPHBgECNAAAAAAAEBK+yfQAQA=","35":"b:Dxtu+OO/o3/JvklPHBgECNAAAAAAAEBK+yfQAQA=","40":"b:Dxtu+OO/o3/JvklPHBgECNAAAAAAAEBK+yfQAQA=","45":"b:Dxtu+OO/o3/JvklPHBgECNAAAAAAAEBK+yfQAQA=","50":"b:Dxtu+OO/o3/JvklPHBgECNAAAAAAAEBK+yfQAQA=","65":"b:Dxtu+OO/o3/JvklPHBgECNAAAAAAAEBK+yfQAQA=","70":"b:Dxtu+OO/o3/JvklPHBgECNAAAAAAAEBK+yfQAQA=","97":"b:Dxtu+OO/o3/JvklPHBgECNAAAAAAAEBK+yfQAQA="},"packages/@n8n/db/src/repositories/workflow-publish-history.repository.ts":{"14":"b:ixFvgGEU43DJ7iQHAAAIAEgAAAAABUFK+wfAAQA=","18":"b:ixFvgGEU43DJ7iQHAAAIAEgAAAAABUFK+wfAAQA=","26":"b:ixFvgGEU43DJ7iQHAAAIAEgAAAAABUFK+wfAAQA=","48":"b:ixFvgGEU43DJ7iQHAAAIAEgAAAAABUFK+wfAAQA=","70":"b:ixFvgGEU43DJ7iQHAAAIAEgAAAAABUFK+wfAAQA=","94":"b:ixFvgGEU43DJ7iQHAAAIAEgAAAAABUFK+wfAAQA=","115":"b:ixFvgGEU43DJ7iQHAAAIAEgAAAAABUFK+wfAAQA=","132":"b:ixFvgGEU43DJ7iQHAAAIAEgAAAAABUFK+wfAAQA=","153":"b:ixFvgGEU43DJ7iQHAAAIAEgAAAAABUFK+wfAAQA="},"packages/@n8n/db/src/repositories/workflow-statistics.repository.ts":{"44":"b:DxBOXnUg4WGJsz4EAAAIAAAAAAAAAAIA+wfYAQA=","52":"b:DxBOXnUg4WGJsz4EAAAIAAAAAAAAAAIA+wfYAQA=","62":"b:DxBOXnUg4WGJsz4EAAAIAAAAAAAAAAIA+wfYAQA=","95":"b:DxBOXnUg4WGJsz4EAAAIAAAAAAAAAAIA+wfYAQA=","138":"b:DxBOXnUg4WGJsz4EAAAIAAAAAAAAAAIA+wfYAQA=","143":"b:DxBOXnUg4WGJsz4EAAAIAAAAAAAAAAIA+wfYAQA=","156":"b:DxBOXnUg4WGJsz4EAAAIAAAAAAAAAAIA+wfYAQA=","209":"b:DxBOXnUg4WGJsz4EAAAIAAAAAAAAAAIA+wfYAQA=","214":"b:DxBOXnUg4WGJsz4EAAAIAAAAAAAAAAIA+wfYAQA=","224":"b:DxBOXnUg4WGJsz4EAAAIAAAAAAAAAAIA+wfYAQA="},"packages/@n8n/db/src/repositories/workflow-tag-mapping.repository.ts":{"10":"b:AgIAsAAEABFALiQAAAAAAAAEAQBAGIBAAAAAAAA=","14":"b:AgIAsAAEABFALiQAAAAAAAAEAQBAGIBAAAAAAAA=","15":"b:AgIAsAAEABFALiQAAAAAAAAEAQBAGIBAAAAAAAA=","18":"b:AgIAsAAEABFALiQAAAAAAAAEAQBAGIBAAAAAAAA="},"packages/@n8n/db/src/repositories/workflow.repository.ts":{"90":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","107":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","126":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","139":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","180":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","199":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","218":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","236":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","246":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","252":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","255":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","262":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","265":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","271":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","280":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","286":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","296":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","311":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","318":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","330":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","336":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","337":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","361":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","363":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","374":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","385":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","396":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","407":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","413":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","416":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","432":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","441":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","448":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","457":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","464":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","470":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","480":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","501":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","520":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","540":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","548":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","552":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","560":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","563":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","585":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","592":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","598":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","604":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","614":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","703":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","727":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","749":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","775":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","786":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","787":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","790":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","812":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","856":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","914":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","948":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","978":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1058":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1069":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1074":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1075":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1078":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1080":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1081":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1084":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1099":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1106":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1107":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1109":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1118":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1130":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1147":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1174":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1245":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1268":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1307":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1317":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1333":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1347":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1357":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1372":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1385":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1402":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1414":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1422":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1445":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1453":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1459":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1470":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1476":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1481":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1492":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1508":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1529":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1542":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1551":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1572":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1583":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1596":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1606":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1619":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1624":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1649":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1676":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1680":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1690":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1725":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1741":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1747":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1757":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1773":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1782":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1789":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1796":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1803":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1813":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1828":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1862":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1869":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1873":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1888":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1895":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1929":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1946":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","1987":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","2003":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA=","2042":"b:/5vu/ve/73/Nv//fHjoECsAFwcBAGEDK/yfZKQA="},"packages/@n8n/db/src/services/typeorm-transaction.ts":{"16":"b:/wv4/ncqonvLvwkTAAAAAAAAAAAAAAAA/4cAAAA=","21":"b:/wv4/ncqonvLvwkTAAAAAAAAAAAAAAAA/4cAAAA=","29":"b:/wv4/ncqonvLvwkTAAAAAAAAAAAAAAAA/4cAAAA=","36":"b:/wv4/ncqonvLvwkTAAAAAAAAAAAAAAAA/4cAAAA=","59":"b:/wv4/ncqonvLvwkTAAAAAAAAAAAAAAAA/4cAAAA="},"packages/@n8n/db/src/subscribers/user-subscriber.ts":{"12":"b:BlgFAEAAgERJDAAgkAAAAAAAAAQAAEAI+w9ABAA=","15":"b:BlgFAEAAgERJDAAgkAAAAAAAAAQAAEAI+w9ABAA=","19":"b:BlgFAEAAgERJDAAgkAAAAAAAAAQAAEAI+w9ABAA=","24":"b:BlgFAEAAgERJDAAgkAAAAAAAAAQAAEAI+w9ABAA="},"packages/@n8n/db/src/subscribers/workflow-entity-subscriber.ts":{"10":"b:/xtq/nc+o3vJvw0XAAAAAMABAABAAAAA/weAAAA=","12":"b:/xtq/nc+o3vJvw0XAAAAAMABAABAAAAA/weAAAA=","16":"b:/xtq/nc+o3vJvw0XAAAAAMABAABAAAAA/weAAAA=","20":"b:/xtq/nc+o3vJvw0XAAAAAMABAABAAAAA/weAAAA=","24":"b:/xtq/nc+o3vJvw0XAAAAAMABAABAAAAA/weAAAA=","32":"b:/xtq/nc+o3vJvw0XAAAAAMABAABAAAAA/weAAAA="},"packages/@n8n/db/src/utils/chunk-ids.ts":{"6":"b:j4JvBIGh43/IrwALnAAACAgAAAAAAAAAAAAIEAA="},"packages/@n8n/db/src/utils/dialect-time.ts":{"13":"b:QgJIiICKAFNTMABDWPogAAAAAAAAAAAAUAIAAAA=","22":"b:QgJIiICKAFNTMABDWPogAAAAAAAAAAAAUAIAAAA=","38":"b:QgJIiICKAFNTMABDWPogAAAAAAAAAAAAUAIAAAA=","54":"b:QgJIiICKAFNTMABDWPogAAAAAAAAAAAAUAIAAAA=","76":"b:QgJIiICKAFNTMABDWPogAAAAAAAAAAAAUAIAAAA=","94":"b:QgJIiICKAFNTMABDWPogAAAAAAAAAAAAUAIAAAA="},"packages/@n8n/db/src/utils/is-query-failed-error-of-kind.ts":{"10":"b:AgEBAwACAEAAAwASGAMCAAAAgAAAEAWAAwAgAAA="},"packages/@n8n/db/src/utils/is-unique-constraint-error.ts":{"6":"b:AgEBAwACAEAAAwASGAMCAAAAgAAAEAWAAwAgAAA="},"packages/@n8n/db/src/utils/transformers.ts":{"7":"b:/wto/ncq43vJvz8TAAAAAAAAAAAAAAAA/wfQAAA=","8":"b:/wto/ncq43vJvz8TAAAAAAAAAAAAAAAA/wfQAAA=","15":"b:/wto/ncq43vJvz8TAAAAAAAAAAAAAAAA/wfQAAA=","16":"b:/wto/ncq43vJvz8TAAAAAAAAAAAAAAAA/wfQAAA=","23":"b:/wto/ncq43vJvz8TAAAAAAAAAAAAAAAA/wfQAAA=","24":"b:/wto/ncq43vJvz8TAAAAAAAAAAAAAAAA/wfQAAA=","32":"b:/wto/ncq43vJvz8TAAAAAAAAAAAAAAAA/wfQAAA=","34":"b:/wto/ncq43vJvz8TAAAAAAAAAAAAAAAA/wfQAAA=","44":"b:/wto/ncq43vJvz8TAAAAAAAAAAAAAAAA/wfQAAA=","45":"b:/wto/ncq43vJvz8TAAAAAAAAAAAAAAAA/wfQAAA="},"packages/@n8n/decorators/src/execution-lifecycle/lifecycle-metadata.ts":{"97":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","100":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","104":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA="},"packages/@n8n/decorators/src/policy-check/policy-check-metadata.ts":{"30":"b:/wvo/3cqo3vLvwkTAQAAAAAAAAAAAAAA/wcAAAA=","55":"b:/wvo/3cqo3vLvwkTAQAAAAAAAAAAAAAA/wcAAAA=","65":"b:/wvo/3cqo3vLvwkTAQAAAAAAAAAAAAAA/wcAAAA=","70":"b:/wvo/3cqo3vLvwkTAQAAAAAAAAAAAAAA/wcAAAA=","71":"b:/wvo/3cqo3vLvwkTAQAAAAAAAAAAAAAA/wcAAAA=","92":"b:/wvo/3cqo3vLvwkTAQAAAAAAAAAAAAAA/wcAAAA=","94":"b:/wvo/3cqo3vLvwkTAQAAAAAAAAAAAAAA/wcAAAA=","125":"b:/wvo/3cqo3vLvwkTAQAAAAAAAAAAAAAA/wcAAAA=","126":"b:/wvo/3cqo3vLvwkTAQAAAAAAAAAAAAAA/wcAAAA="},"packages/@n8n/decorators/src/policy-check/policy-cleared.ts":{"28":"b:/wvr/3duo3vLvw0TAQACAIAFAUBAGAQA/wcgAAA=","39":"b:/wvr/3duo3vLvw0TAQACAIAFAUBAGAQA/wcgAAA=","55":"b:/wvr/3duo3vLvw0TAQACAIAFAUBAGAQA/wcgAAA=","69":"b:/wvr/3duo3vLvw0TAQACAIAFAUBAGAQA/wcgAAA=","78":"b:/wvr/3duo3vLvw0TAQACAIAFAUBAGAQA/wcgAAA=","113":"b:/wvr/3duo3vLvw0TAQACAIAFAUBAGAQA/wcgAAA="},"packages/@n8n/decorators/src/policy-check/policy-mint.ts":{"15":"b:/wvo/3cqo3vLvwkTAQAAAAAAAAAAAAAA/wcAAAA="},"packages/@n8n/decorators/src/redactable.ts":{"14":"b:/wv4/1cLgnvZtwmSHwAAAAAAgAAAAAAA/98GAAA=","21":"b:/wv4/1cLgnvZtwmSHwAAAAAAgAAAAAAA/98GAAA=","46":"b:/wv4/1cLgnvZtwmSHwAAAAAAgAAAAAAA/98GAAA=","47":"b:/wv4/1cLgnvZtwmSHwAAAAAAgAAAAAAA/98GAAA=","53":"b:/wv4/1cLgnvZtwmSHwAAAAAAgAAAAAAA/98GAAA=","54":"b:/wv4/1cLgnvZtwmSHwAAAAAAgAAAAAAA/98GAAA="},"packages/@n8n/errors/src/base.error.ts":{"32":"b:T8t8nyRCQmGIsztQGAMBAAiCgQCAYA0AE4DQAQA="},"packages/@n8n/errors/src/index.ts":{"4":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","8":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","9":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","10":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","11":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","13":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","14":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","15":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","16":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","17":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","18":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","19":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","20":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA="},"packages/@n8n/errors/src/isolate.error.ts":{"2":"b:fwFAXnVgxGGJvyQCAAAAAAAAAAAAAABA/wdAAQA="},"packages/@n8n/errors/src/operational.error.ts":{"15":"b:QhAADABCAAAAAwAAAAABAAAAAAAABAWAAAAAIAA="},"packages/@n8n/errors/src/user.error.ts":{"18":"b:CwQEmARASGGAozhAAAMBAAgAAADAYAQAAAAQAAA="},"packages/@n8n/expression-runtime/src/bridge/host-functions.ts":{"17":"b:fwEABHlAQAAIIDwAAAAIAAgAAAAARGEAAQBYgQA=","34":"b:fwEABHlAQAAIIDwAAAAIAAgAAAAARGEAAQBYgQA=","37":"b:fwEABHlAQAAIIDwAAAAIAAgAAAAARGEAAQBYgQA=","56":"b:fwEABHlAQAAIIDwAAAAIAAgAAAAARGEAAQBYgQA=","88":"b:fwEABHlAQAAIIDwAAAAIAAgAAAAARGEAAQBYgQA=","154":"b:fwEABHlAQAAIIDwAAAAIAAgAAAAARGEAAQBYgQA=","249":"b:fwEABHlAQAAIIDwAAAAIAAgAAAAARGEAAQBYgQA="},"packages/@n8n/expression-runtime/src/bridge/isolated-vm-bridge.ts":{"25":"b:fwFIXn0i42GJvz4CAAAIAAgAAAAARGBA/wdYgQA=","46":"b:fwFIXn0i42GJvz4CAAAIAAgAAAAARGBA/wdYgQA=","64":"b:fwFIXn0i42GJvz4CAAAIAAgAAAAARGBA/wdYgQA=","99":"b:fwFIXn0i42GJvz4CAAAIAAgAAAAARGBA/wdYgQA=","133":"b:fwFIXn0i42GJvz4CAAAIAAgAAAAARGBA/wdYgQA=","156":"b:fwFIXn0i42GJvz4CAAAIAAgAAAAARGBA/wdYgQA=","195":"b:fwFIXn0i42GJvz4CAAAIAAgAAAAARGBA/wdYgQA=","248":"b:fwFIXn0i42GJvz4CAAAIAAgAAAAARGBA/wdYgQA=","265":"b:fwFIXn0i42GJvz4CAAAIAAgAAAAARGBA/wdYgQA=","309":"b:fwFIXn0i42GJvz4CAAAIAAgAAAAARGBA/wdYgQA=","310":"b:fwFIXn0i42GJvz4CAAAIAAgAAAAARGBA/wdYgQA=","329":"b:fwFIXn0i42GJvz4CAAAIAAgAAAAARGBA/wdYgQA=","330":"b:fwFIXn0i42GJvz4CAAAIAAgAAAAARGBA/wdYgQA=","356":"b:fwFIXn0i42GJvz4CAAAIAAgAAAAARGBA/wdYgQA=","357":"b:fwFIXn0i42GJvz4CAAAIAAgAAAAARGBA/wdYgQA=","386":"b:fwFIXn0i42GJvz4CAAAIAAgAAAAARGBA/wdYgQA=","502":"b:fwFIXn0i42GJvz4CAAAIAAgAAAAARGBA/wdYgQA=","516":"b:fwFIXn0i42GJvz4CAAAIAAgAAAAARGBA/wdYgQA=","537":"b:fwFIXn0i42GJvz4CAAAIAAgAAAAARGBA/wdYgQA="},"packages/@n8n/expression-runtime/src/evaluator/expression-evaluator.ts":{"19":"b:fwFIXn1i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","74":"b:fwFIXn1i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","76":"b:fwFIXn1i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","80":"b:fwFIXn1i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","86":"b:fwFIXn1i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","104":"b:fwFIXn1i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","119":"b:fwFIXn1i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","147":"b:fwFIXn1i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","184":"b:fwFIXn1i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","225":"b:fwFIXn1i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","245":"b:fwFIXn1i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","253":"b:fwFIXn1i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","266":"b:fwFIXn1i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","280":"b:fwFIXn1i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","296":"b:fwFIXn1i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","303":"b:fwFIXn1i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA="},"packages/@n8n/expression-runtime/src/pool/isolate-pool.ts":{"6":"b:fwFIXnVi52GJvy4CAAAAAAAAAAAAAABA/wdAAQA=","13":"b:fwFIXnVi52GJvy4CAAAAAAAAAAAAAABA/wdAAQA=","36":"b:fwFIXnVi52GJvy4CAAAAAAAAAAAAAABA/wdAAQA=","43":"b:fwFIXnVi52GJvy4CAAAAAAAAAAAAAABA/wdAAQA=","45":"b:fwFIXnVi52GJvy4CAAAAAAAAAAAAAABA/wdAAQA=","67":"b:fwFIXnVi52GJvy4CAAAAAAAAAAAAAABA/wdAAQA=","75":"b:fwFIXnVi52GJvy4CAAAAAAAAAAAAAABA/wdAAQA=","80":"b:fwFIXnVi52GJvy4CAAAAAAAAAAAAAABA/wdAAQA=","83":"b:fwFIXnVi52GJvy4CAAAAAAAAAAAAAABA/wdAAQA=","90":"b:fwFIXnVi52GJvy4CAAAAAAAAAAAAAABA/wdAAQA=","96":"b:fwFIXnVi52GJvy4CAAAAAAAAAAAAAABA/wdAAQA=","103":"b:fwFIXnVi52GJvy4CAAAAAAAAAAAAAABA/wdAAQA=","112":"b:fwFIXnVi52GJvy4CAAAAAAAAAAAAAABA/wdAAQA=","119":"b:fwFIXnVi52GJvy4CAAAAAAAAAAAAAABA/wdAAQA="},"packages/@n8n/expression-runtime/src/runtime/luxon-transfer.ts":{"49":"b:fwEABHlAQAAIIDwAAAAIAAACAAAARCAAAQBIAQA=","53":"b:fwEABHlAQAAIIDwAAAAIAAACAAAARCAAAQBIAQA=","57":"b:fwEABHlAQAAIIDwAAAAIAAACAAAARCAAAQBIAQA=","61":"b:fwEABHlAQAAIIDwAAAAIAAACAAAARCAAAQBIAQA=","65":"b:fwEABHkAQAAIIDwAAAAIAAACAAAARCAAAQBIAQA=","83":"b:fwEABHkAQAAIIDwAAAAIAAACAAAARCAAAQBIAQA=","94":"b:fwEABHkAQAAIIDwAAAAIAAACAAAARCAAAQBIAQA=","139":"b:fwEABHlAQAAIIDwAAAAIAAACAAAARCAAAQBIAQA=","150":"b:fwEABHlAQAAIIDwAAAAIAAACAAAARCAAAQBIAQA=","158":"b:fwEABHlAQAAIIDwAAAAIAAACAAAARCAAAQBIAQA=","160":[46],"161":"b:fwEABHkAQAAIIDwAAAAIAAACAAAARCAAAQBIAQA=","166":"b:fwEABHlAQAAIIDwAAAAIAAACAAAARCAAAQBIAQA=","179":"b:fwEABHlAQAAIIDwAAAAIAAACAAAARCAAAQBIAQA=","187":"b:fwEABHlAQAAIIDwAAAAIAAACAAAARCAAAQBIAQA=","196":"b:fwEABHlAQAAIIDwAAAAIAAACAAAARCAAAQBIAQA=","208":"b:fwEABHkAQAAIIDwAAAAIAAACAAAARCAAAQBIAQA=","221":"b:fwEABHkAQAAIIDwAAAAIAAACAAAARCAAAQBIAQA=","227":"b:fwEABHkAQAAIIDwAAAAIAAACAAAARCAAAQBIAQA="},"packages/@n8n/expression-runtime/src/runtime/transfer.ts":{"64":"b:fwEABHlAQAAIIDwAgAAIAAgCAAAARCAAAQBYAQA=","70":"b:fwEABHlAQAAIIDwAgAAIAAgCAAAARCAAAQBYAQA=","75":"b:fwEABHkAQAAIIDwAgAAIAAgCAAAARCAAAQBYAQA=","79":"b:fwEABHlAQAAIIDwAgAAIAAgCAAAARCAAAQBYAQA=","87":"b:fwEABHlAQAAIIDwAgAAIAAgCAAAARCAAAQBYAQA=","92":"b:fwEABHlAQAAIIDwAgAAIAAgCAAAARCAAAQBYAQA=","98":"b:fwEABHkAQAAIIDwAgAAIAAgCAAAARCAAAQBYAQA=","111":"b:fwEABHkAQAAIIDwAgAAIAAgCAAAARCAAAQBYAQA=","126":"b:fwEABHkAQAAIIDwAgAAIAAgCAAAARCAAAQBYAQA=","134":"b:fwEABHkAQAAIIDwAgAAIAAgCAAAARCAAAQBYAQA=","164":"b:fwEABHkAQAAIIDwAgAAIAAgCAAAARCAAAQBYAQA=","195":"b:fwEABHkAQAAIIDwAgAAIAAgCAAAARCAAAQBYAQA="},"packages/@n8n/instance-ai/src/runtime/background-task-manager.ts":{"125":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAEAAAAA=","135":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAEAAAAA=","139":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAEAAAAA=","166":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAEAAAAA=","167":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAEAAAAA=","170":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAEAAAAA=","172":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAEAAAAA=","177":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAEAAAAA=","178":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAEAAAAA=","182":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAEAAAAA=","196":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAEAAAAA=","201":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAEAAAAA=","208":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAEAAAAA=","226":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAEAAAAA=","238":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAEAAAAA=","252":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAEAAAAA=","265":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAEAAAAA=","272":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAEAAAAA=","294":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAEAAAAA=","354":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAEAAAAA=","371":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAEAAAAA=","375":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAEAAAAA=","381":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAEAAAAA=","382":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAEAAAAA=","426":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAEAAAAA=","452":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAEAAAAA="},"packages/@n8n/instance-ai/src/runtime/run-state-registry.ts":{"175":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","177":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","216":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","226":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","239":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","240":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","252":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","256":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","260":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","264":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","268":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","277":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","278":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","283":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","287":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","298":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","321":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","331":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","335":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","339":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","350":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","355":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","363":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","378":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","385":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","393":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","422":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","430":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","434":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","442":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","449":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","456":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","463":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","476":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","498":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","506":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","509":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","525":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","529":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","534":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","539":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","544":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","549":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","553":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","557":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","562":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","567":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","571":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","576":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","580":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","584":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","608":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","707":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","716":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","725":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","771":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","777":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA=","783":"b:QgJ4iKCKA1NSMABDWPowAAAAAAAAAAAAAAAAAAA="},"packages/@n8n/nodes-langchain/nodes/agents/Agent/Agent.node.ts":{"9":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/V1/AgentV1.node.ts":{"37":[1,8,4,5,6,9,11,13,14,18,15],"53":[1,8,4,5,6,9,11,13,14,18,15],"63":[1,8,4,5,6,9,11,13,14,18,15],"221":[1,8,4,5,6,9,11,13,14,18,15],"276":[1,8,4,5,6,9,11,13,14,18,15],"349":[1,8,4,5,6,9,11,13,14,18,15],"458":[1,8,4,5,6,9,11,13,14,18,15]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/V2/AgentV2.node.ts":{"24":[1,8,4,5,6,9,11,13,14,15],"134":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/V3/AgentV3.node.ts":{"28":[1,8,4,5,6,9,11,13,14,15],"144":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ConversationalAgent/execute.ts":{"16":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/OpenAiFunctionsAgent/execute.ts":{"15":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/PlanAndExecuteAgent/execute.ts":{"18":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ReActAgent/execute.ts":{"21":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/SqlAgent/execute.ts":{"25":[1,8,4,5,6,9,11,13,14,15],"28":[1,8,4,5,6,9,11,13,14,15],"29":[1,8,4,5,6,9,11,13,14,15],"31":[1,8,4,5,6,9,11,13,14,15],"37":[1,8,4,5,6,9,11,13,14,15],"54":[1,8,4,5,6,9,11,13,14,15],"67":[1,8,4,5,6,9,11,13,14,15],"156":[1,8,4,5,6,9,11,13,14,15],"162":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/SqlAgent/other/handlers/mysql.ts":{"4":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/SqlAgent/other/handlers/postgres.ts":{"6":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/SqlAgent/other/handlers/sqlite.ts":{"8":[1,8,4,5,6,9,11,13,14,15],"38":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V1/execute.ts":{"36":[1,8,4,5,6,9,11,13,14,18,15]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V2/description.ts":{"15":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V2/execute.ts":{"62":[1,8,4,5,6,9,11,13,14,15],"110":[1,8,4,5,6,9,11,13,14,15],"115":[1,8,4,5,6,9,11,13,14,15],"120":[1,8,4,5,6,9,11,13,14,15],"150":[1,8,4,5,6,9,11,13,14,15],"224":[1,8,4,5,6,9,11,13,14,15],"240":[1,8,4,5,6,9,11,13,14,15],"264":[1,8,4,5,6,9,11,13,14,15],"323":[1,8,4,5,6,9,11,13,14,15],"427":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/execute.ts":{"34":[1,8,4,5,6,9,11,13,14,15],"59":[1,8,4,5,6,9,11,13,14,15],"139":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/buildExecutionContext.ts":{"29":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/checkMaxIterations.ts":{"27":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/createAgentSequence.ts":{"25":[1,8,4,5,6,9,11,13,14,15],"73":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/executeBatch.ts":{"40":[1,8,4,5,6,9,11,13,14,15],"78":[1,8,4,5,6,9,11,13,14,15],"108":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/finalizeResult.ts":{"21":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/index.ts":{"11":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/prepareItemContext.ts":{"41":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/resolveSubAgentRequest.ts":{"25":[1,8,4,5,6,9,11,13,14,15],"40":[1,8,4,5,6,9,11,13,14,15],"49":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/runAgent.ts":{"32":[1,8,4,5,6,9,11,13,14,15],"39":[1,8,4,5,6,9,11,13,14,15],"67":[1,8,4,5,6,9,11,13,14,15],"80":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/common.ts":{"32":[1,8,4,5,6,9,11,13,14,18,15],"45":[1,8,4,5,6,9,11,13,14,18,15],"56":[1,8,4,5,6,9,11,13,14,18,15],"60":[1,8,4,5,6,9,11,13,14,18,15],"78":[1,8,4,5,6,9,11,13,14,18,15],"112":[1,8,4,5,6,9,11,13,14,18,15],"133":[1,8,4,5,6,9,11,13,14,18,15],"218":[1,8,4,5,6,9,11,13,14,18,15],"228":[1,8,4,5,6,9,11,13,14,18,15],"229":[1,8,4,5,6,9,11,13,14,18,15],"280":[1,8,4,5,6,9,11,13,14,18,15],"285":[1,8,4,5,6,9,11,13,14,18,15],"288":[1,8,4,5,6,9,11,13,14,18,15],"290":[1,8,4,5,6,9,11,13,14,18,15],"336":[1,8,4,5,6,9,11,13,14,18,15],"357":[1,8,4,5,6,9,11,13,14,18,15],"358":[1,8,4,5,6,9,11,13,14,18,15],"368":[1,8,4,5,6,9,11,13,14,18,15],"369":[1,8,4,5,6,9,11,13,14,18,15],"395":[1,8,4,5,6,9,11,13,14,18,15],"415":[1,8,4,5,6,9,11,13,14,18,15],"416":[1,8,4,5,6,9,11,13,14,18,15],"419":[1,8,4,5,6,9,11,13,14,18,15],"485":[1,8,4,5,6,9,11,13,14,18,15],"519":[1,8,4,5,6,9,11,13,14,18,15],"535":[1,8,4,5,6,9,11,13,14,18,15],"550":[1,8,4,5,6,9,11,13,14,18,15],"565":[1,8,4,5,6,9,11,13,14,18,15],"622":[1,8,4,5,6,9,11,13,14,18,15]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/utils.ts":{"18":[1,8,4,5,6,9,11,13,14,15],"24":[1,8,4,5,6,9,11,13,14,15],"41":[1,8,4,5,6,9,11,13,14,15],"47":[1,8,4,5,6,9,11,13,14,15],"50":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/utils.ts":{"11":[1,8,4,5,6,9,11,13,14,15],"23":[1,8,4,5,6,9,11,13,14,15],"26":[1,8,4,5,6,9,11,13,14,15],"86":[1,8,4,5,6,9,11,13,14,15],"89":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/nodes/llms/LMChatOpenAi/LmChatOpenAi.node.ts":{"76":[1,2,13,15],"753":[1,2,13,15]},"packages/@n8n/nodes-langchain/nodes/llms/LMChatOpenAi/common.ts":{"17":[1,2,13,15],"20":[1,2,13,15],"23":[1,2,13,15],"26":[1,2,13,15],"29":[1,2,13,15],"32":[1,2,13,15],"84":[1,2,13,15]},"packages/@n8n/nodes-langchain/nodes/llms/LMChatOpenAi/methods/loadModels.ts":{"10":[1,2,13,15],"30":[1,2,13,15],"35":[1,2,13,15],"36":[1,2,13,15]},"packages/@n8n/nodes-langchain/nodes/llms/shared/extra-body.ts":{"13":[1,2,13,15],"26":[1,2,13,15],"58":[1,2,13,15]},"packages/@n8n/nodes-langchain/nodes/memory/MemoryRedisChat/MemoryRedisChat.node.ts":{"26":[1,15],"114":[1,15],"152":[1,15],"182":[1,15]},"packages/@n8n/nodes-langchain/nodes/memory/descriptions.ts":{"28":[1,4,5,6,15,16],"63":[1,4,5,6,15,16]},"packages/@n8n/nodes-langchain/nodes/tools/ToolCalculator/ToolCalculator.node.ts":{"15":[1],"21":[1],"55":[1],"61":[1]},"packages/@n8n/nodes-langchain/nodes/tools/ToolCode/ToolCode.node.ts":{"44":[1,10,12],"70":[1,10,12],"90":[1,10,12],"178":[1,10,12],"331":[1,10,12],"336":[1,10,12]},"packages/@n8n/nodes-langchain/nodes/tools/ToolWikipedia/ToolWikipedia.node.ts":{"17":[1,16],"25":[1,16],"58":[1,16],"64":[1,16]},"packages/@n8n/nodes-langchain/nodes/trigger/ChatTrigger/ChatTrigger.node.ts":{"50":[32,1,2,3,4,5,6,9,11,142,144,14,161,18,15],"66":[32,1,2,3,4,5,6,9,11,142,144,14,161,18,15],"70":[32,1,2,3,4,5,6,9,11,142,144,14,161,18,15],"293":[32,1,2,3,4,5,6,9,11,142,144,14,161,18,15],"853":[32,1,2,3,4,5,6,9,11,142,144,14,161,18,15],"916":[32,1,2,3,4,5,6,9,11,142,144,14,161,18,15],"1134":[32,1,2,3,4,5,6,9,11,142,144,14,161,18,15],"1135":[32,1,2,3,4,5,6,9,11,142,144,14,161,18,15]},"packages/@n8n/nodes-langchain/nodes/trigger/ChatTrigger/GenericFunctions.ts":{"17":[32,1,2,3,4,5,6,9,11,142,144,14,15],"26":[32,1,2,3,4,5,6,9,11,142,144,14,15],"30":[32,1,2,3,4,5,6,9,11,142,144,14,15],"46":[32,1,2,3,4,5,6,9,11,142,144,14,15],"64":[32,1,2,3,4,5,6,9,11,142,144,14,15],"158":[32,1,2,3,4,5,6,9,11,142,144,14,15],"270":[32,1,2,3,4,5,6,9,11,142,144,14,15],"305":[32,1,2,3,4,5,6,9,11,142,144,14,15],"362":[32,1,2,3,4,5,6,9,11,142,144,14,15]},"packages/@n8n/nodes-langchain/nodes/trigger/ChatTrigger/connect-panel.ts":{"6":[32,1,2,3,4,5,6,9,11,142,144,14,15],"13":[32,1,2,3,4,5,6,9,11,142,144,14,15],"17":[32,1,2,3,4,5,6,9,11,142,144,14,15],"18":[32,1,2,3,4,5,6,9,11,142,144,14,15],"32":[32,1,2,3,4,5,6,9,11,142,144,14,15],"49":[32,1,2,3,4,5,6,9,11,142,144,14,15]},"packages/@n8n/nodes-langchain/nodes/trigger/ChatTrigger/error.ts":{"4":[32,1,2,3,4,5,6,9,11,142,144,14,15]},"packages/@n8n/nodes-langchain/nodes/trigger/ChatTrigger/shell.ts":{"21":[32,1,2,3,4,5,6,9,11,142,144,14,15],"27":[32,1,2,3,4,5,6,9,11,142,144,14,15],"45":[32,1,2,3,4,5,6,9,11,142,144,14,15],"78":[32,1,2,3,4,5,6,9,11,142,144,14,15],"88":[32,1,2,3,4,5,6,9,11,142,144,14,15],"104":[32,1,2,3,4,5,6,9,11,142,144,14,15],"122":[32,1,2,3,4,5,6,9,11,142,144,14,15],"134":[32,1,2,3,4,5,6,9,11,142,144,14,15],"144":[32,1,2,3,4,5,6,9,11,142,144,14,15],"150":[32,1,2,3,4,5,6,9,11,142,144,14,15],"164":[32,1,2,3,4,5,6,9,11,142,144,14,15],"168":[32,1,2,3,4,5,6,9,11,142,144,14,15],"180":[32,1,2,3,4,5,6,9,11,142,144,14,15],"184":[32,1,2,3,4,5,6,9,11,142,144,14,15],"197":[32,1,2,3,4,5,6,9,11,142,144,14,15]},"packages/@n8n/nodes-langchain/nodes/trigger/ChatTrigger/templates.ts":{"23":[32,1,2,3,4,5,6,9,11,142,144,14,15],"24":[32,1,2,3,4,5,6,9,11,142,144,14,15],"27":[32,1,2,3,4,5,6,9,11,142,144,14,15],"43":[32,1,2,3,4,5,6,9,11,142,144,14,15],"48":[32,1,2,3,4,5,6,9,11,142,144,14,15],"49":[32,1,2,3,4,5,6,9,11,142,144,14,15],"52":[32,1,2,3,4,5,6,9,11,142,144,14,15],"78":[32,1,2,3,4,5,6,9,11,142,144,14,15],"116":[32,1,2,3,4,5,6,9,11,142,144,14,15],"336":[32,1,2,3,4,5,6,9,11,142,144,14,15]},"packages/@n8n/nodes-langchain/nodes/trigger/ChatTrigger/types.ts":{"62":[32,1,2,3,4,5,6,9,11,142,144,14,161,18,15],"66":[32,1,2,3,4,5,6,9,11,142,144,14,161,18,15]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/helpers/credentials.ts":{"16":[1,2,13,75,15]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/helpers/error-handling.ts":{"11":[1,2,13,75,15],"15":[1,2,13,75,15],"19":[1,2,13,75,15],"36":[1,2,13,75,15]},"packages/@n8n/nodes-langchain/utils/N8nTool.ts":{"11":[1,2,3,8,4,5,6,9,10,11,12,13,14,75,15,16],"25":[1,2,3,8,4,5,6,9,10,11,12,13,14,75,15,16],"28":[1,2,3,8,4,5,6,9,10,11,12,13,14,75,15,16],"33":[1,2,3,8,4,5,6,9,10,11,12,13,14,75,15,16],"50":[1,2,3,8,4,5,6,9,10,11,12,13,14,75,15,16],"57":[1,2,3,8,4,5,6,9,10,11,12,13,14,75,15,16],"62":[1,2,3,8,4,5,6,9,10,11,12,13,14,75,15,16]},"packages/@n8n/nodes-langchain/utils/agent-execution/buildResponseMetadata.ts":{"17":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/utils/agent-execution/buildSteps.ts":{"36":[1,8,4,5,6,9,11,13,14,15],"93":[1,8,4,5,6,9,11,13,14,15],"141":[1,8,4,5,6,9,11,13,14,15],"165":[1,8,4,5,6,9,11,13,14,15],"206":[1,8,4,5,6,9,11,13,14,15],"217":[1,8,4,5,6,9,11,13,14,15],"224":[1,8,4,5,6,9,11,13,14,15],"236":[1,8,4,5,6,9,11,13,14,15],"288":[1,8,4,5,6,9,11,13,14,15],"292":[1,8,4,5,6,9,11,13,14,15],"299":[1,8,4,5,6,9,11,13,14,15],"312":[1,8,4,5,6,9,11,13,14,15],"316":[1,8,4,5,6,9,11,13,14,15],"345":[1,8,4,5,6,9,11,13,14,15],"367":[1,8,4,5,6,9,11,13,14,15],"389":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/utils/agent-execution/createEngineRequests.ts":{"16":[1,8,4,5,6,9,11,13,14,15],"25":[1,8,4,5,6,9,11,13,14,15],"43":[1,8,4,5,6,9,11,13,14,15],"76":[1,8,4,5,6,9,11,13,14,15],"150":[1,8,4,5,6,9,11,13,14,15],"157":[1,8,4,5,6,9,11,13,14,15],"214":[1,8,4,5,6,9,11,13,14,15],"222":[1,8,4,5,6,9,11,13,14,15],"225":[1,8,4,5,6,9,11,13,14,15],"230":[1,8,4,5,6,9,11,13,14,15],"232":[1,8,4,5,6,9,11,13,14,15],"272":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/utils/agent-execution/executeEngineAction.ts":{"17":[1,8,4,5,6,9,11,13,14,15],"22":[1,8,4,5,6,9,11,13,14,15],"47":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/utils/agent-execution/index.ts":{"13":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/utils/agent-execution/memoryManagement.ts":{"25":[1,8,4,5,6,9,11,13,14,15],"81":[1,8,4,5,6,9,11,13,14,15],"148":[1,8,4,5,6,9,11,13,14,15],"151":[1,8,4,5,6,9,11,13,14,15],"164":[1,8,4,5,6,9,11,13,14,15],"242":[1,8,4,5,6,9,11,13,14,15],"294":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/utils/agent-execution/processEventStream.ts":{"22":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/utils/agent-execution/processHitlResponses.ts":{"26":[1,8,4,5,6,9,11,13,14,15],"38":[1,8,4,5,6,9,11,13,14,15],"47":[1,8,4,5,6,9,11,13,14,15],"54":[1,8,4,5,6,9,11,13,14,15],"71":[1,8,4,5,6,9,11,13,14,15],"80":[1,8,4,5,6,9,11,13,14,15],"106":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/utils/agent-execution/serializeIntermediateSteps.ts":{"10":[1,8,4,5,6,9,11,13,14,15],"15":[1,8,4,5,6,9,11,13,14,15],"29":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/utils/agent-execution/types.ts":{"194":[1,8,4,5,6,9,11,13,14,15],"210":[1,8,4,5,6,9,11,13,14,15],"224":[1,8,4,5,6,9,11,13,14,15]},"packages/@n8n/nodes-langchain/utils/chatModelMessageWrapper.ts":{"29":[1,2,13,15],"30":[1,2,13,15],"57":[1,2,13,15],"68":[1,2,13,15],"71":[1,2,13,15]},"packages/@n8n/nodes-langchain/utils/descriptions.ts":{"28":[1,2,3,8,4,5,6,9,10,11,12,13,14,75,15,16],"54":[1,2,3,8,4,5,6,9,10,11,12,13,14,75,15,16],"72":[1,2,3,8,4,5,6,9,10,11,12,13,14,75,15,16]},"packages/@n8n/nodes-langchain/utils/helpers.ts":{"23":[1,2,3,8,4,5,6,9,10,11,12,13,14,75,15,16],"30":[1,2,3,8,4,5,6,9,10,11,12,13,14,75,15,16],"77":[1,2,3,8,4,5,6,9,10,11,12,13,14,75,15,16],"90":[1,2,3,8,4,5,6,9,10,11,12,13,14,75,15,16],"99":[1,2,3,8,4,5,6,9,10,11,12,13,14,75,15,16],"114":[1,2,3,8,4,5,6,9,10,11,12,13,14,75,15,16],"183":[1,2,3,8,4,5,6,9,10,11,12,13,14,75,15,16],"185":[1,2,3,8,4,5,6,9,10,11,12,13,14,75,15,16],"197":[1,2,3,8,4,5,6,9,10,11,12,13,14,75,15,16],"218":[1,2,3,8,4,5,6,9,10,11,12,13,14,75,15,16],"230":[1,2,3,8,4,5,6,9,10,11,12,13,14,75,15,16],"253":[1,2,3,8,4,5,6,9,10,11,12,13,14,75,15,16],"257":[1,2,3,8,4,5,6,9,10,11,12,13,14,75,15,16],"261":[1,2,3,8,4,5,6,9,10,11,12,13,14,75,15,16],"311":[1,2,3,8,4,5,6,9,10,11,12,13,14,75,15,16],"329":[1,2,3,8,4,5,6,9,10,11,12,13,14,75,15,16],"347":[1,2,3,8,4,5,6,9,10,11,12,13,14,75,15,16]},"packages/@n8n/nodes-langchain/utils/output_parsers/N8nItemListOutputParser.ts":{"10":[1,2,8,4,5,6,9,11,13,14,15,16],"26":[1,2,8,4,5,6,9,11,13,14,15,16],"29":[1,2,8,4,5,6,9,11,13,14,15,16],"30":[1,2,8,4,5,6,9,11,13,14,15,16],"42":[1,2,8,4,5,6,9,11,13,14,15,16],"57":[1,2,8,4,5,6,9,11,13,14,15,16]},"packages/@n8n/nodes-langchain/utils/output_parsers/N8nOutputFixingParser.ts":{"15":[1,2,8,4,5,6,9,11,13,14,15,16],"24":[1,2,8,4,5,6,9,11,13,14,15,16],"35":[1,2,8,4,5,6,9,11,13,14,15,16],"42":[1,2,8,4,5,6,9,11,13,14,15,16],"88":[1,2,8,4,5,6,9,11,13,14,15,16],"92":[1,2,8,4,5,6,9,11,13,14,15,16]},"packages/@n8n/nodes-langchain/utils/output_parsers/N8nOutputParser.ts":{"4":[1,2,8,4,5,6,9,11,13,14,15,16],"5":[1,2,8,4,5,6,9,11,13,14,15,16],"15":[1,2,8,4,5,6,9,11,13,14,15,16]},"packages/@n8n/nodes-langchain/utils/output_parsers/N8nStructuredOutputParser.ts":{"22":[1,2,8,4,5,6,9,11,13,14,15,16],"31":[1,2,8,4,5,6,9,11,13,14,15,16],"131":[1,2,8,4,5,6,9,11,13,14,15,16],"148":[1,2,8,4,5,6,9,11,13,14,15,16],"175":[1,2,8,4,5,6,9,11,13,14,15,16]},"packages/@n8n/nodes-langchain/utils/output_parsers/langchainParserError.ts":{"13":[1,2,8,4,5,112,6,9,11,13,14,15,16],"21":[1,2,8,4,5,112,6,9,11,13,14,15,16],"29":[1,2,8,4,5,112,6,9,11,13,14,15,16],"33":[1,2,8,4,5,112,6,9,11,13,14,15,16],"36":[1,2,8,4,5,112,6,9,11,13,14,15,16],"49":[1,2,8,4,5,112,6,9,11,13,14,15,16],"60":[1,2,8,4,5,112,6,9,11,13,14,15,16],"66":[1,2,8,4,5,112,6,9,11,13,14,15,16],"98":[1,2,8,4,5,112,6,9,11,13,14,15,16]},"packages/@n8n/nodes-langchain/utils/tracing.ts":{"19":[1,2,3,8,4,5,6,9,11,13,14,75,15],"83":[1,2,3,8,4,5,6,9,11,13,14,75,15]},"packages/@n8n/permissions/src/index.ts":{"21":"b:/wv4/3cro3vbvwmTHwAAAAAAgAAAAAAA/98GAAA=","22":"b:/wv4/3cro3vbvwmTHwAAAAAAgAAAAAAA/98GAAA=","26":"b:/wv4/3cro3vbvwmTHwAAAAAAgAAAAAAA/98GAAA=","28":"b:/wv4/3cro3vbvwmTHwAAAAAAgAAAAAAA/98GAAA="},"packages/@n8n/permissions/src/roles/all-roles.ts":{"57":"b:/+r/+4P/5/92/v//////////////////AIAIAAA=","61":"b:/+r/+4P/5/92/v//////////////////AIAIAAA=","83":"b:/wr4+wMrontStgneHwAAAAAAgAIAAAAAAIAIAAA="},"packages/@n8n/permissions/src/utilities/combine-scopes.ee.ts":{"16":"b:/+v///f/5////////////////////////88GAAA=","18":"b:/+v///f/5////////////////////////88GAAA=","23":"b:/wv4/3dro3vbvwmTHwAAAAAAgAAAAAAA/88GAAA=","26":"b:/wv4/3dro3vbvwmTHwAAAAAAgAAAAAAA/88GAAA="},"packages/@n8n/permissions/src/utilities/get-global-scopes.ee.ts":{"8":"b:/wv4/1cLgnvZtwmSHwAAAAAAgAAAAAAA/98GAAA=","9":"b:/wv4/1cLgnvZtwmSHwAAAAAAgAAAAAAA/98GAAA="},"packages/@n8n/permissions/src/utilities/get-role-scopes.ee.ts":{"5":"b:/+v///f/5////////////////////////88GAAA=","16":"b:/+v///f/5////////////////////////88GAAA=","19":"b:/wv4/3dro3vbvwmTHwAAAAAAgAAAAAAA/88GAAA=","30":"b:/wv4/3cro3vbvwmTHwAAAAAAgAAAAAAA/88GAAA=","36":"b:/wv4/3cro3vbvwmTHwAAAAAAgAAAAAAA/88GAAA=","38":"b:/wv4/3cro3vbvwmTHwAAAAAAgAAAAAAA/88GAAA="},"packages/@n8n/permissions/src/utilities/has-global-scope.ee.ts":{"10":"b:/wv4/1cronvZtwmTHwAAAAAAgAAAAAAA/88GAAA="},"packages/@n8n/permissions/src/utilities/has-scope.ee.ts":{"11":"b:/+v//9f/5////////////////////////88GAAA=","20":"b:/+v//9f/5/////////j////////8/////88GAAA=","21":"b:/+v//9f/5////////////////////////88GAAA="},"packages/@n8n/tournament/src/ExpressionBuilder.ts":{"25":"b:f/9t/nl+x9FKev8HgmIIUE3eLzCu/3/iAQBYQQE=","29":"b:f/9t/nl+x9FKcv8HgmIIUE3eLzCu/3+CAQBYQQE=","33":"b:f/8FjnlSQMEIOL4EgCIIEEDSAQAiVG/iAQBYQQE=","37":"b:fxUADHlQQAAIID4EgAAIAEACAAACZCACAQBYQQE=","50":"b:f/9t/nl+x9FKev8HgmIIUE3eLzCu/3/iAQBYQQE=","54":"b:fxUADHlQQAAIIDwEgAAIAEASAAACRCACAQBYQQE=","58":"b:fxUADHlQQAAIIDwEgAAIAEACAAACRCACAQBYQQE=","62":"b:f/8FDHlSQMEIOD4EgCIIAEDSAQAiVCPiAQBYQQE=","71":"b:f/9t/nl+x9FKev8HgmIIUE3eLzCu/3/iAQBYQQE=","75":"b:f7UEDHlQQAAIKDwEgAAIAEACAAACRCACAQBYQQE=","88":"b:f/9t/nl+x9FKev8HgmIIUE3eLzCu/3/iAQBYQQE=","103":"b:f/9t/nl+x9FKev8HgmIIUE3eLzCu/3/iAQBYQQE=","110":"b:fxUAjHlQQAAIIDwEgAAIAEAaAQACRCECAQBYQQE=","136":"b:f/9t/nl+x9FKev8HgmIIUE3eLzCu/3/iAQBYQQE=","137":"b:f7UEDHlQQAAIKDwEgAAIAEACAAACRCACAQBYQQE=","141":"b:f7UEDHlQQAAIKDwEgAAIAEACAAACRCACAQBYQQE=","157":"b:f/9t/nl+x9FKev8HgmIIUE3eLzCu/3/iAQBYQQE=","158":"b:f/9t/nl+x9FKev8HgmIIUE3eLzCu/3/iAQBYQQE=","171":"b:f/9t/nl+x9FKev8HgmIIUE3eLzCu/3/iAQBYQQE=","191":"b:f/9t/nl+x9FKev8HgmIIUE3eLzCu/3/iAQBYQQE=","193":"b:f/9t/nl+x9FKev8HgmIIUE3eLzCu/3/iAQBYQQE=","194":"b:f/9t/nl+x9FKev8HgmIIUE3eLzCu/3/iAQBYQQE=","259":"b:fxUAjHlQQAAIIDwEgAAIAEAaAQACRCECAQBYQQE="},"packages/@n8n/tournament/src/ExpressionSplitter.ts":{"19":"b:f+tt/nl+x9FKev8DgmIIUE3eLzCu/3/iAQBIAQA=","23":"b:f+tt/nl+x9FKev8DgmIIUE3eLzCu/3/iAQBIAQA=","27":"b:f+tt/nl+x9FKev8DgmIIUE3eLzCu/3/iAQBIAQA=","101":"b:fwEADHkAQAAIIDwAAAAIAAAAAAAABCAAAQBIAQA=","105":"b:fwEADHkAQAAIIDwAAAAIAAAAAAAABCAAAQBIAQA=","107":"b:fwEADHkAQAAIIDwAAAAIAAAAAAAABCAAAQBIAQA="},"packages/@n8n/tournament/src/Parser.ts":{"5":"b:f+tt/nl+x9FKev8DgmIIUE3eLzCu/3/iAQBIAQA="},"packages/@n8n/tournament/src/VariablePolyfill.ts":{"12":"b:fwEABHlAQAAIIDwAAAAIAAAAAAAARCACAQBIQQE=","21":"b:f+tt/nl+x9FKev8DgmIIUE3eLzCu/3/iAQBIQQE=","41":"b:f+tt/nl+x9FKev8DgmIIUE3eLzCu/3/iAQBIQQE=","70":"b:f+sFBHlSQEEIOD4AACIIAECQAAAgVCPiAQBIQQE=","80":"b:f+sFBHlSQEEIOD4AACIIAECQAAAgVCPiAQBIQQE=","107":"b:f+sFBHlSQEEIOD4AACIIAECQAAAgVCPiAQBIQQE=","119":"b:f+tt/nl+x9FKev8DgmIIUE3eLzCu/3/iAQBIQQE=","144":"b:f+tt/nl+x9FKev8DgmIIUE3eLzCu/3/iAQBIQQE=","171":"b:f+tt/nl+x9FKev8DgmIIUE3eLzCu/3/iAQBIQQE=","176":"b:fwEABHlAQAAIIDwAAAAIAAAAAAAARCACAQBIQQE=","181":"b:f+sFBHlSQMEIOD4AACIIAEDQAQAidCPiAQBIQQE=","204":"b:fwEABHlAQAAIIDwAAAAIAAAAAAAARCACAQBIQQE=","209":"b:f+sFBHlSQEEIOD4AACIIAECQAAAgVCPiAQBIQQE=","214":"b:f+sFBHlSQEEIODwAACIIAECQAAAgVCPiAQBIQQE=","223":"b:f+sABHlAQAAIMDwAAAAIAACAAAAARCACAQBIQQE=","228":"b:fwEABHlAQAAIIDwAAAAIAAAAAAAARCACAQBIQQE=","233":"b:fwEABHlAQAAIIDwAAAAIAAAAAAAARCACAQBIQQE=","238":"b:fwEABHlAQAAIIDwAAAAIAAAAAAAARCACAQBIQQE=","243":"b:fwEABHlAQAAIIDwAAAAIAAAAAAAARCACAQBIQQE=","248":"b:fwEABHlAQAAIIDwAAAAIAAAAAAAARCACAQBIQQE=","255":"b:f+tt/nl+x9FKev8DgmIIUE3eLzCu/3/iAQBIQQE=","260":"b:fwEABHlAQAAIIDwAAAAIAAAAAAAARCACAQBIQQE=","263":"b:f+tt/nl+x9FKev8DgmIIUE3eLzCu/3/iAQBIQQE="},"packages/@n8n/tournament/src/index.ts":{"20":"b:f+v///v/5/9++v/v////////////////AQBIAQA=","21":"b:fwEADHlAQAAIIDwAAAAIAAAAAAAABCAAAQBIAQA=","29":"b:f+v///v/5/9++v/v////////////////AQBIAQA=","33":"b:f+tt/nl+x9FKev8DgmIIUE3eLzCu/3/iAQBIAQA=","37":"b:f+tt/nl+x9FKev8DgmIIUE3eLzCu/3/iAQBIAQA="},"packages/@n8n/utils/src/errors/ensure-error.ts":{"2":"b:AhEBByBCAECIAwAWGAMCAEAAgAAAAASAE4DAAQA="},"packages/@n8n/utils/src/lru-cache.ts":{"4":"b:f+v///v/5/9++v/v////////////////AQBIAQA=","13":"b:fwEADHlAQAAIIDwAAAAIAAAAAAAARCAAAQBIAQA=","21":"b:fwEADHlAQAAIIDwAAAAIAAAAAAAARCAAAQBIAQA=","31":"b:fwEADHlAQAAIIDwAAAAIAAAAAAAARCAAAQBIAQA=","35":"b:fwEADHlAQAAIIDwAAAAIAAAAAAAARCAAAQBIAQA="},"packages/@n8n/utils/src/promise/deferred-promise.ts":{"10":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","12":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA="},"packages/cli/src/abstract-server.ts":{"83":"b:SoLoAACgQ11AtDJhAIAEABAAABBAABAAAAAIAAA=","116":"b:SoLoAACgQ11AtDJhAIAEABAAABBAABAAAAAIAAA=","120":"b:SoLoAACgQ11AtDJhAIAEABAAABBAABAAAAAIAAA=","128":"b:SoLoAACgQ11AtDJhAIAEABAAABBAABAAAAAIAAA=","136":"b:SoLoAACgQ11AtDJhAIAEABAAABBAABAAAAAIAAA=","140":"b:SoLoAACgQ11AtDJhAIAEABAAABBAABAAAAAIAAA=","143":"b:SoLoAACgQ11AtDJhAIAEABAAABBAABAAAAAIAAA=","147":"b:SoLoAACgQ11AtDJhAIAEABAAABBAABAAAAAIAAA=","154":"b:SoLoAACgQ11AtDJhAIAEABAAABBAABAAAAAIAAA=","160":"b:SoLoAACgQ11AtDJhAIAEABAAABBAABAAAAAIAAA=","169":"b:SoLoAACgQ11AtDJhAIAEABAAABBAABAAAAAIAAA=","181":"b:SoLoAACgQ11AtDJhAIAEABAAABBAABAAAAAIAAA=","189":"b:SoLoAACgQ11AtDJhAIAEABAAABBAABAAAAAIAAA=","209":"b:SoLoAACgQ11AtDJhAIAEABAAABBAABAAAAAIAAA=","239":"b:SoLoAACgQ11AtDJhAIAEABAAABBAABAAAAAIAAA=","248":"b:SoLoAACgQ11AtDJhAIAEABAAABBAABAAAAAIAAA=","321":"b:SoLoAACgQ11AtDJhAIAEABAAABBAABAAAAAIAAA=","325":"b:SoLoAACgQ11AtDJhAIAEABAAABBAABAAAAAIAAA=","364":"b:SoLoAACgQ11AtDJhAIAEABAAABBAABAAAAAIAAA=","373":"b:SoLoAACgQ11AtDJhAIAEABAAABBAABAAAAAIAAA="},"packages/cli/src/active-executions.ts":{"56":"b:fwBMXnUg4WGJsz4EgAAAAEAAAAAABAIA+wfYoQE=","66":"b:fwBMXnUg4WGJsz4EgAAAAEAAAAAABAIA+wfYoQE=","73":"b:fwBMXnUg4WGJsz4EgAAAAEAAAAAABAIA+wfYoQE=","176":"b:fwBMXnUg4WGJsz4EgAAAAEAAAAAABAIA+wfYoQE=","180":"b:fwBMXnUg4WGJsz4EgAAAAEAAAAAABAIA+wfYoQE=","201":"b:fwBMXnUg4WGJsz4EgAAAAEAAAAAABAIA+wfYoQE=","211":"b:fwBMXnUg4WGJsz4EgAAAAEAAAAAABAIA+wfYoQE=","218":"b:fwBMXnUg4WGJsz4EgAAAAEAAAAAABAIA+wfYoQE=","224":"b:fwBMXnUg4WGJsz4EgAAAAEAAAAAABAIA+wfYoQE=","233":"b:fwBMXnUg4WGJsz4EgAAAAEAAAAAABAIA+wfYoQE=","263":"b:fwBMXnUg4WGJsz4EgAAAAEAAAAAABAIA+wfYoQE=","285":"b:fwBMXnUg4WGJsz4EgAAAAEAAAAAABAIA+wfYoQE=","303":"b:fwBMXnUg4WGJsz4EgAAAAEAAAAAABAIA+wfYoQE=","310":"b:fwBMXnUg4WGJsz4EgAAAAEAAAAAABAIA+wfYoQE=","330":"b:fwBMXnUg4WGJsz4EgAAAAEAAAAAABAIA+wfYoQE=","333":"b:fwBMXnUg4WGJsz4EgAAAAEAAAAAABAIA+wfYoQE=","340":"b:fwBMXnUg4WGJsz4EgAAAAEAAAAAABAIA+wfYoQE=","351":"b:fwBMXnUg4WGJsz4EgAAAAEAAAAAABAIA+wfYoQE=","357":"b:fwBMXnUg4WGJsz4EgAAAAEAAAAAABAIA+wfYoQE=","374":"b:fwBMXnUg4WGJsz4EgAAAAEAAAAAABAIA+wfYoQE=","380":"b:fwBMXnUg4WGJsz4EgAAAAEAAAAAABAIA+wfYoQE=","382":"b:fwBMXnUg4WGJsz4EgAAAAEAAAAAABAIA+wfYoQE=","397":"b:fwBMXnUg4WGJsz4EgAAAAEAAAAAABAIA+wfYoQE=","401":"b:fwBMXnUg4WGJsz4EgAAAAEAAAAAABAIA+wfYoQE=","405":"b:fwBMXnUg4WGJsz4EgAAAAEAAAAAABAIA+wfYoQE=","409":"b:fwBMXnUg4WGJsz4EgAAAAEAAAAAABAIA+wfYoQE=","414":"b:fwBMXnUg4WGJsz4EgAAAAEAAAAAABAIA+wfYoQE=","455":"b:fwBMXnUg4WGJsz4EgAAAAEAAAAAABAIA+wfYoQE="},"packages/cli/src/auth/auth-handler.registry.ts":{"7":"b:/wv4/1cLgnvZtwmSHwAAAAAAgAAAAAAA/98GAAA=","20":"b:/wv4/1cLgnvZtwmSHwAAAAAAgAAAAAAA/98GAAA=","30":"b:/wv4/1cLgnvZtwmSHwAAAAAAgAAAAAAA/98GAAA=","82":"b:/wv4/1cLgnvZtwmSHwAAAAAAgAAAAAAA/98GAAA=","94":"b:/wv4/1cLgnvZtwmSHwAAAAAAgAAAAAAA/98GAAA=","112":"b:/wv4/1cLgnvZtwmSHwAAAAAAgAAAAAAA/98GAAA="},"packages/cli/src/auth/auth.service.ts":{"47":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA=","99":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA=","149":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA=","154":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA=","216":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA=","217":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA=","245":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA=","249":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA=","258":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA=","266":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA=","270":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA=","274":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA=","283":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA=","299":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA=","325":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA=","346":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA=","353":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA=","379":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA=","389":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA=","405":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA=","406":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA=","411":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA=","428":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA=","461":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA=","491":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA=","503":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA=","521":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA=","526":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA=","536":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA=","570":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA=","578":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA=","583":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA=","593":"b:/wv4/1crrnvZvynfHwAIICAAgAAgBAAA/98OAgA="},"packages/cli/src/auth/handlers/email.auth-handler.ts":{"16":"b:/wv4/1cLgnvZtwmSHwAAAAAAgAAAAAAA/98GAAA=","23":"b:/wv4/1cLgnvZtwmSHwAAAAAAgAAAAAAA/98GAAA=","35":"b:/wv4/1cLgnvZtwmSHwAAAAAAgAAAAAAA/98GAAA="},"packages/cli/src/chat/chat-server.ts":{"21":"b:/wr4+wMqolNAvgnHAyAAAAAAgAAAAAAAAAAAAAA=","23":"b:/wr4+wMqolNAvgnHAyAAAAAAgAAAAAAAAAAAAAA=","24":"b:/wr4+wMqolNAvgnHAyAAAAAAgAAAAAAAAAAAAAA=","29":"b:/wr4+wMqolNAvgnHAyAAAAAAgAAAAAAAAAAAAAA=","35":"b:/wr4+wMqolNAvgnHAyAAAAAAgAAAAAAAAAAAAAA=","40":"b:/wr4+wMqolNAvgnHAyAAAAAAgAAAAAAAAAAAAAA=","43":"b:/wr4+wMqolNAvgnHAyAAAAAAgAAAAAAAAAAAAAA=","52":"b:/wr4+wMqolNAvgnHAyAAAAAAgAAAAAAAAAAAAAA="},"packages/cli/src/chat/chat-service.ts":{"44":"b:3gLo3hArAltasgiDvAQgAAAAgAAAAAAAAIIMAAA=","47":"b:3gLo3hArAltasgiDvAQgAAAAgAAAAAAAAIIMAAA=","51":"b:3gLo3hArAltasgiDvAQgAAAAgAAAAAAAAIIMAAA=","63":"b:3gLo3hArAltasgiDvAQgAAAAgAAAAAAAAIIMAAA=","69":"b:3gLo3hArAltasgiDvAQgAAAAgAAAAAAAAIIMAAA=","74":"b:3gLo3hArAltasgiDvAQgAAAAgAAAAAAAAIIMAAA=","121":"b:3gLo3hArAltasgiDvAQgAAAAgAAAAAAAAIIMAAA=","123":"b:3gLo3hArAltasgiDvAQgAAAAgAAAAAAAAIIMAAA=","146":"b:3gLo3hArAltasgiDvAQgAAAAgAAAAAAAAIIMAAA=","176":"b:3gLo3hArAltasgiDvAQgAAAAgAAAAAAAAIIMAAA=","181":"b:3gLo3hArAltasgiDvAQgAAAAgAAAAAAAAIIMAAA=","190":"b:3gLo3hArAltasgiDvAQgAAAAgAAAAAAAAIIMAAA=","191":"b:3gLo3hArAltasgiDvAQgAAAAgAAAAAAAAIIMAAA=","237":"b:3gLo3hArAltasgiDvAQgAAAAgAAAAAAAAIIMAAA=","238":"b:3gLo3hArAltasgiDvAQgAAAAgAAAAAAAAIIMAAA=","268":"b:3gLo3hArAltasgiDvAQgAAAAgAAAAAAAAIIMAAA=","294":"b:3gLo3hArAltasgiDvAQgAAAAgAAAAAAAAIIMAAA=","320":"b:3gLo3hArAltasgiDvAQgAAAAgAAAAAAAAIIMAAA=","322":"b:3gLo3hArAltasgiDvAQgAAAAgAAAAAAAAIIMAAA=","329":"b:3gLo3hArAltasgiDvAQgAAAAgAAAAAAAAIIMAAA=","335":"b:3gLo3hArAltasgiDvAQgAAAAgAAAAAAAAIIMAAA=","340":"b:3gLo3hArAltasgiDvAQgAAAAgAAAAAAAAIIMAAA=","350":"b:3gLo3hArAltasgiDvAQgAAAAgAAAAAAAAIIMAAA=","357":"b:3gLo3hArAltasgiDvAQgAAAAgAAAAAAAAIIMAAA=","386":"b:3gLo3hArAltasgiDvAQgAAAAgAAAAAAAAIIMAAA="},"packages/cli/src/collaboration/collaboration.message.ts":{"133":"b:Dwrs+QMuo1FAvilHAAAAABAAAAAAAAAAAAAAAAA="},"packages/cli/src/collaboration/collaboration.service.ts":{"40":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","50":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","51":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","76":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","85":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","111":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","127":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","149":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","153":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","159":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","161":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","171":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","197":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","212":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","223":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","229":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","245":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","247":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","260":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","262":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","276":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","283":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","314":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","320":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","340":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","342":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","360":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","374":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","388":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","431":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","444":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","448":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","452":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","464":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","482":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","484":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","490":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","492":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","502":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","528":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","543":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","554":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","560":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","574":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","576":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","597":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","614":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","628":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","660":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA=","676":"b:Dxvu/WM+o3PJ/21HAAAAANAFAQBgGUBL+wfBAQA="},"packages/cli/src/collaboration/collaboration.state.ts":{"40":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","57":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","62":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","67":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","78":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","90":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","96":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","124":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","128":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","143":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","150":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","155":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","187":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","198":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","209":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","215":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","223":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","225":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","235":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","249":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","254":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","264":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","266":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","274":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","285":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","291":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","304":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","316":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","322":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","350":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","354":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","358":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","363":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","373":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","379":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","387":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","389":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","398":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","407":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","412":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","414":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","422":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","430":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","432":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","440":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","451":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA=","457":"b:Dwvu/WMuo3PJ/21HAAAAAFAFAQBgGUBB+weAAAA="},"packages/cli/src/concurrency/concurrency-capacity-reservation.ts":{"21":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","23":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","30":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA="},"packages/cli/src/concurrency/concurrency-control.service.ts":{"35":"b:fwBMXnUg4WGJsz4AAAAAAAAAAAAABAAA+wfQIAA=","45":"b:fwBMXnUg4WGJsz4AAAAAAAAAAAAABAAA+wfQIAA=","90":"b:fwBMXnUg4WGJsz4AAAAAAAAAAAAABAAA+wfQIAA=","100":"b:fwBMXnUg4WGJsz4AAAAAAAAAAAAABAAA+wfQIAA=","113":"b:fwBMXnUg4WGJsz4AAAAAAAAAAAAABAAA+wfQIAA=","135":"b:fwBMXnUg4WGJsz4AAAAAAAAAAAAABAAA+wfQIAA=","136":"b:fwBMXnUg4WGJsz4AAAAAAAAAAAAABAAA+wfQIAA=","145":"b:fwBMXnUg4WGJsz4AAAAAAAAAAAAABAAA+wfQIAA=","150":"b:fwBMXnUg4WGJsz4AAAAAAAAAAAAABAAA+wfQIAA=","158":"b:fwBMXnUg4WGJsz4AAAAAAAAAAAAABAAA+wfQIAA=","173":"b:fwBMXnUg4WGJsz4AAAAAAAAAAAAABAAA+wfQIAA=","183":"b:fwBMXnUg4WGJsz4AAAAAAAAAAAAABAAA+wfQIAA=","193":"b:fwBMXnUg4WGJsz4AAAAAAAAAAAAABAAA+wfQIAA=","205":"b:fwBMXnUg4WGJsz4AAAAAAAAAAAAABAAA+wfQIAA=","208":"b:fwBMXnUg4WGJsz4AAAAAAAAAAAAABAAA+wfQIAA=","225":"b:fwBMXnUg4WGJsz4AAAAAAAAAAAAABAAA+wfQIAA=","233":"b:fwBMXnUg4WGJsz4AAAAAAAAAAAAABAAA+wfQIAA=","237":"b:fwBMXnUg4WGJsz4AAAAAAAAAAAAABAAA+wfQIAA=","244":"b:fwBMXnUg4WGJsz4AAAAAAAAAAAAABAAA+wfQIAA="},"packages/cli/src/controller.registry.ts":{"36":"b:/wv4/9d7on//twmDXwAIAAAAgAAAAAAA/88nAgA=","45":"b:/wv4/9d7on//twmDXwAIAAAAgAAAAAAA/88nAgA=","53":"b:/wv4/9d7on//twmDXwAIAAAAgAAAAAAA/88nAgA=","65":"b:/wv4/9d7on//twmDXwAIAAAAgAAAAAAA/88nAgA=","88":"b:/wv4/9d7on//twmDXwAIAAAAgAAAAAAA/88nAgA=","107":"b:/wv4/9d7on//twmDXwAIAAAAgAAAAAAA/88nAgA=","133":"b:/wv4/9d7on//twmDXwAIAAAAgAAAAAAA/88nAgA=","138":"b:/wv4/9d7on//twmDXwAIAAAAgAAAAAAA/88nAgA=","172":"b:/wv4/9d7on//twmDXwAIAAAAgAAAAAAA/88nAgA=","252":"b:/wv4/9d7on//twmDXwAIAAAAgAAAAAAA/88nAgA=","253":"b:/wv4/9d7on//twmDXwAIAAAAgAAAAAAA/88nAgA=","262":"b:/wv4/9d7on//twmDXwAIAAAAgAAAAAAA/88nAgA=","263":"b:/wv4/9d7on//twmDXwAIAAAAgAAAAAAA/88nAgA="},"packages/cli/src/controllers/active-workflows.controller.ts":{"8":"b:jwps+AMro3tAvgnPHgAAAAAAAAAAAAAAAAAAAAA=","11":"b:jwps+AMro3tAvgnPHgAAAAAAAAAAAAAAAAAAAAA=","16":"b:jwps+AMro3tAvgnPHgAAAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/controllers/auth.controller.ts":{"41":"b:/wv4/1cronvbtwnfHwAAAAAAgAIAAAAA/98OAAA=","68":"b:/wv4/1cronvbtwnfHwAAAAAAgAIAAAAA/98OAAA=","110":"b:/wv4/1cronvbtwnfHwAAAAAAgAIAAAAA/98OAAA=","116":"b:/wv4/1cronvbtwnfHwAAAAAAgAIAAAAA/98OAAA=","132":"b:/wv4/1cronvbtwnfHwAAAAAAgAIAAAAA/98OAAA=","165":"b:/wv4/1cronvbtwnfHwAAAAAAgAIAAAAA/98OAAA=","193":"b:/wv4/1cronvbtwnfHwAAAAAAgAIAAAAA/98OAAA=","206":"b:/wv4/1cronvbtwnfHwAAAAAAgAIAAAAA/98OAAA=","252":"b:/wv4/1cronvbtwnfHwAAAAAAgAIAAAAA/98OAAA=","261":"b:/wv4/1cronvbtwnfHwAAAAAAgAIAAAAA/98OAAA=","280":"b:/wv4/1cronvbtwnfHwAAAAAAgAIAAAAA/98OAAA="},"packages/cli/src/controllers/dynamic-node-parameters.controller.ts":{"18":[1,41,60,72,73,176,16,178,179,182,87],"34":[1,41,60,72,73,176,16,178,179,182,87],"57":[1,41,60,72,73,176,16,178,179,182,87],"107":[1,41,60,72,73,176,16,178,179,182,87],"146":[1,41,60,72,73,176,16,178,179,182,87],"175":[1,41,60,72,73,176,16,178,179,182,87],"201":[1,41,60,72,73,176,16,178,179,182,87]},"packages/cli/src/controllers/e2e.controller.ts":{"196":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","215":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","218":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","229":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","233":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","244":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","250":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","256":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","262":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","273":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","286":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","302":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","309":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","323":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","335":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","340":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","379":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","388":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","397":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","418":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","431":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","435":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","436":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","439":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","450":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","457":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","468":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","478":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","489":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","499":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","579":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","585":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","586":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","594":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","605":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","610":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","619":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","640":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","647":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY=","716":"b:/wv4/1cronvbtwnfHwAAAAAAgAoAAAAA/98eCAY="},"packages/cli/src/controllers/me.controller.ts":{"31":[1,2,11,144,14,154,100,75,18,15,16],"47":[1,2,11,144,14,154,100,75,18,15,16],"97":[1,2,11,144,14,154,100,75,18,15,16],"109":[1,2,11,144,14,154,100,75,18,15,16],"118":[1,2,11,144,14,154,100,75,18,15,16],"128":[1,2,11,144,14,154,100,75,18,15,16],"166":[1,2,11,144,14,154,100,75,18,15,16],"199":[1,2,11,144,14,154,100,75,18,15,16],"244":[1,2,11,144,14,154,100,75,18,15,16]},"packages/cli/src/controllers/module-settings.controller.ts":{"7":"b:/wr4+wMrontStgnPHwAAAAAAgAIAAAAAAIAIAAA=","13":"b:/wr4+wMrontStgnPHwAAAAAAgAIAAAAAAIAIAAA="},"packages/cli/src/controllers/project.controller.ts":{"37":"b:/wr6/4P7qn/yt8nPHwAGAAABgHIAAABABIAoAAA=","43":"b:/wr6/4P7qn/yt8nPHwAGAAABgHIAAABABIAoAAA=","64":"b:/wr6/4P7qn/yt8nPHwAGAAABgHIAAABABIAoAAA=","75":"b:/wr6/4P7qn/yt8nPHwAGAAABgHIAAABABIAoAAA=","92":"b:/wr6/4P7qn/yt8nPHwAGAAABgHIAAABABIAoAAA=","110":"b:/wr6/4P7qn/yt8nPHwAGAAABgHIAAABABIAoAAA=","118":"b:/wr6/4P7qn/yt8nPHwAGAAABgHIAAABABIAoAAA=","135":"b:/wr6/4P7qn/yt8nPHwAGAAABgHIAAABABIAoAAA=","147":"b:/wr6/4P7qn/yt8nPHwAGAAABgHIAAABABIAoAAA=","157":"b:/wr6/4P7qn/yt8nPHwAGAAABgHIAAABABIAoAAA=","164":"b:/wr6/4P7qn/yt8nPHwAGAAABgHIAAABABIAoAAA=","174":"b:/wr6/4P7qn/yt8nPHwAGAAABgHIAAABABIAoAAA=","183":"b:/wr6/4P7qn/yt8nPHwAGAAABgHIAAABABIAoAAA=","193":"b:/wr6/4P7qn/yt8nPHwAGAAABgHIAAABABIAoAAA=","203":"b:/wr6/4P7qn/yt8nPHwAGAAABgHIAAABABIAoAAA=","235":"b:/wr6/4P7qn/yt8nPHwAGAAABgHIAAABABIAoAAA=","257":"b:/wr6/4P7qn/yt8nPHwAGAAABgHIAAABABIAoAAA=","270":"b:/wr6/4P7qn/yt8nPHwAGAAABgHIAAABABIAoAAA="},"packages/cli/src/controllers/role.controller.ts":{"39":"b:/wr4+wMrontStgnPHwAAAAAAgAIAAAAAAIAIAAA=","46":"b:/wr4+wMrontStgnPHwAAAAAAgAIAAAAAAIAIAAA=","53":"b:/wr4+wMrontStgnPHwAAAAAAgAIAAAAAAIAIAAA=","54":"b:/wr4+wMrontStgnPHwAAAAAAgAIAAAAAAIAIAAA=","55":"b:/wr4+wMrontStgnPHwAAAAAAgAIAAAAAAIAIAAA=","56":"b:/wr4+wMrontStgnPHwAAAAAAgAIAAAAAAIAIAAA=","61":"b:/wr4+wMrontStgnPHwAAAAAAgAIAAAAAAIAIAAA=","88":"b:/wr4+wMrontStgnPHwAAAAAAgAIAAAAAAIAIAAA=","112":"b:/wr4+wMrontStgnPHwAAAAAAgAIAAAAAAIAIAAA=","118":"b:/wr4+wMrontStgnPHwAAAAAAgAIAAAAAAIAIAAA=","124":"b:/wr4+wMrontStgnPHwAAAAAAgAIAAAAAAIAIAAA=","134":"b:/wr4+wMrontStgnPHwAAAAAAgAIAAAAAAIAIAAA=","145":"b:/wr4+wMrontStgnPHwAAAAAAgAIAAAAAAIAIAAA=","165":"b:/wr4+wMrontStgnPHwAAAAAAgAIAAAAAAIAIAAA=","188":"b:/wr4+wMrontStgnPHwAAAAAAgAIAAAAAAIAIAAA="},"packages/cli/src/controllers/users.controller.ts":{"41":"b:jwr++wMrontivgnPHwAAAAAAAAAAAAAAAAAAAAA=","49":"b:jwr++wMrontivgnPHwAAAAAAAAAAAAAAAAAAAAA=","73":"b:jwr++wMrontivgnPHwAAAAAAAAAAAAAAAAAAAAA=","82":"b:jwr++wMrontivgnPHwAAAAAAAAAAAAAAAAAAAAA=","95":"b:jwr++wMrontivgnPHwAAAAAAAAAAAAAAAAAAAAA=","102":"b:jwr++wMrontivgnPHwAAAAAAAAAAAAAAAAAAAAA=","120":"b:jwr++wMrontivgnPHwAAAAAAAAAAAAAAAAAAAAA=","142":"b:jwr++wMrontivgnPHwAAAAAAAAAAAAAAAAAAAAA=","171":"b:jwr++wMrontivgnPHwAAAAAAAAAAAAAAAAAAAAA=","192":"b:jwr++wMrontivgnPHwAAAAAAAAAAAAAAAAAAAAA=","199":"b:jwr++wMrontivgnPHwAAAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/credential-types.ts":{"8":"b:dgMBhABuohnCAwACAQAAAAAAAAAAAAWABAAgAAA=","10":"b:dgMBhABuohnCAwACAQAAAAAAAAAAAAWABAAgAAA=","15":"b:dgMBhABuohnCAwACAQAAAAAAAAAAAAWABAAgAAA=","19":"b:dgMBhABuohnCAwACAQAAAAAAAAAAAAWABAAgAAA=","23":"b:dgMBhABuohnCAwACAQAAAAAAAAAAAAWABAAgAAA=","30":"b:dgMBhABuohnCAwACAQAAAAAAAAAAAAWABAAgAAA="},"packages/cli/src/credentials/credential-dependency.service.ts":{"13":"b:dgMBhABsoBnCAwACAAACAAAAAEAAAAQABAAgAAA=","22":"b:dgMBhABsoBnCAwACAAACAAAAAEAAAAQABAAgAAA=","27":"b:dgMBhABsoBnCAwACAAACAAAAAEAAAAQABAAgAAA=","42":"b:dgMBhABsoBnCAwACAAACAAAAAEAAAAQABAAgAAA=","49":"b:dgMBhABsoBnCAwACAAACAAAAAEAAAAQABAAgAAA=","67":"b:dgMBhABsoBnCAwACAAACAAAAAEAAAAQABAAgAAA=","85":"b:dgMBhABsoBnCAwACAAACAAAAAEAAAAQABAAgAAA=","101":"b:dgMBhABsoBnCAwACAAACAAAAAEAAAAQABAAgAAA="},"packages/cli/src/credentials/credential-descriptions.service.ts":{"8":"b:/wvo/QMro3vStwnPHwAAAAAAAAIAAAAABAAAAAA=","10":"b:/wvo/QMro3vStwnPHwAAAAAAAAIAAAAABAAAAAA=","17":"b:/wvo/QMro3vStwnPHwAAAAAAAAIAAAAABAAAAAA="},"packages/cli/src/credentials/credentials.controller.ts":{"55":"b:/wvr/YPvo3/Wv0nPHrgGAkKBAFIAAAQABAAgAAA=","73":"b:/wvr/YPvo3/Wv0nPHrgGAkKBAFIAAAQABAAgAAA=","89":"b:/wvr/YPvo3/Wv0nPHrgGAkKBAFIAAAQABAAgAAA=","104":"b:/wvr/YPvo3/Wv0nPHrgGAkKBAFIAAAQABAAgAAA=","114":"b:/wvr/YPvo3/Wv0nPHrgGAkKBAFIAAAQABAAgAAA=","122":"b:/wvr/YPvo3/Wv0nPHrgGAkKBAFIAAAQABAAgAAA=","136":"b:/wvr/YPvo3/Wv0nPHrgGAkKBAFIAAAQABAAgAAA=","166":"b:/wvr/YPvo3/Wv0nPHrgGAkKBAFIAAAQABAAgAAA=","193":"b:/wvr/YPvo3/Wv0nPHrgGAkKBAFIAAAQABAAgAAA=","218":"b:/wvr/YPvo3/Wv0nPHrgGAkKBAFIAAAQABAAgAAA=","266":"b:/wvr/YPvo3/Wv0nPHrgGAkKBAFIAAAQABAAgAAA=","447":"b:/wvr/YPvo3/Wv0nPHrgGAkKBAFIAAAQABAAgAAA=","481":"b:/wvr/YPvo3/Wv0nPHrgGAkKBAFIAAAQABAAgAAA=","510":"b:/wvr/YPvo3/Wv0nPHrgGAkKBAFIAAAQABAAgAAA=","516":"b:/wvr/YPvo3/Wv0nPHrgGAkKBAFIAAAQABAAgAAA=","535":"b:/wvr/YPvo3/Wv0nPHrgGAkKBAFIAAAQABAAgAAA=","536":"b:/wvr/YPvo3/Wv0nPHrgGAkKBAFIAAAQABAAgAAA=","539":"b:/wvr/YPvo3/Wv0nPHrgGAkKBAFIAAAQABAAgAAA=","540":"b:/wvr/YPvo3/Wv0nPHrgGAkKBAFIAAAQABAAgAAA=","564":"b:/wvr/YPvo3/Wv0nPHrgGAkKBAFIAAAQABAAgAAA=","604":"b:/wvr/YPvo3/Wv0nPHrgGAkKBAFIAAAQABAAgAAA=","611":"b:/wvr/YPvo3/Wv0nPHrgGAkKBAFIAAAQABAAgAAA="},"packages/cli/src/credentials/credentials.service.ts":{"120":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","125":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","240":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","245":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","249":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","255":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","283":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","295":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","299":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","304":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","322":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","335":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","395":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","437":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","508":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","531":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","568":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","582":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","584":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","585":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","589":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","592":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","597":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","600":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","604":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","632":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","647":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","648":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","658":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","664":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","672":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","678":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","679":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","684":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","711":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","722":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","723":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","732":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","739":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","746":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","760":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","777":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","807":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","825":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","856":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","926":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","938":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","950":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","979":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","986":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1013":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1037":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1050":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1066":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1087":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1101":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1136":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1163":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1177":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1249":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1266":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1300":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1340":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1361":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1368":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1395":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1407":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1417":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1482":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1497":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1519":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1529":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1545":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1578":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1626":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1640":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1654":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1669":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1713":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1728":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1729":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1732":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1744":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1747":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1760":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1769":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1794":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1806":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1823":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1848":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1938":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1940":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1959":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1968":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1976":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1977":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1988":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1989":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","1994":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","2001":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","2009":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","2030":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","2038":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","2055":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","2095":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","2105":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","2137":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","2151":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","2179":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","2188":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","2202":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","2213":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","2299":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","2312":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","2377":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","2409":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","2418":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA=","2448":"b:/wvv/YP/o3/2v03PHzgGEkgDAFIgEAQABAAgAAA="},"packages/cli/src/credentials/dynamic-credentials-proxy.ts":{"30":"b:chAAAAAgoAAAAAAAAAAIAEAAAAAAAAQABACAAgA=","32":"b:chAAAAAgoAAAAAAAAAAIAEAAAAAAAAQABACAAgA=","36":"b:chAAAAAgoAAAAAAAAAAIAEAAAAAAAAQABACAAgA=","46":"b:chAAAAAgoAAAAAAAAAAIAEAAAAAAAAQABACAAgA=","58":"b:chAAAAAgoAAAAAAAAAAIAEAAAAAAAAQABACAAgA=","64":"b:chAAAAAgoAAAAAAAAAAIAEAAAAAAAAQABACAAgA=","89":"b:chAAAAAgoAAAAAAAAAAIAEAAAAAAAAQABACAAgA=","119":"b:chAAAAAgoAAAAAAAAAAIAEAAAAAAAAQABACAAgA="},"packages/cli/src/credentials/external-secrets.utils.ts":{"14":"b:dgMBhABsoBnCAwACAQAAAAAAAAAAAAQABAAgAAA=","23":"b:dgMBhABsoBnCAwACAQAAAAAAAAAAAAQABAAgAAA=","32":"b:dgMBhABsoBnCAwACAQAAAAAAAAAAAAQABAAgAAA=","70":"b:dgMBhABsoBnCAwACAQAAAAAAAAAAAAQABAAgAAA="},"packages/cli/src/credentials/mock-node-types.ts":{"18":[26,1,4,5,6,46,194,54,55,56,178,89],"29":[26,1,4,5,6,46,194,54,55,56,178,89],"32":[26,1,4,5,6,46,194,54,55,56,178,89],"35":[26,1,4,5,6,46,194,54,55,56,178,89]},"packages/cli/src/credentials/validation.ts":{"20":"b:dgMBhABsoBnCAwACAAACAAAAAEAAAAQABAAgAAA=","27":"b:dgMBhABsoBnCAwACAAACAAAAAEAAAAQABAAgAAA=","55":"b:dgMBhABsoBnCAwACAAACAAAAAEAAAAQABAAgAAA=","91":"b:dgMBhABsoBnCAwACAAACAAAAAEAAAAQABAAgAAA=","134":"b:dgMBhABsoBnCAwACAAACAAAAAEAAAAQABAAgAAA=","152":"b:dgMBhABsoBnCAwACAAACAAAAAEAAAAQABAAgAAA=","153":"b:dgMBhABsoBnCAwACAAACAAAAAEAAAAQABAAgAAA=","165":"b:dgMBhABsoBnCAwACAAACAAAAAEAAAAQABAAgAAA=","182":"b:dgMBhABsoBnCAwACAAACAAAAAEAAAAQABAAgAAA="},"packages/cli/src/credentials-helper.ts":{"67":"b:dhMBhABu4BnGA0ACAQACAEAAABAAAAWABACgAAA=","73":"b:dhMBhABu4BnGA0ACAQACAEAAABAAAAWABACgAAA=","106":"b:dhMBhABu4BnGA0ACAQACAEAAABAAAAWABACgAAA=","122":"b:dhMBhABu4BnGA0ACAQACAEAAABAAAAWABACgAAA=","139":"b:dhMBhABu4BnGA0ACAQACAEAAABAAAAWABACgAAA=","175":"b:dhMBhABu4BnGA0ACAQACAEAAABAAAAWABACgAAA=","176":"b:dhMBhABu4BnGA0ACAQACAEAAABAAAAWABACgAAA=","202":"b:dhMBhABu4BnGA0ACAQACAEAAABAAAAWABACgAAA=","212":"b:dhMBhABu4BnGA0ACAQACAEAAABAAAAWABACgAAA=","276":"b:dhMBhABu4BnGA0ACAQACAEAAABAAAAWABACgAAA=","295":"b:dhMBhABu4BnGA0ACAQACAEAAABAAAAWABACgAAA=","324":"b:dhMBhABu4BnGA0ACAQACAEAAABAAAAWABACgAAA=","331":"b:dhMBhABu4BnGA0ACAQACAEAAABAAAAWABACgAAA=","347":"b:dhMBhABu4BnGA0ACAQACAEAAABAAAAWABACgAAA=","378":"b:dhMBhABu4BnGA0ACAQACAEAAABAAAAWABACgAAA=","397":"b:dhMBhABu4BnGA0ACAQACAEAAABAAAAWABACgAAA=","435":"b:dhMBhABu4BnGA0ACAQACAEAAABAAAAWABACgAAA=","466":"b:dhMBhABu4BnGA0ACAQACAEAAABAAAAWABACgAAA=","475":"b:dhMBhABu4BnGA0ACAQACAEAAABAAAAWABACgAAA=","507":"b:dhMBhABu4BnGA0ACAQACAEAAABAAAAWABACgAAA=","531":"b:dhMBhABu4BnGA0ACAQACAEAAABAAAAWABACgAAA=","541":"b:dhMBhABu4BnGA0ACAQACAEAAABAAAAWABACgAAA=","568":"b:dhMBhABu4BnGA0ACAQACAEAAABAAAAWABACgAAA=","713":"b:dhMBhABu4BnGA0ACAQACAEAAABAAAAWABACgAAA=","726":"b:dhMBhABu4BnGA0ACAQACAEAAABAAAAWABACgAAA=","740":"b:dhMBhABu4BnGA0ACAQACAEAAABAAAAWABACgAAA=","844":"b:dhMBhABu4BnGA0ACAQACAEAAABAAAAWABACgAAA=","871":"b:dhMBhABu4BnGA0ACAQACAEAAABAAAAWABACgAAA=","950":"b:dhMBhABu4BnGA0ACAQACAEAAABAAAAWABACgAAA="},"packages/cli/src/credentials-overwrites.ts":{"23":"b:dgMBhABs4hnCAwACAAAAAAAAAAAAAAQABAAgAAA=","34":"b:dgMBhABs4hnCAwACAAAAAAAAAAAAAAQABAAgAAA=","38":"b:dgMBhABs4hnCAwACAAAAAAAAAAAAAAQABAAgAAA=","60":"b:dgMBhABs4hnCAwACAAAAAAAAAAAAAAQABAAgAAA=","64":"b:dgMBhABs4hnCAwACAAAAAAAAAAAAAAQABAAgAAA=","86":"b:dgMBhABs4hnCAwACAAAAAAAAAAAAAAQABAAgAAA=","91":"b:dgMBhABs4hnCAwACAAAAAAAAAAAAAAQABAAgAAA=","105":"b:dgMBhABs4hnCAwACAAAAAAAAAAAAAAQABAAgAAA=","110":"b:dgMBhABs4hnCAwACAAAAAAAAAAAAAAQABAAgAAA=","125":"b:dgMBhABs4hnCAwACAAAAAAAAAAAAAAQABAAgAAA=","140":"b:dgMBhABs4hnCAwACAAAAAAAAAAAAAAQABAAgAAA=","152":"b:dgMBhABs4hnCAwACAAAAAAAAAAAAAAQABAAgAAA=","180":"b:dgMBhABs4hnCAwACAAAAAAAAAAAAAAQABAAgAAA=","212":"b:dgMBhABs4hnCAwACAAAAAAAAAAAAAAQABAAgAAA=","216":"b:dgMBhABs4hnCAwACAAAAAAAAAAAAAAQABAAgAAA=","217":"b:dgMBhABs4hnCAwACAAAAAAAAAAAAAAQABAAgAAA=","222":"b:dgMBhABs4hnCAwACAAAAAAAAAAAAAAQABAAgAAA=","227":"b:dgMBhABs4hnCAwACAAAAAAAAAAAAAAQABAAgAAA=","231":"b:dgMBhABs4hnCAwACAAAAAAAAAAAAAAQABAAgAAA=","240":"b:dgMBhABs4hnCAwACAAAAAAAAAAAAAAQABAAgAAA=","247":"b:dgMBhABs4hnCAwACAAAAAAAAAAAAAAQABAAgAAA=","258":"b:dgMBhABs4hnCAwACAAAAAAAAAAAAAAQABAAgAAA=","261":"b:dgMBhABs4hnCAwACAAAAAAAAAAAAAAQABAAgAAA=","268":"b:dgMBhABs4hnCAwACAAAAAAAAAAAAAAQABAAgAAA="},"packages/cli/src/environments.ee/variables/variables.service.ee.ts":{"30":"b:fwFIXnUi4XGJvyoCAAAAAAAAAAEAAABA/wdAAAA=","38":"b:fwFIXnUi4XGJvyoCAAAAAAAAAAEAAABA/wdAAAA=","45":"b:fwFIXnUi4XGJvyoCAAAAAAAAAAEAAABA/wdAAAA=","68":"b:fwFIXnUi4XGJvyoCAAAAAAAAAAEAAABA/wdAAAA=","73":"b:fwFIXnUi4XGJvyoCAAAAAAAAAAEAAABA/wdAAAA=","77":"b:fwFIXnUi4XGJvyoCAAAAAAAAAAEAAABA/wdAAAA=","83":"b:fwFIXnUi4XGJvyoCAAAAAAAAAAEAAABA/wdAAAA=","85":"b:fwFIXnUi4XGJvyoCAAAAAAAAAAEAAABA/wdAAAA=","92":"b:fwFIXnUi4XGJvyoCAAAAAAAAAAEAAABA/wdAAAA=","98":"b:fwFIXnUi4XGJvyoCAAAAAAAAAAEAAABA/wdAAAA=","108":"b:fwFIXnUi4XGJvyoCAAAAAAAAAAEAAABA/wdAAAA=","115":"b:fwFIXnUi4XGJvyoCAAAAAAAAAAEAAABA/wdAAAA=","123":"b:fwFIXnUi4XGJvyoCAAAAAAAAAAEAAABA/wdAAAA=","127":"b:fwFIXnUi4XGJvyoCAAAAAAAAAAEAAABA/wdAAAA=","145":"b:fwFIXnUi4XGJvyoCAAAAAAAAAAEAAABA/wdAAAA=","173":"b:fwFIXnUi4XGJvyoCAAAAAAAAAAEAAABA/wdAAAA=","178":"b:fwFIXnUi4XGJvyoCAAAAAAAAAAEAAABA/wdAAAA=","183":"b:fwFIXnUi4XGJvyoCAAAAAAAAAAEAAABA/wdAAAA=","191":"b:fwFIXnUi4XGJvyoCAAAAAAAAAAEAAABA/wdAAAA=","202":"b:fwFIXnUi4XGJvyoCAAAAAAAAAAEAAABA/wdAAAA=","204":"b:fwFIXnUi4XGJvyoCAAAAAAAAAAEAAABA/wdAAAA=","207":"b:fwFIXnUi4XGJvyoCAAAAAAAAAAEAAABA/wdAAAA=","214":"b:fwFIXnUi4XGJvyoCAAAAAAAAAAEAAABA/wdAAAA=","221":"b:fwFIXnUi4XGJvyoCAAAAAAAAAAEAAABA/wdAAAA=","263":"b:fwFIXnUi4XGJvyoCAAAAAAAAAAEAAABA/wdAAAA="},"packages/cli/src/eventbus/event-message-classes/event-message-ai-node.ts":{"33":[0,1,2,3,4,5,6,10,12],"41":[0,1,2,3,4,5,6,10,12]},"packages/cli/src/eventbus/event-message-classes/event-message-node.ts":{"34":"b:fwBIXnUg4WEJsD4AAAAAAAAAAAAAAAAA+wfAAAA=","42":"b:fwBIXnUg4WEJsD4AAAAAAAAAAAAAAAAA+wfAAAA="},"packages/cli/src/eventbus/event-message-classes/event-message-workflow.ts":{"36":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA=","44":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA="},"packages/cli/src/eventbus/message-event-bus/message-event-bus.ts":{"58":"b:fxRMXnUg6WGJsz5AAAAACAAAAABABAAA+4fZAgA=","78":"b:fxRMXnUg6WGJsz5AAAAACAAAAABABAAA+4fZAgA=","117":"b:fxRMXnUg6WGJsz5AAAAACAAAAABABAAA+4fZAgA=","128":"b:fxRMXnUg6WGJsz5AAAAACAAAAABABAAA+4fZAgA=","131":"b:fxRMXnUg6WGJsz5AAAAACAAAAABABAAA+4fZAgA=","142":"b:fxRMXnUg6WGJsz5AAAAACAAAAABABAAA+4fZAgA=","153":"b:fxRMXnUg6WGJsz5AAAAACAAAAABABAAA+4fZAgA=","160":"b:fxRMXnUg6WGJsz5AAAAACAAAAABABAAA+4fZAgA=","183":"b:fxRMXnUg6WGJsz5AAAAACAAAAABABAAA+4fZAgA=","187":"b:fxRMXnUg6WGJsz5AAAAACAAAAABABAAA+4fZAgA=","188":"b:fxRMXnUg6WGJsz5AAAAACAAAAABABAAA+4fZAgA=","193":"b:fxRMXnUg6WGJsz5AAAAACAAAAABABAAA+4fZAgA=","199":"b:fxRMXnUg6WGJsz5AAAAACAAAAABABAAA+4fZAgA=","205":"b:fxRMXnUg6WGJsz5AAAAACAAAAABABAAA+4fZAgA=","211":"b:fxRMXnUg6WGJsz5AAAAACAAAAABABAAA+4fZAgA=","216":"b:fxRMXnUg6WGJsz5AAAAACAAAAABABAAA+4fZAgA=","230":"b:fxRMXnUg6WGJsz5AAAAACAAAAABABAAA+4fZAgA=","241":"b:fxRMXnUg6WGJsz5AAAAACAAAAABABAAA+4fZAgA=","245":"b:fxRMXnUg6WGJsz5AAAAACAAAAABABAAA+4fZAgA=","249":"b:fxRMXnUg6WGJsz5AAAAACAAAAABABAAA+4fZAgA=","253":"b:fxRMXnUg6WGJsz5AAAAACAAAAABABAAA+4fZAgA=","257":"b:fxRMXnUg6WGJsz5AAAAACAAAAABABAAA+4fZAgA=","261":"b:fxRMXnUg6WGJsz5AAAAACAAAAABABAAA+4fZAgA=","265":"b:fxRMXnUg6WGJsz5AAAAACAAAAABABAAA+4fZAgA=","269":"b:fxRMXnUg6WGJsz5AAAAACAAAAABABAAA+4fZAgA=","280":"b:fxRMXnUg6WGJsz5AAAAACAAAAABABAAA+4fZAgA=","346":"b:fxRMXnUg6WGJsz5AAAAACAAAAABABAAA+4fZAgA=","362":"b:fxRMXnUg6WGJsz5AAAAACAAAAABABAAA+4fZAgA="},"packages/cli/src/events/relays/event-relay.ts":{"8":"b:/wv4/1cLgnvZtwmSHwAAAAAAgAAAAAAA/98GAAA=","10":"b:/wv4/1cLgnvZtwmSHwAAAAAAgAAAAAAA/98GAAA=","18":"b:/wv4/1cLgnvZtwmSHwAAAAAAgAAAAAAA/98GAAA="},"packages/cli/src/events/relays/log-streaming.event-relay.ts":{"21":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","25":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","39":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","40":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","47":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","51":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","56":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","68":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","77":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","79":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","80":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","81":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","82":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","83":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","84":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","85":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","86":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","87":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","88":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","89":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","90":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","91":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","92":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","93":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","94":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","95":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","96":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","97":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","98":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","99":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","100":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","101":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","102":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","103":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","104":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","105":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","106":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","107":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","108":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","109":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","110":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","111":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","112":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","113":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","114":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","115":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","116":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","117":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","118":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","120":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","121":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","122":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","123":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","124":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","125":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","126":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","127":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","129":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","130":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","132":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","133":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","135":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","137":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","139":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","140":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","142":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","143":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","144":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","145":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","146":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","147":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","148":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","149":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","150":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","151":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","152":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","153":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","154":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","155":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","156":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","157":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","158":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","159":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","160":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","161":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","162":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","163":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","164":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","165":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","166":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","167":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","168":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","169":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","170":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","171":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","172":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","173":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","174":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","175":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","176":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","177":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","178":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","179":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","180":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","181":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","182":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","183":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","184":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","185":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","186":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","187":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","188":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","189":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","190":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","191":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","192":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","193":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","194":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","195":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","202":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","210":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","224":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","231":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","237":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","242":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","250":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","262":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","270":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","278":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","286":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","299":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","317":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","330":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","351":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","387":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","452":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","475":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","496":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","508":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","528":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","553":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","561":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","569":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","577":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","585":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","593":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","605":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","613":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","620":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","635":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","643":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","651":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","665":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","673":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","681":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","693":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","709":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","741":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","753":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","764":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","772":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","797":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","806":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","820":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","828":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","836":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","847":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","861":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","873":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","886":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","898":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","919":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","928":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","934":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","943":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","953":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","962":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","971":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","980":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","989":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","998":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1007":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1016":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1030":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1041":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1049":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1060":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1067":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1076":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1094":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1109":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1119":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1137":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1152":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1179":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1188":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1195":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1202":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1209":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1216":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1223":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1230":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1237":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1244":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1251":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1258":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1265":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1272":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1283":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1290":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1301":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1308":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1315":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1327":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1375":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1391":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1411":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1424":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1447":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1468":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1475":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1482":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1489":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1496":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1503":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1510":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1517":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1528":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1546":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1561":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1575":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1588":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1605":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1617":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA=","1625":"b:/x///3d/73//vz/3n0ACCMAFgVVAHEZL/9//pwA="},"packages/cli/src/execution-lifecycle/execution-lifecycle-hooks.ts":{"58":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","70":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","88":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","103":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","119":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","134":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","161":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","170":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","180":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","222":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","224":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","226":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","236":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","238":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","254":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","277":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","291":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","308":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","326":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","404":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","464":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","485":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","495":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","500":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","504":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","514":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","519":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","531":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","532":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","537":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","542":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","553":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","576":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","594":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","724":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","733":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","829":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","858":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","865":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","905":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","937":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA=","994":"b:fwBMXnUg4WGJsz5EAEAAAFQAAAAAFmAI+wfYoQA="},"packages/cli/src/execution-lifecycle/restore-binary-data-id.ts":{"30":"b:fwBKXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfAAQA=","64":"b:fwBKXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfAAQA=","78":"b:fwBKXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfAAQA="},"packages/cli/src/execution-lifecycle/shared/shared-hook-functions.ts":{"13":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA=","29":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA=","79":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA=","95":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA="},"packages/cli/src/execution-lifecycle/to-save-settings.ts":{"20":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA="},"packages/cli/src/executions/execution-cursor.ts":{"12":"b:AgBEBEQAiECJgAAAAAAAAEAAAAAEBgAM+AeAAQA=","30":"b:AgBEBEQAiECJgAAAAAAAAEAAAAAEBgAM+AeAAQA=","43":"b:AgBEBEQAiECJgAAAAAAAAEAAAAAEBgAM+AeAAQA=","47":"b:AgBEBEQAiECJgAAAAAAAAEAAAAAEBgAM+AeAAQA="},"packages/cli/src/executions/execution-data/db-store.ts":{"14":"b:fwBMXnUg8WGJsz4EAAAAAEAAAQAADAAA+wfYgQA=","16":"b:fwBMXnUg8WGJsz4EAAAAAEAAAQAADAAA+wfYgQA=","32":"b:fwBMXnUg8WGJsz4EAAAAAEAAAQAADAAA+wfYgQA=","50":"b:fwBMXnUg8WGJsz4EAAAAAEAAAQAADAAA+wfYgQA=","58":"b:fwBMXnUg8WGJsz4EAAAAAEAAAQAADAAA+wfYgQA=","76":"b:fwBMXnUg8WGJsz4EAAAAAEAAAQAADAAA+wfYgQA=","91":"b:fwBMXnUg8WGJsz4EAAAAAEAAAQAADAAA+wfYgQA=","105":"b:fwBMXnUg8WGJsz4EAAAAAEAAAQAADAAA+wfYgQA=","109":"b:fwBMXnUg8WGJsz4EAAAAAEAAAQAADAAA+wfYgQA="},"packages/cli/src/executions/execution-data/types.ts":{"13":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","27":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","39":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","47":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA="},"packages/cli/src/executions/execution-id.ts":{"8":"b:DwBEXlUg9WGBsz4AAAAAAAAAAAAAAAAAAAAAAAA=","16":"b:DwBEXlUg9WGBsz4AAAAAAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/executions/execution-list-v1.service.ts":{"21":"b:AgBEBEQAiECJgAAAAAAAAEAAAAAEBgAM+AeAAQA=","27":"b:AgBEBEQAiECJgAAAAAAAAEAAAAAEBgAM+AeAAQA=","38":"b:AgBEBEQAiECJgAAAAAAAAEAAAAAEBgAM+AeAAQA=","73":"b:AgBEBEQAiECJgAAAAAAAAEAAAAAEBgAM+AeAAQA=","93":"b:AgBEBEQAiECJgAAAAAAAAEAAAAAEBgAM+AeAAQA=","108":"b:AgBEBEQAiECJgAAAAAAAAEAAAAAEBgAM+AeAAQA=","129":"b:AgBEBEQAiECJgAAAAAAAAEAAAAAEBgAM+AeAAQA="},"packages/cli/src/executions/execution-list.service.ts":{"24":"b:AgBEBEQAiECJgAAAAAAAAEAAAAAEBgAE+AeAAQA=","32":"b:AgBEBEQAiECJgAAAAAAAAEAAAAAEBgAE+AeAAQA=","62":"b:AgBEBEQAiECJgAAAAAAAAEAAAAAEBgAE+AeAAQA=","72":"b:AgBEBEQAiECJgAAAAAAAAEAAAAAEBgAE+AeAAQA=","73":"b:AgBEBEQAiECJgAAAAAAAAEAAAAAEBgAE+AeAAQA=","89":"b:AgBEBEQAiECJgAAAAAAAAEAAAAAEBgAE+AeAAQA=","98":"b:AgBEBEQAiECJgAAAAAAAAEAAAAAEBgAE+AeAAQA="},"packages/cli/src/executions/execution-persistence.ts":{"79":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","99":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","109":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","115":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","170":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","207":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","227":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","299":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","397":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","418":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","434":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","487":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","488":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","496":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","497":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","502":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","511":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","557":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","570":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","591":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","596":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","639":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","649":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","654":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","655":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","660":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","676":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","690":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","720":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","734":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","753":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","754":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","757":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","770":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","787":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","809":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","829":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","836":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","886":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","905":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","924":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","950":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","974":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","986":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","996":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","1017":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","1030":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","1035":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","1044":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","1060":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","1080":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","1093":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","1107":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","1119":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","1135":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","1151":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","1157":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA=","1167":"b:f4FPXnUk9fHJ9z4HAAAIAEgMAQACDQBB+wfZoQA="},"packages/cli/src/executions/execution-redaction-proxy.service.ts":{"13":"b:DwBMXlUg8WGBsz4AAAAAAAAAAAAAAAAAAAAAAAA=","17":"b:DwBMXlUg8WGBsz4AAAAAAAAAAAAAAAAAAAAAAAA=","27":"b:DwBMXlUg8WGBsz4AAAAAAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/executions/execution.service.ee.ts":{"13":"b:DwBEWgUg9WGAsz5AAAAAAAAAAAAAAAAAAAAAAAA=","19":"b:DwBEWgUg9WGAsz5AAAAAAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/executions/execution.service.ts":{"109":"b:D4BFXlUk/fHJ9z4DAAAIAEgMAAAEBwAE+AeAIQA=","139":"b:D4BFXlUk/fHJ9z4DAAAIAEgMAAAEBwAE+AeAIQA=","202":"b:D4BFXlUk/fHJ9z4DAAAIAEgMAAAEBwAE+AeAIQA=","234":"b:D4BFXlUk/fHJ9z4DAAAIAEgMAAAEBwAE+AeAIQA=","407":"b:D4BFXlUk/fHJ9z4DAAAIAEgMAAAEBwAE+AeAIQA=","413":"b:D4BFXlUk/fHJ9z4DAAAIAEgMAAAEBwAE+AeAIQA=","448":"b:D4BFXlUk/fHJ9z4DAAAIAEgMAAAEBwAE+AeAIQA=","487":"b:D4BFXlUk/fHJ9z4DAAAIAEgMAAAEBwAE+AeAIQA=","495":"b:D4BFXlUk/fHJ9z4DAAAIAEgMAAAEBwAE+AeAIQA=","510":"b:D4BFXlUk/fHJ9z4DAAAIAEgMAAAEBwAE+AeAIQA=","518":"b:D4BFXlUk/fHJ9z4DAAAIAEgMAAAEBwAE+AeAIQA=","556":"b:D4BFXlUk/fHJ9z4DAAAIAEgMAAAEBwAE+AeAIQA=","577":"b:D4BFXlUk/fHJ9z4DAAAIAEgMAAAEBwAE+AeAIQA=","585":"b:D4BFXlUk/fHJ9z4DAAAIAEgMAAAEBwAE+AeAIQA=","595":"b:D4BFXlUk/fHJ9z4DAAAIAEgMAAAEBwAE+AeAIQA=","624":"b:D4BFXlUk/fHJ9z4DAAAIAEgMAAAEBwAE+AeAIQA=","644":"b:D4BFXlUk/fHJ9z4DAAAIAEgMAAAEBwAE+AeAIQA=","666":"b:D4BFXlUk/fHJ9z4DAAAIAEgMAAAEBwAE+AeAIQA=","700":"b:D4BFXlUk/fHJ9z4DAAAIAEgMAAAEBwAE+AeAIQA=","745":"b:D4BFXlUk/fHJ9z4DAAAIAEgMAAAEBwAE+AeAIQA=","757":"b:D4BFXlUk/fHJ9z4DAAAIAEgMAAAEBwAE+AeAIQA=","773":"b:D4BFXlUk/fHJ9z4DAAAIAEgMAAAEBwAE+AeAIQA=","774":"b:D4BFXlUk/fHJ9z4DAAAIAEgMAAAEBwAE+AeAIQA=","802":"b:D4BFXlUk/fHJ9z4DAAAIAEgMAAAEBwAE+AeAIQA=","832":"b:D4BFXlUk/fHJ9z4DAAAIAEgMAAAEBwAE+AeAIQA=","847":"b:D4BFXlUk/fHJ9z4DAAAIAEgMAAAEBwAE+AeAIQA=","855":"b:D4BFXlUk/fHJ9z4DAAAIAEgMAAAEBwAE+AeAIQA=","887":"b:D4BFXlUk/fHJ9z4DAAAIAEgMAAAEBwAE+AeAIQA=","895":"b:D4BFXlUk/fHJ9z4DAAAIAEgMAAAEBwAE+AeAIQA=","906":"b:D4BFXlUk/fHJ9z4DAAAIAEgMAAAEBwAE+AeAIQA="},"packages/cli/src/executions/executions.controller.ts":{"22":"b:DwBEXlUg/WGJsz4AAAAAAEAAAAAEBgAE+AeAIQA=","30":"b:DwBEXlUg/WGJsz4AAAAAAEAAAAAEBgAE+AeAIQA=","35":"b:DwBEXlUg/WGJsz4AAAAAAEAAAAAEBgAE+AeAIQA=","62":"b:DwBEXlUg/WGJsz4AAAAAAEAAAAAEBgAE+AeAIQA=","73":"b:DwBEXlUg/WGJsz4AAAAAAEAAAAAEBgAE+AeAIQA=","87":"b:DwBEXlUg/WGJsz4AAAAAAEAAAAAEBgAE+AeAIQA=","103":"b:DwBEXlUg/WGJsz4AAAAAAEAAAAAEBgAE+AeAIQA=","114":"b:DwBEXlUg/WGJsz4AAAAAAEAAAAAEBgAE+AeAIQA=","133":"b:DwBEXlUg/WGJsz4AAAAAAEAAAAAEBgAE+AeAIQA=","144":"b:DwBEXlUg/WGJsz4AAAAAAEAAAAAEBgAE+AeAIQA=","165":"b:DwBEXlUg/WGJsz4AAAAAAEAAAAAEBgAE+AeAIQA="},"packages/cli/src/executions/parse-range-query.middleware.ts":{"16":"b:AgBEBEQAiECJgAAAAAAAAEAAAAAEBgAE+AeAAQA=","19":"b:AgBEBEQAiECJgAAAAAAAAEAAAAAEBgAE+AeAAQA=","38":"b:AgBEBEQAiECJgAAAAAAAAEAAAAAEBgAE+AeAAQA="},"packages/cli/src/executions/pre-execution-checks/credentials-permission-checker.ts":{"18":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA=","27":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA=","35":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA=","53":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA=","75":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA=","93":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA=","125":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA=","139":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA=","149":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA=","172":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA=","201":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA=","206":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA=","215":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA=","217":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA=","218":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA=","227":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA=","235":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA=","243":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA=","251":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA=","255":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA=","268":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA=","283":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA=","302":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA=","352":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA=","399":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA=","400":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA=","416":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA=","430":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA=","451":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA=","480":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA=","496":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA=","497":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA=","524":"b:fxFKXnUw4WGJvz4EAIAAAEAAAAAAAGBK+wfQAQA="},"packages/cli/src/executions/pre-execution-checks/workflow-pre-execute.ts":{"30":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","37":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","78":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","95":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA="},"packages/cli/src/executions/sum-binary-data-bytes.ts":{"13":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","37":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","64":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA="},"packages/cli/src/expression-observability/expression-observability.provider.ts":{"45":"b:fwFIXn0i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","48":"b:fwFIXn0i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","73":"b:fwFIXn0i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","74":"b:fwFIXn0i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","75":"b:fwFIXn0i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","79":"b:fwFIXn0i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","83":"b:fwFIXn0i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","84":"b:fwFIXn0i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","85":"b:fwFIXn0i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","86":"b:fwFIXn0i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","90":"b:fwFIXn0i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","122":"b:fwFIXn0i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","129":"b:fwFIXn0i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","137":"b:fwFIXn0i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","145":"b:fwFIXn0i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","155":"b:fwFIXn0i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","186":"b:fwFIXn0i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","194":"b:fwFIXn0i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","203":"b:fwFIXn0i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","207":"b:fwFIXn0i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","211":"b:fwFIXn0i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA=","212":"b:fwFIXn0i42GJvz4CAAAIAAAAAAAARCBA/wdIAQA="},"packages/cli/src/external-hooks.ts":{"57":"b:/wtu/ncq43vJvz8TAAAAAAAAAAAAAAAA/wfQAAA=","184":"b:/wtu/ncq43vJvz8TAAAAAAAAAAAAAAAA/wfQAAA=","201":"b:/wtu/ncq43vJvz8TAAAAAAAAAAAAAAAA/wfQAAA=","221":"b:/wtu/ncq43vJvz8TAAAAAAAAAAAAAAAA/wfQAAA=","232":"b:/wtu/ncq43vJvz8TAAAAAAAAAAAAAAAA/wfQAAA=","236":"b:/wtu/ncq43vJvz8TAAAAAAAAAAAAAAAA/wfQAAA="},"packages/cli/src/generic-helpers.ts":{"13":"b:jwts/ncqo3vJvwkTAAACAAAAAAAAAAAA/wcAAAA=","25":"b:jwts/ncqo3vJvwkTAAACAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/license/license.controller.ts":{"15":"b:jwps+AMro3tAvgnPHgAAAAAAAAAAAAAAAAAAAAA=","22":"b:jwps+AMro3tAvgnPHgAAAAAAAAAAAAAAAAAAAAA=","28":"b:jwps+AMro3tAvgnPHgAAAAAAAAAAAAAAAAAAAAA=","45":"b:jwps+AMro3tAvgnPHgAAAAAAAAAAAAAAAAAAAAA=","61":"b:jwps+AMro3tAvgnPHgAAAAAAAAAAAAAAAAAAAAA=","73":"b:jwps+AMro3tAvgnPHgAAAAAAAAAAAAAAAAAAAAA=","78":"b:jwps+AMro3tAvgnPHgAAAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/license/license.service.ts":{"29":"b:jwps+AMro3tAvgnPHgAAAAAAAAAAAAAAAAAAAAA=","44":"b:jwps+AMro3tAvgnPHgAAAAAAAAAAAAAAAAAAAAA=","70":"b:jwps+AMro3tAvgnPHgAAAAAAAAAAAAAAAAAAAAA=","85":"b:jwps+AMro3tAvgnPHgAAAAAAAAAAAAAAAAAAAAA=","128":"b:jwps+AMro3tAvgnPHgAAAAAAAAAAAAAAAAAAAAA=","136":"b:jwps+AMro3tAvgnPHgAAAAAAAAAAAAAAAAAAAAA=","162":"b:jwps+AMro3tAvgnPHgAAAAAAAAAAAAAAAAAAAAA=","180":"b:jwps+AMro3tAvgnPHgAAAAAAAAAAAAAAAAAAAAA=","195":"b:jwps+AMro3tAvgnPHgAAAAAAAAAAAAAAAAAAAAA=","209":"b:jwps+AMro3tAvgnPHgAAAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/license.ts":{"49":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","59":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","78":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","79":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","81":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","82":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","84":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","85":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","87":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","88":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","90":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","91":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","92":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","118":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","120":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","146":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","160":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","175":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","185":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","190":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","197":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","214":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","216":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","224":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","237":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","248":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","265":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","269":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","278":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","288":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","301":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","305":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","309":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","314":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","319":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","324":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","329":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","334":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","339":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","344":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","349":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","354":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","359":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","364":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","369":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","374":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","379":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","384":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","389":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","394":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","399":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","404":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","409":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","414":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","419":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","424":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","428":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","432":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","436":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","446":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","456":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","459":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","463":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","470":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","475":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","480":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","485":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","490":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","498":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","502":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","506":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","514":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","522":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","537":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","552":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","561":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","566":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","572":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA=","575":"b:/wv8/1cro3vZvwnfHwAAAAAAgAAAAAAA/98GAAA="},"packages/cli/src/load-nodes-and-credentials.ts":{"69":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","78":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","139":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","143":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","144":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","147":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","163":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","166":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","176":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","180":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","186":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","188":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","192":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","196":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","200":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","204":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","208":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","212":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","253":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","260":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","264":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","282":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","312":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","313":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","328":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","339":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","345":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","354":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","365":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","368":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","369":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","388":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","391":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","396":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","405":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","406":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","413":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","429":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","433":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","442":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","453":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","464":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","474":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","551":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","564":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","581":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","582":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","585":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","597":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","603":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","608":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","640":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","657":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","659":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","662":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","667":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","682":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","689":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","710":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","716":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","744":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","745":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","760":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","769":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","771":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","778":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","781":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","809":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","824":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","828":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","829":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","835":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","845":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","846":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA=","847":"b:/695/nVuo3nLvzlXAwAAIGAKiACgHCeA/wcgAAA="},"packages/cli/src/manual-execution.service.ts":{"29":"b:CwBEWhQwrGAAsz4AAEAAACQAAAAAFAAAAAAAAAA=","34":"b:CwBEWhQwrGAAsz4AAEAAACQAAAAAFAAAAAAAAAA=","54":"b:CwBEWhQwrGAAsz4AAEAAACQAAAAAFAAAAAAAAAA=","67":"b:CwBEWhQwrGAAsz4AAEAAACQAAAAAFAAAAAAAAAA="},"packages/cli/src/metrics/prometheus/webhook-and-form-metrics.service.ts":{"18":"b:DgAEAGEAQEGIAAAEgAAAAAAAAAAAAAIAAwDYAQA=","20":"b:DgAEAGEAQEGIAAAEgAAAAAAAAAAAAAIAAwDYAQA=","24":"b:DgAEAGEAQEGIAAAEgAAAAAAAAAAAAAIAAwDYAQA=","46":"b:DgAEAGEAQEGIAAAEgAAAAAAAAAAAAAIAAwDYAQA=","67":"b:DgAEAGEAQEGIAAAEgAAAAAAAAAAAAAIAAwDYAQA="},"packages/cli/src/metrics/prometheus/workflow-execution-duration-metrics.service.ts":{"18":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA=","23":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA=","27":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA=","40":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA="},"packages/cli/src/modules/agents/agent-dependency-index.listener.ts":{"9":"b:AhPKtGAUg1HJLwQEAAAAAMAFAQBAGAAA+weAAAA=","17":"b:AhPKtGAUg1HJLwQEAAAAAMAFAQBAGAAA+weAAAA=","18":"b:AhPKtGAUg1HJLwQEAAAAAMAFAQBAGAAA+weAAAA=","19":"b:AhPKtGAUg1HJLwQEAAAAAMAFAQBAGAAA+weAAAA=","23":"b:AhPKtGAUg1HJLwQEAAAAAMAFAQBAGAAA+weAAAA=","24":"b:AhPKtGAUg1HJLwQEAAAAAMAFAQBAGAAA+weAAAA=","28":"b:AhPKtGAUg1HJLwQEAAAAAMAFAQBAGAAA+weAAAA=","29":"b:AhPKtGAUg1HJLwQEAAAAAMAFAQBAGAAA+weAAAA=","43":"b:AhPKtGAUg1HJLwQEAAAAAMAFAQBAGAAA+weAAAA=","44":"b:AhPKtGAUg1HJLwQEAAAAAMAFAQBAGAAA+weAAAA=","45":"b:AhPKtGAUg1HJLwQEAAAAAMAFAQBAGAAA+weAAAA=","49":"b:AhPKtGAUg1HJLwQEAAAAAMAFAQBAGAAA+weAAAA=","58":"b:AhPKtGAUg1HJLwQEAAAAAMAFAQBAGAAA+weAAAA="},"packages/cli/src/modules/agents/agent-dependency-index.service.ts":{"16":"b:AhPKtGAUg1HJLwQEAAAAAMABAABAAAAA+weAAAA=","28":"b:AhPKtGAUg1HJLwQEAAAAAMABAABAAAAA+weAAAA=","33":"b:AhPKtGAUg1HJLwQEAAAAAMABAABAAAAA+weAAAA=","42":"b:AhPKtGAUg1HJLwQEAAAAAMABAABAAAAA+weAAAA=","47":"b:AhPKtGAUg1HJLwQEAAAAAMABAABAAAAA+weAAAA="},"packages/cli/src/modules/agents/agent-message-queue-consumer.service.ts":{"31":"b:/wr4/wsrontatQmDHwAAAAAAgAAAAAAAcQ2UAAI=","45":"b:/wr4/wsrontatQmDHwAAAAAAgAAAAAAAcQ2UAAI=","47":"b:/wr4/wsrontatQmDHwAAAAAAgAAAAAAAcQ2UAAI=","48":"b:/wr4/wsrontatQmDHwAAAAAAgAAAAAAAcQ2UAAI=","56":"b:/wr4/wsrontatQmDHwAAAAAAgAAAAAAAcQ2UAAI=","63":"b:/wr4/wsrontatQmDHwAAAAAAgAAAAAAAcQ2UAAI=","77":"b:/wr4/wsrontatQmDHwAAAAAAgAAAAAAAcQ2UAAI=","81":"b:/wr4/wsrontatQmDHwAAAAAAgAAAAAAAcQ2UAAI=","84":"b:/wr4/wsrontatQmDHwAAAAAAgAAAAAAAcQ2UAAI=","88":"b:/wr4/wsrontatQmDHwAAAAAAgAAAAAAAcQ2UAAI=","95":"b:/wr4/wsrontatQmDHwAAAAAAgAAAAAAAcQ2UAAI=","98":"b:/wr4/wsrontatQmDHwAAAAAAgAAAAAAAcQ2UAAI=","129":"b:/wr4/wsrontatQmDHwAAAAAAgAAAAAAAcQ2UAAI=","159":"b:/wr4/wsrontatQmDHwAAAAAAgAAAAAAAcQ2UAAI=","181":"b:/wr4/wsrontatQmDHwAAAAAAgAAAAAAAcQ2UAAI=","194":"b:/wr4/wsrontatQmDHwAAAAAAgAAAAAAAcQ2UAAI=","245":"b:/wr4/wsrontatQmDHwAAAAAAgAAAAAAAcQ2UAAI=","246":"b:/wr4/wsrontatQmDHwAAAAAAgAAAAAAAcQ2UAAI=","252":"b:/wr4/wsrontatQmDHwAAAAAAgAAAAAAAcQ2UAAI=","278":"b:/wr4/wsrontatQmDHwAAAAAAgAAAAAAAcQ2UAAI="},"packages/cli/src/modules/agents/agent-workflow-tool-resume.service.ts":{"37":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA=","55":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA=","87":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA=","105":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA=","137":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA=","150":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA=","207":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA=","234":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA=","255":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA=","301":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA=","338":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA="},"packages/cli/src/modules/agents/integrations/agent-channel-reconciler.service.ts":{"81":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","103":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","111":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","130":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","146":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","151":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","156":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","168":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","178":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","186":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","189":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","190":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","202":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","223":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","232":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","237":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","256":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","279":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","310":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","335":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","352":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","356":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","368":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","393":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/modules/agents/register-agent-usage-provider.ts":{"9":"b:C4JtAIGk4/5ArgALABAAAEgAAAAABAAAAAAAAAA=","15":"b:C4JtAIGk4/5ArgALABAAAEgAAAAABAAAAAAAAAA=","18":"b:C4JtAIGk4/5ArgALABAAAEgAAAAABAAAAAAAAAA=","26":"b:C4JtAIGk4/5ArgALABAAAEgAAAAABAAAAAAAAAA=","34":"b:C4JtAIGk4/5ArgALABAAAEgAAAAABAAAAAAAAAA="},"packages/cli/src/modules/agents/repositories/agent-workflow-dependency.repository.ts":{"22":"b:CwPutOEE43/JrwAHAAAAAEgAAABAAAAA+weAAAA=","29":"b:CwPutOEE43/JrwAHAAAAAEgAAABAAAAA+weAAAA=","30":"b:CwPutOEE43/JrwAHAAAAAEgAAABAAAAA+weAAAA=","62":"b:CwPutOEE43/JrwAHAAAAAEgAAABAAAAA+weAAAA=","65":"b:CwPutOEE43/JrwAHAAAAAEgAAABAAAAA+weAAAA=","82":"b:CwPutOEE43/JrwAHAAAAAEgAAABAAAAA+weAAAA=","90":"b:CwPutOEE43/JrwAHAAAAAEgAAABAAAAA+weAAAA=","94":"b:CwPutOEE43/JrwAHAAAAAEgAAABAAAAA+weAAAA=","103":"b:CwPutOEE43/JrwAHAAAAAEgAAABAAAAA+weAAAA=","113":"b:CwPutOEE43/JrwAHAAAAAEgAAABAAAAA+weAAAA=","116":"b:CwPutOEE43/JrwAHAAAAAEgAAABAAAAA+weAAAA=","129":"b:CwPutOEE43/JrwAHAAAAAEgAAABAAAAA+weAAAA="},"packages/cli/src/modules/breaking-changes/breaking-changes.rule-registry.service.ts":{"10":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","14":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","22":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","23":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","26":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","30":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","35":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/breaking-changes.service.ts":{"84":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","95":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","99":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","103":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","129":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","136":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","154":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","203":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","213":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","233":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","305":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","326":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","341":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","351":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","363":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","377":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","381":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","384":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","395":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","406":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","409":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","420":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","428":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","429":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","439":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","448":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","451":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","454":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","482":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/database/repositories/migration-finding.repository.ts":{"30":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","42":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","48":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","56":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","73":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","85":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","97":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","120":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","130":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","138":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","165":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","173":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","204":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","212":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","222":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","237":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","260":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","264":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","277":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","285":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA="},"packages/cli/src/modules/breaking-changes/database/repositories/migration-workflow-owner.repository.ts":{"15":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","19":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","34":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","51":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","56":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","74":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","83":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","94":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","95":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA="},"packages/cli/src/modules/breaking-changes/detection-report.ts":{"14":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","21":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/group-nodes-by-type.ts":{"4":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v2/binary-data-storage.rule.ts":{"14":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","21":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","34":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v2/cli-replace-update-workflow-command.rule.ts":{"11":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","14":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","27":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v2/disabled-nodes.rule.ts":{"14":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","22":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","35":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","52":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","60":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","65":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v2/dotenv-upgrade.rule.ts":{"14":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","16":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","28":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","37":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","54":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","60":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v2/file-access.rule.ts":{"14":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","19":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","31":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","43":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","47":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","52":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v2/oauth-callback-auth.rule.ts":{"12":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","15":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","28":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v2/process-env-access.rule.ts":{"14":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","16":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","28":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","48":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","58":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","67":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","77":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v2/pyodide-removed.rule.ts":{"15":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","18":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","31":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","53":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","66":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","72":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v2/queue-worker-max-stalled-count.rule.ts":{"11":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","14":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","27":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v2/removed-nodes.rule.ts":{"14":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","23":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","35":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","46":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","50":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","55":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v2/settings-file-permissions.rule.ts":{"13":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","17":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","30":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v2/start-node-removed.rule.ts":{"14":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","19":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","30":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","51":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","61":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v2/task-runner-docker-image.rule.ts":{"13":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","17":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","30":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v2/tunnel-option.rule.ts":{"11":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","14":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","25":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v2/wait-node-subworkflow.rule.ts":{"25":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","65":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","78":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","95":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","100":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","136":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","182":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","192":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","202":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","237":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v2/workflow-hooks-deprecated.rule.ts":{"11":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","14":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","27":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/agent-node-mode.ts":{"19":"b:j+tu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","25":"b:j+tu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","29":"b:j+tu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","34":"b:j+tu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/agent-node-version.rule.ts":{"20":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","23":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","35":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","48":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","53":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","56":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/agent-removed-modes.rule.ts":{"20":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","23":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","35":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","48":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","53":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","60":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/ai-transform-deprecated.rule.ts":{"17":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","20":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","32":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","45":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","51":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/always-output-data-multi-output.rule.ts":{"21":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","23":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","34":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","46":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","59":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","72":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","89":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/chat-hub-deprecated.rule.ts":{"16":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","20":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","32":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/chat-trigger-embedded-json.rule.ts":{"24":"b:j8tu/ncqo3vJvwkTAAAAAABAAQAAAAAA/wcAAAA=","27":"b:j8tu/ncqo3vJvwkTAAAAAABAAQAAAAAA/wcAAAA=","40":"b:j8tu/ncqo3vJvwkTAAAAAABAAQAAAAAA/wcAAAA=","53":"b:j8tu/ncqo3vJvwkTAAAAAABAAQAAAAAA/wcAAAA=","58":"b:j8tu/ncqo3vJvwkTAAAAAABAAQAAAAAA/wcAAAA=","59":"b:j8tu/ncqo3vJvwkTAAAAAABAAQAAAAAA/wcAAAA=","61":"b:j8tu/ncqo3vJvwkTAAAAAABAAQAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/compression-node-limits.rule.ts":{"12":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","15":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","26":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/docker-only-deployment.rule.ts":{"14":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","18":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","30":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/execute-workflow-source-modes.rule.ts":{"23":"b:jwtu/ncqo3vJv4kTAAAAAAAAAAAAAGAA/wcAIQA=","26":"b:jwtu/ncqo3vJv4kTAAAAAAAAAAAAAGAA/wcAIQA=","38":"b:jwtu/ncqo3vJv4kTAAAAAAAAAAAAAGAA/wcAIQA=","56":"b:jwtu/ncqo3vJv4kTAAAAAAAAAAAAAGAA/wcAIQA=","61":"b:jwtu/ncqo3vJv4kTAAAAAAAAAAAAAGAA/wcAIQA=","64":"b:jwtu/ncqo3vJv4kTAAAAAAAAAAAAAGAA/wcAIQA="},"packages/cli/src/modules/breaking-changes/rules/v3/external-secrets-project-roles-default.rule.ts":{"16":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","23":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","35":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","66":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","71":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/get-paired-item.rule.ts":{"17":"b:jwtu/ncqo3vJvykTAAAAAAAAAAAAAAAA/wcAAAA=","20":"b:jwtu/ncqo3vJvykTAAAAAAAAAAAAAAAA/wcAAAA=","32":"b:jwtu/ncqo3vJvykTAAAAAAAAAAAAAAAA/wcAAAA=","45":"b:jwtu/ncqo3vJvykTAAAAAAAAAAAAAAAA/wcAAAA=","49":"b:jwtu/ncqo3vJvykTAAAAAAAAAAAAAAAA/wcAAAA=","53":"b:jwtu/ncqo3vJvykTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/gmail-trigger-version.rule.ts":{"18":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAABAA/wcAAAA=","21":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAABAA/wcAAAA=","33":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAABAA/wcAAAA=","46":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAABAA/wcAAAA=","51":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAABAA/wcAAAA=","54":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAABAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/in-memory-binary-data.rule.ts":{"14":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","18":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","29":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/offload-manual-executions.rule.ts":{"14":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","18":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","29":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/pre-execute-error-creates-execution.rule.ts":{"14":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","18":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","29":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/removed-nodes-with-replacements.rule.ts":{"20":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","27":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","30":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","34":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","40":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","47":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","57":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","60":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/removed-nodes.rule.ts":{"14":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","27":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","37":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","48":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","52":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","57":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/ssrf-default-blocked-ranges.rule.ts":{"14":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","18":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","32":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","40":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/storage-path-rename.rule.ts":{"15":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","19":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","30":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/task-runner-task-timeout.rule.ts":{"12":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","15":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","26":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/unverified-packages.rule.ts":{"18":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","25":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","34":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","38":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","49":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/workflow-import-url-removed.rule.ts":{"11":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","14":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","26":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/breaking-changes/sync/migration-finding-diff.ts":{"38":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","50":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA=","54":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAEA/wcAAAA="},"packages/cli/src/modules/breaking-changes/sync/migration-finding-sync.listener.ts":{"16":"b:jxtu/nc+o3vJvw0XAAAAAMAFAQBAGEBK/wfAAQA=","25":"b:jxtu/nc+o3vJvw0XAAAAAMAFAQBAGEBK/wfAAQA=","26":"b:jxtu/nc+o3vJvw0XAAAAAMAFAQBAGEBK/wfAAQA=","29":"b:jxtu/nc+o3vJvw0XAAAAAMAFAQBAGEBK/wfAAQA=","32":"b:jxtu/nc+o3vJvw0XAAAAAMAFAQBAGEBK/wfAAQA=","35":"b:jxtu/nc+o3vJvw0XAAAAAMAFAQBAGEBK/wfAAQA=","42":"b:jxtu/nc+o3vJvw0XAAAAAMAFAQBAGEBK/wfAAQA="},"packages/cli/src/modules/breaking-changes/sync/migration-finding-sync.service.ts":{"21":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","42":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","61":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","70":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","80":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","96":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","153":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","173":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","177":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","188":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","201":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","202":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","224":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","247":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","255":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","261":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","262":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","283":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","287":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","288":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","296":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/modules/chat-hub/chat-hub-execution-store.service.ts":{"58":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA=","79":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA=","93":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA=","103":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA=","127":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA=","140":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA=","154":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA=","158":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA=","171":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA=","189":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA=","199":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA=","202":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA=","211":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA="},"packages/cli/src/modules/chat-hub/chat-hub-execution-watcher.service.ts":{"32":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfYgQA=","54":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfYgQA=","117":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfYgQA=","163":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfYgQA=","206":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfYgQA=","238":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfYgQA=","260":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfYgQA=","283":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfYgQA="},"packages/cli/src/modules/data-table/data-table-aggregate.controller.ts":{"10":"b:3wr4+4Oron9StknPHxgEAoAAgAIAAADAAIAIAAA=","16":"b:3wr4+4Oron9StknPHxgEAoAAgAIAAADAAIAIAAA=","25":"b:3wr4+4Oron9StknPHxgEAoAAgAIAAADAAIAIAAA="},"packages/cli/src/modules/data-table/data-table-file-cleanup.service.ts":{"11":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","19":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","28":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","36":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","73":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/modules/data-table/data-table-file-cleanup.task.ts":{"26":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","31":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/modules/data-table/data-table-size-validator.service.ts":{"16":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","21":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","33":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","56":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","73":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","86":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","91":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA="},"packages/cli/src/modules/data-table/data-table.repository.ts":{"29":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","45":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","47":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","49":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","54":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","62":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","63":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","69":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","88":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","117":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","119":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","126":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","134":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","169":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","171":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","184":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","186":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","200":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","211":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","217":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","222":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","233":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","237":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","242":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","257":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","265":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","275":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","298":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","306":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","317":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","328":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","332":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","335":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","339":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","367":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA=","405":"b:3wr4+4Oron9ytknPHxgEAoAAgAIAAADAAIAIAAA="},"packages/cli/src/modules/data-table/data-table.service.ts":{"54":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","70":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","71":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","73":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","86":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","99":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","123":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","171":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","181":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","193":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","220":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","229":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","241":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","256":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","266":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","277":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","287":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","298":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","312":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","323":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","335":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","339":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","346":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","352":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","373":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","379":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","399":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","408":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","456":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","466":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","513":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","564":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","574":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","635":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","644":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","674":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","677":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","687":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","696":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","703":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","704":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","706":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","724":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","770":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","785":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","798":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","809":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","815":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","827":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","830":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","879":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","881":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","885":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","887":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","903":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","921":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","925":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","928":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","931":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","959":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","984":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","989":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","991":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","996":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","1021":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","1049":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA=","1058":"b:3wr4+wOrontytgnPHwAEAAAAgAIAAAAAAIAIAAA="},"packages/cli/src/modules/data-table/utils/sql-utils.ts":{"25":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","26":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","44":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","72":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","79":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","83":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","87":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","102":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","111":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","128":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","137":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","146":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","149":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","153":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","157":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","170":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","174":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","184":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","192":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","205":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","212":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","230":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","251":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","256":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","260":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","289":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","322":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","340":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","363":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","380":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","386":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA=","391":"b:3wr4+wOrontStgnPHwAEAAAAgAIAAAAAAIAIAAA="},"packages/cli/src/modules/dynamic-credentials.ee/services/dynamic-credential.service.ts":{"43":"b:chACAAAgoAAAAAAAAAAIAEAAAAAAAAQABACAAgA=","64":"b:chACAAAgoAAAAAAAAAAIAEAAAAAAAAQABACAAgA=","195":"b:chACAAAgoAAAAAAAAAAIAEAAAAAAAAQABACAAgA=","212":"b:chACAAAgoAAAAAAAAAAIAEAAAAAAAAQABACAAgA=","244":"b:chACAAAgoAAAAAAAAAAIAEAAAAAAAAQABACAAgA=","275":"b:chACAAAgoAAAAAAAAAAIAEAAAAAAAAQABACAAgA=","321":"b:chACAAAgoAAAAAAAAAAIAEAAAAAAAAQABACAAgA=","336":"b:chACAAAgoAAAAAAAAAAIAEAAAAAAAAQABACAAgA=","353":"b:chACAAAgoAAAAAAAAAAIAEAAAAAAAAQABACAAgA=","366":"b:chACAAAgoAAAAAAAAAAIAEAAAAAAAAQABACAAgA=","369":"b:chACAAAgoAAAAAAAAAAIAEAAAAAAAAQABACAAgA=","389":"b:chACAAAgoAAAAAAAAAAIAEAAAAAAAAQABACAAgA="},"packages/cli/src/modules/external-secrets.ee/provider-registry.service.ts":{"10":"b:BgIBIABoABRiQBICAAAGAoKBQBAkUoVAAAAGAAA=","13":"b:BgIBIABoABRiQBICAAAGAoKBQBAkUoVAAAAGAAA=","17":"b:BgIBIABoABRiQBICAAAGAoKBQBAkUoVAAAAGAAA=","21":"b:BgIBIABoABRiQBICAAAGAoKBQBAkUoVAAAAGAAA=","25":"b:BgIBIABoABRiQBICAAAGAoKBQBAkUoVAAAAGAAA=","29":"b:BgIBIABoABRiQBICAAAGAoKBQBAkUoVAAAAGAAA=","33":"b:BgIBIABoABRiQBICAAAGAoKBQBAkUoVAAAAGAAA=","43":"b:BgIBIABoABRiQBICAAAGAoKBQBAkUoVAAAAGAAA=","47":"b:BgIBIABoABRiQBICAAAGAoKBQBAkUoVAAAAGAAA=","51":"b:BgIBIABoABRiQBICAAAGAoKBQBAkUoVAAAAGAAA=","55":"b:BgIBIABoABRiQBICAAAGAoKBQBAkUoVAAAAGAAA=","57":"b:BgIBIABoABRiQBICAAAGAoKBQBAkUoVAAAAGAAA=","58":"b:BgIBIABoABRiQBICAAAGAoKBQBAkUoVAAAAGAAA="},"packages/cli/src/modules/external-secrets.ee/secrets-providers-completions.controller.ee.ts":{"15":"b:BgIBIABoABBCAAACAAACAAKAABAAAAQAAAAAAAA=","24":"b:BgIBIABoABBCAAACAAACAAKAABAAAAQAAAAAAAA=","55":"b:BgIBIABoABBCAAACAAACAAKAABAAAAQAAAAAAAA=","72":"b:BgIBIABoABBCAAACAAACAAKAABAAAAQAAAAAAAA=","84":"b:BgIBIABoABBCAAACAAACAAKAABAAAAQAAAAAAAA="},"packages/cli/src/modules/external-secrets.ee/secrets-providers-connections.service.ee.ts":{"38":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","52":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","78":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","106":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","123":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","140":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","145":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","146":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","151":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","152":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","167":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","189":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","211":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","220":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","243":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","251":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","261":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","265":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","273":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","281":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","285":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","287":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","294":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","309":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","319":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","337":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","338":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","349":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","375":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","402":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","406":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","419":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","436":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","440":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","467":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","471":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","484":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","500":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA=","522":"b:VgIDIIBoABRCAAADAAAGAAKAABAAAARAAAAAAAA="},"packages/cli/src/modules/favorites/database/repositories/user-favorite.repository.ts":{"9":"b:/wv4/wMrontStgnPHwAEAAABgAIAAABBAIAIAAA=","13":"b:/wv4/wMrontStgnPHwAEAAABgAIAAABBAIAIAAA=","20":"b:/wv4/wMrontStgnPHwAEAAABgAIAAABBAIAIAAA=","24":"b:/wv4/wMrontStgnPHwAEAAABgAIAAABBAIAIAAA="},"packages/cli/src/modules/favorites/favorites.controller.ts":{"10":"b:/wr4+wMrontStgnPHwAAAAAAgAIAAAAAAIAIAAA=","16":"b:/wr4+wMrontStgnPHwAAAAAAgAIAAAAAAIAIAAA=","19":"b:/wr4+wMrontStgnPHwAAAAAAgAIAAAAAAIAIAAA=","24":"b:/wr4+wMrontStgnPHwAAAAAAgAIAAAAAAIAIAAA=","29":"b:/wr4+wMrontStgnPHwAAAAAAgAIAAAAAAIAIAAA="},"packages/cli/src/modules/favorites/favorites.service.ts":{"24":"b:/wv4/wMrontStgnPHwAEAAABgAIAAABBAIAIAAA=","25":"b:/wv4/wMrontStgnPHwAEAAABgAIAAABBAIAIAAA=","27":"b:/wv4/wMrontStgnPHwAEAAABgAIAAABBAIAIAAA=","33":"b:/wv4/wMrontStgnPHwAEAAABgAIAAABBAIAIAAA=","44":"b:/wv4/wMrontStgnPHwAEAAABgAIAAABBAIAIAAA=","53":"b:/wv4/wMrontStgnPHwAEAAABgAIAAABBAIAIAAA=","66":"b:/wv4/wMrontStgnPHwAEAAABgAIAAABBAIAIAAA=","76":"b:/wv4/wMrontStgnPHwAEAAABgAIAAABBAIAIAAA=","94":"b:/wv4/wMrontStgnPHwAEAAABgAIAAABBAIAIAAA=","116":"b:/wv4/wMrontStgnPHwAEAAABgAIAAABBAIAIAAA=","117":"b:/wv4/wMrontStgnPHwAEAAABgAIAAABBAIAIAAA=","125":"b:/wv4/wMrontStgnPHwAEAAABgAIAAABBAIAIAAA=","130":"b:/wv4/wMrontStgnPHwAEAAABgAIAAABBAIAIAAA=","135":"b:/wv4/wMrontStgnPHwAEAAABgAIAAABBAIAIAAA=","149":"b:/wv4/wMrontStgnPHwAEAAABgAIAAABBAIAIAAA=","173":"b:/wv4/wMrontStgnPHwAEAAABgAIAAABBAIAIAAA=","196":"b:/wv4/wMrontStgnPHwAEAAABgAIAAABBAIAIAAA=","214":"b:/wv4/wMrontStgnPHwAEAAABgAIAAABBAIAIAAA=","241":"b:/wv4/wMrontStgnPHwAEAAABgAIAAABBAIAIAAA=","253":"b:/wv4/wMrontStgnPHwAEAAABgAIAAABBAIAIAAA=","257":"b:/wv4/wMrontStgnPHwAEAAABgAIAAABBAIAIAAA="},"packages/cli/src/modules/inbound-auth-core/database/repositories/trusted-source.repository.ts":{"15":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","19":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","73":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","82":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","86":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","90":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","99":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","122":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","126":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","130":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","135":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","148":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","159":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","171":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/modules/inbound-auth-core/trusted-source-discovery.service.ts":{"30":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","37":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","42":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","46":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","57":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","71":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","84":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/modules/inbound-auth-core/trusted-source-discovery.task.ts":{"23":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","25":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/modules/inbound-auth-core/trusted-source.store.ts":{"40":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","45":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","46":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","67":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","78":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","81":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","85":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","88":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","93":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","97":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","99":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","103":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","109":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","110":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","114":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","127":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","142":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","162":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","188":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","200":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","206":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","214":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","227":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","242":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","244":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","245":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","248":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA=","266":"b:QgJIiICKAFNSMABDWPogAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/modules/instance-ai/browser/browser-use-server.ts":{"22":"b:/wr4+wMqolNAvgnHAyAAAAAAgAAAAAAAAAAAAAA=","24":"b:/wr4+wMqolNAvgnHAyAAAAAAgAAAAAAAAAAAAAA=","25":"b:/wr4+wMqolNAvgnHAyAAAAAAgAAAAAAAAAAAAAA=","28":"b:/wr4+wMqolNAvgnHAyAAAAAAgAAAAAAAAAAAAAA=","31":"b:/wr4+wMqolNAvgnHAyAAAAAAgAAAAAAAAAAAAAA=","43":"b:/wr4+wMqolNAvgnHAyAAAAAAgAAAAAAAAAAAAAA=","47":"b:/wr4+wMqolNAvgnHAyAAAAAAgAAAAAAAAAAAAAA=","52":"b:/wr4+wMqolNAvgnHAyAAAAAAgAAAAAAAAAAAAAA=","53":"b:/wr4+wMqolNAvgnHAyAAAAAAgAAAAAAAAAAAAAA=","64":"b:/wr4+wMqolNAvgnHAyAAAAAAgAAAAAAAAAAAAAA="},"packages/cli/src/modules/instance-ai/instance-ai-memory.service.ts":{"51":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","61":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","74":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","110":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","126":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","150":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","163":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","182":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","257":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","277":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","289":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","295":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","317":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","331":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","343":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","351":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","397":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","433":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","454":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","458":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","470":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","474":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","535":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","583":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","593":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","613":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","629":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","639":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","648":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","661":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","665":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","669":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","675":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","699":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","706":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","721":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","736":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","788":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA=","806":"b:j8r+A4GrontiugnPHwiwAQAAAABAAAAAAAAAAAA="},"packages/cli/src/modules/instance-ai/instance-ai-settings.service.ts":{"106":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","120":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","131":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","150":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","171":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","178":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","190":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","213":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","304":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","324":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","329":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","334":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","362":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","404":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","487":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","606":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","639":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","795":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","817":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","875":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","921":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","939":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","953":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1027":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1036":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1062":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1084":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1095":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1102":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1113":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1123":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1128":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1135":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1145":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1147":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1154":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1171":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1186":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1213":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1222":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1231":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1237":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1247":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1251":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1261":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1266":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1275":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1280":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1284":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1289":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1294":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1299":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1315":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1320":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1330":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1336":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1357":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1362":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1371":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1404":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1421":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1438":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1446":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1469":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1477":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1538":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1561":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1567":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1573":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1581":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1617":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1633":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1642":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1655":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1659":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1667":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1671":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1675":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1706":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1715":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1725":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1739":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1745":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1750":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1786":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1790":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1809":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1822":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1827":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1830":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1836":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1837":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1846":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA=","1863":"b:j8r+A4GrontCugnPHwgAAAAAAABAAAAAAEAAAAA="},"packages/cli/src/modules/instance-ai/instance-ai.controller.ts":{"107":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","138":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","150":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","158":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","168":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","178":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","196":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","214":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","265":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","297":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","313":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","324":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","330":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","340":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","409":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","446":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","465":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","502":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","506":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","579":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","587":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","626":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","635":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","649":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","655":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","669":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","692":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","708":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","724":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","733":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","739":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","745":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","768":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","778":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","788":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","797":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","806":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","813":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","816":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","821":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","825":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","843":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","858":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","864":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","878":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","884":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","890":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","897":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","908":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","916":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","964":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","978":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","995":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1007":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1029":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1042":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1113":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1126":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1139":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1158":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1166":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1174":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1181":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1196":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1220":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1240":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1263":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1280":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1334":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1390":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1407":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1426":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1439":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1462":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1466":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1472":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1478":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1484":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1504":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1535":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1552":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1573":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1586":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1599":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1616":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1624":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1632":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1640":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1650":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1665":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1676":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1688":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1713":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA=","1726":"b:j8r+A4Gro3tCugnPHwgwAQAAAABAAAAAAEAAAAA="},"packages/cli/src/modules/instance-ai/liveness/instance-ai-liveness.service.ts":{"114":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAAAAAAA=","116":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAAAAAAA=","120":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAAAAAAA=","123":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAAAAAAA=","128":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAAAAAAA=","138":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAAAAAAA=","142":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAAAAAAA=","146":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAAAAAAA=","152":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAAAAAAA=","161":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAAAAAAA=","165":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAAAAAAA=","206":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAAAAAAA=","225":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAAAAAAA=","235":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAAAAAAA=","244":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAAAAAAA=","267":"b:QgJ4iICKAlNSMABDWPowAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/modules/otel/execution-level-tracer.ts":{"41":"b:fwBIXnUg4WGJsz4AAEAAAAQAAAAAEgAA+wfAAAA=","56":"b:fwBIXnUg4WGJsz4AAEAAAAQAAAAAEgAA+wfAAAA=","62":"b:fwBIXnUg4WGJsz4AAEAAAAQAAAAAEgAA+wfAAAA=","66":"b:fwBIXnUg4WGJsz4AAEAAAAQAAAAAEgAA+wfAAAA=","117":"b:fwBIXnUg4WGJsz4AAEAAAAQAAAAAEgAA+wfAAAA=","153":"b:fwBIXnUg4WGJsz4AAEAAAAQAAAAAEgAA+wfAAAA=","180":"b:fwBIXnUg4WGJsz4AAEAAAAQAAAAAEgAA+wfAAAA=","201":"b:fwBIXnUg4WGJsz4AAEAAAAQAAAAAEgAA+wfAAAA=","252":"b:fwBIXnUg4WGJsz4AAEAAAAQAAAAAEgAA+wfAAAA=","291":"b:fwBIXnUg4WGJsz4AAEAAAAQAAAAAEgAA+wfAAAA=","296":"b:fwBIXnUg4WGJsz4AAEAAAAQAAAAAEgAA+wfAAAA=","317":"b:fwBIXnUg4WGJsz4AAEAAAAQAAAAAEgAA+wfAAAA=","335":"b:fwBIXnUg4WGJsz4AAEAAAAQAAAAAEgAA+wfAAAA=","340":"b:fwBIXnUg4WGJsz4AAEAAAAQAAAAAEgAA+wfAAAA=","353":"b:fwBIXnUg4WGJsz4AAEAAAAQAAAAAEgAA+wfAAAA=","361":"b:fwBIXnUg4WGJsz4AAEAAAAQAAAAAEgAA+wfAAAA=","373":"b:fwBIXnUg4WGJsz4AAEAAAAQAAAAAEgAA+wfAAAA=","385":"b:fwBIXnUg4WGJsz4AAEAAAAQAAAAAEgAA+wfAAAA=","396":"b:fwBIXnUg4WGJsz4AAEAAAAQAAAAAEgAA+wfAAAA=","408":"b:fwBIXnUg4WGJsz4AAEAAAAQAAAAAEgAA+wfAAAA=","417":"b:fwBIXnUg4WGJsz4AAEAAAAQAAAAAEgAA+wfAAAA=","424":"b:fwBIXnUg4WGJsz4AAEAAAAQAAAAAEgAA+wfAAAA=","429":"b:fwBIXnUg4WGJsz4AAEAAAAQAAAAAEgAA+wfAAAA=","435":"b:fwBIXnUg4WGJsz4AAEAAAAQAAAAAEgAA+wfAAAA=","454":"b:fwBIXnUg4WGJsz4AAEAAAAQAAAAAEgAA+wfAAAA=","467":"b:fwBIXnUg4WGJsz4AAEAAAAQAAAAAEgAA+wfAAAA=","474":"b:fwBIXnUg4WGJsz4AAEAAAAQAAAAAEgAA+wfAAAA=","482":"b:fwBIXnUg4WGJsz4AAEAAAAQAAAAAEgAA+wfAAAA="},"packages/cli/src/modules/otel/otel-lifecycle-handler.ts":{"25":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfIgQA=","34":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfIgQA=","46":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfIgQA=","58":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfIgQA=","61":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfIgQA=","66":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfIgQA=","70":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfIgQA=","81":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfIgQA=","93":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfIgQA=","132":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfIgQA=","139":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfIgQA=","173":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfIgQA=","184":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfIgQA=","210":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfIgQA=","213":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfIgQA=","224":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfIgQA=","227":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfIgQA=","240":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfIgQA=","244":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfIgQA=","266":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfIgQA=","285":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfIgQA=","296":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfIgQA=","309":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfIgQA=","314":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfIgQA=","319":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfIgQA=","321":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfIgQA=","324":"b:fwBMXnUg4WGJsz4EAAAAAEAAAAAAAAAI+wfIgQA="},"packages/cli/src/modules/policy-infrastructure/policy-decision.service.ts":{"54":"b:/wvo/3cq43vrvy8TAQAAAAAAAAAAAABA/wfAAAA=","63":"b:/wvo/3cq43vrvy8TAQAAAAAAAAAAAABA/wfAAAA=","68":"b:/wvo/3cq43vrvy8TAQAAAAAAAAAAAABA/wfAAAA=","69":"b:/wvo/3cq43vrvy8TAQAAAAAAAAAAAABA/wfAAAA=","81":"b:/wvo/3cq43vrvy8TAQAAAAAAAAAAAABA/wfAAAA=","92":"b:/wvo/3cq43vrvy8TAQAAAAAAAAAAAABA/wfAAAA=","93":"b:/wvo/3cq43vrvy8TAQAAAAAAAAAAAABA/wfAAAA=","121":"b:/wvo/3cq43vrvy8TAQAAAAAAAAAAAABA/wfAAAA=","129":"b:/wvo/3cq43vrvy8TAQAAAAAAAAAAAABA/wfAAAA=","145":"b:/wvo/3cq43vrvy8TAQAAAAAAAAAAAABA/wfAAAA=","157":"b:/wvo/3cq43vrvy8TAQAAAAAAAAAAAABA/wfAAAA=","168":"b:/wvo/3cq43vrvy8TAQAAAAAAAAAAAABA/wfAAAA=","180":"b:/wvo/3cq43vrvy8TAQAAAAAAAAAAAABA/wfAAAA=","191":"b:/wvo/3cq43vrvy8TAQAAAAAAAAAAAABA/wfAAAA=","197":"b:/wvo/3cq43vrvy8TAQAAAAAAAAAAAABA/wfAAAA=","200":"b:/wvo/3cq43vrvy8TAQAAAAAAAAAAAABA/wfAAAA=","226":"b:/wvo/3cq43vrvy8TAQAAAAAAAAAAAABA/wfAAAA=","234":"b:/wvo/3cq43vrvy8TAQAAAAAAAAAAAABA/wfAAAA=","235":"b:/wvo/3cq43vrvy8TAQAAAAAAAAAAAABA/wfAAAA="},"packages/cli/src/modules/policy-infrastructure/policy-lifecycle-handler.ts":{"17":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","23":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA="},"packages/cli/src/modules/redaction/dynamic-credentials-context-hook.ts":{"21":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","31":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","52":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA="},"packages/cli/src/modules/redaction/executions/execution-redaction.service.ts":{"44":"b:DwBMXlUg8WGBsz4AAAAAAAAAAAAAAAAAAAAAAAA=","53":"b:DwBMXlUg8WGBsz4AAAAAAAAAAAAAAAAAAAAAAAA=","65":"b:DwBMXlUg8WGBsz4AAAAAAAAAAAAAAAAAAAAAAAA=","82":"b:DwBMXlUg8WGBsz4AAAAAAAAAAAAAAAAAAAAAAAA=","97":"b:DwBMXlUg8WGBsz4AAAAAAAAAAAAAAAAAAAAAAAA=","105":"b:DwBMXlUg8WGBsz4AAAAAAAAAAAAAAAAAAAAAAAA=","106":"b:DwBMXlUg8WGBsz4AAAAAAAAAAAAAAAAAAAAAAAA=","222":"b:DwBMXlUg8WGBsz4AAAAAAAAAAAAAAAAAAAAAAAA=","271":"b:DwBMXlUg8WGBsz4AAAAAAAAAAAAAAAAAAAAAAAA=","310":"b:DwBMXlUg8WGBsz4AAAAAAAAAAAAAAAAAAAAAAAA=","339":"b:DwBMXlUg8WGBsz4AAAAAAAAAAAAAAAAAAAAAAAA=","361":"b:DwBMXlUg8WGBsz4AAAAAAAAAAAAAAAAAAAAAAAA=","381":"b:DwBMXlUg8WGBsz4AAAAAAAAAAAAAAAAAAAAAAAA=","396":"b:DwBMXlUg8WGBsz4AAAAAAAAAAAAAAAAAAAAAAAA=","415":"b:DwBMXlUg8WGBsz4AAAAAAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/modules/redaction/redaction-context-hook.ts":{"20":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","29":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","47":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA="},"packages/cli/src/modules/redaction/redaction-enforcement.service.ts":{"20":"b:AgJItEAEA1EALwQQAAAAAIAFAQBAGAAACAAAAAA=","24":"b:AgJItEAEA1EALwQQAAAAAIAFAQBAGAAACAAAAAA=","50":"b:AgJItEAEA1EALwQQAAAAAIAFAQBAGAAACAAAAAA="},"packages/cli/src/modules/workflow-index/agent-usage-provider-proxy.service.ts":{"16":"b:C4JtAIGk4/5ArgALABAAAEgAAAAABAAAAAAAAAA=","19":"b:C4JtAIGk4/5ArgALABAAAEgAAAAABAAAAAAAAAA=","23":"b:C4JtAIGk4/5ArgALABAAAEgAAAAABAAAAAAAAAA=","30":"b:C4JtAIGk4/5ArgALABAAAEgAAAAABAAAAAAAAAA="},"packages/cli/src/modules/workflow-index/workflow-dependency-query.service.ts":{"68":"b:C4JtAIGk4/5A7tALABAEAMgBAHAABYBAAAAAAAA=","87":"b:C4JtAIGk4/5A7tALABAEAMgBAHAABYBAAAAAAAA=","130":"b:C4JtAIGk4/5A7tALABAEAMgBAHAABYBAAAAAAAA=","156":"b:C4JtAIGk4/5A7tALABAEAMgBAHAABYBAAAAAAAA=","250":"b:C4JtAIGk4/5A7tALABAEAMgBAHAABYBAAAAAAAA=","252":"b:C4JtAIGk4/5A7tALABAEAMgBAHAABYBAAAAAAAA=","263":"b:C4JtAIGk4/5A7tALABAEAMgBAHAABYBAAAAAAAA=","294":"b:C4JtAIGk4/5A7tALABAEAMgBAHAABYBAAAAAAAA=","320":"b:C4JtAIGk4/5A7tALABAEAMgBAHAABYBAAAAAAAA=","348":"b:C4JtAIGk4/5A7tALABAEAMgBAHAABYBAAAAAAAA=","355":"b:C4JtAIGk4/5A7tALABAEAMgBAHAABYBAAAAAAAA=","421":"b:C4JtAIGk4/5A7tALABAEAMgBAHAABYBAAAAAAAA=","459":"b:C4JtAIGk4/5A7tALABAEAMgBAHAABYBAAAAAAAA=","479":"b:C4JtAIGk4/5A7tALABAEAMgBAHAABYBAAAAAAAA=","529":"b:C4JtAIGk4/5A7tALABAEAMgBAHAABYBAAAAAAAA=","543":"b:C4JtAIGk4/5A7tALABAEAMgBAHAABYBAAAAAAAA=","553":"b:C4JtAIGk4/5A7tALABAEAMgBAHAABYBAAAAAAAA=","561":"b:C4JtAIGk4/5A7tALABAEAMgBAHAABYBAAAAAAAA=","574":"b:C4JtAIGk4/5A7tALABAEAMgBAHAABYBAAAAAAAA=","577":"b:C4JtAIGk4/5A7tALABAEAMgBAHAABYBAAAAAAAA=","587":"b:C4JtAIGk4/5A7tALABAEAMgBAHAABYBAAAAAAAA="},"packages/cli/src/modules/workflow-index/workflow-dependency.controller.ts":{"9":"b:C4JtAIGk4/5ArhALABAAAMgBADAABYBAAAAAAAA=","12":"b:C4JtAIGk4/5ArhALABAAAMgBADAABYBAAAAAAAA=","25":"b:C4JtAIGk4/5ArhALABAAAMgBADAABYBAAAAAAAA=","41":"b:C4JtAIGk4/5ArhALABAAAMgBADAABYBAAAAAAAA="},"packages/cli/src/modules/workflow-index/workflow-index.service.ts":{"33":"b:jxtu/nc+o3vJv60XAAAAAMAFAQBAGGBL/wfAIQA=","45":"b:jxtu/nc+o3vJv60XAAAAAMAFAQBAGGBL/wfAIQA=","46":"b:jxtu/nc+o3vJv60XAAAAAMAFAQBAGGBL/wfAIQA=","48":"b:jxtu/nc+o3vJv60XAAAAAMAFAQBAGGBL/wfAIQA=","50":"b:jxtu/nc+o3vJv60XAAAAAMAFAQBAGGBL/wfAIQA=","53":"b:jxtu/nc+o3vJv60XAAAAAMAFAQBAGGBL/wfAIQA=","56":"b:jxtu/nc+o3vJv60XAAAAAMAFAQBAGGBL/wfAIQA=","59":"b:jxtu/nc+o3vJv60XAAAAAMAFAQBAGGBL/wfAIQA=","71":"b:jxtu/nc+o3vJv60XAAAAAMAFAQBAGGBL/wfAIQA=","74":"b:jxtu/nc+o3vJv60XAAAAAMAFAQBAGGBL/wfAIQA=","76":"b:jxtu/nc+o3vJv60XAAAAAMAFAQBAGGBL/wfAIQA=","82":"b:jxtu/nc+o3vJv60XAAAAAMAFAQBAGGBL/wfAIQA=","95":"b:jxtu/nc+o3vJv60XAAAAAMAFAQBAGGBL/wfAIQA=","143":"b:jxtu/nc+o3vJv60XAAAAAMAFAQBAGGBL/wfAIQA=","157":"b:jxtu/nc+o3vJv60XAAAAAMAFAQBAGGBL/wfAIQA=","175":"b:jxtu/nc+o3vJv60XAAAAAMAFAQBAGGBL/wfAIQA=","182":"b:jxtu/nc+o3vJv60XAAAAAMAFAQBAGGBL/wfAIQA=","204":"b:jxtu/nc+o3vJv60XAAAAAMAFAQBAGGBL/wfAIQA=","222":"b:jxtu/nc+o3vJv60XAAAAAMAFAQBAGGBL/wfAIQA=","223":"b:jxtu/nc+o3vJv60XAAAAAMAFAQBAGGBL/wfAIQA=","265":"b:jxtu/nc+o3vJv60XAAAAAMAFAQBAGGBL/wfAIQA=","275":"b:jxtu/nc+o3vJv60XAAAAAMAFAQBAGGBL/wfAIQA=","292":"b:jxtu/nc+o3vJv60XAAAAAMAFAQBAGGBL/wfAIQA=","314":"b:jxtu/nc+o3vJv60XAAAAAMAFAQBAGGBL/wfAIQA=","334":"b:jxtu/nc+o3vJv60XAAAAAMAFAQBAGGBL/wfAIQA=","348":"b:jxtu/nc+o3vJv60XAAAAAMAFAQBAGGBL/wfAIQA=","363":"b:jxtu/nc+o3vJv60XAAAAAMAFAQBAGGBL/wfAIQA="},"packages/cli/src/node-types.ts":{"19":"b:/wto/nUqo3HJvykTAAAAAAAAAAAAAAAA/wcAAAA=","35":"b:/wto/nUqo3HJvykTAAAAAAAAAAAAAAAA/wcAAAA=","49":"b:/wto/nUqo3HJvykTAAAAAAAAAAAAAAAA/wcAAAA=","68":"b:/wto/nUqo3HJvykTAAAAAAAAAAAAAAAA/wcAAAA=","96":"b:/wto/nUqo3HJvykTAAAAAAAAAAAAAAAA/wcAAAA=","100":"b:/wto/nUqo3HJvykTAAAAAAAAAAAAAAAA/wcAAAA=","120":"b:/wto/nUqo3HJvykTAAAAAAAAAAAAAAAA/wcAAAA=","161":"b:/wto/nUqo3HJvykTAAAAAAAAAAAAAAAA/wcAAAA=","175":"b:/wto/nUqo3HJvykTAAAAAAAAAAAAAAAA/wcAAAA=","188":"b:/wto/nUqo3HJvykTAAAAAAAAAAAAAAAA/wcAAAA=","190":"b:/wto/nUqo3HJvykTAAAAAAAAAAAAAAAA/wcAAAA=","208":"b:/wto/nUqo3HJvykTAAAAAAAAAAAAAAAA/wcAAAA=","226":"b:/wto/nUqo3HJvykTAAAAAAAAAAAAAAAA/wcAAAA=","229":"b:/wto/nUqo3HJvykTAAAAAAAAAAAAAAAA/wcAAAA=","236":"b:/wto/nUqo3HJvykTAAAAAAAAAAAAAAAA/wcAAAA=","239":"b:/wto/nUqo3HJvykTAAAAAAAAAAAAAAAA/wcAAAA=","250":"b:/wto/nUqo3HJvykTAAAAAAAAAAAAAAAA/wcAAAA=","251":"b:/wto/nUqo3HJvykTAAAAAAAAAAAAAAAA/wcAAAA=","275":"b:/wto/nUqo3HJvykTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/permissions.ee/check-access.ts":{"32":"b:/wv4/1crqn/ZtwmDHwACAAAAgBAAEAAA/88GAAA=","55":"b:/wv4/1crqn/ZtwmDHwACAAAAgBAAEAAA/88GAAA=","77":"b:/wv4/1crqn/ZtwmDHwACAAAAgBAAEAAA/88GAAA=","111":"b:/wv4/1crqn/ZtwmDHwACAAAAgBAAEAAA/88GAAA=","118":"b:/wv4/1crqn/ZtwmDHwACAAAAgBAAEAAA/88GAAA=","120":"b:/wv4/1crqn/ZtwmDHwACAAAAgBAAEAAA/88GAAA=","138":"b:/wv4/1crqn/ZtwmDHwACAAAAgBAAEAAA/88GAAA=","163":"b:/wv4/1crqn/ZtwmDHwACAAAAgBAAEAAA/88GAAA="},"packages/cli/src/policy/policed-agent-nodes.ts":{"26":"b:/wvo/3cqo3vJvykTAAAAAAAAAAAAAAAA/wcAAAA=","40":"b:/wvo/3cqo3vJvykTAAAAAAAAAAAAAAAA/wcAAAA=","67":"b:/wvo/3cqo3vJvykTAAAAAAAAAAAAAAAA/wcAAAA=","82":"b:/wvo/3cqo3vJvykTAAAAAAAAAAAAAAAA/wcAAAA=","85":"b:/wvo/3cqo3vJvykTAAAAAAAAAAAAAAAA/wcAAAA=","110":"b:/wvo/3cqo3vJvykTAAAAAAAAAAAAAAAA/wcAAAA=","118":"b:/wvo/3cqo3vJvykTAAAAAAAAAAAAAAAA/wcAAAA=","119":"b:/wvo/3cqo3vJvykTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/policy/policy-enforcement.service.ts":{"35":"b:/wvr/3du43vrvy8TAQAAAAAAAAAAAARA/wfgAAA=","38":"b:/wvr/3du43vrvy8TAQAAAAAAAAAAAARA/wfgAAA=","43":"b:/wvr/3du43vrvy8TAQAAAAAAAAAAAARA/wfgAAA=","52":"b:/wvr/3du43vrvy8TAQAAAAAAAAAAAARA/wfgAAA=","56":"b:/wvr/3du43vrvy8TAQAAAAAAAAAAAARA/wfgAAA=","74":"b:/wvr/3du43vrvy8TAQAAAAAAAAAAAARA/wfgAAA=","86":"b:/wvr/3du43vrvy8TAQAAAAAAAAAAAARA/wfgAAA=","90":"b:/wvr/3du43vrvy8TAQAAAAAAAAAAAARA/wfgAAA=","103":"b:/wvr/3du43vrvy8TAQAAAAAAAAAAAARA/wfgAAA=","107":"b:/wvr/3du43vrvy8TAQAAAAAAAAAAAARA/wfgAAA=","119":"b:/wvr/3du43vrvy8TAQAAAAAAAAAAAARA/wfgAAA=","123":"b:/wvr/3du43vrvy8TAQAAAAAAAAAAAARA/wfgAAA=","135":"b:/wvr/3du43vrvy8TAQAAAAAAAAAAAARA/wfgAAA=","139":"b:/wvr/3du43vrvy8TAQAAAAAAAAAAAARA/wfgAAA=","151":"b:/wvr/3du43vrvy8TAQAAAAAAAAAAAARA/wfgAAA=","155":"b:/wvr/3du43vrvy8TAQAAAAAAAAAAAARA/wfgAAA=","167":"b:/wvr/3du43vrvy8TAQAAAAAAAAAAAARA/wfgAAA=","171":"b:/wvr/3du43vrvy8TAQAAAAAAAAAAAARA/wfgAAA=","183":"b:/wvr/3du43vrvy8TAQAAAAAAAAAAAARA/wfgAAA=","187":"b:/wvr/3du43vrvy8TAQAAAAAAAAAAAARA/wfgAAA=","197":"b:/wvr/3du43vrvy8TAQAAAAAAAAAAAARA/wfgAAA=","201":"b:/wvr/3du43vrvy8TAQAAAAAAAAAAAARA/wfgAAA=","212":"b:/wvr/3du43vrvy8TAQAAAAAAAAAAAARA/wfgAAA=","216":"b:/wvr/3du43vrvy8TAQAAAAAAAAAAAARA/wfgAAA=","233":"b:/wvr/3du43vrvy8TAQAAAAAAAAAAAARA/wfgAAA="},"packages/cli/src/policy/policy-violation.error.ts":{"8":"b:/wvo/3cqo3vLvwkTAQABAAAAAAAAAAAA/wcAIAA=","11":"b:/wvo/3cqo3vLvwkTAQABAAAAAAAAAAAA/wcAIAA=","14":"b:/wvo/3cqo3vLvwkTAQABAAAAAAAAAAAA/wcAIAA=","46":"b:/wvo/3cqo3vLvwkTAQABAAAAAAAAAAAA/wcAIAA=","63":"b:/wvo/3cqo3vLvwkTAQABAAAAAAAAAAAA/wcAIAA="},"packages/cli/src/posthog/index.ts":{"34":"b:/wv4/1cLgnvZ9wmSHwAAAAAAgAAAAAAA/98HAAA=","54":"b:/wv4/1cLgnvZ9wmSHwAAAAAAgAAAAAAA/98HAAA=","59":"b:/wv4/1cLgnvZ9wmSHwAAAAAAgAAAAAAA/98HAAA=","72":"b:/wv4/1cLgnvZ9wmSHwAAAAAAgAAAAAAA/98HAAA=","76":"b:/wv4/1cLgnvZ9wmSHwAAAAAAgAAAAAAA/98HAAA=","84":"b:/wv4/1cLgnvZ9wmSHwAAAAAAgAAAAAAA/98HAAA=","90":"b:/wv4/1cLgnvZ9wmSHwAAAAAAgAAAAAAA/98HAAA=","110":"b:/wv4/1cLgnvZ9wmSHwAAAAAAgAAAAAAA/98HAAA=","136":"b:/wv4/1cLgnvZ9wmSHwAAAAAAgAAAAAAA/98HAAA=","148":"b:/wv4/1cLgnvZ9wmSHwAAAAAAgAAAAAAA/98HAAA=","152":"b:/wv4/1cLgnvZ9wmSHwAAAAAAgAAAAAAA/98HAAA=","172":"b:/wv4/1cLgnvZ9wmSHwAAAAAAgAAAAAAA/98HAAA=","208":"b:/wv4/1cLgnvZ9wmSHwAAAAAAgAAAAAAA/98HAAA=","237":"b:/wv4/1cLgnvZ9wmSHwAAAAAAgAAAAAAA/98HAAA=","259":"b:/wv4/1cLgnvZ9wmSHwAAAAAAgAAAAAAA/98HAAA="},"packages/cli/src/push/abstract.push.ts":{"34":"b:/wv8//Ou43Pbvj/HW7MgABAAgAAAAAAA+weQAAA=","40":"b:/wv8//Ou43Pbvj/HW7MgABAAgAAAAAAA+weQAAA=","43":"b:/wv8//Ou43Pbvj/HW7MgABAAgAAAAAAA+weQAAA=","58":"b:/wv8//Ou43Pbvj/HW7MgABAAgAAAAAAA+weQAAA=","66":"b:/wv8//Ou43Pbvj/HW7MgABAAgAAAAAAA+weQAAA=","70":"b:/wv8//Ou43Pbvj/HW7MgABAAgAAAAAAA+weQAAA=","79":"b:/wv8//Ou43Pbvj/HW7MgABAAgAAAAAAA+weQAAA=","96":"b:/wv8//Ou43Pbvj/HW7MgABAAgAAAAAAA+weQAAA=","102":"b:/wv8//Ou43Pbvj/HW7MgABAAgAAAAAAA+weQAAA=","106":"b:/wv8//Ou43Pbvj/HW7MgABAAgAAAAAAA+weQAAA=","115":"b:/wv8//Ou43Pbvj/HW7MgABAAgAAAAAAA+weQAAA=","123":"b:/wv8//Ou43Pbvj/HW7MgABAAgAAAAAAA+weQAAA=","131":"b:/wv8//Ou43Pbvj/HW7MgABAAgAAAAAAA+weQAAA=","135":"b:/wv8//Ou43Pbvj/HW7MgABAAgAAAAAAA+weQAAA=","145":"b:/wv8//Ou43Pbvj/HW7MgABAAgAAAAAAA+weQAAA="},"packages/cli/src/push/index.ts":{"52":"b:/wv8/2Mu43PJvj/HAyAAABAAgAAAAAAA+weQAAA=","62":"b:/wv8/2Mu43PJvj/HAyAAABAAgAAAAAAA+weQAAA=","65":"b:/wv8/2Mu43PJvj/HAyAAABAAgAAAAAAA+weQAAA=","70":"b:/wv8/2Mu43PJvj/HAyAAABAAgAAAAAAA+weQAAA=","73":"b:/wv8/2Mu43PJvj/HAyAAABAAgAAAAAAA+weQAAA=","75":"b:/wv8/2Mu43PJvj/HAyAAABAAgAAAAAAA+weQAAA=","79":"b:/wv8/2Mu43PJvj/HAyAAABAAgAAAAAAA+weQAAA=","94":"b:/wv8/2Mu43PJvj/HAyAAABAAgAAAAAAA+weQAAA=","99":"b:/wv8/2Mu43PJvj/HAyAAABAAgAAAAAAA+weQAAA=","111":"b:/wv8/2Mu43PJvj/HAyAAABAAgAAAAAAA+weQAAA=","166":"b:/wv8/2Mu43PJvj/HAyAAABAAgAAAAAAA+weQAAA=","171":"b:/wv8/2Mu43PJvj/HAyAAABAAgAAAAAAA+weQAAA=","180":"b:/wv8/2Mu43PJvj/HAyAAABAAgAAAAAAA+weQAAA=","189":"b:/wv8/2Mu43PJvj/HAyAAABAAgAAAAAAA+weQAAA=","198":"b:/wv8/2Mu43PJvj/HAyAAABAAgAAAAAAA+weQAAA=","219":"b:/wv8/2Mu43PJvj/HAyAAABAAgAAAAAAA+weQAAA=","226":"b:/wv8/2Mu43PJvj/HAyAAABAAgAAAAAAA+weQAAA=","241":"b:/wv8/2Mu43PJvj/HAyAAABAAgAAAAAAA+weQAAA="},"packages/cli/src/push/push-helpers.ts":{"5":"b:/wr4+wMqonNAvgnHAyAAAAAAgAAAAAAAAAAAAAA=","9":"b:/wr4+wMqonNAvgnHAyAAAAAAgAAAAAAAAAAAAAA=","14":"b:/wr4+wMqonNAvgnHAyAAAAAAgAAAAAAAAAAAAAA=","18":"b:/wr4+wMqonNAvgnHAyAAAAAAgAAAAAAAAAAAAAA="},"packages/cli/src/push/websocket.push.ts":{"9":"b:/wr6+wMuo1NA/i3HAyAggBIAgQAgIAwAAAAAAAA=","15":"b:/wr6+wMuo1NA/i3HAyAggBIAgQAgIAwAAAAAAAA=","21":"b:/wr6+wMuo1NA/i3HAyAggBIAgQAgIAwAAAAAAAA=","60":"b:/wr6+wMuo1NA/i3HAyAggBIAgQAgIAwAAAAAAAA=","71":"b:/wr6+wMuo1NA/i3HAyAggBIAgQAgIAwAAAAAAAA=","75":"b:/wr6+wMuo1NA/i3HAyAggBIAgQAgIAwAAAAAAAA=","79":"b:/wr6+wMuo1NA/i3HAyAggBIAgQAgIAwAAAAAAAA=","88":"b:/wr6+wMuo1NA/i3HAyAggBIAgQAgIAwAAAAAAAA="},"packages/cli/src/response-helper.ts":{"19":"b:AhEBByACAECIAwAWGAMDAEAAgAAAEAWAAwDgAQA=","52":"b:AhEBByACAECIAwAWGAMDAEAAgAAAEAWAAwDgAQA=","104":"b:AhEBByACAECIAwAWGAMDAEAAgAAAEAWAAwDgAQA=","118":"b:AhEBByACAECIAwAWGAMDAEAAgAAAEAWAAwDgAQA=","122":"b:AhEBByACAECIAwAWGAMDAEAAgAAAEAWAAwDgAQA="},"packages/cli/src/scheduling/system-tasks/in-memory-system-task-runner.ts":{"61":"b:QgJIiICLAFNSMABDWPogAAAAAAAAAAAAAACAAAA=","71":"b:QgJIiICLAFNSMABDWPogAAAAAAAAAAAAAACAAAA=","79":"b:QgJIiICLAFNSMABDWPogAAAAAAAAAAAAAACAAAA=","97":"b:QgJIiICLAFNSMABDWPogAAAAAAAAAAAAAACAAAA=","114":"b:QgJIiICLAFNSMABDWPogAAAAAAAAAAAAAACAAAA=","123":"b:QgJIiICLAFNSMABDWPogAAAAAAAAAAAAAACAAAA=","130":"b:QgJIiICLAFNSMABDWPogAAAAAAAAAAAAAACAAAA=","137":"b:QgJIiICLAFNSMABDWPogAAAAAAAAAAAAAACAAAA=","142":"b:QgJIiICLAFNSMABDWPogAAAAAAAAAAAAAACAAAA=","149":"b:QgJIiICLAFNSMABDWPogAAAAAAAAAAAAAACAAAA=","156":"b:QgJIiICLAFNSMABDWPogAAAAAAAAAAAAAACAAAA=","167":"b:QgJIiICLAFNSMABDWPogAAAAAAAAAAAAAACAAAA=","177":"b:QgJIiICLAFNSMABDWPogAAAAAAAAAAAAAACAAAA=","191":"b:QgJIiICLAFNSMABDWPogAAAAAAAAAAAAAACAAAA=","204":"b:QgJIiICLAFNSMABDWPogAAAAAAAAAAAAAACAAAA=","227":"b:QgJIiICLAFNSMABDWPogAAAAAAAAAAAAAACAAAA=","231":"b:QgJIiICLAFNSMABDWPogAAAAAAAAAAAAAACAAAA=","241":"b:QgJIiICLAFNSMABDWPogAAAAAAAAAAAAAACAAAA=","246":"b:QgJIiICLAFNSMABDWPogAAAAAAAAAAAAAACAAAA="},"packages/cli/src/scheduling/system-tasks/system-task-timer.ts":{"37":"b:QgJIiICLAFNSMABDWPogAAAAAAAAAAAAAACAAAA=","45":"b:QgJIiICLAFNSMABDWPogAAAAAAAAAAAAAACAAAA=","50":"b:QgJIiICLAFNSMABDWPogAAAAAAAAAAAAAACAAAA=","55":"b:QgJIiICLAFNSMABDWPogAAAAAAAAAAAAAACAAAA=","99":"b:QgJIiICLAFNSMABDWPogAAAAAAAAAAAAAACAAAA=","117":"b:QgJIiICLAFNSMABDWPogAAAAAAAAAAAAAACAAAA=","140":"b:QgJIiICLAFNSMABDWPogAAAAAAAAAAAAAACAAAA=","143":"b:QgJIiICLAFNSMABDWPogAAAAAAAAAAAAAACAAAA=","148":"b:QgJIiICLAFNSMABDWPogAAAAAAAAAAAAAACAAAA="},"packages/cli/src/server.ts":{"94":"b:/wr4+wMro3vSvznfHyAAIGAKiAKgHCIAAIAIAAA=","106":"b:/wr4+wMro3vSvznfHyAAIGAKiAKgHCIAAIAIAAA=","130":"b:/wr4+wMro3vSvznfHyAAIGAKiAKgHCIAAIAIAAA=","172":"b:/wr4+wMro3vSvznfHyAAIGAKiAKgHCIAAIAIAAA=","209":"b:/wr4+wMro3vSvznfHyAAIGAKiAKgHCIAAIAIAAA=","278":"b:/wr4+wMro3vSvznfHyAAIGAKiAKgHCIAAIAIAAA=","308":"b:/wr4+wMro3vSvznfHyAAIGAKiAKgHCIAAIAIAAA=","360":"b:/wr4+wMro3vSvznfHyAAIGAKiAKgHCIAAIAIAAA=","366":"b:/wr4+wMro3vSvznfHyAAIGAKiAKgHCIAAIAIAAA=","378":"b:/wr4+wMro3vSvznfHyAAIGAKiAKgHCIAAIAIAAA=","393":"b:/wr4+wMro3vSvznfHyAAIGAKiAKgHCIAAIAIAAA=","457":"b:/wr4+wMro3vSvznfHyAAIGAKiAKgHCIAAIAIAAA=","465":"b:/wr4+wMro3vSvznfHyAAIGAKiAKgHCIAAIAIAAA=","472":"b:/wr4+wMro3vSvznfHyAAIGAKiAKgHCIAAIAIAAA=","499":"b:/wr4+wMro3vSvznfHyAAIGAKiAKgHCIAAIAIAAA=","518":"b:/wr4+wMro3vSvznfHyAAIGAKiAKgHCIAAIAIAAA=","527":"b:/wr4+wMro3vSvznfHyAAIGAKiAKgHCIAAIAIAAA=","528":"b:/wr4+wMro3vSvznfHyAAIGAKiAKgHCIAAIAIAAA=","537":"b:/wr4+wMro3vSvznfHyAAIGAKiAKgHCIAAIAIAAA=","546":"b:/wr4+wMro3vSvznfHyAAIGAKiAKgHCIAAIAIAAA=","555":"b:/wr4+wMro3vSvznfHyAAIGAKiAKgHCIAAIAIAAA=","564":"b:/wr4+wMro3vSvznfHyAAIGAKiAKgHCIAAIAIAAA=","571":"b:/wr4+wMro3vSvznfHyAAIGAKiAKgHCIAAIAIAAA="},"packages/cli/src/services/access.service.ts":{"13":"b:Dwps+AMuo3NAvi1HAAAAAFAEAQBgGAAAAAAAAAA=","19":"b:Dwps+AMuo3NAvi1HAAAAAFAEAQBgGAAAAAAAAAA=","31":"b:Dwps+AMuo3NAvi1HAAAAAFAEAQBgGAAAAAAAAAA="},"packages/cli/src/services/active-workflows.service.ts":{"14":"b:j4ps+AM7o3tAvgnPHgAAAAAAAEAAEEBKAAAAAAA=","22":"b:j4ps+AM7o3tAvgnPHgAAAAAAAEAAEEBKAAAAAAA=","25":"b:j4ps+AM7o3tAvgnPHgAAAAAAAEAAEEBKAAAAAAA=","28":"b:j4ps+AM7o3tAvgnPHgAAAAAAAEAAEEBKAAAAAAA=","34":"b:j4ps+AM7o3tAvgnPHgAAAAAAAEAAEEBKAAAAAAA=","43":"b:j4ps+AM7o3tAvgnPHgAAAAAAAEAAEEBKAAAAAAA=","47":"b:j4ps+AM7o3tAvgnPHgAAAAAAAEAAEEBKAAAAAAA="},"packages/cli/src/services/database-independent-routes.service.ts":{"5":"b:/wv4/1cronvRtwmTHwAAAAAAgAAAAAAA/88WAAA=","8":"b:/wv4/1cronvRtwmTHwAAAAAAgAAAAAAA/88WAAA=","13":"b:/wv4/1cronvRtwmTHwAAAAAAgAAAAAAA/88WAAA=","18":"b:/wv4/1cronvRtwmTHwAAAAAAgAAAAAAA/88WAAA="},"packages/cli/src/services/dynamic-node-parameters.service.ts":{"63":[1,41,4,5,6,60,72,73,176,16,178,179,182,87],"72":[1,41,4,5,6,60,72,73,176,16,178,179,182,87],"112":[1,41,4,5,6,60,72,73,176,16,178,179,182,87],"113":[1,41,4,5,6,60,72,73,176,16,178,179,182,87],"122":[1,41,4,5,6,60,72,73,176,16,178,179,182,87],"141":[1,41,4,5,6,60,72,73,176,16,178,179,182,87],"143":[1,41,4,5,6,60,72,73,176,16,178,179,182,87],"152":[1,41,4,5,6,60,72,73,176,16,178,179,182,87],"160":[1,41,4,5,6,60,72,73,176,16,178,179,182,87],"172":[1,41,4,5,6,60,72,73,176,16,178,179,182,87],"183":[1,41,4,5,6,60,72,73,176,16,178,179,182,87],"217":[1,41,4,5,6,60,72,73,176,16,178,179,182,87],"284":[1,41,4,5,6,60,72,73,176,16,178,179,182,87],"295":[1,41,4,5,6,60,72,73,176,16,178,179,182,87],"299":[1,41,4,5,6,60,72,73,176,16,178,179,182,87],"313":[1,41,4,5,6,60,72,73,176,16,178,179,182,87],"324":[1,41,4,5,6,60,72,73,176,16,178,179,182,87],"336":[1,41,4,5,6,60,72,73,176,16,178,179,182,87],"342":[1,41,4,5,6,60,72,73,176,16,178,179,182,87],"355":[1,41,4,5,6,60,72,73,176,16,178,179,182,87],"368":[1,41,4,5,6,60,72,73,176,16,178,179,182,87],"394":[1,41,4,5,6,60,72,73,176,16,178,179,182,87],"437":[1,41,4,5,6,60,72,73,176,16,178,179,182,87],"441":[1,41,4,5,6,60,72,73,176,16,178,179,182,87],"467":[1,41,4,5,6,60,72,73,176,16,178,179,182,87],"476":[1,41,4,5,6,60,72,73,176,16,178,179,182,87],"488":[1,41,4,5,6,60,72,73,176,16,178,179,182,87],"492":[1,41,4,5,6,60,72,73,176,16,178,179,182,87]},"packages/cli/src/services/engine-data-plane-proxy.service.ts":{"25":"b:AgBEBEQAiECJgAAAAAAAAEAAAAAEBgAE+AeAAQA=","73":"b:AgBEBEQAiECJgAAAAAAAAEAAAAAEBgAE+AeAAQA=","76":"b:AgBEBEQAiECJgAAAAAAAAEAAAAAEBgAE+AeAAQA=","81":"b:AgBEBEQAiECJgAAAAAAAAEAAAAAEBgAE+AeAAQA=","85":"b:AgBEBEQAiECJgAAAAAAAAEAAAAAEBgAE+AeAAQA=","90":"b:AgBEBEQAiECJgAAAAAAAAEAAAAAEBgAE+AeAAQA=","101":"b:AgBEBEQAiECJgAAAAAAAAEAAAAAEBgAE+AeAAQA=","111":"b:AgBEBEQAiECJgAAAAAAAAEAAAAAEBgAE+AeAAQA="},"packages/cli/src/services/engine-v2-dispatcher.service.ts":{"51":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","52":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","69":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","80":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","95":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","110":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","135":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","188":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","214":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","261":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","270":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","271":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","274":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","275":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","285":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","303":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","315":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA="},"packages/cli/src/services/execution-metadata.service.ts":{"7":[32,1,2,3,4,5,6,144,161],"9":[32,1,2,3,4,5,6,144,161]},"packages/cli/src/services/frontend.service.ts":{"124":"b:/wr4+wMrpntStgnPXxgAAAAAgAIAAAAAAIAJAAA=","145":"b:/wr4+wMrpntStgnPXxgAAAAAgAIAAAAAAIAJAAA=","146":"b:/wr4+wMrpntStgnPXxgAAAAAgAIAAAAAAIAJAAA=","150":"b:/wr4+wMrpntStgnPXxgAAAAAgAIAAAAAAIAJAAA=","162":"b:/wr4+wMrpntStgnPXxgAAAAAgAIAAAAAAIAJAAA=","169":"b:/wr4+wMrpntStgnPXxgAAAAAgAIAAAAAAIAJAAA=","415":"b:/wr4+wMrpntStgnPXxgAAAAAgAIAAAAAAIAJAAA=","416":"b:/wr4+wMrpntStgnPXxgAAAAAgAIAAAAAAIAJAAA=","421":"b:/wr4+wMrpntStgnPXxgAAAAAgAIAAAAAAIAJAAA=","457":"b:/wr4+wMrpntStgnPXxgAAAAAgAIAAAAAAIAJAAA=","464":"b:/wr4+wMrpntStgnPXxgAAAAAgAIAAAAAAIAJAAA=","465":"b:/wr4+wMrpntStgnPXxgAAAAAgAIAAAAAAIAJAAA=","466":"b:/wr4+wMrpntStgnPXxgAAAAAgAIAAAAAAIAJAAA=","470":"b:/wr4+wMrpntStgnPXxgAAAAAgAIAAAAAAIAJAAA=","480":"b:/wr4+wMrpntStgnPXxgAAAAAgAIAAAAAAIAJAAA=","689":"b:/wr4+wMrpntStgnPXxgAAAAAgAIAAAAAAIAJAAA=","700":"b:/wr4+wMrpntStgnPXxgAAAAAgAIAAAAAAIAJAAA=","721":"b:/wr4+wMrpntStgnPXxgAAAAAgAIAAAAAAIAJAAA=","763":"b:/wr4+wMrpntStgnPXxgAAAAAgAIAAAAAAIAJAAA=","767":"b:/wr4+wMrpntStgnPXxgAAAAAgAIAAAAAAIAJAAA=","783":"b:/wr4+wMrpntStgnPXxgAAAAAgAIAAAAAAIAJAAA=","791":"b:/wr4+wMrpntStgnPXxgAAAAAgAIAAAAAAIAJAAA=","796":"b:/wr4+wMrpntStgnPXxgAAAAAgAIAAAAAAIAJAAA=","806":"b:/wr4+wMrpntStgnPXxgAAAAAgAIAAAAAAIAJAAA=","820":"b:/wr4+wMrpntStgnPXxgAAAAAgAIAAAAAAIAJAAA=","821":"b:/wr4+wMrpntStgnPXxgAAAAAgAIAAAAAAIAJAAA=","855":"b:/wr4+wMrpntStgnPXxgAAAAAgAIAAAAAAIAJAAA="},"packages/cli/src/services/jwt.service.ts":{"27":"b:/wv4/1cron/ZtwmyHwAIAAAAgFAAAAAA/98PBgA=","52":"b:/wv4/1cron/ZtwmyHwAIAAAAgFAAAAAA/98PBgA=","71":"b:/wv4/1cron/ZtwmyHwAIAAAAgFAAAAAA/98PBgA=","84":"b:/wv4/1cron/ZtwmyHwAIAAAAgFAAAAAA/98PBgA=","97":"b:/wv4/1cron/ZtwmyHwAIAAAAgFAAAAAA/98PBgA=","105":"b:/wv4/1cron/ZtwmyHwAIAAAAgFAAAAAA/98PBgA=","110":"b:/wv4/1cron/ZtwmyHwAIAAAAgFAAAAAA/98PBgA=","130":"b:/wv4/1cron/ZtwmyHwAIAAAAgFAAAAAA/98PBgA=","146":"b:/wv4/1cron/ZtwmyHwAIAAAAgFAAAAAA/98PBgA=","164":"b:/wv4/1cron/ZtwmyHwAIAAAAgFAAAAAA/98PBgA="},"packages/cli/src/services/last-active-at.service.ts":{"11":"b:/wv4/1cronvZtwmSHwAAAAAAgAAAAAAA/88GAAA=","16":"b:/wv4/1cronvZtwmSHwAAAAAAgAAAAAAA/88GAAA=","18":"b:/wv4/1cronvZtwmSHwAAAAAAgAAAAAAA/88GAAA=","25":"b:/wv4/1cronvZtwmSHwAAAAAAgAAAAAAA/88GAAA="},"packages/cli/src/services/naming.service.ts":{"6":"b:hgoF+AJqQBNCOAnHAuIAAAOAIADgAAQCAAAAAAA=","11":"b:hgoF+AJqQBNCOAnHAuIAAAOAIADgAAQCAAAAAAA=","15":"b:hgoF+AJqQBNCOAnHAuIAAAOAIADgAAQCAAAAAAA=","19":"b:hgoF+AJqQBNCOAnHAuIAAAOAIADgAAQCAAAAAAA=","28":"b:hgoF+AJqQBNCOAnHAuIAAAOAIADgAAQCAAAAAAA="},"packages/cli/src/services/ownership.service.ts":{"25":"b:/xtq/vc+43/rvw0HAEAMAAABAAAAACJB/wfQCQA=","37":"b:/xtq/vc+43/rvw0HAEAMAAABAAAAACJB/wfQCQA=","44":"b:/xtq/vc+43/rvw0HAEAMAAABAAAAACJB/wfQCQA=","54":"b:/xtq/vc+43/rvw0HAEAMAAABAAAAACJB/wfQCQA=","71":"b:/xtq/vc+43/rvw0HAEAMAAABAAAAACJB/wfQCQA=","75":"b:/xtq/vc+43/rvw0HAEAMAAABAAAAACJB/wfQCQA=","83":"b:/xtq/vc+43/rvw0HAEAMAAABAAAAACJB/wfQCQA=","88":"b:/xtq/vc+43/rvw0HAEAMAAABAAAAACJB/wfQCQA=","91":"b:/xtq/vc+43/rvw0HAEAMAAABAAAAACJB/wfQCQA=","106":"b:/xtq/vc+43/rvw0HAEAMAAABAAAAACJB/wfQCQA=","107":"b:/xtq/vc+43/rvw0HAEAMAAABAAAAACJB/wfQCQA=","123":"b:/xtq/vc+43/rvw0HAEAMAAABAAAAACJB/wfQCQA=","130":"b:/xtq/vc+43/rvw0HAEAMAAABAAAAACJB/wfQCQA=","139":"b:/xtq/vc+43/rvw0HAEAMAAABAAAAACJB/wfQCQA=","149":"b:/xtq/vc+43/rvw0HAEAMAAABAAAAACJB/wfQCQA=","191":"b:/xtq/vc+43/rvw0HAEAMAAABAAAAACJB/wfQCQA=","200":"b:/xtq/vc+43/rvw0HAEAMAAABAAAAACJB/wfQCQA=","204":"b:/xtq/vc+43/rvw0HAEAMAAABAAAAACJB/wfQCQA="},"packages/cli/src/services/password.utility.ts":{"8":"b:/wv4/1cLgnvZtwmSHwAAAAAAgAAAAAAA/98GAAA=","12":"b:/wv4/1cLgnvZtwmSHwAAAAAAgAAAAAAA/98GAAA="},"packages/cli/src/services/project.service.ee.ts":{"48":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","56":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","62":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","66":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","89":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","106":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","107":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","112":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","113":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","118":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","120":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","124":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","125":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","130":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","132":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","136":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","137":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","142":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","143":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","148":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","149":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","154":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","156":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","160":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","162":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","166":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","214":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","216":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","238":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","250":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","328":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","355":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","359":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","368":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","377":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","381":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","384":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","386":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","401":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","409":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","423":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","433":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","448":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","452":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","456":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","472":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","509":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","543":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","552":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","553":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","576":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","585":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","589":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","601":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","605":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","608":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","609":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","614":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","618":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","624":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","634":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","640":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","653":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","658":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","669":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","679":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","687":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","693":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","694":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","697":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","714":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","732":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","738":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","756":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","760":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","775":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","785":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","790":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","803":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","809":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","813":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","821":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","822":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","823":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","826":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","831":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","833":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","837":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","849":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","857":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","878":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","884":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","892":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","900":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","904":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","911":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","921":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","936":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","953":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","975":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","978":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","984":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","987":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","1020":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","1033":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","1042":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","1046":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","1058":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","1068":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","1072":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","1082":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","1096":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","1101":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","1106":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA=","1117":"b:/wv6//f7qn/7v8nfH4AGAAABgHMAAABA/4eoAAA="},"packages/cli/src/services/tag.service.ts":{"14":"b:jw4F/Eo6ADNIuFlDAAAAAJAAGAAAAoJkAAAAAAA=","20":"b:jw4F/Eo6ADNIuFlDAAAAAJAAGAAAAoJkAAAAAAA=","26":"b:jw4F/Eo6ADNIuFlDAAAAAJAAGAAAAoJkAAAAAAA=","46":"b:jw4F/Eo6ADNIuFlDAAAAAJAAGAAAAoJkAAAAAAA=","49":"b:jw4F/Eo6ADNIuFlDAAAAAJAAGAAAAoJkAAAAAAA=","53":"b:jw4F/Eo6ADNIuFlDAAAAAJAAGAAAAoJkAAAAAAA=","63":"b:jw4F/Eo6ADNIuFlDAAAAAJAAGAAAAoJkAAAAAAA=","82":"b:jw4F/Eo6ADNIuFlDAAAAAJAAGAAAAoJkAAAAAAA=","95":"b:jw4F/Eo6ADNIuFlDAAAAAJAAGAAAAoJkAAAAAAA=","101":"b:jw4F/Eo6ADNIuFlDAAAAAJAAGAAAAoJkAAAAAAA=","106":"b:jw4F/Eo6ADNIuFlDAAAAAJAAGAAAAoJkAAAAAAA=","111":"b:jw4F/Eo6ADNIuFlDAAAAAJAAGAAAAoJkAAAAAAA=","119":"b:jw4F/Eo6ADNIuFlDAAAAAJAAGAAAAoJkAAAAAAA=","133":"b:jw4F/Eo6ADNIuFlDAAAAAJAAGAAAAoJkAAAAAAA=","134":"b:jw4F/Eo6ADNIuFlDAAAAAJAAGAAAAoJkAAAAAAA=","139":"b:jw4F/Eo6ADNIuFlDAAAAAJAAGAAAAoJkAAAAAAA=","148":"b:jw4F/Eo6ADNIuFlDAAAAAJAAGAAAAoJkAAAAAAA=","150":"b:jw4F/Eo6ADNIuFlDAAAAAJAAGAAAAoJkAAAAAAA=","155":"b:jw4F/Eo6ADNIuFlDAAAAAJAAGAAAAoJkAAAAAAA="},"packages/cli/src/services/user.service.ts":{"58":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","77":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","87":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","91":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","103":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","115":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","126":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","132":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","137":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","180":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","183":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","184":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","189":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","200":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","210":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","283":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","284":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","288":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","290":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","292":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","304":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","310":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","312":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","332":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","340":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","343":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","359":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","362":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","452":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","481":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","496":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","502":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","516":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","543":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","560":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","630":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","650":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","670":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","713":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","721":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","726":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA=","731":"b:/1v//3cron/7vwn/nwAAAAAAgEYAAGAI/99OBAA="},"packages/cli/src/services/workflow-statistics.service.ts":{"33":"b:fxBOXnUg4WGJsz4EgAAIAEAAAAAAAGII+wfYIQA=","69":"b:fxBOXnUg4WGJsz4EgAAIAEAAAAAAAGII+wfYIQA=","84":"b:fxBOXnUg4WGJsz4EgAAIAEAAAAAAAGII+wfYIQA=","88":"b:fxBOXnUg4WGJsz4EgAAIAEAAAAAAAGII+wfYIQA=","91":"b:fxBOXnUg4WGJsz4EgAAIAEAAAAAAAGII+wfYIQA=","99":"b:fxBOXnUg4WGJsz4EgAAIAEAAAAAAAGII+wfYIQA=","122":"b:fxBOXnUg4WGJsz4EgAAIAEAAAAAAAGII+wfYIQA=","151":"b:fxBOXnUg4WGJsz4EgAAIAEAAAAAAAGII+wfYIQA=","204":"b:fxBOXnUg4WGJsz4EgAAIAEAAAAAAAGII+wfYIQA=","224":"b:fxBOXnUg4WGJsz4EgAAIAEAAAAAAAGII+wfYIQA=","261":"b:fxBOXnUg4WGJsz4EgAAIAEAAAAAAAGII+wfYIQA=","273":"b:fxBOXnUg4WGJsz4EgAAIAEAAAAAAAGII+wfYIQA=","319":"b:fxBOXnUg4WGJsz4EgAAIAEAAAAAAAGII+wfYIQA=","350":"b:fxBOXnUg4WGJsz4EgAAIAEAAAAAAAGII+wfYIQA="},"packages/cli/src/sso.ee/sso-helpers.ts":{"15":"b:/wv4/1cLgn/5twmyHwAAAAAAgEAAAAAA/98GBAA=","29":"b:/wv4/1cLgn/5twmyHwAAAAAAgEAAAAAA/98GBAA=","48":"b:/wv4/1cLgn/5twmyHwAAAAAAgEAAAAAA/98GBAA=","52":"b:/wv4/1cLgn/5twmyHwAAAAAAgEAAAAAA/98GBAA=","59":"b:/wv4/1cLgn/5twmyHwAAAAAAgEAAAAAA/98GBAA=","63":"b:/wv4/1cLgn/5twmyHwAAAAAAgEAAAAAA/98GBAA=","67":"b:/wv4/1cLgn/5twmyHwAAAAAAgEAAAAAA/98GBAA=","71":"b:/wv4/1cLgn/5twmyHwAAAAAAgEAAAAAA/98GBAA=","75":"b:/wv4/1cLgn/5twmyHwAAAAAAgEAAAAAA/98GBAA=","79":"b:/wv4/1cLgn/5twmyHwAAAAAAgEAAAAAA/98GBAA=","83":"b:/wv4/1cLgn/5twmyHwAAAAAAgEAAAAAA/98GBAA=","91":"b:/wv4/1cLgn/5twmyHwAAAAAAgEAAAAAA/98GBAA=","96":"b:/wv4/1cLgn/5twmyHwAAAAAAgEAAAAAA/98GBAA=","107":"b:/wv4/1cLgn/5twmyHwAAAAAAgEAAAAAA/98GBAA=","111":"b:/wv4/1cLgn/5twmyHwAAAAAAgEAAAAAA/98GBAA="},"packages/cli/src/task-runners/task-broker/task-broker-ws-server.ts":{"27":"b:Xwbs/hQrCntaojjDuAUgAAAAgABABAAAAIIUAAA=","60":"b:Xwbs/hQrCntaojjDuAUgAAAAgABABAAAAIIUAAA=","70":"b:Xwbs/hQrCntaojjDuAUgAAAAgABABAAAAIIUAAA=","75":"b:Xwbs/hQrCntaojjDuAUgAAAAgABABAAAAIIUAAA=","84":"b:Xwbs/hQrCntaojjDuAUgAAAAgABABAAAAIIUAAA=","92":"b:Xwbs/hQrCntaojjDuAUgAAAAgABABAAAAIIUAAA=","97":"b:Xwbs/hQrCntaojjDuAUgAAAAgABABAAAAIIUAAA=","120":"b:Xwbs/hQrCntaojjDuAUgAAAAgABABAAAAIIUAAA=","130":"b:Xwbs/hQrCntaojjDuAUgAAAAgABABAAAAIIUAAA=","141":"b:Xwbs/hQrCntaojjDuAUgAAAAgABABAAAAIIUAAA=","145":"b:Xwbs/hQrCntaojjDuAUgAAAAgABABAAAAIIUAAA=","149":"b:Xwbs/hQrCntaojjDuAUgAAAAgABABAAAAIIUAAA=","153":"b:Xwbs/hQrCntaojjDuAUgAAAAgABABAAAAIIUAAA=","159":"b:Xwbs/hQrCntaojjDuAUgAAAAgABABAAAAIIUAAA=","192":"b:Xwbs/hQrCntaojjDuAUgAAAAgABABAAAAIIUAAA=","210":"b:Xwbs/hQrCntaojjDuAUgAAAAgABABAAAAIIUAAA=","220":"b:Xwbs/hQrCntaojjDuAUgAAAAgABABAAAAIIUAAA=","263":"b:Xwbs/hQrCntaojjDuAUgAAAAgABABAAAAIIUAAA=","273":"b:Xwbs/hQrCntaojjDuAUgAAAAgABABAAAAIIUAAA=","281":"b:Xwbs/hQrCntaojjDuAUgAAAAgABABAAAAIIUAAA=","292":"b:Xwbs/hQrCntaojjDuAUgAAAAgABABAAAAIIUAAA=","300":"b:Xwbs/hQrCntaojjDuAUgAAAAgABABAAAAIIUAAA=","305":"b:Xwbs/hQrCntaojjDuAUgAAAAgABABAAAAIIUAAA=","315":"b:Xwbs/hQrCntaojjDuAUgAAAAgABABAAAAIIUAAA="},"packages/cli/src/utils/get-item-count-by-connection-type.ts":{"4":"b:DwBMWAEg4WEAsD5EAAAAABAAAAAAAAAAAAAAAAA=","15":"b:DwBMWAEg4WEAsD5EAAAAABAAAAAAAAAAAAAAAAA="},"packages/cli/src/utils/request-path.ts":{"9":"b:/wr4+wMrontStgnPHwAAAAAAgAIAAAAAAIAIAAA=","17":"b:/wr4+wMrontStgnPHwAAAAAAgAIAAAAAAIAIAAA=","22":"b:/wr4+wMrontStgnPHwAAAAAAgAIAAAAAAIAIAAA=","29":"b:/wr4+wMrontStgnPHwAAAAAAgAIAAAAAAIAIAAA=","30":"b:/wr4+wMrontStgnPHwAAAAAAgAIAAAAAAIAIAAA=","39":"b:/wr4+wMrontStgnPHwAAAAAAgAIAAAAAAIAIAAA=","50":"b:/wr4+wMrontStgnPHwAAAAAAgAIAAAAAAIAIAAA="},"packages/cli/src/utils/strapi-utils.ts":{"57":"b:jwoA+AMqoHNAvgnHAiAAAAAAAAAAAAAAAAAAAAA=","69":"b:jwoA+AMqoHNAvgnHAiAAAAAAAAAAAAAAAAAAAAA=","79":"b:jwoA+AMqoHNAvgnHAiAAAAAAAAAAAAAAAAAAAAA=","135":"b:jwoA+AMqoHNAvgnHAiAAAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/utils.ts":{"10":"b:/79t/vX/93/Lv/8fnRgMCsAAAFACAGbI/wf2IQA=","19":"b:/79t/vX/93/Lv/8fnRgMCsAAAFACAGbI/wf2IQA=","28":"b:/79t/vX/93/Lv/8fnRgMCsAAAFACAGbI/wf2IQA=","32":"b:/79t/vX/93/Lv/8fnRgMCsAAAFACAGbI/wf2IQA=","33":"b:/79t/vX/93/Lv/8fnRgMCsAAAFACAGbI/wf2IQA=","35":"b:/79t/vX/93/Lv/8fnRgMCsAAAFACAGbI/wf2IQA=","40":"b:/79t/vX/93/Lv/8fnRgMCsAAAFACAGbI/wf2IQA=","60":"b:/79t/vX/93/Lv/8fnRgMCsAAAFACAGbI/wf2IQA=","64":"b:/79t/vX/93/Lv/8fnRgMCsAAAFACAGbI/wf2IQA=","66":"b:/79t/vX/93/Lv/8fnRgMCsAAAFACAGbI/wf2IQA=","71":"b:/79t/vX/93/Lv/8fnRgMCsAAAFACAGbI/wf2IQA=","76":"b:/79t/vX/93/Lv/8fnRgMCsAAAFACAGbI/wf2IQA=","82":"b:/79t/vX/93/Lv/8fnRgMCsAAAFACAGbI/wf2IQA=","95":"b:/79t/vX/93/Lv/8fnRgMCsAAAFACAGbI/wf2IQA=","97":"b:/79t/vX/93/Lv/8fnRgMCsAAAFACAGbI/wf2IQA=","102":"b:/79t/vX/93/Lv/8fnRgMCsAAAFACAGbI/wf2IQA=","122":"b:/79t/vX/93/Lv/8fnRgMCsAAAFACAGbI/wf2IQA=","129":"b:/79t/vX/93/Lv/8fnRgMCsAAAFACAGbI/wf2IQA=","149":"b:/79t/vX/93/Lv/8fnRgMCsAAAFACAGbI/wf2IQA=","161":"b:/79t/vX/93/Lv/8fnRgMCsAAAFACAGbI/wf2IQA=","165":"b:/79t/vX/93/Lv/8fnRgMCsAAAFACAGbI/wf2IQA=","173":"b:/79t/vX/93/Lv/8fnRgMCsAAAFACAGbI/wf2IQA="},"packages/cli/src/wait-tracker.ts":{"37":"b:RgJMjJCKAFNSMAgDWLogAAAAAAAABAABAgAAoQA=","54":"b:RgJMjJCKAFNSMAgDWLogAAAAAAAABAABAgAAoQA=","67":"b:RgJMjJCKAFNSMAgDWLogAAAAAAAABAABAgAAoQA=","72":"b:RgJMjJCKAFNSMAgDWLogAAAAAAAABAABAgAAoQA=","76":"b:RgJMjJCKAFNSMAgDWLogAAAAAAAABAABAgAAoQA=","81":"b:RgJMjJCKAFNSMAgDWLogAAAAAAAABAABAgAAoQA=","83":"b:RgJMjJCKAFNSMAgDWLogAAAAAAAABAABAgAAoQA=","94":"b:RgJMjJCKAFNSMAgDWLogAAAAAAAABAABAgAAoQA=","103":"b:RgJMjJCKAFNSMAgDWLogAAAAAAAABAABAgAAoQA=","116":"b:RgJMjJCKAFNSMAgDWLogAAAAAAAABAABAgAAoQA=","117":"b:RgJMjJCKAFNSMAgDWLogAAAAAAAABAABAgAAoQA=","137":"b:RgJMjJCKAFNSMAgDWLogAAAAAAAABAABAgAAoQA=","145":"b:RgJMjJCKAFNSMAgDWLogAAAAAAAABAABAgAAoQA=","215":"b:RgJMjJCKAFNSMAgDWLogAAAAAAAABAABAgAAoQA=","254":"b:RgJMjJCKAFNSMAgDWLogAAAAAAAABAABAgAAoQA=","263":"b:RgJMjJCKAFNSMAgDWLogAAAAAAAABAABAgAAoQA=","283":"b:RgJMjJCKAFNSMAgDWLogAAAAAAAABAABAgAAoQA=","289":"b:RgJMjJCKAFNSMAgDWLogAAAAAAAABAABAgAAoQA=","291":"b:RgJMjJCKAFNSMAgDWLogAAAAAAAABAABAgAAoQA=","312":"b:RgJMjJCKAFNSMAgDWLogAAAAAAAABAABAgAAoQA=","347":"b:RgJMjJCKAFNSMAgDWLogAAAAAAAABAABAgAAoQA=","357":"b:RgJMjJCKAFNSMAgDWLogAAAAAAAABAABAgAAoQA=","365":"b:RgJMjJCKAFNSMAgDWLogAAAAAAAABAABAgAAoQA=","412":"b:RgJMjJCKAFNSMAgDWLogAAAAAAAABAABAgAAoQA=","415":"b:RgJMjJCKAFNSMAgDWLogAAAAAAAABAABAgAAoQA=","429":"b:RgJMjJCKAFNSMAgDWLogAAAAAAAABAABAgAAoQA=","433":"b:RgJMjJCKAFNSMAgDWLogAAAAAAAABAABAgAAoQA="},"packages/cli/src/webhooks/engine-v2-webhooks.ts":{"71":"b:DhAEBGEAQEGIAAAEAAAIAAAAAAAAAAIAAwDQAQA=","77":"b:DhAEBGEAQEGIAAAEAAAIAAAAAAAAAAIAAwDQAQA=","96":"b:DhAEBGEAQEGIAAAEAAAIAAAAAAAAAAIAAwDQAQA=","144":"b:DhAEBGEAQEGIAAAEAAAIAAAAAAAAAAIAAwDQAQA=","152":"b:DhAEBGEAQEGIAAAEAAAIAAAAAAAAAAIAAwDQAQA="},"packages/cli/src/webhooks/node-type-matcher.ts":{"5":"b:DhAEAGEAQEGIAAAEAAAIAAAAAAAAAAIAAwDQAQA="},"packages/cli/src/webhooks/test-webhook-registrations.service.ts":{"41":"b:DgAEAAEAQAEAAAAAgAAIAAAAAAACBgKAAAAAAAA=","52":"b:DgAEAAEAQAEAAAAAgAAIAAAAAAACBgKAAAAAAAA=","60":"b:DgAEAAEAQAEAAAAAgAAIAAAAAAACBgKAAAAAAAA=","67":"b:DgAEAAEAQAEAAAAAgAAIAAAAAAACBgKAAAAAAAA=","107":"b:DgAEAAEAQAEAAAAAgAAIAAAAAAACBgKAAAAAAAA=","116":"b:DgAEAAEAQAEAAAAAgAAIAAAAAAACBgKAAAAAAAA=","122":"b:DgAEAAEAQAEAAAAAgAAIAAAAAAACBgKAAAAAAAA=","130":"b:DgAEAAEAQAEAAAAAgAAIAAAAAAACBgKAAAAAAAA=","140":"b:DgAEAAEAQAEAAAAAgAAIAAAAAAACBgKAAAAAAAA=","155":"b:DgAEAAEAQAEAAAAAgAAIAAAAAAACBgKAAAAAAAA=","164":"b:DgAEAAEAQAEAAAAAgAAIAAAAAAACBgKAAAAAAAA="},"packages/cli/src/webhooks/test-webhooks.ts":{"65":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA=","82":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA=","112":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA=","167":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA=","182":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA=","246":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA=","269":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA=","283":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA=","307":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA=","309":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA=","312":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA=","316":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA=","323":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA=","326":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA=","339":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA=","358":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA=","377":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA=","384":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA=","396":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA=","447":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA=","450":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA=","463":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA=","474":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA=","571":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA=","599":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA=","606":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA=","620":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA=","628":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA=","629":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA=","638":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA=","650":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA=","657":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA=","693":"b:DwBEWhUw7GEAszQAgAAIAAAAAAACBgKAAAAAAAA="},"packages/cli/src/webhooks/webhook-execution-context.ts":{"21":"b:DhAEBGEAQEGIAAAEAAAIAAAAAAAAAAIAAwDQAQA=","32":"b:DhAEBGEAQEGIAAAEAAAIAAAAAAAAAAIAAwDQAQA=","53":"b:DhAEBGEAQEGIAAAEAAAIAAAAAAAAAAIAAwDQAQA=","80":"b:DhAEBGEAQEGIAAAEAAAIAAAAAAAAAAIAAwDQAQA="},"packages/cli/src/webhooks/webhook-helpers.ts":{"146":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","152":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","156":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","176":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","193":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","206":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","262":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","272":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","282":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","323":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","342":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","349":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","354":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","357":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","369":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","392":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","428":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","435":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","453":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","486":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","498":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","507":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","524":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","545":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","553":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","624":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","663":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","706":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","725":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","790":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","802":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","811":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","848":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","853":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","869":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","886":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","923":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","957":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","958":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","972":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","1036":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","1236":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","1239":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","1374":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","1399":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","1466":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","1557":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","1614":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","1667":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","1678":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","1694":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","1739":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","1764":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE=","1780":"b:DxFGXnUg5GGJvyQEgAAIAAAAAQAAAAJA+wfYQwE="},"packages/cli/src/webhooks/webhook-last-node-response-extractor.ts":{"30":[32,1,3,214,37,212,193,56,144,18,177],"72":[32,1,3,214,37,212,193,56,144,18,177],"117":[32,1,3,214,37,212,193,56,144,18,177],"184":[32,1,3,214,37,212,193,56,144,18,177]},"packages/cli/src/webhooks/webhook-request-handler.ts":{"34":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAACAAIAAwDYJQA=","43":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAACAAIAAwDYJQA=","97":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAACAAIAAwDYJQA=","113":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAACAAIAAwDYJQA=","122":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAACAAIAAwDYJQA=","125":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAACAAIAAwDYJQA=","138":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAACAAIAAwDYJQA=","144":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAACAAIAAwDYJQA=","153":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAACAAIAAwDYJQA=","183":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAACAAIAAwDYJQA=","237":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAACAAIAAwDYJQA=","245":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAACAAIAAwDYJQA=","284":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAACAAIAAwDYJQA=","291":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAACAAIAAwDYJQA="},"packages/cli/src/webhooks/webhook-responder.ts":{"20":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAAAAAIAAwDYQQE=","23":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAAAAAIAAwDYQQE=","28":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAAAAAIAAwDYQQE=","36":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAAAAAIAAwDYQQE=","42":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAAAAAIAAwDYQQE=","51":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAAAAAIAAwDYQQE="},"packages/cli/src/webhooks/webhook-response-headers.ts":{"33":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAAAAAIAAwDQAQE=","37":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAAAAAIAAwDQAQE=","44":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAAAAAIAAwDQAQE=","66":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAAAAAIAAwDQAQE=","73":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAAAAAIAAwDQAQE=","82":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAAAAAIAAwDQAQE=","90":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAAAAAIAAwDQAQE=","99":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAAAAAIAAwDQAQE="},"packages/cli/src/webhooks/webhook-response.ts":{"37":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAAAAAIAAwDQAQA=","41":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAAAAAIAAwDQAQA=","45":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAAAAAIAAwDQAQA=","49":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAAAAAIAAwDQAQA=","53":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAAAAAIAAwDQAQA=","59":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAAAAAIAAwDQAQA=","72":"b:DhAEBGEAQEGIAAAEAAAIAEAAAAAAAAIAAwDQAQA="},"packages/cli/src/webhooks/webhook.service.ts":{"35":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","42":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","47":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","50":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","54":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","66":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","88":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","101":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","111":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","125":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","129":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","146":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","156":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","163":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","165":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","177":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","179":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","180":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","201":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","215":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","219":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","256":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","268":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","275":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","280":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","284":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","291":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","295":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","300":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","301":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","306":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","310":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","321":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","332":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","334":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","343":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","344":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","348":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","369":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","370":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","377":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","470":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","497":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","518":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","532":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","581":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","583":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","587":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","592":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","611":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","620":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","652":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA=","683":"b:DxFGXnUw5GGJvyQEgAAIAEAAAAAAAkLK+wfZBwA="},"packages/cli/src/workflow-execute-additional-data.ts":{"83":"b:fxVMXnUi6XGJvzpGAEAAAEQAAABABmBA/wdYoQE=","128":"b:fxVMXnUi6XGJvzpGAEAAAEQAAABABmBA/wdYoQE=","179":"b:fxVMXnUi6XGJvzpGAEAAAEQAAABABmBA/wdYoQE=","197":"b:fxVMXnUi6XGJvzpGAEAAAEQAAABABmBA/wdYoQE=","257":"b:fxVMXnUi6XGJvzpGAEAAAEQAAABABmBA/wdYoQE=","290":"b:fxVMXnUi6XGJvzpGAEAAAEQAAABABmBA/wdYoQE=","307":"b:fxVMXnUi6XGJvzpGAEAAAEQAAABABmBA/wdYoQE=","392":"b:fxVMXnUi6XGJvzpGAEAAAEQAAABABmBA/wdYoQE=","404":"b:fxVMXnUi6XGJvzpGAEAAAEQAAABABmBA/wdYoQE=","515":"b:fxVMXnUi6XGJvzpGAEAAAEQAAABABmBA/wdYoQE=","527":"b:fxVMXnUi6XGJvzpGAEAAAEQAAABABmBA/wdYoQE=","541":"b:fxVMXnUi6XGJvzpGAEAAAEQAAABABmBA/wdYoQE=","542":"b:fxVMXnUi6XGJvzpGAEAAAEQAAABABmBA/wdYoQE=","556":"b:fxVMXnUi6XGJvzpGAEAAAEQAAABABmBA/wdYoQE=","575":"b:fxVMXnUi6XGJvzpGAEAAAEQAAABABmBA/wdYoQE=","801":"b:fxVMXnUi6XGJvzpGAEAAAEQAAABABmBA/wdYoQE=","811":"b:fxVMXnUi6XGJvzpGAEAAAEQAAABABmBA/wdYoQE=","850":"b:fxVMXnUi6XGJvzpGAEAAAEQAAABABmBA/wdYoQE=","857":"b:fxVMXnUi6XGJvzpGAEAAAEQAAABABmBA/wdYoQE=","919":"b:fxVMXnUi6XGJvzpGAEAAAEQAAABABmBA/wdYoQE=","925":"b:fxVMXnUi6XGJvzpGAEAAAEQAAABABmBA/wdYoQE=","935":"b:fxVMXnUi6XGJvzpGAEAAAEQAAABABmBA/wdYoQE=","972":"b:fxVMXnUi6XGJvzpGAEAAAEQAAABABmBA/wdYoQE=","975":"b:fxVMXnUi6XGJvzpGAEAAAEQAAABABmBA/wdYoQE=","978":"b:fxVMXnUi6XGJvzpGAEAAAEQAAABABmBA/wdYoQE="},"packages/cli/src/workflow-helpers.ts":{"11":"b:/x9v/n8u43vJvy8XAAAAAEAEASBAGGJI/wfYgQE=","51":"b:/x9v/n8u43vJvy8XAAAAAEAEASBAGGJI/wfYgQE=","78":"b:/x9v/n8u43vJvy8XAAAAAEAEASBAGGJI/wfYgQE=","82":"b:/x9v/n8u43vJvy8XAAAAAEAEASBAGGJI/wfYgQE=","94":"b:/x9v/n8u43vJvy8XAAAAAEAEASBAGGJI/wfYgQE=","121":"b:/x9v/n8u43vJvy8XAAAAAEAEASBAGGJI/wfYgQE=","150":"b:/x9v/n8u43vJvy8XAAAAAEAEASBAGGJI/wfYgQE=","188":"b:/x9v/n8u43vJvy8XAAAAAEAEASBAGGJI/wfYgQE=","196":"b:/x9v/n8u43vJvy8XAAAAAEAEASBAGGJI/wfYgQE=","202":"b:/x9v/n8u43vJvy8XAAAAAEAEASBAGGJI/wfYgQE=","225":"b:/x9v/n8u43vJvy8XAAAAAEAEASBAGGJI/wfYgQE=","262":"b:/x9v/n8u43vJvy8XAAAAAEAEASBAGGJI/wfYgQE=","267":"b:/x9v/n8u43vJvy8XAAAAAEAEASBAGGJI/wfYgQE=","398":"b:/x9v/n8u43vJvy8XAAAAAEAEASBAGGJI/wfYgQE=","419":"b:/x9v/n8u43vJvy8XAAAAAEAEASBAGGJI/wfYgQE=","448":"b:/x9v/n8u43vJvy8XAAAAAEAEASBAGGJI/wfYgQE=","575":"b:/x9v/n8u43vJvy8XAAAAAEAEASBAGGJI/wfYgQE=","597":"b:/x9v/n8u43vJvy8XAAAAAEAEASBAGGJI/wfYgQE="},"packages/cli/src/workflow-runner.ts":{"98":"b:fwBIXnUg4WGJsz4AgAAAAAAAAAAAEAAA+wfYAAE=","110":"b:fwBIXnUg4WGJsz4AgAAAAAAAAAAAEAAA+wfYAAE=","132":"b:fwBIXnUg4WGJsz4AgAAAAAAAAAAAEAAA+wfYAAE=","329":"b:fwBIXnUg4WGJsz4AgAAAAAAAAAAAEAAA+wfYAAE=","351":"b:fwBIXnUg4WGJsz4AgAAAAAAAAAAAEAAA+wfYAAE=","404":"b:fwBIXnUg4WGJsz4AgAAAAAAAAAAAEAAA+wfYAAE=","502":"b:fwBIXnUg4WGJsz4AgAAAAAAAAAAAEAAA+wfYAAE=","521":"b:fwBIXnUg4WGJsz4AgAAAAAAAAAAAEAAA+wfYAAE=","529":"b:fwBIXnUg4WGJsz4AgAAAAAAAAAAAEAAA+wfYAAE=","536":"b:fwBIXnUg4WGJsz4AgAAAAAAAAAAAEAAA+wfYAAE=","543":"b:fwBIXnUg4WGJsz4AgAAAAAAAAAAAEAAA+wfYAAE=","563":"b:fwBIXnUg4WGJsz4AgAAAAAAAAAAAEAAA+wfYAAE=","629":"b:fwBIXnUg4WGJsz4AgAAAAAAAAAAAEAAA+wfYAAE=","634":"b:fwBIXnUg4WGJsz4AgAAAAAAAAAAAEAAA+wfYAAE=","690":"b:fwBIXnUg4WGJsz4AgAAAAAAAAAAAEAAA+wfYAAE=","700":"b:fwBIXnUg4WGJsz4AgAAAAAAAAAAAEAAA+wfYAAE=","711":"b:fwBIXnUg4WGJsz4AgAAAAAAAAAAAEAAA+wfYAAE=","735":"b:fwBIXnUg4WGJsz4AgAAAAAAAAAAAEAAA+wfYAAE=","801":"b:fwBIXnUg4WGJsz4AgAAAAAAAAAAAEAAA+wfYAAE=","803":"b:fwBIXnUg4WGJsz4AgAAAAAAAAAAAEAAA+wfYAAE=","945":"b:fwBIXnUg4WGJsz4AgAAAAAAAAAAAEAAA+wfYAAE=","967":"b:fwBIXnUg4WGJsz4AgAAAAAAAAAAAEAAA+wfYAAE="},"packages/cli/src/workflows/deprecated-nodes-validation.service.ts":{"21":"b:/wto/ncuo3vJvy8TAAAAAAAEAQBAGAAA/wcAAAA=","28":"b:/wto/ncuo3vJvy8TAAAAAAAEAQBAGAAA/wcAAAA=","45":"b:/wto/ncuo3vJvy8TAAAAAAAEAQBAGAAA/wcAAAA=","48":"b:/wto/ncuo3vJvy8TAAAAAAAEAQBAGAAA/wcAAAA=","73":"b:/wto/ncuo3vJvy8TAAAAAAAEAQBAGAAA/wcAAAA=","104":"b:/wto/ncuo3vJvy8TAAAAAAAEAQBAGAAA/wcAAAA=","109":"b:/wto/ncuo3vJvy8TAAAAAAAEAQBAGAAA/wcAAAA=","115":"b:/wto/ncuo3vJvy8TAAAAAAAEAQBAGAAA/wcAAAA=","125":"b:/wto/ncuo3vJvy8TAAAAAAAEAQBAGAAA/wcAAAA=","126":"b:/wto/ncuo3vJvy8TAAAAAAAEAQBAGAAA/wcAAAA="},"packages/cli/src/workflows/error-workflow-validation.service.ts":{"36":"b:AgJItEAEA1EALwQAAAAAAIAFAQBAGAAACAAAAAA=","49":"b:AgJItEAEA1EALwQAAAAAAIAFAQBAGAAACAAAAAA=","77":"b:AgJItEAEA1EALwQAAAAAAIAFAQBAGAAACAAAAAA=","86":"b:AgJItEAEA1EALwQAAAAAAIAFAQBAGAAACAAAAAA=","130":"b:AgJItEAEA1EALwQAAAAAAIAFAQBAGAAACAAAAAA="},"packages/cli/src/workflows/publication/workflow-publication-outbox-consumer.ts":{"69":"b:fxv6/3E7onvbvgmPHwAAAEAAgAAAAEBK+4fcCQA=","83":"b:fxv6/3E7onvbvgmPHwAAAEAAgAAAAEBK+4fcCQA=","84":"b:fxv6/3E7onvbvgmPHwAAAEAAgAAAAEBK+4fcCQA=","86":"b:fxv6/3E7onvbvgmPHwAAAEAAgAAAAEBK+4fcCQA=","90":"b:fxv6/3E7onvbvgmPHwAAAEAAgAAAAEBK+4fcCQA=","98":"b:fxv6/3E7onvbvgmPHwAAAEAAgAAAAEBK+4fcCQA=","107":"b:fxv6/3E7onvbvgmPHwAAAEAAgAAAAEBK+4fcCQA=","118":"b:fxv6/3E7onvbvgmPHwAAAEAAgAAAAEBK+4fcCQA=","134":"b:fxv6/3E7onvbvgmPHwAAAEAAgAAAAEBK+4fcCQA=","158":"b:fxv6/3E7onvbvgmPHwAAAEAAgAAAAEBK+4fcCQA=","162":"b:fxv6/3E7onvbvgmPHwAAAEAAgAAAAEBK+4fcCQA=","183":"b:fxv6/3E7onvbvgmPHwAAAEAAgAAAAEBK+4fcCQA=","203":"b:fxv6/3E7onvbvgmPHwAAAEAAgAAAAEBK+4fcCQA=","218":"b:fxv6/3E7onvbvgmPHwAAAEAAgAAAAEBK+4fcCQA=","242":"b:fxv6/3E7onvbvgmPHwAAAEAAgAAAAEBK+4fcCQA=","252":"b:fxv6/3E7onvbvgmPHwAAAEAAgAAAAEBK+4fcCQA=","267":"b:fxv6/3E7onvbvgmPHwAAAEAAgAAAAEBK+4fcCQA=","281":"b:fxv6/3E7onvbvgmPHwAAAEAAgAAAAEBK+4fcCQA=","289":"b:fxv6/3E7onvbvgmPHwAAAEAAgAAAAEBK+4fcCQA=","290":"b:fxv6/3E7onvbvgmPHwAAAEAAgAAAAEBK+4fcCQA=","311":"b:fxv6/3E7onvbvgmPHwAAAEAAgAAAAEBK+4fcCQA=","322":"b:fxv6/3E7onvbvgmPHwAAAEAAgAAAAEBK+4fcCQA=","326":"b:fxv6/3E7onvbvgmPHwAAAEAAgAAAAEBK+4fcCQA=","371":"b:fxv6/3E7onvbvgmPHwAAAEAAgAAAAEBK+4fcCQA=","454":"b:fxv6/3E7onvbvgmPHwAAAEAAgAAAAEBK+4fcCQA=","482":"b:fxv6/3E7onvbvgmPHwAAAEAAgAAAAEBK+4fcCQA=","492":"b:fxv6/3E7onvbvgmPHwAAAEAAgAAAAEBK+4fcCQA="},"packages/cli/src/workflows/publication/workflow-publication-reconciler.service.ts":{"67":"b:/wr4/xMrontevgmHHwAAAAAAgAAAAEACQIcNCQg=","86":"b:/wr4/xMrontevgmHHwAAAAAAgAAAAEACQIcNCQg=","99":"b:/wr4/xMrontevgmHHwAAAAAAgAAAAEACQIcNCQg=","105":"b:/wr4/xMrontevgmHHwAAAAAAgAAAAEACQIcNCQg=","113":"b:/wr4/xMrontevgmHHwAAAAAAgAAAAEACQIcNCQg=","119":"b:/wr4/xMrontevgmHHwAAAAAAgAAAAEACQIcNCQg=","135":"b:/wr4/xMrontevgmHHwAAAAAAgAAAAEACQIcNCQg=","145":"b:/wr4/xMrontevgmHHwAAAAAAgAAAAEACQIcNCQg=","216":"b:/wr4/xMrontevgmHHwAAAAAAgAAAAEACQIcNCQg=","222":"b:/wr4/xMrontevgmHHwAAAAAAgAAAAEACQIcNCQg=","228":"b:/wr4/xMrontevgmHHwAAAAAAgAAAAEACQIcNCQg=","233":"b:/wr4/xMrontevgmHHwAAAAAAgAAAAEACQIcNCQg=","250":"b:/wr4/xMrontevgmHHwAAAAAAgAAAAEACQIcNCQg=","277":"b:/wr4/xMrontevgmHHwAAAAAAgAAAAEACQIcNCQg=","285":"b:/wr4/xMrontevgmHHwAAAAAAgAAAAEACQIcNCQg=","292":"b:/wr4/xMrontevgmHHwAAAAAAgAAAAEACQIcNCQg=","309":"b:/wr4/xMrontevgmHHwAAAAAAgAAAAEACQIcNCQg="},"packages/cli/src/workflows/publication/workflow-publication-status.service.ts":{"12":"b:Dwts+IO/o39AvslPHBgECJAAAAAAAEBIACABAAA=","27":"b:Dwts+IO/o39AvslPHBgECJAAAAAAAEBIACABAAA=","36":"b:Dwts+IO/o39AvslPHBgECJAAAAAAAEBIACABAAA=","46":"b:Dwts+IO/o39AvslPHBgECJAAAAAAAEBIACABAAA=","60":"b:Dwts+IO/o39AvslPHBgECJAAAAAAAEBIACABAAA=","73":"b:Dwts+IO/o39AvslPHBgECJAAAAAAAEBIACABAAA=","79":"b:Dwts+IO/o39AvslPHBgECJAAAAAAAEBIACABAAA=","87":"b:Dwts+IO/o39AvslPHBgECJAAAAAAAEBIACABAAA="},"packages/cli/src/workflows/utils.ts":{"19":"b:/wtm/nc6rXvJvz8TAEAAAAAAAAAABAAA/wcAAAA=","26":"b:/wtm/nc6rXvJvz8TAEAAAAAAAAAABAAA/wcAAAA=","27":"b:/wtm/nc6rXvJvz8TAEAAAAAAAAAABAAA/wcAAAA=","35":"b:/wtm/nc6rXvJvz8TAEAAAAAAAAAABAAA/wcAAAA=","41":"b:/wtm/nc6rXvJvz8TAEAAAAAAAAAABAAA/wcAAAA=","46":"b:/wtm/nc6rXvJvz8TAEAAAAAAAAAABAAA/wcAAAA=","56":"b:/wtm/nc6rXvJvz8TAEAAAAAAAAAABAAA/wcAAAA="},"packages/cli/src/workflows/workflow-creation.service.ts":{"54":"b:jwtm/ncqoXvJvwkTAAAAAIAAAAAAAAAA/wcAAAA=","81":"b:jwtm/ncqoXvJvwkTAAAAAIAAAAAAAAAA/wcAAAA=","100":"b:jwtm/ncqoXvJvwkTAAAAAIAAAAAAAAAA/wcAAAA=","104":"b:jwtm/ncqoXvJvwkTAAAAAIAAAAAAAAAA/wcAAAA=","105":"b:jwtm/ncqoXvJvwkTAAAAAIAAAAAAAAAA/wcAAAA=","107":"b:jwtm/ncqoXvJvwkTAAAAAIAAAAAAAAAA/wcAAAA=","119":"b:jwtm/ncqoXvJvwkTAAAAAIAAAAAAAAAA/wcAAAA=","141":"b:jwtm/ncqoXvJvwkTAAAAAIAAAAAAAAAA/wcAAAA=","246":"b:jwtm/ncqoXvJvwkTAAAAAIAAAAAAAAAA/wcAAAA=","315":"b:jwtm/ncqoXvJvwkTAAAAAIAAAAAAAAAA/wcAAAA=","418":"b:jwtm/ncqoXvJvwkTAAAAAIAAAAAAAAAA/wcAAAA=","430":"b:jwtm/ncqoXvJvwkTAAAAAIAAAAAAAAAA/wcAAAA=","435":"b:jwtm/ncqoXvJvwkTAAAAAIAAAAAAAAAA/wcAAAA=","446":"b:jwtm/ncqoXvJvwkTAAAAAIAAAAAAAAAA/wcAAAA=","489":"b:jwtm/ncqoXvJvwkTAAAAAIAAAAAAAAAA/wcAAAA="},"packages/cli/src/workflows/workflow-entity-mapper.ts":{"24":"b:jwtm/ncqoXvJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","31":"b:jwtm/ncqoXvJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","32":"b:jwtm/ncqoXvJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/cli/src/workflows/workflow-execution.service.ts":{"63":"b:fwBEWhUw7GEBsz4AAEAIACQEAAAAdAMA+AcAAAg=","84":"b:fwBEWhUw7GEBsz4AAEAIACQEAAAAdAMA+AcAAAg=","134":"b:fwBEWhUw7GEBsz4AAEAIACQEAAAAdAMA+AcAAAg=","277":"b:fwBEWhUw7GEBsz4AAEAIACQEAAAAdAMA+AcAAAg=","319":"b:fwBEWhUw7GEBsz4AAEAIACQEAAAAdAMA+AcAAAg=","335":"b:fwBEWhUw7GEBsz4AAEAIACQEAAAAdAMA+AcAAAg=","336":"b:fwBEWhUw7GEBsz4AAEAIACQEAAAAdAMA+AcAAAg=","347":"b:fwBEWhUw7GEBsz4AAEAIACQEAAAAdAMA+AcAAAg=","526":"b:fwBEWhUw7GEBsz4AAEAIACQEAAAAdAMA+AcAAAg=","574":"b:fwBEWhUw7GEBsz4AAEAIACQEAAAAdAMA+AcAAAg=","619":"b:fwBEWhUw7GEBsz4AAEAIACQEAAAAdAMA+AcAAAg=","782":"b:fwBEWhUw7GEBsz4AAEAIACQEAAAAdAMA+AcAAAg=","800":"b:fwBEWhUw7GEBsz4AAEAIACQEAAAAdAMA+AcAAAg=","805":"b:fwBEWhUw7GEBsz4AAEAIACQEAAAAdAMA+AcAAAg=","808":"b:fwBEWhUw7GEBsz4AAEAIACQEAAAAdAMA+AcAAAg=","811":"b:fwBEWhUw7GEBsz4AAEAIACQEAAAAdAMA+AcAAAg=","814":"b:fwBEWhUw7GEBsz4AAEAIACQEAAAAdAMA+AcAAAg=","822":"b:fwBEWhUw7GEBsz4AAEAIACQEAAAAdAMA+AcAAAg=","841":"b:fwBEWhUw7GEBsz4AAEAIACQEAAAAdAMA+AcAAAg=","856":"b:fwBEWhUw7GEBsz4AAEAIACQEAAAAdAMA+AcAAAg=","870":"b:fwBEWhUw7GEBsz4AAEAIACQEAAAAdAMA+AcAAAg=","883":"b:fwBEWhUw7GEBsz4AAEAIACQEAAAAdAMA+AcAAAg=","895":"b:fwBEWhUw7GEBsz4AAEAIACQEAAAAdAMA+AcAAAg=","902":"b:fwBEWhUw7GEBsz4AAEAIACQEAAAAdAMA+AcAAAg="},"packages/cli/src/workflows/workflow-finder.service.ts":{"42":"b:j49v/veu4//J/wkbABAAAEgBAIAAFAAA/wcAAAA=","50":"b:j49v/veu4//J/wkbABAAAEgBAIAAFAAA/wcAAAA=","84":"b:j49v/veu4//J/wkbABAAAEgBAIAAFAAA/wcAAAA=","107":"b:j49v/veu4//J/wkbABAAAEgBAIAAFAAA/wcAAAA=","113":"b:j49v/veu4//J/wkbABAAAEgBAIAAFAAA/wcAAAA=","114":"b:j49v/veu4//J/wkbABAAAEgBAIAAFAAA/wcAAAA=","135":"b:j49v/veu4//J/wkbABAAAEgBAIAAFAAA/wcAAAA=","186":"b:j49v/veu4//J/wkbABAAAEgBAIAAFAAA/wcAAAA=","205":"b:j49v/veu4//J/wkbABAAAEgBAIAAFAAA/wcAAAA=","209":"b:j49v/veu4//J/wkbABAAAEgBAIAAFAAA/wcAAAA=","212":"b:j49v/veu4//J/wkbABAAAEgBAIAAFAAA/wcAAAA=","253":"b:j49v/veu4//J/wkbABAAAEgBAIAAFAAA/wcAAAA=","288":"b:j49v/veu4//J/wkbABAAAEgBAIAAFAAA/wcAAAA=","309":"b:j49v/veu4//J/wkbABAAAEgBAIAAFAAA/wcAAAA=","328":"b:j49v/veu4//J/wkbABAAAEgBAIAAFAAA/wcAAAA=","339":"b:j49v/veu4//J/wkbABAAAEgBAIAAFAAA/wcAAAA=","356":"b:j49v/veu4//J/wkbABAAAEgBAIAAFAAA/wcAAAA=","365":"b:j49v/veu4//J/wkbABAAAEgBAIAAFAAA/wcAAAA=","414":"b:j49v/veu4//J/wkbABAAAEgBAIAAFAAA/wcAAAA=","418":"b:j49v/veu4//J/wkbABAAAEgBAIAAFAAA/wcAAAA=","427":"b:j49v/veu4//J/wkbABAAAEgBAIAAFAAA/wcAAAA=","439":"b:j49v/veu4//J/wkbABAAAEgBAIAAFAAA/wcAAAA=","446":"b:j49v/veu4//J/wkbABAAAEgBAIAAFAAA/wcAAAA="},"packages/cli/src/workflows/workflow-history/workflow-history.controller.ts":{"20":"b:C4BtgAMA43BA5jQDAAEIAEgMAAAABQAAAAAAAAA=","23":"b:C4BtgAMA43BA5jQDAAEIAEgMAAAABQAAAAAAAAA=","40":"b:C4BtgAMA43BA5jQDAAEIAEgMAAAABQAAAAAAAAA=","59":"b:C4BtgAMA43BA5jQDAAEIAEgMAAAABQAAAAAAAAA=","80":"b:C4BtgAMA43BA5jQDAAEIAEgMAAAABQAAAAAAAAA=","100":"b:C4BtgAMA43BA5jQDAAEIAEgMAAAABQAAAAAAAAA="},"packages/cli/src/workflows/workflow-history/workflow-history.service.ts":{"40":"b:jwtv/ncq43vJ/y0XAAEIAEgAAAAABQBD/wfAAAA=","49":"b:jwtv/ncq43vJ/y0XAAEIAEgAAAAABQBD/wfAAAA=","85":"b:jwtv/ncq43vJ/y0XAAEIAEgAAAAABQBD/wfAAAA=","88":"b:jwtv/ncq43vJ/y0XAAEIAEgAAAAABQBD/wfAAAA=","98":"b:jwtv/ncq43vJ/y0XAAEIAEgAAAAABQBD/wfAAAA=","136":"b:jwtv/ncq43vJ/y0XAAEIAEgAAAAABQBD/wfAAAA=","158":"b:jwtv/ncq43vJ/y0XAAEIAEgAAAAABQBD/wfAAAA=","201":"b:jwtv/ncq43vJ/y0XAAEIAEgAAAAABQBD/wfAAAA=","237":"b:jwtv/ncq43vJ/y0XAAEIAEgAAAAABQBD/wfAAAA=","272":"b:jwtv/ncq43vJ/y0XAAEIAEgAAAAABQBD/wfAAAA=","320":"b:jwtv/ncq43vJ/y0XAAEIAEgAAAAABQBD/wfAAAA=","337":"b:jwtv/ncq43vJ/y0XAAEIAEgAAAAABQBD/wfAAAA=","362":"b:jwtv/ncq43vJ/y0XAAEIAEgAAAAABQBD/wfAAAA=","365":"b:jwtv/ncq43vJ/y0XAAEIAEgAAAAABQBD/wfAAAA=","380":"b:jwtv/ncq43vJ/y0XAAEIAEgAAAAABQBD/wfAAAA="},"packages/cli/src/workflows/workflow-static-data.service.ts":{"11":"b:DhEGBGEQwEGJDAAEAAAAAEAAAAAAAEJK+wfRCQg=","18":"b:DhEGBGEQwEGJDAAEAAAAAEAAAAAAAEJK+wfRCQg=","27":"b:DhEGBGEQwEGJDAAEAAAAAEAAAAAAAEJK+wfRCQg=","48":"b:DhEGBGEQwEGJDAAEAAAAAEAAAAAAAEJK+wfRCQg=","54":"b:DhEGBGEQwEGJDAAEAAAAAEAAAAAAAEJK+wfRCQg="},"packages/cli/src/workflows/workflow-validation.service.ts":{"57":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","58":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","63":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","79":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","88":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","99":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","160":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","161":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","184":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","216":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","276":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","297":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","324":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","345":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","380":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","389":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","400":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","408":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","418":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","481":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","515":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","527":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","528":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","554":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","589":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","594":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","622":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","666":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","671":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","705":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","724":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","749":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","757":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA=","778":"b:jxtv/nc+43vJvwkXAAAAAEAAACAAAEDK/wfAIQA="},"packages/cli/src/workflows/workflow.service.ee.ts":{"53":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","72":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","85":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","87":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","94":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","105":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","117":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","123":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","127":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","144":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","158":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","174":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","175":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","182":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","185":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","193":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","204":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","238":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","253":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","269":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","290":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","343":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","348":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","350":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","354":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","391":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","436":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","448":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","449":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","452":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","469":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","480":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","487":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","542":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","564":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","639":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","665":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","697":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","722":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","746":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","772":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","783":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","822":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","831":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","832":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","835":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","837":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","863":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","868":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","881":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","895":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","901":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA=","922":"b:j5tv/ncu+/vJ/+1DAAAAAIAFAaBAGGAA/wcIIQA="},"packages/cli/src/workflows/workflow.service.ts":{"152":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","212":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","251":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","324":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","355":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","371":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","383":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","404":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","421":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","434":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","441":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","445":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","451":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","463":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","466":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","467":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","470":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","471":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","475":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","481":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","486":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","492":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","500":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","507":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","511":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","513":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","527":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","540":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","859":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","904":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","968":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","997":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1072":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1096":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1106":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1124":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1401":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1483":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1550":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1576":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1625":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1660":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1736":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1766":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1839":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1877":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1881":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1885":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1890":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1894":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1906":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1914":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1923":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1924":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1935":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1936":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1941":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1947":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1959":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1966":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1977":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1979":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1986":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1996":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","1997":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","2017":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","2031":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","2053":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","2077":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","2116":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","2138":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","2145":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","2169":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","2234":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","2240":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA=","2284":"b:/xtu/ve/q3/pv+0PHBgECsAFwYBAGEDL/yfBAwA="},"packages/cli/src/workflows/workflows.controller.ts":{"71":"b:j5tv/ve/7//J/3/PHjoMCNgNwYBAHUBL/yfAAwA=","96":"b:j5tv/ve/7//J/3/PHjoMCNgNwYBAHUBL/yfAAwA=","129":"b:j5tv/ve/7//J/3/PHjoMCNgNwYBAHUBL/yfAAwA=","158":"b:j5tv/ve/7//J/3/PHjoMCNgNwYBAHUBL/yfAAwA=","174":"b:j5tv/ve/7//J/3/PHjoMCNgNwYBAHUBL/yfAAwA=","208":"b:j5tv/ve/7//J/3/PHjoMCNgNwYBAHUBL/yfAAwA=","294":"b:j5tv/ve/7//J/3/PHjoMCNgNwYBAHUBL/yfAAwA=","301":"b:j5tv/ve/7//J/3/PHjoMCNgNwYBAHUBL/yfAAwA=","355":"b:j5tv/ve/7//J/3/PHjoMCNgNwYBAHUBL/yfAAwA=","366":"b:j5tv/ve/7//J/3/PHjoMCNgNwYBAHUBL/yfAAwA=","387":"b:j5tv/ve/7//J/3/PHjoMCNgNwYBAHUBL/yfAAwA=","421":"b:j5tv/ve/7//J/3/PHjoMCNgNwYBAHUBL/yfAAwA=","455":"b:j5tv/ve/7//J/3/PHjoMCNgNwYBAHUBL/yfAAwA=","490":"b:j5tv/ve/7//J/3/PHjoMCNgNwYBAHUBL/yfAAwA=","521":"b:j5tv/ve/7//J/3/PHjoMCNgNwYBAHUBL/yfAAwA=","578":"b:j5tv/ve/7//J/3/PHjoMCNgNwYBAHUBL/yfAAwA=","584":"b:j5tv/ve/7//J/3/PHjoMCNgNwYBAHUBL/yfAAwA=","598":"b:j5tv/ve/7//J/3/PHjoMCNgNwYBAHUBL/yfAAwA=","599":"b:j5tv/ve/7//J/3/PHjoMCNgNwYBAHUBL/yfAAwA=","603":"b:j5tv/ve/7//J/3/PHjoMCNgNwYBAHUBL/yfAAwA=","604":"b:j5tv/ve/7//J/3/PHjoMCNgNwYBAHUBL/yfAAwA=","608":"b:j5tv/ve/7//J/3/PHjoMCNgNwYBAHUBL/yfAAwA=","609":"b:j5tv/ve/7//J/3/PHjoMCNgNwYBAHUBL/yfAAwA=","630":"b:j5tv/ve/7//J/3/PHjoMCNgNwYBAHUBL/yfAAwA=","654":"b:j5tv/ve/7//J/3/PHjoMCNgNwYBAHUBL/yfAAwA=","661":"b:j5tv/ve/7//J/3/PHjoMCNgNwYBAHUBL/yfAAwA=","678":"b:j5tv/ve/7//J/3/PHjoMCNgNwYBAHUBL/yfAAwA=","699":"b:j5tv/ve/7//J/3/PHjoMCNgNwYBAHUBL/yfAAwA=","721":"b:j5tv/ve/7//J/3/PHjoMCNgNwYBAHUBL/yfAAwA=","747":"b:j5tv/ve/7//J/3/PHjoMCNgNwYBAHUBL/yfAAwA=","764":"b:j5tv/ve/7//J/3/PHjoMCNgNwYBAHUBL/yfAAwA="},"packages/community-node-types-utils.ts":{"33":"b:jwoA+AMqoHNAvgnHAiAAAAAAAAAAAAAAAAAAAAA=","41":"b:jwoA+AMqoHNAvgnHAiAAAAAAAAAAAAAAAAAAAAA=","53":"b:jwoA+AMqoHNAvgnHAiAAAAAAAAAAAAAAAAAAAAA=","59":"b:jwoA+AMqoHNAvgnHAiAAAAAAAAAAAAAAAAAAAAA=","78":"b:jwoA+AMqoHNAvgnHAiAAAAAAAAAAAAAAAAAAAAA="},"packages/community-node-types.controller.ts":{"9":"b:jwpo+AMqo3NAvgnHAiAAAAAAwAAAAAAAAAAAAAA=","12":"b:jwpo+AMqo3NAvgnHAiAAAAAAwAAAAAAAAAAAAAA=","17":"b:jwpo+AMqo3NAvgnHAiAAAAAAwAAAAAAAAAAAAAA="},"packages/community-node-types.service.ts":{"32":"b:jwpo+AMqo3NAvgnHAiAAAAAAwAAAAAAAAAAAAAA=","43":"b:jwpo+AMqo3NAvgnHAiAAAAAAwAAAAAAAAAAAAAA=","55":"b:jwpo+AMqo3NAvgnHAiAAAAAAwAAAAAAAAAAAAAA=","73":"b:jwpo+AMqo3NAvgnHAiAAAAAAwAAAAAAAAAAAAAA=","104":"b:jwpo+AMqo3NAvgnHAiAAAAAAwAAAAAAAAAAAAAA=","152":"b:jwpo+AMqo3NAvgnHAiAAAAAAwAAAAAAAAAAAAAA=","160":"b:jwpo+AMqo3NAvgnHAiAAAAAAwAAAAAAAAAAAAAA=","176":"b:jwpo+AMqo3NAvgnHAiAAAAAAwAAAAAAAAAAAAAA=","178":"b:jwpo+AMqo3NAvgnHAiAAAAAAwAAAAAAAAAAAAAA=","191":"b:jwpo+AMqo3NAvgnHAiAAAAAAwAAAAAAAAAAAAAA=","213":"b:jwpo+AMqo3NAvgnHAiAAAAAAwAAAAAAAAAAAAAA=","219":"b:jwpo+AMqo3NAvgnHAiAAAAAAwAAAAAAAAAAAAAA=","224":"b:jwpo+AMqo3NAvgnHAiAAAAAAwAAAAAAAAAAAAAA=","229":"b:jwpo+AMqo3NAvgnHAiAAAAAAwAAAAAAAAAAAAAA=","231":"b:jwpo+AMqo3NAvgnHAiAAAAAAwAAAAAAAAAAAAAA=","237":"b:jwpo+AMqo3NAvgnHAiAAAAAAwAAAAAAAAAAAAAA=","241":"b:jwpo+AMqo3NAvgnHAiAAAAAAwAAAAAAAAAAAAAA=","249":"b:jwpo+AMqo3NAvgnHAiAAAAAAwAAAAAAAAAAAAAA=","250":"b:jwpo+AMqo3NAvgnHAiAAAAAAwAAAAAAAAAAAAAA=","256":"b:jwpo+AMqo3NAvgnHAiAAAAAAwAAAAAAAAAAAAAA=","271":"b:jwpo+AMqo3NAvgnHAiAAAAAAwAAAAAAAAAAAAAA=","278":"b:jwpo+AMqo3NAvgnHAiAAAAAAwAAAAAAAAAAAAAA=","283":"b:jwpo+AMqo3NAvgnHAiAAAAAAwAAAAAAAAAAAAAA="},"packages/core/src/credentials.ts":{"11":"b:dgMBhABsoBnCA0ACAQAAAAAAABAAAAQABAAgAAA=","19":"b:dgMBhABsoBnCA0ACAQAAAAAAABAAAAQABAAgAAA=","27":"b:dgMBhABsoBnCA0ACAQAAAAAAABAAAAQABAAgAAA=","37":"b:dgMBhABsoBnCA0ACAQAAAAAAABAAAAQABAAgAAA=","48":"b:dgMBhABsoBnCA0ACAQAAAAAAABAAAAQABAAgAAA=","72":"b:dgMBhABsoBnCA0ACAQAAAAAAABAAAAQABAAgAAA="},"packages/core/src/errors/error-reporter.ts":{"100":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","117":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","125":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","157":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","163":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","184":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","190":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","195":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","239":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","240":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","286":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","287":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","300":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","327":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","331":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","346":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","352":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","400":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","406":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","410":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","414":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","421":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","426":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","430":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","434":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","446":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA=","468":"b:RgBAGAACAEAAAwACAACFBAAgAAAAFASAAQAAQAA="},"packages/core/src/execution-engine/execution-context-hook-registry.service.ts":{"18":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAGAA+wfQIQA=","34":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAGAA+wfQIQA=","89":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAGAA+wfQIQA=","98":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAGAA+wfQIQA=","111":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAGAA+wfQIQA=","112":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAGAA+wfQIQA=","117":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAGAA+wfQIQA=","127":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAGAA+wfQIQA="},"packages/core/src/execution-engine/execution-context.service.ts":{"25":"b:fwBPXnUy7WGJsz4AAEAIAAAAAAAABG0A+wfYIwA=","31":"b:fwBPXnUy7WGJsz4AAEAIAAAAAAAABG0A+wfYIwA=","36":"b:fwBPXnUy7WGJsz4AAEAIAAAAAAAABG0A+wfYIwA=","55":"b:fwBPXnUy7WGJsz4AAEAIAAAAAAAABG0A+wfYIwA=","77":"b:fwBPXnUy7WGJsz4AAEAIAAAAAAAABG0A+wfYIwA=","95":"b:fwBPXnUy7WGJsz4AAEAIAAAAAAAABG0A+wfYIwA=","104":"b:fwBPXnUy7WGJsz4AAEAIAAAAAAAABG0A+wfYIwA=","148":"b:fwBPXnUy7WGJsz4AAEAIAAAAAAAABG0A+wfYIwA=","173":"b:fwBPXnUy7WGJsz4AAEAIAAAAAAAABG0A+wfYIwA=","185":"b:fwBPXnUy7WGJsz4AAEAIAAAAAAAABG0A+wfYIwA=","207":"b:fwBPXnUy7WGJsz4AAEAIAAAAAAAABG0A+wfYIwA=","235":"b:fwBPXnUy7WGJsz4AAEAIAAAAAAAABG0A+wfYIwA="},"packages/core/src/execution-engine/execution-context.ts":{"134":"b:fwBIXnUg4WGJsz4EAAAAAAAAAAAAAGIA+wfQAQA=","141":"b:fwBIXnUg4WGJsz4EAAAAAAAAAAAAAGIA+wfQAQA="},"packages/core/src/execution-engine/execution-lifecycle-hooks.ts":{"103":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","110":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","118":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA="},"packages/core/src/execution-engine/node-execution-context/base-execute-context.ts":{"56":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE=","71":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE=","75":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE=","79":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE=","80":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE=","87":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE=","88":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE=","100":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE=","104":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE=","108":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE=","113":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE=","123":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE=","135":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE=","139":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE=","149":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE=","158":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE=","223":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE=","253":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE=","267":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE=","275":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE=","298":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE=","307":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE=","331":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE=","335":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE=","353":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE=","361":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE=","381":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE=","398":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE=","403":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE=","412":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE=","437":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE=","448":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE=","473":"b:fxROXnUg7WEJoD5EAEAAAEQAAABABmAI+gfYoQE="},"packages/core/src/execution-engine/node-execution-context/execute-context.ts":{"51":"b:fwBIXnUg4WEJoD4AgAAAABAAAAAAAAAA+gfYAQE=","98":"b:fwBIXnUg4WEJoD4AgAAAABAAAAAAAAAA+gfYAQE=","100":"b:fwBIXnUg4WEJoD4AgAAAABAAAAAAAAAA+gfYAQE=","108":"b:fwBIXnUg4WEJoD4AgAAAABAAAAAAAAAA+gfYAQE=","113":"b:fwBIXnUg4WEJoD4AgAAAABAAAAAAAAAA+gfYAQE=","128":"b:fwBIXnUg4WEJoD4AgAAAABAAAAAAAAAA+gfYAQE=","149":"b:fwBIXnUg4WEJoD4AgAAAABAAAAAAAAAA+gfYAQE=","157":"b:fwBIXnUg4WEJoD4AgAAAABAAAAAAAAAA+gfYAQE=","159":"b:fwBIXnUg4WEJoD4AgAAAABAAAAAAAAAA+gfYAQE=","174":"b:fwBIXnUg4WEJoD4AgAAAABAAAAAAAAAA+gfYAQE=","179":"b:fwBIXnUg4WEJoD4AgAAAABAAAAAAAAAA+gfYAQE=","184":"b:fwBIXnUg4WEJoD4AgAAAABAAAAAAAAAA+gfYAQE=","188":"b:fwBIXnUg4WEJoD4AgAAAABAAAAAAAAAA+gfYAQE=","192":"b:fwBIXnUg4WEJoD4AgAAAABAAAAAAAAAA+gfYAQE=","197":"b:fwBIXnUg4WEJoD4AgAAAABAAAAAAAAAA+gfYAQE="},"packages/core/src/execution-engine/node-execution-context/load-options-context.ts":{"21":[1,41,4,5,6,72,73,176,16,178,179],"42":[1,41,4,5,6,72,73,176,16,178,179],"46":[1,41,4,5,6,72,73,176,16,178,179],"50":[1,41,4,5,6,72,73,176,16,178,179],"79":[1,41,4,5,6,72,73,176,16,178,179]},"packages/core/src/execution-engine/node-execution-context/node-execution-context.ts":{"57":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","69":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","74":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","86":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","90":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","94":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","98":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","103":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","107":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","111":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","133":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","171":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","182":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","186":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","191":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","202":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","212":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","217":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","219":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","223":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","228":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","230":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","234":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","237":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","238":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","239":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","242":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","246":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","250":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","254":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","258":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","262":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","270":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","274":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","305":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","309":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","318":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","329":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","384":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","495":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","509":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","514":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","524":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","623":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE=","638":"b:fxVOXnUi4XGJvy5EgAAIAGAAAQACFGWK+wfZIQE="},"packages/core/src/execution-engine/node-execution-context/supply-data-context.ts":{"64":[0,1,2,3,4,5,6,10,12],"109":[0,1,2,3,4,5,6,10,12],"111":[0,1,2,3,4,5,6,10,12],"119":[0,1,2,3,4,5,6,10,12],"126":[0,1,2,3,4,5,6,10,12],"141":[0,1,2,3,4,5,6,10,12],"168":[0,1,2,3,4,5,6,10,12],"176":[0,1,2,3,4,5,6,10,12],"197":[0,1,2,3,4,5,6,10,12],"205":[0,1,2,3,4,5,6,10,12],"211":[0,1,2,3,4,5,6,10,12],"216":[0,1,2,3,4,5,6,10,12],"232":[0,1,2,3,4,5,6,10,12],"245":[0,1,2,3,4,5,6,10,12],"261":[0,1,2,3,4,5,6,10,12],"271":[0,1,2,3,4,5,6,10,12],"410":[0,1,2,3,4,5,6,10,12],"437":[0,1,2,3,4,5,6,10,12],"439":[0,1,2,3,4,5,6,10,12],"454":[0,1,2,3,4,5,6,10,12]},"packages/core/src/execution-engine/node-execution-context/trigger-context.ts":{"21":"b:CwFMWBQwqWABvCQAAEAAAAAAAAAABAAACAYAAQA=","25":"b:CwFMWBQwqWABvCQAAEAAAAAAAAAABAAACAYAAQA=","29":"b:CwFMWBQwqWABvCQAAEAAAAAAAAAABAAACAYAAQA=","36":"b:CwFMWBQwqWABvCQAAEAAAAAAAAAABAAACAYAAQA=","63":"b:CwFMWBQwqWABvCQAAEAAAAAAAAAABAAACAYAAQA=","67":"b:CwFMWBQwqWABvCQAAEAAAAAAAAAABAAACAYAAQA=","72":"b:CwFMWBQwqWABvCQAAEAAAAAAAAAABAAACAYAAQA="},"packages/core/src/execution-engine/node-execution-context/utils/ai-tool-types.ts":{"13":[0,1,2,3,4,5,6,10,12],"17":[0,1,2,3,4,5,6,10,12],"23":[0,1,2,3,4,5,6,10,12]},"packages/core/src/execution-engine/node-execution-context/utils/binary-helper-functions.ts":{"33":"b:fwFIXnUg4WGJvD4AAAAAABAAAAAAAAAA+wfQAAA=","40":"b:fwFIXnUg4WGJvD4AAAAAABAAAAAAAAAA+wfQAAA=","47":"b:fwFIXnUg4WGJvD4AAAAAABAAAAAAAAAA+wfQAAA=","56":"b:fwFIXnUg4WGJvD4AAAAAABAAAAAAAAAA+wfQAAA=","128":"b:fwFIXnUg4WGJvD4AAAAAABAAAAAAAAAA+wfQAAA=","155":"b:fwFIXnUg4WGJvD4AAAAAABAAAAAAAAAA+wfQAAA=","167":"b:fwFIXnUg4WGJvD4AAAAAABAAAAAAAAAA+wfQAAA=","180":"b:fwFIXnUg4WGJvD4AAAAAABAAAAAAAAAA+wfQAAA=","239":"b:fwFIXnUg4WGJvD4AAAAAABAAAAAAAAAA+wfQAAA=","243":"b:fwFIXnUg4WGJvD4AAAAAABAAAAAAAAAA+wfQAAA=","252":"b:fwFIXnUg4WGJvD4AAAAAABAAAAAAAAAA+wfQAAA=","350":"b:fwFIXnUg4WGJvD4AAAAAABAAAAAAAAAA+wfQAAA=","359":"b:fwFIXnUg4WGJvD4AAAAAABAAAAAAAAAA+wfQAAA=","363":"b:fwFIXnUg4WGJvD4AAAAAABAAAAAAAAAA+wfQAAA=","365":"b:fwFIXnUg4WGJvD4AAAAAABAAAAAAAAAA+wfQAAA=","367":"b:fwFIXnUg4WGJvD4AAAAAABAAAAAAAAAA+wfQAAA="},"packages/core/src/execution-engine/node-execution-context/utils/cleanup-parameter-data.ts":{"8":"b:fwFMXn0i4XGJrCwAAEAIAAgAAAAAAAAA+wfYAQA=","14":"b:fwFMXn0i4XGJrCwAAEAIAAgAAAAAAAAA+wfYAQA=","19":"b:fwFMXn0i4XGJrCwAAEAIAAgAAAAAAAAA+wfYAQA="},"packages/core/src/execution-engine/node-execution-context/utils/credential-check-helper-functions.ts":{"3":"b:fwBIXnUg4WEJoD4AAAAAAAAAAAAAAAAA+gfQAAA=","9":"b:fwBIXnUg4WEJoD4AAAAAAAAAAAAAAAAA+gfQAAA="},"packages/core/src/execution-engine/node-execution-context/utils/custom-data.ts":{"15":"b:fwBMXnUg4WEIoDwAAAAAAAAAAQACAAAAAADQAQA=","23":"b:fwBMXnUg4WEIoDwAAAAAAAAAAQACAAAAAADQAQA=","34":"b:fwBMXnUg4WEIoDwAAAAAAAAAAQACAAAAAADQAQA=","45":"b:fwBMXnUg4WEIoDwAAAAAAAAAAQACAAAAAADQAQA=","48":"b:fwBMXnUg4WEIoDwAAAAAAAAAAQACAAAAAADQAQA="},"packages/core/src/execution-engine/node-execution-context/utils/data-table-helper-functions.ts":{"8":"b:fwBIXnUi4WEJozoAAAAAAAAAAAAAAAAA+gfQAAA=","16":"b:fwBIXnUi4WEJozoAAAAAAAAAAAAAAAAA+gfQAAA=","22":"b:fwBIXnUi4WEJozoAAAAAAAAAAAAAAAAA+gfQAAA="},"packages/core/src/execution-engine/node-execution-context/utils/deduplication-helper-functions.ts":{"16":"b:fwBIXnUg4WEJoD4AAAAAAAAAAAAAAAAA+gfQAAA=","30":"b:fwBIXnUg4WEJoD4AAAAAAAAAAAAAAAAA+gfQAAA=","46":"b:fwBIXnUg4WEJoD4AAAAAAAAAAAAAAAAA+gfQAAA=","60":"b:fwBIXnUg4WEJoD4AAAAAAAAAAAAAAAAA+gfQAAA=","72":"b:fwBIXnUg4WEJoD4AAAAAAAAAAAAAAAAA+gfQAAA=","84":"b:fwBIXnUg4WEJoD4AAAAAAAAAAAAAAAAA+gfQAAA=","88":"b:fwBIXnUg4WEJoD4AAAAAAAAAAAAAAAAA+gfQAAA=","95":"b:fwBIXnUg4WEJoD4AAAAAAAAAAAAAAAAA+gfQAAA=","109":"b:fwBIXnUg4WEJoD4AAAAAAAAAAAAAAAAA+gfQAAA=","116":"b:fwBIXnUg4WEJoD4AAAAAAAAAAAAAAAAA+gfQAAA=","122":"b:fwBIXnUg4WEJoD4AAAAAAAAAAAAAAAAA+gfQAAA="},"packages/core/src/execution-engine/node-execution-context/utils/execution-metadata.ts":{"8":[32,1,2,3,4,5,144,161,18],"46":[32,1,2,3,4,5,144,161,18],"51":[32,1,2,3,4,5,144,161,18],"63":[32,1,2,3,4,5,144,161,18],"70":[32,1,2,3,4,5,144,161,18]},"packages/core/src/execution-engine/node-execution-context/utils/file-system-helper-functions.ts":{"41":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA=","47":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA=","48":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA=","49":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA=","54":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA=","60":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA=","77":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA=","85":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA=","86":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA=","87":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA=","97":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA=","106":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA=","127":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA=","133":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA=","143":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA=","149":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA=","150":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA=","158":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA=","170":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA=","178":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA=","190":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA=","243":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA=","246":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA=","252":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA=","279":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA=","280":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA=","330":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA=","334":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA=","424":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA=","436":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA=","439":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA=","443":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA=","451":"b:fwBIXnUg4WEJoD4AAAAAABAAAAAAAAAA+gfQAAA="},"packages/core/src/execution-engine/node-execution-context/utils/get-additional-keys.ts":{"13":"b:fwFIXnUi4XGJrDwCAAAAAAAAAAAAAAAA/wfQAQA=","20":"b:fwFIXnUi4XGJrDwCAAAAAAAAAAAAAAAA/wfQAQA=","62":"b:fwFIXnUi4XGJrDwCAAAAAAAAAAAAAAAA/wfQAQA="},"packages/core/src/execution-engine/node-execution-context/utils/get-input-connection-data.ts":{"46":[0,1,2,3,4,5,6,10,12],"52":[0,1,2,3,4,5,6,10,12],"64":[0,1,2,3,4,5,6,10,12],"68":[0,1,2,3,4,5,6,10,12],"78":[0,1,2,3,4,5,6,10,12],"91":[0,1,2,3,4,5,6,10,12],"116":[0,1,2,3,4,5,6,10,12],"156":[0,1,2,3,4,5,6,10,12],"160":[0,1,2,3,4,5,6,10,12],"169":[0,1,2,3,4,5,6,10,12],"172":[0,1,2,3,4,5,6,10,12],"181":[0,1,2,3,4,5,6,10,12],"182":[0,1,2,3,4,5,6,10,12],"190":[0,1,2,3,4,5,6,10,12],"221":[0,1,2,3,4,5,6,10,12],"233":[0,1,2,3,4,5,6,10,12],"247":[0,1,2,3,4,5,6,10,12],"341":[0,1,2,3,4,5,6,10,12],"361":[0,1,2,3,4,5,6,10,12],"364":[0,1,2,3,4,5,6,10,12],"378":[0,1,2,3,4,5,6,10,12],"393":[0,1,2,3,4,5,6,10,12],"409":[0,1,2,3,4,5,6,10,12],"418":[0,1,2,3,4,5,6,10,12],"471":[0,1,2,3,4,5,6,10,12],"494":[0,1,2,3,4,5,6,10,12],"577":[0,1,2,3,4,5,6,10,12]},"packages/core/src/execution-engine/node-execution-context/utils/get-secrets-proxy.ts":{"4":[26,1,2,4,5,6,45,46,194,53,54,55,56,178,89],"6":[26,1,2,4,5,6,45,46,194,53,54,55,56,178,89],"25":[26,1,2,4,5,6,45,46,194,53,54,55,56,178,89],"30":[26,1,2,4,5,6,45,46,194,53,54,55,56,178,89],"50":[26,1,2,4,5,6,45,46,194,53,54,55,56,178,89],"66":[26,1,2,4,5,6,45,46,194,53,54,55,56,178,89],"69":[26,1,2,4,5,6,45,46,194,53,54,55,56,178,89],"75":[26,1,2,4,5,6,45,46,194,53,54,55,56,178,89],"78":[26,1,2,4,5,6,45,46,194,53,54,55,56,178,89]},"packages/core/src/execution-engine/node-execution-context/utils/request-helpers/factory.ts":{"28":"b:fwFIXnUi4WGJvyoAAEAAAEQAAAAAEgUA+wfQAAA=","35":"b:fwFIXnUi4WGJvyoAAEAAAEQAAAAAEgUA+wfQAAA=","70":"b:fwFIXnUi4WGJvyoAAEAAAEQAAAAAEgUA+wfQAAA=","90":"b:fwFIXnUi4WGJvyoAAEAAAEQAAAAAEgUA+wfQAAA=","92":"b:fwFIXnUi4WGJvyoAAEAAAEQAAAAAEgUA+wfQAAA=","114":"b:fwFIXnUi4WGJvyoAAEAAAEQAAAAAEgUA+wfQAAA=","131":"b:fwFIXnUi4WGJvyoAAEAAAEQAAAAAEgUA+wfQAAA=","145":"b:fwFIXnUi4WGJvyoAAEAAAEQAAAAAEgUA+wfQAAA=","170":"b:fwFIXnUi4WGJvyoAAEAAAEQAAAAAEgUA+wfQAAA=","191":"b:fwFIXnUi4WGJvyoAAEAAAEQAAAAAEgUA+wfQAAA=","212":"b:fwFIXnUi4WGJvyoAAEAAAEQAAAAAEgUA+wfQAAA="},"packages/core/src/execution-engine/node-execution-context/utils/resolve-source-overwrite.ts":{"7":"b:fwBIXnUg4WEJsD4AAAAAAAAAAAAAAAAA+wfAAAA="},"packages/core/src/execution-engine/node-execution-context/utils/return-json-array.ts":{"8":"b:DwBMWBUgqWAAsDQAAAAAAAAAAAAABAAA+AEAAAA=","15":"b:DwBMWBUgqWAAsDQAAAAAAAAAAAAABAAA+AEAAAA="},"packages/core/src/execution-engine/node-execution-context/utils/scheduling-helper-functions.ts":{"8":"b:CwFMWBQwqWAAvCQAAEAAAAAAAAAABAAC+AEBAQg=","15":"b:CwFMWBQwqWAAvCQAAEAAAAAAAAAABAAC+AEBAQg="},"packages/core/src/execution-engine/node-execution-context/utils/ssh-tunnel-helper-functions.ts":{"7":"b:fwFIXnUi4WEJvyoAAAAAAAAAAAAAAAAA+gfQAAA=","10":"b:fwFIXnUi4WEJvyoAAAAAAAAAAAAAAAAA+gfQAAA=","12":"b:fwFIXnUi4WEJvyoAAAAAAAAAAAAAAAAA+gfQAAA="},"packages/core/src/execution-engine/node-execution-context/utils/validate-value-against-schema.ts":{"25":"b:fwFIXn0i4XGJrCwEAAAIACgAAAAAFEgA+wfYoQA=","46":"b:fwFIXn0i4XGJrCwEAAAIACgAAAAAFEgA+wfYoQA=","113":"b:fwFIXn0i4XGJrCwEAAAIACgAAAAAFEgA+wfYoQA=","125":"b:fwFIXn0i4XGJrCwEAAAIACgAAAAAFEgA+wfYoQA=","187":"b:fwFIXn0i4XGJrCwEAAAIACgAAAAAFEgA+wfYoQA=","198":"b:fwFIXn0i4XGJrCwEAAAIACgAAAAAFEgA+wfYoQA="},"packages/core/src/execution-engine/node-execution-context/webhook-context.ts":{"41":"b:DhQEBGEQQEGIAAAEgAAIAEAAAQACAAIAAwDYAwA=","95":"b:DhQEBGEQQEGIAAAEgAAIAEAAAQACAAIAAwDYAwA=","99":"b:DhQEBGEQQEGIAAAEgAAIAEAAAQACAAIAAwDYAwA=","103":"b:DhQEBGEQQEGIAAAEgAAIAEAAAQACAAIAAwDYAwA=","107":"b:DhQEBGEQQEGIAAAEgAAIAEAAAQACAAIAAwDYAwA=","111":"b:DhQEBGEQQEGIAAAEgAAIAEAAAQACAAIAAwDYAwA=","115":"b:DhQEBGEQQEGIAAAEgAAIAEAAAQACAAIAAwDYAwA=","119":"b:DhQEBGEQQEGIAAAEgAAIAEAAAQACAAIAAwDYAwA=","126":"b:DhQEBGEQQEGIAAAEgAAIAEAAAQACAAIAAwDYAwA=","134":"b:DhQEBGEQQEGIAAAEgAAIAEAAAQACAAIAAwDYAwA=","145":"b:DhQEBGEQQEGIAAAEgAAIAEAAAQACAAIAAwDYAwA=","159":"b:DhQEBGEQQEGIAAAEgAAIAEAAAQACAAIAAwDYAwA=","163":"b:DhQEBGEQQEGIAAAEgAAIAEAAAQACAAIAAwDYAwA=","167":"b:DhQEBGEQQEGIAAAEgAAIAEAAAQACAAIAAwDYAwA=","176":"b:DhQEBGEQQEGIAAAEgAAIAEAAAQACAAIAAwDYAwA=","184":"b:DhQEBGEQQEGIAAAEgAAIAEAAAQACAAIAAwDYAwA=","191":"b:DhQEBGEQQEGIAAAEgAAIAEAAAQACAAIAAwDYAwA=","201":"b:DhQEBGEQQEGIAAAEgAAIAEAAAQACAAIAAwDYAwA=","208":"b:DhQEBGEQQEGIAAAEgAAIAEAAAQACAAIAAwDYAwA=","218":"b:DhQEBGEQQEGIAAAEgAAIAEAAAQACAAIAAwDYAwA=","228":"b:DhQEBGEQQEGIAAAEgAAIAEAAAQACAAIAAwDYAwA=","235":"b:DhQEBGEQQEGIAAAEgAAIAEAAAQACAAIAAwDYAwA=","242":"b:DhQEBGEQQEGIAAAEgAAIAEAAAQACAAIAAwDYAwA="},"packages/core/src/execution-engine/requests-response.ts":{"31":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","55":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","89":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","187":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","203":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","238":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","290":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","296":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA="},"packages/core/src/execution-engine/ssh-clients-manager.ts":{"10":"b:f4FIXvWi4WEJvypAALLAAMAAAAAAAAAA+gfQAAA=","16":"b:f4FIXvWi4WEJvypAALLAAMAAAAAAAAAA+gfQAAA=","17":"b:f4FIXvWi4WEJvypAALLAAMAAAAAAAAAA+gfQAAA=","67":"b:f4FIXvWi4WEJvypAALLAAMAAAAAAAAAA+gfQAAA=","69":"b:f4FIXvWi4WEJvypAALLAAMAAAAAAAAAA+gfQAAA=","85":"b:f4FIXvWi4WEJvypAALLAAMAAAAAAAAAA+gfQAAA=","88":"b:f4FIXvWi4WEJvypAALLAAMAAAAAAAAAA+gfQAAA=","108":"b:f4FIXvWi4WEJvypAALLAAMAAAAAAAAAA+gfQAAA=","133":"b:f4FIXvWi4WEJvypAALLAAMAAAAAAAAAA+gfQAAA=","135":"b:f4FIXvWi4WEJvypAALLAAMAAAAAAAAAA+gfQAAA=","157":"b:f4FIXvWi4WEJvypAALLAAMAAAAAAAAAA+gfQAAA=","158":"b:f4FIXvWi4WEJvypAALLAAMAAAAAAAAAA+gfQAAA=","162":"b:f4FIXvWi4WEJvypAALLAAMAAAAAAAAAA+gfQAAA=","166":"b:f4FIXvWi4WEJvypAALLAAMAAAAAAAAAA+gfQAAA=","170":"b:f4FIXvWi4WEJvypAALLAAMAAAAAAAAAA+gfQAAA=","180":"b:f4FIXvWi4WEJvypAALLAAMAAAAAAAAAA+gfQAAA=","191":"b:f4FIXvWi4WEJvypAALLAAMAAAAAAAAAA+gfQAAA=","203":"b:f4FIXvWi4WEJvypAALLAAMAAAAAAAAAA+gfQAAA="},"packages/core/src/execution-engine/triggers-and-pollers.ts":{"25":"b:CwFMWBQwqWABvDQAAEAAAAAAAAAABAAA+AcAAQA=","60":"b:CwFMWBQwqWABvDQAAEAAAAAAAAAABAAA+AcAAQA=","68":"b:CwFMWBQwqWABvDQAAEAAAAAAAAAABAAA+AcAAQA=","79":"b:CwFMWBQwqWABvDQAAEAAAAAAAAAABAAA+AcAAQA=","104":"b:CwFMWBQwqWABvDQAAEAAAAAAAAAABAAA+AcAAQA=","108":"b:CwFMWBQwqWABvDQAAEAAAAAAAAAABAAA+AcAAQA=","114":"b:CwFMWBQwqWABvDQAAEAAAAAAAAAABAAA+AcAAQA=","118":"b:CwFMWBQwqWABvDQAAEAAAAAAAAAABAAA+AcAAQA=","124":"b:CwFMWBQwqWABvDQAAEAAAAAAAAAABAAA+AcAAQA=","129":"b:CwFMWBQwqWABvDQAAEAAAAAAAAAABAAA+AcAAQA=","134":"b:CwFMWBQwqWABvDQAAEAAAAAAAAAABAAA+AcAAQA=","150":"b:CwFMWBQwqWABvDQAAEAAAAAAAAAABAAA+AcAAQA=","156":"b:CwFMWBQwqWABvDQAAEAAAAAAAAAABAAA+AcAAQA=","157":"b:CwFMWBQwqWABvDQAAEAAAAAAAAAABAAA+AcAAQA=","165":"b:CwFMWBQwqWABvDQAAEAAAAAAAAAABAAA+AcAAQA="},"packages/core/src/execution-engine/workflow-execute.ts":{"110":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","133":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","143":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","149":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","167":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","191":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","238":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","246":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","349":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","381":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","422":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","450":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","469":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","672":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","889":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","956":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","974":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","996":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1060":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1073":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1084":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1099":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1104":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1113":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1164":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1171":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1173":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1198":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1266":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1286":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1339":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1374":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1394":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1525":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1560":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1586":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1612":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1654":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1663":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1678":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1749":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1761":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1774":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1778":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1783":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1821":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1838":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1852":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1865":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1889":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1927":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1953":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","1962":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2000":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2009":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2013":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2024":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2044":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2062":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2155":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2168":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2189":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2206":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2211":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2216":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2221":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2232":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2247":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2260":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2281":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2285":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2349":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2350":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2363":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2364":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2597":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2693":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2710":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2713":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2740":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2745":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2782":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2798":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2816":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2837":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2856":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2877":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","2933":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","3016":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","3027":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","3039":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","3077":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","3146":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","3206":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","3207":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","3209":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA=","3217":"b:fwBMXnUw7WGJsz4EAEABAGwmAAAAlgAM+wfYoQA="},"packages/core/src/html-sandbox.ts":{"4":"b:CgAEBGUAQEGIAAAEAAAIAEAAAAAAAAIAAwDYAQA=","8":"b:CgAEBGUAQEGIAAAEAAAIAEAAAAAAAAIAAwDYAQA=","15":"b:CgAEBGUAQEGIAAAEAAAIAEAAAAAAAAIAAwDYAQA="},"packages/core/src/instance-settings/instance-settings.ts":{"96":[32,1,2,3,103,115,54,56,161,18,177,191],"123":[32,1,2,3,103,115,54,56,161,18,177,191],"133":[32,1,2,3,103,115,54,56,161,18,177,191],"134":[32,1,2,3,103,115,54,56,161,18,177,191],"143":[32,1,2,3,103,115,54,56,161,18,177,191],"144":[32,1,2,3,103,115,54,56,161,18,177,191],"151":[32,1,2,3,103,115,54,56,161,18,177,191],"180":[32,1,2,3,103,115,54,56,161,18,177,191],"229":[32,1,2,3,103,115,54,56,161,18,177,191],"233":[32,1,2,3,103,115,54,56,161,18,177,191],"238":[32,1,2,3,103,115,54,56,161,18,177,191],"243":[32,1,2,3,103,115,54,56,161,18,177,191],"247":[32,1,2,3,103,115,54,56,161,18,177,191],"251":[32,1,2,3,103,115,54,56,161,18,177,191],"255":[32,1,2,3,103,115,54,56,161,18,177,191],"259":[32,1,2,3,103,115,54,56,161,18,177,191],"263":[32,1,2,3,103,115,54,56,161,18,177,191],"267":[32,1,2,3,103,115,54,56,161,18,177,191],"271":[32,1,2,3,103,115,54,56,161,18,177,191],"275":[32,1,2,3,103,115,54,56,161,18,177,191],"279":[32,1,2,3,103,115,54,56,161,18,177,191],"287":[32,1,2,3,103,115,54,56,161,18,177,191],"310":[32,1,2,3,103,115,54,56,161,18,177,191],"318":[32,1,2,3,103,115,54,56,161,18,177,191],"365":[32,1,2,3,103,115,54,56,161,18,177,191],"372":[32,1,2,3,103,115,54,56,161,18,177,191],"380":[32,1,2,3,103,115,54,56,161,18,177,191],"388":[32,1,2,3,103,115,54,56,161,18,177,191],"416":[32,1,2,3,103,115,54,56,161,18,177,191],"421":[32,1,2,3,103,115,54,56,161,18,177,191],"442":[32,1,2,3,103,115,54,56,161,18,177,191],"454":[32,1,2,3,103,115,54,56,161,18,177,191]},"packages/core/src/node-execute-functions.ts":{"17":"b:CwBMWBQwqWAAsDQAAEAAAAAAAAAABAAAAAAAAAA=","31":"b:CwBMWBQwqWAAsDQAAEAAAAAAAAAABAAAAAAAAAA="},"packages/core/src/nodes-loader/directory-loader.ts":{"37":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","88":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","108":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","117":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","123":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","135":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","139":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","143":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","145":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","146":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","147":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","150":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","165":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","229":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","242":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","260":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","289":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","310":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","313":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","325":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","327":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","332":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","344":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","369":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","400":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","406":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","412":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","424":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","443":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","460":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","479":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","499":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","513":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","533":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","539":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","540":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","542":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","548":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","582":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA=","604":"b:+wto/n0+43HJvy0XAEAAQEAAgAAEEAJC/wfAAQA="},"packages/core/src/observability/tracing/tracing.ts":{"38":"b:jxtu/nc6o3vJvwkXAAAAAEAAAAAAAEBK/wfQAQA=","62":"b:jxtu/nc6o3vJvwkXAAAAAEAAAAAAAEBK/wfQAQA=","69":"b:jxtu/nc6o3vJvwkXAAAAAEAAAAAAAEBK/wfQAQA=","77":"b:jxtu/nc6o3vJvwkXAAAAAEAAAAAAAEBK/wfQAQA=","86":"b:jxtu/nc6o3vJvwkXAAAAAEAAAAAAAEBK/wfQAQA=","94":"b:jxtu/nc6o3vJvwkXAAAAAEAAAAAAAEBK/wfQAQA=","102":"b:jxtu/nc6o3vJvwkXAAAAAEAAAAAAAEBK/wfQAQA="},"packages/core/src/storage.config.ts":{"22":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","34":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","40":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","68":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","103":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA="},"packages/core/src/utils/assertions.ts":{"14":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","31":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA="},"packages/core/src/utils/convert-binary-data.ts":{"13":"b:fwBIXnUg4WEJsD4AAAAAAAAAAAAAAAAA+wfAAAA="},"packages/core/src/utils/deep-merge.ts":{"4":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA=","17":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA="},"packages/nodes-base/nodes/Code/JsCodeValidator.ts":{"8":"b:CwUEGAQAGGAAsjBCAAAAAAAAAABABQAAAAAAAAA=","15":"b:CwUEGAQAGGAAsjBCAAAAAAAAAABABQAAAAAAAAA=","42":"b:CwUEGAQAGGAAsjBCAAAAAAAAAABABQAAAAAAAAA=","54":"b:CwUEGAQAGGAAsjBCAAAAAAAAAABABQAAAAAAAAA="},"packages/nodes-base/nodes/Code/JsTaskRunnerSandbox.ts":{"20":"b:CxQEGAQAGGAAsjBCAAAAAAAAAABABQAAAAAQAAA=","30":"b:CxQEGAQAGGAAsjBCAAAAAAAAAABABQAAAAAQAAA=","56":"b:CxQEGAQAGGAAsjBCAAAAAAAAAABABQAAAAAQAAA=","78":"b:CxQEGAQAGGAAsjBCAAAAAAAAAABABQAAAAAQAAA=","123":"b:CxQEGAQAGGAAsjBCAAAAAAAAAABABQAAAAAQAAA=","145":"b:CxQEGAQAGGAAsjBCAAAAAAAAAABABQAAAAAQAAA="},"packages/nodes-base/nodes/Code/PythonTaskRunnerSandbox.ts":{"18":"b:CwQEGAQACGAAsjBCAAAAAAAAAAAABQAAAAAAAAA=","26":"b:CwQEGAQACGAAsjBCAAAAAAAAAAAABQAAAAAAAAA=","42":"b:CwQEGAQACGAAsjBCAAAAAAAAAAAABQAAAAAAAAA=","80":"b:CwQEGAQACGAAsjBCAAAAAAAAAAAABQAAAAAAAAA=","98":"b:CwQEGAQACGAAsjBCAAAAAAAAAAAABQAAAAAAAAA="},"packages/nodes-base/nodes/Code/ValidationError.ts":{"12":"b:CwUEGAQACGAAsjBCAAAAAAAAAAAABQAAAAAAAAA="},"packages/nodes-base/nodes/Code/errors/WrappedExecutionError.ts":{"19":"b:CwQEGAQACGAAsjBCAAAAAAAgAAAABQAMAAAAAAA=","29":"b:CwQEGAQACGAAsjBCAAAAAAAgAAAABQAMAAAAAAA=","37":"b:CwQEGAQACGAAsjBCAAAAAAAgAAAABQAMAAAAAAA="},"packages/nodes-base/nodes/Code/reserved-key-found-error.ts":{"4":"b:CwUEGAQACGAAsjBCAAAAAAAAAAAABQAAAAAAAAA="},"packages/nodes-base/nodes/Code/result-validation.ts":{"16":"b:CwUEGAQAGGAAsjBCAAAAAAAAAABABQAIAAAQAAA=","25":"b:CwUEGAQAGGAAsjBCAAAAAAAAAABABQAIAAAQAAA=","31":"b:CwUEGAQAGGAAsjBCAAAAAAAAAABABQAIAAAQAAA=","61":"b:CwUEGAQAGGAAsjBCAAAAAAAAAABABQAIAAAQAAA=","86":"b:CwUEGAQAGGAAsjBCAAAAAAAAAABABQAIAAAQAAA=","126":"b:CwUEGAQAGGAAsjBCAAAAAAAAAABABQAIAAAQAAA=","159":"b:CwUEGAQAGGAAsjBCAAAAAAAAAABABQAIAAAQAAA=","160":"b:CwUEGAQAGGAAsjBCAAAAAAAAAABABQAIAAAQAAA=","172":"b:CwUEGAQAGGAAsjBCAAAAAAAAAABABQAIAAAQAAA="},"packages/nodes-base/nodes/Code/throw-execution-error.ts":{"5":"b:CwQEGAQACGAAsjBCAAAAAAAgAAAABQAMAAAAAAA="},"packages/nodes-base/nodes/Code/utils.ts":{"3":"b:CwUEGAQACGAAsjBCAAAAAAAAAABABQAAAAAQAAA=","9":"b:CwUEGAQACGAAsjBCAAAAAAAAAABABQAAAAAQAAA=","16":"b:CwUEGAQACGAAsjBCAAAAAAAAAABABQAAAAAQAAA=","17":"b:CwUEGAQACGAAsjBCAAAAAAAAAABABQAAAAAQAAA=","40":"b:CwUEGAQACGAAsjBCAAAAAAAAAABABQAAAAAQAAA=","47":"b:CwUEGAQACGAAsjBCAAAAAAAAAABABQAAAAAQAAA="},"packages/nodes-base/nodes/ManualTrigger/ManualTrigger.node.ts":{"40":"b:iwJseBQ6q3BAsDERAEAAAAAAAAAABAIAAAAAAAA=","41":"b:iwJseBQ6q3BAsDERAEAAAAAAAAAABAIAAAAAAAA="},"packages/nodes-base/nodes/Schedule/GenericFunctions.ts":{"17":"b:AgEEqAAAAAABLwwAAAAAACAAAAAgFAICAAYBAAg=","18":"b:AgEEqAAAAAABLwwAAAAAACAAAAAgFAICAAYBAAg=","20":"b:AgEEqAAAAAABLwwAAAAAACAAAAAgFAICAAYBAAg=","54":"b:AgEEqAAAAAABLwwAAAAAACAAAAAgFAICAAYBAAg=","87":"b:AgEEqAAAAAABLwwAAAAAACAAAAAgFAICAAYBAAg=","164":"b:AgEEqAAAAAABLwwAAAAAACAAAAAgFAICAAYBAAg=","169":"b:AgEEqAAAAAABLwwAAAAAACAAAAAgFAICAAYBAAg=","217":"b:AgEEqAAAAAABLwwAAAAAACAAAAAgFAICAAYBAAg=","236":"b:AgEEqAAAAAABLwwAAAAAACAAAAAgFAICAAYBAAg=","309":"b:AgEEqAAAAAABLwwAAAAAACAAAAAgFAICAAYBAAg=","339":"b:AgEEqAAAAAABLwwAAAAAACAAAAAgFAICAAYBAAg=","346":"b:AgEEqAAAAAABLwwAAAAAACAAAAAgFAICAAYBAAg="},"packages/nodes-base/nodes/Schedule/ScheduleTrigger.node.ts":{"497":"b:AgEEqAAAAAABLwwAAAAAACAAAAAgFAACAAYBAAg=","522":"b:AgEEqAAAAAABLwwAAAAAACAAAAAgFAACAAYBAAg=","563":"b:AgEEqAAAAAABLwwAAAAAACAAAAAgFAACAAYBAAg=","580":"b:AgEEqAAAAAABLwwAAAAAACAAAAAgFAACAAYBAAg=","595":"b:AgEEqAAAAAABLwwAAAAAACAAAAAgFAACAAYBAAg="},"packages/nodes-base/nodes/Set/Set.node.ts":{"8":"b:CgBsHmkAgdEIdjwBAAAAAEAACAAAEQAAAABAAAA="},"packages/nodes-base/nodes/Set/v1/SetV1.node.ts":{"139":"b:CgBsHmkAgdEIdjwBAAAAAEAACAAAFQEAAABAAAA=","146":"b:CgBsHmkAgdEIdjwBAAAAAEAACAAAFQEAAABAAAA=","182":"b:CgBsHmkAgdEIdjwBAAAAAEAACAAAFQEAAABAAAA=","193":"b:CgBsHmkAgdEIdjwBAAAAAEAACAAAFQEAAABAAAA=","211":"b:CgBsHmkAgdEIdjwBAAAAAEAACAAAFQEAAABAAAA="},"packages/nodes-base/nodes/Set/v2/SetV2.node.ts":{"302":"b:CgBsHmkAgdEIdjwBAAAAAEAACAAAEWAAAABQAQA=","309":"b:CgBsHmkAgdEIdjwBAAAAAEAACAAAEWAAAABQAQA="},"packages/nodes-base/nodes/Set/v2/helpers/utils.ts":{"28":"b:CgBsHmkAgdEIdjwBAAAAAEAACAAAUWAAAABQAQA=","31":"b:CgBsHmkAgdEIdjwBAAAAAEAACAAAUWAAAABQAQA=","34":"b:CgBsHmkAgdEIdjwBAAAAAEAACAAAUWAAAABQAQA=","37":"b:CgBsHmkAgdEIdjwBAAAAAEAACAAAUWAAAABQAQA=","43":"b:CgBsHmkAgdEIdjwBAAAAAEAACAAAUWAAAABQAQA=","46":"b:CgBsHmkAgdEIdjwBAAAAAEAACAAAUWAAAABQAQA=","49":"b:CgBsHmkAgdEIdjwBAAAAAEAACAAAUWAAAABQAQA=","56":"b:CgBsHmkAgdEIdjwBAAAAAEAACAAAUWAAAABQAQA=","89":"b:CgBsHmkAgdEIdjwBAAAAAEAACAAAUWAAAABQAQA=","90":"b:CgBsHmkAgdEIdjwBAAAAAEAACAAAUWAAAABQAQA=","104":"b:CgBsHmkAgdEIdjwBAAAAAEAACAAAUWAAAABQAQA=","105":"b:CgBsHmkAgdEIdjwBAAAAAEAACAAAUWAAAABQAQA=","130":"b:CgBsHmkAgdEIdjwBAAAAAEAACAAAUWAAAABQAQA=","161":"b:CgBsHmkAgdEIdjwBAAAAAEAACAAAUWAAAABQAQA=","222":"b:CgBsHmkAgdEIdjwBAAAAAEAACAAAUWAAAABQAQA=","236":"b:CgBsHmkAgdEIdjwBAAAAAEAACAAAUWAAAABQAQA=","238":"b:CgBsHmkAgdEIdjwBAAAAAEAACAAAUWAAAABQAQA=","245":"b:CgBsHmkAgdEIdjwBAAAAAEAACAAAUWAAAABQAQA=","265":"b:CgBsHmkAgdEIdjwBAAAAAEAACAAAUWAAAABQAQA="},"packages/nodes-base/nodes/Set/v2/manual.mode.ts":{"189":"b:CgBsHmkAgdEIdjwBAAAAAEAACAAAEWAAAABQAQA="},"packages/nodes-base/nodes/Set/v2/raw.mode.ts":{"36":"b:CgBsHmkAgdEIdjwBAAAAAEAACAAAEQAAAABAAQA="},"packages/nodes-base/utils/utilities.ts":{"34":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","53":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","65":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","70":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","86":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","89":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","113":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","136":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","140":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","148":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","167":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","174":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","183":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","186":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","189":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","267":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","271":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","276":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","278":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","287":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","309":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","336":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","345":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","346":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","356":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","365":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","387":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","389":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","413":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","414":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","417":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","441":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","447":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA=","454":"b:egJo/nkk49GIdz0DgEAAAEAACACABWAABQAIIQA="},"packages/workflow/src/common/get-child-nodes.ts":{"5":"b:egFIRnUg42GJryAAAEAIAAAAAAAAAAJA+wfAAQA="},"packages/workflow/src/common/get-connected-nodes.ts":{"13":"b:fxFIXnUg42GJvy4EAEAAAAAAAAAABABA+wfAAAA=","29":"b:fxFIXnUg42GJvy4EAEAAAAAAAAAABABA+wfAAAA=","63":"b:fxFIXnUg42GJvy4EAEAAAAAAAAAABABA+wfAAAA=","77":"b:fxFIXnUg42GJvy4EAEAAAAAAAAAABABA+wfAAAA=","83":"b:fxFIXnUg42GJvy4EAEAAAAAAAAAABABA+wfAAAA=","84":"b:fxFIXnUg42GJvy4EAEAAAAAAAAAABABA+wfAAAA="},"packages/workflow/src/common/get-parent-nodes.ts":{"11":"b:fxFIGGkAw0GJHy4AAAAAAAAAAAAAAABA+wfAAAA="},"packages/workflow/src/common/map-connections-by-destination.ts":{"5":"b:fwFIXnUi43GJvyoCAAAAAAAAAAAAAABA/wdAAAA="},"packages/workflow/src/common/resolve-variables.ts":{"23":"b:fwFIXnUi4XGJvyoCAAAAAAAAAAAAAABA/wdAAAA=","51":"b:fwFIXnUi4XGJvyoCAAAAAAAAAAAAAABA/wdAAAA="},"packages/workflow/src/credential-domain-restrictions.ts":{"55":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AGEAAA=","59":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AGEAAA=","66":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AGEAAA=","75":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AGEAAA=","90":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AGEAAA=","95":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AGEAAA=","102":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AGEAAA=","113":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AGEAAA=","134":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AGEAAA=","145":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AGEAAA=","155":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AGEAAA=","180":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AGEAAA=","233":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AGEAAA=","291":"b:jwoA+AMqoHNAvgnHAiAAAAAAgAAAAAAA9AGEAAA="},"packages/workflow/src/dynamic-credentials-helpers.ts":{"9":"b:fwRIXnUg4WGJsz4AAAAAAAAAAAAAAGAA+wfAIQE=","10":"b:fwRIXnUg4WGJsz4AAAAAAAAAAAAAAGAA+wfAIQE=","13":"b:fwRIXnUg4WGJsz4AAAAAAAAAAAAAAGAA+wfAIQE=","22":"b:fwRIXnUg4WGJsz4AAAAAAAAAAAAAAGAA+wfAIQE=","23":"b:fwRIXnUg4WGJsz4AAAAAAAAAAAAAAGAA+wfAIQE=","24":"b:fwRIXnUg4WGJsz4AAAAAAAAAAAAAAGAA+wfAIQE=","33":"b:fwRIXnUg4WGJsz4AAAAAAAAAAAAAAGAA+wfAIQE=","66":"b:fwRIXnUg4WGJsz4AAAAAAAAAAAAAAGAA+wfAIQE=","87":"b:fwRIXnUg4WGJsz4AAAAAAAAAAAAAAGAA+wfAIQE=","99":"b:fwRIXnUg4WGJsz4AAAAAAAAAAAAAAGAA+wfAIQE="},"packages/workflow/src/errors/abstract/execution-base.error.ts":{"28":"b:RgAADAACAAAAAwAAAAABAAAAAAAABASAEAAAYQA=","50":"b:RgAADAACAAAAAwAAAAABAAAAAAAABASAEAAAYQA="},"packages/workflow/src/errors/abstract/node.error.ts":{"44":"b:RgACCAACAAAAAwAAAAABAAAAAAAABAWAEAAAwAA=","83":"b:RgACCAACAAAAAwAAAAABAAAAAAAABAWAEAAAwAA=","107":"b:RgACCAACAAAAAwAAAAABAAAAAAAABAWAEAAAwAA=","115":"b:RgACCAACAAAAAwAAAAABAAAAAAAABAWAEAAAwAA=","147":"b:RgACCAACAAAAAwAAAAABAAAAAAAABAWAEAAAwAA=","157":"b:RgACCAACAAAAAwAAAAABAAAAAAAABAWAEAAAwAA="},"packages/workflow/src/errors/index.ts":{"21":"b:RhFHHyACAECIAwAWGAOFBAAggAAAFAWAEwDAYQA=","31":"b:RhFHHyACAECIAwAWGAOFBAAggAAAFAWAEwDAYQA=","37":"b:RhFHHyACAECIAwAWGAOFBAAggAAAFAWAEwDAYQA=","41":"b:RhFHHyACAECIAwAWGAOFBAAggAAAFAWAEwDAYQA=","43":"b:RhFHHyACAECIAwAWGAOFBAAggAAAFAWAEwDAYQA=","44":"b:RhFHHyACAECIAwAWGAOFBAAggAAAFAWAEwDAYQA=","47":"b:RhFHHyACAECIAwAWGAOFBAAggAAAFAWAEwDAYQA=","49":"b:RhFHHyACAECIAwAWGAOFBAAggAAAFAWAEwDAYQA=","50":"b:RhFHHyACAECIAwAWGAOFBAAggAAAFAWAEwDAYQA="},"packages/workflow/src/errors/node-api.error.ts":{"127":[1,2,41,6,17,176,178],"287":[1,2,41,6,17,176,178],"295":[1,2,41,6,17,176,178],"311":[1,2,41,6,17,176,178]},"packages/workflow/src/errors/node-operation.error.ts":{"12":"b:RgACCAACAAAAAwAAAAABAAAAAAAABASAEAAAwAA=","34":"b:RgACCAACAAAAAwAAAAABAAAAAAAABASAEAAAwAA="},"packages/workflow/src/execution-context-establishment-hooks.ts":{"41":"b:fwBIXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfQAAA="},"packages/workflow/src/execution-context.ts":{"12":"b:ewBAWhQwrGAAsz4AAEABAAAAAAAABAAAAACAIAA=","290":"b:ewBAWhQwrGAAsz4AAEABAAAAAAAABAAAAACAIAA=","425":"b:ewBAWhQwrGAAsz4AAEABAAAAAAAABAAAAACAIAA=","447":"b:ewBAWhQwrGAAsz4AAEABAAAAAAAABAAAAACAIAA=","460":"b:ewBAWhQwrGAAsz4AAEABAAAAAAAABAAAAACAIAA=","465":"b:ewBAWhQwrGAAsz4AAEABAAAAAAAABAAAAACAIAA="},"packages/workflow/src/execution-status.ts":{"16":"b:DwBOXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA=","29":"b:DwBOXnUg4WGJsz4AAAAAAAAAAAAAAAAA+wfAAAA="},"packages/workflow/src/expression-sandboxing.ts":{"28":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","32":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","34":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","82":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","83":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","85":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","98":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","134":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","193":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","194":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","207":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","212":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","222":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","224":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","256":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","280":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","296":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","333":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","335":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","389":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","391":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","400":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","417":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","426":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","434":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","443":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","461":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","470":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","479":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","488":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","497":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","536":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","561":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE=","577":"b:fxEABHkAQAAIIDwAAAAIAAACAAAARGACAQBIQQE="},"packages/workflow/src/expression.ts":{"24":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","27":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","30":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","34":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","48":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","101":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","102":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","126":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","140":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","172":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","174":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","182":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","186":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","197":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","199":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","206":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","209":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","226":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","232":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","242":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","252":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","284":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","291":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","334":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","342":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","347":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","351":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","370":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","385":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","399":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","404":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","408":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","565":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","574":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","615":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","707":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA=","725":"b:fwFIXn0i43GJvz4CAAAIAAAAAAAARCFA/wdIAQA="},"packages/workflow/src/extensions/expression-extension.ts":{"25":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA=","29":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA=","64":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA=","66":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA=","69":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA=","77":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA=","79":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA=","95":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA=","124":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA=","133":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA=","160":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA=","174":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA=","183":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA=","196":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA=","208":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA=","387":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA=","405":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA=","440":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA=","457":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA=","519":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA=","527":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA=","535":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA=","555":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA=","571":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA=","579":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA=","583":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA=","584":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA=","599":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA="},"packages/workflow/src/extensions/expression-parser.ts":{"20":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA=","24":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA=","93":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA=","97":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA=","99":"b:fwEADHkAQAAIIDwAgAAIAAACAAAARGAAAQBIAQA="},"packages/workflow/src/global-state.ts":{"9":"b:fwFIXnUi43GJvyoCAAAAAAAAAAAAAABA/wdAAAA=","13":"b:fwFIXnUi43GJvyoCAAAAAAAAAAAAAABA/wdAAAA="},"packages/workflow/src/highlighted-data.ts":{"3":[32,1,2,3,4,5,6,144,161],"7":[32,1,2,3,4,5,6,144,161]},"packages/workflow/src/index.ts":{"30":"b:fxvv/X8+53HMvz9HgAAIQFgAgCAABErKBwDdYQA=","114":"b:fxvv/X8+53HMvz9HgAAIQFgAgCAABErKBwDdYQA=","123":"b:fxvv/X8+53HMvz9HgAAIQFgAgCAABErKBwDdYQA="},"packages/workflow/src/interfaces.ts":{"150":"b:fwNJ3nVs4XnLoz4CAQAAAAAAAAAAAAQA/wfwAAA=","2728":"b:fwNJ3nVs4XnLoz4CAQAAAAAAAAAAAAQA/wfwAAA=","2745":"b:fwNJ3nVs4XnLoz4CAQAAAAAAAAAAAAQA/wfwAAA="},"packages/workflow/src/node-grouping-validation.ts":{"38":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","65":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","73":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","74":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","78":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","93":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","99":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","102":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","110":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","119":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","124":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","223":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","241":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","260":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","264":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","279":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","291":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","346":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","347":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","380":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","397":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","414":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","422":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","425":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","431":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","482":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","487":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","501":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","518":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","521":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","543":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","544":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","554":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","581":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","595":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","601":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","611":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","619":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","624":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","645":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","649":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","650":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","653":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","680":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","686":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","731":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA=","741":"b:jwtu/ncqo3vJ/wkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/workflow/src/node-helpers.ts":{"258":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","266":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","276":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","286":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","301":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","323":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","324":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","341":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","345":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","360":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","419":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","446":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","485":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","529":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","560":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","593":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","630":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","669":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","674":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","752":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1020":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1059":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1091":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1092":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1140":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1170":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1200":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1221":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1230":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1234":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1240":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1243":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1280":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1342":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1378":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1404":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1433":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1447":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1472":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1500":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1537":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1552":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1563":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1568":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1594":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1606":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1651":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1654":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1819":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1860":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1868":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1880":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1890":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1894":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1911":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1924":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1930":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1932":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1940":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1944":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","1968":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","2003":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","2010":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","2026":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","2031":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","2065":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","2098":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","2113":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","2145":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","2172":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","2188":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","2202":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","2216":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","2227":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","2242":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","2267":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","2276":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA=","2277":"b:/79v/n1643vP/3/XAmAKAHwAABAEFm7C/4f5oQA="},"packages/workflow/src/node-parameters/parameter-type-validation.ts":{"15":[32,1,2,3,4,5,6,144,161,18],"30":[32,1,2,3,4,5,6,144,161,18],"39":[32,1,2,3,4,5,6,144,161,18],"47":[32,1,2,3,4,5,6,144,161,18],"55":[32,1,2,3,4,5,6,144,161,18],"69":[32,1,2,3,4,5,6,144,161,18],"75":[32,1,2,3,4,5,6,144,161,18],"82":[32,1,2,3,4,5,6,144,161,18],"103":[32,1,2,3,4,5,6,144,161,18],"110":[32,1,2,3,4,5,6,144,161,18],"121":[32,1,2,3,4,5,6,144,161,18],"133":[32,1,2,3,4,5,6,144,161,18],"141":[32,1,2,3,4,5,6,144,161,18],"142":[32,1,2,3,4,5,6,144,161,18],"148":[32,1,2,3,4,5,6,144,161,18],"162":[32,1,2,3,4,5,6,144,161,18],"175":[32,1,2,3,4,5,6,144,161,18],"197":[32,1,2,3,4,5,6,144,161,18],"246":[32,1,2,3,4,5,6,144,161,18],"259":[32,1,2,3,4,5,6,144,161,18]},"packages/workflow/src/observable-object.ts":{"9":"b:fwVMXnUi63GJvz5CAAAAACAAAABAFABC/wfRAAA=","38":"b:fwVMXnUi63GJvz5CAAAAACAAAABAFABC/wfRAAA=","48":"b:fwVMXnUi63GJvz5CAAAAACAAAABAFABC/wfRAAA=","51":"b:fwVMXnUi63GJvz5CAAAAACAAAABAFABC/wfRAAA=","54":"b:fwVMXnUi63GJvz5CAAAAACAAAABAFABC/wfRAAA="},"packages/workflow/src/run-execution-data/run-execution-data.ts":{"29":"b:fwBIXlUg8WGBsz4AAAAAAAAAAAAAAAAAAAAIAAA="},"packages/workflow/src/run-execution-data-factory.ts":{"57":"b:fwFIXnVg4WGJsz4GAAAIAAAAAAAAAAbA/wfQAQA=","70":"b:fwFIXnVg4WGJsz4GAAAIAAAAAAAAAAbA/wfQAQA=","89":"b:fwFIXnVg4WGJsz4GAAAIAAAAAAAAAAbA/wfQAQA=","113":"b:fwFIXnVg4WGJsz4GAAAIAAAAAAAAAAbA/wfQAQA=","130":"b:fwFIXnVg4WGJsz4GAAAIAAAAAAAAAAbA/wfQAQA="},"packages/workflow/src/sub-workflow-output.ts":{"18":"b:DgAEACEAQAEAAAAAAAAAAAAAAQAAAGIAAgBQIQE=","22":"b:DgAEACEAQAEAAAAAAAAAAAAAAQAAAGIAAgBQIQE=","28":"b:DgAEACEAQAEAAAAAAAAAAAAAAQAAAGIAAgBQIQE=","32":"b:DgAEACEAQAEAAAAAAAAAAAAAAQAAAGIAAgBQIQE=","37":"b:DgAEACEAQAEAAAAAAAAAAAAAAQAAAGIAAgBQIQE=","50":"b:DgAEACEAQAEAAAAAAAAAAAAAAQAAAGIAAgBQIQE=","59":"b:DgAEACEAQAEAAAAAAAAAAAAAAQAAAGIAAgBQIQE=","82":"b:DgAEACEAQAEAAAAAAAAAAAAAAQAAAGIAAgBQIQE=","84":"b:DgAEACEAQAEAAAAAAAAAAAAAAQAAAGIAAgBQIQE=","90":"b:DgAEACEAQAEAAAAAAAAAAAAAAQAAAGIAAgBQIQE=","91":"b:DgAEACEAQAEAAAAAAAAAAAAAAQAAAGIAAgBQIQE=","92":"b:DgAEACEAQAEAAAAAAAAAAAAAAQAAAGIAAgBQIQE=","93":"b:DgAEACEAQAEAAAAAAAAAAAAAAQAAAGIAAgBQIQE="},"packages/workflow/src/trigger-identity.ts":{"31":[32,1,2,3,215,144,161,18],"46":[32,1,2,3,215,144,161,18],"64":[32,1,2,3,215,144,161,18]},"packages/workflow/src/type-guards.ts":{"15":"b:fxFOXGkg42GIsD5EAAAIAFgAAAAABEpCBwDAIQA=","21":"b:fxFOXGkg42GIsD5EAAAIAFgAAAAABEpCBwDAIQA=","25":"b:fxFOXGkg42GIsD5EAAAIAFgAAAAABEpCBwDAIQA=","29":"b:fxFOXGkg42GIsD5EAAAIAFgAAAAABEpCBwDAIQA=","33":"b:fxFOXGkg42GIsD5EAAAIAFgAAAAABEpCBwDAIQA=","37":"b:fxFOXGkg42GIsD5EAAAIAFgAAAAABEpCBwDAIQA=","41":"b:fxFOXGkg42GIsD5EAAAIAFgAAAAABEpCBwDAIQA=","47":"b:fxFOXGkg42GIsD5EAAAIAFgAAAAABEpCBwDAIQA=","60":"b:fxFOXGkg42GIsD5EAAAIAFgAAAAABEpCBwDAIQA=","70":"b:fxFOXGkg42GIsD5EAAAIAFgAAAAABEpCBwDAIQA=","83":"b:fxFOXGkg42GIsD5EAAAIAFgAAAAABEpCBwDAIQA=","93":"b:fxFOXGkg42GIsD5EAAAIAFgAAAAABEpCBwDAIQA=","99":"b:fxFOXGkg42GIsD5EAAAIAFgAAAAABEpCBwDAIQA=","103":"b:fxFOXGkg42GIsD5EAAAIAFgAAAAABEpCBwDAIQA="},"packages/workflow/src/type-validation.ts":{"15":"b:exVMDnmA50EIIDwAAAAAAEgAAAAARCEAAABYgQA=","24":"b:exVMDnmA50EIIDwAAAAAAEgAAAAARCEAAABYgQA=","38":"b:exVMDnmA50EIIDwAAAAAAEgAAAAARCEAAABYgQA=","48":"b:exVMDnmA50EIIDwAAAAAAEgAAAAARCEAAABYgQA=","72":"b:exVMDnmA50EIIDwAAAAAAEgAAAAARCEAAABYgQA=","114":"b:exVMDnmA50EIIDwAAAAAAEgAAAAARCEAAABYgQA=","124":"b:exVMDnmA50EIIDwAAAAAAEgAAAAARCEAAABYgQA=","146":"b:exVMDnmA50EIIDwAAAAAAEgAAAAARCEAAABYgQA=","162":"b:exVMDnmA50EIIDwAAAAAAEgAAAAARCEAAABYgQA=","206":"b:exVMDnmA50EIIDwAAAAAAEgAAAAARCEAAABYgQA=","233":"b:exVMDnmA50EIIDwAAAAAAEgAAAAARCEAAABYgQA=","286":"b:exVMDnmA50EIIDwAAAAAAEgAAAAARCEAAABYgQA=","298":"b:exVMDnmA50EIIDwAAAAAAEgAAAAARCEAAABYgQA=","319":"b:exVMDnmA50EIIDwAAAAAAEgAAAAARCEAAABYgQA=","347":"b:exVMDnmA50EIIDwAAAAAAEgAAAAARCEAAABYgQA=","451":"b:exVMDnmA50EIIDwAAAAAAEgAAAAARCEAAABYgQA=","452":"b:exVMDnmA50EIIDwAAAAAAEgAAAAARCEAAABYgQA="},"packages/workflow/src/utils.ts":{"17":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","28":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","36":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","57":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","96":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","101":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","102":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","109":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","127":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","129":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","156":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","199":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","205":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","215":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","240":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","247":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","249":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","260":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","278":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","282":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","284":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","291":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","304":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","308":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","325":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","342":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","345":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","352":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","390":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","408":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","415":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","419":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","428":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","440":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","448":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","456":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","475":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","494":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA=","497":"b:/wvv/38u43vNvz9HgAAIQFAAgAAARCUA/wfcAQA="},"packages/workflow/src/versioned-node-type.ts":{"11":"b:egto/mkk41HIPy0DAEAAQAAAAAAAAAAABQAAAAA=","20":"b:egto/mkk41HIPy0DAEAAQAAAAAAAAAAABQAAAAA=","24":"b:egto/mkk41HIPy0DAEAAQAAAAAAAAAAABQAAAAA="},"packages/workflow/src/webhook-description-fields.ts":{"48":"b:DhAGBHEQREGIAAAEAAAIAEAAAAAAAALKAwDQQQA=","50":"b:DhAGBHEQREGIAAAEAAAIAEAAAAAAAALKAwDQQQA=","55":"b:DhAGBHEQREGIAAAEAAAIAEAAAAAAAALKAwDQQQA=","82":"b:DhAGBHEQREGIAAAEAAAIAEAAAAAAAALKAwDQQQA=","106":"b:DhAGBHEQREGIAAAEAAAIAEAAAAAAAALKAwDQQQA=","117":"b:DhAGBHEQREGIAAAEAAAIAEAAAAAAAALKAwDQQQA=","144":"b:DhAGBHEQREGIAAAEAAAIAEAAAAAAAALKAwDQQQA=","162":"b:DhAGBHEQREGIAAAEAAAIAEAAAAAAAALKAwDQQQA=","165":"b:DhAGBHEQREGIAAAEAAAIAEAAAAAAAALKAwDQQQA=","175":"b:DhAGBHEQREGIAAAEAAAIAEAAAAAAAALKAwDQQQA=","179":"b:DhAGBHEQREGIAAAEAAAIAEAAAAAAAALKAwDQQQA=","186":"b:DhAGBHEQREGIAAAEAAAIAEAAAAAAAALKAwDQQQA="},"packages/workflow/src/workflow-checksum.ts":{"46":"b:jwtu/ncqo3vJvykDAAAAAAAAAAAAAAAA/wcAAAA=","50":"b:jwtu/ncqo3vJvykDAAAAAAAAAAAAAAAA/wcAAAA=","74":"b:jwtu/ncqo3vJvykDAAAAAAAAAAAAAAAA/wcAAAA=","99":"b:jwtu/ncqo3vJvykDAAAAAAAAAAAAAAAA/wcAAAA="},"packages/workflow/src/workflow-data-proxy-env-provider.ts":{"13":"b:fwEAHH0AQGAIoDwAAAAIAAAAAAAABCAAAQBIAQA=","41":"b:fwEAHH0AQGAIoDwAAAAIAAAAAAAABCAAAQBIAQA=","49":"b:fwEAHH0AQGAIoDwAAAAIAAAAAAAABCAAAQBIAQA=","53":"b:fwEAHH0AQGAIoDwAAAAIAAAAAAAABCAAAQBIAQA="},"packages/workflow/src/workflow-data-proxy.ts":{"49":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","74":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","79":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","100":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","139":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","144":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","156":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","178":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","179":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","187":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","193":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","205":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","211":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","212":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","216":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","250":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","275":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","276":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","282":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","284":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","286":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","295":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","296":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","298":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","299":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","313":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","318":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","319":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","322":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","328":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","331":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","336":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","337":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","349":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","356":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","357":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","360":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","366":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","368":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","429":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","461":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","578":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","589":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","590":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","697":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","704":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","705":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","708":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","714":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","745":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","752":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","753":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","756":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","762":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","790":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","795":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","796":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","820":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","824":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","851":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","901":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","923":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","938":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","949":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","960":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","972":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","985":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","996":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1007":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1016":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1035":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1044":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1047":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1065":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1080":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1092":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1122":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1145":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1149":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1167":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1174":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1237":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1262":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1280":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1303":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1304":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1317":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1350":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1360":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1458":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1477":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1501":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1532":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1533":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1536":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1542":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1557":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1572":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1587":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1633":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1660":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1684":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1740":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA=","1741":"b:fxEGDHkAQAAIIDwEgAAIAAgCAAAARGUCAQBIoQA="},"packages/workflow/src/workflow-expression.ts":{"22":"b:fxFMXn1i43GJvy4GAEAIAAgAAAAAAAbC/wfYAQA=","30":"b:fxFMXn1i43GJvy4GAEAIAAgAAAAAAAbC/wfYAQA=","74":"b:fxFMXn1i43GJvy4GAEAIAAgAAAAAAAbC/wfYAQA=","89":"b:fxFMXn1i43GJvy4GAEAIAAgAAAAAAAbC/wfYAQA=","94":"b:fxFMXn1i43GJvy4GAEAIAAgAAAAAAAbC/wfYAQA=","154":"b:fxFMXn1i43GJvy4GAEAIAAgAAAAAAAbC/wfYAQA=","189":"b:fxFMXn1i43GJvy4GAEAIAAgAAAAAAAbC/wfYAQA=","222":"b:fxFMXn1i43GJvy4GAEAIAAgAAAAAAAbC/wfYAQA=","269":"b:fxFMXn1i43GJvy4GAEAIAAgAAAAAAAbC/wfYAQA=","274":"b:fxFMXn1i43GJvy4GAEAIAAgAAAAAAAbC/wfYAQA=","278":"b:fxFMXn1i43GJvy4GAEAIAAgAAAAAAAbC/wfYAQA=","282":"b:fxFMXn1i43GJvy4GAEAIAAgAAAAAAAbC/wfYAQA="},"packages/workflow/src/workflow-structure-validation.ts":{"97":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","100":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","106":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","108":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","116":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","122":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA=","206":"b:jwtu/ncqo3vJvwkTAAAAAAAAAAAAAAAA/wcAAAA="},"packages/workflow/src/workflow.ts":{"87":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","137":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","144":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","149":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","153":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","157":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","164":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","217":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","245":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","253":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","254":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","261":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","262":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","271":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","300":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","309":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","330":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","334":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","384":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","403":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","441":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","485":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","538":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","557":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","575":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","589":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","604":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","618":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","629":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","652":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","670":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","671":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","685":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","744":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","815":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","845":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","846":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","865":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA=","890":"b:fxFOXn0y43GJvz4GgEAIAGQAAAACFENK/wfZgQA="},"localhost-43197/assets/index-Dv_brJ4-.js":{"3":[1]},"localhost-43197/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[1],"9":[1],"10":[1],"19":[1],"23":[1],"29":[1],"33":[1],"34":[1]},"localhost-43197/assets/verified-Dido3Ow4.js":{"8":[1]},"packages/@n8n/api-types/src/agent-builder-tool-node-types.ts":{"20":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/@n8n/api-types/src/agents/agent-integration.schema.ts":{"24":"b:f+r/+4P/5/92+v/v////////////////AIABAAA=","38":"b:f+r/+4P/5/92+v/v////////////////AIABAAA=","71":[46,207,208],"75":[46,207,208],"139":[46,207,208],"150":[46,207,208],"249":[207,208]},"packages/@n8n/api-types/src/agents/dto.ts":{"77":[23,24,26,46,123,190],"204":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","206":[23,24,26,46,123,190],"210":[23,24,26,46,123,190],"214":[23,24,26,46,123,190],"220":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","222":[23,24,26,46,123,190],"226":[23,24,26,46,123,190],"230":[23,24,26,46,123,190],"271":[23,24,26,46,123,190],"275":[23,24,26,46,123,190],"287":[23,24,26,123,190],"291":[23,24,26,123,190],"295":[23,24,26,123,190],"344":[46],"345":[23,24,26,123,190],"353":[23,24,26,123,190],"357":[23,24,26,123,190],"361":[23,24,26,123,190]},"packages/@n8n/api-types/src/dto/audit/audit-public.dto.ts":{"114":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","116":[46],"120":[46]},"packages/@n8n/api-types/src/dto/data-table/data-table-public.dto.ts":{"104":[46],"112":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","118":[46],"122":[46],"126":[46],"170":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","172":[46],"176":[46],"231":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","233":[46],"237":[46],"263":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","265":[46],"269":[46],"274":[46],"332":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","334":[46],"338":[46]},"packages/@n8n/api-types/src/dto/data-table/list-data-table-query.dto.ts":{"35":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","39":"b:AAAAAIDBABwAAEAJHBgEAoAAAAAAAADAAAAAAAA="},"packages/@n8n/api-types/src/dto/evaluations/llm-judge-providers.ts":{"120":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/@n8n/api-types/src/dto/folders/folder-public.dto.ts":{"119":[46],"127":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","133":[46],"137":[46],"141":[46]},"packages/@n8n/api-types/src/dto/ldap/ldap-configuration-public.dto.ts":{"45":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","84":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/@n8n/api-types/src/dto/ldap/ldap-sync-public.dto.ts":{"32":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","41":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","55":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/@n8n/api-types/src/dto/log-streaming/log-streaming-public.dto.ts":{"40":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","181":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","206":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","208":[46],"212":[46],"219":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","221":[46],"225":[46],"232":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","234":[46],"238":[46],"254":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/@n8n/api-types/src/dto/oidc/oidc-configuration-public.dto.ts":{"31":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","59":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/@n8n/api-types/src/dto/openapi-nullable.ts":{"6":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/@n8n/api-types/src/dto/otel/otel-settings-public.dto.ts":{"30":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","57":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/@n8n/api-types/src/dto/otel/otel-test-trace-public.dto.ts":{"39":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","49":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/@n8n/api-types/src/dto/promotions/promotion-connection.dto.ts":{"75":[46],"85":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","93":[46],"97":[46],"101":[46]},"packages/@n8n/api-types/src/dto/promotions/promotion-operations.dto.ts":{"31":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","127":[46]},"packages/@n8n/api-types/src/dto/promotions/promotion-provider.dto.ts":{"141":[46],"149":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","155":[46],"159":[46],"163":[46]},"packages/@n8n/api-types/src/dto/saml/saml-configuration-public.dto.ts":{"132":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","269":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/@n8n/api-types/src/dto/security-settings/security-policy.dto.ts":{"43":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","78":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/@n8n/api-types/src/dto/type-availability-policies/node-type-policy-public.dto.ts":{"24":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/@n8n/api-types/src/dto/type-availability-policies/policy-rule.schema.ts":{"33":[46,71,72,73],"54":"b:f+r/+4P/5//2+//v////////////////AAAAAAA="},"packages/@n8n/api-types/src/dto/workflows/workflow-public.openapi.ts":{"303":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/@n8n/api-types/src/schemas/instance-ai.schema.ts":{"58":[46,19,20,117,48,21,206,96,49,22,121,122],"78":[46,19,20,117,48,21,206,96,49,22,121,122],"108":[46,19,20,117,48,21,206,96,49,22,121,122],"120":[46,19,20,117,48,21,206,96,49,22,121,122],"125":[19,20,117,48,21,206,96,49,22,121,122],"134":[46,19,20,117,48,21,206,96,49,22,121,122],"152":[19,20,117,48,21,206,96,49,22,121,122],"157":[19,20,117,48,21,206,96,49,22,121,122],"173":[19,20,117,48,21,206,96,49,22,121,122],"194":[19,20,117,48,21,206,96,49,22,121,122],"338":"b:AAB4AABABwAAAAAAAQDwBwAAAAAAAAAAAEAAAAA=","551":[46,19,20,117,48,21,206,96,49,22,121,122],"577":[46,19,20,117,48,21,206,96,49,22,121,122],"975":[19,20,117,48,21,206,96,49,22,121,122],"979":[19,20,117,48,21,206,96,49,22,121,122],"983":[19,20,117,48,21,206,96,49,22,121,122],"987":[19,20,117,48,21,206,96,49,22,121,122],"990":[19,20,117,48,21,206,96,49,22,121,122],"998":[19,20,117,48,21,206,96,49,22,121,122],"1037":"b:AAB4AABAAwAAAAAAAQDgBgAAAAAAAAAAAEAAAAA=","1038":"b:AAB4AABAAwAAAAAAAQBgBgAAAAAAAAAAAEAAAAA=","1226":[46,19,20,117,48,21,206,96,49,22,121,122],"1472":"b:f+r/+4P/5/92+v/v////////////////AEAAAAA=","1477":"b:f+r/+4P/5/92+v/v////////////////AEAAAAA=","1482":"b:AAB4AABAAwAAAAAAAQCgBgAAAAAAAAAAAEAAAAA=","1490":"b:AAB4AABAAwAAAAAAAQCgBgAAAAAAAAAAAEAAAAA=","1502":"b:AAB4AABAAwAAAAAAAQCgBgAAAAAAAAAAAEAAAAA=","1913":[46,19,20,117,48,21,206,96,49,22,121,122],"2404":[19,20,117,48,21,206,96,49,22,121,122],"2416":[19,20,117,48,21,206,96,49,22,121,122],"2434":[19,20,117,48,21,206,96,49,22,121,122],"2541":[46,19,20,117,48,21,206,96,49,22,121,122],"2592":[19,20,117,48,21,206,96,49,22,121,122],"2729":[46,19,20,117,48,21,206,96,49,22,50,121,122],"3080":[46,19,20,117,48,21,206,96,49,22,121,122],"3083":[46,19,20,117,48,21,206,96,49,22,121,122],"3102":[19,20,117,48,21,206,96,49,22,121,122],"3199":[46,19,20,117,48,21,206,96,49,22,121,122],"3245":[19,20,117,48,21,206,96,49,22,121,122],"3262":[19,20,117,48,21,206,96,49,22,121,122],"3312":[19,20,117,48,21,206,96,49,22,121,122],"3318":[19,20,117,48,21,206,96,49,22,121,122],"3319":[19,20,117,48,21,206,96,49,22,121,122]},"packages/@n8n/api-types/src/schemas/object-guard.schema.ts":{"8":[92,46,62],"11":"b:f+r/+4P/5/92+v//////////////////AAAAAAA=","14":"b:f+r/+4P/5/92+v//////////////////AAAAAAA=","15":[92,46,62]},"packages/@n8n/api-types/src/schemas/password.schema.ts":{"13":"b:f+r/+4P/5/92/v/v////////////////AAgABAA=","18":[203,93,46,218,58,62,69,158,70,74],"21":[203,93,46,218,58,62,69,158,70,74]},"packages/@n8n/api-types/src/schemas/public-api-path-params.schema.ts":{"11":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","17":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","32":[46],"38":[46]},"packages/@n8n/api-types/src/schemas/read-only-public.schema.ts":{"7":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/@n8n/api-types/src/zod-class.ts":{"41":"b:f+r/+4P/5/92////////////////////AAgABAA=","49":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","51":"b:AAKCo4D5AF5iB8AxAAAAAAAAAFAAAAAAAAgABAA=","56":"b:AAKCo4D5AF5iB8AxAAAAAAAAAFAAAAAAAAgABAA=","60":"b:AAKCo4D5AF5iB8AxAAAAAAAAAFAAAAAAAAgABAA=","64":"b:AAKCo4D5AF5iB8AxAAAAAAAAAFAAAAAAAAgABAA=","80":"b:AAKCo4D5AF5iB8AxAAAAAAAAAFAAAAAAAAgABAA=","87":[46],"89":"b:AAKCo4D5AF5iB8AxAAAAAAAAAFAAAAAAAAgABAA=","93":"b:AAKCo4D5AF5iB8AxAAAAAAAAAFAAAAAAAAgABAA=","97":"b:AAKCo4D5AF5iB8AxAAAAAAAAAFAAAAAAAAgABAA="},"packages/@n8n/chat-hub/src/constants.ts":{"50":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/@n8n/codemirror-lang-sql/src/sql.ts":{"19":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","26":[46,167],"29":[46],"61":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","76":[46,167],"80":[46,167],"140":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","152":[46],"157":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","195":[46,167]},"packages/@n8n/codemirror-lang-sql/src/tokens.ts":{"33":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","80":[46,167],"84":[46],"88":[46,167],"100":[46],"113":[46,167],"122":[46,167],"136":[46],"141":[46,167],"160":[46],"164":[46,167],"171":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","221":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","240":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","241":[46,167]},"packages/@n8n/constants/src/browser.ts":{"11":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/@n8n/constants/src/nodes.ts":{"22":"b:T+pt+AN+5/FA+v/HwmAI8H/+P7D8////AAAAAAA=","26":"b:T+pt+AN+5/FA+v/HwmAI8H/+P7D8////AAAAAAA="},"packages/@n8n/permissions/src/roles/custom-role-scopes.ee.ts":{"254":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","279":[46],"280":[46],"290":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","299":[46],"313":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","314":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","326":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","327":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/@n8n/permissions/src/scope-information.ts":{"4":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","5":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","6":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","12":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","13":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","14":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/@n8n/permissions/src/utilities/get-resource-permissions.ee.ts":{"14":"b:f+r/+4P/5/92+v/v//z////////+////AAAAAAA=","15":"b:f+r/+4P/5/92+v/v//z////////+////AAAAAAA=","18":"b:f+r/+4P/5/92+v/v//j////////+////AAAAAAA="},"packages/@n8n/telemetry/src/define.ts":{"19":"b:f+r/+4P/5/92+v/v////////////////AEAAAAA=","26":"b:AAB8QABABwAAUFADAUDgDRACKAAkAEAAAEAAAAA="},"packages/@n8n/tournament/src/FunctionEvaluator.ts":{"8":"b:D+pt+gF+x9FCevcDgmIAUE3eLzCu/3/iAAAAAAA=","18":"b:D+pt+gF+x9FCevcDgmIAUE3eLzCu/3/iAAAAAAA="},"packages/@n8n/utils/src/assert.ts":{"4":"b:BgIBWAJoABBCAAACAIADAACAAEIAAACAAAAAAAA="},"packages/@n8n/utils/src/create-event-queue.ts":{"7":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","17":"b:f+Lv+QF+5/FA+v5HoMAJAH5upbDu/+/fAAAAAAA=","44":"b:f+Lv+QF+5/FA+v5HoMAJAH5upbDu/+/fAAAAAAA="},"packages/@n8n/utils/src/event-bus.ts":{"43":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","50":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","60":[46,157,190],"61":[46,190],"68":"b:b+pt+gP+5/12+v/H0vMO8n/+//P+////AAAAAAA=","75":"b:L+pt+AN+5/l2+v/H8vMK8n/+//P/////AAAAAAA=","78":"b:D+pt+AN+5/ly+v/H0nMK8H/+//L/////AAAAAAA="},"packages/@n8n/utils/src/is-record.ts":{"1":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/@n8n/utils/src/placeholder.ts":{"13":[19,20,48,21,49,22],"22":[19,20,48,21,49,22],"32":"b:Tup9+ABuQ1FWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","43":[31,46,19,20,48,21,49,22],"63":"b:Tup9+ABuQ1FWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","84":[31,46,19,20,48,21,49,22],"87":[31,46,19,20,48,21,49,22],"91":[31,46,19,20,48,21,49,22],"95":[31,46,19,20,48,21,49,22],"107":[31,46,19,20,48,21,49,22],"111":[31,46,19,20,48,21,49,22]},"packages/@n8n/utils/src/redaction/pii-patterns.ts":{"44":"b:f/7//4P/5/92+v/v////////////////AAAAAAA=","52":"b:f/7//4P/5/92+v/v////////////////AAAAAAA=","58":[26,46,10,19,20,21,49,22,12],"81":[26,46,10,19,20,21,49,22,12],"89":[26,46,10,19,20,21,49,22,12],"105":[26,46,10,19,20,21,49,22,12],"128":[26,46,10,19,20,21,49,22,12],"141":[26,46,10,19,20,21,49,22,12],"146":[26,46,10,19,20,21,49,22,12],"159":"b:f/7//4P/5/92+v/v////////////////AAAAAAA=","234":[26,46,10,19,20,21,49,22,12],"237":[26,46,10,19,20,21,49,22,12],"250":"b:f/7//4P/5/92+v/v////////////////AAAAAAA=","253":[26,46,10,19,20,48,21,49,22,12]},"packages/@n8n/utils/src/result.ts":{"7":"b:AAAFEABAAAACAC8AAAAAAEAoKAAAdB4MAAAAAAA=","12":"b:BupEGABAAEAAMDIEAEAAAEyuLQDAPj8cAAAAAAA=","23":[28,141,18,186,187]},"packages/@n8n/utils/src/search/re-rank-search-results.ts":{"1":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","6":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","9":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","23":"b:BsoBKABKAJFAOo5EACAA8C+gABDkZh8CAAAAAAA="},"packages/@n8n/utils/src/search/sublime-search.ts":{"25":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","41":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","182":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","205":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","222":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","231":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","285":"b:BsoBKABKAJFAOo5EACAA8C+gABDkZh8CAAAAAAA="},"packages/@n8n/utils/src/sort/sort-by-property.ts":{"1":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","6":"b:AGIAgABIQN4AQqYBAAAE4Lr3JvAIOAbHAAAAAAA="},"packages/__vite-browser-external":{"1":"b:/+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/@n8n/chat/src/api/generic.ts":{"1":[32,1,2,3,144,161,18],"5":[32,1,2,3,144,161,18],"49":[32,1,2,3,144,161,18]},"packages/frontend/@n8n/chat/src/api/message.ts":{"24":[32,1,2,3,144,161,18]},"packages/frontend/@n8n/chat/src/components/Chat.vue":{"15":[32,1,2,3,142,144,161,18],"21":[32,1,2,3,142,144,161,18],"32":[32,1,2,3,142,144,161,18],"37":[32,1,2,3,142,144,161,18],"42":[32,1,2,3,142,144,161,18],"47":[32,1,2,3,142,144,161,18],"108":[32,1,2,3,142,144,161,18],"114":[1,18],"122":[32,1,2,3,144,161,18],"136":[32,1,2,3,142,144,161,18],"140":[32,1,2,3,142,144,161,18],"158":[32,1,2,3,142,144,161,18]},"packages/frontend/@n8n/chat/src/components/GetStartedFooter.vue":{"5":[32,1,2,3,142,144,161,18]},"packages/frontend/@n8n/chat/src/components/Input.vue":{"23":[32,1,2,3,142,144,161,18],"48":[32,1,2,3,142,144,161,18],"53":[32,1,2,3,142,144,161,18],"60":[32,1,2,3,142,144,161,18],"66":[32,1,2,3,142,144,161,18],"69":[32,1,2,3,142,144,161,18],"105":[32,1,2,3,142,144,161,18],"112":[32,1,2,3,142,144,161,18],"143":[32,1,2,3,144,161,18],"154":[32,1,2,3,144,161,18],"290":[32,1,2,3,144,161,18],"320":[161],"342":[161],"358":[32,1,2,3,142,144,161,18],"366":[32,1,2,3,142,144,161,18],"377":[32,1,2,3,144,161,18]},"packages/frontend/@n8n/chat/src/components/Layout.vue":{"6":[32,1,2,3,142,144,161,18],"8":[32,1,2,3,142,144,161,18],"15":[32,1,2,3,142,144,161,18],"24":[32,1,2,3,142,144,161,18]},"packages/frontend/@n8n/chat/src/components/MarkdownRenderer.vue":{"16":[32,1,2,3,46,144,161,18],"22":[32,1,2,3,46,144,161,18],"32":[46],"42":[32,1,2,3,46,144,161,18]},"packages/frontend/@n8n/chat/src/components/Message.vue":{"20":[32,1,2,3,144,161,18],"25":[32,1,2,3,144,161,18],"29":[32,1,2,3,144,161,18],"37":[32,1,2,3,144,161,18],"57":[32,1,2,3,144,161,18],"69":[32,1,2,3,144,161,18]},"packages/frontend/@n8n/chat/src/components/MessageActions.vue":{"8":[32,1,2,3,144,161,18],"35":[32,1,2,3,144,161,18]},"packages/frontend/@n8n/chat/src/components/MessageTyping.vue":{"8":[32,1,2,3,144,161,18],"23":[32,1,2,3,144,161,18],"31":[32,1,2,3,144,161,18],"34":[32,1,2,3,144,161,18]},"packages/frontend/@n8n/chat/src/components/MessagesList.vue":{"19":[32,1,2,3,142,144,161,18],"23":[32,1,2,3,142,144,161,18],"24":[32,1,2,3,144,161,18],"32":[32,1,2,3,142,144,161,18],"53":[32,1,2,3,144,161,18],"55":[32,1,2,3,144,161,18]},"packages/frontend/@n8n/chat/src/components/PoweredBy.vue":{"2":[32,1,2,3,142,144,161,18]},"packages/frontend/@n8n/chat/src/composables/useChat.ts":{"6":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/@n8n/chat/src/composables/useI18n.ts":{"5":[32,1,2,3,46,142,144,161,18],"9":[32,1,2,3,46,142,144,161,18],"17":[32,1,2,3,46,142,144,161,18]},"packages/frontend/@n8n/chat/src/composables/useOptions.ts":{"6":[32,1,2,3,46,142,144,161,18]},"packages/frontend/@n8n/chat/src/plugins/chat.ts":{"27":[32,1,2,3,144,161,18],"42":[32,1,2,3,144,161,18],"194":[32,1,2,3,144,161,18],"211":[32,1,2,3,142,144,161,18],"220":[32,1,2,3,142,144,161,18],"228":[32,1,2,3,144,161,18],"237":[32,1,2,3,144,161,18],"297":[32,1,2,3,144,161,18],"304":[32,1,2,3,142,144,161,18],"336":[32,1,2,3,142,144,161,18]},"packages/frontend/@n8n/chat/src/utils/credentialStatus.ts":{"40":[32,1,2,3,142,144,161,18],"43":[1,3,144,18]},"packages/frontend/@n8n/chat/src/utils/event-bus.ts":{"11":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","14":[46],"22":[32,1,2,3,46,142,144,161,18],"33":[46],"36":[32,1,2,3,46,142,144,161,18],"40":[32,1,2,3,46,142,144,161,18]},"packages/frontend/@n8n/chat/src/utils/streaming.ts":{"28":[32,1,2,3,144,161,18],"130":[32,1,2,3,144,161,18]},"packages/frontend/@n8n/composables/src/registries/telemetryRegistry.ts":{"68":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","73":"b:f+r/+4P/5/92+v/v//j////////+////AAAAAAA="},"packages/frontend/@n8n/composables/src/structuralComputed.ts":{"21":"b:T+pt+gF+5/FU+v9HgmMI8H/+P7L//3//AAAAAAA=","27":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA="},"packages/frontend/@n8n/composables/src/useClipboard.ts":{"8":"b:f+r/+wP+5/Fg+v/HyuP9/3/+P7H+////AAAAAAA=","9":[46],"25":[46,170],"48":[46,162,165,167,88,184],"59":[46,162,165,167,88],"77":"b:f+r/+wP+5/Fg+v/HyuP9/3/+P7H+////AAAAAAA=","90":"b:DuoNeABiRBEAun5HgAAFUymoHzHs/1/fAAAAAAA="},"packages/frontend/@n8n/composables/src/useDebounce.ts":{"8":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","23":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","27":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","39":"b:DupFeADuQNdCuv9GgOIE8G+uP3Lk/n9aAAAAAAA=","53":"b:BsoBKIDqQJdAut9EgCAE8C+gDhHkfh9KAAAAAAA="},"packages/frontend/@n8n/composables/src/useDeviceSupport.ts":{"3":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","26":"b:CgAEAAFAAAAAYAAAAAAAAAAAEQA8EEIYAAAAAAA=","28":"b:AoIl2ADKAAZCeFoDEEAAEBGTPGW26sP/AAAAAAA="},"packages/frontend/@n8n/composables/src/useDocumentTitle.ts":{"28":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","37":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","42":[46,184],"47":"b:D+oF+AN+4PFA+v/H4mMI8H/+P7D/////AAAAAAA=","62":[46]},"packages/frontend/@n8n/composables/src/useExternalHooks.ts":{"37":[46],"48":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","57":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/@n8n/composables/src/useShortKeyPress.ts":{"6":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","22":[46],"33":"b:AAAByABAAAAAAAsAAAAAAAAAAACEQA4AAAAAAAA="},"packages/frontend/@n8n/composables/src/useStorage.ts":{"4":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/@n8n/composables/src/useStyles.ts":{"3":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","4":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","11":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/@n8n/composables/src/useTelemetry.ts":{"32":[46],"33":[46],"34":[46],"35":[46],"36":[46],"37":[46],"38":[46],"39":[46],"40":[46],"50":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/@n8n/composables/src/useThrottleWithReactiveDelay.ts":{"7":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","12":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA="},"packages/frontend/@n8n/composables/src/useToast.ts":{"50":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","54":[46],"55":[46],"59":"b:TyIHGIF44H9i8H5HGMCHAfyn5cVG9u9dAAAAAAA=","75":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","78":"b:RgIGGAAAAAAAAAADAACEAAAggAQEFgMMAAAAAAA=","86":"b:RgIGGAAAAAAAAAADAACEAAAggAQEFgMMAAAAAAA=","92":"b:TyIHGIF44H9i8H5HGMCHAfyn5cVG9u9dAAAAAAA=","167":[39,135,57,136,59,62,100,69,78,169,86,190],"181":[39],"223":[6,17,9,114,119,151,154,172,177,89],"260":"b:DyBMWAEw5HEAuH5HkFAIAHwmJRDC92vdAAAAAAA=","261":[27,28,169,186,187]},"packages/frontend/@n8n/design-system/src/components/AskAssistantChat/AskAssistantChat.vue":{"25":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","62":[27,46],"77":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","78":[27,28,29,30,31,33,46],"86":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","87":[27,28,29,30,31,33,46],"99":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","133":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","188":[46],"189":[46],"198":[46],"205":[46],"224":[46],"231":[46],"239":[46],"272":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","275":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","287":[27,28,29,30,31,33,46],"303":"b:D+oF+AN+4PFU+v9HgmMI8H/+P7L8/3//AAAAAAA=","307":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","311":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","315":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","321":[27,28,29,30,31,33,46],"327":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","332":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","345":[31,46],"360":"b:D+oF+AN+4PFU+v9HgmMI8H/+P7L8/3//AAAAAAA=","364":[33,46],"378":[27,46],"382":[27,30,31,33,46],"387":[46],"391":[31,33,46],"395":[31,33,46],"399":[27,30,31,33,46],"403":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","405":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","422":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","439":[27,28,29,30,46,63],"443":[27,28,29,30,31,33,46],"456":[27,28,29,30,31,33,46],"464":[27,28,30,31,33,46,63],"469":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","500":[27,28,29,30,31,33,46],"507":[27,28,29,30,31,33,46],"534":[28,46],"535":[28,46],"538":[31,46],"541":[46],"554":[27,28,30,46],"562":[27,46],"563":[27,28,30,46],"597":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","602":[31,33,46],"612":[46],"613":[46],"614":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","630":[46],"632":[46],"635":[46],"699":[46],"701":[46],"704":[46]},"packages/frontend/@n8n/design-system/src/components/AskAssistantIcon/AssistantIcon.vue":{"4":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","22":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","30":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA="},"packages/frontend/@n8n/design-system/src/components/AskAssistantText/AssistantText.vue":{"9":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA="},"packages/frontend/@n8n/design-system/src/components/ConditionalRouterLink/CondtionalRouterLink.vue":{"56":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","61":"b:D+r/+4P/5/9i+v/P+nj89///P/H8////AAAAAAA=","66":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA="},"packages/frontend/@n8n/design-system/src/components/InlineAskAssistantButton/InlineAskAssistantButton.vue":{"8":"b:BgIFeABoAJBCAAAAAAAAAAKAAEAAAAUAAAAAAAA=","39":"b:BgIFeABoAJBCAAAAAAAAAAKAAEAAAAUAAAAAAAA=","41":[27,28,29,46],"44":"b:BgIFeABoAJBCAAAAAAAAAAKAAEAAAAUAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nActionDropdown/ActionDropdown.vue":{"14":"b:f+rv+wP+5/FA+v/H4uAN8X/+P7D+////AAAAAAA=","34":"b:f+rv+wP+5/FA+v/H4uAN8X/+P7D+////AAAAAAA=","39":"b:f+rv+wP+5/FA+v/H4uAN8X/+P7D+////AAAAAAA=","44":"b:f+rv+wP+5/FA+v/H4uAN8X/+P7D+////AAAAAAA=","52":"b:f+rv+wP+5/FA+v/H4uAN8X/+P7D+////AAAAAAA=","66":"b:f+rv+wP+5/FA+v/H4uAN8X/+P7D+////AAAAAAA=","76":[112,46,47,120],"77":[112,46,47,120,18],"78":[46],"83":[46],"84":[46],"87":"b:f+rv+wP+5/FA+v/H4uAN8X/+P7D+////AAAAAAA=","95":"b:f+rv+wP+5/FA+v/H4uAN8X/+P7D+////AAAAAAA=","121":"b:f+rv+wP+5/FA+v/H4uAN8X/+P7D+////AAAAAAA=","135":[112,46,47,120,18],"143":[112,46,47,120,18],"145":[112,46,47,120,18],"150":[112,46,47,120,18],"161":[46],"164":[46],"175":[46]},"packages/frontend/@n8n/design-system/src/components/N8nActionToggle/ActionToggle.vue":{"14":"b:TupH+IDuQh92Ov9PgPAGUu+v/3Ps/3/DAAAAAAA=","35":"b:TupH+IDuQh92Ov9PgPAGUu+v/3Ps/3/DAAAAAAA=","36":"b:TupH+IDuQh92Ov9PgPAGUu+v/3Ps/3/DAAAAAAA=","44":[113,114,57,136,59,150,65,68,69,179,190],"45":[113,114,57,136,59,150,65,68,69,179,190],"74":"b:TupH+IDuQh92Ov9PgPAGUu+v/3Ps/3/DAAAAAAA=","81":[113,114,57,136,59,150,65,68,69,179,190],"99":"b:TupH+IDuQh92Ov9PgPAGUu+v/3Ps/3/DAAAAAAA=","112":[113,114,57,136,59,150,65,68,69,179,190]},"packages/frontend/@n8n/design-system/src/components/N8nBadge/Badge.vue":{"12":"b:BsoDIoDoAF52GECpORgGCoCBwN8AAQDFAAAAAAA=","18":[25,45,60,158,86,190,191],"27":"b:BsoDIoDoAF52GECpORgGCoCBwN8AAQDFAAAAAAA=","39":"b:BsoDIoDoAF52GECpORgGCoCBwN8AAQDFAAAAAAA=","47":"b:BsoDIoDoAF52GECpOBgGCoCBwN8AAQDFAAAAAAA=","62":"b:BsoDIoDoAF52GECpORgGCoCBwN8AAQDFAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nBlockUi/BlockUi.vue":{"12":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","13":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nButton/Button.vue":{"9":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","25":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","31":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","37":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","43":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","48":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","53":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","55":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","81":"b:f+pf+QO65/92+v/OmfDv+f6///P+////AAAAAAA=","84":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","103":"b:f+r/+4P/5/92+v/v+vv/////////////AAAAAAA=","105":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nButtonList/ButtonList.vue":{"11":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nChatInput/ChatInput.vue":{"63":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","101":[46],"113":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","129":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","134":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","148":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","149":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","161":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","165":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","174":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","176":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","185":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","187":"b:cAB6yAJABwAAAAAAAIDhAQAAAAAAAAAAAAAAAAA=","198":"b:cAB6yAJABwAAAAAAAIDhAQAAAAAAAAAAAAAAAAA=","205":"b:cAB6yAJABwAAAAAAAIDhAQAAAAAAAAAAAAAAAAA=","209":[27,30,31,33,46],"215":"b:cABayAJABwAAAAAAAIDhAQAAAAAAAAAAAAAAAAA=","222":[33,46],"229":[27,30,31,33,46,21],"274":"b:cAB62QJAB4AAAAAAAYDxBwAAAAAAAAAAAAAAAAA=","279":"b:cABa2QJABwAAAAAAAIDhAQAAAAAAAAAAAAAAAAA=","284":[31,46],"289":[31,46],"294":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","299":[46,19,20,117,48,21,118,119,49,120,22,50],"306":"b:d+p/+wP6R59A+v9P+vP197//P3T+/9//AAAAAAA=","314":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","316":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","327":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","331":"b:f+r/+4P/5/92+v/v+vv/////////////AAAAAAA=","348":[46],"353":"b:cAB6yABABwAAAAAAAIDhAQAAAAAAAAAAAAAAAAA=","371":"b:cAB6yABABwAAAAAAAIDhAQAAAAAAAAAAAAAAAAA=","387":[6,46],"396":[46],"399":"b:cABayAJABwAAAAAAAIDhAQAAAAAAAAAAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nCommandBar/CommandBar.vue":{"56":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","65":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","86":[46,187],"87":[46,187],"89":[46],"91":[46,187],"94":[46,187],"97":[46,187],"99":[46,187],"100":[46],"101":[46],"102":[46,187],"103":[46],"109":[46],"110":[46],"123":[46],"131":[46],"137":[46],"142":[46],"150":[46],"205":[46],"212":[46,187],"217":[46,187],"225":"b:AoIl2ALKAA5CeF8DEEAAMRGXPGe06s//AAAAAAA=","232":[46,187],"239":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","244":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","246":[46,187],"252":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","256":[46],"259":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","270":[46,187],"280":[46],"281":[46],"288":[46],"309":[46,187],"323":[46,187],"331":[46],"332":[46],"346":[46,187],"357":[46],"379":[46],"380":[46],"381":[46]},"packages/frontend/@n8n/design-system/src/components/N8nDialog/Dialog.vue":{"104":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","106":[43,111,113,9,45,46,60,65,158,70,178,89],"108":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","117":"b:f+r/+4P/5/92+v/v/vz////////8////AAAAAAA=","130":[46],"131":[111,9,46,178,89],"132":[46,96,100,187],"133":"b:BgIBAABoABBCAAACEYACAACAAEAAAAQAAAAAAAA=","134":"b:BgIBIABoABBCAAACEYACCAKAAEAAAAQIAAAAAAA=","136":[123,100],"137":[123,100]},"packages/frontend/@n8n/design-system/src/components/N8nDialog/DialogClose.vue":{"17":"b:BgIBIABoABBCAAACEYACCAKAAEAAAAQIAAAAAAA=","18":[46,187],"25":"b:BgIBIABoABBCAAACEYACCAKAAEAAAAQAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nDialog/DialogContent.vue":{"63":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","85":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","88":"b:BgIBIABoAFBCAAACEYACCAKAAEAAAAQIAAAAAAA=","89":"b:BgIBIABoAFBCAAACEYACCAKAAEAAAAQIAAAAAAA=","99":[111,9,46,178,89],"105":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","114":[46],"116":[46,96,62,100,187],"117":"b:BgIBAABoAFBCAAACEYACAACAAEAAAAQAAAAAAAA=","118":"b:BgIBIABoAFBCAAACEYACCAKAAEAAAAQIAAAAAAA=","121":[96,187]},"packages/frontend/@n8n/design-system/src/components/N8nDialog/DialogHeader.vue":{"6":"b:BgIBIABoAFBCAAACEIACCAKAAEAAAAQAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nDialog/DialogOverlay.vue":{"19":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nDialog/DialogTitle.vue":{"15":"b:BgIBIABoAFBCAAACEIACCAKAAEAAAAQAAAAAAAA=","16":"b:BgIBIABoAFBCAAACEIACCAKAAEAAAAQAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nDropdownMenu/DropdownMenu.typeguards.ts":{"6":"b:f+r/+4P+5/92+v/P4/j///////P+////AAAAAAA=","8":"b:f+r/+4P+5/92+v/P4/j///////P+////AAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nDropdownMenu/DropdownMenu.vue":{"30":"b:f+r/+4P+5/92+v/P4/j///////P+////AAAAAAA=","61":"b:IAAlWAAAAEIACFAAAMABAJATOLAgAYMhAAAAAAA=","66":"b:IAAlWAAAAEIACFAAAMABAJATOLAgAYMhAAAAAAA=","77":"b:IAAlWAAAAEIACFAAAMABAJATOLAgAYMhAAAAAAA=","87":"b:f+r/+4P+5/92+v/P4/j///////P+////AAAAAAA=","92":"b:f+r/+4P+5/92+v/P4/j///////P+////AAAAAAA=","93":"b:f+r/+4P+5/92+v/P4/j///////P+////AAAAAAA=","99":"b:f+r/+4P+5/92+v/P4/j///////P+////AAAAAAA=","107":"b:f+r/+4P+5/92+v/P4/j///////P+////AAAAAAA=","128":[21],"134":[120],"144":[21],"156":[21],"169":[111,5,112,120],"181":[21],"185":[21],"191":"b:IAIFeACAAEsyCFAAAOAHAZATeLAgAYthAAAAAAA=","198":"b:f+r/+4P+5/92+v/P4/j///////P+////AAAAAAA=","203":[57,75],"212":"b:IAIFeQCAAEsyCFAAAOAHAZATeLAgAYthAAAAAAA=","217":"b:IAIFeQCAAEsyCFAAAOAHAZATeLAgAYthAAAAAAA=","226":"b:AAAFWAAAAAAAAFAAAEAAABASOAAgAAMgAAAAAAA=","245":"b:IAIFeQCAAEsyCFAAAOAHAZATeLAgAYthAAAAAAA=","257":"b:IAIFeQCAAEsyCFAAAOAHAZATeLAgAYthAAAAAAA=","276":"b:bupdeYGqR19yOv5PgPDnU/m7f/Ds/9//AAAAAAA=","283":"b:JuoFeQCmQFsyOn5EgOAHQbg7frDk99tzAAAAAAA=","290":"b:JuoFeQCkQFsyOn5EgOAHAZg7frDk95tzAAAAAAA=","304":"b:IAIFeACAAEsyCFAAAOAHAZATeLAgAYthAAAAAAA=","314":"b:IAIFeACAAEsyCFAAAOAHAZATeLAgAYthAAAAAAA=","318":[21],"326":[21],"351":"b:f+r/+4P+5/92+v/P4/j///////P+////AAAAAAA=","352":"b:f+r/+4P+5/92+v/P4/j///////P+////AAAAAAA=","366":"b:f+r/+4P+5/92+v/P4/j///////P+////AAAAAAA=","377":[21],"400":"b:TupdaIGqRx9yOv5PgLDnU+mpf3Ds/1/fAAAAAAA=","409":"b:IAIleQCAAEsyCFAAAOAHAZATeLAgAYthAAAAAAA=","439":"b:f+r/+4P+5/92+v/P4/j///////P+////AAAAAAA=","443":"b:f+r/+4P+5/92+v/P4vj///////P+////AAAAAAA=","451":"b:f+r/+4P+5/92+v/P4/j///////P+////AAAAAAA=","470":"b:f+r/+4P+5/92+v/P4/j///////P+////AAAAAAA=","489":"b:IAIleQCAAEsyCFAAAOAHAZATeLAgAYthAAAAAAA=","503":[111,5,112],"511":[111,5,112,21,120],"532":[120],"537":[111,5,112,21],"540":[111,5,112,21,120],"543":[111,5,112,21,120],"571":[112,47,120,18],"574":[112,47,120,135,57,136,18],"577":"b:AAAEAQCAAAoyAAAAAAAHAQABQAAAAAhAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nFormInput/validators.ts":{"7":[107,108,17,46,58,60,99,152,100],"23":[46],"36":[46,152],"49":[46],"67":[108,46,100],"79":[46],"97":[46,99,152],"109":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","139":[107,108,17,46,58,60,99,152,100]},"packages/frontend/@n8n/design-system/src/components/N8nHeading/Heading.vue":{"27":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","34":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","50":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","52":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","56":"b:f+r/+4P/5/92+v/v/v//////////////AAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/Icon.vue":{"25":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","32":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","42":"b:f+r/+4O/5/92+v/v////////////////AAAAAAA=","54":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","66":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","83":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","91":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","93":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","95":"b:T+pt+gE+5/FC+v9HgGMI8H/+P/Dv/3//AAAAAAA=","107":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","109":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","129":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/bolt-filled.svg":{"9":"b:D+pt+wF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/grip-lines-vertical.svg":{"9":[1,2,46,11,14,15,16]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/mcp.svg":{"13":"b:AsgAAIDAAF42AECpGBACCoABwA4AAQDAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/node-ellipsis.svg":{"11":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D+/3//AAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/node-execution-error.svg":{"11":[27,28,1,2,46,141,169,170,18,176,186,187]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/node-play.svg":{"11":"b:D+pt+AF+5fFA+v9HgmAI8H/+P7Du/3//AAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/node-power.svg":{"11":"b:D+pt+AF+5fFA+v9HgmAI8H/+P7Ds/3//AAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/node-success.svg":{"11":"b:DyBEWAFw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/node-trash.svg":{"11":"b:D+pt+AF+5fFA+v9HgmAI8H/+P7D8/3//AAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/node-validation-error.svg":{"11":"b:BuoF+ABuQhFAGKUGgiAAUAeKCjCEBheiAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/pop-out.svg":{"8":"b:D+pt+AN+5/FA+v/HwmAI8H/+P7D+////AAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/schema.svg":{"8":[32,1,2,3,46,144,18,188]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/spinner.svg":{"9":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/text.svg":{"8":[1,46,18]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/toolbox.svg":{"10":"b:BgIBKABqQJFAOt9EgAAA4AagDhDkah8CAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/vector-square.svg":{"9":[1,2,46,11,60,14,15,16]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/iconColor.ts":{"25":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/icons.ts":{"832":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","836":"b:T+pt+gF+5/FC+v9HgGMI8H/+P/Dv/3//AAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/ai-agent.svg":{"11":[1,2,6,9,11,13,143,14,76,18,15,16]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/calculator.svg":{"11":[1,6]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/call-n8n-sub-workflow-tool.svg":{"11":[1,6,11,14,15]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/chat-trigger.svg":{"11":"b:DsoFKAEqQJFAOI9EgCAA8C/ADxDmZh8KAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/compression.svg":{"11":[1,6]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/data-table.svg":{"11":[1,43,6,9,156,70,73,167,176,16,185]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/date-and-time.svg":{"11":[1,6]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/edit-fields.svg":{"11":"b:CqBtGgEQhdEAcHwBACMAAEhYLwAr3XMgAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/form-trigger.svg":{"11":"b:BsoBKAAqQBFAOI9EgCAI8C+ADhDkZh8KAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/http-request.svg":{"11":"b:QsoAQAAmAAECEAEAAGAAAAQACkAAAgKAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/item-list-output-parser.svg":{"11":[1]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/manual-trigger.svg":{"11":"b:D+pteAA+5/FA+P9FgGEA8H+2PrDl738eAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/model-selector.svg":{"11":[1,2,15]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/rss-read.svg":{"11":[1,6]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/schedule-trigger.svg":{"11":"b:BsoFqAAqQBFAOs9EgCAA8C+IDhDsdh8rAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/send-mail.svg":{"11":[1,90,6,126,53]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/simple-memory.svg":{"11":[1,15]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/structured-output-parser.svg":{"11":[1,16]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/sub-workflow-trigger.svg":{"11":"b:BsoBKgAqQBFAOI9EgCAA8C+ADhDkZh8KAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/think-tool.svg":{"11":[1,6]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/totp.svg":{"11":[1,6]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/vector-store-question-answer-tool.svg":{"11":[1]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/webhook.svg":{"11":"b:BsoBKAA6QFFAOI9EgCIA8G+ADhDkdh/KAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIconButton/IconButton.vue":{"6":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","7":"b:f+r/+4P/5/92+v/v+vv/////////////AAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIconPicker/iconCategories.ts":{"118":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","129":[46,60]},"packages/frontend/@n8n/design-system/src/components/N8nInfoAccordion/InfoAccordion.vue":{"29":"b:AgAEAABCQEEAgAAAgCAAAAAAAAAAFgMcAAAAAAA=","40":"b:AgAEAABCQEEAgAAAgCAAAAAAAAAAFgMcAAAAAAA=","41":[46],"47":[46],"51":[46],"53":[46],"54":"b:AgAEAABCQEEAgAAAgCAAAAAAAAAAFgMcAAAAAAA=","61":"b:AgAEAABCQEEAgAAAgCAAAAAAAAAAFgMcAAAAAAA=","72":[46],"74":[46],"75":[46],"76":[46],"79":[46],"83":[46]},"packages/frontend/@n8n/design-system/src/components/N8nInfoTip/InfoTip.vue":{"14":"b:DgJFOIDoQF9WAH4PgNACAu6FIFPA/2/QAAAAAAA=","57":"b:DgJFOIDoQF9WAH4PgNACAu6FIFPA/2/QAAAAAAA=","63":"b:DgJFOIDoQF9WAH4PgNACAu6FIFPA/2/QAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nInlineTextEdit/InlineTextEdit.vue":{"16":"b:T+rt+QP+5/NW+v/H4uIO8P//P/L8////AAAAAAA=","35":"b:T+rt+QP+5/NW+v/H4uIO8P//P/L8////AAAAAAA=","38":"b:T+rt+QP+5/NW+v/H4uIO8P//P/L8////AAAAAAA=","44":"b:T+rt+QP+5/NW+v/H4uIO8P//P/L8////AAAAAAA=","47":"b:T+rt+QP+5/NW+v/H4uIO8P//P/L8////AAAAAAA=","57":"b:T+rt+QP+5/NW+v/H4uIO8P//P/L8////AAAAAAA=","68":"b:AAIFWADoAABCQFACAEAAABATOEIAAINgAAAAAAA=","74":"b:AAAFWABgABAAAFAAAEAAABASOAAAAINhAAAAAAA=","81":"b:AAIFWADoAABCQFACAEAAABATOEIAAINgAAAAAAA=","92":"b:AAIFWADoAABCQFACAEAAABATOEIAAINgAAAAAAA=","96":"b:AAIFWADoABBCQFACAEAAABATOEIAAINhAAAAAAA=","103":"b:T+rt+QP+5/NW+v/H4uIO8P//P/L8////AAAAAAA=","122":"b:T+rt+QP+5/NW+v/H4uIO8P//P/L8////AAAAAAA=","127":"b:T+rt+QP+5/NW+v/H4uIO8P//P/L8////AAAAAAA=","145":"b:AAIFWACoAABCQFACAEAAABATOEIAAINgAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nInput/Input.vue":{"10":"b:TupH+oHuQl92ev9vmfoHWu+v/3f8///3AAAAAAA=","41":"b:TupH+oHuQl92ev9vmfoHUu+v/3f8///3AAAAAAA=","50":"b:TupH+oHuQl92ev9vmfoHWu+v/3f8///3AAAAAAA=","60":"b:TupH+oHuQl92ev9vmfoHWu+v/3f8///3AAAAAAA=","79":"b:TupH+oHuQl92ev9vmfoHWu+v/3f8///3AAAAAAA=","82":"b:TupH+oHuQl92ev9vmfoHWu+v/3f8///3AAAAAAA=","84":"b:TupH+oHuQl92ev9vmfoHWu+v/3f8///3AAAAAAA=","98":"b:TupH+oHuQl92ev9vmfoHWu+v/3f8///3AAAAAAA=","112":"b:BkIBQACoQBdiAJQGkfAFAAyAwEcAgo1gAAAAAAA=","119":"b:BkIBQACoQBViCJUGkfAFAEyAwEcogs0jAAAAAAA=","125":"b:BkIBQACoQBdiCJUGkfgFAEyAwEcogs1jAAAAAAA=","131":"b:AAIBQACAAAYAAAQAEAAAAAAAAAcggIFAAAAAAAA=","136":"b:AEABAAAAQAIgAIUEgGAAAAQAAAAgAAxAAAAAAAA=","147":"b:TupH+oHuQl92ev9vmfoHWu+v/3f8///3AAAAAAA=","151":"b:TupH+oHuQl92ev9vmfoHWu+v/3f8///3AAAAAAA=","157":"b:TuoHagGqQB1yev9HkbAHUmmtX2Hs/9/zAAAAAAA=","158":"b:TupH+oHuQl92ev9vmfoHWu+v/3f8///3AAAAAAA=","163":"b:TupH+oHuQl92ev9vmfoHWu+v/3f8///3AAAAAAA=","164":"b:BsJFSACuQFd2ALQmkfIHEE6M4UcMns/gAAAAAAA=","173":"b:TupH+oHuQl92ev9vmfoHWu+v/3f8///3AAAAAAA=","183":"b:BkIBQACoQBdiAJUGkPgFAAyAAEMogs1gAAAAAAA=","184":[176,178],"185":[47,114,134,58,60,75,175,84,182,184,185],"188":"b:TupH+oHuQl92ev9vmfoHWu+v/3f8///3AAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nInputLabel/InputLabel.vue":{"25":"b:TupH+ADuQlV2Ov9GmfoHUG+u/3Ps/n9TAAAAAAA=","31":[46],"34":[46],"38":"b:TupH+ADuQlV2Ov9GmfoHUG+u/3Ps/n9TAAAAAAA=","72":"b:TupF+ADuQlF2Ov9GkfoHUG+u/3Ps/n9TAAAAAAA=","76":"b:BgIBIADIABBACAACAIAHAEKAAEEAAAQDAAAAAAA=","85":[46]},"packages/frontend/@n8n/design-system/src/components/N8nInputNumber/InputNumber.vue":{"24":"b:CsAFKABAAEECKD8GACICUCAMBAKgfB8CAAAAAAA=","25":"b:CsAFKABAAEECKD8GACICUCAMBAKgfB8CAAAAAAA=","26":"b:CsAFKABAAEECKD8GACICUCAMBAKgfB8CAAAAAAA=","40":"b:CsAFKABAAEECKD8GACICUCAMBAKgfB8CAAAAAAA=","41":"b:CsAFKABAAEECKD8GACICUCAMBAKgfB8CAAAAAAA=","48":[109,46,56,138,153,81,173,83,179],"53":[109,46,56,138,153,81,173,83,179],"54":[46],"55":[46],"62":"b:CsAFKABAAEECKD8GACICUCAMBAKgfB8CAAAAAAA=","93":[109,46,56,138,153,81,173,83,179],"98":[46,81,173,83,179],"105":[46],"113":[46],"126":[109,46,56,138,153,179],"143":[46],"163":"b:CsAFKABAAEECKD8GACICUCAMBAKgfB8CAAAAAAA=","164":"b:CsAFKABAAEECKD8GACICUCAMBAKgfB8CAAAAAAA=","173":"b:CsAFKABAAEECKD8GACICUCAMBAKgfB8CAAAAAAA=","183":[46],"206":[109,46,56,138,153,81,173,83,179],"210":[46],"223":[113,46,62,75],"234":[113,46,62,75]},"packages/frontend/@n8n/design-system/src/components/N8nKeyboardShortcut/N8nKeyboardShortcut.vue":{"7":"b:AgAAAABAAAAAYAAAAAAAAAAAEQA0EEIIAAAAAAA=","10":"b:AgAAAABAAAAAYAAAAAAAAAAAEQA0EEIIAAAAAAA=","25":"b:AgAAAABAAAAAYAAAAAAAAAAAEQA0EEIIAAAAAAA=","29":"b:AgAAAABAAAAAYAAAAAAAAAAAEQA0EEIIAAAAAAA=","33":"b:AgAAAABAAAAAYAAAAAAAAAAAEQA0EEIIAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nLink/Link.vue":{"31":"b:D+rt+4P+5/92+v/v+/oO+v/////8////AAAAAAA=","32":"b:D+rt+4P+5/92+v/v+voO+v/////8////AAAAAAA=","34":"b:D+rt+4P+5/92+v/v+voO+v/////8////AAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nLoading/Loading.vue":{"38":"b:Bsp5KIDrR59iut9PmDD296+hznHkbx/LAAAAAAA=","44":[46],"47":"b:Bsp5KIDrR59iut9PmDD296+hznHkbx/LAAAAAAA=","49":[113,46,47,114,89],"60":"b:BsohKIDrQJ9iut9PmDAG8q+hznHkbx/LAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nMenuItem/MenuItem.vue":{"16":"b:f+r/+4P/5/92+v/v+/j////////8////AAAAAAA=","38":"b:dgIDIABpAFh2AACrGIAHCAKAwE4gAAQAAAAAAAA=","45":"b:dgIDIABpAFh2AACrGIAHCAKAwE4gAAQAAAAAAAA=","49":"b:f+r/+4P/5/92+v/v+/j////////8////AAAAAAA=","65":"b:AAAAAADgAAhAAEAJAAAHAQAAAEAgAQAAAAAAAAA=","72":"b:f+r/+4P/5/92+v/v+/j////////8////AAAAAAA=","84":"b:f+r/+4P/5/92+v/v+/j////////8////AAAAAAA=","93":"b:f+r/+4P/5/92+v/v+/j////////8////AAAAAAA=","97":[46],"109":"b:f+r/+4P/5/92+v/v+/j////////8////AAAAAAA=","112":"b:f+r/+4P/5/92+v/v+/j////////8////AAAAAAA=","117":[46],"119":"b:f+r/+4P/5/92+v/v+/j////////8////AAAAAAA=","138":"b:f+r/+4P/5/92+v/v+vj////////8////AAAAAAA=","147":[91,46,60,165],"173":"b:dgIDIABpAFh2AACrGIAHCAKAwE4gAAQAAAAAAAA=","183":"b:AAAAAABAAEA2AACgGAACCAAAwA4AAAAAAAAAAAA=","187":[46]},"packages/frontend/@n8n/design-system/src/components/N8nNavigationDropdown/NavigationDropdown.vue":{"41":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","47":[46],"55":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","57":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","58":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","59":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","67":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","79":[46],"83":"b:D+pf+4P+5/9C+v/P4WDs8///P/H8////AAAAAAA=","88":[46,58,60,86],"93":[46,58,60],"102":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","112":[46,58,60,86],"116":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","125":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","127":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","129":"b:D+r/+4P/5/9i+v/P+nj89///P/H8////AAAAAAA=","140":"b:AGICgIBYQN4CQqYBAAAE4Lr3JvEoOSbnAAAAAAA=","142":"b:AGICgIBYQN4CQqYBAAAE4Lr3JvEoOSbnAAAAAAA=","154":[46],"160":"b:AGICgIBYQN4CQqYBAAAE4Lr3JvEoOSbnAAAAAAA=","162":"b:AGICgIBYQN4CQqYBAAAE4Lr3JvEoOSbnAAAAAAA=","165":"b:AGICgIBYQN4CQqYBAAAE4Lr3JvEoOSbnAAAAAAA=","169":[46,60],"170":"b:AGICgIBYQN4CQqYBAAAE4Lr3JvEoOSbnAAAAAAA=","171":"b:AGICgIBYQN4CQqYBAAAE4Lr3JvEoOSbnAAAAAAA=","183":[46,60],"195":[46],"207":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","211":"b:D+r/+4P/5/9i+v/P+nj89///P/H8////AAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nNodeCreatorNode/NodeCreatorNode.vue":{"32":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","33":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","60":[46],"70":[1,43,9,46,127,131,156,70,73,167,176,16,185],"73":[1,46,11,14,15]},"packages/frontend/@n8n/design-system/src/components/N8nNodeIcon/IconContent.vue":{"20":"b:f+pt+gF+5/lC+v9HguML8H/+P/Dv/3//AAAAAAA=","34":"b:T+pt+gE+5/FC+v9HgGMI8H/+P/Dv/3//AAAAAAA=","53":"b:T+pt+gE+5/FC+v9HgGMI8H/+P/Dv/3//AAAAAAA=","56":"b:f+pt+gF+5/lC+v9HguML8H/+P/Dv/3//AAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nNodeIcon/NodeIcon.vue":{"24":"b:f+pt+gF+5/lC+v9HguML8H/+P/Dv/3//AAAAAAA=","28":"b:f+pt+gF+5/lC+v9HguML8H/+P/Dv/3//AAAAAAA=","43":"b:f+pt+gF+5/lC+v9HguML8H/+P/Dv/3//AAAAAAA=","59":"b:DupFeAAuQFFAOv9GgGIAUG+uPzDk/n+SAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nNotice/Notice.vue":{"16":"b:DsIFeABuQBFCOo9GimIAUCSoXjDk9mcSAAAAAAA=","30":"b:DsIFeABuQBFCOo9GimIAUCSoXjDk9mcSAAAAAAA=","31":[46],"34":"b:DsIFeABuQBFCOg9EgGIAUCSoXjDk9icSAAAAAAA=","50":[46,16],"66":"b:DsIFeABuQBFCOo9GimIAUCSoXjDk9mcSAAAAAAA=","75":"b:DsIFeABuQBFCOo9GimIAUCSoXjDk9mcSAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nOption/Option.vue":{"12":"b:bupH+IDuQl92Ov9PiPIGUu+vP/Ps///WAAAAAAA=","13":"b:bupH+IDuQl92Ov9PiPIGUu+vP/Ps///WAAAAAAA=","16":"b:bupH+IDuQl92Ov9PiPIGUu+vP/Ps///WAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nPopover/Popover.vue":{"89":"b:f+r/+4P/5/9i+v/P+/j99///P/H8////AAAAAAA=","110":"b:AEABAACQAFACCK8IAAAAAAAAAAC4YA9EAAAAAAA=","116":"b:AAABAACQAFACCI4AAAAAAAAAAACoYA1AAAAAAAA=","130":"b:AAABAACQAEACAI8AAAAAAAAAAACoYA5EAAAAAAA=","138":"b:f+r/+4P/5/9i+v/P+/j99///P/H8////AAAAAAA=","139":"b:AEABAACQAFACCK8AAAAAAAAAAACYYA8AAAAAAAA=","148":"b:f+r/+4P/5/9i+v/P+/j99///P/H8////AAAAAAA=","151":"b:AAABAACQAEACCI8IAAAAAAAAAACoYA5EAAAAAAA=","152":"b:f+r/+4P/5/9i+v/P+/j99///P/H8////AAAAAAA=","153":"b:f+r/+4P/5/9i+v/P+/j99///P/H8////AAAAAAA=","156":"b:f+r/+4P/5/9i+v/P+/j99///P/H8////AAAAAAA=","172":"b:AEABAACQAFACCK8IAAAAAAAAAAC4YA9EAAAAAAA=","179":[91,44,47,62,75,163,165,186,190]},"packages/frontend/@n8n/design-system/src/components/N8nPromptInputSuggestions/N8nPromptInputSuggestions.vue":{"10":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","20":[33,46],"23":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","41":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","46":[33,46]},"packages/frontend/@n8n/design-system/src/components/N8nResizeWrapper/ResizeWrapper.vue":{"11":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","74":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","92":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","104":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","107":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","115":[46],"118":[46],"128":"b:DuoNaABiRBEAun5HgAABUymoHzDk/1vfAAAAAAA=","132":[46],"138":[46],"141":[46],"144":[46],"150":[46],"171":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","183":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","190":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","196":[46],"200":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","213":[46]},"packages/frontend/@n8n/design-system/src/components/N8nRoute/Route.vue":{"13":"b:f+r/+4P/5/92+v/v+/r////////8////AAAAAAA=","15":"b:f+r/+4P/5/92+v/v+/r////////8////AAAAAAA=","28":"b:f+r/+4P/5/92+v/v+/r////////8////AAAAAAA=","29":"b:f+r/+4P/5/92+v/v+/r////////8////AAAAAAA=","38":"b:f+r/+4O/5/92+v/v+/j////////8////AAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nScrollArea/N8nScrollArea.vue":{"50":"b:f+r/+4P/5/9i+v/P+/j99///P/H8////AAAAAAA=","68":"b:f+r/+4P/5/9i+v/P+/j99///P/H8////AAAAAAA=","82":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","104":[31,33,46],"125":[46],"144":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","163":"b:f+r/+4P/5/9i+v/P+/j99///P/H8////AAAAAAA=","172":"b:f+r/+4P/5/9i+v/P+vj99///P/H8////AAAAAAA=","174":"b:f+r/+4P/5/9i+v/P+/j99///P/H8////AAAAAAA=","181":[4,46,117,119],"189":[46]},"packages/frontend/@n8n/design-system/src/components/N8nSegmentControl/SegmentControl.vue":{"11":"b:D+pF+AN+5fFG+v/H4uIK8H/+P/L/////AAAAAAA=","25":"b:D+pF+AN+5fFG+v/H4uIK8H/+P/L/////AAAAAAA=","26":"b:D+pF+AN+5fFG+v/H4uIK8H/+P/L/////AAAAAAA=","44":"b:D+pF+AN+5fFG+v/H4uIK8H/+P/L/////AAAAAAA=","48":"b:D+pF+AN+5fFG+v/H4uIK8H/+P/L/////AAAAAAA=","49":"b:D+pF+AN+5fFG+v/H4uIK8H/+P/L+////AAAAAAA=","55":"b:AiAFAABAAAACgL8AAAAAAAAAAAAA5g8cAAAAAAA=","59":"b:AiAFAABAAAACgL8AAAAAAAAAAAAA5g8cAAAAAAA=","62":[46,187],"73":[46],"88":"b:AiAFAABAAAACgL8AAAAAAAAAAAAA5g8cAAAAAAA=","96":"b:AiAFAABAAAACgL8AAAAAAAAAAAAA5g8cAAAAAAA=","105":"b:D+pF+AN+5fFG+v/H4uIK8H/+P/L/////AAAAAAA=","132":"b:D+pF+AN+5fFG+v/H4uIK8H/+P/L/////AAAAAAA=","134":"b:D+pF+AN+5fFG+v/H4uIK8H/+P/L/////AAAAAAA=","141":"b:D+pF+AN+5fFG+v/H4uIK8H/+P/L/////AAAAAAA=","142":"b:D+pF+AN+5fFG+v/H4uIK8H/+P/L+////AAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nSegmentControl/SegmentControlItem.vue":{"18":"b:D+pF+AN+5fFG+v/H4uIK8H/+P/L/////AAAAAAA=","23":"b:D+pF+AN+5fFG+v/H4uIK8H/+P/L/////AAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nSelect/Select.vue":{"25":"b:bupH+IDuQl92Ov9PiPIGUu+vP/Ps///WAAAAAAA=","83":"b:bupH+IDuQl92Ov9PiPIGUu+vP/Ps///WAAAAAAA=","87":"b:bupH+IDuQl92Ov9PiPIGUu+vP/Ps///WAAAAAAA=","107":"b:bupH+IDuQl92Ov9PiPIGUu+vP/Ps///WAAAAAAA=","108":"b:bupH+ICuQl92Ov9PiPIGUu+vP/Ps///WAAAAAAA=","116":"b:bupH+IDuQl92Ov9PiPIGUu+vP/Ps///WAAAAAAA=","129":"b:bupH+IDuQl92Ov9PiPIGUu+vP/Ps///WAAAAAAA=","133":[29,43,9,45,60,65,158,70],"137":[1,113],"141":[90,109,6,9,45,126,129,54,56,166,16,183],"170":[113,183,190],"174":"b:bupH+IDuQl92Ov9PiPIGUu+vP/Ps///WAAAAAAA=","195":"b:bupH+IDuQl92Ov9PiPIGUu+vP/Ps///WAAAAAAA=","197":"b:ZiIHoAAsQB1iADQCAAACAACAAPEAgAVEAAAAAAA=","203":"b:ZgIFgAAsQAFAAAACAAACAACAADAAAAQAAAAAAAA=","206":"b:ZgIFgAAsQAFAAAACAAACAACAADAAAAQAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nSendStopButton/N8nSendStopButton.vue":{"5":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","30":"b:cABayABABwAAAAAAAIDhAQAAAAAAAAAAAAAAAAA=","34":[33,46],"36":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","62":"b:f+r/+4P/5/92+v/v+vv/////////////AAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nSpinner/Spinner.vue":{"7":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","18":"b:f+r/+4P/5/92+v/v/v//////////////AAAAAAA=","54":[46]},"packages/frontend/@n8n/design-system/src/components/N8nSuggestedActions/SuggestedActions.vue":{"39":"b:D+Jt+ANe5/FA+v5GoEAIAH5uJbDs/+/fAAAAAAA=","48":[46],"50":[46,75],"53":"b:D+Jt+ANe5/FA+v5GoEAIAH5uJbDs/+/fAAAAAAA=","64":[44,46,62,75],"66":"b:D+Jt+ANe5/FA+v5GoEAIAH5uJbDs/+/fAAAAAAA=","70":[46],"74":[44,46,62,75],"77":[44,46,62,75],"82":[46,75],"83":[44,46,62,75],"87":[46],"89":[44,46,62,75],"99":[46,75],"107":[44,46,62,75],"111":[44,46,62,75],"119":[46],"120":[44,46,62,75]},"packages/frontend/@n8n/design-system/src/components/N8nTabs/Tabs.vue":{"12":"b:TurHeYDuQF9COv9NoHIEWu+vP3Hs/3/TAAAAAAA=","25":"b:TurHeYDuQF9COv9NoHIEWu+vP3Hs/3/TAAAAAAA=","33":"b:TurHeYDuQF9COv9NoHIEWu+vP3Hs/3/TAAAAAAA=","43":"b:TuoFaADiQBUAOn5FgAAEUimoHzDs/1tTAAAAAAA=","53":"b:TurHeYDuQF9COv9NoHIEWu+vP3Hs/3/TAAAAAAA=","55":[29,43,45,46,47,114,58,59,60,158,70,85,88],"67":[46],"68":[46,60,176,85],"73":[46],"79":[46],"80":[46],"81":"b:TurHeYDuQF9COv9NoHIEWu+vP3Hs/3/TAAAAAAA=","101":"b:TurHeYDuQF9COv9NoHIEWu+vP3Hs/3/TAAAAAAA=","108":[46],"109":[46],"110":"b:TurHeYDuQF9COv9NoHIEWu+vP3Hs/3/TAAAAAAA=","119":[46],"129":[46],"136":"b:AAICIIDoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","143":[46],"158":[46,60,176,85],"159":[46],"179":[46]},"packages/frontend/@n8n/design-system/src/components/N8nText/Text.vue":{"21":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","29":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","49":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","51":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","55":"b:f+r/+4P/5/92+v/v+vv/////////////AAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nTooltip/Tooltip.vue":{"21":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","37":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","45":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","46":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","48":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","57":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","62":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","63":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","73":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","75":"b:T+pHaQG65Plg+v/MgGAM8X+6/zD+939+AAAAAAA=","77":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","88":"b:f+r/+4P/5/92+v/v+vv/////////////AAAAAAA=","94":"b:f+r/+4O/5/92+v/v+/v/////////////AAAAAAA=","98":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","101":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","109":"b:DoAEAAEQQEEAMAAAgAAIAQAAAQBABAKAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/PreviewBadge/PreviewBadge.vue":{"9":"b:BsoDIIDoAF52EECpGRgGCoCBwF8AAQDBAAAAAAA=","17":"b:BsoDIIDoAF52EECpGRgGCoCBwF8AAQDBAAAAAAA=","22":"b:BsoDIIDoAF52EECpGRgGCoCBwF8AAQDBAAAAAAA=","26":"b:BsoDIIDoAF52EECpGBgGCoCBwF8AAQDBAAAAAAA="},"packages/frontend/@n8n/design-system/src/composables/useAutosizeTextarea.ts":{"41":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","57":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","70":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","116":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","141":"b:f+r/+4O/5/92+v/v+/v/////////////AAAAAAA=","152":"b:T+pf+gO+5/12+v9Hk/Pv83//f/P8////AAAAAAA=","162":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","168":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA="},"packages/frontend/@n8n/design-system/src/composables/useCharacterLimit.ts":{"15":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","19":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","21":[46],"23":[27,30,31,33,46],"25":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA="},"packages/frontend/@n8n/design-system/src/composables/useI18n.ts":{"4":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","6":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/@n8n/design-system/src/composables/useIconBodyLoader.ts":{"9":[46],"20":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/@n8n/design-system/src/composables/useMessage.ts":{"14":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","15":[68,169,178,86,89],"49":"b:AAIAAACAAAAQAEACAAAFAAAAAAEABgRBAAAAAAA=","64":[112,9,47,114,152,68,169,170,178,86,184,190],"111":[57,136,162]},"packages/frontend/@n8n/design-system/src/composables/useResizablePanel.ts":{"75":[46],"79":[46],"83":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","88":[46],"93":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","109":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","113":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","116":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","119":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","140":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","150":[46],"159":[46],"164":[46],"170":[46],"180":"b:DuoNaAFiRBEAun5HgAABUymoHzDk/1vfAAAAAAA=","184":[46],"190":[46],"195":"b:f+pv+AN+5/FA+v/HwuAJ8H/+P7D+////AAAAAAA=","199":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","202":"b:Dup9eQBuR1FAOv9EgGLwV2+uPzDk/n8SAAAAAAA=","211":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","215":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","218":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","225":"b:f+pv+AN+5/FA+v/HwuAJ8H/+P7D+////AAAAAAA=","232":"b:CgAMAAFABAAAiEAAAAABAAAAAQAABwAdAAAAAAA=","241":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","264":[46],"288":[46],"293":[46],"300":[46],"305":"b:DuoNaAFiRBEAun5HgAABUymoHzDk/1vfAAAAAAA=","317":"b:DuoNaAFiRBEAun5HgAABUymoHzDk/1vfAAAAAAA=","328":[46],"341":[46],"347":[46],"353":[46],"379":[46],"386":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","389":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","392":"b:f+pv+AN+5/FA+v/HwuAJ8H/+P7D+////AAAAAAA=","395":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA="},"packages/frontend/@n8n/design-system/src/composables/useTooltipAppendTo.ts":{"7":"b:D+pt+AN+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","11":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","14":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA="},"packages/frontend/@n8n/design-system/src/directives/n8n-html.ts":{"19":"b:TupF+oPuQFtWOv/GguIGUW+v/3Ps/n/SAAAAAAA=","31":"b:TupF+oPuQFtWOv/GguIGUW+v/3Ps/n/SAAAAAAA="},"packages/frontend/@n8n/design-system/src/icons/lucide/bucket.ts":{"16":"b:T+pt+gF+5/FC+v9HgGMI8H/+P/Dv////AAAAAAA="},"packages/frontend/@n8n/design-system/src/icons/lucide/index.ts":{"16":"b:T+pt+gF+5/FC+v9HgGMI8H/+P/Dv////AAAAAAA=","22":"b:T+pt+gF+5/FC+v9HgGMI8H/+P/Dv////AAAAAAA=","27":[46]},"packages/frontend/@n8n/design-system/src/locale/format.ts":{"8":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","9":"b:AAAAAIDAAB4AAEAJABAEAoABAAAAAQDAAAAAAAA=","12":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","30":"b:AAAAAIDAAB4AAEAJABAEAoABAAAAAQDAAAAAAAA="},"packages/frontend/@n8n/design-system/src/locale/index.ts":{"15":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","35":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","37":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/@n8n/design-system/src/plugin.ts":{"8":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/@n8n/design-system/src/utils/cn.ts":{"4":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA="},"packages/frontend/@n8n/design-system/src/utils/typeguards.ts":{"1":"b:bupH+IDuQl92Ov9PiPIGUu+vP/Ps///WAAAAAAA="},"packages/frontend/@n8n/design-system/src/utils/uid.ts":{"6":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/@n8n/design-system/src/v2/components/Checkbox/Checkbox.vue":{"11":"b:AgAEAgBAAEAAiAAACAAAAEAAwAABBgDfAAAAAAA=","14":"b:AgAEAgBAAEAAiAAACAAAAEAAwAABBgDfAAAAAAA=","19":"b:AgAEAgBAAEAAiAAACAAAAEAAwAABBgDfAAAAAAA=","22":"b:AgAEAgBAAEAAiAAACAAAAEAAwAABBgDfAAAAAAA=","28":[46,150,151,75,18,190,191],"32":"b:AgAEAgBAAEAAiAAACAAAAEAAwAABBgDfAAAAAAA=","37":"b:AgAEAgBAAEAAiAAACAAAAEAAwAABBgDfAAAAAAA=","45":"b:AgAEAgBAAEAAiAAACAAAAEAAwAABBgDfAAAAAAA=","47":"b:AgAEAgBAAEAAiAAAAAAAAAAAwAABBgDcAAAAAAA=","56":"b:AgAEAgBAAEAAiAAACAAAAEAAwAABBgDfAAAAAAA=","57":"b:AgAEAgBAAEAAgAAAAAAAAAAAAAABBgDcAAAAAAA="},"packages/frontend/@n8n/design-system/src/v2/components/Select/Select.vue":{"40":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","42":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","46":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","69":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","75":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","97":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","105":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","109":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","113":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","117":[46],"129":[46],"138":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","171":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","179":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","229":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","230":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","233":"b:f+r/i4P/5392+v/v+/v/////////////AAAAAAA=","234":"b:f+r/i4P/5392+v/v+/v/////////////AAAAAAA=","237":[46],"245":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","249":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","253":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","257":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","261":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","272":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","275":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","283":[17,46,114,62,69],"291":[46],"304":[17,46,114,62,69],"312":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","319":"b:AAACAIDAAF4AAEAJABAFAoABAAAAAQDAAAAAAAA=","328":[46],"329":[46],"332":[46],"337":"b:AAACAIDAAF4AAEAJABAFAoABAAAAAQDAAAAAAAA=","343":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","352":[17,46,114,62,69],"353":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","362":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","364":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","372":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","385":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","386":"b:AAACAIDAAF4AAEAJABAFAoABAAAAAQDAAAAAAAA=","395":[46],"396":[46],"417":"b:f+r/i4P/5392+v/v+/v/////////////AAAAAAA=","425":[46],"430":"b:f+r/i4P/5392+v/v+/v/////////////AAAAAAA=","437":"b:f+r/i4P/5392+v/v+vv/////////////AAAAAAA=","448":[17,46,58,69],"454":"b:f+r/i4P/5392+v/v+/v/////////////AAAAAAA=","458":"b:f+r/i4P/5392+v/v+vv/////////////AAAAAAA=","463":"b:f+r/i4P/5392+v/v+/v/////////////AAAAAAA=","466":"b:f+r/i4P/5392+v/v+/v/////////////AAAAAAA=","469":"b:f+r/i4P/5392+v/v+/v/////////////AAAAAAA=","484":[46]},"packages/frontend/@n8n/design-system/src/v2/components/Select/SelectItem.vue":{"19":"b:f+r/i4P/5392+v/v+/v/////////////AAAAAAA=","23":"b:f+r/i4P/5392+v/v+/v/////////////AAAAAAA=","28":"b:f+r/i4P/5392+v/v+/v/////////////AAAAAAA=","33":"b:f+r/i4P/5392+v/v+/v/////////////AAAAAAA=","34":"b:f+r/i4P/5392+v/v+/v/////////////AAAAAAA=","43":[17,46,114,62,69],"44":"b:f+r/i4P/5392+v/v+/v/////////////AAAAAAA=","46":"b:f+r/i4P/5392+v/v+/v/////////////AAAAAAA=","50":"b:f+r/i4P/5392+v/v+/v/////////////AAAAAAA=","57":"b:f+r/i4P/5392+v/v+/v/////////////AAAAAAA="},"packages/frontend/@n8n/frontend-constants/src/views.ts":{"20":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/@n8n/frontend-module-sdk/src/declareCapability.ts":{"19":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/@n8n/frontend-module-sdk/src/defineFrontendModule.ts":{"27":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/@n8n/frontend-module-sdk/src/registries/capabilityRegistry.ts":{"16":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","29":[46,123],"39":[46],"55":[46]},"packages/frontend/@n8n/frontend-module-sdk/src/registries/componentRegistry.ts":{"17":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","27":[46]},"packages/frontend/@n8n/frontend-module-sdk/src/registries/modalRegistry.ts":{"16":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","20":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","21":[46],"24":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","63":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA="},"packages/frontend/@n8n/frontend-module-sdk/src/registries/parameterInputRegistry.ts":{"13":[46],"17":[46],"18":[46],"25":[46],"49":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA="},"packages/frontend/@n8n/frontend-module-sdk/src/registries/pushHandlerRegistry.ts":{"9":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","27":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","36":"b:f+Lv+QF+5/FA+v5HoMAJAH5upbDu/+/fAAAAAAA=","40":"b:D+Jt+AF+5/FA+v5HoEAIAH5upbDu/+/fAAAAAAA="},"packages/frontend/@n8n/frontend-module-sdk/src/registries/resourceRegistry.ts":{"25":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA="},"packages/frontend/@n8n/frontend-module-sdk/src/routeNames.ts":{"7":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","32":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/@n8n/frontend-utils/src/htmlUtils.ts":{"24":"b:T6IHOIH44H9y+H5HGMCHEfyv5cXm9u9fAAAAAAA=","26":[39,135,57,136,59,139,82,83,176,182,190],"47":"b:QAICAIAAAAogAAwAAACEAIAJgAQAUENAAAAAAAA=","64":[46],"81":"b:AAIAAADAAAIQAEACAAAFAAABAAEEBgRBAAAAAAA=","88":[46],"92":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","93":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","94":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","100":[46,76,88,89],"117":"b:D+pt+AN+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","138":"b:BsoFGABCAAACMi5AAAAAAACoEQDsZA0AAAAAAAA="},"packages/frontend/@n8n/i18n/src/index.ts":{"41":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","49":[46],"53":"b:T+pN+AF+5/FUuv9EgGII8H+uPzLu/n8eAAAAAAA=","57":[46],"68":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","98":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","106":"b:T+pN+AF+5/FWuv9GgOIK8H+uP3Lu/n8eAAAAAAA=","110":"b:DgBEAAFABUAAgAAAAAAAAAAAAQACBgAcAAAAAAA=","143":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","150":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","158":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","175":"b:BgIBIAAoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","185":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","195":"b:BgIBIAAoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","208":"b:BgIBIAAoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","221":"b:BgIBIAAoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","234":"b:T+pN+AF+53FWuv9GgOIKUH+uP3Lu/n8eAAAAAAA=","243":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","255":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","267":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","282":"b:TupF+ABuQFFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","300":"b:TupF+ABuQFFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","322":"b:TupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","345":[46,172,82,176,84,85],"367":[46],"378":[103,46,54],"385":"b:DyBMWAFw5WEAsDREgEAIAHwmJQBCFiscAAAAAAA=","394":"b:BsoF+ABqQJFAOt9HgmAA8D+yPhD0bl+qAAAAAAA=","412":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","443":[46],"473":[46],"489":[46],"495":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/@n8n/i18n/src/utils.ts":{"9":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","29":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","31":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","34":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","41":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","49":"b:AkBFaABEQEEAKD4EgGAAEGgIIQAodDsCAAAAAAA=","57":"b:AkBFaABEQEEAKD4EgGAAEGgIIQAodDsCAAAAAAA=","58":"b:AkBFaABEQEEAKD4EgGAAEGgIIQAodDsCAAAAAAA="},"packages/frontend/@n8n/rest-api-client/src/api/externalSecrets.ee.ts":{"6":[46],"15":[46],"24":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","38":[43,9,46,60,65,178],"49":[46],"55":[46],"62":[46],"70":[46],"78":[46],"85":[46],"95":[46]},"packages/frontend/@n8n/rest-api-client/src/api/module-settings.ts":{"6":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA="},"packages/frontend/@n8n/rest-api-client/src/api/nodeTypes.ts":{"24":"b:f+pv+gN+5/lC+v/H4uMJ8n/+f/D/////AAAAAAA=","38":"b:f+pv+gN+5/lC+v/H4uMJ8n/+f/D/////AAAAAAA=","62":"b:D+pp+AN+5/FA+v/H4mMI8n/+f7D/////AAAAAAA=","68":[46,129,150,151],"79":[46],"85":[46],"92":[41,46,176,16],"99":[1,46,178],"111":[46,178,179],"123":[46,182,87],"135":[46]},"packages/frontend/@n8n/rest-api-client/src/api/roles.ts":{"13":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","17":[46],"21":[46],"28":[46],"36":[46],"45":[46],"52":[46],"64":[46]},"packages/frontend/@n8n/rest-api-client/src/api/settings.ts":{"6":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/@n8n/rest-api-client/src/api/usage.ts":{"6":"b:D+pt+IP/5/9g+v/P+nMM8v//P7D+////AAAAAAA=","10":[46],"20":[46],"24":[46],"30":[46]},"packages/frontend/@n8n/rest-api-client/src/api/users.ts":{"92":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","98":[108,46,100],"105":[46],"109":[46],"121":[46],"128":[46],"135":[46],"142":[46],"149":[46,154,100],"156":[46,100],"163":[46],"170":[46],"177":[46,144,14,75,18,15,16],"184":[46],"192":[46],"199":[46,69],"206":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","220":[46],"227":[46],"234":[46],"247":[46,69]},"packages/frontend/@n8n/rest-api-client/src/api/versions.ts":{"50":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","59":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA="},"packages/frontend/@n8n/rest-api-client/src/api/workflowHistory.ts":{"52":[46,168],"65":"b:C6BtgAFU5/BA4nQDIAMIAEhsAbAOn+HdAAAAAAA=","77":[31,33,46],"92":[46],"105":[46]},"packages/frontend/@n8n/rest-api-client/src/utils.ts":{"14":[46],"45":"b:AgIBA4BCAAAgAAACEJsEAAAAgAQAEAAAAAAAAAA=","81":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","86":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","88":"b:f+r/+4P/5/92+v/P+/j/////f/P8////AAAAAAA=","89":"b:f+r/+4P/5/92+v/P+/j/////f/P8////AAAAAAA=","91":[66,153,68,69,191],"100":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","179":"b:AADoAYDhB15gCMAJGBAGCoABwPAAAUDJAAAAAAA=","196":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","214":"b:f+r/+4P/5/92+v/v//v////////+////AAAAAAA=","223":[31,33,46,150,151],"232":[46],"241":[27,28,29,30,31,33,46],"251":[33,46],"276":[27,28,29,30,31,46]},"packages/frontend/@n8n/stores/src/cloudPlan.store.ts":{"31":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","43":[46],"45":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","49":[46],"55":[95,46],"57":[95,46],"60":[95,46],"63":[95,46],"72":[95,46],"79":[95,46],"85":[95,46],"87":[95,46],"97":[95,46],"99":[95,46],"101":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","103":[95,46],"105":"b:AAAAAIDBAB4gAEAJGBAEAoABABAAAQDBAAAAAAA=","106":[46],"125":[95,46],"130":[46],"135":[93,95,46,154,100],"141":[95,46],"152":[46],"156":[95,46],"172":[95,46],"178":[46],"187":[46],"197":[95,46],"218":[95,46],"219":[46],"233":[95,46],"244":[95,46],"252":[95,46],"272":[46]},"packages/frontend/@n8n/stores/src/composables/useAssistantTopUpEligibility.ts":{"20":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","26":[46,118]},"packages/frontend/@n8n/stores/src/composables/useBasePageRedirectionHelper.ts":{"36":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","44":[46],"50":[46],"91":[46],"100":[46],"110":[46],"140":[46]},"packages/frontend/@n8n/stores/src/composables/useCloudUbbActive.ts":{"21":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","27":[46]},"packages/frontend/@n8n/stores/src/metaTagConfig.ts":{"1":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","8":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","34":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/@n8n/stores/src/notifications.store.ts":{"22":"b:T+oH+IN+4P9i+v/H+vuP8f////X/////AAAAAAA=","26":[104,105,108,100,161]},"packages/frontend/@n8n/stores/src/rbac.store.ts":{"9":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","70":[46],"76":[46],"80":[46],"86":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","90":[46],"105":[46],"122":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/@n8n/stores/src/registries/upgradeRedirectGuard.ts":{"16":[46],"18":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","22":[46]},"packages/frontend/@n8n/stores/src/roles.store.ts":{"23":[17,46,58,60,69],"24":[17,46,58,60,69],"35":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","51":[17,46,58,60],"52":[17,46,58,60],"56":[46,69],"57":[46,69],"60":[46,69],"62":[46,69],"70":[46,69],"71":[46,69],"74":[17,46,58,60],"76":[17,46,58,60],"84":[113,45,46,158,70],"85":[113,45,46,158,70],"88":[46,156,159,190],"89":[46,156,159,190],"92":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","96":[46],"100":[46],"104":[46],"108":[46],"112":[46],"116":[46],"123":[46]},"packages/frontend/@n8n/stores/src/settings.store.ts":{"29":[46],"44":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","73":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","75":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","77":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","79":[46],"81":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","83":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","85":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","90":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","92":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","94":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","96":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","98":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","100":"b:f+r/+4P/5/92+v/v+/j////////8////AAAAAAA=","102":[95,46],"104":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","106":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","108":"b:f+r/+4P/5/92+v/v///////////+////AAAAAAA=","110":[46],"114":[95,46],"116":[95,46],"118":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","122":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","124":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","128":[27,28,29,30,31,102,33,46,63],"132":"b:f+r/+4P/5/92+v/v//v/////////////AAAAAAA=","134":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","136":"b:f+r/+4P/5/92+v/v//v/////////////AAAAAAA=","138":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","140":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","144":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","156":[46],"160":"b:furHeYDvQl9COv9PiPIHUu+vP3Hs/3/TAAAAAAA=","164":[4,111,5,112,6,17,46],"166":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","170":"b:f+r/+4P/5/92+v/v+/r////////+////AAAAAAA=","172":"b:f+r/+4P/5/92+v/v+/j////////8////AAAAAAA=","176":[46],"180":[46],"182":[46],"184":"b:D+p9+IP/5/9g+v/P23v89///P7D+////AAAAAAA=","188":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","190":[46],"192":"b:BqAFAABEAMAkCNIIgHgAEHX+f/oYsHm9AAAAAAA=","194":[46],"198":[93,46,154,100],"200":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","202":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","204":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","208":"b:TupHeABuQFVAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","217":[17,46,58,60],"220":[23,24,46],"224":[2,46],"228":[17,46,58,69],"232":"b:AAAFWIDAAB4AAFAJAFAAApATOAAAAYPgAAAAAAA=","236":"b:D+pt+AN+5/FA+v/H4mMI8H/+P7D+////AAAAAAA=","242":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","244":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","246":[46,191],"248":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","250":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","252":"b:X+r/+4P+5/92+v/v+/v/////////////AAAAAAA=","254":[46,150,151],"258":[46],"260":"b:f+r/+4P/5/92+v/v+/j////////8////AAAAAAA=","261":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","263":[46,155],"265":[46,62,75],"269":[95,46],"271":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","273":[46],"275":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","277":"b:D+pt+AN+5/FA+v/H4mAI8H/+P7D8////AAAAAAA=","281":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","313":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","317":[46],"321":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","325":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","329":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","333":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","337":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","391":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","401":[46],"405":[46],"415":[46,191],"416":[46,191],"417":[46,191],"423":[46,62,75],"428":[46],"432":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","437":[46]},"packages/frontend/@n8n/stores/src/useAgentRequestStore.ts":{"18":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","23":[46],"34":[46],"38":[46],"51":[46],"64":[0,3,46,22,13,144,76,170,172,81,173],"70":[46],"78":"b:DSBEGABAAAEAED4AAEAAACQEAQBAdAsAAAAAAAA="},"packages/frontend/@n8n/stores/src/useRootStore.ts":{"41":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","74":"b:f+r/+4P/5/92+v/P+/v/9/////f/////AAAAAAA=","76":"b:AAIAAABCQAEAAAAAgCIAEAAAAAAAFAcAAAAAAAA=","78":"b:AAIAAABCQAEAAAAAgCIIEAAAAAAAFAcAAAAAAAA=","82":[46,18],"86":"b:AAIAAABCQAEAAAAAgCIAEAAAAAAAFAcAAAAAAAA=","88":"b:DgIEAAFCQAEAAAAAgCIAEABAAQACFAcAAAAAAAA=","92":[46],"96":"b:AAIAAABCQAEAAAAAgCIAEAAAAAAAFAcAAAAAAAA=","98":"b:AAIAAABCQAEAAAAAgCIAEAAAAAAAFAcAAAAAAAA=","102":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","104":"b:DyBEWAFw5GEAsD5EgEAIAHwmJQBC9mucAAAAAAA=","106":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","108":[27,28,1,2,46,18,176,178],"110":[46],"112":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","114":"b:f+r/+4P/5/92+v/v//v/////////////AAAAAAA=","116":[29,9,46],"118":[46],"120":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","122":[46,62,75],"124":[46,62,75],"126":[46,62,75],"128":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","133":[46],"143":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","148":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","153":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","158":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","162":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","166":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","170":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","174":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","178":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","182":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","186":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","190":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","195":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","199":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","203":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","207":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","211":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","215":[46],"219":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","223":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","227":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","231":[46],"235":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/@n8n/stores/src/users.store.ts":{"40":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","41":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","42":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","44":[45,46,60,88],"47":[46],"53":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","66":[46],"74":[46],"75":[46],"78":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","87":[46],"88":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","99":"b:D+r/+4P/5/9i+v/P63j89///P/H8////AAAAAAA=","101":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","105":"b:AAIBIABKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","107":[46],"109":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","111":[45,46,60,88],"113":"b:RsoBKABqQJFAOt9EgCAA8C+gzhDkbh8KAAAAAAA=","115":[93,46,154,100],"117":[93,46,154,100],"119":[46],"121":[1,2,46,144,14,75,18,15,16],"125":[91,46],"129":[46,144,14,75,18,15,16],"135":"b:AAAFWABAAAAAEFADAEAAAhASKAAkBAIgAAAAAAA=","138":[46],"146":[46,69],"152":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","153":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","175":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","188":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","197":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","211":[46],"215":[46,69],"220":[46],"234":[108,46,100],"243":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","247":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","251":[46],"259":[46],"290":[46],"303":[46],"307":[46],"319":[46],"323":[46],"327":[46],"331":[46,154,100],"337":[46,154,100],"345":[46,100],"356":[46],"360":[46],"364":[46],"375":[46],"379":[46],"383":[46,69],"388":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","405":[46],"408":[46],"416":[46],"425":[46],"429":[46],"433":[46],"440":"b:D+p9+IP/5/9g+v/P23v89///P7D+////AAAAAAA=","447":[46],"451":[46],"455":[46],"459":[46],"466":[46,100],"474":[46],"479":[46],"483":[46,69],"488":[46],"501":[46,69],"510":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA="},"packages/frontend/@n8n/stores/src/versions.store.ts":{"32":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","59":[46],"67":[46],"68":[46],"71":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","81":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","85":[46],"108":[46],"112":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","116":[39,46],"120":"b:D+r/+wP/5/9i+v/P+3j89///P/H8////AAAAAAA=","126":"b:f+r/+wP/5/92+v/v//j////////8////AAAAAAA=","132":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","142":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","157":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","158":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","159":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","162":"b:f+r/+wP/5/92+v/v//j////////8////AAAAAAA=","166":[46],"175":"b:D+r/+wP/5/9i+v/P+3j89///P/H8////AAAAAAA=","179":[46],"184":[46],"186":[46],"190":"b:f+r/+wP/5/92+v/v//j////////8////AAAAAAA=","195":"b:f+r/+wP/5/92+v/v//j////////8////AAAAAAA=","202":"b:f+r/+wP/5/92+v/v//j////////8////AAAAAAA=","209":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","228":[46],"251":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","255":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","278":[39,46]},"packages/frontend/editor-ui/src/app/App.vue":{"42":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","57":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","81":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","82":[46],"86":"b:CsIBMABgQAEAAL4EgCAAAACAAADA4AcAAAAAAAA=","93":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","99":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","105":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","106":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","113":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","126":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","133":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","138":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","142":[46],"146":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","153":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/api/favorites.ts":{"16":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","20":[46],"31":[46]},"packages/frontend/editor-ui/src/app/api/workflow-dependencies.ts":{"10":"b:C6JtAIH05/5A4nQLIBAMAshtAfAMn2HdAAAAAAA=","23":[46,59,62,156,157,159,75,168,183,184,190],"36":[46]},"packages/frontend/editor-ui/src/app/api/workflows.ts":{"26":"b:BsoF+AJ6QBFAON/GwmMA8D+SPhD3Zp/rAAAAAAA=","39":"b:BsoF+AJ6QBFAON/GwmMA8D+SPhD3Zp/rAAAAAAA=","65":"b:C6BtAAFU5/hA6vQDIAAIAkhsAbAMn+HdAAAAAAA=","69":"b:BsoF+AJ6QBFAON/EwGAA8D+SPhD0Zp9rAAAAAAA=","80":[46,19,48,21,49,22,50,121,62,75,187],"96":[46,150,151],"107":"b:AAAAAIDBAB4gAMAJGBAEAoABABAAAUDBAAAAAAA=","123":"b:D+pt+IP/5/9g+v/P+nAM8v//P7D8////AAAAAAA=","145":"b:DyBEGAFw5WEAsD5EAEAAAHwmJQBC9mscAAAAAAA=","158":"b:C6AFAAFU4PBA4nQDAAAIAEhsAbAMn2HdAAAAAAA=","169":"b:D+Jt+AN+5/FA+v5HoEAIAH5uJbDs/+/fAAAAAAA="},"packages/frontend/editor-ui/src/app/capabilities.manifest.ts":{"21":[46],"22":[46],"26":[46],"48":[46,123],"49":[46],"50":[46],"57":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/componentSlots.manifest.ts":{"12":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","16":[46]},"packages/frontend/editor-ui/src/app/components/Banner.vue":{"22":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","36":[46],"40":[46],"48":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","58":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","65":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","71":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","78":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA="},"packages/frontend/editor-ui/src/app/components/BottomMenu.vue":{"23":"b:f+r/+4O/5/9i+v/P+/j99///P/H8////AAAAAAA=","33":[91,165],"36":[91,165],"78":[91,165],"84":"b:f+r/+4O/5/9i+v/P+/j99///P/H8////AAAAAAA=","104":[91,165],"106":[91,165],"118":[91,165],"129":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","134":[91,165],"168":"b:f+r/+4O/5/9i+v/P+/j99///P/H8////AAAAAAA="},"packages/frontend/editor-ui/src/app/components/ConnectionTracker.vue":{"26":"b:D+pt+AM+5/FA+v/H4mAI8H/+P7j8////AAAAAAA="},"packages/frontend/editor-ui/src/app/components/Draggable.vue":{"18":"b:DupFeoHuQF9AOv9NgHIAUu+vPzDs/3/SAAAAAAA=","40":"b:DupFeoHuQF9AOv9NgHIAUu+vPzDs/3/SAAAAAAA=","44":"b:AAAAAABAABoAADQBAAAAAoABAAAAgQBAAAAAAAA=","78":[46,135,82],"105":[46,135,82],"115":[46,121,135,57,136,59,60,168,82,190],"127":[46,121,135,57,136,59,60,168,82,190],"135":"b:DuoFSoHiQB8AOn5NgFAAUq2tHyDs/1vSAAAAAAA=","140":"b:DupFeoHuQF9AOv9NgHIAUu+vPzDs/3/SAAAAAAA=","149":"b:DupFeoHuQF9AOv9NgHIAUu+vPzDs/3/SAAAAAAA="},"packages/frontend/editor-ui/src/app/components/DraggableTarget.vue":{"15":"b:TupF+ABuQlFWOv9EgGIAUG+uPzLs/n8SAAAAAAA=","31":"b:TupF+ABuQhFGOv9EgGAAUG+uPzLs/n8CAAAAAAA=","32":[46,82],"33":[46],"34":"b:TupF+ABuQlFWOv9EgGIAUG+uPzLs/n8SAAAAAAA=","37":"b:TupF+ABuQlFWOv9EgGIAUG+uPzLs/n8SAAAAAAA=","39":[46,82],"49":"b:QkIFiABkQAECAK8EgGAAQAYIASDAdC8AAAAAAAA=","53":"b:QgIFCABgQAECAK8EgGAAQAYIASDAdC8AAAAAAAA=","57":"b:QkIBAABkQAECAK8EgGAAQAYAAADAcA8AAAAAAAA=","64":[46,82],"79":"b:TupF+ABuQlFWOv9EgGIAUG+uPzLs/n8SAAAAAAA="},"packages/frontend/editor-ui/src/app/components/DropArea/DropArea.vue":{"4":"b:AgBFCABAABEAMFwAACAAAEAIJwAoXBMAAAAAAAA=","6":[46],"8":"b:AgBFCABAABEAMFwAACAAAEAIJwAoXBMAAAAAAAA=","13":"b:AgBFCABAABEAMFwAACAAAEAIJwAoXBMAAAAAAAA="},"packages/frontend/editor-ui/src/app/components/DynamicModalLoader.vue":{"8":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","19":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","20":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","27":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","31":"b:f+r/+4P/5/92+v/v/v//////////////AAAAAAA=","33":[5,112,113,6,46,47,114,66,153,68,100]},"packages/frontend/editor-ui/src/app/components/EnterpriseEdition.ee.vue":{"6":"b:BgIBIABoAFhCAAACAIACAAKAAPAAAARAAAAAAAA=","17":"b:BgIBIABoAFhCAAACAIACAAKAAPAAAARAAAAAAAA=","18":"b:BgIBIABoAFhCAAACAIACAAKAAPAAAARAAAAAAAA=","23":"b:BgIBIABoAFhCAAACAIACAAKAAPAAAARAAAAAAAA="},"packages/frontend/editor-ui/src/app/components/FocusSidebar.vue":{"32":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","51":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","52":[148,163],"53":"b:D+pN+AM+5vFA+v/HgmII8H/+P7D+////AAAAAAA=","55":[148,163],"60":[148,163],"65":[148,163],"72":[148,163],"83":[148,163],"87":"b:D+pN+AM+5vFA+v/HgmII8H/+P7D+////AAAAAAA=","95":[148,163],"111":[148,163],"115":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","119":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","120":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","131":"b:D+pN+AM+5vFA+v/HgmII8H/+P7D+////AAAAAAA=","159":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","163":"b:AgAMAAAABBAAiEAAAAAAAAAAAAAABwCdAAAAAAA=","166":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","188":[148,163]},"packages/frontend/editor-ui/src/app/components/FreeAiCreditsCallout.vue":{"21":"b:DupFeABuQlFCOv9GgOICUG+uP3Ds/n8SAAAAAAA=","41":[46],"45":[46],"51":[46],"55":"b:DupFeABuQlFCOv9GgOICUG+uP3Ds/n8SAAAAAAA=","57":"b:DupFeABuQlFCOv9GgOICUG+uP3Ds/n8SAAAAAAA=","59":[46],"63":"b:DupFeABuQlFCOv9GgOICUG+uP3Ds/n8SAAAAAAA=","78":[46],"89":[46],"90":[46]},"packages/frontend/editor-ui/src/app/components/KeyboardShortcutTooltip.vue":{"16":"b:f+r/+4P/5/9i+v/P+/v99///P/H/////AAAAAAA=","17":[46],"21":"b:f+r/+4P/5/9i+v/P+/v99///P/H/////AAAAAAA="},"packages/frontend/editor-ui/src/app/components/MainHeader/ActionsDropdownMenu.vue":{"61":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","99":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","100":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","108":[42,53,54,55,134,57,60,157,73,89],"133":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","141":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","143":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","147":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","156":"b:AAAFWAAAAAIAAFAAAEAAABASOAAAAAMgAAAAAAA=","160":"b:AAAFWAAAAAIAAFAAAEAAABASOAAAAAMgAAAAAAA=","178":"b:AAAFWAAAAAIAAFAAAEAAABASOAAAAAMgAAAAAAA=","186":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","364":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","370":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","371":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","376":[57,183],"397":"b:AAAFWAAAAEIACFAAAEAAABASOLAgAYMhAAAAAAA=","402":"b:AAAFWAAAAEIACFAAAEAAABASOLAgAYMhAAAAAAA=","439":[57,75],"461":[57],"479":[57],"559":[57],"560":[57],"592":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","596":[19,50,57,60,168,86,184],"603":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA="},"packages/frontend/editor-ui/src/app/components/MainHeader/MainHeader.vue":{"52":"b:D+oF+AM+4PNA+v/H4mAI8H/+P7D8////AAAAAAA=","60":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","61":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","66":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","67":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","68":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","69":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","70":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","72":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","82":"b:DuoF+AIuQBNAuv9GgmAAUH+uPzDk///fAAAAAAA=","86":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","90":[19,50,57,168,86,184],"94":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","99":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","106":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","116":"b:D+oF+AM+4PNA+v/HwmAI8H/+P7D8////AAAAAAA=","136":[1,57,169,170,79,18,186,187,188],"157":[1,57,187,188],"188":[1,57,169,170,79,18,186,187,188],"214":[57],"232":[57]},"packages/frontend/editor-ui/src/app/components/MainHeader/TabBar.vue":{"22":[1,57,169,170,79,18,186,187,188],"24":"b:D+oF+AM+4PNA+v/H4mAI8H/+P7D8////AAAAAAA="},"packages/frontend/editor-ui/src/app/components/MainHeader/WorkflowDetails.vue":{"39":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","71":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","75":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","79":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","83":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","88":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","100":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","101":[57,60,86,184],"108":[57],"114":"b:AAAFWAAgAAIAAFAAAEAAABASOAAAAINgAAAAAAA=","140":[57],"184":[57],"205":[57],"249":[57,184],"259":[57,184],"310":[57],"312":[57],"318":"b:AAAFWAAAAAIAAFAAAEAAABASOAAAAAMgAAAAAAA=","324":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","332":[19,50,57,60,168,86,184],"339":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","349":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","388":[57,184],"395":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA="},"packages/frontend/editor-ui/src/app/components/MainHeader/WorkflowHeaderDraftPublishActions.vue":{"79":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","85":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","87":[57],"88":[57],"91":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","110":[57],"114":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","118":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","122":[57],"124":[57],"127":[57],"130":[57],"136":[57],"148":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","149":[57,60,86,184],"160":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","162":[57],"171":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","175":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","181":"b:BsoEoAACQAMACAACgiAAEACIAAAAABWiAAAAAAA=","183":"b:DsoFqAESQMMAKk4CgiAIEGDIAQAodBfjAAAAAAA=","185":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","188":"b:D+pt+AM+5/NA+v/G4mAI8H/+P7D8////AAAAAAA=","214":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","215":[57],"216":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","218":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","248":"b:D+Jt+AM+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","249":"b:D+Jt+AM+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","250":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","251":[44,134,57,62,75,184,185],"253":"b:BsoF+AI6QBNAON/HwmAA8D+SPhD0Zp/rAAAAAAA=","260":[57],"271":[57],"277":[57,75],"302":[134,57,75,184,185],"307":[134,57,75,184,185],"314":[57],"320":[57],"331":[57],"341":[57],"350":[57],"355":[57],"364":[57],"370":[57],"385":[134,57,75,184,185],"420":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","561":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","566":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","581":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","592":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","601":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","602":[134,57,60,75,86,184,185],"612":[57],"619":[57],"624":"b:D+p9+AM+5/NA+v/H4mD493/+P7D8////AAAAAAA=","629":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","631":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","667":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","672":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","675":[57],"694":[57],"729":[57],"739":[57],"760":[57],"785":[57],"786":[57],"791":[57],"795":[57],"800":[57],"806":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","811":[19,50,57,60,168,86,184],"815":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","826":[57],"845":[57],"860":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","907":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","918":[57],"927":[57]},"packages/frontend/editor-ui/src/app/components/MainSidebar.vue":{"36":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","83":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","86":"b:D+r/+wO/5/9i+v/H+3j89///P/H8////AAAAAAA=","91":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","93":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","226":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","228":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","229":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","231":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","235":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","247":[91,95,114,59,60],"248":[91,95,114,59,60],"253":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","257":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","262":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","273":[121,60,156,168,86,88,184,190,89,191],"282":[165],"304":[91,165],"360":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","393":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA="},"packages/frontend/editor-ui/src/app/components/MainSidebarHeader.vue":{"37":"b:D+pf+4O+5/9C+v/P4WDs8///P/H8////AAAAAAA=","41":[91,95,114,59,60],"69":[91,40,4,111,5,112,6,17,95,114,59,60,100,88],"114":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","123":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","132":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","144":[107,40,45,60,100,69,88],"157":[100],"169":"b:f+r/+4O/5/9i+v/P+/j99///P/H8////AAAAAAA="},"packages/frontend/editor-ui/src/app/components/MainSidebarSourceControl.vue":{"27":[99],"37":[99],"41":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","47":[99],"53":[99],"62":[99],"84":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","111":[99],"144":[99],"170":[99]},"packages/frontend/editor-ui/src/app/components/ModalDrawer.vue":{"7":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","34":[46],"40":"b:AIIlWADKAAZCeFADEEAAABATOEU2oMPpAAAAAAA=","50":[46],"61":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","71":[46],"75":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","89":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","91":[39,46],"92":[46]},"packages/frontend/editor-ui/src/app/components/ModalRoot.vue":{"5":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","25":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","26":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/components/Modals.vue":{"131":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","132":[46],"134":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","139":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","146":[46],"168":[46,165],"172":[46],"176":[29,43,9,45,46,60,65,158,70],"180":[46],"186":[46,165,189],"190":[46],"194":[46,183],"198":[46],"202":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","206":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","212":[46,62,75],"216":[46],"222":[46,69],"228":[46,134,75,184,185],"232":[46,156,159,190],"238":[46,150,151],"242":[46],"246":[46,150,151],"256":[46],"262":[46],"268":[46],"274":[46],"280":[46],"286":[46],"292":[46],"298":[46,65],"304":[46],"314":[46,190],"324":[46],"334":[46,97,89],"343":[46,59],"352":[27,46],"358":[46],"364":[46,136],"370":[46,59,157],"376":[46],"382":[46],"388":[46],"394":[46],"400":[46,182],"406":[46],"412":[46],"418":[46],"424":[46,152],"430":[46],"436":[46,183],"442":[46,134,75,184,185],"448":[46],"454":[46],"463":[46],"469":[46],"475":[46]},"packages/frontend/editor-ui/src/app/components/NodeExecuteButton.vue":{"15":"b:DupFeABuQBFAOv9EgGAAUG+uPzDs/n8CAAAAAAA=","60":"b:DupFeABuQBFAOv9EgGAAUG+uPzDs/n8CAAAAAAA=","75":"b:DAAAGABAAAEAADwAAEAAACQEAQBAUAsAAAAAAAA=","77":[46],"82":"b:DupFeABuQBFAOv9EgGAAUG+uPzDs/n8CAAAAAAA=","94":"b:DupFeABuQBFAOv9EgGAAUG+uPzDs/n8CAAAAAAA=","100":"b:DupFeABuQBFAOv9EgGAAUG+uPzDs/n8CAAAAAAA=","106":"b:DupFeABuQBFAOv9EgGAAUG+uPzDs/n8CAAAAAAA=","121":"b:DsoFeABuQBFAOv9EgGAAUC+MHzDsch8CAAAAAAA=","125":"b:DAAAGABAAAEAADwAAEAAACQEAQBAUAsAAAAAAAA=","137":"b:DAAAGABAAAEAADwAAEAAACQEAQBAUAsAAAAAAAA=","141":"b:DupFeABuQBFAOv9EgGAAUG+uPzDs/n8CAAAAAAA=","150":[46],"153":"b:DupFeABuQBFAOv9EgGAAUG+uPzDs/n8CAAAAAAA="},"packages/frontend/editor-ui/src/app/components/NodeIcon.vue":{"25":"b:T+pt+gF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","43":"b:T+pt+gF+5/FA+v9HgmII8H++P7Du/3//AAAAAAA=","44":"b:T+pt+gF+5/FA+v9HgmII8H++P7Du/3//AAAAAAA=","48":"b:T+pt+gF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","50":"b:T+pt+gF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","51":"b:T+pt+gF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","56":"b:T+pt+gF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","61":"b:T+pt+gF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","66":"b:T+pt+gF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","68":"b:T+pt+gF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","71":"b:T+pt+gF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","86":"b:CKBFWABEQFEAcj4HgEIAAEguMSDsvmsfAAAAAAA="},"packages/frontend/editor-ui/src/app/components/NpsSurvey.vue":{"14":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","40":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","54":[46],"75":[46],"88":[46],"92":[46],"107":[46],"117":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","118":[46],"127":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","144":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","146":"b:f+r/+4P/5/92+v/v/v//////////////AAAAAAA=","149":[46],"153":[46],"159":[46],"164":[46],"165":[46]},"packages/frontend/editor-ui/src/app/components/SaveButton.vue":{"12":"b:BgIBIABoABBWAAACAIACAAKAAEIAAAQAAAAAAAA=","36":"b:BgIBIABoABBCAAACAIACAAKAAEIAAAQAAAAAAAA=","42":[46],"45":"b:BgIBIABoABBWAAACAIACAAKAAEIAAAQAAAAAAAA=","73":"b:BgIBAAAoABBCAAACAIACAACAAEIAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/app/components/TidyUpIcon.vue":{"2":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA="},"packages/frontend/editor-ui/src/app/components/UpdatesPanel.vue":{"11":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","15":"b:f+r/+4P/5/92+v/v/v//////////////AAAAAAA=","24":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","29":[39,46],"60":[46],"61":[39,46],"70":[39,46]},"packages/frontend/editor-ui/src/app/components/WorkflowProductionChecklist.vue":{"34":"b:D+Jt+AM+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","50":[44,134,57,62,75,184,185],"51":[44,134,57,62,75,184,185],"52":[44,134,57,62,75,184,185],"58":[57,75],"62":[44,134,57,62,75,184,185],"67":[44,134,57,62,75,184,185],"68":[44,134,57,62,75,184,185],"73":[44,134,57,62,75,184,185],"74":[44,134,57,62,75,184,185],"77":[44,134,57,62,75,184,185],"82":[44,57,62,75],"86":[44,134,57,62,75,185],"88":"b:D+Jt+AMe5/NA+v5GoEAIAH5uJbDs/+/fAAAAAAA=","92":"b:D6Jt+AM+53NA+vxHoEAIAHpmJLDkX+7OAAAAAAA=","93":[45,57,60,88],"95":"b:D+Jt+AM+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","99":"b:D+Jt+AM+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","103":"b:D6Jt+AM+53NA+vxHoEAIAHpmJLDkX+7OAAAAAAA=","105":"b:D+Jt+AM+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","198":"b:D+Jt+AM+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","206":[57,75],"231":[44,57,62,75],"235":[57],"239":[44,57,62,75],"254":"b:D+Jt+AM+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","267":[44,134,57,62,75,184,185],"274":[57,75],"281":[44,57,62],"292":"b:D+Jt+AM+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","298":"b:D+Jt+AM+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","301":"b:D+Jt+AM+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA="},"packages/frontend/editor-ui/src/app/components/app/AppBanners.vue":{"7":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","9":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","10":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/components/app/AppChatPanel.vue":{"9":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","24":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","26":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","34":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","39":[46],"45":[46],"49":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/components/app/AppCommandBar.vue":{"11":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","29":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","31":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","35":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","41":[46,187],"46":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/components/app/AppHeader.vue":{"6":"b:D+oF+AM+4PFA+v/H4mAI8H/+P7D8////AAAAAAA="},"packages/frontend/editor-ui/src/app/components/app/AppLayout.vue":{"5":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","6":"b:AAKCI4DpAB5iAEALGBgEAoABAFEAAQDBAAAAAAA=","9":"b:AAAAAABAAEA2AACgGAACCAAAwA4AAAAAAAAAAAA=","12":"b:D+oF+AN+4PFA+v/H4mAI8H/+P7D8////AAAAAAA=","14":[107,108,46,100],"15":[104,105,46,160,161],"16":[4,111,5,112,6,17,46],"18":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","30":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","35":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","37":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/components/app/AppModals.vue":{"7":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/components/app/E2ETestModeMarker.vue":{"5":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","7":"b:f+r/+4P/5/92+v/v/v//////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/components/transitions/SlideTransition.vue":{"3":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA="},"packages/frontend/editor-ui/src/app/composables/canvasConnectionReplacement.utils.ts":{"86":"b:BsoBIABqQBFAOs9EgAAAQAaADhD0ah8CAAAAAAA=","94":"b:BgIBIABqQBFAOs9EgAAAAAaAABD0YhcCAAAAAAA=","102":"b:BsoBIABqQBFAOs9EgAAAQAaADhD0ah8CAAAAAAA=","138":[46],"184":[46],"189":[46],"192":[46,146,147,76],"212":[46,146,147,76],"221":[46,146,147,76],"228":[46,146,147,76],"262":[46,146,147,76],"277":[46,146,147,76]},"packages/frontend/editor-ui/src/app/composables/useActivationError.ts":{"9":"b:D+pt+IP+5/9A+v/P4nAI8v//P7D8////AAAAAAA=","13":[46]},"packages/frontend/editor-ui/src/app/composables/useActivityDetection.ts":{"12":"b:AsIBsAAIQIEAemYBAAAAAAAgAQDkOkseAAAAAAA=","18":"b:AsIFsAAIQIFAemYBAAAAAEAkBQDkOksfAAAAAAA=","19":"b:AsIFsAAIQIFAemYBAAAAAEAkBQDkOksfAAAAAAA=","24":"b:AgAMAAAABBAAiEADAAAAAAAAABAABwDdAAAAAAA=","25":"b:AgAMAAAABBAAiEADAAAAAAAAABAABwDdAAAAAAA=","31":"b:D+rt+QM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","32":"b:AsIFsAAIQIFAemYBAAAAAEAkBQDkOksfAAAAAAA=","42":"b:D+rt+QM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","49":"b:AgAMAAAABBAAiEADAAAAAAAAABAABwDdAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useAiGateway.ts":{"8":"b:f+r/+4P/5/92+v/v+/r////////8////AAAAAAA=","14":"b:f+r/+4P/5/92+v/v+/j////////8////AAAAAAA=","15":[46],"16":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","17":[46],"19":"b:T+r/+4P/5/92+v/v+/j+///////8////AAAAAAA=","21":"b:TupF+ABuQlFCOv9GgOACUG+uP3Ds/n8SAAAAAAA=","26":[46],"29":[46],"32":[46],"38":[46],"41":"b:QCIBIABKQBFACDIAgAAAUAMKADCEIB8CAAAAAAA=","47":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","50":"b:T+rt+QN+5/FC+v/HwuAK8H/+P/D8////AAAAAAA=","55":[46]},"packages/frontend/editor-ui/src/app/composables/useAiGatewayTopUp.ts":{"14":"b:f+r/+4P/5/92+v/v+/j////////8////AAAAAAA=","23":[46],"29":[46]},"packages/frontend/editor-ui/src/app/composables/useAiSimulatedDataGuard.ts":{"13":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","18":"b:CABEGAAAQEEAADwEgEAAAGwEIABA1msQAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useAutocompleteTelemetry.ts":{"12":"b:BsoFCABAAAACEK8AAAAAAECKIQAAZA8AAAAAAAA=","22":[46],"26":[46],"27":[46],"36":[46],"49":[46],"57":[46,65,80,81,82,173,83,174,16,177,178,179],"61":[46,65,80,81,82,173,83,174,16,177,178,179],"70":[46],"96":[46,65,80,81,82,173,83,174,16,177,178,179],"103":"b:BsoFCABAAAACEK8AAAAAAECKIQAAZA8AAAAAAAA=","109":"b:BsoFCABAAAACEK8AAAAAAECKIQAAZA8AAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useBackendStatus.ts":{"10":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","19":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","25":[46],"52":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","70":"b:QoBPAADARwlAIIIAAIAPAIAAAMTEI4IKAAAAAAA=","75":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","85":[46]},"packages/frontend/editor-ui/src/app/composables/useBeforeUnload.ts":{"15":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","22":[46],"27":[46],"32":[46],"43":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","47":"b:D+pt+AN+5/FA+v/H4mMI8H/+P7D+////AAAAAAA=","51":"b:AgAMAABABBAAiEADAAAAAAAAABAABwDdAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useBrowserNotifications.ts":{"57":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","66":[31,33,46],"67":[46],"68":[46],"70":[46],"76":[46],"80":[31,33,46],"89":[46],"101":[46],"126":[46],"133":[46],"137":[46],"162":[46]},"packages/frontend/editor-ui/src/app/composables/useBugReporting.ts":{"27":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","30":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useCalloutHelpers.ts":{"17":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","28":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","42":[46],"75":[46,170,16],"79":[46]},"packages/frontend/editor-ui/src/app/composables/useCanvasOnlyExternalLinks.ts":{"15":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","41":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useCanvasOperations.ts":{"226":"b:BsoF+ABqQJFAOt9HgmAA8D+yPhD0bl+qAAAAAAA=","236":"b:AgIF+ABqQBFAMt9HgmAAUB8yPhDkal+iAAAAAAA=","245":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","269":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","306":"b:BsoBKAAqQJFAOI9EgCAA8C+ABhDkZh8KAAAAAAA=","310":"b:BsoF+AAqQJFAOt9HgmAA8D+yPhD0bl+qAAAAAAA=","325":[78],"333":[78],"346":[31,145],"365":[145],"373":[144,76,77,78,165,88],"377":[144,76,77,78,165,88],"390":[144,76,77,78,165,88],"399":[31,145],"416":[31,145],"420":[31,145],"461":[31,144,146,147,76,77,78,165,88],"486":[165],"495":[147,182],"523":[182],"535":[162,16,87],"596":[140,141,76,77,78,165,18,182],"679":[140,141,76,77,78,165,18,182],"809":[76,77,78,165,182],"823":[76,77,78,165,182],"837":[165,182],"842":[140,141,76,77,78,165,18,182],"861":[182],"882":[182],"1066":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","1076":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","1099":"b:D+pFeAEuQNFAev9HgGIA8H++PzD8/n8/AAAAAAA=","1115":[1,75,76,162,165,169,18,172,185,186,187,188],"1128":[165],"1188":"b:BsoF+AAqQJFAOt9HgmAA8D+yPhD0bl+qAAAAAAA=","1196":"b:BsoF+AAqQJFAOt9HgmAA8D+yPhD0bl+qAAAAAAA=","1281":"b:BsoF+AAqQJFAOt9HgmAA8D+yPhD0bl+qAAAAAAA=","1300":"b:BsoF+AAqQJFAOt9HgmAA8D+yPhD0bl+qAAAAAAA=","1314":[162,88],"1325":"b:BsoF+AAqQJFAOt9HgmAA8D+yPhD0bl+qAAAAAAA=","1355":"b:BsoF+AAqQJFAOt9HgmAA8D+yPhD0bl+qAAAAAAA=","1410":"b:AAAFWAAAAAAAAFABAEAAABASOAAkAAMgAAAAAAA=","1411":"b:AAAFWAAAAAAAAFABAEAAABASOAAkAAMgAAAAAAA=","1439":[165,182],"1448":[146,147,76],"1459":"b:BsoF+AAqQJFAOt9HgmAA8D+yPhD0bl+qAAAAAAA=","1532":"b:BsoBKAAqQJFAOs9EgCAA8C+gDhD0bh8KAAAAAAA=","1542":[164],"1548":"b:BsoBKAAqQJFAOs9EgCAA8C+gDhDkbh8KAAAAAAA=","1600":"b:BsoF+AAqQJFAOt9HgmAA8D+yPhD0bl+qAAAAAAA=","1644":"b:BsoF+AAqQJFAOt9HgmAA8D+yPhD0bl+qAAAAAAA=","1650":"b:BsoF+AAqQJFAOt9HgmAA8D+yPhD0bl+qAAAAAAA=","1655":"b:BsoF+AAqQJFAOt9HgmAA8D+yPhD0bl+qAAAAAAA=","1675":"b:BsoBKAAqQJFAOs9EgCAA8C+gDhD0bh8KAAAAAAA=","1687":"b:BsoF+AAqQJFAOt9HgmAA8D+yPhD0bl+qAAAAAAA=","1813":"b:BsoAAAAAAAEAMkIAAAAAAACACgDkKBoAAAAAAAA=","1826":"b:BsoBIAAqQBFAOs9EgAAAQAaADhDkah8CAAAAAAA=","1847":[146,147,76],"1903":"b:BsoBIAAqQBFAOs9EgAAAQAaADhDkah8CAAAAAAA=","1908":[1,2,9,11,143,14,15],"1935":"b:AgAAAAAAAAEAMkIAAAAAAAAACgDkKBoAAAAAAAA=","1986":"b:BsoF+AAqQJFAOt9HgmAA8D+yPhD0bl+qAAAAAAA=","1995":[146,147,76],"2017":[146,147,76],"2054":[146,147,76],"2069":[147],"2074":[146,147,76],"2076":[146,147,76],"2082":[147],"2096":[147],"2108":[147],"2122":[147],"2129":[147],"2136":[146,147,76],"2143":[146,147,76],"2151":[147,76],"2160":[147,76],"2164":[146,147,76],"2176":[146,147,76],"2179":[146,147,76],"2182":[146,147,76],"2283":[147],"2330":[146,147,76],"2354":[146,147,76],"2401":"b:BsoF+AAqQBFAet9EgGAAUB+SPhDkal8iAAAAAAA=","2439":"b:BsoF+AAqQBFAet9EgGAAUB+SPhD0al8iAAAAAAA=","2528":"b:BsoF+AAqQBFAet9EgGAAUB+SPhDkal8iAAAAAAA=","2538":[165,182],"2553":[140,141,76,77,78,165,18,182],"2619":[31,140,141,146,147,76,77,78,165,18,182],"2654":[31,140,141,146,147,76,77,78,165,18,182],"2668":[165,182],"2684":[1,109,56,182,191],"2701":[1,182,191],"2728":[1,182,191],"2732":[109,56,182,191],"2736":"b:BsoF+AAqQBFAet9EgGAAUB+SPhD0al+iAAAAAAA=","2744":"b:BsoF+AAqQBFAet9EgGAAUB+SPhD0al+iAAAAAAA=","2750":"b:BsoF+AAqQBFAet9EgGAAUB+SPhDkal+iAAAAAAA=","2757":"b:BsoF+AAqQBFAet9EgGAAUB+SPhDkal+iAAAAAAA=","2761":"b:BsoF+AAqQBFAet9EgGAAUB+SPhDkal+iAAAAAAA=","2766":"b:BsoF+AAqQBFAet9EgGAAUB+SPhDkal+iAAAAAAA=","2845":"b:BsoF+AAqQBFAet9EgGAAUB+SPhDkal+iAAAAAAA=","2876":"b:BsoF+AAqQJFAOt9FgGAA8D+yPhD0bh8qAAAAAAA=","2903":"b:D+pt+AM+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","2954":"b:C6BtAAEU5/BA4nQDIAMIAEhsAbAOn+HdAAAAAAA=","2992":"b:AAAFWAAAAAAAAFABAEAAABASOAAkAAMgAAAAAAA=","3009":"b:AAAFWAAAAAAAAFABAEAAABASOAAkAAMgAAAAAAA=","3027":"b:AAAFWAAAAAAAAFABAEAAABASOAAkAAMgAAAAAAA=","3044":"b:AAAFWAAAAAAAAFABAEAAABASOAAkAAMgAAAAAAA=","3047":"b:AAAFWAAAAAAAAFABAEAAABASOAAkAAMgAAAAAAA=","3090":"b:AAAFWAAAAAAAAFABAEAAABASOAAkAAMgAAAAAAA=","3212":"b:AAAFWAAAAAAAAFABAEAAABASOAAkAAMgAAAAAAA=","3250":"b:AAAFWAAAAAAAAFABAEAAABASOAAkAAMgAAAAAAA=","3265":"b:AAAFWAAAAAAAAFABAEAAABASOAAkAAMgAAAAAAA=","3272":"b:AAAFWAAAAAAAAFABAEAAABASOAAkAAMgAAAAAAA=","3282":"b:AAAFWAAAAAAAAFABAEAAABASOAAkAAMgAAAAAAA=","3283":"b:AAAFWAAAAAAAAFABAEAAABASOAAkAAMgAAAAAAA=","3413":"b:AAAFWAAAAAAAAFABAEAAABASOAAkAAMgAAAAAAA=","3443":[132,147,148,84,16,177,86,189],"3445":[189],"3448":[148,86,189],"3454":[148,86,189],"3463":[148,86,189],"3471":[148,86,189],"3472":[148,86,189],"3483":[189],"3506":[76,162,165,177,88,89],"3520":"b:AAAFWAAAAAAAAFABAEAAABASOAAkAAMgAAAAAAA=","3557":[76,162,165,177,88,89],"3569":[76,162,165,177,88],"3617":[89],"3630":[76,162,165,177,88,89],"3651":[76,162,88,89],"3658":[76,162,88],"3659":[76,162,88],"3670":[162,165,177],"3677":[162,165,177],"3679":[76,88,89],"3681":[76,88],"3697":[76,88],"3760":[1,2,3,144,161],"3775":[1,2,3,144,161],"3780":[97,89,191],"3885":"b:BsoBKAAqQJFAOs9EgCAA8C+gDhD0bh8KAAAAAAA=","3899":"b:BsoBKAAqQJFAOs9EgCAA8C+gDhD0bh8KAAAAAAA=","3937":"b:BsoBAAAAAAAAAAAAACAAUAuABgAAAA0AAAAAAAA=","4050":"b:D+pt+AM+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","4051":"b:D+pt+AM+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","4054":[97,89,191],"4062":[97,89,191],"4069":[97,89,191]},"packages/frontend/editor-ui/src/app/composables/useCollectionOverhaul.ts":{"5":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","8":"b:TupFeABuQFFUOv9GgOICUG+uPzLs/n8SAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useDataSchema.ts":{"31":"b:D+pt+gN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","35":"b:CCBFmgBAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","58":[46],"65":[46,131,137,163,18,82,174,175,16,85],"75":"b:CCBFGgBAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","100":"b:CCBFmgBAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","110":[46,147,172,180],"130":[46,147,172,180],"151":[46,147,172,180],"163":"b:CCBEGABAQEEAID4EgEAAAGwEJABA9msQAAAAAAA=","179":"b:DupF+ABuQFFAev9EgGIAUG+uPzDs/n8SAAAAAAA=","207":"b:DupF+ABuQFFAev9EgGIAUG+uPzDs/n8SAAAAAAA=","216":"b:AAABAABAAAAAAD4AAAIAAAAAAACI8kIAAAAAAAA=","221":"b:AAABAABAAAAAAD4AAAIAAAAAAACI8kIAAAAAAAA=","228":[46,84],"236":"b:CCBFGgBAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","241":[46,84],"365":"b:CCBFGgBAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","367":"b:ACBEGgBAAEAAIDAEAEAAAEwGJABAPjsQAAAAAAA=","378":[46,172,180],"385":"b:CCBFGgBAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","394":"b:CCBFGgBAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","396":"b:CCBFGgBAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","399":[46,82,84],"407":"b:CCBFGgBAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","468":"b:CCBFGgBAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","509":"b:ACBFGABAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","514":"b:ACBFGABAAEAAID4EAEAAAEwGJADI/nsQAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useDebugInfo.ts":{"70":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","76":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","113":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","124":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","134":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","145":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","152":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","156":[46,165],"164":[46,165],"167":[46,165],"170":[46],"172":[46,165],"182":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","199":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","217":[46,165],"231":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","235":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useDependencies.ts":{"17":"b:C6JtAIHwB/5A4nQJIBAMAohtAZAMn2HdAAAAAAA=","31":"b:C6JtIIH85/5C6nQLIBAMAshtAfAMn+HdAAAAAAA=","41":"b:D+Jt+IP+5/9C+v5PoFAMAv5/PfDs/+//AAAAAAA=","50":"b:C6JtAIH05/5A6nQLIBAMAshtAfAMn+HdAAAAAAA=","56":"b:D+pt+IP/5/9i+v/P+nAO8v//P/D8////AAAAAAA=","60":"b:C6JtIIG85/5C4nQLIBAMAshtAfAMn2HdAAAAAAA=","65":"b:C6JtAIG05/5A4nQLIBAMAshtAfAMn2HdAAAAAAA=","66":"b:C6JtAIG05/5A4nQLIBAMAshtAfAMn2HdAAAAAAA=","89":[59,62,156,157,159,75,168,183,184,190],"94":[59,62,156,157,159,75,168,183,184,190],"95":[59,62,156,157,159,75,168,183,184,190],"137":"b:AAAFWAAk4FgAClACAEAAAFASOPAgAYPhAAAAAAA=","144":[190],"151":"b:D+Jt+IP+5/9C+v5PoFAMAv5vJfDs/+/fAAAAAAA=","154":"b:C6JtAIG05/5A4nQLIAAMAshtAfAMn2HdAAAAAAA=","157":"b:D+Jt+IP+5/9C+v5PoFAMAv5vJfDs/+/fAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useDocumentTitle.ts":{"18":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","20":[46,121],"23":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","30":"b:D+pt+AN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useDocumentVisibility.ts":{"12":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","17":"b:EAAjAIBEQF4WYkIhGAA0B4gBAAAECELBAAAAAAA=","22":[46],"24":[46],"28":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","32":[46],"36":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","40":"b:AAAIeABABJAAAMADAAAAAgAAABAAAUzBAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useEditorContext.ts":{"21":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","27":"b:D+pF+ANe4PFA+v/GwmAI8H/+P7D8////AAAAAAA=","30":"b:D+pF+AN+4PFA+v/HwmAI8H/+P7D8////AAAAAAA=","53":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","54":"b:D+pF+AN+4PFA+v/HwmAI8H/+P7D8////AAAAAAA=","61":"b:T+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","62":"b:D+pt+AN+5/FA+v/HwmAI8H/+P7D8////AAAAAAA=","63":"b:C6Jt+AB+5fFA+v9HgmAI8H8+PrDs/3//AAAAAAA=","64":"b:D+Jt+AF+5/FA+v5HoEAIAH5upbDu/+/fAAAAAAA=","67":"b:D+Jt+AF+5/FA+v5HoEAIAH5upbDu/+/fAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useErrorHandler.ts":{"26":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","33":[46]},"packages/frontend/editor-ui/src/app/composables/useExecutingNode.ts":{"19":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","25":"b:DyBEWAFw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA=","37":"b:DyBEWAFw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA=","45":"b:D+pt+AN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","51":"b:D+pt+AF+5/FA+v9HgmAI8H/+P7D//3//AAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useExposeCssVar.ts":{"7":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","11":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","12":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","19":[46]},"packages/frontend/editor-ui/src/app/composables/useExternalHooks.ts":{"16":"b:f+r/+4P/5/92+v/v//v/////////////AAAAAAA=","38":"b:f+r/+4P/5/92+v/v//v/////////////AAAAAAA=","50":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useFloatingUiOffsets.ts":{"17":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","22":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","27":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","28":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","37":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useFreeAiCredits.ts":{"24":"b:furHeQBuQlFCOv9GgOIDUG+uP3Ds/n8SAAAAAAA=","35":"b:furHeQBuQlFCOv9GgOIDUG+uP3Ds/n8SAAAAAAA=","37":[4,111,5,112,6,17,46],"39":[46],"44":[46],"49":[46],"53":"b:furHeQBuQlFCOv9GgOIDUG+uP3Ds/n8SAAAAAAA=","61":[46],"92":[46]},"packages/frontend/editor-ui/src/app/composables/useGlobalEntityCreation.ts":{"34":"b:AGICgIBYQN4CQqYBAAAE4Lr3JvEoOSbnAAAAAAA=","37":"b:AGICgIBYQN4CQqYBAAAE4Lr3JvEoOSbnAAAAAAA=","58":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","87":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","91":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","94":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","98":"b:D+r/+4P/5/9i+v/P63j89///P/H8////AAAAAAA=","102":"b:D+r/+4P/5/9i+v/P63j89///P/H8////AAAAAAA=","106":"b:D+r/+4P/5/9i+v/P63j89///P/H8////AAAAAAA=","109":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","113":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","123":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","127":[46,152,165,168,181,189],"147":[46,152,165,168,181,189],"156":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","167":"b:AGICgIBYQN4CQqYBAAAE4Lr3JvEoOSbnAAAAAAA=","179":"b:AGICgIBYQN4CQqYBAAAE4Lr3JvEoOSbnAAAAAAA=","191":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","213":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","235":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","360":"b:AGICgIBYQN4CQqYBAAAE4Lr3JvEoOSbnAAAAAAA=","394":"b:AGICgIBYQN4CQqYBAAAE4Lr3JvEoOSbnAAAAAAA=","429":"b:AGICgIBYQN4CQqYBAAAE4Lr3JvEoOSbnAAAAAAA=","449":[46,58,60],"472":[46],"514":[46,58,60,86],"567":[107,40,45,46,60,100,69,88],"592":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","593":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","594":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","597":[46,100]},"packages/frontend/editor-ui/src/app/composables/useGlobalLinkActions.ts":{"14":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","15":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","18":"b:AgAMAABABFAAiEADAAAAAAAAABAABwDdAAAAAAA=","22":[46,16],"34":"b:D+pF+AN+5PFA+v/HgGII8H/+P7D+//9/AAAAAAA=","47":[46],"55":[46,16],"60":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","69":"b:AgAMAABABFAAiEADAAAAAAAAABAABwDdAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useHistoryHelper.ts":{"18":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","24":"b:AoIl2ADKAAZCeFADEEAAEBGTPGU2qsP/AAAAAAA=","32":[46,165,182],"60":[46,165],"88":[46,165,182],"94":[46,165,182],"99":[46,165],"110":"b:AoIl2ADCAAYAeFADEEAAEBGTPAU2qsP/AAAAAAA=","117":"b:AoIl2ADKAAZCeFADEEAAEBGTPGU2qsP/AAAAAAA=","147":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","151":[46]},"packages/frontend/editor-ui/src/app/composables/useInjectWorkflowId.ts":{"4":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useInstanceAiEditorCapability.ts":{"79":"b:T+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useIntersectionObserver.ts":{"45":"b:AgBYAAAABwAAgAAAAADgAwAAAAAAAwAYAAAAAAA=","56":[79,187],"62":[79,187],"82":"b:AgBYAAAABwAAAAAAAADgAwAAAAAAAwAYAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useInvalidNodeGroupCleanup.ts":{"24":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","32":[46,78],"51":[46,78],"52":[46,78],"58":[46],"64":[46],"80":"b:BsIF+AJqQBEAer5GgEAAADYGJQDkds/eAAAAAAA=","84":[46,78]},"packages/frontend/editor-ui/src/app/composables/useKeybindings.ts":{"53":"b:f+r/+4P/5/9i+v/P+/v99///P/H/////AAAAAAA=","65":"b:f+r/+4P/5/9i+v/P+/v99///P/H/////AAAAAAA=","76":[46],"80":[46],"86":"b:AoIl2ADKAAZCeFADAEAAEBGTPGE2qsP/AAAAAAA=","88":"b:AoIl2ADKAAZCeFADAEAAEBGTPGE2qsP/AAAAAAA=","90":"b:AoIl2ADKAAZCeFABAEAAEBGTPGE2qsP/AAAAAAA=","92":"b:AoIl2ADKAAZCeFABAEAAEBGTPGE2qsP/AAAAAAA=","97":"b:AoIl2ADKAAZCeFADAEAAEBGTPGE2qsP/AAAAAAA=","99":"b:AoIl2ADKAAZCeFABAEAAEBGTPGE2qsP/AAAAAAA=","100":"b:AoIl2ADKAAZCeFABAEAAEBGTPGE2qsP/AAAAAAA=","104":"b:AoIl2ADKAAZCeFADAEAAEBGTPGE2qsP/AAAAAAA=","110":"b:AoIl2ADKAAZCeFABAEAAEBGTPGE2qsP/AAAAAAA=","128":"b:AoIl2ADKAAZCeFADAEAAEBGTPGE2qsP/AAAAAAA=","146":"b:AoIl2ADKAAZCeFADAEAAEBGTPGE2qsP/AAAAAAA=","200":"b:AoIl2ADKAAZCeFADAEAAEBGTPGE2qsP/AAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useLayoutProps.ts":{"4":"b:D+oF+AM+4PFA+v/H4mAI8H/+P7D8////AAAAAAA=","7":"b:D+oF+AM+4PFA+v/H4mAI8H/+P7D8////AAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useLoadingService.ts":{"10":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","14":[46,97,99,189,89,191],"26":[46,97,89,191],"32":[46,97,99,189,89,191],"39":"b:BsIF+AJqQBEAer5GgEAAADYGJQDkds/eAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useModulePushDispatcher.ts":{"16":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","23":"b:f+Lv+QF+5/FA+v5HoMAJAH5upbDu/+/fAAAAAAA=","32":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","33":"b:f+Lv+QF+5/FA+v5HoMAJAH5upbDu/+/fAAAAAAA=","38":[46]},"packages/frontend/editor-ui/src/app/composables/useNodeConnections.ts":{"12":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","25":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","26":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","29":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","30":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","33":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","34":[0,1,2,3,9,46,11,13,143,14,75,76,18,15,16],"37":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","45":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","46":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","49":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","50":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","53":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","61":[46,78,182]},"packages/frontend/editor-ui/src/app/composables/useNodeDirtiness.ts":{"27":[46,141,146,77,169,18,172,182,186,187,188],"35":[46,141,146,77,169,18,172,182,186,187,188],"58":[46,141,18,182],"66":[46,146,77,169,18,172,182,186,187,188],"67":[46,146,77,169,18,172,182,186,187,188],"77":[46,186,187,188],"89":[28,46,56,138,146,166,18,172,177,179,182],"138":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","141":"b:DyBEWAFw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA=","144":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","148":"b:DyBEWAFw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA=","152":[46,146,186,187,188],"156":"b:DyBEWAFw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA=","158":"b:DyBEGAFg5WEAoD5EgEAAAFwmJQBC9mscAAAAAAA=","159":[0,1,2,3,46,18],"162":"b:DyBEWAFw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA=","179":"b:DyBEWAFw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA=","215":[46,146],"218":[46,146],"258":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","262":[28,46,56,138,146,166,18,172,177,179,182],"271":[46,146],"308":"b:DyBEGAFg5WEAoD5EgEAAAFwmJQBC9mscAAAAAAA=","309":"b:DyBEGAFg5WEAoD5EgEAAAFwmJQBC9mscAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useNodeDocsUrl.ts":{"5":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","8":[46,129],"10":[9,46,129,84,15],"18":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useNodeExecution.ts":{"82":"b:DupF+ABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","105":[46],"106":[46],"109":"b:DAAAGABAAAEAADwAAEAAACQEAQBAUAsAAAAAAAA=","117":"b:DupF+ABuQBFAOv9EgGAAUG+uPzDs/n8CAAAAAAA=","121":"b:DupF+ABuQBFAOv9EgGAAUG+uPzDk/n8CAAAAAAA=","127":"b:DupF+ABuQBFAOv9EgGAAUG+uPzDs/n8CAAAAAAA=","131":[103,46,54,56],"133":"b:DupF+ABuQBFAOv9EgGAAUG+uPzDk/n8CAAAAAAA=","135":"b:DAAAGABAAAEAADwAAEAAACQEAQBAUAsAAAAAAAA=","141":"b:DupF+ABuQBFAOv9EgGAAUG+uPzDk/n8CAAAAAAA=","143":"b:DupF+ABuQBFAOv9EgGAAUG+uPzDk/n8CAAAAAAA=","145":[103,46,54,133,56,177],"147":"b:DupF+ABuQBFAOv9EgGAAUG+uPzDk/n8CAAAAAAA=","149":"b:DupF+ABuQBFAOv9EgGAAUG+uPzDs/n8CAAAAAAA=","159":"b:DupF+ABuQBFAOv9EgGAAUG+uPzDs/n8CAAAAAAA=","172":"b:DupF+ABuQBFAOv9EgGAAUG+uPzDk/n8CAAAAAAA=","180":"b:DupF+ABuQBFAOv9EgGAAUG+uPzDs/n8CAAAAAAA=","186":"b:BoIAqABCQAEAKI4AgCAAECAIAACg9BcCAAAAAAA=","193":"b:DupFeABuQBFAOv9EgGAAUG+uPzDs/n8CAAAAAAA=","222":"b:DupF+ABuQBFAOv9EgGAAUG+uPzDk/n8CAAAAAAA=","250":"b:DupF+ABuQBFAOv9EgGAAUG+uPzDk/n8CAAAAAAA=","256":"b:DupF+ABuQBFAOv9EgGAAUG+uPzDs/n8CAAAAAAA=","276":[46],"284":[46],"356":[2,3,46,144],"365":"b:DAAAGABAAAEAADwAAEAAACQEAQBAUAsAAAAAAAA=","451":[46]},"packages/frontend/editor-ui/src/app/composables/useNodeGroupRules.ts":{"13":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","17":"b:BsglWAAAAAAAcFADAEAAABASOAAkAEMgAAAAAAA=","23":"b:BsgFWAAAAAAAcFADAEAAABASOAAkAEMgAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useNodeHelpers.ts":{"67":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","83":"b:TupF+AAuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","113":"b:DupF+AAuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","146":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","159":"b:BgIFAAAsQBFAAAAAAAAAAACAADAAAAAAAAAAAAA=","160":"b:BgIFAAAsQBFAAAAAAAAAAACAADAAAAAAAAAAAAA=","161":"b:BgIFAAAsQBFAAAAAAAAAAACAADAAAAAAAAAAAAA=","165":"b:TupF+AF+5tFWOv9GguMKUG/uP3Lu/n/yAAAAAAA=","185":[2,6,15],"251":"b:T6BEWAEw5WEAsD5EgEAIAHwmJQBC9mucAAAAAAA=","267":[42,9,45,130],"281":"b:D+pt+AE+5/FA+v9HgmAI8H/+P7D8/3//AAAAAAA=","301":"b:AsIBUAAqQAFAMo9EgGAAAA4kEBDkck8AAAAAAAA=","309":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","317":"b:D+pF+AM+5fFA+v/HwmAI8H/+P7D+////AAAAAAA=","329":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","337":"b:AsIBUAAqQAFAMo9GgGAAAA4kEBDkck8AAAAAAAA=","345":"b:BsoF+AAqQJFAOt9HgmAA8D+2PhD0fl++AAAAAAA=","360":"b:AsIB0AAqQAFAMo9EgGAAAA4kEBDkck8AAAAAAAA=","368":"b:D+pt+AE+5/FA+v9HgmII8H/+P7D8/3//AAAAAAA=","395":"b:D+pt+AE+5/FA+v9HgmAI8H/+P7D8/3//AAAAAAA=","409":[1,2,9,11,143,14,76,18,15,16],"454":"b:TuoF4AE+5tFAGiEGgmMIUEfOCzCmHjfiAAAAAAA=","458":"b:DuoF4AE+5tFAGiEGgmMIUEfOCzCmHjfiAAAAAAA=","466":"b:DuoF4AE+5tFAGiEGgmMIUEfOCzCmHjfiAAAAAAA=","509":"b:TuoF4AE+5tFAGiEGgmMIUEfOCzCmHjfiAAAAAAA=","541":"b:T+pt+AE+5/FA+v9HgmMI8H/+P7D+/3//AAAAAAA=","649":"b:RgIFgAAI4AFAAgACAAAAAECAADAAAAAAAAAAAAA=","704":[42,9,45,130],"712":[42,9],"723":[42,9],"726":"b:D+pt+AN+5/FA+v/HwmMK8H/+P/D+////AAAAAAA=","741":"b:DupFegEuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","745":"b:DupFegEuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","752":"b:DupFeAAuQFFAOv9EgGAAUE+OPzDk/n8SAAAAAAA=","754":"b:ACBEGAAAAEAAID4EAEAAAEwGJABA9msQAAAAAAA=","760":"b:ACBFGAAAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","768":"b:ACBEGAAAAEAAID4EAEAAAEwGJABA/msQAAAAAAA=","774":"b:DupFegEuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","800":"b:DiBEGgEAQEEAID4EgEAAAGwGJQBA/msQAAAAAAA=","808":"b:DupFegEuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","830":[1,75,76,162,165,169,18,172,185,186,187,188],"837":[1,75,76,162,165,169,18,172,185,186,187,188],"879":"b:D+pt+gE+5/FA+v9HgmMI8H/+P7D+/3//AAAAAAA=","883":[42,53,54,55,134,60,157,73,18,89],"899":[42,53,54,55,134,157,73,18,89],"934":"b:AAAFWAAAAAAAAFABAEAAABASOAAkAAMgAAAAAAA=","938":"b:AAAFWAAAAAAAAFABAEAAABASOAAkAAMgAAAAAAA=","941":"b:AAAFWAAAAAAAAFABAEAAABASOAAkAAMgAAAAAAA=","959":[165],"993":[3,131,82,176,85,177],"1009":"b:DupFegEuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","1078":"b:BsoBKAAqQJFAOs9EgCAA8C+gDhD0bh8KAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useNodeIconSource.ts":{"6":"b:T+pt+gN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","12":"b:T+pt+gF+5/FA+v9HgmII8H++P7Du/3//AAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useNodeType.ts":{"8":"b:D+pt+gN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","16":"b:DupFeABuQNFAOv9EgGIA8G+uPzDs/n8aAAAAAAA=","29":"b:DupFeABuQNFAOv9EgGIA8G+uPzDs/n8aAAAAAAA=","31":"b:DspFeABuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/usePageRedirectionHelper.ts":{"15":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/composables/usePinnedData.ts":{"50":"b:D+pt+gN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","70":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8yAAAAAAA=","78":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","83":"b:DupFeABuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","93":"b:DupFeABuQFFAev9EgGIAUG+uPzDs/n8SAAAAAAA=","104":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","109":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","126":[46],"171":"b:AAABAABAAAAAAD4AAAAAAAACAACgYgMgAAAAAAA=","175":"b:AAABAABAAAAAAD4AAAAAAAACAACgYgMgAAAAAAA=","225":"b:AAABAABAAAAAAD4AAAAAAAACAACgYgMgAAAAAAA=","244":[46,177],"266":"b:AAABAABAAAAAAD4AAAAAAAACAACgYgMgAAAAAAA=","303":[46],"316":[46]},"packages/frontend/editor-ui/src/app/composables/usePolicyViolationToast.ts":{"28":[46],"29":[46],"32":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","40":[46],"51":[46],"57":[46],"66":[46],"69":[46],"84":[46],"86":[46],"96":[46],"107":"b:BsIF+AJqQBEAer5GgEAAAHYGJQDkds/fAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/usePostMessageHandler.ts":{"40":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","44":"b:D+oF+AM+4PFA+v/H4mMI8H/+P7D/////AAAAAAA=","66":"b:D+oF+AM+4PFA+v/H4mMI8H/+P7D/////AAAAAAA=","85":[104,105,161],"233":"b:D+oF+AM+4PFA+v/H4mMI8H/+P7D/////AAAAAAA=","296":"b:D+oF+AM+4PFA+v/H4mMI8H/+P7D/////AAAAAAA=","302":[168,86,184]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/executionFinished.ts":{"70":"b:DyBEGAEw5WEAsD5EAEAAAHwmJQBC9mscAAAAAAA=","216":"b:DyBEGAEw5WEAsD5EAEAAAHwmJQBC9mscAAAAAAA=","237":"b:DyBEGAEw5WEAsD5EAEAAAHwmJQBA9mscAAAAAAA=","243":"b:CgBEAAEw5WAAoDBEAEAAAFgCJQAAlmMcAAAAAAA=","278":"b:DyBEGAEw5WEAsD5EAEAAAHwmJQBC9mscAAAAAAA=","308":"b:DyBEGAEw5WEAsD5EAEAAAHwmJQBA9mscAAAAAAA=","321":"b:DyBEGAEw5WEAsD5EAEAAAHwmJQBA9mscAAAAAAA=","382":[27,28,1,2,141,169,170,18,172,176,186,187],"465":[27,28,169,186,187],"488":"b:CyBEAAEw5WEAsD5EAEAAAHwGJQBC9mscAAAAAAA=","509":"b:CyBEAAEw5WEAsD5EAEAAAHwGJQBC9mscAAAAAAA=","579":"b:DyBEGAEw5WEAsD5EAEAAAHwmJQBA9mscAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/executionStarted.ts":{"13":"b:DyBEWAEw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/nodeExecuteAfter.ts":{"16":"b:DyBEWAEw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA=","49":"b:DyBEWAEw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA=","50":"b:DyBEWAEw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/nodeExecuteAfterData.ts":{"11":"b:DyBEWAEw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/nodeExecuteBefore.ts":{"9":"b:DyBEWAEw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/testWebhookReceived.ts":{"8":[32,1,2,3,103,44,54,56,144,161,170,18,177]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/trackNodeExecution.ts":{"11":"b:DyBEWAEw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/usePushConnection/usePushConnection.ts":{"47":"b:D+pt+AM+5/FA+v/H4mMI8H/+/7j/////AAAAAAA=","48":"b:D+Jt+AE+5/FA+v5HoEAIAH5upbDu/+/fAAAAAAA=","53":[19,50,168,86,184],"62":"b:D+Jt+AE+5/FA+v5HoEAIAH5upbDu/+/fAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useResolvedExpression.ts":{"30":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","45":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","52":"b:DupFeABuQFFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","59":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","60":[27,46,134,137,149,170,18,81,82,173,85,177],"61":"b:BsoFCABAAAACEC8AAAAAAECKIQAAZA8AAAAAAAA=","66":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","68":"b:BsoFCABAAAACEC8AAAAAAECKIQAAZA8AAAAAAAA=","107":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","160":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","161":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","162":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useRunWorkflow.ts":{"72":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","97":"b:DyBEWAFw5GEAsD5EgEAIAHwmJQBC9mucAAAAAAA=","100":[46],"101":[46],"115":[27,28,46,56,138,166,170,18,172,84,85,179],"119":"b:DyBEWAFw5GEAsD5EgEAIAHwmJQBC9mucAAAAAAA=","120":[46],"134":"b:DyBEWAFw5GEAsD5EgEAIAHwmJQBC9mucAAAAAAA=","138":"b:DyBEWAFw5GEAsD5EgEAIAHwmJQBC9mucAAAAAAA=","289":"b:DyBEWAFw5GEAsD5EgEAIAHwmJQBC9mucAAAAAAA=","292":"b:DyBEWAFw5GAAsD5EgEAIAHwmJQBC9mucAAAAAAA=","298":[46],"324":[32,1,3,46,144,161,18],"335":[46,133,56,76,170,177],"359":[46,133,56,76,170,177],"402":[46,56,138,166,172,179],"455":[103,46,115,54],"495":"b:DyBEWAFw5GEAsD5EgEAIAHwmJQBC9mucAAAAAAA=","546":[46,170,18],"553":[46],"602":[46,170,18],"621":[46],"630":"b:AgBEQABw5GEAoDBEgEAIAFgiJAAAlmOcAAAAAAA=","651":[46]},"packages/frontend/editor-ui/src/app/composables/useRunWorkflowApi.ts":{"9":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","14":"b:DyBEWAFw5GEAsD5EgEAIAHwmJQBC9mucAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useSelectionValidation.ts":{"32":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","38":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","53":"b:DupFeAEuQJFAev9HgGAA8H++PzD8/n8+AAAAAAA=","70":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","77":"b:BsgFWAAAAAAAcFADAEAAABASOAAkAEMgAAAAAAA=","84":[78],"109":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","111":"b:DupFeAEuQJFAev9FgGAA8H++PzD8/n8+AAAAAAA=","115":"b:DupFeAEuQJFAev9FgGAA8H++PzD8/n8+AAAAAAA=","124":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","130":"b:DupleAEuQJFAev9FgGAA8H++PzD8/n8+AAAAAAA=","132":"b:DupleAEuQJFAev9FgGAA8H++PzD8/n8+AAAAAAA=","139":"b:DspleAAuQBFAev9FgGAAUE+OPzDs/n8eAAAAAAA=","141":"b:CoBhAAAAAAEAcjYAAAAAQAAKDwDssnocAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useSettingsItems.ts":{"29":"b:f+r/+4O/5/92+v/v+/j////////8////AAAAAAA=","228":"b:f+r/+4O/5/92+v/v+/j////////8////AAAAAAA=","229":"b:f+r/+4O/5/92+v/v+/j////////8////AAAAAAA=","232":"b:f+r/+4O/5/92+v/v+/j////////8////AAAAAAA=","237":"b:f+r/+4O/5/92+v/v+/j////////8////AAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useSidebarLayout.ts":{"11":"b:f+r/+4O/5/9i+v/P+/j99///P/H8////AAAAAAA=","17":"b:f+r/+4O/5/9i+v/P+/j99///P/H8////AAAAAAA=","27":[91,95,114,59,60]},"packages/frontend/editor-ui/src/app/composables/useTelemetryContext.ts":{"11":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useTelemetryInitializer.ts":{"13":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","23":[46],"27":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","32":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","36":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","40":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","59":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","63":[46],"69":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useUniqueNodeName.ts":{"4":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","11":[1,77,162,164,165,166,167,177,179,180,88],"12":[1,77,162,164,165,166,167,177,179,180,88],"27":"b:BsoF+AAqQJFAOt9HgmAA8D+yPhD0bl+qAAAAAAA=","34":[1,77,162,164,165,166,167,177,179,180,88]},"packages/frontend/editor-ui/src/app/composables/useUserHelpers.ts":{"5":"b:f+r/+4O/5/92+v/v+/j////////8////AAAAAAA=","6":"b:f+r/+4O/5/92+v/v+/j////////8////AAAAAAA=","12":"b:f+r/+4O/5/92+v/v+/j////////8////AAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useWorkflowActivate.ts":{"35":"b:D+pt+IP+5/9A+v/P4nAI8v//P7D8////AAAAAAA=","44":"b:AAAIAIDABBwACEAJABAAAsAAAAAAAQDDAAAAAAA=","57":[46],"79":[46],"99":[46],"111":[46,134,75,184,185],"118":[46,134,75,184,185],"119":[46,134,75,184,185],"134":[46,134,75,184,185],"150":[46,134,75,184,185],"155":[46],"163":[46,134,75,184,185],"197":[46,134,75,184,185],"314":[46,190]},"packages/frontend/editor-ui/src/app/composables/useWorkflowDiffRouting.ts":{"18":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","27":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","33":[46],"50":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","73":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","111":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","133":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useWorkflowExtraction.ts":{"45":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","60":[46],"69":[46],"81":[46],"85":[46],"95":[46,182],"113":[46,182],"115":[46,182],"146":[46,182],"147":[46,182],"151":[46],"173":[46,182],"184":[46,182],"192":[46,182],"193":[46,182],"199":[46,182],"200":[46,182],"254":[46,182],"279":[46,182],"307":[46,182],"312":[46,182],"313":[46,182],"320":[46,182],"338":[46,182],"342":[46,182],"344":[46,182],"351":[46,182],"352":[46],"356":[46],"357":[46],"370":[46],"380":[46,182],"383":[46,182],"417":[46,182],"436":[46,182],"455":[46,182],"460":[46,182],"476":[46,182],"479":[46,182],"480":[46,182],"489":[46],"514":[46,182],"524":[46],"535":[46],"568":[46,182],"575":[46,182],"578":[46,182],"583":[46,182],"592":[46,182],"593":[46,182],"599":[46,182],"600":[46,182],"615":[46,182],"644":[46,182],"645":[46,182],"653":[46,182],"660":[46,182],"672":[46,182],"692":[46,182]},"packages/frontend/editor-ui/src/app/composables/useWorkflowHelpers.ts":{"77":"b:RuoFCABCQAECEK8AgCIAEEiKIQCAdE8AAAAAAAA=","178":"b:ACAECABAAAAAACYAAAAAAEACIAAAJEoAAAAAAAA=","281":[46,178,179],"288":[46],"295":[46],"312":[1,41,46,176,16,178,179,182,87],"322":[1,41,46,176,16,178,179,182,87],"348":"b:BgBFWgBw5GEAoHBFgEAIAFgyPAAklmO8AAAAAAA=","354":"b:BuoFCABCQAEAEK8AgCIAEEiKIQCAdE8AAAAAAAA=","385":"b:ACAFCABAAAAAAC4AAAAAAEAAIACAZEoAAAAAAAA=","401":[46,133,56,76,170,177],"427":"b:BuoFCABCQAEAEK8AgCIAEGiKIQCAdE8AAAAAAAA=","516":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","530":"b:AAAFWAAAAAAAAFABAEAAABASOAAkAAMgAAAAAAA=","556":"b:BsoFeAAqAJBAMNVEAGAA8B+SPhDkBg8KAAAAAAA=","570":"b:BAIAAAACQAEAAAAAgCIAEAAAAAAAFAcAAAAAAAA=","591":"b:AAIAAAACQAEAAAAAgCIAEAAAAAAAFAcAAAAAAAA=","632":[27,28],"635":[27,28],"666":"b:RuoFCAACQAECEC8AgCIAEECKIQCAdA8AAAAAAAA=","742":"b:AAAFWAAAAAAAAFABAEAAABASOAAkAAMgAAAAAAA=","764":[76,162,165,177,88,89],"768":[76,162,165,177,88],"812":"b:C6BtAAEU5/BA4nQDIAMIAEhsAbAOn+HdAAAAAAA=","850":"b:C6BtAAEU5/BA4nQDIAMIAEhsAbAOn+HdAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useWorkflowId.ts":{"17":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","20":"b:f+r/+4O/5/92+v/v////////////////AAAAAAA=","40":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useWorkflowImport.ts":{"11":"b:D+oF+AM+4PFA+v/H4mMI8H/+P7D/////AAAAAAA=","17":[104,105,161],"19":[104,105,161]},"packages/frontend/editor-ui/src/app/composables/useWorkflowInitialization.ts":{"82":"b:D+pt+AM+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","93":"b:D+pt+AM+5/FA+v/H4GAI8n/+P7D8////AAAAAAA=","94":"b:D+pt+AM+5/FA+v/H4GMI8H/+P7D/////AAAAAAA=","95":"b:D+pt+AM+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","96":[97,89,191],"97":"b:D+pt+AM+5/FA+v/H4mAI8H/+P7D8////AAAAAAA=","99":"b:D+pt+AM+5/FA+v/H4mAI8n/+P7D8////AAAAAAA=","124":"b:D+pt+AM+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","209":"b:C6BtAAEU5/BA4nQDIAAIAEhsAbAMn2HdAAAAAAA=","226":"b:D+pt+AM+5/FA+v/H4mMI8n/+P7D/////AAAAAAA=","228":"b:D+pt+AM+5/FA+v/H4mMI8n/+P7D/////AAAAAAA=","264":"b:C6BtAAEU5/BA4nQDIAAIAEhsAbAMn2HdAAAAAAA=","319":"b:BsoF+AI6QBFAON/EwGMA8D+SPhD3Zp9rAAAAAAA=","334":"b:BsoF+AI6QBFAON/EwGMA8D+SPhD3Zp9rAAAAAAA=","367":"b:C6BtAAEU5/BA4nQDIAAIAEhsAbAMn2HdAAAAAAA=","422":"b:D+pt+AM+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","492":[19,50,168,86,184]},"packages/frontend/editor-ui/src/app/composables/useWorkflowNormalization.ts":{"22":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","26":"b:D+pt+gE+5/FA+v9HgmMI8H/+P7D+/3//AAAAAAA=","46":"b:D+pt+gE+5/FA+v9HgmMI8H/+P7D+/3//AAAAAAA=","58":"b:D+pt+gE+5/FA+v9HgmMI8H/+P7D+/3//AAAAAAA=","76":"b:C6BtAgEU5/BA4nQDIAMIAEhsAbAOn+HdAAAAAAA=","81":"b:C6BtAgEU5/BA4nQDAAMIAEhsAaAOn2HdAAAAAAA=","82":"b:C6BtAgEU5/BA4nQDAAMIAEhsAaAOn2HdAAAAAAA=","83":"b:C6BtAgEU5/BA4nQDAAMIAEhsAaAOn2HdAAAAAAA=","85":"b:C6BtAgEU5/BA4nQDAAMIAEhsAaAOn2HdAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useWorkflowPublicationStatusSync.ts":{"26":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","35":[134,57,75,184,185],"38":[57],"49":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","54":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","76":[44,57,62],"77":[57],"84":[57],"98":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","104":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","105":[44,134,57,62,75,184,185],"111":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","114":[57],"117":[19,50,57,60,168,86,184]},"packages/frontend/editor-ui/src/app/composables/useWorkflowSaving.ts":{"51":[46],"66":[46],"99":[46],"109":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","148":[46],"182":[46],"185":[46],"194":[46],"219":[46],"286":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","287":"b:D+pt+AN+5fFA+v/HwmMI8H/+P7D+////AAAAAAA=","291":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","316":"b:BsoF+ABqQJFAev9FgGAA8D+2PxD0ft9+AAAAAAA=","335":[46,60,168,169,86,184,187,188,191],"338":[46],"339":[46,86],"402":[46],"412":"b:BsIF+AJqQBEAer5GgEAAADYGJQDkds/eAAAAAAA=","419":"b:BsIF+AJqQBEAer5GgEAAADYGJQDkds/eAAAAAAA=","449":"b:BsIF+AJqQBEAer5EgEAAADYGJQDkds/eAAAAAAA=","569":"b:BsIF+AJqQBEAOJpGgEAAADYCJADkZo/KAAAAAAA=","629":[46],"637":[46],"639":[46],"645":[46],"746":[46],"804":"b:BsIFuABqQBEAerZCAEAAAAICJADkJsdaAAAAAAA=","818":"b:AsIBoABKQBEAeoIAAAAAAAIAAADkIodaAAAAAAA=","838":"b:BsoF+ABqQJFAev9HgGAA8D+2PxD0ft9+AAAAAAA=","847":"b:BgAE2AJgQAEAOH5EgEAAADQGJQBAdkuMAAAAAAA=","866":[104,105,46,19,48,22,50,60,161]},"packages/frontend/editor-ui/src/app/composables/useWorkflowUpdate.ts":{"39":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","58":[31,46],"60":[31,46],"63":[31,46],"70":[31,46],"93":[31,46],"106":[31,46],"183":[31,46],"192":[31,46],"196":[31,46],"211":[31,46],"236":[31,46],"248":[31,46],"249":[31,46],"253":[31,46],"255":[31,46],"279":[31,46],"313":[31,46],"325":[31,46],"340":[31,46],"348":[31,46],"367":[31,46]},"packages/frontend/editor-ui/src/app/composables/useWorkflowsCache.ts":{"24":"b:D+Jt+AM+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","27":"b:D+Jt+AM+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","32":"b:D+Jt+AM+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","36":"b:D+Jt+AM+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","43":[44,134,57,62,75,185],"58":[44,134,57,62,75,184,185],"69":[57],"78":[57]},"packages/frontend/editor-ui/src/app/constants/actions.ts":{"1":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/constants/experiments.ts":{"16":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/constants/localStorage.ts":{"18":[4,111,5,112,6,17,46],"20":[4,111,5,112,6,17,46],"22":[23,24,46],"26":[4,111,5,112,6,17,46],"28":[46],"33":[46],"38":[46],"48":"b:D+pt+AN+5/FA+v/H4mAI8H/+P7D8////AAAAAAA=","50":"b:D+pt+AN+5/FA+v/H4mAI8H/+P7D8////AAAAAAA=","52":"b:D+pt+AN+5/FA+v/H4mAI8H/+P7D8////AAAAAAA=","54":[46]},"packages/frontend/editor-ui/src/app/constants/navigation.ts":{"9":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/constants/nodeCreator.ts":{"27":"b:BsoBKABqQJFAOt9EgCAA8C+gDhD0bh8KAAAAAAA="},"packages/frontend/editor-ui/src/app/constants/workflows.ts":{"16":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/dev/render-tracker.ts":{"38":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","47":[46],"67":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","78":[46],"83":[46],"86":[46],"94":[46]},"packages/frontend/editor-ui/src/app/init/expressionEngine.ts":{"19":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/init/index.ts":{"52":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","116":"b:f+r/+4P/5/92+v/v//v/////////////AAAAAAA=","136":[93,95,46,154,100],"157":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","197":[95,46],"208":[46],"219":"b:X+r/+4P/5/92+v/v//j////////8////AAAAAAA=","226":[46],"260":[46],"268":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","281":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","327":[46]},"packages/frontend/editor-ui/src/app/init/toastNotifier.ts":{"19":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","20":"b:TyIHGIF44H9i8H5HGMCHAfyn5cVG9u9dAAAAAAA="},"packages/frontend/editor-ui/src/app/layouts/BaseLayout.vue":{"4":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","10":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","13":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/layouts/WorkflowLayout.vue":{"34":"b:D+oF+AM+4PFA+v/H4mAI8H/+P7D8////AAAAAAA=","35":"b:D+oF+AM+4PFA+v/H4mAI8H/+P7D8////AAAAAAA=","36":[32,1,2,3,142,144,18,188],"63":"b:D+oF+AM+4PFA+v/H4mAI8H/+P7D8////AAAAAAA=","72":[60,97,86,184,89,191],"85":[169],"93":[168,86,184],"102":"b:D+oF+AM+4PFA+v/H4mAI8H/+P7D8////AAAAAAA=","104":"b:D+oF+AM+4PFA+v/H4mAI8H/+P7D8////AAAAAAA=","106":"b:D+oF+AM+4PFA+v/H4mAI8H/+P7D8////AAAAAAA=","116":"b:D+oF+AM+4PFA+v/HwmAI8H/+P7D8////AAAAAAA=","119":"b:D+oF+AM+4PFA+v/H4mAI8H/+P7D8////AAAAAAA="},"packages/frontend/editor-ui/src/app/modals.manifest.ts":{"20":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","21":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","39":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","40":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA="},"packages/frontend/editor-ui/src/app/models/history.ts":{"8":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","38":"b:BsoF+ABqQJFAet9FgGAA8D+yPxD0fl8+AAAAAAA=","47":[46],"55":"b:BsoF+AJqQJFAet9FgGAA8D+yPxD0fl8+AAAAAAA=","60":"b:BgAEWABgQAEAMBpEgEAAADQiJQBAdkscAAAAAAA=","61":"b:BgAEWABgQAEAMBpEgEAAADQiJQBAdkscAAAAAAA=","72":[31,46,144,146,147,76,77,78,165,88],"84":[46,165],"88":[46,146,147,76,78],"99":[46,165],"100":[46,165],"113":"b:BsoF+ABqQJFAOt9FgGAA8D+yPhD0bl8qAAAAAAA=","118":[46,165,182],"122":"b:BsoF+ABqQBFAOt9EgGAAUB+SPhDkal8iAAAAAAA=","126":[46,165,182],"127":[46,165,182],"137":[46,140,141,76,77,78,165,18,182],"142":[46,165,182],"146":[46,77,165,182],"150":[46,165,182],"151":[46,165,182],"161":"b:BsoF+ABqQBFAet9EgGAAUB+SPhDkal8iAAAAAAA=","166":[46,165,182],"170":"b:BAAFmABAAAAAcBAAAAAAQBASLAAgAEMgAAAAAAA=","180":[46,165,182],"181":[46,165,182],"191":[31,46,140,141,146,147,76,77,78,165,18,182],"196":[46,165,182],"200":[31,46,140,141,146,147,76,77,78,165,18,182],"210":[46,165,182],"211":[46,165,182],"212":[46,165,182],"227":"b:AgAEAABAAAAAGAAAAAAAAAAAAAAkEgAeAAAAAAA=","234":[46,165],"238":[46,162,165],"244":[46,165],"245":[46,165],"260":[46,162],"266":[46],"270":[46],"278":[46],"279":[46],"290":[46,147,182],"299":[46,182],"308":[46,147],"317":[46,182],"318":[46,182],"329":[46,78],"333":[46],"339":[46],"346":[46,78],"351":[46],"355":[46],"361":[46],"362":[46],"372":[46,78],"377":[46],"381":[46,78],"387":[46],"388":[46],"400":[46,78],"406":[46],"410":[46,78],"418":[46],"419":[46]},"packages/frontend/editor-ui/src/app/moduleInitializer/moduleInitializer.ts":{"25":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","26":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","27":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","36":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","38":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","56":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","58":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","73":"b:AAD4AwDABwAUAAAAAQj0DwAAAAIAAAAAAAAAAAA=","80":[46],"105":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","106":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","107":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","110":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","123":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","125":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","135":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","136":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","137":[46],"152":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","153":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","154":[46],"161":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","170":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","187":[46,66,153,68],"197":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","200":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","201":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/plugins/cache.ts":{"3":"b:D+Jt+AM+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","8":"b:D+Jt+AM+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","9":"b:D+Jt+AM+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","10":"b:D+Jt+AM+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","13":"b:D+Jt+AM+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","25":[57],"33":"b:D+Jt+AM+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","34":"b:D+Jt+AM+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","36":"b:D+JN+AM+5/NA+v5GoEAIAH5uJbDs9+/fAAAAAAA=","39":"b:D+Jt+AM+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","40":[57],"44":[44,134,57,62,75,185],"49":"b:D+Jt+AM+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","53":[57],"58":[57],"63":[57],"67":[57],"68":[57],"71":[57],"82":[57],"89":"b:D+Jt+AM+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","99":"b:D+Jt+AM+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","100":"b:D+Jt+AM+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","104":[57],"111":[44,134,57,62,75,185],"112":[44,134,57,62,75,185],"117":[57],"118":[57],"123":[57],"124":[57]},"packages/frontend/editor-ui/src/app/plugins/chartjs.ts":{"15":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/plugins/components.ts":{"10":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/plugins/directives.ts":{"5":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/plugins/sentry.ts":{"33":[46,98],"36":[46,98],"60":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/plugins/telemetry/index.ts":{"31":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","46":"b:f+r/+4P/5/92+v/v//v/////////////AAAAAAA=","50":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","55":[46],"85":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","119":"b:f+p/+AP+5/9C+v/P8/j////////+////AAAAAAA=","149":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","179":[46],"183":[46],"186":[46],"191":[46],"205":[46],"221":"b:AsIBUABqQAFAMo9EgGAAAA4kEBDkck8AAAAAAAA=","247":[46],"266":[46],"267":[46],"283":[46],"309":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/plugins/vitePreloadError.ts":{"4":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","5":[46],"14":[46]},"packages/frontend/editor-ui/src/app/push-connection/useEventSourceClient.ts":{"13":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","17":[46,61],"22":[46],"32":[46,61],"36":[46,61],"46":[46,61],"59":[46],"64":[46,61]},"packages/frontend/editor-ui/src/app/push-connection/useHeartbeat.ts":{"12":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","17":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","21":[112,46,168]},"packages/frontend/editor-ui/src/app/push-connection/useReconnectTimer.ts":{"14":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","21":[46],"27":[46],"33":[112,46,168],"40":"b:f+r/+wN+5/FA+v/H4+j593/+/7j+////AAAAAAA="},"packages/frontend/editor-ui/src/app/push-connection/useWebSocketClient.ts":{"24":"b:f+r/+4P/5992+v/v////////////////AAAAAAA=","35":[6,46],"40":"b:f+r/+wN+59FA+v/H4+j593/+/7j+////AAAAAAA=","47":[46],"53":"b:f+Lv+QF+59FA+v5HoMAJAH5upbDu/+/fAAAAAAA=","57":[46],"61":"b:f+r/+wN+59FA+v/H4+j593/+/7j+////AAAAAAA=","75":"b:f+r/+wN+59FA+v/H4+j593/+/7j+////AAAAAAA=","89":[46],"94":"b:D+Lt+QN+59FA+v5HoEAIAH5uJbDs/+/fAAAAAAA="},"packages/frontend/editor-ui/src/app/router.ts":{"35":[46],"36":[46],"37":[46],"38":[46],"39":[46],"40":[46],"41":[46],"42":[46],"43":[46],"44":[46],"46":"b:D+oF+AN+4PFA+v/HwmMI8H/+P7D+////AAAAAAA=","47":[1,46,62,169,170,79,18,186,187,188],"48":[1,46,62,169,170,79,18,186,187,188],"49":[1,46,169,170,79,18,186,187,188],"50":[1,46,169,170,79,18,186,187,188],"53":[46,62,169,170,79,18,186,187,188],"54":[46,62,169,170,79,18,186,187,188],"55":[46],"56":[46],"57":[93,46,154,100],"58":[93,46,154,100],"59":[46,69],"60":[46,69],"61":[46],"62":[46,150,151],"63":[46,150,151],"64":[95,46],"65":[95,46],"66":[46],"67":[107,108,46,100],"68":[46],"69":[46,89],"70":[46,89],"71":[46,191],"72":[46,191],"73":[46,89],"74":[46,89],"75":[46,191],"76":[46,191],"77":[46],"78":[46],"79":[46],"80":[46],"81":[46],"82":[46],"83":[46],"84":[46,99],"85":[46,99],"86":[46,65],"91":[46,65],"96":[46],"100":[46,155],"101":[46,155],"102":[46,168],"103":[46,168],"104":[46,191],"105":[46,75],"106":[46,75],"107":[46],"108":[46],"109":[101,46],"110":[101,46],"111":[101,46,75],"112":[101,46,75],"113":[46],"114":[46],"115":[46],"116":[46],"117":[46],"119":[46,62],"120":[46,62],"124":[46],"125":[46],"127":[46],"128":[46],"130":[46],"142":[46],"164":[46],"165":"b:IABYAABBBwAAAAAAAAjgAQAAAAAAAAAAAAAAAAA=","189":[46],"212":[46],"234":[46],"246":[46,97,89],"268":[46],"275":[46,191],"280":[46,191],"296":[46],"312":[46],"430":[46],"445":"b:BsoF+AJ6QBFAON/GwmAA8D+SPhD0Zp/rAAAAAAA=","465":[104,105,46,161],"476":[46,160],"482":[46,160],"605":[106,46],"624":"b:f+r/+4P/5/92+v/v+/j////////8////AAAAAAA=","631":[46],"642":[46],"670":[46],"686":[46],"707":[46],"728":[46],"746":[27,28,29,30,31,102,33,46,63],"753":[46],"765":[46],"774":[46],"781":[46],"806":"b:X+r/+4P+5/92+v/u+/j////////8////AAAAAAA=","813":[46],"824":[46],"835":[46],"846":[46],"856":[46],"872":[46],"877":[46],"882":[46],"888":[46],"904":[46],"921":[46],"926":[46],"931":[46],"944":[46],"960":[46],"981":[46],"1002":[46],"1023":[46],"1041":[46],"1050":[46],"1081":"b:X+r/+4P+5/92+v/u+/j////////8////AAAAAAA=","1114":[46],"1157":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","1172":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","1182":[107,108,46,100],"1186":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","1226":[107,46,69],"1265":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/stores/aiGateway.store.ts":{"17":[46],"18":[46],"22":[46],"38":"b:f+r/+4P/5/92+v/v+/r////////8////AAAAAAA=","42":[46],"44":[46],"46":[46],"64":[46],"70":[46],"74":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","81":"b:f+r/+4P/5/92+v/v+/r////////8////AAAAAAA=","88":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","101":[46],"105":[46],"107":[46],"120":[46],"132":[46],"143":[46],"154":[46],"162":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","173":[46],"191":[46],"206":[46],"215":[46],"226":[46],"243":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","245":"b:RgIFgABsQBFAAAAAAAAAAACAADAAAAAAAAAAAAA=","248":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","265":"b:QCIBIABKQBFACDIAgAAAUAMKADCEIB8CAAAAAAA=","279":[46]},"packages/frontend/editor-ui/src/app/stores/aiSimulatedExecutions.store.ts":{"21":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","24":[46],"36":"b:CABEGABAQEEAADwEgEAAAGwEIABA1msQAAAAAAA="},"packages/frontend/editor-ui/src/app/stores/backendConnection.store.ts":{"7":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","10":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/stores/canvas.store.ts":{"6":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","13":"b:CQAMAAFCBAEAUBAAAAAAAAAAAQAcAEEAAAAAAAA=","20":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","27":"b:D+pt+AN+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","28":"b:D+pt+AN+5/FA+v/HwmAI8H/+P7D+////AAAAAAA="},"packages/frontend/editor-ui/src/app/stores/executionData.store.ts":{"59":"b:D+pt+gN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","66":"b:D+pt+gN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","75":[46,18,187,188],"85":"b:D+pt+gN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","86":"b:D+pt+gN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","95":"b:D+pt+gN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","99":"b:ACBEGABAQAEAID4EgEAAAGwmJABA9msAAAAAAAA=","101":"b:DyBEGAFw5WEAsD5EAEAAAHwmJQBC9mscAAAAAAA=","116":"b:DyBEWAFw5WEAsD5EgEAIAHwmJQBC9mucAAAAAAA=","133":"b:DyBEWgFw5WEAsD5EgEAAAHwmJQBG/mscAAAAAAA=","136":"b:DyBEWgFw5WEAsD5EgEAAAHwmJQBG/mscAAAAAAA=","139":[46],"142":[27,28,46,56,138,18,172,84,85,179,187],"145":[27,28,46,56,138,18,172,84,85,179,187],"151":"b:D+pt+gN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","159":"b:D+pt+gN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","190":"b:D+pt+gN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","192":"b:DyBEWgFw5WEAsD5EgEAIAHwmJQBG/mucAAAAAAA=","196":"b:DyBEWAFw5WEAsD5EgEAIAHwmJQBC9mucAAAAAAA=","200":"b:D+pt+gN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","219":"b:DyBEWAFw5WEAsD5EgEAIAHwmJQBC9mucAAAAAAA=","236":"b:DyBEWAFw5WEAsD5EgEAIAHwmJQBC9mucAAAAAAA=","246":"b:DyBEWAFw5WEAsD5EgEAIAHwmJQBC9mucAAAAAAA=","255":"b:DyBEGAFw5WEAsD5EAEAAAHwmJQBC9mscAAAAAAA=","264":"b:DyBEWAFw5WEAsD5EgEAIAHwmJQBC9mucAAAAAAA=","300":"b:DyBEWgFw5WEAsD5EgEAIAHwmJQBG/mucAAAAAAA=","306":"b:DyBEWgFw5WEAsD5EgEAIAHwmJQBG/mucAAAAAAA=","309":"b:DyBEWAFw5WEAsD5EgEAIAHwmJQBC9mucAAAAAAA=","319":"b:DyBEWAFw5WEAsD5EgEAIAHwmJQBC9mucAAAAAAA=","324":"b:DyBEWAFw5WEAsD5EgEAIAHwmJQBC9mucAAAAAAA=","329":"b:DyBEWAFw5WEAsD5EgEAIAHwmJQBC9mucAAAAAAA=","338":"b:DyBEGAFw5WEAsD5EAEAAAHwmJQBC9mscAAAAAAA=","342":[46,182],"345":[46,182],"355":"b:D+pt+gN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","363":"b:D+pt+gN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","379":"b:D+pt+gN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","389":"b:DyBEGAFw5WEAoDZEgEAIAFwmJQBAvmscAAAAAAA=","480":"b:DyBEWgFw5WEAsD5EgEAIAHwmJQBG/mucAAAAAAA=","500":"b:DyBEWAFw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA=","508":[46],"522":"b:DyBEGAFw5WEAsD5EAEAAAHwmJQBA9mscAAAAAAA=","526":"b:DyBEWgFw5WEAsD5EgEAIAHwmJQBG/mucAAAAAAA=","538":"b:DyBEWAFw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA=","546":"b:DyBEWAFw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA=","561":[46,170,18],"566":"b:DyBEWAFw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA=","585":[3,90,46,54,134,18,84,85,181,182],"590":[3,90,46,54,134,18,84,85,181,182],"609":"b:DyBEWAFw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA=","613":[46],"628":"b:DyBEWAFw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA=","631":"b:DyBEWAFw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA=","639":[46],"646":[46],"666":[46],"667":[46],"671":[46],"683":[46],"684":[46],"692":[46],"736":[46,170,18],"744":[46,170,18],"756":[46],"807":"b:D+pt+gN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA="},"packages/frontend/editor-ui/src/app/stores/favorites.store.ts":{"9":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","16":[46],"17":[46],"20":[46],"21":[46],"24":[46],"25":[46],"28":[46],"29":[46],"32":[46],"33":[46],"36":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","46":"b:D+rv+YP+5/9C+v/P4nAM8v//P7D8////AAAAAAA=","47":[46],"52":[23,24,46,47,136,58,60],"53":[46],"61":[46],"68":[46],"86":[46,184,190],"87":[46],"92":[46]},"packages/frontend/editor-ui/src/app/stores/focusPanel.store.ts":{"47":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","49":[46],"54":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","64":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","71":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","72":[46,148,163],"73":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","76":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","78":[46],"98":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","104":[46,148,163],"139":"b:BsIF+AJqQBEAOJpGgEAAADYCJADkZo/KAAAAAAA=","155":[46],"163":[46],"167":[46],"171":[46],"175":[46,148,163],"179":[46],"183":[46],"189":[46],"193":[46,148,163],"196":[46],"204":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","205":[46,148,163],"217":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","221":[46],"229":[46]},"packages/frontend/editor-ui/src/app/stores/history.store.ts":{"10":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","17":[46,165,182],"24":"b:BsoF+ABqQJFAet9FgGAA8D+yPxD0fl8+AAAAAAA=","28":"b:BsoF+ABqQBFAet9EgGAAUB+yPhDkal8iAAAAAAA=","41":[46,165],"48":"b:BsoF+ABqQJFAet9FgGAA8D+yPxD0fl8+AAAAAAA=","53":[46,165,182],"58":"b:D+pt+AN+5/FA+v/H4GMI8H/+P7D/////AAAAAAA=","61":"b:D+pt+AN+5/FA+v/H4GMI8H/+P7D/////AAAAAAA=","64":"b:D+pt+AN+5/FA+v/H4GMI8H/+P7D/////AAAAAAA=","68":[46,165],"74":[46,165,182],"78":"b:BsoF+AJqQJFAet9FgGAA8D+yPxD0fl8+AAAAAAA=","81":"b:BsoF+AJqQJFAet9FgGAA8D+yPxD0fl8+AAAAAAA="},"packages/frontend/editor-ui/src/app/stores/logs.store.ts":{"18":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","24":"b:D+p9+AN+5/FA+v/H42j493/+P7D+////AAAAAAA=","52":"b:D+pt+AN+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","56":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","60":[32,1,3,46,60,161,18],"64":[32,1,3,46,60,161,18],"68":"b:D+p9+AN+5/FA+v/H42j493/+P7D+////AAAAAAA=","72":[46],"76":[32,1,2,3,46,144,18,188],"80":[46,18],"101":[46],"122":[46],"126":[32,1,2,3,46,144,161,18],"132":"b:D+p9+AN+5/FA+v/H42j493/+P7D+////AAAAAAA=","133":[32,1,2,3,46,144,18,188],"136":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","137":"b:D+pt+AN+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","138":"b:DsoEAAFAAIAAAAAAAAAAAADAAQACAAAAAAAAAAA=","139":[32,1,2,3,46,142,144,161,18]},"packages/frontend/editor-ui/src/app/stores/nodeTypes.store.ts":{"41":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","58":"b:DupFeABuQNFAOv9EgGIA8G+uPzDs/n+aAAAAAAA=","59":"b:DupFeABuQNFAOv9EgGIA8G+uPzDs/n+aAAAAAAA=","77":"b:T+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","79":"b:DuIB+AB+QNFA+v/HwmAI8H/+P7D8////AAAAAAA=","80":"b:DuIB+AB+QNFA+v/HwmAI8H/+P7D8////AAAAAAA=","83":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","85":"b:BsIBKABKQJFAOt5AgCAA8C+gDhDkbh8KAAAAAAA=","86":"b:BsIBKABKQJFAOt5AgCAA8C+gDhDkbh8KAAAAAAA=","89":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","93":"b:D+pt+AN+5/FA+v/H4mMI8n/+P7D/////AAAAAAA=","94":"b:BsoN+ABqQJFAOt9HgmAA8D+yPhD0b1+qAAAAAAA=","95":"b:BsoN+ABqQJFAOt9HgmAA8D+yPhD0b1+qAAAAAAA=","99":"b:T+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","101":"b:T+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","109":"b:T+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","116":"b:T+pt+gN+5/FW+v/HwmMI8H/+P/L/////AAAAAAA=","117":"b:T+pt+gN+5/FW+v/HwmMI8H/+P/L/////AAAAAAA=","132":"b:DupFeABuQFFAOv9GgGIAUG+uPzDs/n8SAAAAAAA=","133":"b:DupFeABuQFFAOv9GgGIAUG+uPzDs/n8SAAAAAAA=","138":[1,2,46,11,130,14,15,16],"139":[1,2,46,11,130,14,15,16],"150":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","151":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","163":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","168":"b:D+pt+gF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","169":"b:D+pt+gF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","175":"b:D+pF+ABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","176":"b:D+pF+ABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","179":"b:D+pF+ABuQFFAOv9EgGAAUG+uPzDs/n8SAAAAAAA=","191":"b:DspFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","192":"b:DspFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","195":"b:DspFeABuQFFAOv9EgGAAUG+uPzDs/n8SAAAAAAA=","207":[46],"208":[46],"213":"b:T+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","216":"b:T+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","219":[46],"220":[46],"226":[1,2,6,46,11,14,15,16],"227":[1,2,6,46,11,14,15,16],"231":[1,2,6,46,11,14,15,16],"252":[1,2,6,46,11,14,15,16],"268":[46],"269":[46],"273":[46],"292":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","293":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","307":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","318":"b:f+pv+gN+5/lC+v/H4uMJ8H/+f/D/////AAAAAAA=","326":[46],"327":[46],"335":[46],"339":[46],"362":[46],"373":[46],"385":[46],"399":[46],"401":[46],"409":"b:f+pv+gN+5/lC+v/H4uMJ8n/+f/D/////AAAAAAA=","420":"b:cAIiIgBoAhhCAAACAIABAAAAAEABAACIAAAAAAA=","426":[46],"434":[41,46,176,16],"438":[1,46,178],"442":[46,178,179],"450":[46,182,87],"458":[46],"462":"b:T+pt+AN+5/FA+v/H4mMI8n/+f7D/////AAAAAAA=","472":"b:DuIB+AB+QNFA+v/H4mMI8H/+f7D/////AAAAAAA=","479":[46,129,150,151],"497":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","504":"b:D+pt+gF+5/FA+v9HgmMI8H/+P7D+/3//AAAAAAA=","505":"b:D+pt+gF+5/FA+v9HgmMI8H/+P7D+/3//AAAAAAA=","514":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","517":[46],"518":"b:D+pF2gFy5WEAsP9FgGIIEHy+PQDn92+8AAAAAAA="},"packages/frontend/editor-ui/src/app/stores/npsSurvey.store.ts":{"18":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","27":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","35":"b:BqAFAABEAMAkCNIIgHgAEHX+f/oYsHm9AAAAAAA=","75":[46],"79":"b:AsIBoABKQBEAeoICAAAAAAIAAADkIodSAAAAAAA=","99":[46],"110":[46]},"packages/frontend/editor-ui/src/app/stores/posthog.store.ts":{"30":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","47":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","52":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","62":[46],"72":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","76":[46,11],"81":"b:f+r/+4P/5/92+v/v+/j////////8////AAAAAAA=","88":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","92":[46],"94":[101,46],"100":[46],"118":[31,101,46,21,121,97,148,163,89],"131":[46],"142":[46],"146":[46],"150":[46],"168":[46],"192":[46],"193":[46],"199":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","261":[46],"284":[46],"301":[46],"312":[46],"324":"b:AAAFWABAAAAAEFADAEAAABASKAAkAAIgAAAAAAA=","359":[46],"366":[46]},"packages/frontend/editor-ui/src/app/stores/pushConnection.store.ts":{"18":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","36":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","39":"b:AABIAABABRAACEAAAAABA0AAAAAAAQADAAAAAAA=","47":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","49":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","67":"b:f+Lv+QF+5/FA+v5HoMAJAH5upbDu/+/fAAAAAAA=","81":"b:f+Lv+QF+5/FA+v5HoMAJAH5upbDu/+/fAAAAAAA=","86":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","88":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","94":"b:D+Lt+QN+5/FA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","106":"b:f+r/+wN+5/FA+v/H4+j593/+/7j+////AAAAAAA=","129":"b:f+r/+wN+5/FA+v/H4+j593/+/7j+////AAAAAAA=","136":"b:f+r/+wN+5/FA+v/H4+D58X/+/7D+////AAAAAAA=","157":[112,46,168,86,184],"183":[112,46],"196":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","197":"b:f+r/+wN+5/FA+v/H4+j593/+/7j+////AAAAAAA=","218":[46,19,50,60,168,86,184],"222":"b:f+p/+wN+5/FA+v/H4+D59X/+P7j+////AAAAAAA="},"packages/frontend/editor-ui/src/app/stores/recentWorkflows.store.ts":{"26":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","34":"b:D+It+AN+4PNA+v5HgEAIAH5uJbDs/+/fAAAAAAA=","44":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","61":[46,73,182,190],"64":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","89":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","99":"b:D+IN+AN+4PFA+v5HgEAIAH5uJbDs/+/fAAAAAAA=","106":[46],"110":"b:D+IN+AN+4PFA+v5HgEAIAH5uJbDs/+/fAAAAAAA=","114":"b:CuIFKABOQBFAenYFgEAAAGguJSDkv2NbAAAAAAA=","143":[46,21],"156":[46],"164":[46],"174":[46],"175":[46],"176":[46],"177":[46],"193":[46],"194":[46],"195":[46]},"packages/frontend/editor-ui/src/app/stores/ui.store.ts":{"65":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","67":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","84":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","100":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","104":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","111":[46],"131":"b:AAChAIBFQF4CYkIBGAA0B4gBAAAECELBAAAAAAA=","132":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","195":"b:f+pt+gF+5/lC+v9HguML8H/+P/Dv/3//AAAAAAA=","199":"b:f+pt+gF+5/lC+v9HguML8H/+P/Dv/3//AAAAAAA=","203":[46,152,159,190],"270":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","280":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","282":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","290":"b:L+pt+AN+5/lC+v/HwmMK8H/+P/D+////AAAAAAA=","292":"b:f+r/+4P/5/92+v/v+/j////////8////AAAAAAA=","294":"b:f+r/+4P/5/92+v/v+/j////////8////AAAAAAA=","299":"b:f+r/+4P/5/92+v/v+/j////////8////AAAAAAA=","305":"b:C6BtAAFU5/BA4nQDIAAIAEhsEbA+n2PdAAAAAAA=","313":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","314":[46],"320":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","325":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","333":[46],"337":[46],"347":"b:ZgINqILoBFh2iEADEoAHAEKBwPMgB8T/AAAAAAA=","355":[46],"358":[46],"371":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","372":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","381":"b:BgIBIABoABBCAAACAIACAAKAwEAAAAQAAAAAAAA=","385":"b:BgIBIABoABBCAAACAIACAAKBwEAAAAQAAAAAAAA=","389":"b:BgIBIABoABBCAAACAIAAAAKAAEAAAAQAAAAAAAA=","393":"b:YAIAKABoABh2CAAAEAADAEABAPMAAMBDAAAAAAA=","404":"b:ZgIBKIDoAFh2CAACEoAHAEKBwPMgAMRjAAAAAAA=","418":"b:ZgIBKIDoAFh2CAACEoAHAEKBwPMgAMRjAAAAAAA=","424":"b:YAIAKABoABh2CAAAEAADAEABAPMAAMBDAAAAAAA=","429":"b:ZgINqALoBFhyiEADEIAHAECAwPEgB8T/AAAAAAA=","431":"b:ZgIBKADoAFhyCAACEIAHAECAwOEgAMBjAAAAAAA=","434":[46],"444":[46],"449":[113,9,45,46],"480":"b:BgIBIABoABBCAAACAIAAAAKAAEAAAAQAAAAAAAA=","532":[46,150],"538":[46,150,151],"548":[46,136],"557":[46,59,157],"574":[46],"580":[46],"587":[91,95,46,114,59,60],"594":"b:D+pt+AN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","601":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","612":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","625":"b:DyBEGAFw5WEAsD5EAEAAAHwmJQBC9mscAAAAAAA=","629":"b:BsoF+ABqQJFUev9HgmAA8D+2PxL0ft/+AAAAAAA=","637":"b:D+pt+AN+5/FQ+v/H4mMI8H/+P7L/////AAAAAAA=","652":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","653":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","654":[44,46,134,62,75,184,185],"668":[93,46,154,100],"712":[29,43,5,113,9,45,46,59,60,97,65,158,70,89],"719":[29,43,5,113,9,45,46,59,60,97,65,158,70,89],"720":[29,43,5,113,9,45,46,59,60,65,158,70,89]},"packages/frontend/editor-ui/src/app/stores/ui.utils.ts":{"4":[105,46,160],"12":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","17":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","23":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentActive.ts":{"14":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","17":"b:D+JF+AN65XEA+r5GgGAIAH4mLQDu/v/+AAAAAAA=","21":"b:D+Jt+gN+5/FA+v5HoEMIAH5uJbDv/+/fAAAAAAA=","30":"b:D+Jt+gN+5/FA+v5HoEMIAH5uJbDv/+/fAAAAAAA=","34":"b:C6BtAAFU5/BA4nQDIAAIAEhsAbAOn+HdAAAAAAA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentChecksum.ts":{"12":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","17":"b:D+Jt+gN+5/FA+v5HoEMIAH5uJbDv/+/fAAAAAAA=","22":"b:D+Jt+gN+5/FA+v5HoEMIAH5uJbDv/+/fAAAAAAA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentConnections.ts":{"35":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","46":"b:C6BtggFU5/BA4vQDIgMIAEhsAbAPn+HdAAAAAAA=","52":"b:BsoF+ABqQBFAet9EgGAAUB+SPhDkal8iAAAAAAA=","74":"b:BsoF+ABqQBFAet9EgGAAUB+SPhDkal8iAAAAAAA=","117":[31,46,140,141,146,147,76,77,78,165,18,182],"147":[46,140,141,76,77,78,165,18,182],"189":[46,68],"198":"b:T+pt+gN+5/FC+v/HwmMI8H/+P7D/////AAAAAAA=","200":"b:T+pt+gF+5/FC+v9HgmMI8H/+P7D//3//AAAAAAA=","204":"b:DupF+ABuQFFAev9HgGIAUG++PzDs/n8eAAAAAAA=","211":"b:DyBE2AFw5WEA8D5EgEAAAHw2JQBi9mscAAAAAAA=","222":"b:C6BtggFU5/BA4vQDIgMIAEhsAbAPn+HdAAAAAAA=","226":"b:BsoF+ABqQBFAet9EgGAAUB+SPhDkal8iAAAAAAA=","230":[31,46,140,141,146,147,76,77,78,165,18,182],"234":[46,140,141,76,77,78,165,18,182],"241":[46],"247":[46,68]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentDescription.ts":{"12":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","17":"b:C6BtAgFU5/BA4nQDIAMIAEhsAbAPn+HdAAAAAAA=","25":"b:C6BtAgFU5/BA4nQDIAMIAEhsAbAPn+HdAAAAAAA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentExpression.ts":{"6":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","11":"b:T+pt+gN+5/FC+v/HwmMI8H/+P7D/////AAAAAAA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentGraph.ts":{"16":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","21":"b:T+pF+AFuQtFUev9HgGIA8H++PzL8/n8+AAAAAAA=","29":"b:D+pFegBuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","37":"b:DupF+gBuQNFAOv9HgmIA8H++PzD8/n+6AAAAAAA=","41":[46,182],"48":[46,146,147,76],"74":[46],"78":[2,3,46,144],"82":"b:BuoFCABCQAEAEK8AgCIAEEiKIQCAdE8AAAAAAAA=","86":"b:BuoFCABCQAEAEK8AgCIAEEiKIQCAdE8AAAAAAAA=","94":"b:DuoFeABuQBFAOv9EgGAAUA+OHzDsej8CAAAAAAA=","109":"b:DSBEGABAAAEAED4AAEAAACQEAQBAdAsAAAAAAAA=","112":"b:DSBEGABAAAAAAD4AAEAAAAQEAQBAdAsAAAAAAAA=","120":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","123":"b:DspF+ABuQFFAOv9EgGAAUE+OPzDs/n8SAAAAAAA=","132":"b:CSBEGABAAAEAED4AAEAAACQEAABAdAsAAAAAAAA=","134":[46]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentHomeProject.ts":{"9":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","14":"b:D+pt+gN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","22":"b:D+pt+gN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentIsArchived.ts":{"12":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","17":"b:C6BtAgFU5/BA4nQDIAMIAEhsAbAPn+HdAAAAAAA=","22":"b:C6BtAgFU5/BA4nQDIAMIAEhsAbAPn+HdAAAAAAA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentMeta.ts":{"13":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","18":"b:D6JtAgFc5/FA6nQDIgMIAEjsAbAPn+XfAAAAAAA=","26":"b:C6BtAgFU5/BA4nQDIAMIAEhsAbAPn+HdAAAAAAA=","30":"b:BgIBAABIAAFACAACAgAAAACAABAAAASCAAAAAAA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentName.ts":{"16":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","21":"b:D+pt+gN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","27":"b:D+pt+gN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentNodeGroups.ts":{"41":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","48":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","50":"b:DupF+AFuQNFAev9HgGIA8H++PzD8/n8/AAAAAAA=","60":"b:C6BtAgFU5/BA4nQDIAMIAEhsAbAPn+HdAAAAAAA=","61":[46,21,78],"68":[46,78],"84":[46,78],"93":"b:C6BtAgFU5/BA4nQDIAMIAEhsAbAPn+HdAAAAAAA=","97":[46,78],"113":[46,78],"114":[46],"132":[46,78],"136":[46,78],"142":[46],"150":[46,78],"156":[46],"161":[46,78],"166":[46,78],"172":[46],"181":[46],"188":[46,21,78],"192":"b:DupF+AFuQNFAev9HgGIA8H++PzD8/n8/AAAAAAA=","197":[46,140,141,153,68,76,77,78,165,18,182],"200":[46,78],"209":[104,105,46,19,50,60,68,161,168,86,184]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentNodeMetadata.ts":{"20":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","29":"b:S6BtggFU5/BQ4vQDIAMIAEhsAbAPn+HdAAAAAAA=","34":"b:T+pt+gF+5/FU+v9HgmMI8H/+P7L//3//AAAAAAA=","42":"b:DupF+ABuQNFAOv9HgmIA8H++PzD8/n+6AAAAAAA=","52":[46,169],"65":[46,140,141,66,153,68,76,77,78,165,18,182],"75":[46,162,16,87],"89":"b:S6BtggFU5/BQ4vQDIAMIAEhsAbAPn+HdAAAAAAA=","94":"b:BsoF+ABqQJFUOt9HgmAA8D+yPhL0bl+qAAAAAAA=","100":"b:S6BtggFU5/BA4vQDAAMIAEhsAaAPn2HdAAAAAAA=","105":[46,140,141,66,153,68,76,77,78,165,18,182],"109":[46,162,16,87],"113":"b:DupF+ABuQNFAOv9HgmIA8H++PzD8/n+6AAAAAAA=","117":"b:AkIB0ABiQAEAMo9EgGAAUA4kGADkck8AAAAAAAA=","124":[46],"131":[46],"138":[46,169],"142":"b:DyBEWAFw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA=","146":"b:DyBEGAFg5WEAoD5EgEAAAFwmJQBC9mscAAAAAAA=","150":"b:DyBEWAFw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA=","154":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentNodes.ts":{"75":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","91":"b:BuoF+ABuQhFAeq9HgmAAUA+uHzLkdl++AAAAAAA=","115":"b:S6BtggFU5/BA4vQDIAMIAEhsAbAPn+HdAAAAAAA=","139":"b:S6BtggFU5/BA4vQDAAMIAEhsAaAPn2HdAAAAAAA=","143":"b:BsoF+ABqQJFUOt9HgmAA8D+yPhL0bl+qAAAAAAA=","163":[46,66,153,68],"164":[46,153,68],"178":[46,140,141,76,77,78,165,18,182],"179":[46,140,141,76,77,78,165,18,182],"180":[46,140,141,76,77,78,165,18,182],"199":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","223":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","238":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","252":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","266":"b:T+pt+gF+5/FU+v9HgmMI8H/+P7L//3//AAAAAAA=","269":"b:T+pt+gF+5/FU+v9HgmMI8H/+P7L//3//AAAAAAA=","272":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","276":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","279":[104,46,140,141,153,68,76,77,78,165,18,182],"282":[104,46,140,141,153,68,76,77,78,165,18,182],"289":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","297":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","298":"b:S6BtggFU5/BA4vQDAAMIAEhsAaAPn2HdAAAAAAA=","299":"b:S6BtggFU5/BA4vQDAAMIAEhsAaAPn2HdAAAAAAA=","305":"b:T+pt+gF+5/FU+v9HomMI8H/+P7L/////AAAAAAA=","339":"b:T+pt+gF+5/FU+v9HomMI8H/+P7L/////AAAAAAA=","365":[46],"367":"b:BsoF+ABqQJFAOt9HgmAA8D+yPhD0bl+qAAAAAAA=","369":"b:T+pt+AN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","370":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D+/3//AAAAAAA=","376":"b:BsoBKABqQJFAOt9EgCAA8C+gDhD0bh8KAAAAAAA=","377":"b:BsoBKABqQJFAOt9EgAAA4AagDhDkah8CAAAAAAA=","384":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","388":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","392":"b:DuoFeABuQBFAOv9EgGAAUG+uPzDk/n8CAAAAAAA=","393":"b:DuoFeABuQBFAOv9EgGAAUG+uPzDk/n8CAAAAAAA=","396":"b:AgAEAABAAAAAGAADAAAAAAAAAAAkEgIeAAAAAAA=","404":"b:S6BtggFU5/BA4vQDIAMIAEhsAbAPn+HdAAAAAAA=","408":"b:BsoF+ABqQJFUOt9HgmAA8D+yPhL0bl+qAAAAAAA=","412":[46,66,153,68],"416":[46,140,141,76,77,78,165,18,182],"420":"b:BsIBcABqQAFAOo9EgGAAUA8kGBDkcl8CAAAAAAA=","421":"b:BsIBcABqQAFAOo9EgGAAUA8kGBDkcl8CAAAAAAA=","446":"b:BAIBIABKQAFAOoJAgAAAUAEgABDkIB8CAAAAAAA=","447":"b:BAIBIABKQAFAOoJAgAAAUAEgABDkIB8CAAAAAAA=","465":[31,46,144,146,147,76,77,78,165,88],"466":[31,46,144,146,147,76,77,78,165,88],"489":[31,46,144,146,147,76,77,78,165,88],"490":[31,46,144,146,147,76,77,78,165,88],"496":[46],"497":[46],"506":"b:BgIFgABoAAFAGAACAAAAAACAABIkEgQeAAAAAAA=","510":"b:BgIFgABoAAFAGAAAAAAAAACAABIkEgAeAAAAAAA=","526":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D+/3//AAAAAAA=","527":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D+/3//AAAAAAA=","554":[46,68],"564":[46,169],"565":[46,169],"572":[46],"577":[46],"607":[1,2,43,6,9,45,46,56,143,16,178],"614":[1,2,43,6,9,45,46,56,143,16],"633":[1,2,9,46,143]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentNodesIssues.ts":{"37":[31,46],"38":[31,46],"39":[31,46],"43":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","54":"b:DsoFqAFSQMEAKk4CgiAIEGDIAQAodBfjAAAAAAA=","63":"b:DsoFqAFSQMEAKk4CgiAIEGDIAQAodBfjAAAAAAA=","77":"b:BsoEoABCQAEACAACgiAAEACIAAAAABWiAAAAAAA=","93":"b:DsoFqAFSQMEAKk4CgiAIEGDIAQAodBfjAAAAAAA=","95":[31,33,46],"98":[46],"101":[31,46],"110":[31,46],"114":[31,46],"136":[46],"149":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","155":"b:T+pt+gF+5/FU+v9HgmMI8H/+P7L//3//AAAAAAA=","158":"b:T+pt+gF+5/FU+v9HgmMI8H/+P7L//3//AAAAAAA=","161":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","164":[104,46,140,141,153,68,76,77,78,165,18,182],"167":[104,46,140,141,153,68,76,77,78,165,18,182],"173":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","181":"b:T+pt+gF+5/FU+v9HomMI8H/+P7L/////AAAAAAA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentParentFolder.ts":{"9":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","14":"b:D+pt+gN+5/FA+v/H4GMI8H/+P7D/////AAAAAAA=","22":"b:D+pt+gN+5/FA+v/H4GMI8H/+P7D/////AAAAAAA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentPinData.ts":{"38":"b:AAABAABAAAAAAD4AAAAAAAACAACgYgMgAAAAAAA=","43":"b:AAABAABAAAAAAD4AAAAAAAACAACgYgMgAAAAAAA=","56":"b:C6BtAgFU5/BQ4nQDIAMIAEhsAbAPn+HdAAAAAAA=","57":"b:AAABAABAAAAAADQAAAIAAAAAAAAIlEGAAAAAAAA=","58":"b:AAABAABAAAAAADQAAAIAAAAAAAAIlEGAAAAAAAA=","68":"b:DupFegFuQFFAOv9HgGIAUG+uPzDs/n8yAAAAAAA=","72":"b:AAABAABAAAAAAD4AAAIAAAACAACo8kMgAAAAAAA=","76":"b:AAABAABAAAAAAD4AAAAAAAACAACgYgMgAAAAAAA=","79":"b:AAABAABAAAAAAD4AAAAAAAACAACgYgMgAAAAAAA=","89":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","94":"b:C6BtAgFU5/BQ4nQDIAMIAEhsAbAPn+HdAAAAAAA=","99":"b:AAABAABAAAAAAD4AAAAAAAACAACgYgMgAAAAAAA=","107":[46,165,169],"116":[46,162,16,87],"122":[46],"123":[46],"129":[46],"140":"b:C6BtAgFU5/BQ4nQDIAMIAEhsAbAPn+HdAAAAAAA=","144":"b:AAABAABAAAAAAD4AAAAAAAACAACgYgMgAAAAAAA=","148":[46,169],"152":[46,162,16,87],"156":"b:T+pt+gN+5/FC+v9HgmMI8H/+P7D/////AAAAAAA=","160":"b:DupF+ABuQFFAev9EgGIAUG+uPzDs/n8SAAAAAAA=","179":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","185":"b:T+pt+gF+5/FU+v9HgmMI8H/+P7L//3//AAAAAAA=","188":"b:T+pt+gF+5/FU+v9HgmMI8H/+P7L//3//AAAAAAA=","191":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","194":[104,46,140,141,153,68,76,77,78,165,18,182],"197":[104,46,140,141,153,68,76,77,78,165,18,182],"203":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","211":"b:T+pt+gF+5/FU+v9HomMI8H/+P7L/////AAAAAAA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentPublicationStatus.ts":{"6":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","10":"b:D+Jt+AN+5/FA+v5HoEMIAH5uJbDu/+/fAAAAAAA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentRenderData.ts":{"81":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","110":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","116":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","126":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","132":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","153":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","174":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","225":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","247":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","263":[46,137,147,78,164,170,181,189,191],"275":[46],"291":[46],"295":[46],"299":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","334":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","355":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","358":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","361":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","365":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","369":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","373":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","377":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","381":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","392":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","399":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","402":"b:AgAMAABABBAA+EAAAAEAAAAwAAAgB0CdAAAAAAA=","405":[104,46,140,141,76,77,78,165,18,182],"418":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","428":"b:BuoF+ABuQtFAev9HgGMA8D++PzD2ft+/AAAAAAA=","461":"b:AgAMAABABBAAiEAAAAAAAAAAAAACBwCdAAAAAAA=","473":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","494":[46,147,78,164,181],"495":[46,137,147,78,164,170,181,189,191],"529":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","532":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","535":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","538":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","541":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","560":[46],"563":[46],"566":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","569":"b:DyBEGAFw5WEAsD5EAEAAAHwmJQBC9mscAAAAAAA=","572":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","575":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","578":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","581":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","584":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","587":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","590":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentScopes.ts":{"13":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","18":"b:D+pt+gN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","23":"b:D+pt+gN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentSettings.ts":{"19":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","24":"b:D+Jt+gN+5/FA+v5HoEMIAH5uJbDv/+/fAAAAAAA=","33":"b:D+Jt+gN+5/FA+v5HoEMIAH5uJbDv/+/fAAAAAAA=","37":[46],"41":"b:D+JF+AN65XEA+r5GgEAIAH4mJQDu/v/+AAAAAAA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentSharedWithProjects.ts":{"13":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","18":"b:C6BtAgFU5/BA4nQDIAMIAEhsAbAPn+HdAAAAAAA=","29":"b:C6BtAgFU5/BA4nQDIAMIAEhsAbAPn+HdAAAAAAA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentTags.ts":{"15":"b:C6BtAgFU5/BA4nQDIAMIAFhsGbAPn+P9AAAAAAA=","16":[46,148,86,183,189],"19":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","24":"b:C6BtAgFU5/BA4nQDIAMIAFhsGbAPn+P9AAAAAAA=","29":[46,183],"30":[46],"37":"b:C6BtAgFU5/BA4nQDIAMIAEhsAbAPn+HdAAAAAAA=","41":[46,132,147,148,84,16,177,86,189],"46":[46,183]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentTimestamps.ts":{"19":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","26":"b:C6BtAgFU5/BA4nQDIAMIAEhsAbAPn+HdAAAAAAA=","31":"b:D+Jt+gN+5/FA+v5HoEMIAH5uJbDv/+/fAAAAAAA=","36":"b:C6BtAgFU5/BA4nQDIAMIAEhsAbAPn+HdAAAAAAA=","40":"b:D+Jt+gN+5/FA+v5HoEMIAH5uJbDv/+/fAAAAAAA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentUsedCredentials.ts":{"13":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","18":"b:C6BtAgFU5/BA4nQDIAMIAEhsAbAPn+HdAAAAAAA=","26":"b:C6BtAgFU5/BA4nQDIAMIAEhsAbAPn+HdAAAAAAA=","27":[42,46,53,54,55,134,60,157,73,18,89]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentVersionData.ts":{"14":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","20":"b:D+Jt+gN+5/FA+v5HoEMIAH5uJbDv/+/fAAAAAAA=","32":"b:D+Jt+gN+5/FA+v5HoEMIAH5uJbDv/+/fAAAAAAA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentViewport.ts":{"13":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","18":"b:AgAMAABABBAAiEADAAMAAAAAABACBwDdAAAAAAA=","26":"b:AgAMAABABBAAiEADAAMAAAAAABACBwDdAAAAAAA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentWorkflowObject.ts":{"12":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","26":"b:AAAMAgBABFAAgEAAAAMAAAAAAAADBwCdAAAAAAA=","46":"b:T+pt+gF+5/FU+v9HomMI8H/+P7L/////AAAAAAA=","50":"b:D+pt+gF+5/FQ+v9HomMIUF/+P7Dv////AAAAAAA=","54":"b:D+pt+gN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","58":"b:D+Jt+gN+5/FA+v5HoEMIAH5uJbDv/+/fAAAAAAA=","62":"b:AAAF2ABAAAAAANABAEAAABASOAAkAAMgAAAAAAA=","81":[31,46,162,16,87],"87":[31,46,162,16,87]},"packages/frontend/editor-ui/src/app/stores/workflowDocument.store.ts":{"121":"b:D+Jt+gN+5/FA+v5HoEMIAH5uJbDv/+/fAAAAAAA=","126":[46],"131":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","156":[46,62,169,170,79,18,186,187,188],"165":[46,62,169,170,79,18,186,187,188],"178":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","192":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","193":"b:f+r/+4O/5/92+v/v////////////////AAAAAAA=","203":"b:D+pt+gM+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","217":"b:D+Jt+gM+5/FA+v5HoEMIAH5uJbDv/+/fAAAAAAA=","226":"b:BAIBIAAKQAFAOoJAgAAAUAEgABDkIB8CAAAAAAA=","229":"b:T+pt+gE+5/FU+v9HomMI8H/+P7L/////AAAAAAA=","241":"b:D+pt+gE+5/FQ+v9HomMIUF/+P7Dv////AAAAAAA=","258":"b:DsoFqAESQMEAKk4CgiAIEGDIAQAodBfjAAAAAAA=","259":[1,2,9,11,143,14,18,15],"272":[1,2,9,11,143,14,18,15],"293":"b:BsoF+AAqQJFUet9HgmAA8D+2PxL0fl++AAAAAAA=","294":"b:BsoF+AAqQBFAet9EgGAAUB+yPhDkal8iAAAAAAA=","295":[78],"297":"b:T+pt+gE+5/FU+v9HomMI8H/+P7L/////AAAAAAA=","303":[68],"310":"b:D+JF+AM65HEA+r5GgEAIAH4mJQDm9u/eAAAAAAA=","311":"b:D+JF+AE65HEA+r5EgEAIAH4mJQDm9m+eAAAAAAA=","331":[78],"344":"b:D+pt+gM+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","348":"b:AAAEAgAAAEAAgAAAAAAAAAAAAAABBwCcAAAAAAA=","401":[104,105,19,50,60,161,168,86,184],"443":"b:T+pt+gE+5/FC+v9HgmMI8H/+P7D//3//AAAAAAA=","460":"b:DyBF2AMw5WEAsD5EAEAAAHwmJQDg9ms8AAAAAAA=","542":"b:QAAIAgBABBAAAEAAAAAAAAAAAAAABwCZAAAAAAA=","557":[46,21],"572":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","574":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","583":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","600":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","604":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/stores/workflowExecutionState.store.ts":{"98":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","114":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","115":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","189":[46],"199":[46],"203":[46],"210":"b:DyBEWAFw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA=","219":"b:D+pt+gN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","226":[46],"263":[46],"269":"b:D+pt+gN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","282":"b:DyBMWgFw5WEAsD5EgEMIAHwmJQBH/mucAAAAAAA=","306":"b:T+pt+AN+5/FW+v/HwuMK8H/+P/L/////AAAAAAA=","333":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","340":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","349":"b:DyBMWgFw5WEAsD5EgEAIAHwmJQBC9mucAAAAAAA=","357":"b:DyBEWgFw5WEAsD5EgEAIAHwmJQBC9mucAAAAAAA=","359":"b:DyBEWgFw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA=","371":"b:T+pt+gF+5/FW+v9HguMK8H/+P/Lv/3//AAAAAAA=","388":"b:DupF+ABuQBFAOv9EgGAAUG+uPzDs/n8CAAAAAAA=","394":"b:D+pt+AN+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","404":[46,82,175,84,85],"411":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","418":[46],"432":[46],"444":[46],"457":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","463":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","469":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","476":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","482":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","488":"b:DyBEGAFw5WEAsD5EAEAAAHwmJQBC9mscAAAAAAA=","494":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","503":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","533":"b:D+pt+AF+5/FA+v9HgmAI8H/+P7D//3//AAAAAAA=","541":"b:D+pt+AF+5/FA+v9HgmAI8H/+P7D//3//AAAAAAA=","551":"b:T+pt+gF+5/FU+v9HgmMI8H/+P7L//3//AAAAAAA=","554":"b:T+pt+gF+5/FU+v9HgmMI8H/+P7L//3//AAAAAAA=","557":"b:D+pt+AF+5/FA+v9HgmAI8H/+P7D//3//AAAAAAA=","561":"b:D+pt+AF+5/FA+v9HgmAI8H/+P7D//3//AAAAAAA=","564":"b:AAAMAgBABBAQcEAAAAEAAAAwAAIgB0CZAAAAAAA=","567":[46,140,141,153,68,76,77,78,165,18,182],"574":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","588":"b:T+pt+gF+5/FU+v9HomMI8H/+P7L+////AAAAAAA=","624":"b:D+pt+gN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","636":[46],"639":[46],"644":[46],"645":[46],"650":[46],"654":"b:DyBMWAFw5WEAsD5EgEMIAHwmJQBD9mucAAAAAAA=","683":"b:DyBEGgFw5WEAsD5EAEAAAHwmJQBA9mscAAAAAAA=","692":"b:D+pF+AN+5fFA+v/HwmAI8H/+P7D+////AAAAAAA=","698":[46],"709":[46],"728":"b:DyBEWAFw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA=","745":"b:D+pF+AN+5fFA+v/HwmAI8H/+P7D+////AAAAAAA=","768":"b:AgAEAABAAAAAeAAAAAAAAAAwAAAkEkAeAAAAAAA=","775":"b:DgAEAAFQQAEAAAAAgAAIAAAAAQACBAIAAAAAAAA=","780":[46,169],"785":"b:D+oF+AN+4PFA+v/HwmAI8H/+P7D+////AAAAAAA=","798":"b:C6AFAAFU4PBA4nQDAAAIAEhsAbAMn2HdAAAAAAA=","820":[46],"829":"b:D+oF+AN+4PFA+v/HwmAI8H/+P7D+////AAAAAAA=","838":[46],"842":[46],"847":[46,97,89,191],"852":[46,97,89,191],"856":[46],"858":[46],"864":[46],"866":[46],"867":[46],"876":[46],"881":[46],"886":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","899":[46,162,16,87],"912":[46],"918":[46],"924":[46],"937":[46,162,16,87],"962":"b:D+pt+AN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","997":[46,170,18],"1126":"b:D+pt+gN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","1149":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","1153":"b:T+pt+gM+5/FW+v/HwuMK8H/+P/L/////AAAAAAA="},"packages/frontend/editor-ui/src/app/stores/workflowSave.store.ts":{"15":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","26":"b:BsoF+AJqQJFAev9HgGAA8D+2PxD0ft/+AAAAAAA=","30":"b:BsIF+AJqQBEAer5GgEAAADYGJQDkds/eAAAAAAA=","34":[46],"39":[46],"43":[46],"47":[46],"51":[46],"55":"b:AoAIgABABAEAaiYAAAAAAAAEAQDAMkseAAAAAAA=","63":[46,19,50]},"packages/frontend/editor-ui/src/app/stores/workflows.store.ts":{"42":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","59":"b:D+pt+AN+5/FA+v/H4mAI8H/+P7D+////AAAAAAA=","69":"b:D+pt+AN+5/FA+v/H4mAI8H/+P7D+////AAAAAAA=","70":"b:D+Jt+AN+5/FA+v5HoEAIAH5uJbDu/+/fAAAAAAA=","79":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","84":"b:DuoFeABuQBFAOv9EgGAAUG+uPzDk/n8CAAAAAAA=","88":"b:DuoFeABuQBFAOv9EgGAAUG+uPzDk/n8CAAAAAAA=","98":[46,97,89,191],"99":[46],"119":[46,189],"126":"b:D+pt+AN+5/FA+v/H4mAI8H/+P7D+////AAAAAAA=","156":[46],"164":"b:D+pt+AN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","168":"b:D+pt+AN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","179":"b:C6BtAAFU5/BA4nQDIAAIAEhsAbAOn+HdAAAAAAA=","186":[46,190],"202":[46,184,190],"217":[46,134,75,184,185],"229":[46,190],"233":[46],"251":[46,62,169,170,79,18,186,187,188],"265":"b:BsIF+AJqQFEAer5GgEAAALYGJQDkds/eAAAAAAA=","266":"b:BsIF+ABqQFEAer5GgEAAADYGJQDkdk+eAAAAAAA=","274":"b:BsIF+AJqQBEAOJpGgEAAADYCJADkZs/KAAAAAAA=","302":"b:AoAAkABAAEEAaiYAAAAAAIAEAQDAMsseAAAAAAA=","345":[46,134,75,182,184,185],"359":"b:D+Jt+AN+5/FA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","367":[46,190],"394":[46],"446":"b:DyBEWAFw5GEAsD5EgEAIAHwmJQBC9mucAAAAAAA=","465":[46],"473":"b:DyBEGAFw5WEAsD5EAEAAAHwmJQBC9mscAAAAAAA=","485":[46]},"packages/frontend/editor-ui/src/app/stores/workflowsList.store.ts":{"27":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","39":[46,182,87],"40":[46,182,87],"45":"b:D+pt+AN+5/FA+v/H4mAI8n/+P7D+////AAAAAAA=","50":[46],"51":[46],"59":"b:D+Jt+IP+5/9A+v5PoFMIAv5vJbDu/+/fAAAAAAA=","69":[46,184,190],"74":"b:D+pt+AN+5/FA+v/H4GMI8H/+P7D/////AAAAAAA=","83":[46],"87":[46],"94":[46],"99":[46,134,75,184,185],"112":[46,190],"126":"b:AAAAAIDBAB4gAMAJGBAEAoABABAAAUDBAAAAAAA=","154":"b:AAAAAIDAAB4AAMAJABAAAoABAAAAAUDAAAAAAAA=","155":"b:AAAAAIDAAB4AAMAJABAAAoABAAAAAUDAAAAAAAA=","166":"b:AAAAAIDBAB4gAMAJGBAEAoABABAAAUDBAAAAAAA=","187":[46,19,48,21,49,22,50,121,62,75,187],"221":[46,19,48,21,49,22,50,121,62,75,187],"234":[46],"242":"b:C6BtAAFU5/hA6vQDIAAIAkhsAbAMn+HdAAAAAAA=","248":[46,150,151],"252":"b:D+pt+IP/5/9g+v/P+nAM8v//P7D8////AAAAAAA=","258":"b:BsoF+AJ6QBFAON/EwGAA8D+SPhD0Zp9rAAAAAAA=","264":[46,184,190],"270":[46,190],"291":[46,184,190]},"packages/frontend/editor-ui/src/app/upgradeRedirectGuard.manifest.ts":{"11":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","12":[46],"13":[46]},"packages/frontend/editor-ui/src/app/utils/aiUtils.ts":{"23":[46],"29":[46],"42":[46],"57":[1,46,18],"82":[46,18],"87":[46,18],"110":[46],"118":[46],"132":[46],"182":[46],"193":[46],"204":[46],"215":[46],"236":[25,1,46,18],"245":[25,46],"248":[1,46,18],"257":[46],"263":[1,46,18],"264":[1,46,18],"274":[25,32,1,2,3,46,48,22,50,144,161,18,188],"286":[46,18],"300":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D+/3//AAAAAAA="},"packages/frontend/editor-ui/src/app/utils/credentialOnlyNodes.ts":{"16":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","51":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA="},"packages/frontend/editor-ui/src/app/utils/expressions.ts":{"19":[46],"28":[46],"30":[46],"31":[46],"46":[46],"65":[46],"86":[46],"110":[46],"128":[46],"132":[46,82,173],"136":[46,65],"137":[46,65],"145":"b:BsoECABAAAAAECMAAAAAAACCAQAAIA0AAAAAAAA=","149":"b:BsoACABAAAAAEAMAAAAAAACAAQAAAAwAAAAAAAA=","153":"b:BsoACABAAAAAEAsAAAAAAACAAQCAYAwAAAAAAAA=","159":[27,46,80,178,179],"163":"b:AAABCABAAAACAC8AAAAAAAAAAACAQA4AAAAAAAA=","167":[27,46,80,178,179],"171":[27,46,80,178,179],"175":[27,46,80,178,179],"179":[27,46,80,178,179],"183":"b:BsoFCABAAAACEC8AAAAAAECCAQCAZA8AAAAAAAA=","198":[27,1,46,80,81,173,15,85,178,179],"247":"b:BsoFCABAAAACEC8AAAAAAECKIQAAZA8AAAAAAAA=","271":"b:RkIBUABqQBFCMo9GgOAAAA6kEELkYk8AAAAAAAA=","281":"b:RgIBQABqQBFCMo1GgKAAAAygEELkQg8AAAAAAAA="},"packages/frontend/editor-ui/src/app/utils/formatters/dateFormatter.ts":{"4":"b:CABEGABAQEEAADwEgEAAAGwEIABA1msQAAAAAAA=","15":[25,46,62,169,170,79,18,186,187,188],"27":[32,1,2,3,46,48,22,50,144,161,18],"29":[32,1,2,3,46,48,22,50,144,161,18],"32":[46,69],"35":[46,69]},"packages/frontend/editor-ui/src/app/utils/injectStrict.ts":{"4":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/utils/mappingUtils.ts":{"11":"b:CiBFGgFAQEEAID4EgEIAAGwGLQDI/nsQAAAAAAA=","15":"b:CiBFGgFAQEEAID4EgEIAAGwGLQDI/nsQAAAAAAA=","16":"b:CiBFGgFAQEEAID4EgEIAAGwGLQDI/nsQAAAAAAA=","29":"b:CiBFAAFAQEEAID8EgEIAAGwGIQDI9msQAAAAAAA=","33":"b:CiBEAAFAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA=","53":"b:CiBFAAFAQEEAID4EgEIAAGwGIQDI/nsQAAAAAAA=","70":[46],"82":[46,82],"96":[46,82]},"packages/frontend/editor-ui/src/app/utils/nodeIcon.ts":{"39":[46],"81":"b:T+pt+gF+5/FC+v9HgGMI8H/+P/Dv/3//AAAAAAA=","95":"b:T+pt+gF+5/FC+v9HgmMI8H/+P/Dv/3//AAAAAAA=","99":[46],"105":"b:T+pt+gF+5/FC+v9HgGMI8H/+P/Dv/3//AAAAAAA=","113":"b:RuoFqABKghBAOj5GAgAA8G2uCDDkfDeiAAAAAAA=","118":"b:T+pt+gF+5/FC+v9HgmMI8H/+P/Dv/3//AAAAAAA=","125":"b:RuoFqABKghBAOj5GAgAA8G2uCDDkfDeiAAAAAAA=","131":"b:T+pt+gF+5/FC+v9HgGMI8H/+P/Dv/3//AAAAAAA=","138":[46,191],"152":"b:T+pt+gF+5/FC+v9HgmMI8H/+P/Dv/3//AAAAAAA=","214":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA="},"packages/frontend/editor-ui/src/app/utils/nodeTypes/nodeTypeTransforms.ts":{"8":"b:f+pv+gN+5/lC+v/H4uMJ8H/+f/D/////AAAAAAA=","29":"b:f+pv+gN+5/lC+v/H4uMJ8H/+f/D/////AAAAAAA=","32":"b:f+pv+gN+5/lC+v/H4uMJ8H/+f/D/////AAAAAAA="},"packages/frontend/editor-ui/src/app/utils/nodeTypesUtils.ts":{"44":"b:BsoBoABqAhBCCCACAKACUAeKAECEABcCAAAAAAA=","47":"b:BsoBoABqAhBCCCACAKACUAeKAECEABcCAAAAAAA=","55":"b:TuoF4AF+5tFAGiEGgmMIUEfOCzCmHjfiAAAAAAA=","59":[46,97,16,178,89],"62":[46,97,16,178,89],"66":[41,109,46,56,172,176,177,191],"78":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","112":[103,46,115,124,53,54,132,56,176,191],"123":[103,46,115,124,53,54,132,56,176,191],"135":"b:D+pt+AN+5/FA+v/H4mAI8H/+P7D8////AAAAAAA=","136":"b:D+pt+AF+5/FA+v9HgmAI8H/+P7Ds/3//AAAAAAA=","141":[46,89,191],"142":[46,89,191],"143":[46,89,191],"147":[46,89,191],"150":"b:AEABAABAAAACAI8AAAAAAAAAAAAAYA4AAAAAAAA=","151":"b:AEABAABAAAACAA8AAAAAAAAAAAAAYA4AAAAAAAA=","154":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","174":"b:DupF+gFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","175":"b:CiBFGgFAQEEAID4EgEIAAGwGJQDI/msQAAAAAAA=","183":"b:BoIFIABIAhBACIAAAAAAUACAADAAAEUCAAAAAAA=","195":"b:RsoFIABKQBFACCAAACAAUAeKADCEABciAAAAAAA=","215":"b:TupF+ABKQlFUOv5EgCAAUG+uNzLs/H8yAAAAAAA=","222":"b:AAIBoABKQhFAACAAACAAUAAIADAAABcCAAAAAAA=","225":"b:AAIBoABKQhFAACAAACAAQAAIADAAABcCAAAAAAA=","242":"b:TupFuABCQFEAOv5AgCAAUG+uNwDs/H8yAAAAAAA=","247":"b:RsoFgABCQAEACAAAACAAEAeCAACEAAAgAAAAAAA=","251":[41,109,9,46,124,54,56],"256":[41,109,9,46,124,54,56],"266":[41,109,46,124,54,56],"283":"b:BgIBOABoABBCAAACAIACAAKAAFAAAAQAAAAAAAA=","297":[29,43,9,46,156,70,16,178],"301":[29,43,9,46,156,70,16,178],"304":[29,43,9,46,156,70,16,178],"331":[29,43,9,46,156,70,16,178],"332":[29,43,9,46,156,70,16,178],"336":"b:AAIBIABKABBAACAAAAAAUAAIADAAABcCAAAAAAA=","342":"b:AAIBIABKABBAACAAAAAAUAAIADAAABcCAAAAAAA=","351":[29,43,9,46,156,70,16,178],"358":[29,43,9,46,156,70,16,178],"364":[29,1,2,43,9,46,129,143,156,70,16,178],"373":[29,43,9,46,156,70,16,178],"381":"b:AAIBoABKAhBAACAAAAAAUAAIADAAABcCAAAAAAA=","386":"b:AAIBoABKAhBAACAAAAAAUAAIADAAABcCAAAAAAA=","398":"b:TupFuABKQlFAOv5AgCAAUG+uNzDs/H8yAAAAAAA=","404":"b:RsoFoABKQhFACCAAACAAUAeKADCEABciAAAAAAA=","406":"b:AAIBoABKQhFAACAAACAAUAAIADAAABcCAAAAAAA=","407":"b:AAIBoABKQhFAACAAACAAUAAIADAAABcCAAAAAAA=","409":"b:AAIBoABKQhFAACAAACAAUAAIADAAABcCAAAAAAA=","425":"b:AAIBoABKQhFAACAAACAAUAAIADAAABcCAAAAAAA=","448":[43,9,46,156,70,16,178],"474":"b:AAIBoABKAhBAACAAAAAAUAAIADAAABcCAAAAAAA=","483":[46],"484":[46],"496":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","503":[46,179],"516":[46,179],"525":[46,179],"559":[46],"560":[46],"563":[46,179],"579":"b:RgIFgABo4AFAAAACAAAAAECAABAAAASAAAAAAAA=","592":[9,45,46],"597":[9,45,46],"620":[31,1,2,43,6,9,45,46,56,143,156,70,16,178],"641":[31,1,2,43,6,9,45,46,56,143,156,70,16],"646":"b:f+pt+gF+5/lC+v9HguML8H/+P/Dv/3//AAAAAAA="},"packages/frontend/editor-ui/src/app/utils/nodeViewUtils.ts":{"67":[104,105,46,97,161,89,191],"68":[104,105,46,97,161,89,191],"77":"b:AAAFWABAAAAAAFABAEAAABASOAAkAAMgAAAAAAA=","78":"b:AAAFWABAAAAAAFABAEAAABASOAAkAAMgAAAAAAA=","87":"b:AAAFWABAAAAAAFABAEAAABASOAAkAAMgAAAAAAA=","88":"b:AAAFWABAAAAAAFABAEAAABASOAAkAAMgAAAAAAA=","97":"b:AAAFWABAAAAAAFABAEAAABASOAAkAAMgAAAAAAA=","98":"b:AAAFWABAAAAAAFABAEAAABASOAAkAAMgAAAAAAA=","107":"b:AAAFWABAAAAAAFABAEAAABASOAAkAAMgAAAAAAA=","108":"b:AAAFWABAAAAAAFABAEAAABASOAAkAAMgAAAAAAA=","117":"b:AAAFWABAAAAAAFABAEAAABASOAAkAAMgAAAAAAA=","134":"b:BsoBIABqQJFAOs9FgAAAQAagDhDkah8CAAAAAAA=","151":[46,146,147,76],"166":"b:T+pt+gF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","185":"b:T+pt+gF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","192":[31,46,145,160],"199":"b:BsoF+ABqQJFAOt9HgmAA8D+yPhD0bl+qAAAAAAA=","264":"b:D+hFWAFGQFEAcj4HgEIA4EguMyD8vmsfAAAAAAA=","274":[46,164],"286":[46,164],"305":[46,164],"314":[104,105,46,97,161,89,191],"325":[104,105,46,97,161,89,191],"395":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","537":[46],"563":"b:AoIl2ADKABZC+FADEEAAEBGTPGU2r8P/AAAAAAA=","580":"b:BsoFeAFqQJFAOt9FgGAA8D+yPhD0bh8qAAAAAAA=","592":[32,46,18],"601":[32,46,18],"607":[32,46,18],"643":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA="},"packages/frontend/editor-ui/src/app/utils/nodes/nodeTransforms.ts":{"40":"b:BsoFeABqQJFAOt9HgmAA8D+yPhD0bl+qAAAAAAA=","49":"b:B+pt+AB+5XFA+v9HgmAI8H+6PrD893//AAAAAAA=","74":"b:BuoF4AB+5FFAGiEGgmAIUEeKCjCkFhfiAAAAAAA=","84":[46,89,191],"98":"b:BuoFoABK4BFACiACAiAAUEeKCDCEABeiAAAAAAA=","112":"b:B+pt+AB+5XFA+v9HgmAI8H+6PrD893//AAAAAAA=","118":"b:BuoFoABK4BFACiACAiAAUEeKCDCEABeiAAAAAAA=","129":"b:CSBAGABAAAEAED4AAEAAACQEAQBAdAsAAAAAAAA=","143":"b:TupF+ABuQFFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","165":"b:DupFeABuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","189":"b:D+JF+AF65HEA+r5HgEAIAH4mJQDm9m+eAAAAAAA=","266":[1,2,46,53,54,55,134,56,18],"269":[1,2,46,53,54,55,134,56,18]},"packages/frontend/editor-ui/src/app/utils/objectUtils.ts":{"3":"b:T+pt+gN+5/FA+v/H4mMI8H/+P7D+////AAAAAAA=","7":"b:T+pt+gN+5/FU+v/H4mMI8H/+P7L+////AAAAAAA=","11":"b:T+pt+gN+5/FU+v/H4mMI8H/+P7L+////AAAAAAA=","15":[46,21,78],"16":[46,78],"19":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","23":[46,175,84],"24":[46,175,84],"36":[27,28,29,30,46],"62":[46],"66":[46]},"packages/frontend/editor-ui/src/app/utils/pairedItemUtils.ts":{"19":"b:DyBEGgFw5WEAsD5EgEIAAHwmJQDE/mscAAAAAAA=","23":[46,82,85],"48":[46,82,85],"58":[46,82,85],"61":"b:DyBEGgFw5WEAsD5EAEAAAHwmJQBE/mscAAAAAAA=","89":"b:CyBEAgFgpWAAoD5AAEAAABwGJQBE/mscAAAAAAA=","95":"b:DyBEGgFw5WEAsD5EAEAAAHwmJQBE/mscAAAAAAA=","124":"b:CyBEAgFg5WAAoD5EAEAAAFwGJQBE/mscAAAAAAA=","138":"b:DyBEGgFw5WEAsD5EAEAAAHwmJQBE/mscAAAAAAA=","143":"b:DyBEGgFw5WEAsD5EAEAAAHwmJQBE/mscAAAAAAA=","152":[46,55],"168":"b:DyBEWgFw5WEAsD5EgEAIAHwmJQBG/mucAAAAAAA=","171":"b:DyBEGgFw5WEAsD5EAEAAAHwmJQBE/mscAAAAAAA=","172":"b:DyBEGgFw5WEAsD5EAEAAAHwmJQBE/mscAAAAAAA=","173":"b:DyBEGgFw5WEAsD5EAEAAAHwmJQBE/mscAAAAAAA=","188":"b:DyBEWgFw5WEAsD5EgEAIAHwmJQBG/mucAAAAAAA=","197":"b:DyBEGgFw5WEAsD5EAEAAAHwmJQBE/mscAAAAAAA=","209":"b:DyBEWgFw5WEAsD5EgEAIAHwmJQBG/mucAAAAAAA=","229":"b:DyBEGgFw5WEAsD5EAEAAAHwmJQBE/mscAAAAAAA=","230":"b:DyBEGgFw5WEAsD5EAEAAAHwmJQBE/mscAAAAAAA="},"packages/frontend/editor-ui/src/app/utils/parameterUtils.ts":{"13":"b:RsIBUABqQBFCMo9GgOAAAA6kEFDkck8AAAAAAAA=","31":[46]},"packages/frontend/editor-ui/src/app/utils/rbac/checks/hasScope.ts":{"4":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/utils/rbac/checks/isAuthenticated.ts":{"5":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","14":"b:f+r/+4P/5/92+v/v//v/////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/utils/rbac/checks/isValid.ts":{"3":"b:f+r/+4P/5/92+v/v+/j////////8////AAAAAAA="},"packages/frontend/editor-ui/src/app/utils/rbac/middleware/authenticated.ts":{"7":"b:f+r/+4P/5/92+v/v//v/////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/utils/rbac/permissions.ts":{"28":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/utils/timeAgoLocale.ts":{"5":"b:AAIAAIDoAB5CAEALABAGAoABAEAAAQDAAAAAAAA=","25":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/utils/typeGuards.ts":{"31":[46],"35":[46,82,85],"39":[46,178,89],"43":"b:CCBFmgBAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","46":[46],"49":"b:QCIFoABKQhFACLYAgAAAUAMKADCEJH8CAAAAAAA=","57":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","61":[46,179],"65":[46,65],"71":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","77":"b:D+pt+AF+5/FA+v9HgmMI8H/+PzD//3++AAAAAAA=","81":"b:BsgBAABCAAAAEAAAAAAA4AAADgAACAgAAAAAAAA=","90":[103,41,109,46,54,56,170,172,176,177],"96":[46,169,179],"102":[46],"109":[46,62,169,170,79,18,186,187,188],"113":[9,46,59,152,158,70],"117":[9,46,59,152,158,70],"121":[46,152],"125":[43,9,45,46,59,60,152,65,158,70],"129":[46],"135":[9,46,59,152,158,70],"142":"b:AAIAAIDoAB5CAEAJABAEAoABAEEAAQDAAAAAAAA=","155":[17,46,58,60],"167":"b:BgAE2AJgQAEAOH5EgEAAADQGJQBAdkuMAAAAAAA="},"packages/frontend/editor-ui/src/app/utils/typesUtils.ts":{"12":[46],"14":"b:CiBFGgFAQEEAID4EgEIAAGwGJQDo/muwAAAAAAA=","23":"b:TupF+oP/Rl12uv/P2vMC8n++P3L//v//AAAAAAA=","40":[46,89,191],"59":[46],"63":"b:AAABAABAAAAAAD4AAAAAAAACAACgYgMgAAAAAAA=","69":[46,177],"74":"b:CiBFGgFAQEEAID4EgEIAAGwGLQDI/nsQAAAAAAA=","85":[46],"91":[46],"92":[46],"102":[46],"122":[46,167,81,82,173,83,174,85,177],"127":[46,167,81,82,173,83,174,85,177],"169":[46,97,89,191],"173":"b:Tupt+AFuR9tWev9HgOIC8v+/P3L8/39+AAAAAAA=","177":"b:BkIBQADoQBFCAC8GgOAAAAyEAEIIYg8AAAAAAAA=","186":[46],"195":[46],"204":"b:RkIBQABoQBFCAC8GgOAAQA6EAEJIYg8AAAAAAAA="},"packages/frontend/editor-ui/src/app/utils/urlUtils.ts":{"2":"b:f+r/+4P/5/92+v/v//v/////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/utils/workflowUtils.ts":{"11":"b:C6BtAAFU5/BA4nQDIAMIAEhsAbAOn+HdAAAAAAA=","15":[46,183],"26":[46,160],"36":[46,160],"49":"b:C6BtWgFU5/BA4nQDAEMIAFh+OaAun2P9AAAAAAA=","60":"b:C6BtWgFU5/AA4nQDAEMIAFh+OSAun2O8AAAAAAA=","80":"b:C6BtWgFU5/BA4nQDIEMIAFh+ObAun+P9AAAAAAA=","100":"b:C6BtWgFU5/AA4nQDAEMIAFh+OSAun2O8AAAAAAA=","103":"b:C6BtWgFU5/AA4nQDAEMIAFh+OSAun2O8AAAAAAA=","138":[31,46],"145":[31,46],"146":[31,46],"158":[31,46],"167":[31,46]},"packages/frontend/editor-ui/src/app/views/LoadingView.vue":{"6":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/app/views/NodeView.vue":{"169":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","173":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","177":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","178":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","196":"b:AsIBoAAKQBEAeoICAAAAAAIAAADkIodaAAAAAAA=","208":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","301":"b:D+pt+AM+5/FA+v9HgGII8H/+P7D+////AAAAAAA=","312":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","316":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","318":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","319":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","320":"b:BsoFKAAqQJFAOs9FgCAA8C+gDhD0fh8eAAAAAAA=","321":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","332":"b:C6Jt+AA+5fFA+v9HgmAI8H8+PrDs/3//AAAAAAA=","336":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","348":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","352":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","368":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","370":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","374":[32,1,2,3,9,11,63,142,143,144,14,161,18,15],"380":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","425":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","430":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","440":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","444":"b:D+pt+AE+5/FA+v9HgmMI8H/+P7Du/3//AAAAAAA=","445":"b:D+pt+AE+5/FA+v9HgmMI8H/+P7Du/3//AAAAAAA=","448":"b:BsoF+AAqQJFAON9EgGMA8D+SPhDmdh+qAAAAAAA=","486":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","488":"b:D+pt+AE+5/FA+v9HgmMI8H/+P7D+/3//AAAAAAA=","494":"b:C6Jt+AA+5fFA+v9HgmAI8H8+PrDs/3//AAAAAAA=","496":"b:C6Jt+AA+5fFA+v9HgmAI8H8+PrDs/3//AAAAAAA=","497":"b:C6Jt+AA+5fFA+v9HgmAI8H8+PrDs/3//AAAAAAA=","501":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","502":"b:D+pt+AE+5/FA+v9HgmMI8H/+P7Du/3//AAAAAAA=","505":[31,145],"516":[182],"520":[144,76,77,78,165,88],"528":[165],"532":[140,141,76,18],"541":[76,77,78,165],"545":[165,182],"561":[75,76,18],"569":[165],"573":[1,162,165,169,172,185,186,187,188],"581":"b:DKBFWAAEQFEAcj4HgEIAAEguMSDsvmMfAAAAAAA=","586":"b:DKBFWAAEQFAAAj4EgEIAAEguMSDEvmMQAAAAAAA=","608":"b:D+pFeAEuQNFAev9HgGIA8H++PzD8/n8/AAAAAAA=","617":[76,162,165,88,189,89],"621":[76,88,89],"623":[76,88,89],"636":[162,165,88,184],"681":[162,165,88],"690":[162,165,88],"706":[162,165,177],"730":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","734":"b:AgAMAAAABBAAiEADAAAAAAAAABAABwDdAAAAAAA=","753":[162],"775":[162],"794":[162],"821":[182],"837":[1,182,191],"841":[109,56,182,191],"845":[1,2,41,11,125,126,127,145,14,76,171,179],"885":[78,182],"889":[165,182],"893":[1,2,41,11,125,126,127,145,14,76,171,179],"921":[76,78,165],"925":[165,182],"933":"b:AAAFWAAAAAAAAFAAAEAAABASOAAAAAMgAAAAAAA=","948":"b:AAAFWAAAAAAAAFAAAEAAABASOAAAAAMgAAAAAAA=","964":[189],"971":[189],"980":[189],"986":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","992":"b:AgAMAAAABBAAiEADAAAAAAAAABAABwDdAAAAAAA=","1004":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","1008":"b:BsoBKAAqQJFAOs9EgCAA8C+gDhD0bh8KAAAAAAA=","1025":"b:BsoBKAAqQJFAOs9EgCAA8C+gDhD0bh8KAAAAAAA=","1127":[165,182],"1131":[166,167,15,179],"1139":[15],"1152":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","1165":[187],"1178":"b:D+pFeAEuQNFAev9HgGIA8H++PzD8/n8/AAAAAAA=","1184":[164],"1188":[146,147,76],"1253":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D8////AAAAAAA=","1259":"b:BsoF+AI6QBFAON/HwmAA8D+SPhD0Zp/rAAAAAAA=","1261":[31,43,44,9,60,156,178,86,87,190],"1272":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","1273":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D+////AAAAAAA=","1282":[191],"1291":"b:C6Jt+AA+5fFA+v9HgmAI8H8+PrDs/3//AAAAAAA=","1309":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D+////AAAAAAA=","1312":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D+////AAAAAAA=","1315":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D+////AAAAAAA=","1319":[0,3,22,13,144,76,170,172,81,173],"1389":[0,3,22,13,144,76,170,172,81,173],"1445":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","1450":"b:AgAMAAAABBAAiEADAAAAAAAAABAABwDdAAAAAAA=","1455":[170,18],"1465":"b:AgBEQAAw5GEAoDBEgEAIAFgiJAAAlmMcAAAAAAA=","1469":"b:AABEQAAw5GEAoDBEgEAIAFgiJAAAlmMcAAAAAAA=","1477":"b:Dsol+AM6QJFAON/EwGAA8D/SPxD2dp9rAAAAAAA=","1478":"b:DsokAAEAAIAAEAAAAAAAAADACQA2EAEAAAAAAAA=","1483":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D+////AAAAAAA=","1486":"b:D+pt+AE+5fFA+v9HgmAI8H/+P7D+/3//AAAAAAA=","1494":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D+////AAAAAAA=","1495":"b:D+pt+AE+5fFA+v9HgmAI8H/+P7Du/3//AAAAAAA=","1498":"b:Dsol+AM6QJFAON/EwGAA8D/SPxD2dp9rAAAAAAA=","1504":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","1520":[1,161],"1528":[1],"1607":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","1621":"b:AgAMAAAABBAAiEADAAAAAAAAABAABwDdAAAAAAA=","1659":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","1663":"b:AgAMAAAABBAAiEADAAAAAAAAABAABwDdAAAAAAA=","1670":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","1674":"b:AgAMAAAABBAAiEADAAAAAAAAABAABwDdAAAAAAA=","1682":"b:BsoFKAAqQJFAOs9FgCAA8C+gDhD0fh8eAAAAAAA=","1725":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","1743":[169],"1759":"b:BsoFeAAqQJFAOt9FgGAA8D+yPhD0bh8qAAAAAAA=","1763":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","1769":"b:BsoFeAAqQJFAOt9EgGAA8D+yPhD0bh8qAAAAAAA=","1770":"b:BsoFeAAqQJFAOt9EgGAA8D+yPhD0bh8qAAAAAAA=","1777":"b:CQAEAAECAAEAUBAAAAAAAAAAAQAcAEEAAAAAAAA=","1782":"b:CQAEAAECAAEAUBAAAAAAAAAAAQAcAEEAAAAAAAA=","1790":[76],"1812":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","1822":[16],"1852":"b:AgAMAAAABBAAiEADAAAAAAAAABAABwDdAAAAAAA=","1858":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","1872":"b:DuoFeAAuQBFAOv9EgGAAUG+uPzDk/n8CAAAAAAA=","1890":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","1895":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","1900":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","1912":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","1918":"b:BsoF+AI6QBFAON/EwGAA8D+SPhD0Zp9rAAAAAAA=","1950":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","1952":"b:DuoFeAAuQBFAOv9EgGAAUG+uPzDk/n8KAAAAAAA=","1961":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","1963":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","1981":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","1982":"b:BsoF+AAqQJFAev9HgGAA8D+2PxD0ft9+AAAAAAA=","2000":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","2001":[31,33],"2013":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","2025":"b:CSBEGAAABQEAED4AAEAAACQEAABAdAsAAAAAAAA=","2026":"b:CSBEGAAABQEAED4AAEAAACQEAABAdAsAAAAAAAA=","2031":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","2040":"b:CyJFuAA65XFA+v9FgEAAQH42LhDk/n+fAAAAAAA=","2050":"b:CyJFuAA65XFA+v9FgEAAQH42LhDk/n+fAAAAAAA=","2051":"b:CyJFuAA65XFA+v9FgEAAQH42LhDk/n+fAAAAAAA=","2062":"b:AgAEAAAAABAAiEAAAAAAAAAAAAAABwCdAAAAAAA=","2111":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","2113":[62,183,184],"2130":"b:D+pt+AM+5/FA+v9HgGII8H/+P7D+////AAAAAAA=","2151":"b:AgAMAAAABBAAiEADAAAAAAAAABAABwDdAAAAAAA=","2233":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","2269":"b:AgBEQAAw5GEAoDBEgEAIAFgiJAAAlmMcAAAAAAA=","2284":[32,1,2,3,9,11,63,142,143,144,14,161,18,15]},"packages/frontend/editor-ui/src/app/workers/isDataWorkerEnabled.ts":{"10":"b:f+r/+4P/5/92+v/v//v/////////////AAAAAAA="},"packages/frontend/editor-ui/src/experiments/aiTemplatesStarterCollection/stores/aiTemplatesStarterCollection.store.ts":{"20":"b:D+pt+IO/5/9g+v/P+nMM8v//P7D/////AAAAAAA=","33":"b:AAAAAICAAB4AAEAJABAEAoABABAAAQDAAAAAAAA="},"packages/frontend/editor-ui/src/experiments/credentialDescriptions/useCredentialDescriptionsExperiment.ts":{"6":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","8":"b:BgIBIABoABhCAAACAIACAAKAAEAAAAQAAAAAAAA="},"packages/frontend/editor-ui/src/experiments/evaluationsWizardSidepanel/useEvaluationsWizardSidepanelExperiment.ts":{"7":"b:D+pt+AM+5/FA+v/H4mMI8H/+P7D+////AAAAAAA=","13":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA="},"packages/frontend/editor-ui/src/experiments/inlineAgents/useInlineAgentsExperiment.ts":{"7":[46],"10":[46],"24":"b:BsoBKABqQJFAOt9EgCAA8C+gDhD0bh8KAAAAAAA="},"packages/frontend/editor-ui/src/experiments/instanceAiComputerUse/useInstanceAiComputerUseExperiment.ts":{"6":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","9":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/experiments/instanceAiSetupPanel/useInstanceAiSetupPanelExperiment.ts":{"6":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","8":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","13":[46,49]},"packages/frontend/editor-ui/src/experiments/readyToRunWorkflows/stores/readyToRunWorkflows.store.ts":{"21":"b:D+pt+IO/5/9g+v/P+nMM8v//P7D/////AAAAAAA=","30":"b:AAAAAICAAB4AAEAJABAEAoABABAAAQDBAAAAAAA=","38":"b:AAAAAICAAB4AAEAJABAEAoABABAAAQDBAAAAAAA=","44":"b:AAAAAICAAB4AAEAJABAEAoABABAAAQDBAAAAAAA="},"packages/frontend/editor-ui/src/experiments/readyToRunWorkflowsV2/stores/readyToRunWorkflowsV2.store.ts":{"12":"b:D+r/+4O/5/9i+v/P+3j89///P/H+////AAAAAAA="},"packages/frontend/editor-ui/src/experiments/resourceCenter/stores/resourceCenter.store.ts":{"19":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","32":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","114":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA="},"packages/frontend/editor-ui/src/experiments/sidebarExpanded/useSidebarExpandedExperiment.ts":{"6":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","10":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA="},"packages/frontend/editor-ui/src/experiments/surfaceAssistantOnWorkflowError/components/WorkflowErrorNudge.vue":{"27":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","32":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","47":[46],"60":[46],"65":[46],"89":[46],"95":[46],"99":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","105":[46],"109":[46],"115":[46],"116":[46],"117":[46],"127":[46],"132":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","137":[46],"148":[46],"152":[46],"155":[46],"161":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","168":[46],"172":[46],"177":[46],"194":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","206":[46],"212":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","248":[46]},"packages/frontend/editor-ui/src/experiments/surfaceAssistantOnWorkflowError/composables/useSurfaceAssistantOnWorkflowError.ts":{"31":"b:DyBEGAFw5WEAsD5EAEAAAHwmJQBC9mscAAAAAAA=","37":"b:DyBEGAFw5WEAsD5EAEAAAHwmJQBC9mscAAAAAAA=","42":[27,28,46,169,186,187],"56":"b:BgAEGABAAEAAgAAAAAAAAAAgAAAAFgEcAAAAAAA=","61":[46],"71":"b:BgAEGABAAAAAAAAAAAAAAAAgAAAAFgEMAAAAAAA=","103":[46]},"packages/frontend/editor-ui/src/experiments/trialIntroModal/stores/trialIntroModal.store.ts":{"22":[46],"36":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","45":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","47":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","51":[46],"60":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","63":"b:AAAAAIDBAB4gAEAJGBAEAoABABAAAQDBAAAAAAA=","72":[46],"74":[46],"76":[46],"89":[46],"101":[46],"112":[46],"116":[46],"128":[46],"142":[46],"158":[46]},"packages/frontend/editor-ui/src/experiments/trialIntroModal/useTrialIntroModalAutoOpen.ts":{"6":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","12":[46],"17":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","24":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/experiments/utils.ts":{"26":[46],"46":"b:BsoF+AJ6QBFAON/EwGAA8D+SPhD0Zp9rAAAAAAA=","53":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","60":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","91":[46]},"packages/frontend/editor-ui/src/features/agents/agentNodeCanvasGeometry.store.ts":{"10":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","17":[46],"26":[46],"30":[46],"41":[46],"50":[46],"54":[46],"63":[46],"71":"b:AgAMAABABBAAiEAAAAAAAAAAAAAABwCdAAAAAAA="},"packages/frontend/editor-ui/src/features/agents/agentReturnContext.store.ts":{"27":"b:D+r9+wN+5/FA+v/HwmP493/+P7D+////AAAAAAA=","31":[46],"35":[46],"39":[46],"43":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/agents/composables/useAgentAssistantCredentialHelp.ts":{"8":"b:BgIBIABoAhhCAAACAIACAAKAAEAAAAQAAAAAAAA=","11":"b:BgIBIABoAhBCAAACAIACAAKAAEAAAAQAAAAAAAA=","15":[46],"20":[46]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentCapabilitiesActions.ts":{"110":"b:D+rt+QN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","134":[46],"148":[46],"162":[46],"168":[46],"194":[46],"198":[46],"201":[46],"202":[46],"207":[46],"221":[46],"244":[46],"245":[46],"246":[46],"251":[46],"256":[23,24,46],"285":[46],"286":[46],"305":[46],"309":[46],"337":[46],"370":[46],"371":[46],"374":[46],"379":[46],"380":[46],"387":[46],"389":[46],"394":[46],"403":[46],"407":[46],"414":[46],"417":[46],"419":[46],"423":[46],"424":[46],"430":[46],"432":[46],"438":[46],"447":[46],"457":[46],"471":[46],"527":[46],"538":[46],"542":[46]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentConfig.ts":{"6":"b:D+rt+wN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","27":"b:D+rt+wN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","39":"b:D+rt+QN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","46":[23,24,25,46],"70":[46]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentNavigation.ts":{"11":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","23":[46],"42":[46],"62":[46],"66":[46]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentPermissions.ts":{"21":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","28":[107,40,111,5,45,46,60,69,88],"31":[107,40,111,5,45,46,60,69,88],"34":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","37":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","39":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","42":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","43":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","51":[23,24,46],"52":[46]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentScopeProjectId.ts":{"15":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","19":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA="},"packages/frontend/editor-ui/src/features/agents/composables/useAgentTelemetry.ts":{"20":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","25":[46],"28":[46],"36":[46],"44":[46],"53":[46],"67":[46],"84":[46],"92":[46],"100":[46],"107":[46],"124":[46],"132":[46],"145":[46],"160":[46],"177":[46],"184":[46],"195":[46],"212":[46],"221":[46],"236":[46,120]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentsN8nChatFlag.ts":{"8":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","17":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","24":"b:AABYAABABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","27":"b:AABYAABABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","31":"b:AABYAABABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","32":"b:AABYAABABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","43":[46]},"packages/frontend/editor-ui/src/features/agents/composables/useCreateAgent.ts":{"17":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","21":[46]},"packages/frontend/editor-ui/src/features/agents/composables/useMessageAgentSessionLink.ts":{"33":[32,1,2,3,144,18,188],"61":[32,1,2,3,144,18,188],"66":[32,1,2,3,144,18,188]},"packages/frontend/editor-ui/src/features/agents/module.descriptor.ts":{"22":[46],"23":[46],"24":[23,24,25,46],"25":[23,24,25,46],"26":[23,24,46],"27":[23,24,46],"28":[25,46],"29":[25,46],"30":[25,46],"31":[25,46],"32":[46],"33":[46],"34":[46],"35":[46],"39":[46],"54":[46],"172":"b:f+r/+4P/5/92+v/v+/j////////8////AAAAAAA="},"packages/frontend/editor-ui/src/features/agents/n8nChatPage/n8nChatThreads.store.ts":{"20":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA="},"packages/frontend/editor-ui/src/features/agents/n8nChatPage/useRecentChats.ts":{"19":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","25":[91,95,114,59,60,100],"31":[91,95,114,59,60,100]},"packages/frontend/editor-ui/src/features/agents/utils/agentNode.ts":{"10":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","27":[46],"32":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/assistant.store.ts":{"37":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","45":"b:D+oF+AN+4PFA+v/HwmAI8H/+P7D8////AAAAAAA=","58":[28,46],"59":[28,46],"79":[27,28,29,30,31,102,33,46,63],"80":[27,28,30,46],"82":[27,28,29,30,46],"84":[27,28,29,30,31,102,33,46,63],"94":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","96":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","100":[27,28,29,46],"102":[27,29,46],"107":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","115":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","119":[27,28,29,30,46],"123":[27,28,29,30,46],"136":[27,28,29,30,46],"138":[27,28,29,30,46],"142":[27,28,29,30,46],"199":[27,28,46],"210":[29,46],"216":[27,28,29,30,46],"220":[27,28,29,30,46],"232":[46],"236":[46],"247":[27,28,29,30,46],"251":[27,29,30,46],"261":[46],"277":[27,28,29,30,46],"297":[27,28,29,30,46],"301":[27,28,29,30,46],"305":[27,28,29,30,46],"309":[46],"317":[29,46],"336":[27,30,46],"420":[27,29,30,46],"480":[27,29,30,46],"481":[27,29,30,46],"482":[46],"487":[46],"493":[27,28,46],"554":[27,28,46],"555":[27,28,46],"556":[46],"557":[46],"562":[28,46],"590":[28,46],"591":[28,46],"592":[46],"593":[46],"598":"b:DyBEWAFw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA=","629":[27,30,46],"639":[46],"640":[46],"679":[27,30,46],"680":[27,30,46],"681":[46],"692":[27,30,46],"706":[27,28,29,30,31,102,33,46,63],"746":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","747":"b:BsoF+ABqQJFUev9HgmAA8D+2PxL0ft/+AAAAAAA=","753":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","756":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","764":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/builder.store.ts":{"166":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","188":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","190":[46],"202":[46],"211":[46],"230":"b:f+pf+AP+5/9A+v/H8vPt8///P/D/////AAAAAAA=","259":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","262":[31,33,46],"265":[31,33,46],"292":[46],"297":[46],"304":[31,33,46],"307":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","315":[46],"316":[46],"323":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","327":[31,33,46],"329":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","331":[46],"332":[46],"335":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","351":[46],"355":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","367":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","371":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","374":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","376":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","388":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","404":[46],"410":[31,33,46],"420":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","432":"b:f+pf+AP+5/9A+v/H8vPt8///P/D/////AAAAAAA=","450":[46],"457":[46],"462":"b:DyBEGAFw5WEAsD5EAEAAAHwmJQBC9mscAAAAAAA=","469":"b:D+pt+AN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","477":[31,33,46],"481":[31,33,46],"485":[46],"491":[46],"503":[31,33,46],"530":[31,33,46],"531":[31,33,46],"541":[46],"573":[46],"580":[31,33,46],"644":[33,46],"655":[33,46],"664":[33,46],"695":[31,33,46],"726":[31,33,46],"727":[46],"729":[46],"739":[31,33,46],"816":[31,33,46],"832":[31,33,46],"864":[31,46],"889":[31,33,46],"912":[46],"1014":[46],"1025":[31,46],"1028":[31,46],"1050":[31,46],"1057":[33,46],"1067":[46],"1078":[46],"1128":[31,102,33,46],"1221":[46],"1235":[46],"1353":[46],"1364":[46],"1372":[46],"1387":[46],"1397":[31,46],"1402":[31,46],"1404":[46],"1411":[46],"1424":[46],"1429":[31,33,46],"1440":"b:AoAAkABAAAEAaiYAAAAAAAAEAQDAMkseAAAAAAA=","1448":"b:AoAAgABAAAEAaiYAAAAAAAAEAQDAMkseAAAAAAA=","1456":[31,46],"1460":[31,102,33,46],"1465":[31,102,33,46],"1479":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","1480":"b:D+oF+AN+4PFA+v/H4mMI8H/+P7D/////AAAAAAA=","1513":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","1525":[31,46],"1546":[31,46],"1577":[46],"1605":[46],"1610":[46],"1632":[46],"1648":[46],"1677":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA="},"packages/frontend/editor-ui/src/features/ai/assistant/chatPanel.store.ts":{"32":[27,28,29,30,31,102,33,46,63],"39":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","50":[27,28,29,30,46,63],"58":[27,28,29,30,31,102,33,46,63],"63":[46],"64":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","66":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","69":[27,28,29,30,31,102,33,46,63],"103":[27,29,46],"110":[27,28,30,31,33,46,63],"119":[27,46],"127":[27,46],"142":[27,30,31,102,33,46,63],"150":[27,28,29,30,31,33,46,63],"168":[46],"182":[29,46],"200":[27,28,46],"216":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","217":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","254":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","255":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","256":[46],"257":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/chatPanelState.store.ts":{"14":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/AskAssistantBuild.vue":{"71":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","84":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","106":[46],"114":[31,46],"121":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","122":[46],"128":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","132":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","137":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","141":[46],"147":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","152":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","163":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","164":[31,33,46],"166":[31,33,46],"174":[31,33,46],"175":[31,33,46],"178":[31,33,46],"194":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","195":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","196":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","199":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","205":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","212":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","219":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","223":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","236":[46],"241":[31,46],"246":[46],"254":[46],"263":[46],"275":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","299":[46],"303":[46],"307":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","323":[46],"325":[46],"339":"b:D+oFgAN+4HFU+v9HgmMI8H/+P7L8/3//AAAAAAA=","341":[31,33,46],"352":[46],"354":[46],"357":[46],"360":[46],"388":[31,33,46],"404":[31,46],"413":"b:cgBeAADoBx5AiEADEpDlA4ABAFAABwDdAAAAAAA=","421":[46],"439":[46],"509":[46],"512":[46],"527":[46],"539":[31,46],"553":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","555":"b:cgBegALoBx5AiEADEpDlA4ABAFAABwDdAAAAAAA=","590":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","591":[31,33,46],"603":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","605":[31,33,46],"634":[46],"668":[46],"680":"b:cgBeAADoBx5AiEADEpDlA4ABAFAABwDdAAAAAAA=","687":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","688":[46],"690":[46],"699":[31,33,46],"705":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","708":[31,33,46],"727":[46],"729":[46],"735":[46],"739":[31,102,33,46],"741":[46],"745":[31,46],"749":[46],"752":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","766":[46],"767":[46],"770":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","775":[31,33,46],"782":"b:D+oFAAF+4HFU+v9HgmMI8H/+P7L8/3//AAAAAAA=","785":[31,46],"791":[46],"805":[46],"806":[46],"837":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","867":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","869":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","877":"b:D+oFgAN+4HFU+v9HgmMI8H/+P7L8/3//AAAAAAA=","905":[46],"907":"b:D+oFgAN+4HFU+v9HgmMI8H/+P7L8/3//AAAAAAA="},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/BuildModeEmptyState.vue":{"5":"b:D+oFAAF+4HFU+v9HgmMI8H/+P7L8/3//AAAAAAA=","6":"b:D+oFAAF+4HFU+v9HgmMI8H/+P7L8/3//AAAAAAA="},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/PlanModeSelector.vue":{"14":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","24":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","43":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","44":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","47":[46],"50":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","65":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","68":"b:f+r/i4P/5392+v/v+/v/////////////AAAAAAA=","70":"b:f+r/i4P/5392+v/v+/v/////////////AAAAAAA=","72":"b:f+r/i4P/5392+v/v+/v/////////////AAAAAAA="},"packages/frontend/editor-ui/src/features/ai/assistant/components/AssistantsHub.vue":{"19":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","36":[46],"39":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","40":[27,28,29,30,31,102,33,46,63],"51":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","55":[46],"59":[46],"63":[46],"85":[27,46],"89":[27,28,30,31,33,46,63],"98":"b:DyBE+ANw5eEAsD5EwEAAAHwmJQBC9mscAAAAAAA=","106":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","112":"b:fupf+QLuRx9Cuv9HkvDlU/+vP3Hk///fAAAAAAA=","124":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","137":[46],"141":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","150":"b:f+r/+4P/5/92+v/v+vv/////////////AAAAAAA=","164":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","169":[31,102,33,46],"175":[46],"176":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/components/FocusedNodes/ChatInputWithMention.vue":{"24":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","45":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","66":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","67":[31,33,46],"73":[31,33,46],"91":[46],"92":[46],"93":[46],"95":[46],"99":[46],"103":[31,46],"114":[31,33,46],"121":[31,33,46],"127":[33,46],"131":[46],"135":[46],"138":[46],"144":[46],"146":[46],"151":[46],"155":[46],"159":[31,33,46],"163":[46],"174":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","199":[46],"216":[46],"219":[46],"220":[46],"223":[46],"242":[46],"245":[46],"254":[46],"267":[46],"283":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","288":[46],"293":[46],"306":[46],"309":[46],"310":[46],"317":[46],"344":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useAIAssistantHelpers.ts":{"45":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","47":[27,28,29,46],"62":[27,28,29,46],"74":[46],"81":[27,28,29,46],"100":[46],"101":[46],"113":[46],"122":[46],"131":[46],"137":[46],"163":[46],"180":[46],"207":[27,28,46],"214":[27,28,46],"227":[27,28,29,30,46],"251":[29,46],"276":[27,28,46],"298":[27,28,29,46],"301":[27,28,29,46],"309":[27,28,29,31,46],"335":[27,30,46],"357":[30,46],"379":[30,46],"420":[27,30,31,33,46],"428":[46],"447":[46],"465":[46],"509":[46],"582":[46],"596":[46],"632":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useAskModeCoachmark.ts":{"14":[31,102,33,46],"17":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","25":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","27":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","35":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","49":[46],"59":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useBuilderMessages.ts":{"29":[46],"44":[46],"55":[46],"69":[46],"82":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","88":[31,33,46],"89":[31,33,46],"104":[46],"141":[46],"166":[46],"173":[46],"208":[31,46],"262":[46],"269":[46],"276":[46],"282":[46],"326":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","327":[31,33,46],"330":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","331":[46],"342":[31,46],"354":[46],"355":[46],"395":[31,46],"419":[31,46],"436":[31,46],"460":[31,46],"462":[31,46],"471":[31,33,46],"492":[46],"517":[33,46],"541":[46],"556":"b:f+pf+AP+5/9A+v/H8vPt8///P/D/////AAAAAAA=","560":[46],"567":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useBuilderTodos.ts":{"37":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","47":[31,46],"89":[31,46],"129":[31,33,46],"138":[31,46],"151":[31,33,46],"206":[31,33,46],"212":[31,46],"221":[46],"246":[31,33,46],"247":[31,46],"254":[31,46]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useCodeDiff.ts":{"28":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","31":[28,46],"41":[28,46],"43":[28,46],"64":[28,46],"68":[28,46],"74":[28,46],"87":[28,46],"133":[28,46]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useFocusedNodesChipUI.ts":{"14":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","19":[46],"20":[46],"21":[46],"22":[46],"24":[46],"31":[46],"39":[46],"40":[46],"42":[46],"48":[46],"54":[46],"58":[46],"68":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useNodeMention.ts":{"32":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","46":[46],"51":[46],"54":[46],"61":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","62":"b:BsptgABqRxFAes9FgAAAQAawDhD2a18DAAAAAAA=","70":[46],"85":[46],"104":[46],"126":[46],"155":[31,33,46],"200":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useReviewChanges.ts":{"34":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","46":[46],"51":[46],"71":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","73":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","100":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","101":[31,46],"115":[31,46],"116":[46],"134":[31,46],"138":[46],"140":[46],"141":[46],"163":[31,46],"168":[31,46],"205":[46],"210":[46],"212":[46],"213":[46],"227":[46],"231":[46],"241":[46],"255":[27,28,29,30,46,63],"269":[46],"278":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","279":[31,33,46],"288":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","289":[31,46],"299":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","300":[31,102,33,46],"309":[27,28,29,30,46,63],"313":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","322":[46],"328":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/focusedNodes.store.ts":{"27":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","29":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","36":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","42":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","52":"b:D+pt+AN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","53":[46],"56":[46],"57":[46],"60":[46],"73":[46],"78":[46],"80":[46],"82":[46],"84":[46],"88":[46],"92":[46],"93":[46],"101":[46],"139":[46],"169":[46],"174":[46],"189":[46],"206":[46],"219":[46],"226":[46],"233":[46],"240":[46],"241":[46],"247":[31,33,46],"249":[46],"273":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","274":"b:D+pt+AN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","289":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","290":"b:D+pt+AN+5/FU+v/H4mMI8H/+P7L/////AAAAAAA=","292":"b:D+pt+AF+5/FU+v9HgmMI8H/+P7L+/3//AAAAAAA=","318":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","319":"b:D+pt+AN+5/FU+v/H4mMI8H/+P7L/////AAAAAAA=","331":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","332":"b:DupFeABuQBFUOv9EgGIAUG+uPzLk/n8CAAAAAAA=","341":[31,33,46]},"packages/frontend/editor-ui/src/features/ai/chatHub/chat.store.ts":{"108":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","137":[4,111,5,112,6,17,46],"140":[4,111,5,112,6,17,46],"147":[4,111,5,112,6,17,46],"163":[4,111,5,112,6,17,46],"173":[4,111,5,112,6,17,46],"177":[4,111,5,112,6,17,46],"214":[4,111,5,112,6,17,46],"237":[46],"279":[4,111,5,112,6,17,46],"291":[46],"305":[4,111,5,112,46],"315":[4,111,5,112,6,17,46],"334":[4,111,5,112,6,17,46],"341":[6,46],"347":[46],"349":[46],"355":[46],"357":[46],"363":[46],"365":[46],"368":[4,111,5,112,6,17,46],"371":[4,111,5,112,6,17,46],"377":[4,111,5,112,6,17,46],"382":[4,111,5,112,6,17,46],"411":[4,111,5,112,6,17,46],"435":[46],"441":[4,46],"447":[4,46],"458":[4,111,5,112,6,17,46],"467":[4,111,5,112,6,17,46],"484":[6,17,46],"497":[46],"517":[46],"544":[46],"555":[46],"568":[46],"595":[4,111,5,112,6,17,46],"610":[4,46],"657":[6,46],"694":[46],"715":[46],"729":[46],"797":[46],"868":[46],"883":[46],"894":[46],"900":[46],"907":[46],"915":[46],"925":[46],"931":[46],"942":[46],"946":[46],"949":[46],"961":[112,46],"967":[46],"968":[46],"973":[46],"985":[112,46],"996":[112,46],"999":[46],"1031":[112,46],"1052":[46],"1056":[112,46],"1076":[112,46],"1081":[112,46],"1091":[4,111,5,112,6,17,46],"1095":[4,111,5,112,6,17,46],"1106":[113,46],"1117":[113,46],"1127":[46],"1133":[113,46],"1150":[4,111,5,112,6,17,46],"1196":[4,111,5,112,46],"1214":[4,111,5,112,6,17,46],"1230":[6,17,46],"1252":[4,111,5,112,6,17,46],"1294":[4,111,5,112,6,17,46],"1335":[4,111,5,112,6,17,46],"1362":[4,111,5,112,6,17,46],"1392":[4,46],"1413":[46],"1447":[46],"1465":[46],"1492":[46],"1519":[46],"1531":[4,111,5,112,6,17,46],"1532":[4,111,5,112,6,17,46],"1557":[4,111,5,112,6,17,46],"1558":[4,111,5,112,6,17,46]},"packages/frontend/editor-ui/src/features/ai/chatHub/chatHubPanel.store.ts":{"12":[46],"19":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","29":"b:D+pt+AN+5/FA+v/H4mMI8H/+P7D+////AAAAAAA=","39":[46],"45":[46],"52":[46],"60":[46],"66":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","67":"b:cgBeIADoBx5AiEADEpDlA4ABAFAABwDdAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/chatHub/module.descriptor.ts":{"18":[4,111,5,112,6,17,46],"19":[17,46],"20":[17,46],"21":[112,46],"22":[112,46],"23":[113,46],"24":[113,46],"34":[46],"40":[46],"46":[6,46],"51":[46],"57":[112,46],"62":[46],"63":[46],"69":[5,46],"75":[46],"81":[46],"87":[46],"93":[113,46],"99":[46],"100":[46],"113":[46],"127":[46],"141":[46],"155":[46],"176":[46],"203":"b:f+r/+4P/5/92+v/v+/j////////8////AAAAAAA="},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/components/EvaluationsCanvasInfoCard/EvaluationsCanvasInfoCard.vue":{"25":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","74":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","85":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","99":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","103":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","134":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","159":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","182":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA="},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/composables/useAiRootNodes.ts":{"15":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA="},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/composables/useEvaluationsLicense.ts":{"9":[101],"12":"b:D+pt+AM+5/FA+v/H4mMI8H/+P7D+////AAAAAAA="},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/evaluation.store.ts":{"11":"b:D+pt+AN+5/FA+v/H4mAI8H/+P7D8////AAAAAAA=","26":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","28":[46],"30":[46],"31":[46],"45":[101,46],"52":[101,46],"65":[101,46],"69":[101,46],"81":[46],"87":[46],"99":[46],"108":[46],"127":[46],"138":[101,46],"147":[46],"160":[46],"175":[46],"176":[46],"182":[46],"187":[46],"198":[46],"199":[46]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/wizardSidepanel.store.ts":{"29":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","32":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useAddNodesToChat.ts":{"18":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","27":[46],"43":[46]},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useInstanceAiAvailability.ts":{"14":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","16":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","42":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","45":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useInstanceAiHandoff.ts":{"43":[46],"52":[46],"53":[46],"66":[46],"78":[46],"89":[46,116,117,21,120,122],"90":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","92":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","93":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","95":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","97":[46,116,117,21,120,121,122],"113":[46],"134":[46],"165":[46,122],"173":[46,116,117,21,120,122],"197":[46],"204":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","215":[46,120],"224":[46],"235":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","260":[46,120],"264":[46],"271":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","282":[46,120],"291":[46,121],"298":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","311":[46,120],"321":[46,121],"325":[46,116,117,21,120,122],"332":[46,120],"337":[46,120],"341":[46,116,117,21,120,121,122],"344":[46],"354":[46,120],"358":[46,116,117,21,120,121,122],"369":[46,120],"380":[46,122],"398":[46,122],"422":[46,121],"456":[46],"483":[46],"525":[46],"549":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","564":[46],"568":[46],"575":[46],"615":[46],"683":[46],"718":[46]},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useInstanceAiHandoffCapability.ts":{"37":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","51":[46],"71":[46],"79":[46],"93":[46],"132":[46],"168":[46],"194":[46]},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useIsNodeContextEnabled.ts":{"8":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","12":"b:D+pt+AN+5/FA+v9HgmMI8H/+P7D+/3//AAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAi.memory.api.ts":{"17":"b:D+r/A4H+539C+v/Ou3j89///P/H8////AAAAAAA=","23":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","30":[46,116,117,21,120],"37":[46,120],"41":[46,120],"51":[46],"61":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","68":[46,48,49,22,50],"82":[46],"95":[46,116,117,21,120,121,122],"112":[46,116,117,48,21,120,22,122],"119":[46],"126":[46]},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAi.store.ts":{"54":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","62":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","90":[46],"94":[46,19,20,117,48,118,119,120,22,50],"97":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","101":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","106":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","113":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","117":[46,120],"128":[46],"129":[46],"130":[46],"133":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","144":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","156":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","165":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","168":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","176":[46],"190":[46],"197":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","210":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","221":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","222":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","225":"b:D+r/A4H+539C+v/Ou3j89///P/H8////AAAAAAA=","233":"b:AAB4AABABQAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","234":"b:AAB4AABABQAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","244":[46,116,117,21,120],"247":[46,116,117,21,120],"256":[46,19,20,117,48,118,119,49,120,22,50,121],"262":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","288":[46],"289":"b:AAB4AABABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","294":"b:AABYAABABwAAAAAAAADgBwAAAAAAAAAAAAAAAAA=","315":[46,118,119,120],"335":[46,120],"353":[46,120],"354":[46,120],"360":[46,120],"378":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","379":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","383":[46],"384":[46],"393":[46],"394":[46],"398":[46],"414":[46],"415":[46],"428":[46],"435":[46],"440":[46],"449":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","452":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","458":[46,19,48,118,119,49,22,50],"465":[46],"526":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","536":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAiPermissions.ts":{"4":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","9":"b:X+r/+4P+5/92+v/u//j////////8////AAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAiSettings.store.ts":{"52":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","82":[46],"91":[46],"94":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","98":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","101":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","104":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","110":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","113":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","122":[46,19,20,117,48,118,119,49,120,22,50,122],"128":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","131":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","134":[107,46],"137":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","142":[46,96],"175":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","178":[46],"181":[46,96],"185":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","225":[46,96],"241":[46],"253":[46],"260":[46],"279":[46],"293":"b:AAB4AABABwAAAAAAAQDwBQAAAAAAAAAAAAAAAAA=","300":[46],"301":[46],"305":[46],"309":[46],"315":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","324":[46],"342":[46,96],"350":"b:AAB4AABABwAAAAAAAQDwBQAAAAAAAAAAAAAAAAA=","356":[46],"361":[46],"371":[46,96],"386":"b:AAB4AABABwAAAAAAAQDwBQAAAAAAAAAAAAAAAAA=","399":[46],"409":[46],"427":[46],"454":[46],"498":"b:AAB4AABABwAAAAAAAQDwBQAAAAAAAAAAAAAAAAA=","501":[46,19,48,21,49,22,50],"520":"b:AAB4AABABwAAAAAAAQDwBQAAAAAAAAAAAAAAAAA=","521":[46],"531":[46],"542":[46],"550":[46],"570":[46,96],"579":[46],"588":[46],"594":[46],"595":[46],"599":[46],"600":[46],"609":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","613":"b:AAB4AABABwAAAAAAAQDwBQAAAAAAAAAAAAAAAAA=","621":[46],"627":[46],"633":[46,96]},"packages/frontend/editor-ui/src/features/ai/instanceAi/module.descriptor.ts":{"41":"b:f+r/+4P/5/92+v/v+/j////////8////AAAAAAA=","61":[46],"78":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","79":"b:AABYAABABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","80":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","81":[46],"82":[46],"93":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","103":[46,121,122],"158":"b:AABYAABABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","187":[46],"191":[46],"202":[46],"222":[46],"232":[46],"250":[46],"251":[46],"254":[46],"255":[46],"268":"b:f+r/+4P/5/92+v/v+/j////////8////AAAAAAA="},"packages/frontend/editor-ui/src/features/collaboration/collaboration/collaboration.store.ts":{"33":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","77":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","81":[46],"85":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","86":"b:D+Jt+AF+59FA+v5HgEAIAH5uJbDs/+/fAAAAAAA=","89":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","93":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","97":"b:D+Jt+AN+5/FA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","119":"b:D+Jt+AN+5/FA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","124":[46,19,50,60,168,86,184],"128":[46,19,50,60,168,86,184],"133":"b:D+Jt+AN+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","140":"b:D+Jt+AN+5/FA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","145":"b:AsINsABIRJFAemYBAAAAAEAkBQDkO0sfAAAAAAA=","152":[46],"164":"b:AsIFsABIQIFAemYBAAAAAEAkBQDkOksfAAAAAAA=","172":"b:AsINsABIRJFAemYBAAAAAEAkBQDkO0sfAAAAAAA=","183":[46],"198":[46],"204":[46],"209":[46],"214":[46],"218":"b:AsIFsABIQIFAemYBAAAAAEAkBQDkOksfAAAAAAA=","222":"b:BsoF+AJqQJFAev9HgGAA8H+2PxD0ft9/AAAAAAA=","243":[46],"261":[46,86],"280":"b:CgAFAABAABEAgDAAAAAIAIAAAICAAkAIAAAAAAA=","295":"b:D+Jt+AN+5/FA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","302":"b:D+Jt+AN+5/FA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","307":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","311":"b:BsIN+ABoRBEQev5GgEAAADQGJQLkd8vfAAAAAAA=","316":[46],"326":[46],"332":"b:AoAAgABAAEEAaiYAAAAAAEAEAQDAMssfAAAAAAA=","359":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","360":"b:BsoF+ABqQJFUev9HgmAA8D+2PxL0ft/+AAAAAAA=","369":"b:D+Jt+AF+59FA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","372":[43,9,46,76,77,166,167,177],"381":"b:D+Jt+AN+5/FA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","404":"b:D+Jt+AF+5/FA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","460":[46,19,50,60,168,86,184]},"packages/frontend/editor-ui/src/features/collaboration/collaboration/components/CollaborationPane.vue":{"11":"b:D+Jt+AM+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","15":[42,21,57,62,73,77,162,78,171,86,182,88,190],"24":"b:D+Jt+AM+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","26":[57,88],"27":[57,88],"29":[57,88],"35":[57,88],"37":"b:D+Jt+AM+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","41":[19,50,57,60,168,86,184],"44":"b:D+Jt+AM+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA="},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectCardBadge.vue":{"23":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","32":"b:AAIAAIDoAB5CAEAJABAEAgAAAEAAAQDAAAAAAAA=","37":"b:AAIAAIDoAB5CAEAJABAEAgAAAEAAAQDAAAAAAAA=","46":"b:AAIAAIDoAB5CAEAJABAEAgAAAEAAAQDAAAAAAAA=","50":"b:AAIAAIDoAB5CAEAJABAEAgAAAEAAAQDAAAAAAAA=","73":"b:AAIAAIDoAB5CAEAJABAEAgAAAEAAAQDAAAAAAAA=","77":"b:AAIAAIDoAB5CAEAJABAEAgAAAEAAAQDAAAAAAAA=","89":"b:AAIAAIDoAB5CAEAJABAEAgAAAEAAAQDAAAAAAAA=","105":"b:AAIAAIDoAB5CAEAJABAEAgAAAEAAAQDAAAAAAAA=","148":"b:AAIAAIDoAB5CAEAJABAEAgAAAEAAAQDAAAAAAAA=","162":"b:AAIAAIDoAB5CAEAJABAEAgAAAEAAAQDAAAAAAAA=","174":"b:AAIAAIDoAB5CAEAJABAEAgAAAEAAAQDAAAAAAAA=","177":"b:AAAAAICAAB4AAEAJABAAAgAAAAAAAQDAAAAAAAA="},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectIcon.vue":{"13":"b:D+r/+4P+5/9C+v/P4nD+9///P/D8////AAAAAAA=","14":"b:D+r/+4P+5/9C+v/P4nD+9///P/D8////AAAAAAA=","35":[60]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectNavigation.vue":{"48":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","77":"b:D+r/+4O/5/9i+v/P63j89///P/H8////AAAAAAA=","78":[100],"79":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","85":"b:D+r/+4O/5/9i+v/P63j89///P/H8////AAAAAAA=","86":"b:D+r/+4O/5/9i+v/P63j89///P/H8////AAAAAAA=","89":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","101":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","108":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","132":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","141":"b:D+r/+4O/5/9C+v/P63D89///P/H8////AAAAAAA=","150":"b:AGICgIAYQN4CQqYBAAAE4Lr3JvEoOSbnAAAAAAA=","162":"b:D+r/+4O/5/9i+v/P63j89///P/H8////AAAAAAA=","174":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","176":"b:D+r/A4G+539C+v/Ou3j89///P/H8////AAAAAAA=","186":[120],"190":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","192":"b:D+rfA4G+539C+v/Ou3js9///P/H8////AAAAAAA=","197":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","223":[17],"236":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","243":[121,60,156,168,86,88,184,190,89,191],"248":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","403":[114,59,60,88],"420":"b:AGICgIAYQN4CQqYBAAAE4Lr3JvEoOSbnAAAAAAA="},"packages/frontend/editor-ui/src/features/collaboration/projects/composables/useFavoriteNavItems.ts":{"23":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA=","155":"b:D+r/+4O/5/9i+v/P+3j89///P/H8////AAAAAAA="},"packages/frontend/editor-ui/src/features/collaboration/projects/composables/useMoveResourceToProjectToast.ts":{"21":"b:D+pt+AN+5/lA+v/H4mAI8H/+P7D8////AAAAAAA=","26":[46,59],"45":[46]},"packages/frontend/editor-ui/src/features/collaboration/projects/composables/useProjectPages.ts":{"9":"b:D+r/+4O/5/9i+v/P+3j89///P/H+////AAAAAAA=","13":"b:AAICAIAIAB4CAAABAAAEAIABABAAAABAAAAAAAA=","16":"b:AAICIICpAB5iAEAJGBAEAoABAFEAAQDBAAAAAAA=","19":"b:AAICIICpAB5iAEAJGBAEAoABAFEAAQDBAAAAAAA="},"packages/frontend/editor-ui/src/features/collaboration/projects/projects.api.ts":{"9":[17,46,58,60,65],"13":[46,59,157,190],"29":[113,45,46,69,156,158,70,159,190],"47":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","51":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","55":"b:AAKCo4D4AB5CAsABAAAEAIABAHAAAARBAAAAAAA=","59":[46,58,60],"66":[46,58,60],"74":[46],"87":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","91":[17,46,58],"99":[17,46],"108":[46],"116":[46]},"packages/frontend/editor-ui/src/features/collaboration/projects/projects.routes.ts":{"9":"b:AAAAAIDBAB4gAEAJHBgEAoABABAAAQDBAAAAAAA=","10":[29,43,9,45,46,59,60,65,158,70],"11":[29,43,9,45,46,59,60,65,158,70],"12":[17,46,58,60],"13":[46],"14":[46],"15":[46,152],"17":"b:AAAAIIDpABxgAEAJHBgAAgAAAEEAAQDAAAAAAAA=","18":"b:AAAAIIDpABxgAEAJHBgAAgAAAEEAAQDAAAAAAAA=","19":"b:AAAAIIDpABxgAEAJHBgAAgAAAEEAAQDAAAAAAAA=","25":[46],"28":"b:IAIAIIDpAB5iAEAJHBgEAoABAFEAAQDBAAAAAAA=","32":"b:AAIAIIDoABpCAAABAAAEAIABAFAAAABBAAAAAAA=","43":"b:IAAAAIDBAB4gAEAJHBgEAoABABAAAQDBAAAAAAA=","54":[29,43,9,45,46,59,60,65,158,70],"64":[46],"74":[46,135,57,136],"84":[46,152],"144":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","156":[17,46,58,60],"157":[17,46,58,60],"183":"b:IAAAIIDpABxgAEAJHBgAAgAAAEEAAQDAAAAAAAA=","197":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","218":[46],"230":[46]},"packages/frontend/editor-ui/src/features/collaboration/projects/projects.store.ts":{"42":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","62":[46,59,157,190],"65":[46,190],"69":"b:f+r/+4P/5/92+v/v//v/////////////AAAAAAA=","75":[46,190],"76":[46],"77":[46],"79":[113,45,46,158,70],"80":"b:X+r/+4P/5/92+v/v//j////////8////AAAAAAA=","81":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","82":"b:X+r/+4P/5/92+v/v//j////////8////AAAAAAA=","83":[46],"86":"b:X+r/+4P/5/92+v/v//j////////8////AAAAAAA=","92":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","95":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","100":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","101":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","106":"b:cAJ6oID5BxxgAMAJGZj1BwAAAEEAAQTAAAAAAAA=","110":[17,46,58,60,65],"114":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","118":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","122":[46],"130":[46,59,157,190],"140":[113,45,46,69,156,158,70,159,190],"150":"b:AAKCo4D4AB5CAsABAAAEAIABAHAAAARBAAAAAAA=","153":"b:AAKCI4DoAB5CAgABAAAEAIABAHAAAABBAAAAAAA=","157":[31,43,44,9,46,60,178,86,87],"164":"b:f+r/+4P/5/92+v/v//v/////////////AAAAAAA=","170":[46,58,60],"177":[46,58,60],"185":[46,58,60],"203":[46],"211":[46],"222":[17,46,58],"230":[17,46],"239":[46],"244":[46],"247":[46],"250":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","254":"b:C6BtAAFU5/BA4nQDIAAIAEhsAbAMn2HdAAAAAAA=","262":[46,70],"294":[46,59],"317":[46],"331":[17,46,58,60],"342":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/features/collaboration/projects/projects.utils.ts":{"21":[113,45,46,69,156,158,70,159,190],"25":[113,45,46,69,156,158,70,159,190],"39":"b:AAIAAIDoAB5CAEAJABAAAoABAGEAAQDAAAAAAAA=","41":[59,157,190],"58":"b:BgIBIABoAFpiCAADAIAGAAKAAPAAAATAAAAAAAA=","74":[46],"78":[46],"86":[46,59],"91":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/features/core/dataTable/components/NodeStorageLimitCallout.vue":{"9":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","13":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","28":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","31":[46]},"packages/frontend/editor-ui/src/features/core/dataTable/dataTable.api.ts":{"13":"b:AAAAAIDBABwgAEAJGBAEAgAAAAAAAADAAAAAAAA=","40":[46,47,114],"61":[46,114],"77":[46,47],"93":[46,47],"109":[46,47],"122":[46,47],"139":[46],"156":[46,47,114],"176":[46,47],"193":[46,47],"214":[46,47],"220":[46,47],"238":"b:X+r/+4P/5/92+v/v//j////////8////AAAAAAA=","246":[46],"269":[46],"283":[46]},"packages/frontend/editor-ui/src/features/core/dataTable/dataTable.store.ts":{"37":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","50":[46,47,114],"56":"b:X+r/+4P/5/92+v/v//j////////8////AAAAAAA=","60":[46],"64":[46,47,114],"72":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","76":"b:AAAAAIDBABwgAEAJGBAEAgAAAAAAAADAAAAAAAA=","101":[46,47,114],"127":[46],"131":[46],"158":[46],"172":[46],"176":[46,114],"179":[46,114],"185":[46,47],"197":[46,47],"199":[46,47],"207":[46,47],"215":[46,47],"224":[46],"238":[46],"246":[46,47,114],"247":[46,47,114],"254":[46,47],"266":[46,47],"274":[46,47],"288":[46,47],"289":[46,47],"299":[46],"313":[46],"317":[46],"323":[46,47,114],"341":[46,47],"353":[46],"363":[46,47],"378":[46,47],"382":"b:X+r/+4P/5/92+v/v//j////////8////AAAAAAA=","396":[46],"403":[46],"424":[46],"445":[46],"446":[46]},"packages/frontend/editor-ui/src/features/core/folders/components/FolderBreadcrumbs.vue":{"59":"b:D+pt+AO+5/tA+v/H4mAI8P//P7D8////AAAAAAA=","65":"b:D+pt+AO+5/tA+v/H4mAI8P//P7D8////AAAAAAA=","67":"b:D+pt+AO+5/tA+v/H4mAI8P//P7D8////AAAAAAA=","76":[57],"88":"b:D+pt+AO+5/tA+v/H4mAI8P//P7D8////AAAAAAA=","92":[57,136],"96":[47,135,57,136,59,88,190],"107":"b:D+pt+AO+5/tA+v/H4mAI8P//P7D8////AAAAAAA=","111":"b:D+pt+AO+5/tA+v/H4mAI8P//P7D8////AAAAAAA=","147":[57],"162":[57],"174":[57,136],"185":[57,136],"196":[57],"208":"b:D+pt+AO+5/tA+v/H4mAI8P//P7D8////AAAAAAA=","209":"b:D+pt+AO+5/tA+v/H4mAI8P//P7D8////AAAAAAA=","212":"b:D+pt+AO+5/tA+v/H4mAI8P//P7D8////AAAAAAA=","219":[47,19,50,136,59,60,168,86,88,184],"242":[57,136],"249":[57,136],"275":[47,135,57,136,59,88,190],"305":[57,136]},"packages/frontend/editor-ui/src/features/core/folders/components/ProjectBreadcrumb.vue":{"30":"b:D+pt+AO+5/tA+v/H4mAM8P//P7D8////AAAAAAA=","52":"b:D+pt+AO+5/tA+v/H4mAM8P//P7D8////AAAAAAA=","63":"b:D+pt+AO+5/tA+v/H4mAM8P//P7D8////AAAAAAA=","75":[57,136],"91":[57,136],"100":"b:D+pt+AO+5/tA+v/H4mAM8P//P7D8////AAAAAAA="},"packages/frontend/editor-ui/src/features/core/folders/composables/useFolders.ts":{"12":[46,135],"16":[46,135],"20":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","25":[46,135,57,136],"29":[46,57,136],"63":[46,135],"80":[46,135],"86":[46,135,57,136],"101":[46,135,57,136,59,190],"109":[46,135],"130":[46,135,57,136]},"packages/frontend/editor-ui/src/features/core/folders/composables/useParentFolder.ts":{"5":"b:D+pt+AM+5/FA+v/H4mMI8n/+P7D/////AAAAAAA=","11":"b:BsoF+AI6QBFAON/EwGMA8D+SPhD3Zp9rAAAAAAA="},"packages/frontend/editor-ui/src/features/core/folders/folders.constants.ts":{"16":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/features/core/folders/folders.store.ts":{"23":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","40":"b:AAAAAIDBAB4AAEAJCBAEAoABADAAAQDAAAAAAAA=","41":[46,135,57,136],"52":[46,57,136],"56":[46,57,136],"64":[46,57,136],"75":[46,57,136],"81":[46,57,136],"99":"b:AAAAAIDBAB4gAEAJGBAEAoABABAAAQDBAAAAAAA=","115":[46,136],"116":[46,136],"121":[46,136],"125":[46,136],"130":[46],"134":[46,59,157],"174":[46],"183":[46],"190":[46],"206":[46],"219":[46,135],"229":[46],"249":[46,136],"262":[46,57],"273":[46,57],"286":[46],"342":[46,57]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialConfig.vue":{"103":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","137":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","140":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","161":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","164":[29,9,46],"169":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","170":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","176":[46,178,89],"181":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","211":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","216":[29,9,46],"224":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","233":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","242":[46],"248":[46],"255":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","263":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","271":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","273":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","275":[29,111,113,46,178,89],"286":[29,46],"290":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","292":"b:BgIBAABoABBCAAACAIACAACAAEAAAAQAAAAAAAA=","296":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","303":[9,46,178],"309":[29,9,46,178,89],"318":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","329":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","338":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","340":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","345":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","347":[46],"349":"b:BgIBIABoABBCAAACAIACAACAAEAAAAQAAAAAAAA=","353":[1,2,43,111,9,45,46,60,143,65,158,70,16,89],"360":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","367":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","373":[46],"382":[29,9,46],"390":[46],"418":[29,46],"436":[46],"441":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","495":[29,111,113,89],"497":[29,111,113,89],"524":[1,2,43,9,45,60,143,65,158,70,16,178],"675":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","733":[29,9,46,178],"738":"b:BgIBIAAoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","804":"b:BgIBIABoABBAAAACAIACAAKAAEAAAAQAAAAAAAA=","806":"b:BgIBIAAoABBAAAACAIACAAKAAEAAAAQAAAAAAAA=","808":"b:BgIBIAAoABBAAAACAIACAAKAAEAAAAQAAAAAAAA="},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialEdit.vue":{"105":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","113":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","115":[9,46,178,89],"120":[9,46],"146":[46],"152":[46],"158":[46],"165":[46],"199":"b:BgIBAABoABBCAAACAIACAACAAEAAAAQAAAAAAAA=","211":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","213":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","221":"b:BgIBAABoABBCAAACAIACAACAAEAAAAQAAAAAAAA=","226":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","236":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","242":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","247":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","248":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","249":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","250":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","251":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","252":"b:BgIBIABoABBCAAACAIAAAAKAAEAAAAQAAAAAAAA=","253":"b:BgIBIABoABBCAAACAIAAAAKAAEAAAAQAAAAAAAA=","254":"b:BgIBIABoABBCAAACAIAAAAKAAEAAAAQAAAAAAAA=","255":"b:BgIBIABoABBCAAACAIAAAAKAAEAAAAQAAAAAAAA=","258":[46],"305":"b:BgIBAABoABBCAAACAIACAACAAEAAAAAAAAAAAAA=","309":"b:BgIBAABoABBCAAACAIACAACAAEAAAAAAAAAAAAA=","318":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","323":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","327":"b:BgIBAABoABBCAAACAIACAACAAEAAAAAAAAAAAAA=","331":"b:BgIBAABoABBCAAACAIAAAACAAEAAAAQAAAAAAAA=","335":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","340":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","344":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","348":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","381":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","391":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","402":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","411":[113,9,45,46,158,70],"413":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","429":[46],"447":[46],"460":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","534":[46],"538":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","560":[29,1,2,43,111,9,46,60,143,158,70,16,89],"566":"b:BgIBAABoABBCAAACAIACAACAAEAAAAQAAAAAAAA=","605":[46],"621":[113,45,46,158,70],"636":[46,158,70],"645":[113,45,46],"650":[29,9,46],"658":[29,9,46],"665":[29,9,46],"674":[46],"732":[1,2,43,111,9,45,46,60,143,65,158,70,16,89],"736":"b:BgIBAABoABBCAAACAIACAACAAEAAAAQAAAAAAAA=","753":[43,111,113,9,45,46,60,65,158,70,178,89],"758":[46],"764":[46],"771":[46],"817":[43,9,45,46,65,158,70,89],"823":[46],"829":[1,2,43,111,113,9,46,60,143,158,70,16,89],"830":[1,2,43,111,113,9,46,60,143,158,70,16,89],"837":[46],"838":[46],"845":[46],"862":"b:BgIBAABoABBCAAACAIACAACAAEAAAAQAAAAAAAA=","892":"b:BgIBAABoABBCAAACAIACAACAAEAAAAQAAAAAAAA=","994":[1,2,43,111,113,9,45,60,143,65,158,70,16,89],"1061":"b:BgIBAABoABBCAAACAIACAACAAEAAAAAAAAAAAAA=","1094":"b:BgIBAABoABBCAAACAIAAAACAAEAAAAQAAAAAAAA=","1114":"b:BgIBAABoABBCAAACAIAAAACAAEAAAAQAAAAAAAA=","1187":[113,9,45,46,158,70],"1242":[9,46],"1312":[46,178,89],"1420":[46],"1448":[46],"1454":[46],"1494":[46],"1537":[29,9,46],"1584":[46],"1609":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","1619":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","1623":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","1624":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","1657":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","1706":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","1710":[113,45,158,70],"1819":[46],"1820":[46]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialInputs.vue":{"28":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","31":[46],"39":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","43":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","44":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","53":[1,2,43,111,9,45,46,60,143,65,158,70,16,89],"55":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","65":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA="},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialModeSelector.vue":{"27":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","46":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","47":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","52":[29,1,2,43,9,46,129,143,16,178],"53":[29,1,2,43,9,46,129,143,16,178],"63":[29,46],"65":"b:BgIAIABoABBCAAACAIACAAKAAEAAAAAAAAAAAAA=","66":"b:BgIAIABoABBCAAACAIACAAKAAEAAAAAAAAAAAAA=","67":[46],"71":[29,46],"92":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","103":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","115":[29,43,9,46,16,178],"128":[29,43,9,46,16,178],"133":[29,43,9,46,16,178],"145":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","167":[29,43,9,46,16,178],"194":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","195":[29,43,9,46,16,178],"196":[29,43,9,46,16,178],"199":[29,43,9,46,16,178],"206":[29,43,9,46,16,178],"207":[29,43,9,46,16,178],"214":[29,9,46],"217":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","224":[29,43,9,46,16,178],"234":[29,43,9,46,16,178],"236":[29,43,9,46,16,178]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialIcon.vue":{"13":"b:dsoBoABqAhhCCCACAKADUAeKAECEABcCAAAAAAA=","24":"b:dsoBoABqAhhCCCACAKADUAeKAECEABcCAAAAAAA=","26":"b:dsoBoABqAhhCCCACAKADUAeKAECEABcCAAAAAAA=","30":"b:dsoBoABqAhhCCCACAKADUAeKAECEABcCAAAAAAA=","42":"b:dsoBoABqAhhCCCACAKADUAeKAECEABcCAAAAAAA=","53":"b:dsoBoABqAhhCCCACAKADUAeKAECEABcCAAAAAAA=","59":"b:dsoBoABqAhhCCCACAKADUAeKAECEABcCAAAAAAA=","69":"b:dsoBoABqAhhCCCACAKADUAeKAECEABcCAAAAAAA=","79":"b:dsoBoABqAhhCCCACAKADUAeKAECEABcCAAAAAAA=","103":"b:dsoBoABqAhhCCCACAKADUAeKAECEABcCAAAAAAA="},"packages/frontend/editor-ui/src/features/credentials/components/NodeCredentials.vue":{"177":[29,1,2,43,9,46,129,143,16,178],"181":[46],"191":"b:RgIBoABoAAFAAAAAAAAAAAKAABAAAAQAAAAAAAA=","209":[46],"223":"b:BsIBoABKAhAACCAAACAAUAeKAACEABcCAAAAAAA=","229":"b:RgIFgABsQAFAAAAAAAAAAACAADAAAAQAAAAAAAA=","235":[29,1,2,43,9,46,129,143,16,178],"237":"b:RsIFoABuQhFACCAAACAAUAeKADCEABcCAAAAAAA=","253":"b:RsoF4ABuQhFAGCEEgGAAUAeKCjCEFhcCAAAAAAA=","255":"b:TupF+ABuQlFAOv9EgGAAUG+uPzDs/n8SAAAAAAA=","267":"b:TupF+ABuQlFAOv9EgGAAUG+uPzDs/n8SAAAAAAA=","268":[109,9,46,54,56,16],"269":"b:RsoFoABuQhFACCAAACAAUAeKADCEABcCAAAAAAA=","275":"b:RsoFoABKQhFACCAAACAAUAeKADCEABcCAAAAAAA=","286":"b:RsoFoABuQhFACCAAACAAUAeKADCEABcCAAAAAAA=","290":[46],"291":[46],"294":[46],"304":"b:RsoFoABuQhFACCAAACAAUAeKADCEABcCAAAAAAA=","311":"b:RgIFgABsQAFAAAAAAAAAAACAADAAAAQAAAAAAAA=","317":[31,1,2,43,6,9,45,46,56,143,156,70,16,178],"322":[46],"329":[46],"353":"b:RgIFgABsQBFAAAAAAAAAAACAADAAAAQAAAAAAAA=","357":"b:RgIFgABsQBFAAAAAAAAAAACAADAAAAAAAAAAAAA=","361":"b:RgIFgABsQAFAAAAAAAAAAACAADAAAAAAAAAAAAA=","366":"b:RgIFgABsQAFAAAAAAAAAAACAADAAAAQAAAAAAAA=","374":"b:RsoFoABuQhFACCAAACAAUAeKADCEABcCAAAAAAA=","382":[46],"386":[46],"391":[46],"396":[46],"412":[46],"421":[46],"441":[46],"449":[46],"457":"b:TupF+ABuQlFAOv9EgGAAUG+uPzDs/n8SAAAAAAA=","458":"b:TupF+ABuQlFAOv9EgGAAUG+uPzDs/n8SAAAAAAA=","494":"b:TupF+ABuQlFAOv9EgGAAUG+uPzDs/n8SAAAAAAA=","559":"b:DupF+ABuQlFAOv9EgGAAUG+uPzDs/n8SAAAAAAA=","572":"b:TupF+ABuQlFAOv9EgGAAUG+uPzDs/n8SAAAAAAA=","573":"b:TupF+ABuQlFAOv9EgGAAUG+uPzDs/n8SAAAAAAA=","580":[29,1,2,43,9,46,129,143,16,178],"672":"b:TupF+ABuQFFAOv9EgGAAUG+uPzDs/n8SAAAAAAA=","677":"b:RgIFgABsQAFAAAAAAAAAAACAADAAAAQAAAAAAAA=","687":[42,46],"698":"b:RgIFgABsQAFAAAAAAAAAAACAADAAAAQAAAAAAAA=","710":[9,46],"729":[29,1,2,43,9,46,129,143,16,178],"767":[46,178],"777":[31,1,2,43,6,9,45,46,56,143,156,70,16,178],"895":[43,9,46,156,70,16],"926":[46],"941":"b:RsoFoABuQhFACCAAACAAUAeKADCEABcCAAAAAAA=","953":[46],"969":"b:RsIFoABuQhFACCAAACAAUAeKADCEABcCAAAAAAA=","982":[46],"983":[46],"999":[46],"1026":[46],"1033":[46],"1070":"b:RgIFgABsQAFAAAAAAAAAAACAADAAAAQAAAAAAAA=","1083":[46],"1091":[9,46],"1112":"b:RsoFoABuQhFACCAAACAAUAeKADCEABcCAAAAAAA=","1132":[1,6,45,46,56,157],"1136":[1,42,6,9,45,46,56,156,157,70],"1147":[46],"1153":"b:RgIFgABsQAFAAAAAAAAAAACAADAAAAQAAAAAAAA=","1179":"b:TupF+ABuQlFAOv9EgGAAUG+uPzDs/n8SAAAAAAA=","1182":[46],"1190":[46],"1198":[46],"1217":"b:RgIFgABsQAFAAAAAAAAAAACAADAAAAQAAAAAAAA=","1225":"b:RgIFgABsQAFAAAAAAAAAAACAADAAAAQAAAAAAAA=","1244":"b:RgIFgABsQAFAAAAAAAAAAACAADAAAAQAAAAAAAA=","1266":[46],"1292":"b:RgIFgABsQAFAAAAAAAAAAACAADAAAAQAAAAAAAA=","1298":[46],"1306":"b:RgIFgABsQAFAAAAAAAAAAACAADAAAAQAAAAAAAA=","1310":"b:RgIFgABsQAFAAAAAAAAAAACAADAAAAAAAAAAAAA=","1311":"b:RgIFgABsQAFAAAAAAAAAAACAADAAAAAAAAAAAAA=","1321":[46],"1325":[46],"1353":"b:RsIFoABuQhFACCAAACAAUAeKADCEABcCAAAAAAA=","1357":"b:RgIFgABsQAFAAAAAAAAAAACAADAAAAQAAAAAAAA=","1363":[46],"1368":[6,45,46,56],"1379":[29,1,2,43,9,46,129,143,16],"1380":[1,46],"1385":"b:BsoBoABKAhAACCAAACAAUAeKAACEABcCAAAAAAA=","1390":"b:BsoBoABKAhAACCAAACAAUAeKAACEABcCAAAAAAA=","1398":"b:AAIBIABKABAAACAAAAAAUAAIAAAAABcCAAAAAAA=","1403":"b:BsoBoABKAhAACCAAACAAUAeKAACEABcCAAAAAAA=","1410":"b:BsoBoABKAhAACCAAACAAUAeKAACEABcCAAAAAAA=","1414":"b:BsoBoABKAhAACCAAACAAUAeKAACEABcCAAAAAAA=","1418":"b:BsIBoABKAhAACCAAACAAUAeKAACEABcCAAAAAAA=","1425":"b:RsoFoABuQhFACCAAACAAUAeKADCEABcCAAAAAAA=","1437":"b:RsIFoABuQhFACCAAACAAUAeKADCEABcCAAAAAAA=","1449":[29,46,11],"1458":[46],"1482":"b:TupF+ABuQlFAOv9EgGAAUG+uPzDs/n8SAAAAAAA=","1492":"b:RsoFoABuQhFACCAAACAAUAeKADCEABcCAAAAAAA=","1502":"b:RsoFoABuQhFACCAAACAAUAeKADCEABcCAAAAAAA=","1504":[31,46],"1527":[46],"1528":[46],"1546":[46],"1550":[29,46],"1558":[29,46],"1559":[29,46],"1575":[29,1,2,43,9,46,129,143,16],"1588":[46],"1590":[46],"1599":[46],"1604":[46],"1607":[46],"1615":[46],"1620":[46],"1621":[46],"1627":[46],"1632":[46],"1635":[46],"1684":[6,45,46,56],"1685":[1,42,6,9,45,46,56,156,157,70],"1686":[1,6,45,46,56,157],"1689":"b:RgIFgABsQAFAAAAAAAAAAACAADAAAAQAAAAAAAA=","1701":[46],"1705":[46],"1711":[46],"1722":"b:RgIFgABsQAFAAAAAAAAAAACAADAAAAAAAAAAAAA=","1730":[46],"1731":[46],"1740":[46],"1747":[46],"1755":[46],"1762":[46],"1779":"b:RgIFgABsQAFAAAAAAAAAAACAADAAAAQAAAAAAAA=","1787":"b:RgIFgABsQAFAAAAAAAAAAACAADAAAAQAAAAAAAA=","1792":[46],"1794":[46],"1803":"b:RgIFgABsQAFAAAAAAAAAAACAADAAAAQAAAAAAAA=","1820":"b:RgIFgABsQAFAAAAAAAAAAACAADAAAAQAAAAAAAA=","1821":"b:RgIFgABsQAFAAAAAAAAAAACAADAAAAQAAAAAAAA=","1827":[1,46],"1851":[46],"1857":[46],"1858":[46],"1873":[46],"1883":[46],"1887":[42,46],"1899":[46],"1917":[9,46],"1931":[46],"1932":[46],"1933":[46]},"packages/frontend/editor-ui/src/features/credentials/composables/useCredentialForm.ts":{"87":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","117":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","122":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","126":[46],"130":[46],"137":"b:BgIBIABoABBCAAACAIAAAAKAAEAAAAQAAAAAAAA=","147":[29,1,2,43,9,46,129,143,16,178],"159":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","168":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","179":[46],"183":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","188":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","198":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","203":[29,1,2,43,9,46,129,143,16,178],"208":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","212":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","223":[46],"225":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","231":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","235":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","245":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","249":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","256":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","260":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","306":"b:BgIBAABoABBCAAACAIACAACAAEAAAAAAAAAAAAA=","313":"b:BgIBAABoABBCAAACAIACAACAAEAAAAQAAAAAAAA=","318":[1,2,43,111,113,9,45,60,143,65,158,70,16,89],"329":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","347":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","357":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","371":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","402":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","411":"b:BgIBAABoABBCAAACAIACAACAAEAAAAQAAAAAAAA=","412":"b:BgIBAABoABBCAAACAIACAACAAEAAAAAAAAAAAAA=","419":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","435":[29,9,46],"460":[113,9,45,46],"462":[113,9,45,46],"468":[113,9,45,46],"505":[113,9,45,46],"518":[46],"538":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","564":[46],"593":[1,2,43,111,9,45,46,60,143,65,158,70,16,89],"612":[46],"615":[46],"616":[46],"617":[46],"620":[1,2,43,111,113,9,46,60,143,158,70,16,89],"649":[113,9,45,46]},"packages/frontend/editor-ui/src/features/credentials/composables/useCredentialOAuth.ts":{"52":"b:Tur9+QBuR1lCOv9Ggery12+u/3Ds/n8SAAAAAAA=","69":"b:BsoBoAAqAhBCCCACAKACUAeKAECEABcCAAAAAAA=","87":"b:BsoBoAAqAhBCCCACAKACUAeKAECEABcCAAAAAAA=","100":"b:BgoBIAAoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","110":"b:BsoBoAAKAhAACCAAACAAUAeKAACEABcCAAAAAAA=","127":"b:AAIBIAAKABAAACAAAAAAQAAIAAAAABcCAAAAAAA=","137":[29],"149":"b:AAoBIAAKABAAACAAAAAAQAAIAAAAABcCAAAAAAA=","156":"b:AAoBIAAKABAAACAAAAAAQAAIAAAAABcCAAAAAAA=","162":"b:AAoBIAAKABAAACAAAAAAQAAIAAAAABcCAAAAAAA=","181":[29,11],"545":"b:TupF+AAuQFFAOv9EgGAAUG+uPzDs/n8SAAAAAAA="},"packages/frontend/editor-ui/src/features/credentials/composables/useCredentialSharing.ts":{"9":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","12":"b:T+pt+AN+5/FA+v/H4mAI8H/+P7D/////AAAAAAA="},"packages/frontend/editor-ui/src/features/credentials/composables/useNodeCredentialOptions.ts":{"23":"b:TupF+ABuQlFAOv9FgGIAUH++PzDs/n8yAAAAAAA=","38":"b:RsoFoABKQhFACCAAACAAUAeKADCEABciAAAAAAA=","39":"b:RsoFoABuQhFACCAAACAAUAeKADCEABciAAAAAAA=","44":"b:TupF+ABuQlFAOv9FgGAAUH++PzDs/n8yAAAAAAA=","51":"b:TupF+ABuQlFAOv9FgGAAUH++PzDs/n8yAAAAAAA=","52":"b:RsoFoABuQhFACCAAACAAUAeKADCEABciAAAAAAA=","58":[46],"59":[46],"62":"b:RsoFoABuQhFACCAAACAAUAeKADCEABciAAAAAAA=","65":"b:RsoFoABuQhFACCAAACAAUAeKADCEABciAAAAAAA=","71":[46],"74":"b:RgIFgABsQAFAAAAAAAAAAACAADAAAAAAAAAAAAA=","81":"b:RgIFgABsQAFAAAAAAAAAAACAADAAAAAAAAAAAAA=","84":[42,9,45,46],"90":"b:RsoF4ABuQhFAGCEEgGAAUAeKCjCkFhciAAAAAAA=","108":"b:RsoFIABqQBFACCAAACAAUAeKADCEABciAAAAAAA=","119":[109,9,46,54,56,16],"127":"b:RsoFIABKQBFACCAAACAAUAeKADCEABciAAAAAAA=","140":"b:RsoFoABuQhFACCAAACAAUAeKADCEABciAAAAAAA=","152":"b:AAIBIABKABBAACAAAAAAUAAIADAAABcCAAAAAAA=","157":"b:RsoFoABuQhFACCAAACAAUAeKADCEABcCAAAAAAA=","166":"b:RgIFgABsQAFAAAAAAAAAAACAADAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/credentials/composables/useUnusableWorkflowCredentials.ts":{"15":[46],"33":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","40":[46],"54":"b:D+pt+AN+5/FA+v/H4mAI8H/+P7D/////AAAAAAA=","57":[46],"64":"b:D+pt+AN+5/FA+v/H4mAI8H/+P7D/////AAAAAAA=","66":[46],"68":[46],"70":"b:D+pt+AN+5/FA+v/H4mAI8H/+P7D/////AAAAAAA="},"packages/frontend/editor-ui/src/features/credentials/credentials.api.ts":{"26":"b:f+rv+QN+5/lW+v/H4+gL8n/+//L8////AAAAAAA=","44":"b:f+rv+QN+5/lW+v/H4+gL8n/+//L8////AAAAAAA=","48":"b:BgIBIABoABBCAAACAIAAAAKAAEAAAAQAAAAAAAA=","71":"b:AAIAIIDpABx2AEALGBACAgAAAGIAAADAAAAAAAA=","87":[46],"101":"b:f+rv+QN+5/FA+v/H4uAJ8n/+P7D8////AAAAAAA=","110":"b:BgIBAABoABBCAAACAIAAAACAAEAAAAQAAAAAAAA=","117":[9,46],"121":[46],"125":[46],"129":[113,9,45,46,158,70],"142":[31,5,113,9,45,46,89],"152":[46,89],"163":[46,178],"173":[1,2,43,111,113,9,46,60,143,158,70,16,89],"190":[46],"213":[46],"220":[46]},"packages/frontend/editor-ui/src/features/credentials/credentials.store.ts":{"46":"b:f+rv+QN+5/FA+v/H4uAJ8n/+P7D8////AAAAAAA=","49":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","71":"b:AsIFqABIQAEAOBIEgEAAAAACJADkIgMCAAAAAAA=","82":[31,46],"86":[31,46],"96":[46],"100":"b:f+rv+QN+5/lW+v/H4+gL8n/+//L8////AAAAAAA=","101":"b:f+rv+QN+5/FC+v/HwuAL8H/+P/D8////AAAAAAA=","106":"b:dgKHoYDt4B9iEkALGpAHAsCBAHAkAQbBAAAAAAA=","107":"b:QgIDAABEQAlAAEACAAADAECAAEAAAABBAAAAAAA=","110":"b:dgKHgQBM4BFAAgACAoADAECAADAAAAQAAAAAAAA=","113":"b:dgKHgQBM4BFAAgACAoADAECAADAAAAAAAAAAAAA=","115":"b:dgIHgABM4AFAAgACAIADAECAADAAAAAAAAAAAAA=","124":"b:RsoFoABuQhFACCAAACAAUAeKADCEABciAAAAAAA=","132":[1,42,9,46,124,54,137,143,70,167],"138":[1,2,43,9,46,143,16,178],"139":[1,2,43,9,46,143,16,178],"143":[1,2,43,9,46,143,16],"147":[46],"155":"b:furF+QBu4llCOv9HguIDUH++P3Ds/n+yAAAAAAA=","156":"b:furF+QBu4llCOv9HguIDUH++P3Ds/n+yAAAAAAA=","159":"b:dgIHoABs4BFCAgACAIADAEKAAHAEAAQgAAAAAAA=","160":"b:dgIHoABs4BFCAgACAIADAEKAAHAEAAQgAAAAAAA=","163":[1,2,43,6,9,45,46,56,143,16,178],"164":[1,2,43,6,9,45,46,56,143,16,178],"170":"b:dgKHgQBM4BFAAgACAoADAECAADAAAAQAAAAAAAA=","171":"b:dgKHgQBM4BFAAgACAoADAECAADAAAAQAAAAAAAA=","176":[46],"177":[46],"181":[46],"183":"b:BgIBgABoABBAAAACAIACAACAAEAAAAAAAAAAAAA=","184":"b:BgIBgABoABBAAAACAIACAACAAEAAAAAAAAAAAAA=","194":[9,45,46,89],"197":[9,45,46,89],"200":[9,45,46,89],"208":[42,9,46],"209":[42,9,46],"215":[42,9,46],"239":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","240":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","257":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","258":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","265":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","266":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","277":"b:f+rv+QN+5/lW+v/H4+AL8H/+f/L8////AAAAAAA=","278":"b:f+rv+QN+5/lW+v/H4+AL8H/+f/L8////AAAAAAA=","288":[46],"289":[46],"296":"b:f+rv+YP/5/1W+v/P6vAL8n/+P/L8////AAAAAAA=","297":"b:diIHgABs4BlGAkACAMADEHD2LvCINIBNAAAAAAA=","308":"b:BgIBAABoABBCAAACAIACAACAAEAAAAQAAAAAAAA=","321":"b:f+rv+QN+5/lW+v/H4+gL8n/+//L8////AAAAAAA=","329":"b:AAIAIIDpABx2AEALGBACAgAAAGIAAADAAAAAAAA=","361":"b:f+rv+QN+5/FA+v/H4uAJ8n/+P7D8////AAAAAAA=","387":"b:diIHgABs4AFAAkACAMABEHD2LrCINIBNAAAAAAA=","404":[46],"415":[46],"416":[46],"422":[31,5,113,9,45,46,89],"430":"b:TupF+ABuQlFAOv9FgGIAUH++PzDs/n8yAAAAAAA=","443":"b:BgIBAABoABBCAAACAIAAAACAAEAAAAQAAAAAAAA=","485":[113,9,45,46,158,70],"503":[9,46],"512":[46],"517":[46],"526":[46],"543":[46,178],"547":[46,89],"551":[1,2,43,111,113,9,46,60,143,158,70,16,89],"575":"b:BgIBIABoABBCAAACAIAAAAKAAEAAAAQAAAAAAAA=","596":[46],"605":[46,158,70],"615":[46,158,70],"627":[46],"633":[46],"698":"b:IAB4gABABwAAAAACAwjyBwAAAAAAAAAAAAAAAAA=","707":[31,5,113,46,19,48,21,49,22,50,121,89],"709":[31,5,113,46,19,48,21,49,22,50,89]},"packages/frontend/editor-ui/src/features/credentials/credentials.utils.ts":{"21":"b:RsoF+ABqAgFACHABAGAAUBeaOBCkABciAAAAAAA=","37":"b:RsoFoABqAgFACCAAACAAUAeKABCEABciAAAAAAA=","40":[9,46,70]},"packages/frontend/editor-ui/src/features/credentials/gatewayCreditsPromotion/useGatewayCreditsPromotion.ts":{"7":[46],"16":"b:DupFeABuQFFCOv9GgOIC0G+uP3Ds/n8SAAAAAAA=","26":"b:DupFeABuQFFCOv9GgOIC0G+uP3Ds/n8SAAAAAAA=","39":"b:DupFeABuQFFCOv9GgOIC0G+uP3Ds/n8SAAAAAAA=","48":[46],"53":[46],"57":"b:DupFeABuQFFCOv9GgOIC0G+uP3Ds/n8SAAAAAAA="},"packages/frontend/editor-ui/src/features/credentials/quickConnect/components/QuickConnectButton.vue":{"9":"b:BgoBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","35":"b:BgoBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","44":"b:BgoBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","48":[46],"49":"b:BgoBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","54":[46],"63":[46],"64":"b:BgoBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA="},"packages/frontend/editor-ui/src/features/credentials/quickConnect/composables/useQuickConnect.ts":{"20":"b:TupF+ABuQlFCOv9GgOIC0G+u/3Ds/n8SAAAAAAA=","35":"b:DupF+ABuQlFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","43":"b:BAIBIABKQAFAOpJAgAAAkAMgwBDkIB8CAAAAAAA=","53":"b:BsoBoABKAhAACCAAACAAUAeKAACEABcCAAAAAAA=","66":"b:BAIBIABKQAFAOpJAgAAAkAMgwBDkIB8CAAAAAAA=","73":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","86":[46],"87":[46],"89":[46],"91":[46],"92":[46],"97":[46],"101":[46],"106":[46],"119":"b:TupF+ABuQFFCOv9GgOAC0G+uf3Ds/n8SAAAAAAA=","120":[46],"129":[46],"135":[46],"143":[46]},"packages/frontend/editor-ui/src/features/execution/executions/components/ExecutionStopAllText.vue":{"11":[1,62,169,170,79,18,186,187,188],"18":[1,62,169,170,79,18,186,187,188],"25":[1,62,169,170,79,18,186,187,188]},"packages/frontend/editor-ui/src/features/execution/executions/components/ExecutionsFilter.vue":{"42":[1,62,169,170,79,18,186,187,188],"64":[186],"67":[186],"69":[1,62,169,170,79,18,186,187,188],"87":[186],"104":[186],"113":[186],"120":[186],"127":[186],"139":[186],"155":[1,62,169,170,79,18,186,187,188],"200":[186],"214":[1,62,169,170,79,18,186,187,188],"217":[1,62,169,170,79,18,186,187,188],"228":[1,62,169,170,79,18,186,187,188],"244":[186],"251":[186],"284":[186],"336":[186],"348":[186],"357":[186],"359":[186],"362":[186],"394":[186],"413":[186],"439":[186],"461":[186],"485":[186]},"packages/frontend/editor-ui/src/features/execution/executions/components/workflow/WorkflowExecutionsInfoAccordion.vue":{"58":[1,62,169,170,79,18,186,187,188],"78":[1,62,169,170,79,18,186,187,188],"88":[1,62,169,170,79,18,186,187,188],"96":[1,62,169,170,79,18,186,187,188],"109":[1,62,169,170,79,18,186,187,188],"110":[1,62,169,170,79,18,186,187,188],"119":[187],"123":[1,62,169,170,79,18,186,187,188],"130":[1,62,169,170,79,18,186,187,188]},"packages/frontend/editor-ui/src/features/execution/executions/components/workflow/WorkflowExecutionsLandingPage.vue":{"22":[1,169,170,79,18,186,187,188],"25":[1,169,170,79,18,186,187,188],"27":[187],"45":[187],"48":[187],"56":[1,169,170,79,18,186,187,188]},"packages/frontend/editor-ui/src/features/execution/executions/components/workflow/WorkflowExecutionsList.vue":{"12":[1,62,169,170,79,18,186,187,188],"42":[1,62,169,170,79,18,186,187,188],"43":[62,169,170,79,18,186,187,188],"48":[1,62,169,170,79,18,186,187,188],"52":[170],"73":[1,169,187,188],"81":[1,62,169,170,79,18,186,187,188],"92":[18],"94":[186]},"packages/frontend/editor-ui/src/features/execution/executions/components/workflow/WorkflowExecutionsSidebar.vue":{"26":[1,62,169,170,79,18,186,187,188],"63":[79,187],"70":[1,62,169,170,79,18,186,187,188],"79":[62,169,170,79,18,186,187,188],"83":[1,62,169,170,79,18,186,187,188],"87":[1,62,169,170,79,18,186,187,188],"97":[1,62,169,170,79,18,186,187,188],"98":[62,169,170,79,18,186,187,188],"107":[62,169,170,79,18,186,187,188],"116":[62,169,170,79,18,186,187,188],"125":[62,169,170,79,18,186,187,188],"136":[186],"143":[18],"147":[169,186],"169":[1,62,169,170,79,18,186,187,188],"176":[1,62,169,170,79,18,186,187,188],"219":[1,62,169,170,79,18,186,187,188],"224":[170,186],"232":[1,62,169,170,79,18,186,187,188],"235":[62,169,170,79,18,186,187,188]},"packages/frontend/editor-ui/src/features/execution/executions/composables/useExecutionData.ts":{"8":"b:CABEGAAAQEEAADwEgEAAAGwEIABA1msQAAAAAAA=","10":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","14":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","18":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA="},"packages/frontend/editor-ui/src/features/execution/executions/composables/useExecutionHelpers.ts":{"19":"b:CgBEAAFAQEEAgD4EgEIAAGwEIQDA9mscAAAAAAA=","24":[46,62,169,170,79,18,186,187,188],"69":[46,62,169,170,79,18,186,187,188],"74":[46,62,169,170,79,18,186,187,188],"78":[46],"87":[46,181,182],"107":[46]},"packages/frontend/editor-ui/src/features/execution/executions/composables/useExecutionRedaction.ts":{"13":"b:DupFeAFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","22":[32,1,2,3,46,62,144,18,188],"26":[32,1,2,3,46,144,18,188],"28":[46,62],"30":[46,62],"34":[46]},"packages/frontend/editor-ui/src/features/execution/executions/executions.store.ts":{"33":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","46":[1,46,62,169,170,79,18,186,187,188],"55":[46],"70":[1,46,62,169,170,79,18,186,187,188],"78":[1,46,62,169,170,79,18,186,187,188],"79":[46,62,169,170,79,18,186,187,188],"89":[46],"95":[46],"108":[1,46,62,169,170,79,18,186,187,188],"116":[1,46,62,169,170,79,18,186,187,188],"117":[46],"126":[46],"128":[46,62,169,170,79,18,186,187,188],"138":[46],"145":[46,170],"150":[46,186],"154":[46,186],"158":[1,46,62,169,170,79,18,186,187,188],"162":[1,46,62,169,170,79,18,186,187,188],"171":[1,46,62,169,170,79,18,186,187,188],"186":[1,46,62,169,170,79,18,186,187,188],"214":[46,62,169,170,79,18,186,187,188],"245":[1,46,62,169,170,79,18,186,187,188],"250":[46,79,187],"255":[46],"259":[25,46,62,169,170,79,18,186,187,188],"273":[1,46,62,169,170,79,18,186,187,188],"279":[46],"287":[1,46,62,169,170,79,18,186,187,188],"292":[1,46,62,169,170,79,18,186,187,188],"299":[46],"340":[46],"351":[46,170,18],"359":[46],"373":[46,170],"387":[46],"395":[1,46,169,186,187,188],"406":[1,46,169,186,187,188]},"packages/frontend/editor-ui/src/features/execution/executions/executions.utils.ts":{"50":[1,46,62,169,170,79,18,186,187,188],"53":[46,62,169,170,79,18,186,187,188],"56":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","69":[1,46,62,169,170,79,18,186,187,188],"127":[90,103,46,115,54],"140":"b:DyBEGAFw5WEAsD5EgEAIAHwmJQBC9mscAAAAAAA=","142":"b:DyBEWAFw5GEAsD5EgEAIAHwmJQBC9mscAAAAAAA=","193":[46,18],"250":"b:DiBEGgFAQEEAID4EgEAAAGwmJQBA9msQAAAAAAA=","251":"b:DiBEGgFAQEEAID4EgEAAAGwmJQBA9msQAAAAAAA=","259":"b:DiBEGgFAQEEAID4EgEAAAGwmJQBA9msQAAAAAAA=","268":"b:DiBEGgFAQEEAID4EgEAAAGwmJQBA9msQAAAAAAA=","269":"b:DiBEGgFAQEEAID4EgEAAAGwmJQBA9msQAAAAAAA=","272":[46],"327":"b:DyBEGAFw5WEAsD5EAEAAAHwmJQBA9mscAAAAAAA=","365":"b:BgAEGABAAAAAAAAAAAAAAAAgAAAAFgEMAAAAAAA=","414":"b:DyBEGgFw5WEAsD5EAEAAAHwmJQBA9mscAAAAAAA=","431":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","445":[31,46,176],"452":[31,46,134,170,172,176,177],"458":"b:C6Jt+AB+5/FA+v9HgmMI8H8+PrDs/3//AAAAAAA=","464":[46],"500":[46],"522":[46]},"packages/frontend/editor-ui/src/features/execution/executions/views/WorkflowExecutionsView.vue":{"36":[1,62,169,170,79,18,186,187,188],"40":[1,62,169,170,79,18,186,187,188],"45":[1,62,169,170,79,18,186,187,188],"54":[1,62,169,170,79,18,186,187,188],"55":[62,169,170,79,18,186,187,188],"73":[1,62,169,170,79,18,186,187,188],"77":[1,62,169,170,79,18,186,187,188],"84":[1,62,169,170,79,18,186,187,188],"86":[169,170,79,18,186,187,188],"91":[1,62,169,170,79,18,186,187,188],"102":[1,169,187,188],"107":[1,62,169,170,79,18,186,187,188],"133":[62],"141":[1,62,169,170,79,18,186,187,188],"153":[1,62,169,170,79,18,186,187,188],"165":[18],"200":[186],"228":[170],"234":[170],"305":[79,187],"311":[1,62,169,170,79,18,186,187,188],"317":[79,187]},"packages/frontend/editor-ui/src/features/execution/logs/components/ChatMessagesPanel.vue":{"30":[32,1,2,3,9,11,63,142,143,144,14,161,18,15],"57":[32,1,2,3,142,144,161,18],"61":[32,1,2,3,9,11,63,142,143,144,14,161,18,15],"67":[32],"76":[32,1,2,3,142,144,161,18],"96":[32,1,2,3,142,144,161,18],"105":[32,1,2,3,9,11,63,142,143,144,14,161,18,15],"107":[32,1,2,3,142,144,161,18],"117":[32,1,2,3,9,11,63,142,143,144,14,161,18,15],"135":[32,1,2,3,9,11,63,142,143,144,14,161,18,15],"137":[32,1,2,3,9,11,63,142,143,144,14,161,18,15],"154":[32,1,2,3,9,11,63,142,143,144,14,161,18,15],"166":[32,1,2,3,9,11,63,142,143,144,14,161,18,15],"182":[32,1,2,3,9,11,63,142,143,144,14,161,18,15],"190":[32,1,3,18],"193":[32,1,2,3,9,11,63,142,143,144,14,161,18,15],"208":[32,1,2,3,9,11,63,142,143,144,14,161,18,15],"214":[32,1,2,3,9,11,63,142,143,144,14,161,18,15],"221":[32,1,2,3,9,11,63,142,143,144,14,161,18,15],"227":[32,1,2,3,9,11,63,142,143,144,14,161,18,15]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogDetailsPanel.vue":{"41":[32,1,2,3,144,18,188],"79":[32,1,2,3,144,18,188],"80":[32,1,2,3,144,18,188],"81":[32,1,2,3,144,18,188],"86":[32,1,2,3,144,18,188],"93":[32,1,2,3,144,18,188],"94":[32,1,18],"102":[32,1,2,3,144,18,188],"103":[32,1,2,3,144,18,188],"104":[32,1,2,3,144,18,188],"110":[1,18],"114":[1,18],"122":[1,18],"123":[32,1,2,3,144,18,188],"138":[32,1,2,3,144,18,188],"149":[32,1,2,3,144,18,188],"163":[32,1,2,3,144,18,188],"178":[32,1,2,3,144,18,188],"184":[32,1,2,3,144,18,188],"191":[32,1,2,3,144,18,188],"197":[32,1,2,3,144,18,188],"225":[1,18]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsOverviewPanel.vue":{"39":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","51":[32,1,2,3,48,22,50,142,144,161,18,188],"52":[32,1,2,3,48,22,50,144,161,18,188],"57":[32,1,2,3,48,22,50,144,161,18,188],"59":[32,1,2,3,48,22,50,144,161,18,188],"67":[32,1,2,3,48,22,50,144,161,18,188],"72":[32,1,2,3,48,22,50,144,161,18,188],"75":[32,1,2,3,48,22,50,144,161,18,188],"80":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","94":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","98":"b:DyBEGAEw5WEAsD5EAEAAAHwmJQBA9mscAAAAAAA=","107":"b:DyBEGAEw5WEAsD5EAEAAAHwmJQBA9mscAAAAAAA=","125":[32,1,2,3,48,22,50,142,144,161,18,188],"161":[18],"162":[32,18]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsOverviewRow.vue":{"57":[25,32,1,2,3,48,22,50,144,161,18,188],"58":[25,32,1,2,3,48,22,50,144,161,18,188],"59":[25,32,1,2,3,48,22,50,144,161,18,188],"60":[25,32,1,2,3,48,22,50,144,161,18,188],"61":[25,32,1,2,3,48,22,50,144,161,18,188],"64":[25,32,1,2,3,48,22,50,144,161,18,188],"73":[25,32,1,2,3,48,22,50,144,161,18,188],"76":[25,32,1,2,3,48,22,50,144,161,18,188],"79":[32,1,2,3,48,22,50,144,161,18],"80":[25,32,1,2,3,48,22,50,144,161,18,188],"83":[32,1,2,3,48,22,50,144,161,18],"93":[32,1,2,3,48,22,50,144,161,18],"96":[32,1,2,3,48,22,50,144,161,18],"109":[32,1,2,3,48,22,50,144,161,18],"112":[32,1,2,3,48,22,50,144,161,18],"136":[32,1,2,3,48,22,50,144,161,18],"140":[25,32,1,2,3,48,22,50,144,161,18,188],"144":[25,32,1,2,3,48,22,50,144,161,18,188],"161":[25,32,1,2,3,48,22,50,144,161,18,188],"162":[25,32,1,2,3,48,22,50,144,161,18,188],"164":[25,32,1,2,3,48,22,50,144,161,18,188],"198":[1,2,18],"224":[32,1,2,3,48,22,50,144,161,18],"225":[32,1,2,3,48,22,50,144,161,18],"227":[32,1,2,3,48,22,50,144,161,18],"233":[32,1,2,3,48,22,50,144,161,18],"243":[32,1,2,3,48,22,50,144,161,18],"271":[32,1,2,3,48,22,50,144,161,18,188],"294":[32,1,2,3,48,22,50,144,161,18,188]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsOverviewRows.vue":{"44":[32,1,2,3,48,22,50,144,161,18,188],"45":[32,1,2,3,48,22,50,144,161,18,188],"51":[32,1,2,3,48,22,50,144,161,18,188],"55":[32,1,2,3,48,22,50,144,161,18,188],"59":[18],"79":[32,1,2,3,48,22,50,144,161,18,188],"80":[32,1,2,3,48,22,50,144,161,18,188],"81":[32,1,2,3,48,22,50,144,161,18,188],"91":[32,1,2,3,48,22,50,144,161,18,188],"93":[32,1,2,3,48,22,50,144,161,18,188],"94":[32,1,2,3,48,22,50,144,161,18,188],"99":[32,1,2,3,144,18,188],"110":[32,1,2,3,48,22,50,144,161,18,188],"127":[18],"128":[18],"129":[32,18]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsPanel.vue":{"21":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","31":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","68":[32,1,2,3,144,18,188],"71":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","72":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","75":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","84":[32,1,2,3,144,18,188],"89":[32,1,2,3,144,18,188],"95":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","134":[18],"141":[18],"163":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","192":[32,1,2,3,9,11,63,142,143,144,14,161,18,15],"217":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","261":[32,1,2,3,144,18,188]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsPanelActions.vue":{"20":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","27":[32,1,2,3,48,22,50,142,144,161,18,188],"29":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","30":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","33":[32,1,2,3,48,22,50,142,144,161,18,188],"51":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","58":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","77":[18],"84":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA="},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsPanelHeader.vue":{"8":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","10":[32,1,142,18,188],"13":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","20":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA="},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsViewExecutionSummary.vue":{"18":[32,1,2,3,48,22,50,144,161,18,188],"20":[32,1,2,3,48,22,50,144,161,18,188],"37":[32,1,2,3,48,22,50,144,161,18,188]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsViewKeyboardEventListener.vue":{"8":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","11":"b:AoIl2AAKAAAAeFADAEAAEBGSPCA2qsP/AAAAAAA=","24":[161],"27":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA="},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsViewNodeName.vue":{"12":[25,32,1,2,3,48,22,50,144,161,18,188],"18":[25,32,1,2,3,48,22,50,144,161,18,188]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsViewRunData.vue":{"43":[32,1,2,3,144,18,188],"55":[32,1,2,3,144,18,188],"58":[32,1,2,3,144,18,188],"81":[32,1,2,3,144,18,188],"92":[1,18],"94":[32,1,2,3,144,18,188],"124":[32,1,2,3,144,18,188],"126":[32,1,2,3,144,18,188],"130":[32,1,2,3,144,18,188],"137":[1,18],"141":[18],"143":[18]},"packages/frontend/editor-ui/src/features/execution/logs/composables/useChatState.ts":{"41":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","59":[32,1,2,3,142,144,161,18],"60":[18],"63":[32,1,2,3,142,144,161,18],"66":[32,1,2,3,9,11,63,142,143,144,14,161,18,15],"74":[32,1,2,3,9,11,63,142,143,144,14,161,18,15],"101":[32,1,2,3,9,11,63,142,143,144,14,161,18,15],"120":[32,1,2,3,9,11,63,142,143,144,14,161,18,15],"125":[32,1,2,3,9,11,63,142,143,144,14,161,18,15],"130":[32,1,2,3,9,11,63,142,143,144,14,161,18,15],"135":[32,1,2,3,142,144,161,18],"149":[32,1,2,3,142,144,161,18],"165":[32,1,2,3,144,161,18],"230":[32,1,2,3,142,144,161,18],"276":[32,1,2,3,144,161,18],"290":[32,1,2,3,144,161,18],"321":[18],"329":[32,1,3,60,161,18],"350":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","351":"b:D+oF+AM+4PFA+v/HwmAI8H/+P7D+////AAAAAAA=","362":[32,1,2,3,9,11,63,142,143,144,14,161,18,15]},"packages/frontend/editor-ui/src/features/execution/logs/composables/useClearExecutionButtonVisible.ts":{"8":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","13":"b:D+pt+AE+5/FA+v9HgmAI8H/+P7Ds/3//AAAAAAA=","14":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D8////AAAAAAA=","15":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","17":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D8////AAAAAAA=","18":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D8////AAAAAAA=","20":"b:D+pt+AE+5/FA+v9HgmAI8H/+P7D8/3//AAAAAAA=","21":"b:D+pt+AE+5/FA+v9HgmAI8H/+P7Ds/3//AAAAAAA=","24":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA="},"packages/frontend/editor-ui/src/features/execution/logs/composables/useLogsExecutionData.ts":{"36":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","42":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","49":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","56":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","63":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","64":"b:DyBEWAEw5WEAsD5EgEAIAHwmJQBC9mucAAAAAAA=","79":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","89":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","94":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","118":"b:D+oF+AM+4PFA+v/HwmAI8H/+P7D+////AAAAAAA=","157":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","158":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","159":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","160":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","161":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","163":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","187":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","188":"b:D+oF+AM+4PFA+v/HwmAI8H/+P7D+////AAAAAAA=","197":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","207":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA="},"packages/frontend/editor-ui/src/features/execution/logs/composables/useLogsPanelLayout.ts":{"25":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","41":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","44":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","48":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","63":[32,1,2,3,9,11,63,142,143,144,14,161,18,15],"74":"b:DsoEAAEAAIAAAAAAAAAAAADAAQACAAAQAAAAAAA=","84":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","89":[32,1,2,3,144,18,188],"90":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","91":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","93":[32,1,142,18,188],"118":[32,1,142,18,188],"147":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","170":"b:AgAMAAAABAAAiEAAAAAAAAAAAAAABwAdAAAAAAA="},"packages/frontend/editor-ui/src/features/execution/logs/composables/useLogsSelection.ts":{"25":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","34":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","35":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","43":[32,18],"58":[32,18],"116":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","127":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","156":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","162":[1,2,3,144,18,188],"183":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","222":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","224":[32,1,2,3,144,18,188],"229":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","230":[1,2,18]},"packages/frontend/editor-ui/src/features/execution/logs/composables/useLogsTreeExpand.ts":{"15":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","19":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","23":[1,18]},"packages/frontend/editor-ui/src/features/execution/logs/composables/usePopOutWindow.ts":{"77":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","88":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","89":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","90":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","93":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","171":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","180":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","185":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","194":"b:AgAMAAAABAAAiEAAAAAAAAAAAAAABwAdAAAAAAA=","199":"b:AgAMAAAABAAAiEAAAAAAAAAAAAAABwAdAAAAAAA="},"packages/frontend/editor-ui/src/features/execution/logs/logs.types.ts":{"55":[25,32,1,2,3,48,22,50,144,161,18,188],"59":[25,32,1,2,3,48,22,50,144,161,18,188]},"packages/frontend/editor-ui/src/features/execution/logs/logs.utils.ts":{"45":[25,32,1,2,3,48,22,50,144,161,18,188],"46":[25,32,1,2,3,48,22,50,144,161,18,188],"60":[25,32,1,2,3,48,22,50,144,161,18,188],"68":[25,32,1,2,3,48,22,50,144,161,18,188],"93":[25,32,1,2,3,48,22,50,144,161,18,188],"124":[1,2,18],"132":[1,2,18],"133":[1,2,18],"137":[1,2,18],"158":[25,32,1,2,3,48,22,50,144,161,18,188],"176":[25,32,1,2,3,48,22,50,144,161,18,188],"180":[25,32,1,2,3,48,22,50,144,161,18,188],"186":[25,32,1,2,3,48,22,50,144,161,18,188],"274":"b:DyBEGAEw5WEAsD5EAEAAAHwmJQBA9mscAAAAAAA=","275":[32,1,2,144,18,188],"281":[32,1,144,18,188],"298":[25,32,1,2,3,48,22,50,144,161,18,188],"304":[25,32,1,2,3,48,22,50,144,161,18,188],"320":[25,32,1,2,3,48,22,50,144,161,18,188],"333":[1,2,18],"351":[25,32,1,2,3,48,22,50,144,161,18,188],"367":[25,32,1,2,3,48,22,50,144,161,18,188],"513":[25,32,1,2,3,48,22,50,144,161,18,188],"575":[25,32,1,2,3,48,22,50,144,161,18,188],"602":"b:D+pFeAE+5fFA+v9HgGAA8H++PzD8/n8/AAAAAAA=","621":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","632":[32,1,2,3,144,18,188],"657":"b:D+pt+gM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","673":[25,32,1,2,3,48,22,50,144,161,18,188],"692":[25,32,1,2,3,48,22,50,144,161,18,188],"714":[32,1,2,3,48,22,50,144,161,18,188],"728":[32,1,2,3,48,22,50,144,161,18,188],"733":[32,1,2,3,48,22,50,144,161,18],"738":[32,1,2,3,48,22,50,144,161,18],"748":[18],"750":[32,1,2,3,48,22,50,144,161,18],"773":[25,32,1,2,3,48,22,50,144,161,18,188],"777":[25,32,1,2,3,48,22,50,144,161,18,188],"788":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","791":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","811":[32,18],"823":[18],"834":[18],"859":[18],"911":[18],"918":[18],"930":[18],"993":[32,1,2,3,144,18,188],"1002":[32,1,2,3,144,18,188],"1012":"b:DyBEWAEw5WEAsD5EgEAIAHwmJQBC9mucAAAAAAA=","1020":"b:DyBEWAEw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA="},"packages/frontend/editor-ui/src/features/integrations/externalSecrets.ee/externalSecrets.ee.store.ts":{"21":[46,65],"24":[46,65],"28":[46,65],"61":"b:TupF+ABuQllWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","67":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","79":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","85":[46],"93":[46,65],"94":[46,65],"95":[46],"96":[46],"98":[46,65],"101":[46,65],"102":[46,65],"119":[46],"132":[46],"142":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","156":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","182":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","201":[46],"217":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","224":[46],"233":[46],"239":[46],"247":[46],"253":[46],"263":[46],"264":[46],"279":[46],"287":[46],"295":[46]},"packages/frontend/editor-ui/src/features/integrations/logStreaming.ee/module.descriptor.ts":{"9":[46,66,153,68],"10":[46],"11":[46],"30":"b:f+r/+4P/5/92+v/v+/j////////8////AAAAAAA=","35":"b:f+r/+4P/5/92+v/v+/j////////8////AAAAAAA="},"packages/frontend/editor-ui/src/features/integrations/sourceControl.ee/sourceControl.api.ts":{"22":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","24":[46,99],"30":[46],"37":[46],"44":[46,99],"53":[46,99],"61":[46],"65":[46],"76":[46],"87":[46],"96":[46]},"packages/frontend/editor-ui/src/features/integrations/sourceControl.ee/sourceControl.store.ts":{"14":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","18":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","24":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","45":[46],"58":[46],"62":[46,99],"66":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","68":[46,99],"73":[46,99],"78":[46,99],"87":[46],"102":[46],"112":[46],"116":[46],"124":[46]},"packages/frontend/editor-ui/src/features/ndv/agents/composables/useInlineAgentConfig.ts":{"38":[46],"65":[46],"69":[46],"70":[46],"85":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","89":[46],"99":[46],"106":[46],"109":[46],"115":[46],"124":[46],"135":[46],"149":[46],"170":[46],"175":[46],"201":[46]},"packages/frontend/editor-ui/src/features/ndv/agents/composables/useNdvAgentConfig.ts":{"28":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","33":[46],"35":[46],"42":[46]},"packages/frontend/editor-ui/src/features/ndv/agents/composables/useReferencedAgentSummary.ts":{"23":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","29":[46],"32":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","36":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","56":[46],"59":[46],"80":[46],"87":[46],"95":[46],"112":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","131":[46],"138":"b:AgAMAABABBAAiEAAAAAAAAAAAAAABwCdAAAAAAA=","145":[46],"163":[46]},"packages/frontend/editor-ui/src/features/ndv/panel/components/InputPanel.vue":{"60":"b:DupFeABuQFFAOv9EgGAAUE+uPzDs/n8SAAAAAAA=","108":"b:DupFeABuQFFAOv9EgGAAUE+uPzDs/n8SAAAAAAA=","114":"b:DupFeABuQFFAOv9EgGAAUE+uPzDs/n8SAAAAAAA=","118":[46],"122":"b:DupFeABuQFFAOv9EgGAAUE+uPzDs/n8SAAAAAAA=","126":"b:DuoFeABuQBFAOv9EgGAAUA+OHzDsej8CAAAAAAA=","132":[46],"143":"b:DupFeABuQFFAOv9EgGAAUE+uPzDs/n8SAAAAAAA=","145":"b:DupFeABuQFFAOv9EgGAAUE+uPzDs/n8SAAAAAAA=","154":"b:DupFeABuQFFAOv9EgGAAUE+uPzDs/n8SAAAAAAA=","178":"b:DspFeABuQFFAOv9EgGAAUE+uPzDs/n8SAAAAAAA=","179":[1,46,16],"183":"b:DupFeABuQFFAOv9EgGAAUE+uPzDs/n8SAAAAAAA=","191":"b:DupFeABuQFFAOv9EgGAAUE+uPzDs/n8SAAAAAAA=","207":"b:AAAAGABAAAAAAD4AAEAAAAwEAABA8CsAAAAAAAA=","216":"b:DuoFeABuQBFAOv9EgGAAUA+OHzDsej8CAAAAAAA=","221":"b:DupFeABuQFFAOv9EgGAAUE+uPzDs/n8SAAAAAAA=","236":"b:DupFeABuQFFAOv9EgGAAUE+uPzDs/n8SAAAAAAA=","237":"b:DspFeABuQFFAOv9EgGAAUE+OPzDs/n8SAAAAAAA=","240":"b:DupFeABuQFFAOv9EgGAAUE+uPzDs/n8SAAAAAAA=","247":"b:DspFeABuQFFAOv9EgGAAUE+OPzDs/n8SAAAAAAA=","251":"b:DupFeABuQFFAOv9EgGAAUE+uPzDs/n8SAAAAAAA=","252":"b:DspFeABuQFFAOv9EgGAAUE+OPzDs/n8SAAAAAAA=","258":"b:DupFeABuQFFAOv9EgGAAUE+uPzDs/n8SAAAAAAA=","263":[46],"277":"b:DsoFeABuQBFAOvdEgGAAUA+MHzDkMh8CAAAAAAA=","282":"b:DupFeABuQFFAOv9EgGAAUE+uPzDs/n8SAAAAAAA=","299":"b:AEABAABAQAEAAC4AgAAAAAAAAAAIYAoAAAAAAAA=","302":[103,46,54,56,81,82,173,174,16,177,179],"312":"b:DspFeABuQFFAOv9EgGAAUE+uPzDs/n8SAAAAAAA=","321":[46],"325":[46],"332":[46,82],"345":"b:DupFeABuQFFAOv9EgGAAUE+uPzDs/n8SAAAAAAA=","349":[3,46,84],"353":"b:DuoFeABuQBFAOv9EgGAAUA+OHzDsej8CAAAAAAA=","357":[46,175],"361":[46,82,84,85],"370":[46,18,82,175,176,84,85],"374":[46,82,85],"375":[46,82,85],"379":[46],"391":"b:CKAFAABAAAAAEDQAAAAAAAAgAAAAgAUAAAAAAAA=","395":[46],"397":"b:DupFeABuQFFAOv9EgGAAUE+uPzDs/n8SAAAAAAA=","433":[46,13,18,82,175,176,84,85],"436":"b:DupFeABuQFFAOv9EgGAAUE+uPzDs/n8SAAAAAAA=","443":"b:DupFeABuQFFAOv9EgGAAUE+uPzDs/n8SAAAAAAA=","455":[46,13,18,82,175,176,84,85],"464":[2,9,46,13,143,16],"468":[2,9,46,13,143,16],"477":"b:DsoFeABuQBFAOvdEgGAAUA+sHzDkMh8CAAAAAAA=","484":[46],"511":"b:DsoFeABuQBFAOvdEgGAAUA+MHzDkMh8CAAAAAAA=","528":"b:DsoFeABuQBFAOvdEgGAAUA+MHzDkMh8CAAAAAAA=","545":[46],"554":[46],"556":[46],"560":[46],"572":[2,41,9,46,56,141,143,70,176,16,177,86],"575":[46],"577":[46],"592":[46],"594":[46],"598":[3,46],"602":[46],"604":[46],"608":[46,62],"618":[46]},"packages/frontend/editor-ui/src/features/ndv/panel/components/NDVEmptyState.vue":{"21":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA="},"packages/frontend/editor-ui/src/features/ndv/panel/components/NDVFloatingNodes.vue":{"13":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","18":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","30":[15],"37":"b:AoIBQAAKAAAAEF8AAAAAEAGEDCCk6A8AAAAAAAA=","51":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","53":"b:DupFeAAuQFFAOv9EgGIAUE+OPzDk/n8SAAAAAAA=","63":"b:DupFeAAuQFFAOv9EgGIAUE+OPzDk/n8SAAAAAAA=","66":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","95":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","99":"b:DuoFaAAiQBEAOn5EgAAAUCmoHyDk/lsSAAAAAAA=","105":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","122":[166,15],"123":"b:DupFeAAuQFFAOv9EgGIAUE+OPzDk/n8SAAAAAAA=","129":[166,167,15,179]},"packages/frontend/editor-ui/src/features/ndv/panel/components/NDVHeader.vue":{"27":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","34":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","62":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","64":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","70":[1,76,77,166],"72":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA="},"packages/frontend/editor-ui/src/features/ndv/panel/components/NDVSubConnections.vue":{"25":"b:DupFeABuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","57":"b:DupFeABuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","61":"b:DupFeABuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","66":[2,46,15],"72":[46],"84":[1,2,9,46,11,143,14,75,76,15,16],"87":[1,2,9,46,11,143,14,75,76,15,16],"99":[2,46,15],"110":[1,2,9,46,11,143,14,75,76,15,16],"127":[1,2,9,46,11,143,14,75,76,15,16],"131":[1,2,9,46,11,143,14,75,76,15,16],"133":[1,2,9,46,11,143,14,75,76,15,16],"137":[1,2,9,46,11,143,14,75,76,15,16],"145":[1,2,9,46,11,143,14,75,76,15,16],"152":[1,2,9,46,11,14,75,15,16],"161":[46],"167":[1,2,9,46,11,143,14,75,76,15,16],"169":[2,46,15],"183":[2,46,15],"186":[1,2,9,46,11,143,14,75,76,15,16],"193":"b:DspFeABuQFFAOv9EgGAAUE+uPzDk/n8SAAAAAAA=","201":"b:DupFeABuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","210":"b:DspFeABuQFFAOv9EgGAAUE+uPzDk/n8SAAAAAAA=","219":[46],"231":[46,15],"250":"b:AAAAGABAAAAAADwAAEAAACQEAABAUAsAAAAAAAA=","253":"b:AAAAGABAAAAAADwAAEAAACQEAABAUAsAAAAAAAA=","259":"b:DupFeABuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","260":"b:DupFeABuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","262":"b:DupFeABuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","274":"b:DupFeABuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","283":[1,2,9,46,11,143,14,75,76,15,16],"296":[1,2,9,46,11,14,75,15,16],"297":[1,2,9,46,11,143,14,75,76,15,16],"305":[46,15],"317":[46,15],"329":[46],"335":[1,2,9,46,11,143,14,75,76,15,16],"355":[2,46,15],"370":[46],"376":[2,46,15],"382":[46]},"packages/frontend/editor-ui/src/features/ndv/panel/components/OutputPanel.vue":{"34":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","85":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","86":"b:CABEGAAAQEEAADwEgEAAAGwEIABA1msQAAAAAAA=","111":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","115":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","123":"b:DuoFeAAuQBFAOv9EgGAAUC+uHzDkfj8CAAAAAAA=","127":"b:DuoFeAAuQBFAOv9EgGAAUC+uHzDkfj8CAAAAAAA=","135":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","154":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","157":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","161":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","169":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","171":"b:CABEGAAAQEEAADwEgEAAAGwEIABA1msQAAAAAAA=","179":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","181":"b:CABEGAAAQEEAADwEgEAAAGwEIABA1msQAAAAAAA=","189":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","193":"b:DuoFeAAuQBFAOv9EgGAAUC+uHzDkfj8CAAAAAAA=","197":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","238":[84],"242":[84],"261":[3,84,85,181],"266":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","279":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","285":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","316":"b:CABEAAAAQEEAAD4EgEIAAGwEIADA9msQAAAAAAA=","317":[82,175,84,85],"318":[175,84],"319":[167,170,84,85],"322":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","348":"b:DuoFeAAuQBFAOv9EgGAAUC+uHzDkfj8CAAAAAAA=","371":"b:BoIAKAACQAEAKI4AgCAAECAIAACgdBcCAAAAAAA=","379":"b:DuoFeAAuQBFAOv9EgGAAUA+uHzDkej8CAAAAAAA=","381":"b:DuoFeAAuQBFAOv9EgGAAUC+uHzDkfj8CAAAAAAA=","392":[1,2,9,11,126,131,13,143,146,14,18,15,16,85],"418":"b:DsoBeAAuQBFAOv9EgGAAUC+uHzDkfj8CAAAAAAA=","422":"b:DuoFeAAuQBFAOv9EgGAAUC+uHzDkfj8CAAAAAAA=","439":[18],"441":[18],"445":[3],"463":[62],"484":[3,18,84,85,181]},"packages/frontend/editor-ui/src/features/ndv/panel/components/PanelDragButton.vue":{"6":"b:DupFeAAuQFFAOv9EgGAAUE+uPzDk/n8SAAAAAAA=","22":"b:DupFeAAuQFFAOv9EgGAAUE+uPzDk/n8SAAAAAAA="},"packages/frontend/editor-ui/src/features/ndv/panel/composables/useNdvLayout.ts":{"21":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","29":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","35":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","37":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","41":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","45":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","46":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","51":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","53":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","81":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","117":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","195":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","202":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA="},"packages/frontend/editor-ui/src/features/ndv/parameters/components/AssignmentCollection/AssignmentCollection.vue":{"39":"b:AgBFCABAAFEAMFwAACAAAEAIJwAoXBMAAAAAAAA=","53":"b:AgBFCABAAFEAMFwAACAAAEAIJwAoXBMAAAAAAAA=","56":"b:AABFCABAAEAAABQAAAAAAEAIIQAIFAAAAAAAAAA=","72":"b:AABFCABAAEEAABwAACAAAEAIIQAIVAIAAAAAAAA=","77":"b:AgBFCABAAFEAMFwAACAAAEAIJwAoXBMAAAAAAAA=","78":"b:AgBFCABAAFEAMFwAACAAAEAIJwAoXBMAAAAAAAA=","79":[46],"82":[46],"85":[46],"90":[46,82],"91":"b:AgBFCABAAFEAMFwAACAAAEAIJwAoXBMAAAAAAAA=","92":"b:AgBFCABAAFEAMFwAACAAAEAIJwAoXBMAAAAAAAA=","107":"b:AgBFCABAAFEAMFwAACAAAEAIJwAoXBMAAAAAAAA=","108":[46],"116":"b:AgBFCABAAFEAMFwAACAAAEAIJwAoXBMAAAAAAAA=","117":[109,46,56,172,82,83,174,16,177],"119":[109,46,56,172,82,83,174,16,177],"129":[109,46,56,172,83,174,177],"138":[46],"150":[109,46,56,163,82,83,174,16],"154":[46],"158":"b:AABFCABAAEEAABwAACAAAEAIIQAIVAIAAAAAAAA=","162":[46],"168":"b:AgBFCABAAFEAMFwAACAAAEAIJwAoXBMAAAAAAAA=","190":"b:AgBFCABAAFEAMFwAACAAAEAIJwAoXBMAAAAAAAA=","225":"b:AABFCABAAEEAABwAACAAAEAIIQAIVAIAAAAAAAA=","234":[109,46,56,163,82,83,174,16],"235":[46],"241":[46],"252":[46],"262":"b:AgBFCABAABEAMFwAACAAAEAIJwAoXBMAAAAAAAA="},"packages/frontend/editor-ui/src/features/ndv/parameters/components/Collection/CollectionParameter.vue":{"9":"b:TupFaABmQFEUOP8EgGIAUE2ILwKs/ncAAAAAAAA=","25":"b:TupFaABmQFEUOP8EgGIAUE2ILwKs/ncAAAAAAAA=","34":[46,54,56,14],"39":[46],"40":[46]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/Collection/CollectionParameterLegacy.vue":{"25":"b:TupFaABmQFEUOP8EgGIAUE2ILwKs/ncAAAAAAAA=","46":"b:TupFaABmQFEUOP8EgGIAUE2ILwKs/ncAAAAAAAA=","50":"b:TupFaABmQBEUOP8EgGAAUE2ILwKs/lcAAAAAAAA=","57":"b:TupFaABmQBEUOH8EgGAAUE2ILwKs/hcAAAAAAAA=","63":"b:TupFaABmQBEUOH8EgGAAUE2ILwKs/hcAAAAAAAA=","75":"b:TupFaABmQFEUOP8EgGIAUE2ILwKs/ncAAAAAAAA=","91":[30,110,46,54,56,139,14,84,181],"95":[30,110,46,54,56,139,14,84,181],"100":[46],"112":"b:TupFaABmQFEUOP8EgGIAUE2ILwKs/ncAAAAAAAA=","114":"b:TupFaABmQFEUOP8EgGIAUE2ILwKs/ncAAAAAAAA=","115":[30,110,46,54,56,139,14,84,181],"118":[30,110,46,54,56,139,14,84,181],"120":[30,110,46,54,56,139,14,84,181],"131":"b:TupFaABmQFEUOP8EgGIAUE2ILwKs/ncAAAAAAAA=","133":"b:TupFaABmQFEUOP8EgGIAUE2ILwKs/ncAAAAAAAA=","148":"b:TupFaABmQFEUOP8EgGIAUE2ILwKs/ncAAAAAAAA=","149":"b:TupFaABmQFEUOP8EgGIAUE2ILwKs/ncAAAAAAAA=","152":[46,54,56,14],"206":[46,54,56,14],"208":"b:TupFaABmQFEUOP8EgGIAUE2ILwKs/ncAAAAAAAA=","212":[46],"215":"b:TupFKABmQFEUOP8EgCIAUE2ILwKs/lcAAAAAAAA=","238":[46],"248":"b:TupFaABmQBEUOH8EgGAAUE2ILwKs/hcAAAAAAAA=","251":"b:TupFaABmQBEUOH8EgGAAUE2ILwKs/hcAAAAAAAA="},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ExpressionEditModal.vue":{"40":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","70":[46,173],"88":[46,173],"89":[46],"90":[46,173],"95":[46,173],"98":[46],"104":[46],"109":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","110":[46,173],"138":[46],"146":[46,173],"151":[46,173],"155":[46],"161":[46],"166":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","177":[46,173],"189":[46,173],"197":[46,173],"218":[46,173],"228":[46,173],"252":[46,173]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ExpressionEditorModal/theme.ts":{"4":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","33":[46,173],"39":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA="},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ExpressionFunctionIcon.vue":{"8":"b:BsoAAABAAAACEK8AAAAAAACKAAAAJA0AAAAAAAA="},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ExpressionParameterInput.vue":{"26":"b:BsoFCABAAAACEK8AAAAAAECKIQAAZA8AAAAAAAA=","67":"b:BsoFCABAAAACEK8AAAAAAECKIQAAZA8AAAAAAAA=","68":"b:BsoFCABAAAACEK8AAAAAAECKIQAAZA8AAAAAAAA=","72":[46],"78":"b:AEABAABAAAACAC8AAAAAAAAAAAAAYA4AAAAAAAA=","84":"b:AEABAABAAAACAC8AAAAAAAAAAAAAYA4AAAAAAAA=","89":[46,65,81,82,173,83,174,16,85,178,179],"97":"b:BsoFCABAAAACAC4AAAAAAAAIAQAAZA0AAAAAAAA=","100":"b:AoAFCABAAAACAC4AAAAAAAAAAAAAZAwAAAAAAAA=","128":"b:AoAFCABAAAACAC8AAAAAAEAIAAAAZA4AAAAAAAA=","137":"b:BsoFCABAAAACEK8AAAAAAECKIQAAZA8AAAAAAAA=","148":[46,82],"160":[46,82],"166":[46,82],"175":[46,82],"181":"b:BsoFCABAAAACEK8AAAAAAECKIQAAZA8AAAAAAAA=","185":"b:BsoECABAAAACECoAAAAAAACIAQAAJAAAAAAAAAA=","189":[46,82],"196":"b:BsoFCABAAAACAC4AAAAAAAAIAQAAZA0AAAAAAAA=","199":"b:BsoFCABAAAACEK8AAAAAAECKIQAAZA8AAAAAAAA=","219":"b:BsoFCABAAAACEK8AAAAAAECKIQAAZA8AAAAAAAA=","244":[46,173]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FilterConditions/constants.ts":{"299":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","305":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","311":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","317":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","323":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","329":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FixedCollection/FixedCollectionParameterLegacy.vue":{"66":"b:BoIBaAAMQBBAKL4EgGAAUCAIABAg8BMCAAAAAAA=","71":"b:AgABaAAEQAEAKD4EgGAAECAIAAAgcBMCAAAAAAA=","73":"b:AgABaAAEQAEAKD4EgGAAECAIAAAgcBMCAAAAAAA=","76":"b:AgABaAAEQAEAKD4EgGAAECAIAAAgcBMCAAAAAAA=","80":"b:BoIBaAAMQBFAKL4EgGAAUCAIABAg8BMCAAAAAAA=","81":"b:BIIBAAAIQBBAALQEgAAAQAAAABAAkAECAAAAAAA=","82":"b:AgABaAAEQAAAKD4EgGAAECAIAAAgcBMCAAAAAAA=","83":"b:AgABaAAEQAEAKD4EgGAAECAIAAAgcBMCAAAAAAA=","85":"b:BoIBaAAMQBBAKL4EgGAAUCAIABAg8BMCAAAAAAA=","92":"b:BoIBaAAMQBFAKL4EgGAAUCAIABAg8BMCAAAAAAA=","94":"b:BoIBaAAMQBFAKL4EgGAAUCAIABAg8BMCAAAAAAA=","105":"b:BoIBaAAMQBFAKL4EgGAAUCAIABAg8BMCAAAAAAA=","108":[126,54,56],"111":"b:BoIBaAAMQBFAKL4EgGAAUCAIABAg8BMCAAAAAAA=","115":[103,54],"122":[103,54],"126":[103,54],"140":"b:BoIBaAAMQBFAKL4EgGAAUCAIABAg8BMCAAAAAAA=","155":[103,54],"160":[103,54],"191":[103,54],"196":"b:AgABaAAEQAEAKD4EgGAAECAIAAAgcBMCAAAAAAA=","207":[103,54],"232":"b:AgABaAAEQAEAKD4EgGAAECAIAAAgcBMCAAAAAAA=","242":[103,54],"263":[54],"276":[54],"299":"b:BoIBaAAMQBFAKL4EgGAAUCAIABAg8BMCAAAAAAA=","300":[30,90,103,43,110,9,54,56,81,82,83,15,16],"307":"b:BoIBaAAMQBFAKL4EgGAAUCAIABAg8BMCAAAAAAA=","339":[90,103,54,82,16],"362":[90,103,54,82,16],"368":[90,103,54,82,16],"382":[90,103,54,82,16],"389":[90,103,54,56,81,82,83],"421":"b:AgABaAAEQAAAKD4EgGAAECAIAAAgcBMCAAAAAAA=","423":"b:BoIBaAAMQBFAKL4EgGAAUCAIABAg8BMCAAAAAAA=","439":"b:AgABaAAEQAEAKD4EgGAAECAIAAAgcBMCAAAAAAA=","461":"b:AgABaAAEQAAAKD4EgGAAECAIAAAgcBMCAAAAAAA=","531":[54],"532":[103,54],"636":[90,103,54,82,16],"644":[172,82,176,84,85]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInput.vue":{"142":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","228":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","230":[46,173,176],"245":[46],"252":[46],"261":[46],"273":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","279":[41,46,176,16],"283":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","289":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","293":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","295":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","299":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","308":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","315":"b:TupF+ABuQBFWOv9GgOACUG+uP3Ls/n8CAAAAAAA=","319":"b:BkIBQABoQBFCAAQGgOAAAAyAAEIAAgkAAAAAAAA=","323":[46],"333":[3,42,46,128,66,162,16,181],"336":[46],"349":[3,42,46,128,66,162,16,181],"353":[3,42,46,128,66,162,16,181],"361":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","365":"b:TupF+ABuQFFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","390":"b:QCIBIABKQBFACDIAgAAAUAMKADCEIB8CAAAAAAA=","397":"b:CgABEABGAAAEMgBAAAAAAAEgEADkACEQAAAAAAA=","406":"b:BoIFIABIAhBACIAAAAAAUACAADAAAEUCAAAAAAA=","410":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","419":[46],"429":[46],"434":"b:TupF+ABuQFFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","450":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","453":"b:AgAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","461":"b:TupF+ABuQFFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","465":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","473":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","477":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","551":"b:CsAFKABAAAEAKDoGACIAUCAMBAIgfBsCAAAAAAA=","559":"b:CsAFKABAAAEAKDoGACIAUCAMBAIgfBsCAAAAAAA=","561":"b:BsoFKABIAhBCGK8AAAAAUECKITAAZE8CAAAAAAA=","576":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","609":"b:TupF+ABuQFFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","632":"b:TupF+ABuQFFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","636":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","676":"b:TupFeABuQFFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","707":[46,182,87],"726":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","740":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","747":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","751":[46],"755":[6,9,46,13,14,15],"759":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","786":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","805":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","809":"b:TupF+ABuQFFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","810":[46],"813":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","819":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","823":[46,167],"825":"b:RkIBQABoQBFCAC8GgOAAQA6EAEJIYg8AAAAAAAA=","826":"b:QAIBAABgQAEAAC4EACAAQAIEAAJAIAgAAAAAAAA=","828":[46,138,82],"829":"b:BkIBQABoQBFCAA8GgOAAAAyEAEIIIg0AAAAAAAA=","836":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","848":[1,46],"850":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","859":"b:TupF+ABuQFFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","863":"b:TupF+ABuQFFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","867":[9,45,46],"885":"b:TupF+ABuQFFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","892":"b:TupF+ABuQFFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","904":"b:TupF+ABuQFFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","912":"b:TupFeABuQFFCOv9GgOICUG+uP3Ds/n8SAAAAAAA=","920":[41,46,176,16,178],"972":[46,176],"977":[46,176],"982":[46,173],"986":[46,173],"1004":[46],"1008":[46],"1016":[46,176],"1028":[46,173],"1035":[46],"1043":"b:RkIBQABoQBFCAK8GgOAAQA6EAEJIYg8AAAAAAAA=","1051":"b:RkIBQABoQBFCAK8GgOAAQA6EAEJIYg8AAAAAAAA=","1098":[46],"1105":[46],"1112":"b:BkIBQABoQBFCAAQGgOAAAAyAAEIAAgkAAAAAAAA=","1122":[46],"1135":"b:RkIBUABqQBFCMo9GgOAAQA6kEELkYk8AAAAAAAA=","1222":[46,65,80,81,82,173,83,174,16,177,178,179],"1229":"b:RkIBQABoQBFCAI8GgOAAQAyEAEJIYg0AAAAAAAA=","1234":[46],"1258":[46],"1268":[46],"1272":[46],"1291":[46],"1296":"b:BkIBQABoQBFCAAQGgOAAAAyAAEIAAgkAAAAAAAA=","1303":"b:AEABAABAAAACAI8AAAAAAAAAAAAAYA4AAAAAAAA=","1334":[46],"1383":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","1417":[6,9,46,13,14,15],"1442":[46],"1443":[46],"1446":"b:TuoFaABqQBFSOv5GgIACUCmoH2Ds/l8SAAAAAAA=","1453":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","1455":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","1469":[46],"1483":[46,176,16,178],"1489":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","1490":"b:BkIBcABqQBFCMo9GgOACAA6kAELkYk8AAAAAAAA=","1500":[41,46,176,16],"1505":"b:AEABAABAAAACAI8AAAAAAAAAAAAAYA4AAAAAAAA=","1515":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","1518":[29,109,9,46],"1534":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","1547":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","1553":"b:AAABAABAAAAAAA8AAAAAAAAEAAKAQA8AAAAAAAA=","1716":[46,176],"1800":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","1805":[46,176],"1825":[46,167],"1829":[46],"1847":[46],"1851":[46],"1870":[46,167],"1874":[46],"1893":[1,46],"1898":[46],"1916":[3,42,46,128,66,162,16,181],"1920":[46],"1931":[46],"1945":"b:BkIBQABoQBFCAAQGgOAAAAyAAEIAAgkAAAAAAAA=","1965":[30,46,153,82,176,16],"1970":"b:TupF+ABuQFFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","1979":[46],"2011":[46],"2044":[46],"2081":[42,9,45,46],"2099":[46],"2102":"b:TupF+ABuQFFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","2104":"b:TupF+ABuQFFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","2110":"b:TupF+ABuQFFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","2139":[46],"2142":[41,46,124,178],"2144":[41,46,124,178],"2149":[41,46,124,178],"2168":[46]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputExpanded.vue":{"24":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","25":[46],"62":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","66":[46],"78":[46],"85":[46],"93":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","115":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","123":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","130":[1,2,43,111,9,45,46,60,143,65,158,70,16,89],"134":[1,2,43,111,9,45,46,60,143,65,158,70,16,89],"139":[46],"143":[46,65],"147":[1,2,43,111,9,45,46,60,143,65,158,70,16,89],"160":[46],"170":[46],"172":"b:BgIBIABoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","185":"b:BgIBIAAoABBCAAACAIACAAKAAEAAAAQAAAAAAAA=","196":"b:BgIBIAAoABBCAAACAIACAAKAAEAAAAQAAAAAAAA="},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputFull.vue":{"67":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","105":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","119":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","122":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","131":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","136":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","141":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","145":[46,82],"151":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","159":"b:TupF6ABuQBFEOP8EgGAAUG+OLzIs/n8CAAAAAAA=","164":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","172":[46],"176":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","194":"b:QEIBQABgQAEAAK8EgGAAQA4EAAJIYg8AAAAAAAA=","202":"b:QEIBQABgQAEAAI8EgGAAQAwEAAJIYg0AAAAAAAA=","214":[46],"218":"b:QkIFgABkQAEAAL8EgGAAQA4IASDAdC8AAAAAAAA=","222":"b:QgIFAABkQAEAAL4EgGAAQA4IASDAdC4AAAAAAAA=","226":[46,80,81,173,83,174,16,177,178,179,87],"243":"b:QkIBUABiQAEAMo9EgGAAAA4kEALkYk8AAAAAAAA=","247":"b:AEABQABgQAEAAAQEgGAAAAwAAAIAAgkAAAAAAAA=","255":[46,82],"263":[46,82],"278":[46],"280":[46],"334":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","339":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","340":[46,179],"349":"b:QkIFgABkQAEAAL8EgGAAQA4IASDAdC8AAAAAAAA=","354":[6,9,46,13,14,15],"358":[6,46],"378":[46],"399":[46],"403":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","421":[46],"456":[46],"490":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","494":[6,9,46,13,14,15],"507":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","529":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","534":[46],"564":[6,9,46,13,14,15]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputHint.vue":{"14":"b:BoAFKABAAAECKC8AAAAAEGCIIACgdA8CAAAAAAA=","23":"b:BoAFKABAAAECKC8AAAAAEGCIIACgdA8CAAAAAAA=","25":[46,139],"29":"b:AAAFCABAAAACAC8AAAAAAEAIIAAAZA4AAAAAAAA=","41":"b:BoAFKABAAAECKC8AAAAAEGCIIACgdA8CAAAAAAA=","45":"b:BoAFKABAAAECKC8AAAAAEGCIIACgdA8CAAAAAAA="},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputList.vue":{"67":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","68":"b:BoIBaABMQBFAKL4EgGAAUCAIABAg8BMCAAAAAAA=","71":"b:TupFaABmQFEUOP8EgGIAUE2ILwKs/ncAAAAAAAA=","129":"b:TupFeABuQFFUOv9EgGIAUG2oPzLs/ncSAAAAAAA=","131":[46],"150":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","155":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","162":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","192":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","205":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","211":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","212":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","240":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","285":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","312":[3,6,46,144,148,68,166,167,15,16,179,87],"313":[3,6,46,144,148,68,166,167,15,16,179,87],"319":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","320":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","323":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","324":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","327":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","344":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","353":[103,46,54],"356":[103,46,54],"379":[103,46,54],"397":[90,46],"400":[90,46],"407":[46],"417":[46],"438":[1,2,9,46,11,143,14,76,15],"445":[1,46,76],"449":[1,46,76],"464":[103,46,54],"467":[103,46,54],"471":[103,46,54],"476":"b:QEIBQABgQAEAAI8EgGAAQAQEAAJAIg0AAAAAAAA=","480":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","487":"b:BIIF4ABuQhFAECEEgGIAUAQICjAAFhcCAAAAAAA=","494":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","498":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","502":[46],"513":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","526":[46,18],"541":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","558":"b:QkIBUABiQAEAMo9EgGAAAA4kEALkck8AAAAAAAA=","562":[46],"568":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","583":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","587":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","615":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","621":[46,16],"625":[46,16],"635":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","640":"b:RgIFgABsQBFAAAAAAAAAAACAADAAAAAAAAAAAAA=","656":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","659":[46],"664":[46],"667":[46],"675":[46],"679":[46],"680":[46],"687":[46],"691":[46],"706":[46],"726":[46],"734":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","736":[46,14],"752":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","757":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","824":[46,16],"838":[46],"839":[46,16],"845":[46,16],"853":[46],"887":[46,87],"889":[46],"890":[46],"891":[46,87],"897":"b:TupFaABuQFFUOP8EgGIAUG2ILxKs/ncCAAAAAAA=","920":"b:TupFaABuQFFUOP8EgGIAUG2ILxKs/ncCAAAAAAA=","922":"b:TupFaABuQFFUOP8EgGIAUG2ILxKs/ncCAAAAAAA=","938":[46],"951":[46],"955":[46],"970":[46],"1024":[46],"1046":[46],"1048":"b:QEIBQABgQAEAAI8EgGAAQAQEAAJAIg0AAAAAAAA=","1057":[46]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputWrapper.vue":{"51":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","71":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","75":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","86":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","92":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","103":[46,139,65,80,81,82,173,83,85,178,179],"105":[46,85],"109":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","114":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","131":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","135":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","142":"b:RkIBQABoQBFCAK8GgOAAQA6EAEJIYg8AAAAAAAA=","146":"b:RkIBQABoQBFCAI8GgOAAQAyEAEJIYg0AAAAAAAA=","150":[46],"154":"b:RkIBUABqQBFCMo9GgOAAAA6kEELkYk8AAAAAAAA=","158":"b:BkIBQABoQBFCAAQGgOAAAAyAAEIAAgkAAAAAAAA=","163":[6,9,46,13,14,15],"164":[46],"168":[46],"169":[46],"171":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","176":[46],"178":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","210":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA="},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterOptions.vue":{"41":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","62":"b:TupF+ABuQhFWOv9GgOACUG+uP3Ls/n8CAAAAAAA=","63":"b:TupF+ABuQhFWOv9GgOACUG+uP3Ls/n8CAAAAAAA=","64":"b:DupFaABuQBFGOP8GgOACUG+OL3Ks/n8CAAAAAAA=","68":"b:TupF+ABuQhFWOv9GgOACUG+uP3Ls/n8CAAAAAAA=","71":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","81":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","100":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","119":"b:DupFaABuQBFGOP8GgOACUG+OL3Is/n8CAAAAAAA=","120":"b:TupF+ABuQhFWOv9GgOACUG+uP3Ls/n8CAAAAAAA=","124":"b:TupF+ABuQhFWOv9GgOACUG+uP3Ls/n8CAAAAAAA=","132":"b:TupF+ABuQhFWOv9GgOACUG+uP3Ls/n8CAAAAAAA=","177":[46,179],"178":[46,65,80,81,173,83,174,16,177,178,179,87],"185":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","193":[46,179],"207":[46],"219":[46,179]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ResourceLocator/ResourceLocator.vue":{"82":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","165":[46,176,178],"179":[46,16,178],"188":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","201":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","203":[46,16,178],"210":[46,176,178],"213":[46,176,178],"222":[1,46,176,178],"235":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","238":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","246":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","261":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","265":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","269":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","270":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","283":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","340":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","350":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","352":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","365":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","367":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","370":[46,178],"378":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","380":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","387":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","391":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","392":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","393":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","394":[46],"396":[1,46,176,178],"400":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","414":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","420":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","426":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","430":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","454":[46],"517":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","523":[46,176,178],"531":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","533":[46],"542":[46,16,178],"552":[46,176,178],"560":[46],"572":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","573":[46,176,16,178],"593":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","595":[1,2,43,9,46,143,16,178],"620":[46],"640":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","644":"b:BoIFIABIABBACAAAAAAAUACAADAAAAUCAAAAAAA=","649":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","654":[1,2,46,124,126,143,157,75,18,176,15,16,185],"662":"b:BoIFIABIAABACAAAAAAAQACAADAAAAUCAAAAAAA=","669":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","675":[46,16,178],"686":[46],"691":[46],"697":[46],"702":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","709":[46],"725":[46,178],"745":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","747":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","752":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","760":[46,16,178],"763":[46],"779":[46,178],"785":[46,178],"791":[46,16,178],"810":[46,16,178],"822":[46],"827":[46],"832":[46,176,178],"839":[46,178],"851":[1,46,176,178],"862":[1,46,176,178],"979":[1,46,178],"992":[1,46,178],"1000":[46,176,16,178],"1009":[46],"1012":[46],"1025":"b:BoIFIABIAABACAAAAAAAQACAADAAAAUCAAAAAAA=","1033":[46,176,178],"1039":[46,176,178],"1047":[46],"1052":[46,176,16,178],"1065":[46],"1080":[46],"1091":[46],"1095":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","1121":[46],"1126":[46,176,178],"1133":[46,176,178],"1138":[46,178],"1149":[46],"1166":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","1186":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","1188":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","1195":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","1217":"b:BoIFIABIAhBACAAAAAAAUACAADAAAAUCAAAAAAA=","1243":[46],"1269":"b:BoIFIABAAAAACAAAAAAAUACAACAAAAUAAAAAAAA=","1298":[46],"1299":[46,16,178],"1312":[46]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ResourceLocator/ResourceLocatorDropdown.vue":{"15":"b:BoIFIABIAhBACIAAAAAAUACAADAAAEUCAAAAAAA=","61":[46,178],"79":[46,178,87],"81":[46,178,87],"121":"b:BoIFIABIAhBACIAAAAAAUACAADAAAEUCAAAAAAA=","122":[46,176,178,87],"128":[46,176,178,87],"137":"b:BoIFIABIAhBACIAAAAAAUACAADAAAEUCAAAAAAA=","141":"b:BoAFAABAAAAACIAAAAAAUACAACAAAEECAAAAAAA=","145":[46],"152":[46],"204":[46,87],"208":[46,87],"221":[46,87],"224":[46,87],"231":[46],"235":[46,87],"250":"b:BoIBIABIAABAAIAAAAAAQACAADAAAAQAAAAAAAA=","256":"b:BoIFIABIAhBACIAAAAAAUACAADAAAEUCAAAAAAA=","258":"b:BoIFIABIAhBACIAAAAAAUACAADAAAEUCAAAAAAA=","272":"b:BoIFIABIAhBACIAAAAAAUACAADAAAEUCAAAAAAA=","284":"b:BoIFIABIAhBACIAAAAAAUACAADAAAEUCAAAAAAA=","287":[46,176,178,87],"309":[46,178,87],"346":[46,87],"347":[46],"348":[46,87],"356":[46,178,87],"367":[46,87],"368":[46,87],"369":[46],"380":[46],"389":[46],"395":[46,178],"403":[46]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/TextEdit.vue":{"11":"b:TupF+ABuQFFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","31":[46],"33":"b:TupF+ABuQFFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","35":[46],"43":"b:TupF+ABuQFFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","44":"b:BgIBcABqQBFCMgRGgOACAA6gAELkAg0AAAAAAAA=","50":"b:TupF+ABuQFFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","54":[46],"58":[46],"64":[46],"68":"b:TupF+ABuQFFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","82":[46],"86":[46],"87":[46]},"packages/frontend/editor-ui/src/features/ndv/parameters/composables/useParameterInputContribution.ts":{"16":[46],"38":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","39":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","41":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","45":"b:TupF+ABuQlFWOv9GgOIAUG+uP3Ls/n8SAAAAAAA="},"packages/frontend/editor-ui/src/features/ndv/parameters/utils/fromAIOverride.utils.ts":{"42":[6,46],"83":[46,13],"90":[6,9,46,13,14,15],"106":[6,46],"117":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","121":[6,46],"132":[6,46],"138":[6,46],"139":[46],"153":[6,46],"157":[6,46],"184":[46],"189":[46],"210":[9,46,14],"246":[6,9,46,13,14,15],"268":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","277":[46],"285":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","286":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","302":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","309":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","321":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA="},"packages/frontend/editor-ui/src/features/ndv/runData/components/MappingPill.vue":{"13":"b:CgBEAAFAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA="},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunData.vue":{"105":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","106":[46,13,170,18,82,84],"108":"b:CCBFGgBAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","109":[46],"111":[1,46,18],"113":"b:CiBFGgFAQEEAID4EgEIAAGwGJQDI9msQAAAAAAA=","238":"b:DupFeAFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","239":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","269":"b:AABEGAFAQAEAAD4EgEAAAGwEIADA9msAAAAAAAA=","270":"b:DspFegFuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","271":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","277":"b:AiAEAABAAAAAAD4AAAAAAAAEAACA7gMAAAAAAAA=","278":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","284":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","285":"b:CiBFGgBAAEAAID4EAEAAAEwGJADI9msQAAAAAAA=","287":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","288":"b:CCBFGABAQEEAID4EgEIAAGwGJADA9msQAAAAAAA=","289":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","290":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","291":"b:DupFeAFuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","294":"b:DupFeABuQFFAOv9EgGAAUE+MPzDk/n8CAAAAAAA=","298":"b:DupFeAFuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","306":"b:CiBFGgBAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","307":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","308":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","309":"b:AABEAABAQEEAAD4EgEIAAGwEIADA9msQAAAAAAA=","317":"b:CCBFGgBAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","326":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","331":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","353":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","357":"b:DiBFGgFAQEEAID4EgEIAAGwGLQDI/nsQAAAAAAA=","361":"b:CiBFGgFAQEEAID4EgEIAAGwGLQDI/nsQAAAAAAA=","370":"b:CiBFGgFAQEEAID4EgEIAAGwGLQDI/nsQAAAAAAA=","374":"b:CiBFGgFAQEEAID4EgEIAAGwGLQDI/nsQAAAAAAA=","384":"b:DupFegFuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","386":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","395":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","412":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","421":"b:DiBFGgFAQEEAID4EgEIAAGwGJQDI9msQAAAAAAA=","425":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","430":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","443":"b:DupFegFuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","449":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","456":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","466":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","469":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","479":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","483":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","487":"b:AAAAGAFAQAEAAD4AgEAAACwEAABA8CsAAAAAAAA=","491":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","499":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","502":"b:AiBFCgFAAEAAID4EAEIAAEgCJQCI9mMQAAAAAAA=","503":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","511":"b:CgBEAAFAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA=","512":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","516":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","521":[3,46,18,84,85,181],"531":[3,46,18,84,85,181],"537":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","541":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","542":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","543":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","547":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","548":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","553":[46],"555":[46],"556":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","566":[1,3,46,131,18,175,176,84,85],"567":[1,3,46,131,18,175,176,84,85],"607":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","611":"b:DspFeABuQBFAOv9EgGAAUG+uPzDk/n8CAAAAAAA=","612":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","618":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","629":"b:CiBFGgFAQEEAID4EgEIAAGwGLQDI/nsQAAAAAAA=","633":"b:DupFeAFuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","645":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","662":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","667":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","676":"b:AABEAABAQEEAAD4EgEIAAGwEIADA9msQAAAAAAA=","680":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","698":[3,46],"704":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","707":"b:DupFegBuQFFAOv9EgGAAUE+OPzDs/n8SAAAAAAA=","710":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","713":[46,134,139,147,167,171,172,84,177,180,181],"714":[46,134,139,147,167,171,172,84,177,180,181],"731":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","738":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","742":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","743":[25,1,46,18],"746":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","750":[46,18],"756":[32,1,46,166,167,18,82,15,16,85,179,87],"761":"b:DgAEGAFAQAEAAD4AgEAAACwEAQDA8CsAAAAAAAA=","771":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","776":"b:CiBFGgFAQEEAID4EgEIAAGwEJQDI9msQAAAAAAA=","783":"b:DuoFGAFAQAEAAL4AgEAAACyEAQDA8isAAAAAAAA=","792":"b:DgAEGAFAQAEAAD4AgEAAACwEAQBA8CsAAAAAAAA=","800":[27,28,46,18,176,85],"807":[46,175,84],"813":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","822":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","843":[46,18],"854":"b:DuoFagFiQBEAOn5EgAAAUCmoHyDs/lsSAAAAAAA=","859":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","875":[46,126,137,139,146,170,84,180,87],"905":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","927":[46],"943":[46,82,175,84,85],"955":[46],"965":"b:DupFegFuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","981":"b:AAAAGAFAQAEAAA4AAAAAAAQEAADA8AoAAAAAAAA=","989":"b:DuoFagFiQBEAOn5EgAAAUCmoHyDs/lsSAAAAAAA=","997":"b:AAAEGAFAQAEAAA4AgEAAACQEAADA8gsAAAAAAAA=","1002":[46,167,171,81,82,173,83,174,85,177],"1038":[46,167,171,81,82,173,83,174,85,177],"1056":[46],"1062":[46,167,81,82,173,83,174,85,177],"1094":[46,167,81,82,173,83,174,85,177],"1108":[46,167,169,81,82,173,83,174,85,177],"1113":[46,169,177],"1167":[46],"1171":[46,85],"1183":[46],"1195":[3,46,84],"1203":[3,46,84],"1207":[3,46,84],"1211":[46,138],"1224":"b:CgAEGAFAQAEAAD4AgEAAACwEAQDA4CsAAAAAAAA=","1231":[46],"1247":[1,46,13,170,18,82,175,176,84,85],"1278":[3,46,18,84,85,181],"1306":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","1331":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","1334":"b:AAABAABAAAAAAD4AAAIAAAAAAACI8kIAAAAAAAA=","1346":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","1352":[46,175,84],"1355":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","1373":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","1383":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","1408":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","1412":[46],"1421":[46],"1435":[1,3,46,131,18,175,176,84,85],"1453":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","1456":"b:CiBFGgFAQEEAID4EgEIAAGwEJQDI9msQAAAAAAA=","1462":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","1469":[3,46,84,85,181],"1473":[46],"1486":"b:DupFegFuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","1492":"b:DupFegFuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","1498":"b:DupFegFuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","1502":[46],"1507":[46],"1515":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","1549":[46],"1550":[46,167,169,81,82,173,83,174,175,84,85,177],"1554":"b:AAAAAABAAAAAAD4AAAIAAAAAAACA4gIAAAAAAAA=","1562":"b:AAAAAABAAAAAAD4AAAIAAAAAAACA4gIAAAAAAAA=","1574":[46],"1587":[46,167,169,171,81,82,173,83,174,85,177],"1607":[46],"1638":[46,167,171,81,82,173,83,174,85,177],"1651":[46,169,177],"1697":[3,46,84,85,181],"1699":[3,46,18,84,85,181],"1700":[3,46,18,84,85,181],"1701":[3,46,18,84,85,181],"1710":[46],"1712":[3,46,84,85],"1738":[46],"1802":[46],"1819":"b:DgAEGAFAQAEAAD4AgEAAACwEAQBAcCsAAAAAAAA=","1848":[46],"1849":[46],"1856":[46,171],"1862":[46,167,81,82,173,83,174,85,177],"1867":[46,167,171,81,82,173,83,174,85,177],"1869":[46,167,171,81,82,173,83,174,85,177],"1876":[46],"1986":[46,62],"2061":[46],"2103":[46],"2104":[46],"2128":"b:AiBFCgFAAEAAID4EAEIAAEgCJQCI9mMQAAAAAAA=","2143":[46],"2171":[46,175],"2173":[46,175],"2196":"b:CgBEAAFAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA=","2199":[46]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataDisplayModeSelect.vue":{"18":"b:DupFeAFuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","21":"b:DupFeAFuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","45":"b:DupFeAFuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","47":"b:DupFeAFuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","53":"b:DupFeAFuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","62":[46,13,170,18,82,175,176,84,85],"64":[32,1,2,3,46,144,18,188]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataItemCount.vue":{"16":"b:DiBEGAFAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA=","17":"b:DiBEGAFAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA=","21":[46,175,84],"29":"b:DiBEGAFAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA="},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataSearch.vue":{"44":"b:CiBFGgEAQEEAID4EgEIAAGwGJQDI9msQAAAAAAA=","50":"b:CiBFGgEAQEEAID4EgEIAAGwGJQDI9msQAAAAAAA=","68":"b:CiBFGgEAQEEAID4EgEIAAGwGJQDI9msQAAAAAAA=","72":[138,146,81,82,173,83,174,175,84,16,177],"99":[175,84],"104":[175,84],"109":[175,84],"115":[175,84],"121":[175,84],"134":[138,146,81,82,173,83,174,175,84,16,177],"152":"b:CiBFGgEAQEEAID4EgEIAAGwGJQDI9msQAAAAAAA=","153":[175,84]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataTable.vue":{"87":"b:CABEAAAAQEEAAD4EgEIAAGwEIADA9msQAAAAAAA=","88":"b:CgBEAAEAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA=","89":"b:CgBEAAEAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA=","91":"b:CgBEAAEAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA=","92":"b:CgBEAAEAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA=","93":[82,175,84,85],"96":"b:CgBEAAEAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA=","97":"b:CgBEAAEAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA=","105":"b:CgBEAAEAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA=","116":"b:CgBEAAEAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA=","153":[181],"165":[82,175,84,85],"187":[82,84,85],"194":[82],"198":[82],"202":[82,175],"208":"b:CgBEAAEAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA=","221":"b:CgBEAAEAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA=","228":[3,105,131,56,169,18,82,174,175,84,85],"241":[3,105,131,56,169,18,82,174,175,84,85],"254":"b:CgBEAAEAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA=","264":"b:CgBEAAEAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA=","286":[82],"296":[82],"304":[82],"310":[3,105,131,56,169,18,82,174,175,84,85],"318":[82],"320":[82],"342":"b:CgBEAAEAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA=","351":[3,105,131,56,169,18,82,174,175,84,85],"355":"b:CgBEAAEAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA=","359":"b:CgBEAAEAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA=","371":"b:CgBEAAEAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA=","396":[131,138,170,18,82,175,176,84,85,177,181],"414":"b:CgBEAAEAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA=","430":"b:CgBEAAEAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA=","458":[56,138,82,85],"459":[56,138,82,85],"468":"b:CgBEAAEAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA=","513":[18,176,84],"570":"b:CgBEAAEAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA=","582":"b:CgBEAAEAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA=","591":[82],"593":"b:CgBEAAEAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA=","596":"b:CgBEAAEAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA=","613":"b:CgBEAAEAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA=","669":"b:CgBEAAEAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA=","699":[181],"713":"b:CgBEAAEAQEEAAD4EgEIAAGwEIQDA9msQAAAAAAA=","731":[3,105,131,56,169,18,82,174,175,84,85],"745":[82],"754":[3,105,131,56,169,18,82,174,175,84,85]},"packages/frontend/editor-ui/src/features/ndv/runData/components/TextWithHighlights.vue":{"6":"b:CiBFGgFAQEEAID4EgEIAAGwGLQDI/nsQAAAAAAA=","11":"b:CiBFGgFAQEEAID4EgEIAAGwGLQDI/nsQAAAAAAA=","16":"b:CiBFGgFAQEEAID4EgEIAAGwGLQDI/nsQAAAAAAA=","20":[46,175,84],"29":"b:CiBFGgFAQEEAID4EgEIAAGwGLQDI/nsQAAAAAAA="},"packages/frontend/editor-ui/src/features/ndv/runData/components/error/NodeErrorView.vue":{"47":[27,28,1,2,46,18,176],"64":[46],"70":[46,176],"71":[46],"72":[46],"74":[46],"78":[27,28,1,2,46,18,176],"82":[27,46,176],"95":[27,28,1,2,46,18,176],"106":[27,28,1,2,46,18,176],"110":[1,2,46],"119":[27,28,1,2,46,18,176],"126":[1,2,46],"128":[46],"150":[27,28,1,2,46,18,176],"167":[27,28,1,2,46,18,176],"172":[27,28,46],"179":[27,28,1,2,46,18,176],"186":[27,1,2,46,176],"202":[27,28,1,2,46,176],"206":[27,28,1,2,46,176],"231":[27,28,1,2,46,18,176],"243":[27,28,1,2,46,18,176],"246":[27,28,1,2,46,18,176],"271":[27,46,176],"281":[27,46,176],"287":[27,46,176],"301":[27,46,176],"331":[46],"416":[46],"423":[27,28,1,2,46,176],"428":[46],"457":[27,28,46],"486":[46],"488":[27,28,1,2,46,18,176],"544":[27,28,1,2,46,18,176],"583":[1,2,46]},"packages/frontend/editor-ui/src/features/ndv/runData/schemaPreview.store.ts":{"12":"b:D+pFegF+5XFAuv9EgGIAUH+uPzDu/n8eAAAAAAA=","22":"b:DyBEWAFw5WEAsD5EgEAAAHwuLQDC/nscAAAAAAA=","31":"b:AAAAAABAAAAAADAAAAAAAEAKDACAODIQAAAAAAA=","50":"b:DyBEWAFw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA="},"packages/frontend/editor-ui/src/features/ndv/settings/components/NodeSettings.vue":{"80":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","141":"b:DupFeABuQFFAOv9EgGAAUG+uPzDs/n8SAAAAAAA=","154":[46],"171":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","174":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","175":[46,60],"178":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","179":[46,60],"182":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","192":"b:DupFeABuQFFAOv9EgGAAUG+uPzDs/n8SAAAAAAA=","195":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","196":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","198":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","204":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","207":[46,167,171,81,82,173,83,174,85,177],"209":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","211":"b:DspFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","213":"b:DupFeABuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","217":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","222":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","224":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","228":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","242":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","256":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","264":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","268":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","272":"b:BsoFYABuQBFAGCEEgGIAUAeKCjCEFhcCAAAAAAA=","276":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","279":"b:BsoFYABuQBFAGCEEgGIAUAeKCjCEFhcCAAAAAAA=","280":"b:BsoFIABKQBFACCAAACAAUAeKADCEABcCAAAAAAA=","284":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","288":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","297":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","298":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","303":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","306":"b:DupFeABmQFEAOv9EgGIAUG6sPwDs/n8SAAAAAAA=","309":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","311":[46,176],"312":[46],"314":[46],"315":[46],"316":[46],"322":[46],"324":[46],"332":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","339":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","348":"b:AsIBUABqQAFAMo9EgGAAAA4kEBDkck8AAAAAAAA=","506":[46],"518":[46],"522":[46,15],"530":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","533":"b:BsoFKABqQBFAOs9EgCAAUC+gHhDsah8CAAAAAAA=","539":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","554":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","555":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","556":[46],"558":"b:AgIBQABgQAEAAIMEgGAAQAQEACBAIg0AAAAAAAA=","559":"b:AgIBAABgQAEAAIMEgCAAQAQAAABAIg0AAAAAAAA=","562":[46],"567":"b:AAAAGABAAAAAADwAAEAAACQEAABAUAsAAAAAAAA=","573":[1,2,43,9,46,56,143,156,70,16,178],"587":[46],"597":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","614":[46],"618":[46],"622":[46,176],"626":[46],"639":[3,46,144,166,167,15,16,179,87],"643":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","654":"b:DuoFaABiQBEAOn5EgAAAUCmoHyDs/lsSAAAAAAA=","660":"b:BsoFYABuQBFAGCEEgGIAUAeKCjCEFhcCAAAAAAA=","672":[46],"684":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","712":[46],"714":[46],"746":[46],"758":[46],"805":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA="},"packages/frontend/editor-ui/src/features/ndv/settings/components/NodeSettingsHeader.vue":{"25":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","29":"b:AAAEGABAQAEAAD4AgEAAACwEAABA8CsAAAAAAAA=","33":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","49":[46,176],"70":"b:AAAAGABAAAAAADwAAEAAACQEAABAUAsAAAAAAAA=","71":[46],"72":[46]},"packages/frontend/editor-ui/src/features/ndv/settings/components/NodeSettingsHint.vue":{"13":"b:DupFeABuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","16":"b:DupFeABuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","68":"b:DupFeABuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","72":[46,176],"77":[46,176]},"packages/frontend/editor-ui/src/features/ndv/settings/components/NodeSettingsTabs.vue":{"28":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","43":[46,148,163],"45":[46],"47":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","51":[46,129],"53":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","61":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","127":[46,176],"155":[46],"158":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA="},"packages/frontend/editor-ui/src/features/ndv/settings/components/NodeWebhooks.vue":{"21":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","38":"b:AAIAAABCQAEAAAAAgCIAEAAAAAAAFAcAAAAAAAA=","45":[103,105,41,109,46,54,56,170,172,176,177],"53":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","58":"b:BAIFIABCQAEAACAEgCIAUAAIAAAAFAcAAAAAAAA=","70":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","124":"b:AAIAAABCQAEAAAAAgCIAEAAAAAAAFAcAAAAAAAA=","177":[46],"192":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","193":[46,166,167,15,16,179,87],"200":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","208":[46],"218":[103,105,41,109,46,54,56,170,172,176,177],"224":[103,105,41,109,46,54,56,170,172,176,177],"229":[103,105,41,109,46,54,56,170,172,176,177],"235":[46],"242":[46]},"packages/frontend/editor-ui/src/features/ndv/settings/composables/useNodeSettingsParameters.ts":{"39":[46],"42":[46],"59":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","61":[46],"71":"b:AsIBUABqQAFAMo9EgGAAAA4kEBDkck8AAAAAAAA=","139":[46,16],"179":[46],"196":"b:TupF+ABuQlFUOv9EgGIAUG+uPzLs/n8SAAAAAAA="},"packages/frontend/editor-ui/src/features/ndv/shared/composables/useBinaryDataAccessTooltip.ts":{"9":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","13":[46]},"packages/frontend/editor-ui/src/features/ndv/shared/ndv.store.ts":{"41":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","45":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","46":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","109":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","113":"b:DupFeABuQFFCOv9GgOIAUG+uP3Ds/n8SAAAAAAA=","138":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","142":"b:DupFeABuQFFCOv9GgOIAUG+uP3Ds/n8SAAAAAAA=","149":"b:BkIBQABoQBFCAC8GgOAAAAyEAECIYg8AAAAAAAA=","153":"b:TupF+ABuQhFGOv9EgGAAUG+uPzLs/n8CAAAAAAA=","155":[46,82],"157":[46,82],"159":"b:CiBFGgFAQEEAID4EgEIAAGwGLQDI/nsQAAAAAAA=","161":"b:DupF+gFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","163":"b:CiBFGgFAQEEAID4EgEIAAGwGLQDI/nsQAAAAAAA=","165":"b:ACBFGABAAEAAID4EAEAAAEwGJADI/nsQAAAAAAA=","185":"b:AoAFGABAAAAAAC8AAAAAAEAIAADAZA8AAAAAAAA=","187":"b:AoAFCABAAAAAAC8AAAAAAEAIAACAZA8AAAAAAAA=","189":"b:AEABAABAAAACAC4AAAAAAAAEAACAYA4AAAAAAAA=","191":[46],"193":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","206":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","214":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","231":"b:D+oF+AN+4PFA+v/H4mMI8H/+P7D/////AAAAAAA=","233":"b:DuoF6AJiQBEQOn5EgAAAcCuoHyDk/lsaAAAAAAA=","238":"b:DupFeABuQFFUOv9EgGIAUG+uPzLk/n8SAAAAAAA=","247":"b:DupFeABuQFFAOv9EgGAAUE+OPzDk/n8SAAAAAAA=","251":[3,46,84,85],"255":"b:DupFeABuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","259":[46],"269":"b:DupFeABuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","273":"b:BuoE6ABiQBEAOn5EgAAAUCmoHiDk/lsSAAAAAAA=","277":[46,13,167,170,18,82,175,176,84,85],"288":[46,167,171,81,82,173,83,174,85,177],"292":[46,167,171,81,82,173,83,174,85,177],"296":"b:AEIBQABgQAEAAK8EgGAAAAwEAAAIYg8AAAAAAAA=","300":[46,82],"318":[46,82],"328":[46,82],"332":[46,82],"336":[46,82],"340":[46,82,175,84,85],"345":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","353":"b:DupFegFuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","361":[46,82],"366":[46,82,175,84,85],"371":[46],"376":"b:AEABQABgQAECAC8EgGAAAAwAAACAYg4AAAAAAAA=","380":[46],"393":"b:QEIBQABgQAEAAK8EgGAAQA4EAAJIYg8AAAAAAAA=","470":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","474":"b:QAAIAgBABBAAAEAAAAAAAAAAAAAABwCZAAAAAAA=","498":"b:T+pt+gN+5/FW+v/HwuMK8H/+P/L+////AAAAAAA=","501":"b:T+pt+gN+5/FW+v/HwuMK8H/+P/L+////AAAAAAA=","525":"b:T+pt+AN+5/FW+v/H4uIK8H/+P/L8////AAAAAAA=","528":"b:T+pt+AN+5/FW+v/H4uIK8H/+P/L8////AAAAAAA="},"packages/frontend/editor-ui/src/features/ndv/shared/ndv.utils.ts":{"41":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","57":"b:AsIBUABqQAFAMo9EgGAAAA4kEBDkck8AAAAAAAA=","132":"b:AsIBUABqQAFAMo9EgGAAAA4kEBDkck8AAAAAAAA=","171":[46],"225":[46],"261":"b:QkIBUABqQAFAMo9EgGAAAA4kEBDkck8AAAAAAAA=","267":"b:QkIBUABqQAFAMo9EgGAAAA4kEBDkck8AAAAAAAA=","289":[6,46,16,178],"290":[6,46,16,178],"293":[46,16],"307":"b:AsIBUABqQAFAMo9EgGAAAA4kEBDkck8AAAAAAAA=","328":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","335":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","339":"b:TupF+ABuQFFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","345":[46],"361":"b:AsIBUABqQAFAMo9EgGAAAA4kEBDkck8AAAAAAAA=","367":"b:AEABAABAAAACAI8AAAAAAAAAAAAAYA4AAAAAAAA=","403":[46],"413":[46],"447":"b:TupFeABuQFFUOv9EgGIAUG+uPzLs/n8SAAAAAAA=","458":"b:TupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","622":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","734":"b:TupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA="},"packages/frontend/editor-ui/src/features/ndv/shared/views/NodeDetailsView.vue":{"77":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","78":"b:DupFeAAuQBFAOv9EgGAAUG+uPzDk/n8CAAAAAAA=","99":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","118":"b:DupF+AAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","120":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","124":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","133":[27,28,166,82,177,179],"135":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","149":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","154":"b:DspFeAAuQFFAOv9EgGAAUE+OPzDk/n8SAAAAAAA=","161":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","174":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","180":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","201":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","208":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","210":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","214":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","231":[103,54,56,170],"237":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","242":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","244":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","262":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","268":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","289":"b:DupFeAAuQFFAOv9EgGAAUE+OPzDk/n8SAAAAAAA=","304":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","315":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","319":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","321":"b:BuoE6AAiQBEAOn5EgAAAUCmoHiDk/lsSAAAAAAA=","323":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","325":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","329":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","331":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","335":"b:DupFeAAuQBFAOv9EgGAAUG+uPzDk/n8CAAAAAAA=","337":"b:DupFeAAuQFFAOv9EgGAAUE+uPzDk/n8SAAAAAAA=","339":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","341":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","343":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","347":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","358":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","383":"b:AAAAGAEAQAEAAA4AAAAAAAQEAADA8AoAAAAAAAA=","387":[18],"391":"b:AoIBQAAKAAAAEF8AAAAAEAGEDCCk6A8AAAAAAAA=","397":[82,84,85],"412":[18,82,175,176,84,85],"421":[82,175,84,85],"455":[84],"460":"b:DuoFeAAuQBFAOv9EgGAAUA+OHzDkej8CAAAAAAA=","466":"b:AAAAGAAAAAAAADwAAEAAACQEAABAUAsAAAAAAAA=","467":[27,28,166,82,84,177,179],"484":"b:DuoFeAAuQBFAOv9EgGAAUA+OHzDkej8CAAAAAAA=","493":[3,84],"499":[166,167,15,179],"503":[15],"507":"b:BuoE6AAiQBEAOn5EgAAAUCmoHiDk/lsSAAAAAAA=","554":"b:DupFeAAuQFFAOv9EgGAAUE+uPzDk/n8SAAAAAAA=","563":[3,84,85,181],"568":"b:DupFeAAuQFFAOv9EgGAAUE+uPzDk/n8SAAAAAAA=","576":"b:CABEAAAAQEEAAD4EgEIAAGwEIADA9msQAAAAAAA=","580":[82,85],"598":[3,141,13,76,18,82,175,176,84,15,16,85,178],"603":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","608":[175,84],"612":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","616":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","624":[13,167,170,18,82,175,176,84,85],"630":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","648":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","658":"b:DsIFMAAgQBEAOr5EgCAAAACABADk5h8CAAAAAAA=","696":[3,18,84,85,181],"700":[3,84,85],"704":"b:DupFeAAuQFFAOv9EgGAAUE+OPzDk/n8SAAAAAAA=","705":"b:DupFeAAuQFFAOv9EgGAAUE+OPzDk/n8SAAAAAAA=","710":[3,84,85],"711":[3,84,85],"716":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","721":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","724":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","745":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","751":"b:AgAMAAAABBAAiEAAAAAAAAAAAAAABwCdAAAAAAA=","825":"b:DuoFeAAuQBFAOv9EgGAAUA+OHzDkej8CAAAAAAA=","833":[13,18,82,175,176,84,85],"851":"b:DupFeAAuQFFAOv9EgGIAUG+uPzDk/n8SAAAAAAA=","891":[84],"898":[167,170,84,85]},"packages/frontend/editor-ui/src/features/resolvers/composables/useDynamicCredentials.ts":{"13":"b:X+r/+4P+5/92+v/u+/j////////8////AAAAAAA=","17":"b:X+r/+4P+5/92+v/u+/j////////8////AAAAAAA="},"packages/frontend/editor-ui/src/features/resolvers/composables/useNodePrivateCredential.ts":{"14":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","20":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","22":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","26":"b:BgIFgABs4BFAAgACAAAAAECAADAAAAAAAAAAAAA=","32":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","41":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","47":[46]},"packages/frontend/editor-ui/src/features/resolvers/composables/usePrivateCredentials.ts":{"12":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","15":"b:T+pv+IH+5/9C+v9PgvMK8v//P/Dv/3//AAAAAAA="},"packages/frontend/editor-ui/src/features/settings/communityNodes/communityNodes.store.ts":{"12":"b:TupFeABuQFFAOv9EgGIAUG+u/zDs/n8SAAAAAAA=","22":[46,129,150,151],"23":[46],"30":[46,150,151],"36":[46,129,150,151],"37":[46,150,151],"46":[46,129,150,151],"55":[46,129,150,151],"60":[46,150,151],"65":[46,150],"70":[46,150],"75":[46,150],"79":[46,150,151],"89":[46,129],"94":[46]},"packages/frontend/editor-ui/src/features/settings/communityNodes/composables/useInstalledCommunityPackage.ts":{"9":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","17":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","18":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","26":[46,129],"33":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","35":[3,46,129,144,15],"45":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","55":"b:DupFeABuQFFAOv9EgGIAUG+uPzDs/n8SAAAAAAA=","59":[46,129]},"packages/frontend/editor-ui/src/features/settings/context/context.utils.ts":{"22":"b:f+r/+4P/5/92+v/v+/j////////8////AAAAAAA=","36":[46],"41":[46],"52":[46],"76":[46],"83":[46],"90":[46],"100":[46],"102":[46],"106":[46],"121":[46]},"packages/frontend/editor-ui/src/features/settings/environments.ee/environments.store.ts":{"13":"b:T+r/+4P/5/92+v/P+/v+9///P/P/////AAAAAAA=","18":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","21":"b:AAAAAIDBAB4gAEAJGBAEAoABABEAAQDBAAAAAAA=","22":[46,152,168],"29":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","30":[46,165,181],"35":[46,152],"36":[46,152],"39":[46,152,165,168,181,189],"47":[46,152],"51":[46],"52":[46],"60":[46,152],"68":[46,152],"71":[46,152],"76":[46,152],"81":[46,152],"86":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","90":[46]},"packages/frontend/editor-ui/src/features/settings/sso/sso.store.ts":{"18":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","25":[107,108,46,100],"35":[46],"43":[46],"58":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","110":[107,108,93,46,154,100,69],"111":[46],"118":[46],"122":[46],"124":[46],"132":[46],"135":[46],"157":[46],"164":[46],"170":[46],"173":[107,108,46,100,69],"174":[46],"179":[46],"194":[107,108,46,100],"196":[46],"198":[46],"203":[46],"208":[46],"213":[46],"218":[46],"223":[46]},"packages/frontend/editor-ui/src/features/settings/usage/usage.store.ts":{"38":"b:D+pt+IP/5/9g+v/P+nMM8v//P7D+////AAAAAAA=","45":[46],"46":[46],"47":[46],"48":[46],"49":[101,46],"52":[46],"55":[46],"58":[46],"59":[46],"60":[46],"61":[46],"64":[46],"70":[46],"74":"b:D+pt+IP/5/9A+v/P6nMM8v//P7D+////AAAAAAA=","79":"b:D+pt+IP/5/9g+v/P+nMM8v//P7D+////AAAAAAA=","84":[46],"94":[46],"103":[46],"107":[46],"129":[46],"135":[46],"138":[46],"142":[46],"143":[46]},"packages/frontend/editor-ui/src/features/setupPanel/setupPanel.store.ts":{"10":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","14":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","20":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","22":[46],"29":[31,46],"34":[31,46]},"packages/frontend/editor-ui/src/features/shared/banners/banners.store.ts":{"14":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","28":[46],"32":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","58":[46],"70":[46],"71":[46],"80":[46,134,75,184,185],"81":[46],"84":[46],"96":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","100":[95,46],"105":[46],"109":[46],"113":"b:f+r/+4P/5/92+v/v//j////////8////AAAAAAA=","116":[46],"117":[46]},"packages/frontend/editor-ui/src/features/shared/banners/components/BannerStack.vue":{"38":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","46":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","51":[95,46],"55":[95,46],"56":[95,46],"59":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","65":[95,46],"86":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","89":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useAgentNavigationCommands.ts":{"28":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","40":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","42":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","43":[107,40,111,5,45,46,60,69,88],"45":[46],"50":[46],"55":[46],"61":[46],"72":[46],"78":[46],"97":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","116":[46]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useChatHubCommands.ts":{"27":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","36":[4,111,5,112,6,17,46],"43":[4,111,5,112,6,17,46],"48":[46],"77":[4,111,5,112,6,17,46],"78":[4,111,5,112,6,17,46],"83":[4,111,5,112,6,17,46],"85":[4,111,5,112,6,17,46],"86":[4,111,5,112,6,17,46],"101":[4,111,5,112,6,17,46],"117":[46],"123":[4,111,5,112,6,17,46],"124":[4,111,5,112,6,17,46],"127":[4,111,5,112,6,17,46],"142":[46],"148":[4,111,5,112,6,17,46],"149":[4,111,5,112,6,17,46],"152":[4,111,5,112,6,17,46],"161":[46],"167":[4,111,5,112,6,17,46],"168":[4,111,5,112,6,17,46],"171":[4,111,5,112,6,17,46],"177":[46],"246":[46]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useCommandBar.ts":{"88":[46],"92":[46,187],"108":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","116":"b:X+r/+4P/5/92+v/v//j////////8////AAAAAAA=","123":"b:X+r/+4P/5/92+v/v//j////////8////AAAAAAA=","150":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","151":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","153":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","160":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","168":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","177":"b:D+qF+wP+4PlC+v/HwmAM8H/+P/D8////AAAAAAA=","180":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","183":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","188":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","190":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","191":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","194":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","196":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","198":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","202":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","206":[46],"211":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","213":[46],"225":[46],"228":[46],"234":[46],"238":[46],"259":[46],"260":[46],"282":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","285":[46,187],"288":[46,187],"299":[46],"303":[46],"313":[46],"323":[46],"341":[46],"351":[46,187],"378":[46],"379":[46],"394":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","398":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","406":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","411":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","415":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","417":[46],"426":[46],"431":[46],"454":[46],"461":[46],"473":[46,187],"477":[46,187],"482":[46,187],"493":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","494":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useCredentialNavigationCommands.ts":{"26":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","40":[46],"41":[46],"44":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","46":[46],"53":[46],"73":[46],"79":[46],"96":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","118":[46],"149":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","152":[46,187]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useDataTableNavigationCommands.ts":{"24":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","37":[46],"43":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","45":[46],"46":[46],"49":[46],"56":[46],"72":[46],"78":[46],"98":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","119":[46],"136":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useExecutionCommands.ts":{"27":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","38":[46,62,169,170,79,18,186,187,188],"40":[46,62,169,170,79,18,186,187,188],"46":[46,62,169,170,79,18,186,187,188],"50":[46,62,169,170,79,18,186,187,188],"56":[46,62,169,170,79,18,186,187,188],"61":[46],"67":[46],"69":[46],"78":[46,62,169,170,79,18,186,187,188],"84":[46,62,169,170,79,18,186,187,188],"89":[46],"113":[46],"132":[46],"149":[46],"178":[46],"194":[46],"204":[46],"214":[46,62,169,170,79,18,186,187,188],"242":[46],"255":[46],"288":[46],"304":[46]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useExecutionNavigationCommands.ts":{"10":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","18":[46],"19":[46],"22":[46],"28":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","44":[46]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useGenericCommands.ts":{"31":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","40":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","45":[46],"65":[46],"84":[46],"107":[46],"126":[46],"143":[46],"158":[46],"173":[46],"188":[46],"203":[46],"218":[46],"233":[46],"248":[46]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useInstanceAiCommands.ts":{"20":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","26":"b:X+r/+4P+5/92+v/u//j////////8////AAAAAAA=","27":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","32":[46],"38":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","46":[46],"59":[46],"85":[46,187]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useNodeCommands.ts":{"25":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","38":"b:D+oF+AN+4PFA+v/HwmAI8H/+P7D8////AAAAAAA=","41":"b:D+oF+AN+4PFA+v/HwmAI8H/+P7D8////AAAAAAA=","43":"b:D+oF+AN+4PFA+v/HwmAI8H/+P7D8////AAAAAAA=","47":"b:D+oF+AN+4PFA+v/HwmAI8H/+P7D8////AAAAAAA=","52":[46],"56":[46],"57":[46],"60":[46],"73":[46],"81":[46],"97":[46],"103":[46],"104":[46],"107":[46],"108":[46],"111":[46],"115":[46],"116":[46],"121":"b:D+oF+AN+4PFA+v/HwmAI8H/+P7D8////AAAAAAA=","135":[46],"154":"b:D+oF+AN+4PFA+v/HwmAI8H/+P7D8////AAAAAAA="},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useProjectNavigationCommands.ts":{"22":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","30":[46],"47":[46],"53":[46],"71":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","88":[46],"101":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useRecentResources.ts":{"55":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","73":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","92":[23,24,25],"95":[23,24],"99":"b:D+IF+AM+4PFA+v5HgEAIAH5uJbDs/+/fAAAAAAA=","105":"b:CuIFOAAOQBFAOv4EgEAAAG4uJSDk/m8CAAAAAAA=","108":"b:AqIFCAAMAAEAInYAAAAAAAgoACDkvgMAAAAAAAA=","124":[187],"132":[187],"140":[187],"172":[187],"208":[187],"210":[187],"216":[187],"219":[187],"224":[187],"228":[187],"237":[187],"245":[187],"246":[187],"252":[187]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useWorkflowCommands.ts":{"50":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","67":"b:D+oF+AN+4PFA+v/HwmAI8H/+P7D8////AAAAAAA=","70":"b:D+oF+AN+4PFA+v/HwmAI8H/+P7D8////AAAAAAA=","72":"b:D+oF+AN+4PFA+v/HwmAI8H/+P7D8////AAAAAAA=","76":"b:D+oF+AN+4PFA+v/HwmAI8H/+P7D8////AAAAAAA=","80":"b:D+oF+AN+4PFA+v/HwmAI8H/+P7D8////AAAAAAA=","83":"b:D+oF+AF+4PFA+v9HgmAI8H/+P7D8/3//AAAAAAA=","84":"b:BgIFgABs4BFAAgACAAAAAECAADAAAAAAAAAAAAA=","96":"b:BgIFgABs4BFAAgACAAAAAECAADAAAAAAAAAAAAA=","99":[46],"116":"b:D+oF+AN+4PFA+v/HwmAI8H/+P7D8////AAAAAAA=","123":[46],"137":[46],"162":[46],"182":[46],"198":[46],"212":[46],"233":[46],"247":[46],"263":[46],"286":"b:D+oF+AN+4PFA+v/HwmAI8H/+P7D8////AAAAAAA=","288":"b:D+oF+AF+4PFA+v9HgmAI8H/+P7D8/3//AAAAAAA=","289":[46,181,182,87],"290":[46,181,182,87],"296":[46,182,87],"306":[46,182,87],"309":[46],"328":"b:D+oF+AN+4PFA+v/HwmAI8H/+P7D8////AAAAAAA=","334":[46],"343":[46],"369":"b:D+oF+AN+4PFA+v/HwmAI8H/+P7D8////AAAAAAA=","385":[46],"399":[46],"406":"b:D+oF+AN+4PFA+v/HwmAI8H/+P7D8////AAAAAAA=","422":[46],"439":[46],"453":[46],"460":"b:D+oF+AN+4PFA+v/HwmAI8H/+P7D8////AAAAAAA=","470":"b:D+oF+AN+4PFA+v/HwmAI8H/+P7D8////AAAAAAA="},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useWorkflowNavigationCommands.ts":{"29":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","44":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","46":[46],"57":[46],"71":[46],"80":[46],"98":[46],"104":[46],"105":[46],"107":[46],"115":[46],"160":[46],"167":[46],"170":[46],"174":"b:f+r/+4P/5/92+v/v//z////////8////AAAAAAA=","196":[46],"216":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","219":[46,187]},"packages/frontend/editor-ui/src/features/shared/contextMenu/components/ContextMenu.vue":{"17":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","26":[1,46,144,77,162,78,164,165,172,177,182],"30":[1,46,144,77,162,78,164,165,172,177,182],"51":[1,46,144,77,162,78,164,165,172,177,182],"59":[1,46,144,77,162,78,164,165,172,177,182],"66":[1,46,144,77,162,78,164,165,172,177,182],"69":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","76":[1,46,144,77,162,78,164,165,172,177,182],"77":[1,46,144,77,162,78,164,165,172,177,182],"93":[1,46,144,77,162,78,164,165,172,177,182],"94":[1,46,144,77,162,78,164,165,172,177,182],"106":[1,46,144,77,162,78,164,165,172,177,182],"107":[1,46,144,77,162,78,164,165,172,177,182]},"packages/frontend/editor-ui/src/features/shared/contextMenu/composables/contextMenuGroupView.ts":{"20":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA="},"packages/frontend/editor-ui/src/features/shared/contextMenu/composables/useContextMenu.ts":{"28":[46],"32":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","35":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","37":[1,46,144,77,162,78,164,165,172,177,182],"49":[46],"56":[1,46,144,77,162,78,164,165,172,177,182],"60":[1,46,144,77,162,78,164,165,172,177,182],"62":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","67":[1,46,144,77,162,78,164,165,172,177,182],"88":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","94":[1,46,144,77,162,78,164,165,172,177,182]},"packages/frontend/editor-ui/src/features/shared/contextMenu/composables/useContextMenuItems.ts":{"78":[1,46,144,77,162,78,164,165,172,177,182],"84":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","105":[1,46,144,148,77,162,78,164,165,172,177,182],"109":[1,46,144,148,77,162,78,164,165,172,177,182],"119":[46],"129":[1,46,144,148,77,162,78,164,165,172,177,182],"131":[1,46,144,148,77,162,78,164,165,172,177,182],"135":[1,46,144,148,77,162,78,164,165,172,177,182],"145":[1,46,144,148,77,162,78,164,165,172,177,182],"147":[1,46,144,148,77,162,78,164,165,172,177,182],"148":[1,46,144,148,77,162,78,164,165,172,177,182],"154":[1,46,144,148,77,162,78,164,165,172,177,182],"156":[1,46,144,148,77,162,78,164,165,172,177,182],"166":[1,46,144,148,77,162,78,165,172,177,182],"170":[1,46,144,148,77,162,78,164,165,172,177,182],"185":[1,46,144,77,162,78,164,165,172,177,182],"194":[1,46,144,148,77,162,78,165,172,177,182],"199":[1,46,144,148,77,162,78,164,165,172,177,182],"206":[1,46,144,148,77,162,78,164,165,172,177,182],"209":[46,78],"214":[46],"217":[46],"239":[1,46,144,148,77,162,78,164,165,172,177,182],"243":[46],"288":[1,46,144,148,77,162,78,164,165,172,177,182],"398":[1,46,144,148,77,162,78,164,165,172,177,182],"421":[46,78],"429":[46,78],"447":[46,78],"456":[46,78],"481":[46],"488":[1,46,144,148,77,162,78,165,172,177,182],"496":[1,46,144,148,77,162,78,165,172,177,182],"503":[1,46,144,148,77,162,78,165,172,177,182]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/completions/js.snippets.ts":{"8":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/theme.ts":{"91":"b:CgABEABGAAAEMi5AAAAAAAEgEADkaCMQAAAAAAA="},"packages/frontend/editor-ui/src/features/shared/editors/components/InlineExpressionEditor/InlineExpressionEditorInput.vue":{"26":"b:BsoFCABAAAACEK8AAAAAAECKIQAAZA8AAAAAAAA=","39":"b:BsoFCABAAAACEK8AAAAAAECKIQAAZA8AAAAAAAA=","51":"b:BsoFCABAAAACEK8AAAAAAECKIQAAZA8AAAAAAAA=","55":[46],"75":"b:BsoFCABAAAACEK8AAAAAAECKIQAAZA8AAAAAAAA=","81":"b:AoAFCABAAAACAC8AAAAAAEAIAAAAZA4AAAAAAAA=","88":"b:BsoFCABAAAACEK8AAAAAAECKIQAAZA8AAAAAAAA=","97":"b:AEABAABAAAACAC8AAAAAAAAAAAAAYA4AAAAAAAA=","104":"b:AEABAABAAAACAC8AAAAAAAAAAAAAYA4AAAAAAAA=","107":"b:AEABAABAAAACAA8AAAAAAAAAAAAAYA4AAAAAAAA=","112":[46],"118":"b:BsoFCABAAAACEK8AAAAAAECKIQAAZA8AAAAAAAA="},"packages/frontend/editor-ui/src/features/shared/editors/components/InlineExpressionEditor/InlineExpressionEditorOutput.vue":{"26":"b:BsoFCABAAAACEK8AAAAAAECKIQCAZA8AAAAAAAA=","39":"b:AEABAABAAAACAC8AAAAAAAAAAACAYA4AAAAAAAA=","40":[46,65,167,80,81,82,83,174,16,85,177,179],"45":"b:BsoECABAAAACECoAAAAAAACIAQCAJAAAAAAAAAA=","52":"b:BsoFCABAAAACEK8AAAAAAECKIQCAZA8AAAAAAAA=","69":"b:AEABAABAAAACAC8AAAAAAAAAAACAYA4AAAAAAAA=","73":"b:AEABAABAAAACAC8AAAAAAAAAAACAYA4AAAAAAAA=","79":"b:AEABAABAAAACAC8AAAAAAAAAAACAYA4AAAAAAAA="},"packages/frontend/editor-ui/src/features/shared/editors/components/InlineExpressionEditor/theme.ts":{"4":"b:BsoFCABAAAACEK8AAAAAAECKIQCAZA8AAAAAAAA=","18":"b:BsoFCABAAAACEK8AAAAAAECKIQAAZA8AAAAAAAA=","58":"b:BsoFCABAAAACEK8AAAAAAECKIQCAZA8AAAAAAAA="},"packages/frontend/editor-ui/src/features/shared/editors/components/JsEditor/JsEditor.vue":{"31":[1,46],"36":[1,46],"40":[1,46],"41":[46],"57":[1,46],"65":[46],"73":[1,46],"77":[1,46],"102":[1,46],"111":[46],"121":[1,46]},"packages/frontend/editor-ui/src/features/shared/editors/composables/useExpressionEditor.ts":{"73":"b:BsoFCABAAAACEK8AAAAAAECKIQCAZA8AAAAAAAA=","84":[46,65,80,81,82,173,83,174,16,177,178,179],"99":"b:BsoFCABAAAACEK8AAAAAAECKIQCAZA8AAAAAAAA=","118":"b:BsoFCABAAAACEK8AAAAAAECKIQCAZA8AAAAAAAA=","123":"b:BsoFCABAAAACEC8AAAAAAECIAQCAZA4AAAAAAAA=","137":"b:BsoFCABAAAACEC8AAAAAAECIAQCAZA4AAAAAAAA=","157":"b:BsoFCABAAAACEC8AAAAAAECIAQCAZA4AAAAAAAA=","192":"b:BsoFCABAAAACEK8AAAAAAECKIQCAZA8AAAAAAAA=","196":"b:AoAFCABAAAACAC8AAAAAAEAIAACAZA4AAAAAAAA=","202":"b:BsoFCABAAAACEK8AAAAAAECKIQCAZA8AAAAAAAA=","213":"b:BsoFCABAAAACEK8AAAAAAECKIQCAZA8AAAAAAAA=","217":"b:BsoFCABAAAACEK8AAAAAAECKIQCAZA8AAAAAAAA=","228":"b:BsoBCABAAAACEC4AAAAAAACAAACAYA0AAAAAAAA=","236":"b:BsoBCABAAAACEC8AAAAAAACAAACAYA8AAAAAAAA=","243":[46,167,80,81,82,173,83,174,16,177,178,179],"254":"b:BsoFCABAAAACEK8AAAAAAECKIQAAZA8AAAAAAAA=","265":"b:BsoFCABAAAACEK8AAAAAAECKIQCAZA8AAAAAAAA=","292":"b:AEABAABAAAACAC8AAAAAAAAAAACAYA4AAAAAAAA=","297":"b:AEABAABAAAACAA8AAAAAAAAAAAAAYA4AAAAAAAA=","309":"b:AAABAABAAAACACsAAAAAAAAAAACAYA4AAAAAAAA=","327":"b:BsoFCABAAAACEK8AAAAAAECKIQCAZA8AAAAAAAA=","335":"b:BsoFCABAAAACEK8AAAAAAECKIQCAZA8AAAAAAAA=","345":"b:BsoFCABAAAACEK8AAAAAAECKIQCAZA8AAAAAAAA=","357":"b:BsoFCABAAAACEK8AAAAAAECKIQCAZA8AAAAAAAA=","368":"b:BsoFCABAAAACEK8AAAAAAECKIQCAZA8AAAAAAAA=","372":"b:BsoECABAAAACECoAAAAAAACIAQCAJAAAAAAAAAA=","379":[1,2,9,46,11,143,144,14,76,81,15],"381":[1,2,9,46,11,143,144,14,76,81,15],"387":[1,2,9,46,11,143,144,14,76,81,15],"397":"b:BsoFCABAAAACEC8AAAAAAECAAQCAZA4AAAAAAAA=","485":"b:BsoFCABAAAACEK8AAAAAAECKIQCAZA8AAAAAAAA=","487":"b:BsoFCABAAAACEK8AAAAAAECKIQCAZA8AAAAAAAA=","488":"b:AoAFCABAAAACAC8AAAAAAEAIAACAZA4AAAAAAAA=","491":"b:AoAFCABAAAACAC8AAAAAAEAIAACAZA4AAAAAAAA=","492":"b:AoAFCABAAAACAC8AAAAAAEAIAACAZA4AAAAAAAA=","495":[46],"496":[46],"522":"b:BsoFCABAAAACEK8AAAAAAECKIQAAZA8AAAAAAAA=","525":"b:AoAFCABAAAACAC8AAAAAAEAIAAAAZA4AAAAAAAA=","555":"b:AoAFCABAAAACAC8AAAAAAEAIAAAAZA4AAAAAAAA=","571":"b:BsoFCABAAAACEK8AAAAAAECKIQCAZA8AAAAAAAA=","572":"b:BsoFCABAAAACEK8AAAAAAECKIQCAZA8AAAAAAAA=","582":"b:AEABAABAAAACAA8AAAAAAAAAAAAAYA4AAAAAAAA=","594":[46],"600":[46],"602":"b:AEABAABAAAACAA8AAAAAAAAAAAAAYA4AAAAAAAA="},"packages/frontend/editor-ui/src/features/shared/editors/composables/useRedactionHint.ts":{"11":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","15":"b:BsoFAABAAAACEC8AAAAAAECIIQAAZA4AAAAAAAA=","19":"b:BsoFAABAAAACEC8AAAAAAECIIQAAZA4AAAAAAAA=","21":[46]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/addCompletions.ts":{"8":"b:BsoFCABAAAACEK8AAAAAAECKIQCAZA8AAAAAAAA=","15":"b:BsoFCABAAAACEK8AAAAAAECKIQCAZA8AAAAAAAA="},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/constants.ts":{"467":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","471":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/datatype.completions.ts":{"75":"b:AAABAABAAAACAC8AAAAAAAAAAACAYA4AAAAAAAA=","163":[46,81,82,16,177],"179":[46,81,82,83,174,16,177],"181":[46,81,82,83,174,16,177],"187":[46,81,82,83,174,16],"188":[46,81,82,83,174,16],"205":[46,81,82,83,174,16,177],"208":[46,81,82,83,174,16,177],"210":[46,81,82,83,174,16,177],"211":[46,81,82,83,174,16,177],"215":[46,83,174],"231":[46],"240":[46,81,82,83,174,16,177],"261":[46,81,82,83,174,16,177],"263":[46],"285":[46,81,82,83,174,16],"287":[46],"292":[46,81,82,83,174,16],"315":[46,81,82,83,174,16],"318":[46],"324":[46,81,82,83,174,16],"330":[46,81,82,83,174,16],"342":[46,81,82,16],"348":[46,81,82,16],"353":[46,81,82,16],"362":[46,81,82,16],"368":[46,81,82,83,174,16],"372":[46],"380":[46,81,82,83,174,16],"381":[46,81,82,83,174,16],"382":[46,81,82,83,174,16],"392":[46,81,82,83,174,16,177],"396":[46],"414":[46,81,82,83,174,16],"422":[46,81,82,16,177],"453":[46,81,82,16,177],"457":[46],"466":[46],"472":[46,177],"476":[46,81,82,16],"477":[46,81,82,16],"527":[46,81,82,83,174,16,177],"545":[46,81,82,83,174,16,177],"553":[46,81,82,83,174,16,177],"561":[46,81,82,83,174,16,177],"562":[46,81,82,83,174,16,177],"573":[46,83,174],"574":[46,83,174],"578":[46,83,174],"583":[46,83,174],"633":[46,83,174],"668":[46],"677":[46],"681":[46],"700":[46,174],"731":[46,174],"737":[46],"739":[46],"744":[46,83],"752":[46,83],"763":[46,174],"776":[46,174],"779":[46],"784":[46,81,82,16],"793":[46],"797":[46],"818":[46],"820":[46],"838":[46],"863":[46],"866":[46],"897":[46],"900":[46],"982":[46],"985":[46,177],"1077":[46,177],"1078":[46,177],"1084":[46],"1150":[46],"1151":[46],"1157":[46],"1174":[46],"1177":[46],"1191":[46],"1194":[46],"1231":[46],"1234":[46],"1251":[46],"1254":[46],"1272":[46],"1295":[46],"1299":[46],"1322":[46],"1327":[46],"1330":[46],"1352":[46,83],"1354":[46],"1362":[46,83],"1363":[46,83],"1364":[46,83],"1380":[46,83],"1385":[46,83],"1386":[46,83],"1397":[46,83],"1402":[46],"1454":[46],"1537":[46],"1560":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/infoBoxRenderer.ts":{"6":[46,83,174],"18":[46,83,174],"31":[46,83,174],"64":[46,177],"76":[46,83,174,177],"100":[46],"117":[46,83,174],"166":[46,83,174],"170":[46,83,174],"177":[46,83,174],"189":[46,83,174],"217":[46,83,174],"238":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","239":[46,83,174,177]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/utils.ts":{"27":[46,167,80,81,82,173,83,174,16,177],"48":[46],"52":[46],"60":[46],"64":[46],"72":[46],"83":[46,80,81,82,83,174,16,177],"91":[46],"94":[46],"119":[46,81,82,16,177],"122":[46,81,82,16,177],"131":[46,65,167,80,81,82,173,83,174,16,177,179],"134":[46,81,82,16],"143":[46,81,82,16],"159":[46],"169":[46,167,80,81,82,173,83,174,16,177,179],"183":[46,177],"207":[46,65,167,80,81,82,173,83,174,16,177,179],"232":"b:BsoFCABAAAACEC8AAAAAAECAAQCAZA4AAAAAAAA=","234":[46,65,167,80,81,82,173,83,174,16,177,179],"252":[46,167,80,81,82,173,83,174,16,177,179],"269":[46,81,82,16,177],"271":[46,81,82,16,177],"274":"b:AAABEABCAAAAMg9AAAAAAAAgEADkYAsQAAAAAAA=","292":[46],"298":"b:AAABEABCAAAAMg9AAAAAAAAgEADkYAsQAAAAAAA=","302":"b:AAABEABCAAAAMg9AAAAAAAAAEADkYAsQAAAAAAA=","303":"b:AAABEABCAAAAMg9AAAAAAAAAEADkYAsQAAAAAAA=","310":[46,65,167,80,81,82,173,83,174,16,177,179],"314":[46,65,167,80,81,82,173,83,174,16,177,179],"315":[46,65,167,80,81,82,173,83,174,16,177,179],"319":[46,65,167,80,81,82,173,83,174,16,177,179],"328":[46,65,167,80,81,82,173,83,174,16,177,179],"339":[46],"353":[46,81,82,83,174,16,177],"356":[46,81,82,83,174,16,177],"357":[46,81,82,83,174,16,177],"358":[46,81,82,83,174,16,177],"362":[46],"376":[46,167,80,81,82,173,83,174,16,177,179],"380":[46],"385":[46],"406":[46],"416":[46],"432":[46,81,82,83,174,16,177],"434":[46,81,82,83,174,16,177],"438":[46,81,82,83,174,16],"439":[46,81,82,83,174,16],"442":[46,81,82,16,177],"453":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","458":[46],"464":[46,81,82,16],"481":[46,81,82,83,174,16,177]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/dragAndDrop.ts":{"9":[46],"15":"b:DsoFGABGAAAGMq9AAAAAAEGqMQDkbC8QAAAAAAA=","18":"b:BsoFGABAAAACEK9AAAAAAECKMQDAZC8AAAAAAAA=","20":"b:BsoFGABAAAACEK9AAAAAAECKMQDAZC8AAAAAAAA=","35":"b:DsoFGABGAAAGMq9AAAAAAEGqMQDkbC8QAAAAAAA=","42":"b:DsoFGABGAAAGMq9AAAAAAEGqMQDkbC8QAAAAAAA=","46":"b:DsoFGABCAAAGMq9AAAAAAEGqMQDkbC8QAAAAAAA=","67":[46],"80":[46],"93":"b:DsoFCABCAAACMi5AAAAAAAGoEQDkZAMQAAAAAAA=","97":"b:AAABAABAAAACAC8AAAAAAAAAAACAYC8AAAAAAAA=","104":"b:AAABAABAAAACAC8AAAAAAAAAAADAYA8AAAAAAAA=","112":"b:AAABAABAAAACAC4AAAAAAAAAAACAYC4AAAAAAAA=","115":"b:AAABAABAAAACAC8AAAAAAAAAAACAYA8AAAAAAAA=","123":[46,82],"127":[46,82],"139":[46,82],"143":[46,82],"156":[46],"163":"b:DsoFGABGAAAGMq9AAAAAAEGqMQDkbC8QAAAAAAA="},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/expressionCloseBrackets.ts":{"10":"b:BsoFCABAAAACEK8AAAAAAECKIQCAZA8AAAAAAAA=","14":"b:AAABAABAAAACAA8AAAAAAAAAAACAYA4AAAAAAAA=","36":"b:BsoFCABAAAACEK8AAAAAAECKIQCAZA8AAAAAAAA="},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/expressionDeprecations.ts":{"11":"b:BsoFCABAAAACEC8AAAAAAECAAQCAZA4AAAAAAAA=","15":"b:BsoFCABAAAACEC8AAAAAAECAAQCAZA4AAAAAAAA="},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/format.ts":{"10":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","13":[46],"14":[46],"19":[46]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/keymap.ts":{"83":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","100":[46,82],"261":"b:AAABAABAAAAAAA8AAAAAAAAAAACAYA8AAAAAAAA="},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/multiCursor.ts":{"4":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","5":[46],"23":[46]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/n8nLang.ts":{"11":[46,139,81,82,173,83,174],"14":"b:BsoFCABAAAACEK8AAAAAAECKIQAAZA8AAAAAAAA=","25":"b:BsoFCABAAAACEK8AAAAAAECKIQAAZA8AAAAAAAA=","28":"b:BsoFCABAAAACEK8AAAAAAECKIQAAZA8AAAAAAAA=","32":"b:DsoFCABEAAAGEK8AAAAAAEGKIQCEbC8AAAAAAAA=","37":[46,81,82,16,177]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/resolvableHighlighter.ts":{"56":[46],"64":[46],"75":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","76":"b:AsAFCABAAAACAC8AAAAAAEAIAACAZA4AAAAAAAA=","79":"b:AsAFCABAAAACAC8AAAAAAEAIAACAZA4AAAAAAAA=","105":[46,167,82,83,174],"111":[46,82,16,85,179],"131":"b:AsAFCABAAAACAC8AAAAAAEAIAACAZA4AAAAAAAA=","132":"b:AsAFCABAAAACAC8AAAAAAEAAAACAZA4AAAAAAAA=","145":"b:AsAFCABAAAACAC8AAAAAAEAIAACAZA4AAAAAAAA=","146":[46,139,167,170,82,173,83,174,16]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/tooltips/InfoBoxTooltip.ts":{"27":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","28":"b:BsoFCABAAAAAEC8AAAAAAECKIQAAZA8AAAAAAAA=","44":[46,81,83,174,177,179],"55":[46,83,174],"74":[46,81,83,174,177,179],"96":[46,81,173,83,174,177,179],"116":[46,81,173,83,174,177,179],"119":"b:BsoFCABAAAACEC8AAAAAAECKIQAAZA8AAAAAAAA=","123":"b:BsoFCABAAAAAEC8AAAAAAECKIQAAZA8AAAAAAAA=","127":"b:BsoFCABAAAACEK8AAAAAAECKIQAAZA8AAAAAAAA=","142":[46,81,83,174,177,179],"143":[46,81,173,83,174,177,179],"166":[46,81,83,174,177,179],"188":[46,83,174],"202":"b:BsoFCABAAAACEK8AAAAAAECKIQAAZA8AAAAAAAA=","256":[46,81,83,174,177,179],"262":[46,83,174],"274":"b:BsoFCABAAAACEK8AAAAAAECKIQAAZA8AAAAAAAA=","282":"b:BsoFCABAAAACEK8AAAAAAECKIQAAZA8AAAAAAAA=","291":"b:BsoFCABAAAACEK8AAAAAAECKIQAAZA8AAAAAAAA=","315":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","319":"b:BsoFCABAAAACEK8AAAAAAECKIQAAZA8AAAAAAAA=","322":"b:BsoFCABAAAACEK8AAAAAAECKIQAAZA8AAAAAAAA=","352":"b:BsoFCABAAAACEK8AAAAAAECKIQAAZA8AAAAAAAA=","360":[46,81,174,177],"378":[46,174],"381":[46,174],"423":"b:BsoBGABCAAACMi5AAAAAAACgEADkYA0AAAAAAAA=","435":"b:BsoFCABAAAACEK8AAAAAAECKIQAAZA8AAAAAAAA=","436":[46],"443":"b:BsoECABAAAACECoAAAAAAACIAQAAJAAAAAAAAAA=","449":"b:BsoFCABAAAACEK8AAAAAAECKIQAAZA8AAAAAAAA="},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/typescript/client/facet.ts":{"9":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/features/shared/envFeatureFlag/useEnvFeatureFlag.ts":{"5":"b:f+r/+4P/5/92+v/v+/r////////8////AAAAAAA=","8":"b:X+r/+4P+5/92+v/u+/j////////8////AAAAAAA="},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/CategoryItem.vue":{"12":"b:BsoBKAAKQJFAOp5AgCAA8C+gABDkZh8CAAAAAAA=","16":"b:BsoBKAAKQJFAOp5AgCAA8C+gABDkZh8CAAAAAAA=","20":"b:BsoBKAAKQJFAOp5AgCAA8C+gABDkZh8CAAAAAAA="},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/NodeItem.vue":{"41":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","56":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","63":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","84":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","100":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","101":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","106":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","111":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","115":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","119":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","125":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","127":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","132":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","133":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","135":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","144":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","148":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","152":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","160":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","172":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","198":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","220":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","233":"b:BsIBIAAKAAFAOgRAACAAcAmgABDkABMCAAAAAAA=","236":"b:BsIBIAAKAAFAOgRAACAAcAmgABDkABMCAAAAAAA=","246":[129],"251":[129],"266":[73],"273":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA="},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/SubcategoryItem.vue":{"13":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","15":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","16":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA="},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/ViewItem.vue":{"16":"b:BgIBKAAqQJFAOt9EgAAA4AagDhDkah8CAAAAAAA="},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/Modes/NodesMode.vue":{"50":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","75":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","76":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","79":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","83":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","85":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","86":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","90":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","92":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","105":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","108":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","120":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","122":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","201":"b:BAIBIAAKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","245":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","257":[41,76],"265":[41,76],"273":[41,76],"283":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","301":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA="},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/NodeCreator.vue":{"57":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","59":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","67":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","75":[76],"86":"b:BsoNqAIqRJFAut9EgCAA8C+gDhDkbx8eAAAAAAA=","90":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","94":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","122":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","126":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","127":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","137":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","145":[41,125,16],"148":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","152":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","163":"b:AgAMgAIABBAAiEAAAAAAAAAAAAAABwAcAAAAAAA=","168":[84]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/NodeCreatorShortcutCoachmark.vue":{"14":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","28":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA="},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/Panel/NodesListPanel.vue":{"34":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","46":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","57":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","59":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","61":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","63":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","65":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","67":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","87":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","92":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","94":[129],"98":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","105":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","117":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","143":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","153":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","164":[27,41,124,125,76,162,165,16],"172":"b:BsoBIAAKQAFAOpJAgAAA8AMgABDkIB8CAAAAAAA=","179":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","183":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","191":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","197":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","198":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","225":[125,127],"227":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","239":[41,124,125,162,165]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/Panel/SearchBar.vue":{"16":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","26":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","30":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","39":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","44":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","52":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA="},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/Renderers/CategorizedItemsRenderer.vue":{"28":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","38":"b:BsoBKAAKQJFAOp5AgCAA8C+gABDkZh8CAAAAAAA=","39":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","41":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","45":[128],"49":[128],"62":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","83":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","97":[41,76],"106":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","122":"b:BsoBKAAKQJFAOp5AgCAA8C+gABDkZh8CAAAAAAA=","153":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","154":[124,176,16,178,179]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/Renderers/ItemsRenderer.vue":{"30":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","45":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","47":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","49":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","53":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","63":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","80":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","122":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","126":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","133":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","134":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","141":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","154":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","163":[1,126,15],"186":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA="},"packages/frontend/editor-ui/src/features/shared/nodeCreator/composables/useActions.ts":{"58":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","65":"b:BAIBIABKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","72":"b:BAIBIABKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","76":"b:BAIBIABKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","77":"b:BAIBIABKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","97":"b:BAIBIABKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","98":"b:BAIBIABKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","103":"b:BAIBIABKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","154":"b:BAIBIABKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","170":"b:BAIBIABKQAFAOoJAgAAAEAEgABDkIB8CAAAAAAA=","173":"b:AAIBIABKAABAOgJAAAAAAAEgABDkIBcCAAAAAAA=","188":"b:BAIBIABKQAFAOoJAgAAAEAEgABDkIB8CAAAAAAA=","217":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","243":"b:BsoBKABqQJFAOs9EgCAA8CagDhD0bh8KAAAAAAA=","251":"b:BsoBKABqQJFAOs9EgCAA8C+gDhD0bh8KAAAAAAA=","253":"b:BsoBKABqQJFAOs9EgCAA8C+gDhD0bh8KAAAAAAA=","256":"b:BsoBKABqQJFAOs9EgCAA8C+gDhD0bh8KAAAAAAA=","268":"b:BsoBKABqQJFAOs9EgCAA8C+gDhD0bh8KAAAAAAA=","278":"b:BsoBKABqQJFAOs9EgCAA8C+gDhD0bh8KAAAAAAA=","283":[1,46],"287":"b:BsoBKABqQJFAOs9EgCAA8C+gDhD0bh8KAAAAAAA=","291":"b:BsoBKABqQBFAOs9EgCAA8C+gDhD0bh8KAAAAAAA=","306":"b:BsoBKABqQJFAOs9EgCAA8C+gDhD0bh8KAAAAAAA=","315":"b:BsoBKABqQJFAOs9EgCAA8C+gDhD0bh8KAAAAAAA=","318":"b:BsoBKABqQJFAOs9EgCAA8C+gDhD0bh8KAAAAAAA=","325":"b:BsoBKABqQJFAOs9EgCAA8C+gDhD0bh8KAAAAAAA=","367":"b:BsoBKABqQJFAOs9EgCAA8C+gDhD0bh8KAAAAAAA=","401":"b:BsoBKABqQJFAOs9EgCAA8C+gDhD0bh8KAAAAAAA=","405":"b:BsoBKABqQJFAOs9EgCAA8C+gDhD0bh8KAAAAAAA=","406":"b:BsoBAABAAAAAAAAAACAAUAuABgAAAA0AAAAAAAA=","415":"b:BAIBIABKQAFAOoJAgAAAUAEgABDkIB8CAAAAAAA=","420":"b:BAIBIABKQAFAOoJAgAAAUAEgABDkIB8CAAAAAAA=","430":"b:BAIBIABKQAFAOoJAgAAAEAEgABDkIB8CAAAAAAA="},"packages/frontend/editor-ui/src/features/shared/nodeCreator/composables/useActionsGeneration.ts":{"32":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","38":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","46":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","49":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","62":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","68":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","83":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","104":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","114":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","120":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","126":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","133":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","148":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","153":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","157":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","161":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","179":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","184":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","192":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","210":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","213":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","234":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","245":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","264":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","267":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","271":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","273":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","274":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","278":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","291":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","329":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","330":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","348":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","351":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","362":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","392":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","399":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","421":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","422":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","427":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","433":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","444":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","445":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","449":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA="},"packages/frontend/editor-ui/src/features/shared/nodeCreator/composables/useGetNodeCreatorFilter.ts":{"9":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","13":[1,2,46,11,14,15,16],"30":[1,2,46,11,14,15,16],"49":[1,46,11,14,15]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/composables/useKeyboardNavigation.ts":{"14":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","20":[41,46,125,76,16],"43":[41,46,76],"46":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","51":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","52":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","55":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","64":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","72":[41,46,125,76,16],"74":[41,46,125,76,16],"76":[41,46,125,76,16],"89":[27,41,46,124,125,76,162,165,16],"112":[41,46,125,76,16],"137":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","141":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","151":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","157":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","161":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","170":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","171":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","180":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","185":"b:BgoBIABKQAFAOpJAgAAA8AMgABDkIB8CAAAAAAA=","186":"b:BgoBIABKQAFAOpJAgAAA8AMgABDkIB8CAAAAAAA="},"packages/frontend/editor-ui/src/features/shared/nodeCreator/composables/useNodeCreatorShortcutCoachmark.ts":{"7":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","12":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","16":[46],"22":"b:AgAMgAJABBAAiEAAAAAAAAAAAAAABwAcAAAAAAA=","26":[46]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/composables/useViewStacks.ts":{"119":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","126":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","136":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","168":[46],"171":[46],"182":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","201":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","214":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","218":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","222":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","226":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","230":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","231":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","237":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","255":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","256":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","258":[46],"269":[29,43,46,125],"271":[46],"272":[46],"284":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","286":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","290":[1,2,9,46,11,143,14,15,16],"291":[1,2,9,46,11,143,14,15,16],"302":[1,2,46,11,14,15,16],"303":[1,2,46,11,14,15],"305":[46],"306":[46],"317":[1,46,11,14,15],"325":[1,46,11,14,15],"326":[1,46,11,14,15],"329":[1,46,11,14,15],"343":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","348":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","360":[1,2,9,46,11,14,15,16],"401":[1,46,11,14,15],"433":[1,46,11,14,15],"448":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","449":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","465":[1,2,46,11,14,15,16],"484":[1,2,46,11,14,15,16],"517":[1,2,46,11,14,15,16],"533":[1,46,11,14,15],"540":[1,2,46,11,14,15,16],"554":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","569":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","583":[1,46,11,125,126],"609":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","633":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","634":[1,46,11,125,126],"638":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","653":"b:BgIBKABqQJFAOt9EgAAA4AagDhDkah8CAAAAAAA=","658":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","659":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","665":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","668":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","673":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","674":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","681":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","682":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","684":"b:BgoBKABqQJFAOt9EgAAA4AagDhDkah8CAAAAAAA=","689":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","700":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","705":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","706":[46,16],"713":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","725":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","747":[46,125,127],"754":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","756":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","760":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","769":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA="},"packages/frontend/editor-ui/src/features/shared/nodeCreator/nodeCreator.store.ts":{"51":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","53":"b:AIABKABCABAAAAAAAAAAIAMAAACkJAAIAAAAAAA=","73":[1,2,46,11,14,15,16],"74":[1,2,46,11,14,15,16],"77":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","81":[46],"82":[46],"85":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","89":"b:D+pt+AN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","93":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","97":[46,15,16],"118":[46,15,16],"143":"b:D+pt+AN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA=","182":"b:BsgBAABCAAAAEAAAAAAA4AAADgAACAgAAAAAAAA=","233":[46],"237":[46],"274":"b:AAAAKABCABAAAAAAAAAAIAMAAACkJAAIAAAAAAA=","285":[46],"296":[46],"301":[46],"309":[46],"334":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","340":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","344":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","351":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","379":"b:BsIBIABqQBFAOo9EgCAAQAaABhDkZh8CAAAAAAA=","395":"b:BsIBIABqQBFAOo9EgCAAQAaABhDkZh8CAAAAAAA=","435":[46,128],"439":"b:BAIBIABKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","448":[46],"452":[1,46,11,125,126],"459":[46],"463":"b:BsoBKABqQJFAOs9EgCAA8C+gDhDkbh8KAAAAAAA=","479":"b:D+pt+AN+5/FA+v/H4mMI8H/+P7D/////AAAAAAA="},"packages/frontend/editor-ui/src/features/shared/nodeCreator/nodeCreator.utils.ts":{"66":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","70":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","96":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","100":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","103":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","109":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","113":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","125":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","136":"b:BsoBKABqQJFAOt9EgAAA8AegDhDkah8CAAAAAAA=","137":"b:BsoBKABqQJFAOt9EgAAA8AegDhDkah8CAAAAAAA=","149":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","154":"b:AgIBKABqAJBAOI9AAAAA4CYAABDkZgcCAAAAAAA=","174":[46],"177":[46],"186":[46],"193":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","206":[46],"221":[46],"231":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","250":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","257":[46],"269":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","285":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","294":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","297":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","298":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","304":"b:RsoBKABqQJFAOt9EgCAA8C+gDhD0bh8KAAAAAAA=","308":"b:RsoBKABqQJFAOt9EgCAA8C+gDhD0bh8KAAAAAAA=","315":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","319":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","333":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","337":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","340":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","341":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8CAAAAAAA=","349":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","363":[1,46,11,14,15],"368":[1,46,11,14,15],"382":[1,46,11,14,15],"397":"b:BsoBKABqQJFAOt9EgAAA4AagDhDkah8CAAAAAAA=","402":"b:BsoBKABqQJFAOt9EgAAA4AagDhDkah8CAAAAAAA=","406":"b:BsoBKABqQJFAOt9EgAAA4AagDhDkah8CAAAAAAA=","407":"b:BsoBKABqQJFAOt9EgAAA4AagDhDkah8CAAAAAAA=","408":"b:BsoBKABqQJFAOt9EgAAA4AagDhDkah8CAAAAAAA=","417":"b:BsoBKABqQJFAOt9EgAAA4AagDhDkah8CAAAAAAA=","421":"b:BsoBKABqQJFAOt9EgAAA4AagDhDkah8CAAAAAAA=","432":"b:BsoBKABqQJFAOt9EgAAA4AagDhDkah8CAAAAAAA=","433":"b:BsoBKABqQJFAOt9EgAAA4AagDhDkah8CAAAAAAA=","449":"b:BsoBKABqQJFAOt9EgAAA4AagDhDkah8CAAAAAAA=","451":"b:BoIBKABqQJFAOt9EgAAA4AagDhDkah8CAAAAAAA=","465":"b:BsoBKABqQJFAOt9EgAAA4AagDhDkah8CAAAAAAA=","473":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","481":"b:D+pt+gN+5/FA+v/HwmMI8H/+/7D+////AAAAAAA=","484":"b:T+pt+gF+5/FC+v9HgmMI8H/+P/Dv/3//AAAAAAA=","490":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","507":[1,2,46,15],"531":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","577":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","579":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","592":[46,14],"598":[46,14],"603":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","628":[46,14],"629":[46,14],"633":"b:BsIBKABKQJFAOt5AgCAA8C+gDhDkbh8CAAAAAAA=","638":[46,129],"661":[46],"687":[46,127],"705":"b:BgIBKABqQJFAOt9EgAAA4AagDhDkah8CAAAAAAA=","726":"b:BgIBKABqQJFAOt9EgAAA4AagDhDkah8CAAAAAAA=","728":"b:BgIBKABqQJFAOt9EgAAA4AagDhDkah8CAAAAAAA=","729":"b:BgIBKABqQJFAOt9EgAAA4AagDhDkah8CAAAAAAA=","735":[46],"753":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","762":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","768":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","775":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","783":[46,126],"784":[46,126]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/views/NodeCreation.vue":{"51":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","80":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","87":"b:BsoBKAAqQJFAOt9EgCAA8C6gBhDkYh8CAAAAAAA=","94":[164],"116":"b:BsoBKAAqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","123":"b:BsoBKAAqQJFAOs9EgCAA8C+gDhDkbh8KAAAAAAA=","133":[148,163],"155":[27,30,63],"194":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","196":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","200":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","216":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","231":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","245":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","271":"b:D+oFAAEe4HFA+v/GgmAI8H/+P7D8////AAAAAAA=","283":[27,28,29,30,31,102,33,63],"292":[27,28,29,30,31,102,33,63]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/views/viewsData.ts":{"123":[1,2,46,11,14,15,16],"140":"b:BgIBKABqQJFAOt9EgAAA4AagDhDkah8CAAAAAAA=","157":"b:BgIBKABqQJFAOt9EgAAA4AagDhDkah8CAAAAAAA=","159":"b:BgIBKABqQJFAOt9EgAAA4AagDhDkah8CAAAAAAA=","163":"b:BgIBKABqQJFAOt9EgAAA4AagDhDkah8CAAAAAAA=","166":"b:BgIBKABqQJFAOt9EgAAA4AagDhDkah8CAAAAAAA=","192":"b:BgIBKABqQJFAOt9EgAAA4AagDhDkah8CAAAAAAA=","202":"b:BgIBKABqQJFAOt9EgAAA4AagDhDkah8CAAAAAAA=","207":"b:BgIBKABqQJFAOt9EgAAA4AagDhDkah8CAAAAAAA=","247":[1,2,46,11,14,15,16],"250":[1,2,46,11,14,15,16],"260":[1,2,46,11,14,15,16],"386":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","398":"b:BsoBKABqQJFAOt9EgCAA8C+gDhDkbh8KAAAAAAA=","525":"b:BgIBKABqQJFAOt9EgAAA4AagDhDkah8CAAAAAAA=","690":[46],"695":[46],"697":[46],"721":"b:BgIBKABqQJFAOt9EgAAA4AagDhDkah8CAAAAAAA="},"packages/frontend/editor-ui/src/features/shared/promotions/usePromotionsEnabled.ts":{"9":"b:f+r/+4P/5/92+v/v+/j////////8////AAAAAAA=","13":"b:f+r/+4P/5/92+v/v+/j////////8////AAAAAAA="},"packages/frontend/editor-ui/src/features/shared/tags/tags.api.ts":{"8":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","10":"b:AAABAABAAAAAAFAAAAAAABAAGAAAAIJoAAAAAAA=","13":[46,148,86,183,189],"19":[46],"26":[46,183]},"packages/frontend/editor-ui/src/features/shared/tags/tags.store.ts":{"34":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","39":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","51":[46,183,190],"52":[46,183,190],"55":[46,183,190],"57":[46],"61":"b:AAABAABAAAAAAFAAAAAAABAAGAAAAIJoAAAAAAA=","62":[46,183,187,189,190],"70":"b:C6BtAAFU5/BA4nQDIAMIAEhsEbAOn+H9AAAAAAA=","71":[46,148,86,183,189],"92":[46,183],"97":"b:AAABAABAAAAAAFAAAAAAABAAGAAAAIJoAAAAAAA=","119":[46,148,86,183,189],"131":[46],"142":[46],"152":[46,183]},"packages/frontend/editor-ui/src/features/workflow-reviews/composables/useWorkflowReviewDialogPreferences.ts":{"10":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA="},"packages/frontend/editor-ui/src/features/workflow-reviews/composables/useWorkflowReviewStatusSync.ts":{"14":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","20":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","30":"b:D+Jt+AE+5/NA+v5HoEAIAH5uJbDs/+/fAAAAAAA=","42":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","43":"b:BsIF+AIqQBMAONpGgEAAADYCJADkZo/LAAAAAAA=","50":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","51":[57],"57":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","60":[57],"63":[19,50,57,60,168,86,184]},"packages/frontend/editor-ui/src/features/workflow-reviews/composables/useWorkflowReviewsFeature.ts":{"6":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","9":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","15":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA="},"packages/frontend/editor-ui/src/features/workflow-reviews/reviewRequired.store.ts":{"7":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","15":[57],"17":[57]},"packages/frontend/editor-ui/src/features/workflow-reviews/reviewStatus.store.ts":{"17":"b:D+pt+AM+5/NA+v/H4mAI8H/+P7D8////AAAAAAA=","24":[57],"32":[57],"38":[57],"43":[57],"46":[57],"82":[57]},"packages/frontend/editor-ui/src/features/workflows/canvas/canvas.types.ts":{"32":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","59":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","174":[46,21,78],"178":"b:DupleAFuQNFAev9HgGIA8H++PzD8/n8/AAAAAAA=","228":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/canvas.utils.ts":{"37":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","51":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Du/3//AAAAAAA=","60":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDu/3++AAAAAAA=","61":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Du/3//AAAAAAA=","63":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDu/3++AAAAAAA=","64":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Du/3//AAAAAAA=","80":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","97":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","124":[46],"132":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","137":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","139":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","145":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","147":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","148":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","205":[46,165,182],"237":"b:D+pt+AF+5/FA+v9HgmMI8H/+PzD//3++AAAAAAA=","257":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","272":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","283":[46,146,147,76,78,165],"300":"b:BsoF+ABqQBFAet9EgGAAUB+yPhD0al8iAAAAAAA=","334":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","343":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","351":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","368":[46,147,78,164,181],"386":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","403":"b:D+pt+AF+5fFA+v9HgmAI8H/+P7Dt/3//AAAAAAA=","413":"b:D+pt+AF+5fFA+v9HgmAI8H/+P7Dt/3//AAAAAAA=","417":"b:D+pt+AF+5fFA+v9HgmAI8H/+P7Dt/3//AAAAAAA=","431":"b:AoIl2ABKAAAAeFADAEAAEBGSPCA2qsP/AAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/Canvas.vue":{"253":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","255":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","256":[46,160],"293":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","294":[46],"307":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","308":"b:DupFeAFuQNFAev9FgGIA8H++PzD8/n8/AAAAAAA=","310":[46,76,77,162,165,88,89],"311":[46,76,77,162,165,88],"319":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","336":"b:AAAAAABAAAAAcAADAAAAAAAAAAA0AEGBAAAAAAA=","342":"b:AAAByABAAAAAcAsDAAAAAAAAAAC0YE+BAAAAAAA=","362":[46],"380":"b:AoIl2ABKAAAAeFADAEAAEBGSPCA2qsP/AAAAAAA=","382":[46,76],"390":[46,76],"398":[46],"400":[46],"409":[46],"411":[46],"420":[46,182],"422":[46,182],"425":[46,76],"427":[46,76],"430":[46],"442":[46,78],"449":[46,78],"465":[46,78],"472":[46,21,78],"478":[46],"479":[46],"485":[46,21,78],"497":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","507":[46,78],"510":[46],"524":[46],"529":[46,78],"534":[46],"541":"b:AAAl2ABAAAAAeFADAEAAABASOCA2AsP/AAAAAAA=","543":[46],"545":[46,76,88,89],"546":[46,76,88,89],"548":[46],"551":[46],"552":[46],"553":[46,162],"554":[46],"561":[46],"562":[46],"563":[46],"569":[46],"572":[46],"576":[46],"580":[46],"586":[46],"588":[46,162],"589":[46,162,165,169,185,186,187,188],"590":[46],"591":[46,162],"592":[46],"594":[46],"595":[46],"600":[46,164],"601":[46,164],"603":[46],"605":[46],"606":[46],"608":[46,191],"612":[46],"613":[46],"615":[46],"617":[46],"618":[46],"620":[46],"621":[46],"625":[46],"626":[46],"629":[46],"635":[46],"639":[46],"640":[46],"658":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","664":"b:AAAAAABAAAAAMAADAAAAAAAAAAA0AkAeAAAAAAA=","675":[46],"678":[46],"680":[46],"685":[46],"695":[46],"704":"b:D+hF+ANGQFEAej4HwEIA4Es+PyD8v2s/AAAAAAA=","705":"b:D+hF+ANGQFEAej4FwEIA4Es+PyD8v2s/AAAAAAA=","714":"b:D+hFWAFGQFEAej4HgEIA4Eg+PyDsv2s/AAAAAAA=","721":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","722":"b:DuoFeAFqQFFAev9FgGAAQD6ePxD89n8eAAAAAAA=","730":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","731":"b:DuoFeAFuQBFAev9HgGAAwF6GPzDs9n8fAAAAAAA=","745":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","752":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","753":"b:DupFeAFuQNFAev9FgGIA8H++PzD8/n8/AAAAAAA=","755":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","758":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","759":[27,28,29,30,31,102,33,46,63],"767":[1,2,41,46,11,125,126,127,145,14,76,171,179],"771":[46],"775":[46],"779":[46,144,76,77,78,165,88],"786":[46],"790":[31,46,145,160],"792":[31,46,145],"797":[31,46,145],"800":[31,46,145],"812":[46,78],"816":[46],"827":[46,144,76,77,78,165,88],"828":[46,78],"829":[46,78],"830":[46,144,76,77,78,165,88],"831":[46,144,76,77,78,165,88],"832":[46,78],"845":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","846":[46,78],"847":"b:DupFeAFuQNFAev9HgGIA8H++PzD8/n8/AAAAAAA=","849":[46,78],"855":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","866":[46,144,76,77,78,165,88],"870":[46,144,76,77,78,165,88],"874":[46,144,76,77,78,165,88],"879":[46],"883":[46],"887":[46,78],"911":[46,78],"912":[46,78],"927":[46,78],"928":[46,78],"933":[46,78],"949":[46],"961":[46],"974":[46],"992":[46],"1016":[46],"1033":[46],"1037":[46,78],"1061":[46],"1067":[46,21,78],"1072":[46,21,78],"1077":[46],"1086":[46],"1101":[46],"1103":[46],"1111":[46],"1114":[46],"1115":[46],"1120":[46],"1128":[46],"1140":[46],"1154":[46],"1167":[46,76,77,165],"1175":[46,76,77,78,165],"1178":[46],"1179":[46],"1190":"b:DKBFWABEQFEAcj4HgEIAAEguMSDsvmMfAAAAAAA=","1229":[46],"1234":"b:CQAEAAFCAAEAUBAAAAAAAAAAAQAcAEEAAAAAAAA=","1244":"b:DKBFWABEQFAAAj4EgEIAAEguMSDEvmMQAAAAAAA=","1249":[46],"1253":"b:BsoFeAFqQJFAet9FgGAA8D+yPxD0fl8qAAAAAAA=","1257":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","1258":[46],"1262":[46,76,77,162,165,88,89],"1266":"b:DupFeAFuQNFAev9HgGIA8H++PzD8/n8/AAAAAAA=","1270":"b:BsoFeAFqQJFAet9FgGAA8D+yPxD0fl8qAAAAAAA=","1275":"b:BsoFeAFqQJFAet9FgGAA8D+yPxD0fl8qAAAAAAA=","1300":[46,75,76,18],"1304":[46,140,141,76,18],"1308":[46],"1312":[1,46,182,191],"1316":[1,46,182,191],"1319":[109,46,56,182,191],"1323":[109,46,56,182,191],"1326":[46],"1339":[46],"1343":[46],"1348":[46],"1364":"b:BkgAAABCAAAAUAAAAAAA4AAAAgAACEgAAAAAAAA=","1377":[46,78,182],"1394":"b:BkgAAABCAAAAUAAAAAAA4AAAAgAACEgAAAAAAAA=","1411":"b:BkgAAABCAAAAUAAAAAAA4AAAAgAACEgAAAAAAAA=","1419":[46,78,182],"1427":"b:BkgAAABCAAAAUAAAAAAA4AAAAgAACEgAAAAAAAA=","1438":[46,76,78,165],"1442":[46,146,147,76],"1455":[46,50,60,146,147,148,76,162,78,165,18],"1461":[46,146,147,148,76,78,165],"1479":[46,50,60,146,147,148,76,162,78,165,18],"1484":[46,60,146,147,148,76,162,78,165,18],"1491":"b:D+hF+AJGQlEAej4HwEIA4Es+OyD8vms/AAAAAAA=","1495":"b:D+hF+AJGQFEAej4HgEIA4EsuOyD8vms/AAAAAAA=","1503":[0,3,46,22,13,76,170,172,81,173],"1511":"b:AAAl2ABAAAAAeFADAEAAABASOCA2AsP/AAAAAAA=","1512":[46,76,162,165,169,88,185,186,187,188,89],"1519":"b:AAAl2ABAAAAAeFADAEAAABASOCA2AsP/AAAAAAA=","1520":[46,76,162,182],"1527":[46],"1535":[46],"1556":"b:D+hFWAFGQFEAcj4HgEIA4EguMyD8vmsfAAAAAAA=","1566":"b:CQAEAAFCAAEAUBAAAAAAAAAAAQAcAEEAAAAAAAA=","1570":[46],"1574":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","1582":[46,162],"1586":[46,162,168],"1590":[46,162],"1594":[46,162],"1598":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","1607":[46],"1611":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","1617":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","1618":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","1626":[46],"1627":[46],"1644":[1,46,144,77,162,78,164,165,172,177,182],"1646":[46,77,162,164,182],"1660":[46],"1664":[1,46,144,77,162,78,164,165,172,177,182],"1679":[46],"1709":[1,46,144,77,162,78,164,165,172,177,182],"1810":[31,46,145,160],"1812":[46],"1845":[46,76],"1849":[46,76],"1859":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","1863":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","1868":[46],"1876":[46],"1885":[46],"1886":[46],"1891":[46],"1895":[46],"1903":[46],"1922":"b:AAAhAABEQEIAYkIBAAAAAAgAAAAECEJAAAAAAAA=","1929":[104,105,46,161],"1937":[104,105,46,161],"1945":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","1956":"b:AgAMAABABBAAiEAAAAAAAAAAAAAABwCdAAAAAAA=","1967":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","1976":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","1992":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","2002":"b:CQAEAAFCAAEAUBAAAAAAAAAAAQAcAEEAAAAAAAA=","2006":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","2009":[46],"2016":[46],"2043":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","2087":[46,21,78],"2106":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","2107":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","2133":[46],"2135":[46],"2142":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","2143":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDu/3++AAAAAAA=","2152":[46,60,146,147,148,76,162,78,165,18],"2157":"b:BkgAAABCAAAAUAAAAAAA4AAAAgAACEgAAAAAAAA=","2159":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","2163":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","2175":[46],"2176":[46],"2180":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","2208":[46,145]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/WorkflowCanvas.vue":{"83":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","84":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","88":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","94":"b:AgAMAAAABBAAiEAAAAAAAAAAAAAABwCdAAAAAAA=","98":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","103":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","106":"b:D+pt+AM+5/FA+v/HwmAI8H/+P7D8////AAAAAAA=","107":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","108":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","109":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","113":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","114":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","115":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","119":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","120":[161],"128":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","129":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","130":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","133":"b:D+pt+AE+5/FA+v9HgmMI8H/+P7Du/3//AAAAAAA=","151":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","166":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","174":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","181":[21,78],"182":[21,78],"183":[21,78],"185":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","191":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","194":[21,78],"195":[21,78],"196":[21,78],"197":[21,78],"203":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","213":[78],"218":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","234":[162,165,177,88,189],"242":[162,165,177,88,189],"248":[162,165,177,88],"299":"b:D+pt+AM+5/FA+v/HwmMI8H/+P7D+////AAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/background/CanvasBackground.vue":{"13":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","18":"b:AABMgAJAB0AAgAABAAMAAAAAAAACBwCdAAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/buttons/CanvasChatButton.vue":{"9":[32,1,2,3,9,11,63,142,143,144,14,161,18,15]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/buttons/CanvasControlButtons.vue":{"11":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","36":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","38":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","40":[46,162,168],"44":[46,162],"48":"b:CwAEAAFAAAAAcDAAAAAAAAAAMQAsFWEgAAAAAAA=","52":[46,145],"56":[46],"58":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","62":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","63":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","66":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","79":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","92":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","110":[46],"122":[46],"129":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","138":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","146":[46],"159":[46]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/buttons/CanvasRunWorkflowButton.vue":{"49":"b:C6Jt+AB+5fFA+v9HgmAI8H8+PrDs/3//AAAAAAA=","53":"b:C6Jt+AB+5fFA+v9HgmAI8H8+PrDs/3//AAAAAAA=","54":"b:C6Jt+AB+5fFA+v9HgmAI8H8+PrDs/3//AAAAAAA=","58":"b:C6Jt+AB+5fFA+v9HgmAI8H8+PrDs/3//AAAAAAA=","71":[31,46,134,165,170,172,176,177],"73":[31,46,134,165,170,172,176,177],"74":[31,46,134,165,170,172,176,177],"80":[31,46,134,165,170,172,176,177],"86":"b:C6Jt+AB+5fFA+v9HgmAI8H8+PrDs/3//AAAAAAA=","91":"b:C6Jt+AB+5fFA+v9HgmAI8H8+PrDs/3//AAAAAAA=","93":"b:C6Jt+AB+5fFA+v9HgmAI8H8+PrDs/3//AAAAAAA=","96":"b:C6Jt+AB+5fFA+v9HgmAI8H8+PrDs/3//AAAAAAA=","101":"b:C6Jt+AB+5fFA+v9HgmAI8H8+PrDs/3//AAAAAAA=","108":"b:C6Jt+AB+5fFA+v9HgmAI8H8+PrDs/3//AAAAAAA=","109":"b:C6Jt+AB+5fFA+v9HgmAI8H8+PrDs/3//AAAAAAA=","114":"b:C6Jt+AB+5fFA+v9HgmAI8H8+PrDs/3//AAAAAAA=","116":"b:C6Jt+AB+5fFA+v9HgmAI8H8+PrDs/3//AAAAAAA=","118":[46,19,48,21,22,50],"119":"b:C6Jt+AB+5fFA+v9HgmAI8H8+PrDs/3//AAAAAAA=","125":[31,41,9,46,124,97,176,178,180,189,89,191],"131":"b:C6Jt+AB+5fFA+v9HgmAI8H8+PrDs/3//AAAAAAA=","140":[46],"141":[46],"150":[46],"153":"b:C6Jt+AB+5fFA+v9HgmAI8H8+PrDs/3//AAAAAAA=","172":"b:C6Jt+AB+5fFA+v9HgmAI8H8+PrDs/3//AAAAAAA=","183":"b:AgBEQABw5GEAoDBEgEAIAFgiJAAAlmMcAAAAAAA=","184":"b:AABEQABw5GEAoDBEgEAIAFgiJAAAlmMcAAAAAAA=","185":"b:AgBEQABw5GEAoDBEgEAIAFgiJAAAlmMcAAAAAAA=","186":"b:C6Jt+AB+5fFA+v9HgmAI8H8+PrDs/3//AAAAAAA=","188":"b:C6Jt+AB+5fFA+v9HgmAI8H8+PrDs/3//AAAAAAA=","211":[31,46,134,165,170,172,176,177],"222":[46]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/buttons/CanvasStopCurrentExecutionButton.vue":{"6":"b:DyBMWAEw5GEAsD5EgEAIAHwmJQBC9mucAAAAAAA=","13":"b:DyBMWAEw5GEAsD5EgEAIAHwmJQBC9mucAAAAAAA=","18":"b:DyBMWAEw5GEAsD5EgEAIAHwmJQBC9mucAAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/buttons/CanvasStopWaitingForWebhookButton.vue":{"5":"b:DgAEAAEQQAEAAAAAgAAIAAAAAQACBAIAAAAAAAA=","9":"b:DgAEAAEQQAEAAAAAgAAIAAAAAQACBAIAAAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/edges/CanvasArrowHeadMarker.vue":{"6":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/edges/CanvasConnectionLine.vue":{"11":"b:BkgAAABCAAAAUAAAAAAA4AAAAgAACEgAAAAAAAA=","17":"b:BkgAAABCAAAAUAAAAAAA4AAAAgAACEgAAAAAAAA=","21":"b:BkgAAABCAAAAUAAAAAAA4AAAAgAACEgAAAAAAAA=","25":"b:BkgAAABCAAAAUAAAAAAA4AAAAgAACEgAAAAAAAA=","32":"b:BkgAAABCAAAAUAAAAAAA4AAAAgAACEgAAAAAAAA=","40":"b:BkgAAABCAAAAUAAAAAAA4AAAAgAACEgAAAAAAAA=","47":"b:BkgAAABCAAAAUAAAAAAA4AAAAgAACEgAAAAAAAA=","55":"b:BkgAAABCAAAAUAAAAAAA4AAAAgAACEgAAAAAAAA=","56":[1,2,41,46,11,126,127,145,14,76,171,179,182],"60":"b:BkgAAABCAAAAUAAAAAAA4AAAAgAACEgAAAAAAAA=","64":"b:BkgAAABCAAAAUAAAAAAA4AAAAgAACEgAAAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/edges/CanvasEdge.vue":{"16":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","37":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","46":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","47":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","53":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDu/3++AAAAAAA=","61":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","63":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","65":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","67":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","72":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","78":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","83":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","90":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","96":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","98":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","100":[46,146,147,76,78,165],"110":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","120":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","121":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","125":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","136":[46,146,147,76],"140":[46,76,78,165],"144":[46,60,146,147,148,76,162,78,165,18],"148":[46,60,146,147,148,76,162,165],"150":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","164":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/edges/utils/getEdgeRenderData.ts":{"11":"b:D+pt+AF+5/FA+v9HgmMI8F/+PzDv/3++AAAAAAA=","13":"b:D+pt+AF+5/FA+v9HgmMI8F/+PzDv/3++AAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/handles/CanvasHandleRenderer.vue":{"16":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","46":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","50":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","56":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","60":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","64":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","70":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","80":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","88":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","98":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","100":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","124":[1,2,41,46,11,125,126,127,145,14,76,171,179],"153":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","166":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/handles/render-types/CanvasHandleMainInput.vue":{"14":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","22":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","26":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","27":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/handles/render-types/CanvasHandleMainOutput.vue":{"22":"b:D+pt+AF+5fFA+v9HgmAI8H/+P7Dt/3//AAAAAAA=","27":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","29":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","38":"b:D+pt+AF+5fFA+v9HgmAI8H/+P7Dt/3//AAAAAAA=","40":"b:DyBEGAFw5WEAoDZEAEAAAFwmJABAtmscAAAAAAA=","49":"b:D+pt+AF+5fFA+v9HgmAI8H/+P7Dt/3//AAAAAAA=","51":"b:D+pt+AF+5fFA+v9HgmAI8H/+P7Dt/3//AAAAAAA=","53":"b:D+pt+AF+5fFA+v9HgmAI8H/+P7Dt/3//AAAAAAA=","58":"b:AAAkgABSAEEAYDQAACIAQEgSDAAglQPgAAAAAAA=","63":"b:DyBEGAFw5WEAoDZEAEAAAFwmJABAtmscAAAAAAA=","70":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","75":"b:AAAAAABCAAAAEAAAAAAA4AAACgAACEoAAAAAAAA=","79":[41,46,126,127,145,147,76,171,177,179,182],"83":[41,46,125,126,127,145,76,171,179],"85":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","93":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/handles/render-types/CanvasHandleNonMainInput.vue":{"19":[0,1,2,3,9,46,11,13,143,14,75,76,18,15,16],"21":[0,1,2,3,9,46,11,13,143,14,75,76,18,15,16],"27":[0,1,2,3,9,46,11,13,143,14,75,76,18,15,16],"33":[1,2,9,46,11,13,143,14,75,76,18,15,16],"39":[0,1,2,3,9,46,11,13,143,14,75,76,18,15,16],"44":[1,2,46,11,14],"48":[1,2,46,11,14],"52":[1,2,46,11,14],"54":[0,1,2,3,9,46,11,13,143,14,75,76,18,15,16],"61":[0,1,2,3,9,46,11,13,143,14,75,76,18,15,16]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/handles/render-types/CanvasHandleNonMainOutput.vue":{"13":[0,1,2,3,9,46,11,13,143,14,18,15,16],"15":[0,1,2,3,9,46,11,13,143,14,18,15,16],"23":[0,1,2,3,9,46,11,13,143,14,18,15,16],"27":[0,1,2,3,9,46,11,13,143,14,18,15,16]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/handles/render-types/parts/CanvasHandleDiamond.vue":{"13":[0,1,2,3,9,46,11,13,143,14,75,76,18,15,16]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/handles/render-types/parts/CanvasHandleDot.vue":{"4":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","13":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","14":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/handles/render-types/parts/CanvasHandlePlus.vue":{"6":"b:D+pt+AF+5fFA+v9HgmAI8H/+P7Dt/3//AAAAAAA=","34":"b:D+pt+AF+5fFA+v9HgmAI8H/+P7Dt/3//AAAAAAA=","41":"b:D+pt+AF+5fFA+v9HgmAI8H/+P7Dt/3//AAAAAAA=","57":"b:D+pt+AF+5fFA+v9HgmAI8H/+P7Dt/3//AAAAAAA=","64":"b:D+pt+AF+5fFA+v9HgmAI8H/+P7Dt/3//AAAAAAA=","89":"b:D+pt+AF+5fFA+v9HgmAI8H/+P7Dt/3//AAAAAAA=","102":[1,2,41,46,11,125,126,127,145,14,76,171,179],"104":"b:D+pt+AF+5fFA+v9HgmAI8H/+P7Dt/3//AAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/CanvasNode.vue":{"50":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","91":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","92":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","93":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","107":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","109":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","117":[46],"120":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","122":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","138":"b:DKBFWABEQFAAAj4EgEIAAEguMSDUvmMQAAAAAAA=","148":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","152":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","156":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","163":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","167":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","174":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","178":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","253":[1,2,41,46,11,125,126,127,145,14,76,171,179],"257":[46,140,141,76,18],"261":[0,3,46,22,13,76,170,172,81,173],"265":[46,75,76,18],"269":"b:DKBFWABEQFAAAj4EgEIAAEguMSDAvmMQAAAAAAA=","273":[46],"277":[46,162],"281":[1,46,144,77,162,78,164,165,172,177,182],"285":[46],"289":[46],"293":[46],"297":[46],"301":[46],"305":[46],"309":[46],"312":[46],"334":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","339":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","348":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","349":"b:DupFeAFuQNFAev9HgGIA8H++PzD8/n8/AAAAAAA=","355":[1,46,182,191],"361":[109,46,56,182,191],"367":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","372":"b:BsoN+AJqRBFA+N9EgGEA8D+yPhD0Z1+/AAAAAAA=","376":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","386":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","403":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/CanvasNodeRenderer.vue":{"11":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","13":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","37":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/CanvasNodeToolbar.vue":{"19":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D+/3//AAAAAAA=","58":[46],"59":[46],"63":[0,1,2,3,9,46,11,13,143,14,18,15,16],"66":[0,1,2,3,9,46,11,13,143,14,18,15,16],"68":"b:D+pt+AF+5fFA+v9HgmAI8H/+P7Ds/3//AAAAAAA=","72":"b:D+pt+AF+5fFA+v9HgmAI8H/+P7Du/3//AAAAAAA=","83":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D+/3//AAAAAAA=","90":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D+/3//AAAAAAA=","108":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D+/3//AAAAAAA=","115":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D+/3//AAAAAAA=","117":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D+/3//AAAAAAA=","119":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D+/3//AAAAAAA=","126":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D+/3//AAAAAAA=","137":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D+/3//AAAAAAA=","141":[0,3,46,22,13,76,170,172,81,173],"145":[46,75,76,18],"149":[46,140,141,76,18],"153":[46],"159":[46,162],"163":"b:CSAEAABAAAAAWAIAAAAAAAAwAAAENAAAAAAAAAA=","167":[0,3,46,13,75,162,78,170,18,172,81,173],"171":[46],"177":[46],"183":[46],"186":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D+/3//AAAAAAA=","196":"b:CSAEAABAAAAAGAIAAAAAAAAwAAAENAAAAAAAAAA=","197":[46],"201":"b:D+pt+AF+5fFA+v9HgmAI8H/+P7Du/3//AAAAAAA=","212":"b:D+pt+AF+5fFA+v9HgmAI8H/+P7Ds/3//AAAAAAA=","225":"b:D+pt+AF+5fFA+v9HgmAI8H/+P7D8/3//AAAAAAA=","249":[46],"263":[46],"275":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D+/3//AAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/CanvasNodeAddNodes.vue":{"18":"b:BsoFeAB6QBFAON/EgGAA8D+SPhD0Zp9rAAAAAAA=","26":"b:BsoFeAB6QBFAON/EgGAA8D+SPhD0Zp9rAAAAAAA=","30":"b:BsoFeAB6QBFAON/EgGAA8D+SPhD0Zp9rAAAAAAA=","35":"b:BsoFeABqQBFAON9EgGAA8D+SPhD0Zh8qAAAAAAA=","40":[46],"44":[46],"48":"b:AAAAKABCABAAAAAAAAAAIAMAAACkJAAAAAAAAAA=","55":[46],"63":"b:BsoFeAB6QBFAON/EgGAA8D+SPhD0Zp9rAAAAAAA=","71":[46],"83":[46]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/CanvasNodeDefault.vue":{"23":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","56":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","57":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","58":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","61":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","66":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","71":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","80":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","81":[46],"83":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","110":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","116":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","129":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","136":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","149":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","158":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","183":"b:C6BtAAFU5/BA4nQDAgMIAEhsAaAPn2HdAAAAAAA=","189":"b:D+pt+AF+5/FA+v9HgmMIUH/+P7Dv/3//AAAAAAA=","191":"b:D+pt+AF+5/FA+v9HgmMIUH/+P7Dv/3//AAAAAAA=","196":[1,46,144,77,162,78,165,172,177,182],"200":"b:DKBFWABEQFAAAj4EgEIAAEguMSDAvmMQAAAAAAA=","207":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/parts/CanvasNodeSettingsIcons.vue":{"12":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","13":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","19":[46],"28":[46,176],"36":[46],"45":[46],"53":[46],"62":[46],"72":[46],"81":[46]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/parts/CanvasNodeStatusIcons.vue":{"25":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","46":"b:BuoF+ABuQhFAGKUGgiAAUAeKCjCEBheiAAAAAAA=","53":[46],"60":[46],"65":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","68":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","69":"b:D+pt+AF+5/FA+v9HgGMI8H/+P7Dv/3//AAAAAAA=","74":"b:D+pt+AF+5/FA+v9HgGMI8H/+P7Dv/3//AAAAAAA=","79":"b:D+pt+AF+5/FA+v9HgGMI8H/+P7Dv/3//AAAAAAA=","82":"b:BuoF+ABuQhFAGKUGgiAAUAeqCjCEBheuAAAAAAA=","83":[46],"84":"b:D+pt+AF+5/FA+v9HgGMI8H/+P7Dv/3//AAAAAAA=","88":"b:D+pF+AF+53FAur9GgmIAUH+uLzDu9n++AAAAAAA=","94":[46],"102":[46],"103":[46],"111":[46],"115":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","124":[46],"125":[46,73],"134":[46],"135":[46],"147":[46],"149":[27,28,1,2,46,141,169,170,18,176,186,187],"159":[46],"163":"b:BuoF+ABuQhFAGKUGgiAAUAeKCjCEBheiAAAAAAA=","182":[46],"185":[46,56,138,146,166,172,177,179,182]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/parts/CanvasNodeStatusMark.vue":{"5":"b:DyBEWAFw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA=","10":"b:DyBEWAFw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/parts/CanvasNodeTooltip.vue":{"11":"b:DgAEAAFQQAEAAAAAgAAIAAAAAQAABAKAAAAAAAA=","13":"b:DgAEAAFQQAEAAAAAgAAIAAAAAQAABAKAAAAAAAA=","14":"b:DgAEAAFQQAEAAAAAgAAIAAAAAQAABAKAAAAAAAA=","26":"b:DgAEAAFQQAEAAAAAgAAIAAAAAQAABAKAAAAAAAA=","28":"b:DgAEAAFQQAEAAAAAgAAIAAAAAQAABAKAAAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/parts/CanvasNodeTrigger.vue":{"34":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","35":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","46":"b:D+pt+AF+5fFA+v9HgmAI8H/+P7Dt/3//AAAAAAA=","53":[46],"54":[46],"58":[46],"59":[46],"63":[32,1,2,3,9,46,11,63,142,143,144,14,18,15],"68":[46],"69":[32,1,2,3,9,46,11,63,142,143,144,14,18,15],"72":"b:D+pt+AF+5fFA+v9HgmAI8H/+P7Dt/3//AAAAAAA=","73":"b:D+pt+AF+5fFA+v9HgmAI8H/+P7Dt/3//AAAAAAA=","75":[46],"83":[46],"91":[46,134,170],"94":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","99":[46,134,170],"121":[32,1,2,3,9,46,11,63,142,143,144,14,18,15],"137":"b:C6Jt+AB+5fFA+v9HgmAI8H8+PrDt/3//AAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/selection/CanvasSelectionToolbar.vue":{"16":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","39":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","40":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","50":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","52":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","62":"b:BoJN+ANqR9FA+P9HgGMA8DYaOBDu91e/AAAAAAA=","66":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","72":[46],"79":[46,78,182],"91":[46,147,78,182],"99":[46,78],"104":[46],"106":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","118":[46,78],"125":[46,147,78,182],"141":[46,78,182],"153":[46],"160":[46]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvas.ts":{"4":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasAgentNodeGeometry.ts":{"16":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","19":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","57":"b:AgAMAABABBAAiEAAAAAAAAAAAAAABwCdAAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasGroupIdStorage.ts":{"10":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","11":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","22":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","26":[46,21,78]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasLayout.ts":{"116":[46],"120":[46],"130":[46],"134":[46],"138":[46],"151":[46],"154":[46],"165":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","172":[31,46,145,160],"175":[46],"181":[31,46,145,160],"186":[31,46,145,160],"192":[46],"194":[46],"198":[46],"200":[31,46,145,160],"203":[31,46,145,160],"209":[31,46,145,160],"219":[46],"223":[31,46,145,160],"224":[46],"231":[46],"244":[31,46,145,160],"254":[46],"255":[46],"256":[46],"261":[46],"264":[46],"265":[46],"276":[46],"282":[46],"283":[46],"289":[46],"299":[46],"301":[46],"359":[46],"362":[46],"363":[46],"369":[46],"374":[46],"381":[46],"384":[46],"388":[46],"391":[46],"394":[46],"395":[46],"408":[46],"410":[46],"414":[46],"419":[46],"423":[46],"426":[46],"461":[31,46,145,160],"502":[31,46,145,160],"507":[31,46,145,160],"520":[31,46,145,160],"534":[31,46,145,160],"543":[31,46,145,160],"550":[31,46,145,160],"602":[31,46,145,160],"604":[31,46,145,160],"606":[46],"609":[31,46,145,160],"610":[31,46,145,160],"614":[31,46,145,160],"616":[31,46,145,160],"624":[31,46,145,160],"626":[31,46,145,160],"631":[31,46,145,160],"645":[46],"650":[31,46,145,160],"651":[31,46,145,160],"657":[31,46,145,160],"658":[31,46,145,160],"663":[31,46,145,160],"672":[31,46],"674":[31,46,145,160],"678":[31,46,145,160],"686":[46],"700":[46],"705":[46],"706":[46],"712":[46],"713":[46],"719":[31,46,145,160],"720":[31,46,145,160],"742":[31,46,145,160],"756":[31,46,145,160],"765":[31,46,145,160],"767":[31,46,145,160],"771":[31,46,145,160],"776":[31,46,145,160],"781":[46],"795":[46],"801":[46],"819":[46],"828":[46],"843":[31,46,145,160],"850":[46],"854":[46],"855":[46],"885":[31,46,145,160],"898":[31,46,145,160],"902":[31,46,145,160],"907":[46],"918":[46],"921":[46],"929":[46],"940":[31,46,145,160],"949":[31,46,145,160],"952":[46],"958":[31,46,145,160],"971":[46],"982":[46],"1001":[31,46,145,160],"1013":[31,46,145,160],"1014":[46],"1017":[46],"1023":[46],"1024":[46],"1038":[31,46,145,160],"1044":[46],"1047":[31,46,145,160],"1067":[46],"1080":[31,46,145,160],"1081":[31,46,145,160],"1128":[31,46,145,160],"1134":[31,46,145,160],"1138":[46],"1140":[31,46,145,160],"1141":[31,46,145,160],"1152":[46],"1157":[46],"1171":[46],"1176":[46],"1178":[46],"1187":[31,46,145,160],"1202":[46]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasMapping.groups.ts":{"46":[46,21,78],"54":[46,21,78],"71":[46,21,78],"93":[46,21,78],"100":[46,21,78],"118":[46,21,78],"124":[46,21,78],"172":[46,21,78],"187":[46,21,78],"217":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","230":[46,21,78],"237":[46,21,78],"243":[46,21,78],"251":[46,21,78],"284":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","310":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasMapping.ts":{"54":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","73":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","79":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","80":"b:DyBEWAFw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA=","84":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","112":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","114":[46,21,78],"120":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","144":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","152":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","159":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","211":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","214":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","223":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","251":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","254":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","266":[46],"275":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","276":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA=","288":"b:D+pt+AF+5/FA+v9HgmMIUF/+PzDv/3++AAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasNode.ts":{"9":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","11":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","34":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","35":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","37":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","38":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","39":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","41":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","42":[46,137,147,78,164,170,181,189,191],"43":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","45":[46],"46":[46],"47":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","49":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","50":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","51":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","52":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","54":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","55":"b:DyBEWAFw5WEAsD5EgEAAAHwmJQBC9mscAAAAAAA=","56":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","58":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","60":[46,137,147,78,164,170,181,189,191],"64":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","70":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasNodeGroupActions.ts":{"21":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","30":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","32":"b:D+pt+AN+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","34":"b:DupFeAFuQJFAev9FgGAA8H++PzD8/n8+AAAAAAA=","35":"b:DupFeAFuQJFAev9FgGAA8H++PzD8/n8+AAAAAAA=","38":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","43":[46],"59":[46],"64":[46],"70":[46],"79":[46,78],"91":[46,78],"95":[46,78],"108":[46],"121":[46,78]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasNodeGroupDescriptionVisibility.ts":{"16":[46,21,78],"33":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","39":[46],"43":[46,21,78],"47":[46,78],"59":[46],"65":[46],"82":[46,78],"88":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","89":[46],"91":[46],"94":[104,105,46,62,78,18,183,184,187,188],"110":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","114":[46]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasNodeGroupDrag.ts":{"38":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","46":[46,78],"52":[46,78],"71":[46,78],"82":[46,78],"108":[46,78],"113":[46,144,76,77,78,165,88],"118":[46,144,76,77,78,165,88],"130":[46,144,76,77,78,165,88],"131":[46,144,76,77,78,165,88],"142":[46,144,76,77,78,165,88],"190":[46,78],"198":[46,144,76,77,78,165,88],"205":[46,144,76,77,78,165,88],"223":[46,144,76,77,78,165,88],"235":[46,144,76,77,78,165,88],"246":[46,78],"255":[46,144,76,77,78,165,88],"274":[46],"284":[46],"288":[46]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasNodeGroupLayout.ts":{"69":[46,21,78],"81":[46,21,78],"114":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","126":[46,21,78],"133":[46,78],"137":[46,78],"141":[46,78],"145":[46,78],"149":[46,78],"160":[46,78],"164":[46,78],"244":[46],"260":[46,21,78],"270":[46,78],"276":[46],"279":[46,21,78],"284":[46,78],"287":[46,21,78],"291":[46],"302":[46,78],"309":[46],"341":[46,78],"359":[46],"365":[46],"373":[46,78],"381":[46],"401":[46],"402":[46],"421":[46,78],"483":[46,78],"505":[46,21,78],"517":[46,78],"519":[46,78]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasNodeGroupOperationGuards.ts":{"57":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","59":"b:BsoF+AAqQBFAet9EgGAAUB+SPhDkal8iAAAAAAA=","69":[78],"89":[78],"98":[78],"106":[78],"128":"b:BsoF+AAqQBFAet9EgGAAUB+SPhDkal8iAAAAAAA=","140":[78],"143":[78],"227":[78],"237":[78],"253":[78],"272":[78],"277":"b:BsoF+AAqQBFAet9EgGAAUB+SPhDkal8iAAAAAAA=","323":[31,76,78,165]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasNodeGroupSelection.ts":{"37":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","53":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","55":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","58":[46,21,78],"63":"b:DupFeAFuQNFAev9HgGIA8H++PzD8/n8/AAAAAAA=","70":"b:DupFeAFuQNFAev9HgGIA8H++PzD8/n8/AAAAAAA=","77":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","78":"b:DupFeAFuQNFAev9FgGIA8H++PzD8/n8/AAAAAAA=","79":"b:DuoFeAFqQFFAev9FgGAAQD6ePxD89n8eAAAAAAA=","93":[46,78],"120":[46,78],"130":[46,78],"131":[46,78],"140":[46,78],"141":[46],"143":[46],"151":"b:D+pFeAFuQNFAev9HgGIA8H++PzD8/n8/AAAAAAA=","157":[46,78],"168":"b:CQAEAAFCAAEAUBAAAAAAAAAAAQAcAEEAAAAAAAA=","177":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","188":"b:DupFeAFuQNFAev9FgGIA8H++PzD8/n8/AAAAAAA=","189":"b:DuoFeAFqQFFAev9FgGAAQD6ePxD89n8eAAAAAAA=","202":"b:DupFeAFuQNFAev9FgGIA8H++PzD8/n8/AAAAAAA=","207":"b:DupFeAFuQNFAev9FgGIA8H++PzD8/n8/AAAAAAA=","222":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","255":[46]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasNodeGroupTelemetry.ts":{"25":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","32":[78],"45":[78],"64":[78],"94":[78],"97":[78],"100":[78]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasNodeGroupView.ts":{"37":[46,78],"62":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","66":[31,46,21,144,145,76,77,78,165,88],"69":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","74":[46,21,78],"77":[46,78],"81":[46,21,78],"89":[46,21,78],"92":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","94":[46,21,78],"99":[46,78],"106":[46,78],"107":[46,78],"109":[46,78],"115":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","126":[46,78],"132":[46,78],"139":[46,78],"143":[46,78],"148":[46,21,78],"150":[46,78],"154":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","158":[46,21,78],"162":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","167":[46,78],"177":[46,78],"181":[46],"182":[46],"196":[46,78],"208":[46,78],"223":[31,46,144,145,76,77,78,165,88],"230":[46,78],"259":[46],"263":[46,78],"268":[46],"282":[46],"294":[104,105,46,62,78,18,183,184,187,188],"296":[46],"314":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasNodeHandle.ts":{"11":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","14":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","15":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","16":"b:D+pt+AF+5fFA+v9HgmAI8H/+P7Dt/3//AAAAAAA=","17":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","18":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","19":[0,1,2,3,46,11,13,14,18,15],"20":[46],"21":[46],"22":[46],"23":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasNodeHover.ts":{"10":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","17":"b:D+hF+ANGQFEAej4HwEIA4Es+PyD8v2s/AAAAAAA=","31":"b:D+hFWAFGQFEAej4FgEIA4Eg+PyDsv2s/AAAAAAA=","64":[46],"73":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","77":"b:AgAMAABABBAAiEAAAAAAAAAAAAAABwCdAAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasTraversal.ts":{"4":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","5":[46,76],"6":[46],"9":[46,76],"13":[46,76],"17":[46],"18":[46],"21":[46],"26":[46],"27":[46],"32":[46,182],"42":[46,182],"43":[46,182],"46":[46,76],"56":[46,76],"57":[46,76]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useEmptyCanvasGroupsFlag.ts":{"6":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","9":"b:DupF+AEuQJFAev9HgGAA8H++PzD8/n8+AAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useNodeGroupsSubscription.ts":{"18":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","21":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","30":"b:AgAMAABABBAAiEAAAAAAAAAAAAAABwCdAAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useViewportAutoAdjust.ts":{"7":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","21":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","27":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","46":"b:AgAMAABABBAAiEAAAAAAAAAAAAAABwCdAAAAAAA=","51":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useVueFlowTransformPaneTeleport.ts":{"9":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","14":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA=","16":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useZoomAdjustedValues.ts":{"8":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","17":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","39":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","40":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","60":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","61":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","76":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","77":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","92":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","94":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/composables/useIsInExperimentalNdv.ts":{"4":"b:TupF+ABuQlFWOv9GgOICUG+uP3Ls/n8SAAAAAAA=","8":"b:AEABAABAAAASAC8AAAAAAAAAEAAIYA4AAAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/experimentalNdv.store.ts":{"17":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","19":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","24":"b:D+pt+AN+5/FU+v/HwmMI8H/+P7L+////AAAAAAA=","29":[46],"36":[46],"43":[46],"44":[46],"50":[46],"54":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","58":[46],"62":[31,46,148,163],"72":[46],"107":[46],"121":[46],"122":[46],"138":[46],"139":[46],"140":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","141":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D+////AAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/readyToRun/composables/useEmptyStateDetection.ts":{"13":"b:D+r/+4O/5/9i+v/P+3j89///P/H+////AAAAAAA=","26":"b:AAAAAICBABwgAEAJGBAAAgAAAAAAAQDAAAAAAAA=","45":"b:AAAAAICBAB4AAEAJCBAEAoABABAAAQDBAAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/readyToRun/stores/readyToRun.store.ts":{"22":"b:D+r/+4O/5/9i+v/P+3j89///P/H+////AAAAAAA=","59":"b:D+r/+4O/5/9i+v/P+3j89///P/H+////AAAAAAA=","66":"b:D+r/+4O/5/9i+v/P+3j89///P/H+////AAAAAAA=","74":"b:D+r/+4O/5/9i+v/P+3j89///P/H+////AAAAAAA=","90":"b:D+r/+4O/5/9i+v/P+3j89///P/H+////AAAAAAA=","91":"b:D+r/+4O/5/9i+v/P+3j89///P/H+////AAAAAAA=","110":"b:AAIAIICpAB5CAEAJCBAEAoABAFEAAQDBAAAAAAA=","208":"b:AAIAIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","220":"b:AAAAAICBAB4AAEAJCBAEAoABABAAAQDBAAAAAAA=","224":[97]},"packages/frontend/editor-ui/src/features/workflows/templates/components/SetupWorkflowCredentialsButton.vue":{"32":[97,89,191],"34":[97],"38":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","42":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","49":"b:B+pt+AA+5XFA+v9HgmAI8H+6PrD893//AAAAAAA=","54":"b:B+pt+AA+5XFA+v9HgmAI8H+6PrD893//AAAAAAA=","57":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","63":[97,89,191],"67":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","84":[97,89,191],"92":"b:BsoBIAAKAAFACAACACAAUAeCCBCEABciAAAAAAA=","107":[97],"111":[97],"119":"b:AgAMgAIABBAAiEAAAAAAAAAAAAAABwAcAAAAAAA=","123":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA=","139":"b:D+pt+AM+5fFA+v/HwmAI8H/+P7D8////AAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/templates/templates.store.ts":{"49":[46,191],"55":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","90":[46,191],"91":[46,191],"96":[46,89],"97":[46,89],"100":[46,89,191],"101":[46,89,191],"107":[46,89],"109":[46,191],"110":[46,191],"113":[46,191],"114":[46,191],"121":[46,191],"125":[46,191],"126":[46,191],"133":[46,191],"137":[46,191],"138":[46,191],"146":[46],"147":[46],"155":[46],"156":[46],"166":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","170":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","186":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","194":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","212":"b:D+r/+4P/5/9i+v/P+3j89///P/H8////AAAAAAA=","217":"b:BgIBKABqQJFAOt9EgAAA4AagDhDkah8CAAAAAAA=","224":[46,191],"228":[46,89,191],"231":[46,89,191],"232":[46,89,191],"243":[46,89,191],"244":[46,89,191],"250":[46,191],"254":[46,191],"262":[46,191],"267":[46,191],"286":[46],"299":[46],"312":"b:f+r/+4P/5/92+v/v+/v/////////////AAAAAAA=","317":[46,97,89,191],"323":[46,89,191],"339":[46,89],"357":[46,191],"373":[46,191],"388":[46,191],"393":[46,191],"413":[46],"439":[46,97,89,191],"447":[46,97,89,191],"455":[46,97,89,191]},"packages/frontend/editor-ui/src/features/workflows/templates/utils/typeGuards.ts":{"8":[46,89],"14":[46,89],"20":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/templates/utils/workflowSamples.ts":{"9":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","17":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","21":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","30":[46],"35":[46]},"packages/frontend/editor-ui/src/features/workflows/workflowHistory/workflowHistory.store.ts":{"24":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","31":[46,168],"33":[46,168],"37":[46,168],"41":[46,168],"47":[31,46,62,168,169,170,79,18,186,187,188],"53":[46],"78":[46],"104":[46],"120":[46],"133":[46],"141":[46],"147":[46]},"packages/modules/instance-registry/frontend/src/instance-registry.store.ts":{"7":"b:f+r/+4P/5/92+v/v////////////////AAAAAAA=","12":[46],"14":[46,165]},"packages/modules/mcp/frontend/src/mcp.module.ts":{"11":[46,123],"12":[46],"13":[46],"14":[46],"76":"b:f+r/+4P/5/92+v/v+/j////////8////AAAAAAA=","81":"b:f+r/+4P/5/92+v/v+/j////////8////AAAAAAA="},"packages/modules/mcp/frontend/src/mcp.store.ts":{"38":"b:D+rt+YP/5/9g+v/P+nMM+v//P7D+////AAAAAAA=","70":"b:AAAFWABAAAAAEFADAEAACBASOAAkAAMgAAAAAAA=","71":[46,123],"72":[46],"78":[46,123],"83":[46,123],"99":[46],"113":[46],"120":[46,123],"132":[46],"141":[46],"150":[46],"158":[46],"167":[46],"199":[46],"223":[46],"250":[46],"257":[46],"263":[46],"269":[46],"273":[46,123],"279":[46],"321":[46,123],"346":[46],"351":[46],"358":[46],"364":[46],"371":[46,123],"390":[46],"408":[46],"416":[46],"424":[46,123],"428":[46],"432":[46,123],"438":[46]},"packages/modules/otel/frontend/src/otel.module.ts":{"10":[46],"40":"b:f+r/+4P/5/92+v/v+/j////////8////AAAAAAA=","45":"b:f+r/+4P/5/92+v/v+/j////////8////AAAAAAA="},"packages/modules/type-availability-policies/frontend/src/composables/useNodeTypeRestriction.ts":{"19":"b:T+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","24":"b:BgIBKABqQJFAOt9EgAAA4A6gDhDkah8CAAAAAAA=","39":"b:T+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","50":"b:AgAAAABAAAAAcAADAAAAAAAAEQA0EEIAAAAAAAA=","59":[46,73],"81":[46],"93":"b:D+pt+AN+5/FA+v/HwmMI8H/+P7D/////AAAAAAA=","94":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","99":"b:D+pt+AF+5/FA+v9HgmMI8H/+P7Dv/3//AAAAAAA=","100":[46,73]},"packages/modules/type-availability-policies/frontend/src/policy-violations/policyViolations.ts":{"10":"b:BgAEGABAAAAAAAAAAAAAAAAgAAAAFgEMAAAAAAA=","16":"b:BgAEGABAAAAAAAAAAAAAAAAgAAAAFgEMAAAAAAA="},"packages/modules/type-availability-policies/frontend/src/type-availability-policies.store.ts":{"16":[46,73],"19":[46,73],"23":"b:T+rt+QN+5/FA+v/HwmMI8H/+/7D/////AAAAAAA=","37":"b:T+rt+QN+5/FA+v/HwmAI8H/+f7D+////AAAAAAA=","41":"b:T+rt+QN+5/FA+v/HwmAI8H/+P7D+////AAAAAAA=","56":[46,150],"67":[46,73],"92":"b:T+pt+AF+5/FA+v9HgmMI8H/+P7D//3//AAAAAAA=","98":[46],"102":"b:BgKBKQBqQJFAOt9EgAAA4A6gDhDkah8CAAAAAAA=","108":[46]},"packages/vite/source-map-js-shim.ts":{"1":"b:/+r/+4P/5/92+v/v////////////////AAAAAAA="},"localhost-43513/assets/index-Dv_brJ4-.js":{"3":[41,58,82,177]},"localhost-43513/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[41,58,82,177],"9":[41,58,82,177],"10":[41,58,82,177],"19":[41,58,82,177],"23":[41,58,82,177],"29":[41,58,82,177],"33":[41,58,82,177],"34":[41,58,82,177]},"localhost-43513/assets/verified-Dido3Ow4.js":{"8":[41,82,177]},"packages/@n8n/utils/src/string/truncate.ts":{"1":"b:cCJ+AoDoAh5CAHQJAJAFAgAAAEEAgQHAAAAAAAA=","11":"b:cAD6gQBAAgAAAAAAAIABAEAAAAAgFAMAAAAAAAA=","29":[46,19,20,21,49,22]},"packages/frontend/@n8n/design-system/src/components/N8nCallout/Callout.vue":{"10":"b:EADBIABAAAAAAL6CKYrDUAAIBAGA5h8AAAAAAAA=","36":"b:EADBIABAAAAAAL6CKYrDUAAIBAGA5h8AAAAAAAA=","45":"b:EADBAABAAAAAAL6AKYrBQAAIBAGA5hIAAAAAAAA=","49":"b:EADBAABAAAAAAL6AKYrBQAAIBAGA5hIAAAAAAAA=","58":"b:EADBIABAAAAAAL6CKYrDUAAIBAGA5h8AAAAAAAA=","65":[23,95,46],"70":"b:EADBIABAAAAAAL6CKYrDUAAIBAGA5h8AAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nDropdownMenu/DropdownMenuItem.vue":{"71":"b:IAIleQDAAEsyCFAAAOAHAZATeLAgAYthAAAAAAA=","73":"b:IAAFWABAAAAAAFAAAMABABASOAAgAAMgAAAAAAA=","75":"b:IAAFWABAAAAAAFAAAMABABASOAAgAAMgAAAAAAA=","78":[46],"82":"b:IAIleQDAAEsyCFAAAOAHAZATeLAgAYthAAAAAAA=","83":"b:IAIleQDAAEsyCFAAAOAHAZATeLAgAYthAAAAAAA=","85":"b:IAAlWABAAEIACFAAAMABAJATOLAgAYMgAAAAAAA=","91":[46],"95":"b:IAIleQDAAEsyCFAAAOAHAZATeLAgAYthAAAAAAA=","99":"b:IAIleQDAAEsyCFAAAOAHAZATeLAgAYthAAAAAAA=","103":"b:IAIleQDAAEsyCFAAAOAHAZATeLAgAYthAAAAAAA=","107":"b:AAIFeQBAAEsyCFAAAGAGABATeLAgAYthAAAAAAA=","109":"b:IAAFWABAAAAAAFAAAMABABASOAAgAAMgAAAAAAA=","113":"b:IAIFeQDAAEsyCFAAAOAHAZATeLAgAYthAAAAAAA=","120":"b:IAIFeQDAAEsyCFAAAOAHAZATeLAgAYthAAAAAAA=","125":[46],"130":[46],"146":[46],"152":[46],"158":"b:IAAFWABAAAAAAFAAAEAAABASOAAgAAMgAAAAAAA=","169":[5,46],"175":"b:IAAFWABAAAAAAFAAAMABABASOAAgAAMgAAAAAAA=","181":"b:IAAFWABAAAAAAFAAAMABABASOAAgAAMgAAAAAAA=","185":"b:IAAFWABAAAAAAFAAAMABABASOAAgAAMgAAAAAAA=","195":[46],"203":[46],"210":[46],"222":[46],"227":"b:IAIleQDAAEsyCFAAAOAHAZATeLAgAYthAAAAAAA=","228":"b:IAIleQDAAEsyCFAAAOAHAZATeLAgAYthAAAAAAA=","237":"b:IAAFWABAAAAAAFAAAMABABASOAAgAAMgAAAAAAA=","247":"b:IAIleADAAEsyCFAAAOAHAZATeLAgAYthAAAAAAA=","250":"b:IAIleQDAAEsyCFAAAOAHAZATeLAgAYthAAAAAAA=","257":[46,21,120],"264":"b:IAAlWABAAEIACFAAAMABAJATOLAgAYMhAAAAAAA=","279":"b:IAAlWABAAEIACFAAAMABAJATOLAgAYMhAAAAAAA=","281":"b:AAAFWABAAEIACFAAAEAAAJATOLAgAYMhAAAAAAA=","299":[46],"304":[46],"310":"b:AAAFWABAAEAACFAAAEAAABASOLAgAYMhAAAAAAA=","315":"b:AAAFWABAAEAACFAAAEAAABASOLAgAYMhAAAAAAA=","357":"b:IAAlWABAAEIACFAAAMABAJATOLAgAYMhAAAAAAA=","370":"b:IAAFWABAAAAAAFAAAMABABASOAAgAAMgAAAAAAA=","380":[46],"384":[46],"387":[46],"400":[46],"411":[46],"414":[46],"416":[46],"419":[46],"422":[46],"436":[46],"445":"b:IAAFWABAAAAAAFAAAMABABASOAAgAAMgAAAAAAA=","453":"b:IAAFWABAAAAAAFAAAMABABASOAAgAAMgAAAAAAA=","456":"b:IAAFWABAAAAAAFAAAMABABASOAAgAAMgAAAAAAA=","459":"b:IAAFWABAAAAAAFAAAMABABASOAAgAAMgAAAAAAA=","486":[24,46],"488":[24,46],"500":[24,46],"505":[24,46],"526":"b:IAIleQDAAEsyCFAAAOAHAZATeLAgAYthAAAAAAA=","528":"b:AAIFeQBAAEsyCFAAAGAHAZATeLAgAYthAAAAAAA=","540":"b:AAIFeQBAAEsyCFAAAGAGABATeLAgAYthAAAAAAA=","545":"b:AAIFeQBAAEsyCFAAAGAGABATeLAgAYthAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nDropdownMenu/DropdownMenuItems.vue":{"37":"b:IAIleQDAAEsyCFAAAOAHAZATeLAgAYthAAAAAAA=","53":"b:IAIleQDAAEsyCFAAAOAHAZATeLAgAYthAAAAAAA=","60":[46,21,57],"74":"b:IAIleQDAAEsyCFAAAOAHAZATeLAgAYthAAAAAAA=","76":"b:IAIleQDAAEsyCFAAAOAHAZATeLAgAYthAAAAAAA=","84":"b:IAIFeQDAAEsyCFAAAOAHAZATeLAgAYthAAAAAAA=","85":[46],"86":"b:IAAFWABAAAAAAFAAAMABABASOAAgAAMgAAAAAAA=","87":"b:IAIFeQDAAEsyCFAAAOAHAZATeLAgAYthAAAAAAA=","88":[46],"90":[111,5,112,46,47,21,120,18],"93":[111,5,112,46,47,21,120,135,57,136,18],"96":"b:IAAkAQDAAAoyAAAAAIAHAQABQAAAAAhAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/node-dirty.svg":{"11":[46,56,138,146,166,172,177,179,182]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/node-pin.svg":{"11":"b:AAABAABAAAAAAD4AAAIAAAACAACo9kOAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/triangle.svg":{"8":[28,46,56,60,138,166,172,177,179,182]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/no-operation.svg":{"11":"b:ACJBAAAIAAFAAqYAAAAAQAgCDBAgJAKiAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/respond-to-webhook.svg":{"11":[41,109,56,176,177]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/svgContentDirective.ts":{"13":"b:AAAFWABAAFAACFAAAEAAABASOLAgAYMhAAAAAAA=","16":[46,75],"21":"b:AAAFWABAAFAACFAAAEAAABASOLAgAYMhAAAAAAA="},"packages/frontend/@n8n/design-system/src/types/binary.ts":{"24":"b:CCBFmgBAAEEAID4EAEIAAEwGLADI/nsQAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useDependencyMenu.ts":{"59":"b:AAAAAAAk4BAAAkACAAAAAEAAAGAAAADAAAAAAAA=","80":[157],"125":"b:AAAFWAAAAEAACFAAAEAAABASOLAgAYMhAAAAAAA="},"packages/frontend/editor-ui/src/app/utils/json-schema.ts":{"5":[46,172,177],"9":[46,172,177],"12":[46,172,177],"25":[46,172],"32":[46,172,177],"35":[46,172,177]},"packages/frontend/editor-ui/src/experiments/mcpJsonNudge/composables/useMcpJsonNudgeEligibility.ts":{"22":"b:AAAFWAAAAAAAEFADAEAAABASOAAkAAMgAAAAAAA=","32":"b:AAAFWAAAAAAAEFADAEAAABASOAAkAAMgAAAAAAA="},"packages/frontend/editor-ui/src/experiments/mcpJsonNudge/composables/useMcpJsonNudgeTrigger.ts":{"26":"b:AAAFWAAAAAAAEFADAEAAABASOAAkAAMgAAAAAAA="},"packages/frontend/editor-ui/src/features/ndv/panel/components/TriggerPanel.vue":{"40":"b:AAIAAAACQAEAAAAAgCAAEAAAAAAAFBcAAAAAAAA=","71":"b:AAIAAAACQAEAAAAAgCAAEAAAAAAAFBcAAAAAAAA=","75":"b:AAIAAAACQAEAAAAAgCAAEAAAAAAAFBcAAAAAAAA=","83":[103,41,109,54,56,170,172,176,177],"91":[103,41,109,54,56,170,172,176,177],"110":"b:AAIAAAACQAEAAAAAgCAAEAAAAAAAFBcAAAAAAAA=","116":[41,109,56,172,176,177],"124":[103,54],"132":[103,41,109,54,56,170,172,176,177],"136":"b:AAIAAAACQAEAAAAAgCAAEAAAAAAAFBcAAAAAAAA=","154":"b:AAIAAAACQAEAAAAAgCAAEAAAAAAAFBcAAAAAAAA=","162":[103,41,109,54,56,170,172,176,177],"166":[103,54,56,172],"170":[103,41,109,54,56,170,172,176,177],"188":[103,41,109,54,56,172,176,177],"190":[103,41,109,54,56,172,176,177],"196":[103,41,109,54,56,172,176,177],"198":[103,54],"204":[103,54],"217":[103,41,109,54,56,172,176,177],"235":[103,41,109,54,56,172,176,177],"245":[103,41,109,54,56,172,176,177],"285":[103,41,109,54,56,172,176,177],"375":[170],"384":"b:AAIAAAACQAEAAAAAgCAAEAAAAAAAFBcAAAAAAAA=","415":[56,170],"436":[103,54],"440":[103,54],"471":[103,41,109,54,56,172,176,177],"514":[103,41,109,54,56,172,176,177],"520":[103,41,109,54,56,172,176,177]},"packages/frontend/editor-ui/src/features/ndv/panel/components/WireMeUp.vue":{"8":[2,41,9,46,56,141,143,70,176,16,177,86]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/AssignmentCollection/Assignment.vue":{"35":"b:AABFCABAAEEAABwAACAAAEAIIQAIVAIAAAAAAAA=","39":"b:AABFCABAAEEAABwAACAAAEAIIQAIVAIAAAAAAAA=","40":[46],"57":"b:AABFCABAAEEAABwAACAAAEAIIQAIVAIAAAAAAAA=","81":"b:AABFCABAAEEAABwAACAAAEAIIQAIVAIAAAAAAAA=","90":"b:AABFCABAAEEAABwAACAAAEAIIQAIVAIAAAAAAAA=","104":"b:AABFCABAAEEAABwAACAAAEAIIQAIVAIAAAAAAAA=","106":"b:AABFCABAAEEAABwAACAAAEAIIQAIVAIAAAAAAAA=","115":"b:AABFCABAAEEAABwAACAAAEAIIQAIVAIAAAAAAAA=","117":[27,46,134,139,149,170,18,82,83,174,16,177],"119":[109,46,56,82],"123":[109,46,56],"131":[109,46,56,82,83,174,16,177],"135":[46],"139":[109,46,56,163,82,83,174,16],"143":[46,82],"156":"b:AABFCABAAEEAABwAACAAAEAIIQAIVAIAAAAAAAA=","214":"b:AABFCABAAEEAABwAACAAAEAIIQAIVAIAAAAAAAA=","230":"b:AABFCABAAEEAABwAACAAAEAIIQAIVAIAAAAAAAA=","232":[46],"234":"b:AABFCABAAEEAABwAACAAAEAIIQAIVAIAAAAAAAA=","244":"b:AABFCABAAEEAABwAACAAAEAIIQAIVAIAAAAAAAA="},"packages/frontend/editor-ui/src/features/ndv/parameters/components/AssignmentCollection/TypeSelect.vue":{"17":"b:AABFCABAAEEAABwAACAAAEAIIQAIVAIAAAAAAAA=","30":"b:AABFCABAAEEAABwAACAAAEAIIQAIVAIAAAAAAAA=","32":"b:AABFCABAAEEAABwAACAAAEAIIQAIVAIAAAAAAAA=","33":"b:AABFCABAAEEAABwAACAAAEAIIQAIVAIAAAAAAAA=","43":[109,46,56],"45":"b:AABFCABAAEEAABwAACAAAEAIIQAIVAIAAAAAAAA=","58":"b:AABFCABAAEEAABwAACAAAEAIIQAIVAIAAAAAAAA=","60":"b:AABFCABAAEEAABwAACAAAEAIIQAIVAIAAAAAAAA="},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ImportCurlParameter.vue":{"11":"b:AIIAQABkAAEAEAEAAGAAAAQACgAAAgIAAAAAAAA=","14":[46],"16":"b:AIIAQABkAAEAEAEAAGAAAAQACgAAAgIAAAAAAAA="},"packages/frontend/editor-ui/src/features/ndv/parameters/components/InputTriple/InputTriple.vue":{"10":"b:AABFCABAAEEAABwAACAAAEgIIQAIVAIAAAAAAAA=","13":"b:AABFCABAAEEAABwAACAAAEgIIQAIVAIAAAAAAAA=","21":"b:AABFCABAAEEAABwAACAAAEgIIQAIVAIAAAAAAAA=","22":"b:AABFCABAAEEAABwAACAAAEgIIQAIVAIAAAAAAAA="},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataPinButton.vue":{"6":"b:AABEAABAQEEAAD4EgEIAAGwEIADA9msQAAAAAAA=","24":"b:AABEAABAQEEAAD4EgEIAAGwEIADA9msQAAAAAAA=","27":"b:AABEAABAQEEAAD4EgEIAAGwEIADA9msQAAAAAAA=","31":[46,54,56],"45":[46],"48":[46],"49":"b:AABEAABAQEEAAD4EgEIAAGwEIADA9msQAAAAAAA=","67":[46,169,177]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunInfo.vue":{"7":"b:CABEGAAAQEEAADwEgEAAAGwEIABA1msQAAAAAAA=","15":"b:CABEGAAAQEEAADwEgEAAAGwEIABA1msQAAAAAAA=","19":"b:CABEGAAAQEEAADwEgEAAAGwEIABA1msQAAAAAAA=","23":"b:CABEGAAAQEEAADwEgEAAAGwEIABA1msQAAAAAAA=","33":"b:CABEGAAAQEEAADwEgEAAAGwEIABA1msQAAAAAAA="},"packages/frontend/editor-ui/src/features/ndv/runData/components/VirtualSchema.vue":{"69":"b:CCBFGgBAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","107":"b:CCBFGgBAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","108":"b:CCBFGgBAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","110":[46],"114":[46,82],"117":[46,82],"123":"b:ACBFGABAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","134":"b:ACBFGABAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","143":"b:ACBFGABAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","159":[46,18,176,85],"165":"b:ACBEGABAAEAAID4EAEAAAEwGJABA/msQAAAAAAA=","176":"b:ACBEGABAAEAAID4EAEAAAEwGJABA/msQAAAAAAA=","205":"b:ACBFGABAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","209":"b:ACBFGABAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","231":"b:ACBFGABAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","254":"b:ACBFGABAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","286":"b:CCBFGgBAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","298":"b:ACBEGABAAEAAIDAEAEAAAEwGLABAPjsQAAAAAAA=","320":"b:CCBFGgBAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","366":"b:ACBFGABAAEAAID4EAEAAAEwGJADI/nsQAAAAAAA=","384":"b:ACBFGABAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","388":[25,3,46,18,84],"403":"b:CCBFGgBAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","405":"b:CCBFGgBAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","431":"b:CCBFGgBAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","439":"b:CCBFGgBAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","443":"b:CCBFGgBAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","444":[46,84],"456":"b:CCBFGgBAAEAAID4EAEAAAEwGJADI/nsQAAAAAAA=","461":"b:ACBFGABAAEAAID4EAEAAAEwGJADI/nsQAAAAAAA=","463":"b:ACBFGABAAEAAID4EAEAAAEwGJADI/nsQAAAAAAA=","466":"b:CCBFGgBAAEAAID4EAEAAAEwGJADI/nsQAAAAAAA=","467":[46],"473":[46,82],"482":[46,82],"484":[46,82],"486":[46,82],"511":"b:CCBFGgBAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","523":[46,84],"524":[46,84],"525":[46],"543":"b:CCBFGgBAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","545":"b:CCBFGgBAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","552":"b:CCBFGgBAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","558":"b:CCBFGgBAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","563":[46],"564":[46,82],"565":[46],"574":[46,84],"579":[46,172,180],"593":[46],"602":[46,170],"610":[46],"622":"b:AABEGgBAAEAAABAEAEAAAAQGBABALgkQAAAAAAA=","628":[46,170,171,173]},"packages/frontend/editor-ui/src/features/ndv/runData/components/VirtualSchemaHeader.vue":{"10":"b:ACBFGABAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","22":"b:ACBFGABAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","24":"b:ACBFGABAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","32":[46],"63":[46],"70":[46,171],"71":[46],"72":[46,171],"77":[46,172,180],"78":[46],"79":[46,172,180],"82":[46,172,180],"84":[46,172,180]},"packages/frontend/editor-ui/src/features/ndv/runData/components/VirtualSchemaItem.vue":{"37":"b:CCBFGgBAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","41":[46],"60":[46],"70":"b:CCBFGgBAAEAAID4EAEAAAEwGLADI/nsQAAAAAAA=","77":[46,84],"105":[46],"107":"b:ACBFGABAAEAAID4EAEAAAEwGLADAflsQAAAAAAA="},"packages/frontend/editor-ui/src/features/ndv/runData/schemaPreview.api.ts":{"13":"b:AAAAAABAAAAAADAAAAAAAEAKDACAODIQAAAAAAA=","17":[46,147,172,177,180],"27":"b:AAAAAABAAAAAADAAAAAAAEAKDACAODIQAAAAAAA="},"packages/frontend/editor-ui/src/features/shared/editors/components/InlineExpressionEditor/ExpressionOutput.vue":{"20":"b:AEABAABAAAACAC8AAAAAAAAAAACAYA4AAAAAAAA=","33":"b:AEABAABAAAACAC8AAAAAAAAAAACAYA4AAAAAAAA=","34":"b:AAABAABAAAACAC8AAAAAAAAAAACAYAoAAAAAAAA=","37":"b:AEABAABAAAACAC8AAAAAAAAAAACAYA4AAAAAAAA=","46":"b:AAABAABAAAACAC8AAAAAAAAAAACAYAoAAAAAAAA=","60":"b:AEABAABAAAACAC8AAAAAAAAAAACAYA4AAAAAAAA=","62":"b:AAABAABAAAACAC8AAAAAAAAAAACAYAoAAAAAAAA=","65":"b:AEABAABAAAACAC8AAAAAAAAAAACAYA4AAAAAAAA=","88":"b:AAABAABAAAACAC8AAAAAAAAAAACAYAoAAAAAAAA=","99":"b:AAABAABAAAACAC8AAAAAAAAAAACAYAoAAAAAAAA=","102":"b:AEABAABAAAACAC8AAAAAAAAAAACAYA4AAAAAAAA=","112":[46,173],"122":"b:AEABAABAAAACAC8AAAAAAAAAAACAYA4AAAAAAAA=","123":"b:AAABAABAAAACAC8AAAAAAAAAAACAYAoAAAAAAAA=","136":"b:AEABAABAAAACAC8AAAAAAAAAAACAYA4AAAAAAAA=","138":[46],"149":"b:AEABAABAAAACAC8AAAAAAAAAAACAYA4AAAAAAAA=","154":[46,65,167,81,82,173,83,174,16,178,179],"158":[46,173],"159":"b:AEABAABAAAACAC8AAAAAAAAAAACAYA4AAAAAAAA="},"packages/frontend/editor-ui/src/features/shared/editors/components/InlineExpressionEditor/InlineExpressionTip.vue":{"28":"b:AEABQABgQAECAC8EgGAAAAwAAACAYg4AAAAAAAA=","41":"b:AEABAABAAAACAC4AAAAAAAAAAACAYA4AAAAAAAA=","45":[46,81,82,173,83,174,16,85,177],"47":"b:AEABQABgQAECAC8EgGAAAAwAAACAYg4AAAAAAAA=","68":[46,65,81,82,173,83,174,16,85,177,178,179],"94":"b:AAABQABgQAECAA8EgGAAAAwAAACAYgwAAAAAAAA=","99":"b:AEABQABgQAECAC8EgGAAAAwAAACAYg4AAAAAAAA=","107":"b:AEABQABgQAECAC8EgGAAAAwAAACAYg4AAAAAAAA=","108":[46,65,81,82,173,83,174,16,85,177,178,179],"111":[46],"117":"b:AEABQABgQAECAC8EgGAAAAwAAACAYg4AAAAAAAA=","121":"b:AEABQABgQAECAC8EgGAAAAwAAACAYg4AAAAAAAA=","125":[46,82,83,174,16,177],"131":[46,82,83,174,16,177]},"packages/frontend/editor-ui/src/features/shared/editors/components/InlineExpressionEditor/OutputItemSelect.vue":{"7":"b:AEABAABAAAACAC8AAAAAAAAAAACAYA4AAAAAAAA=","10":"b:AEABAABAAAACAC8AAAAAAAAAAACAYA4AAAAAAAA=","11":"b:AEABAABAAAACAC8AAAAAAAAAAACAYA4AAAAAAAA=","12":"b:AEABAABAAAACAC8AAAAAAAAAAACAYA4AAAAAAAA=","13":"b:AEABAABAAAACAC8AAAAAAAAAAACAYA4AAAAAAAA=","14":"b:AEABAABAAAACAC8AAAAAAAAAAACAYA4AAAAAAAA=","17":"b:AEABAABAAAACAC8AAAAAAAAAAACAYA4AAAAAAAA=","18":"b:AEABAABAAAACAC8AAAAAAAAAAACAYA4AAAAAAAA=","19":"b:AEABAABAAAACAC8AAAAAAAAAAACAYA4AAAAAAAA=","20":"b:AEABAABAAAACAC8AAAAAAAAAAACAYA4AAAAAAAA=","21":"b:AEABAABAAAACAC8AAAAAAAAAAACAYA4AAAAAAAA=","25":"b:AEABAABAAAACAC8AAAAAAAAAAACAYA4AAAAAAAA=","26":"b:AEABAABAAAACAC8AAAAAAAAAAACAYA4AAAAAAAA=","28":[46],"32":[46,16,85],"36":[46,16],"38":"b:AEABAABAAAACAC8AAAAAAAAAAACAYA4AAAAAAAA=","44":"b:AEABAABAAAACAC8AAAAAAAAAAACAYA4AAAAAAAA=","69":[46],"71":"b:AEABAABAAAACAC8AAAAAAAAAAACAYA4AAAAAAAA="},"packages/frontend/editor-ui/src/features/shared/editors/components/JsonEditor/JsonEditor.vue":{"33":"b:CAABAABEAAAEAC4AAAAAAAEAAACEaCIAAAAAAAA=","43":"b:CAABAABEAAAEAC4AAAAAAAEAAACEaCIAAAAAAAA=","71":"b:CAABAABAAAAEAC4AAAAAAAEAAACEaCIAAAAAAAA=","80":"b:CAABAABEAAAEAC4AAAAAAAEAAACEaCIAAAAAAAA=","84":[3,46,128,167,81,82,173,83,174,16,85,177],"89":"b:CAABAABEAAAEAC4AAAAAAAEAAACEaCIAAAAAAAA=","90":[46,167,81,82,173,83,174,85,177],"102":"b:CAABAABEAAAEAC4AAAAAAAEAAACEaCIAAAAAAAA=","110":[46],"114":[46],"124":"b:CAABAABEAAAEAC4AAAAAAAEAAACEaCIAAAAAAAA="},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/blank.completions.ts":{"8":"b:AAABAABAAAACAA8AAAAAAAAAAACAYA4AAAAAAAA="},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/bracketAccess.completions.ts":{"17":"b:AAABAABAAAACAA8AAAAAAAAAAACAYA4AAAAAAAA=","53":[46,81,82,173,16],"62":[46,82],"70":[46,81,82,173,16],"74":[46,81,82,173,16],"75":[46,81,82,173,16]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/dollar.completions.ts":{"29":"b:AAABAABAAAACAA8AAAAAAAAAAACAYA4AAAAAAAA=","43":[46,65,167,80,81,82,173,83,174,16,177,179],"52":[46],"60":[46,65,167,80,81,82,173,83,174,16,177,179],"138":[46,167,80,81,82,173,83,174,16,177,179],"153":[46,167,80,81,82,173,83,174,16,177,179],"155":[46,167,80,81,82,173,83,174,16,177,179]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/nonDollar.completions.ts":{"9":"b:AAABAABAAAACAA8AAAAAAAAAAACAYA4AAAAAAAA=","56":[46]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/ActionItem.vue":{"19":"b:BAIBIAAKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","35":"b:BAIBIAAKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","42":"b:BAIBIAAKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","99":"b:BAIBIAAKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","111":"b:BAIBIAAKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","117":"b:BAIBIAAKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA="},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/LabelItem.vue":{"11":"b:AAIBIAAKAABACAIAAAAAAAEAABAAIBcCAAAAAAA="},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/Modes/ActionsMode.vue":{"44":"b:BAIBIAAKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","67":"b:BAIBIAAKQABAAIAAgAAAEAEAABCAAB8CAAAAAAA=","70":"b:BAIBIAAKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","73":"b:AAIBIAAKQAFAOpJAgAAAgAAgABDkIB8CAAAAAAA=","80":[2,41,9,124,128,176,16,178,179,180],"90":"b:BAIBIAAKQABAAIAAgAAAEAEAABCAAB8CAAAAAAA=","96":"b:BAIBIAAKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","97":"b:BAIBIAAKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","102":"b:BAIBIAAKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","104":"b:BAIBIAAKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","106":"b:BAIBIAAKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","108":"b:BAIBIAAKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","113":"b:BAIBIAAKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","124":"b:BAIBIAAKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","130":"b:BAIBIAAKQABAAIAAgAAAEAEAABCAAB8CAAAAAAA=","139":"b:BAIBIAAKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","142":"b:BAIBIAAKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","149":"b:BAIBIAAKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","151":"b:BAIBIAAKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","173":"b:BAIBIAAKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","188":"b:BAIBIAAKQAFAOoJAgAAAEAEgABDkIB8CAAAAAAA=","200":"b:BAIBIAAKQAFAOoJAgAAAEAEgABDkIB8CAAAAAAA=","223":"b:BAIBIAAKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","226":"b:BAIBIAAKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","234":"b:BAIBIAAKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","269":"b:BAIBIAAKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","273":"b:BAIBIAAKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","274":"b:BAIBIAAKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","296":"b:BAIBIAAKQABAAIAAgAAAEAEAABCAAB8CAAAAAAA=","309":[124,176,16,178,179],"315":[124,176,16,178,179],"336":"b:BAIBIAAKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA=","351":[124,16,178,179]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/OrderSwitcher.vue":{"11":"b:BAIBIAAKQAFAOpJAgAAAkAEgABDkIB8CAAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/emptyGroup.utils.ts":{"13":[46],"17":[46],"20":[46],"31":[46],"42":[46],"96":"b:AAAFWABAAAAAEFADAEAAABASOAAkAAMgAAAAAAA=","114":[46],"115":[46]},"localhost-46447/assets/index-Dv_brJ4-.js":{"3":[31,123,63,14,81]},"localhost-46447/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[31,123,63,14,81],"9":[31,123,63,14,81],"10":[31,123,63,14,81],"19":[31,123,63,14,81],"23":[31,123,63,14,81],"29":[31,123,63,14,81],"33":[31,123,63,14,81],"34":[31,123,63,14,81]},"localhost-46447/assets/verified-Dido3Ow4.js":{"8":[14]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputOverrides/FromAiOverrideButton.vue":{"5":[6,9,46,13,14,15],"16":[6,9,46,13,14,15],"22":[46],"24":[6,9,46,13,14,15],"34":[6,46]},"packages/@n8n/backend-network/src/http/env-proxy-http-agent.ts":{"26":"b:gQoA+AEqoHNAvgnHAmAAAAAAgAAAEAAA9AEGAAA=","28":"b:gQoA+AEqoHNAvgnHAmAAAAAAgAAAEAAA9AEGAAA=","33":"b:gQoA+AEqoHNAvgnHAmAAAAAAgAAAEAAA9AEGAAA="},"packages/@n8n/backend-network/src/http/retryability.ts":{"30":[196],"49":[196],"66":[196],"81":[196],"82":[196],"85":[196],"89":[196],"96":[196],"116":[196],"130":[196],"142":[196],"166":[196]},"packages/@n8n/db/src/repositories/poller-state.repository.ts":{"32":[196,219,197,198,199,200],"42":[196,219,197,198,199,200],"59":[196,219,197,198,199,200],"104":[196,219,197,198,199,200],"119":[196,219,197,198,199,200],"150":[196,219,197,198,199,200],"159":[196,219,197,198,199,200],"183":[196,219,197,198,199,200],"196":[196,219,197,198,199,200],"197":[196,219,197,198,199,200],"199":[196,219,197,198,199,200],"212":[196,219,197,198,199,200],"223":[196,219,197,198,199,200],"232":[196,219,197,198,199,200]},"packages/@n8n/db/src/repositories/scheduled-job.repository.ts":{"71":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","79":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","96":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","130":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","135":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","141":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","153":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","163":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","170":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","181":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","186":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","192":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","197":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","203":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","208":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","238":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","263":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","279":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","288":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","301":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","311":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","321":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","332":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","355":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","365":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","375":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","381":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","396":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","413":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","428":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","438":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","462":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","488":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","512":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","535":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","553":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","569":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","580":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","581":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","583":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","589":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","590":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","599":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","600":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","617":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","618":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","619":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","642":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","650":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA="},"packages/@n8n/db/src/repositories/scheduled-task.repository.ts":{"154":[196,197,198,200,201,202,64],"175":[196,197,198,200,201,202,64],"187":[196,197,198,200,201,202,64],"230":[196,197,198,200,201,202,64],"247":[196,197,198,200,201,202,64],"257":[196,197,198,200,201,202,64],"260":[196,197,198,200,201,202,64],"261":[196,197,198,200,201,202,64],"282":[196,197,198,200,201,202,64],"292":[196,197,198,200,201,202,64],"313":[196,197,198,200,201,202,64],"318":[196,197,198,200,201,202,64],"325":[196,197,198,200,201,202,64],"329":[196,197,198,200,201,202,64],"334":[196,197,198,200,201,202,64],"370":[196,197,198,200,201,202,64],"375":[196,197,198,200,201,202,64],"420":[196,197,198,200,201,202,64],"432":[196,197,198,200,201,202,64],"443":[196,197,198,200,201,202,64],"450":[196,197,198,200,201,202,64],"452":[196,197,198,200,201,202,64],"477":[196,197,198,200,201,202,64],"489":[196,197,198,200,201,202,64],"490":[196,197,198,200,201,202,64],"505":[196,197,198,200,201,202,64],"507":[196,197,198,200,201,202,64],"520":[196,197,198,200,201,202,64],"522":[196,197,198,200,201,202,64],"527":[196,197,198,200,201,202,64],"530":[196,197,198,200,201,202,64],"539":[196,197,198,200,201,202,64],"542":[196,197,198,200,201,202,64],"543":[196,197,198,200,201,202,64],"554":[196,197,198,200,201,202,64],"561":[196,197,198,200,201,202,64],"562":[196,197,198,200,201,202,64],"582":[196,197,198,200,201,202,64],"598":[196,197,198,200,201,202,64],"623":[196,197,198,200,201,202,64],"669":[196,197,198,200,201,202,64],"686":[196,197,198,200,201,202,64],"691":[196,197,198,200,201,202,64],"692":[196,197,198,200,201,202,64],"693":[196,197,198,200,201,202,64],"715":[196,197,198,200,201,202,64],"720":[196,197,198,200,201,202,64],"721":[196,197,198,200,201,202,64],"736":[196,197,198,200,201,202,64],"741":[196,197,198,200,201,202,64],"754":[196,197,198,200,201,202,64],"787":[196,197,198,200,201,202,64],"823":[196,197,198,200,201,202,64],"824":[196,197,198,200,201,202,64],"845":[196,197,198,200,201,202,64],"860":[196,197,198,200,201,202,64],"890":[196,197,198,200,201,202,64],"915":[196,197,198,200,201,202,64],"928":[196,197,198,200,201,202,64],"940":[196,197,198,200,201,202,64],"969":[196,197,198,200,201,202,64],"1011":[196,197,198,200,201,202,64],"1015":[196,197,198,200,201,202,64],"1016":[196,197,198,200,201,202,64]},"packages/@n8n/db/src/repositories/settings.repository.ts":{"12":"b:ABB6BGAAgkCJAAAAgQAAAEAAAAAAAGAI+0dIAQA=","16":"b:ABB6BGAAgkCJAAAAgQAAAEAAAAAAAGAI+0dIAQA=","21":"b:ABB6BGAAgkCJAAAAgQAAAEAAAAAAAGAI+0dIAQA=","25":"b:ABB6BGAAgkCJAAAAgQAAAEAAAAAAAGAI+0dIAQA=","46":"b:ABB6BGAAgkCJAAAAgQAAAEAAAAAAAGAI+0dIAQA=","61":"b:ABB6BGAAgkCJAAAAgQAAAEAAAAAAAGAI+0dIAQA=","78":"b:ABB6BGAAgkCJAAAAgQAAAEAAAAAAAGAI+0dIAQA=","90":"b:ABB6BGAAgkCJAAAAgQAAAEAAAAAAAGAI+0dIAQA=","94":"b:ABB6BGAAgkCJAAAAgQAAAEAAAAAAAGAI+0dIAQA="},"packages/@n8n/db/src/repositories/workflow-publication-retry-state.repository.ts":{"11":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","15":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","27":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA="},"packages/@n8n/db/src/repositories/workflow-published-version.repository.ts":{"33":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfQAwA=","37":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfQAwA=","41":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfQAwA=","50":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfQAwA=","58":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfQAwA=","66":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfQAwA=","82":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfQAwA=","94":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfQAwA="},"packages/@n8n/db/src/repositories/workflow-review-request-workflow.repository.ts":{"34":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA=","38":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA=","58":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA=","82":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA=","94":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA=","107":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA=","129":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA=","144":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA=","165":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA=","172":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA=","201":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA="},"packages/@n8n/db/src/services/transaction.ts":{"29":"b:cBEAAGAQgECJDwAEAAAAAEAAAAAAAEBK+wfQAQA=","32":"b:cBEAAGAQgECJDwAEAAAAAEAAAAAAAEBK+wfQAQA="},"packages/@n8n/scheduler/src/core/executor/backoff.ts":{"24":[196]},"packages/@n8n/scheduler/src/core/executor/executor.ts":{"143":[196,197,198,201,202,64],"182":[196,197,198,201,202,64],"219":[196,197,198,201,202,64],"222":[196,197,198,201,202,64],"233":[196,197,198,201,202,64],"236":[196,197,198,201,202,64],"241":[196,197,198,201,202,64],"254":[196,197,198,201,202,64],"255":[196,197,198,201,202,64],"259":[196,197,198,201,202,64],"305":[196,197,198,201,202,64],"307":[196,197,198,201,202,64],"310":[196,197,198,201,202,64],"322":[196,197,198,201,202,64],"340":[196,197,198,201,202,64],"388":[196,197,198,201,202,64],"396":[196,197,198,201,202,64],"399":[196,197,198,201,202,64],"409":[196,197,198,201,202,64],"418":[196,197,198,201,202,64],"431":[196,197,198,201,202,64],"447":[196,197,198,201,202,64],"454":[196,197,198,201,202,64],"463":[196,197,198,201,202,64]},"packages/@n8n/scheduler/src/core/executor/lease-heartbeat.ts":{"43":[196,197,198,201,202,64],"45":[196,197,198,201,202,64],"51":[196,197,198,201,202,64],"68":[196,197,198,201,202,64],"74":[196,197,198,201,202,64],"79":[196,197,198,201,202,64],"80":[196,197,198,201,202,64],"85":[196,197,198,201,202,64],"86":[196,197,198,201,202,64],"87":[196,197,198,201,202,64],"91":[196,197,198,201,202,64]},"packages/@n8n/scheduler/src/core/executor/precision-timer.ts":{"14":[196,197,198,201,202,64],"15":[196,197,198,201,202,64],"16":[196,197,198,201,202,64],"35":[196,197,198,201,202,64],"38":[196,197,198,201,202,64],"43":[196,197,198,201,202,64],"50":[196,197,198,201,202,64],"58":[196,197,198,201,202,64],"66":[196,197,198,201,202,64]},"packages/@n8n/scheduler/src/core/executor/task-handler.ts":{"50":[196,197,198,201,202,64],"52":[196,197,198,201,202,64],"56":[196,197,198,201,202,64],"100":[196,197,198,201,202,64],"104":[196,197,198,201,202,64],"111":[196,197,198,201,202,64],"116":[196,197,198,201,202,64]},"packages/@n8n/scheduler/src/core/factory.ts":{"148":[196,197,198,201,202,64],"233":[196,197,198,201,202,64],"243":[196,197,198,201,202,64],"276":[196,197,198,201,202,64],"291":[196,197,198,201,202,64],"298":[196,197,198,201,202,64],"305":[196,197,198,201,202,64],"311":[196,197,198,201,202,64],"317":[196,197,198,201,202,64],"323":[196,197,198,201,202,64],"329":[196,197,198,201,202,64],"336":[196,197,198,201,202,64],"337":[196,197,198,201,202,64],"348":[196,197,198,201,202,64],"349":[196,197,198,201,202,64],"354":[196,197,198,201,202,64],"355":[196,197,198,201,202,64],"356":[196,197,198,201,202,64],"363":[196,197,198,201,202,64],"364":[196,197,198,201,202,64],"404":[196,197,198,201,202,64],"410":[196,197,198,201,202,64],"416":[196,197,198,201,202,64],"427":[196,197,198,201,202,64],"454":[196,197,198,201,202,64],"470":[196,197,198,201,202,64],"471":[196,197,198,201,202,64],"477":[196,197,198,201,202,64],"482":[196,197,198,201,202,64],"492":[196,197,198,201,202,64],"497":[196,197,198,201,202,64],"503":[196,197,198,201,202,64],"508":[196,197,198,201,202,64],"518":[196,197,198,201,202,64],"523":[196,197,198,201,202,64],"533":[196,197,198,201,202,64],"542":[196,197,198,201,202,64],"545":[196,197,198,201,202,64],"552":[196,197,198,201,202,64],"577":[196,197,198,201,202,64],"586":[196,197,198,201,202,64],"593":[196,197,198,201,202,64],"600":[196,197,198,201,202,64],"606":[196,197,198,201,202,64],"613":[196,197,198,201,202,64],"618":[196,197,198,201,202,64],"642":[196,197,198,201,202,64],"647":[196,197,198,201,202,64],"657":[196,197,198,201,202,64],"673":[196,197,198,201,202,64],"679":[196,197,198,201,202,64],"685":[196,197,198,201,202,64],"732":[196,197,198,201,202,64],"757":[196,197,198,201,202,64],"773":[196,197,198,201,202,64],"786":[196,197,198,201,202,64],"789":[196,197,198,201,202,64],"792":[196,197,198,201,202,64]},"packages/@n8n/scheduler/src/core/index.ts":{"18":[196,197,198,200,201,202,64],"72":[196,197,198,200,201,202,64],"104":[196,197,198,200,201,202,64],"106":[196,197,198,200,201,202,64]},"packages/@n8n/scheduler/src/core/materializer/coalesce-group.ts":{"15":[196,197,198,200,201,202,64],"17":[196,197,198,200,201,202,64],"19":[196,197,198,200,201,202,64],"26":[196,197,198,200,201,202,64],"36":[196,197,198,200,201,202,64],"40":[196,197,198,200,201,202,64],"46":[196,197,198,200,201,202,64],"54":[196,197,198,200,201,202,64],"68":[196,197,198,200,201,202,64]},"packages/@n8n/scheduler/src/core/materializer/materialize.ts":{"98":[196,197,198,200,201,202,64],"105":[196,197,198,200,201,202,64],"150":[196,197,198,200,201,202,64],"151":[196,197,198,200,201,202,64],"155":[196,197,198,200,201,202,64],"156":[196,197,198,200,201,202,64],"157":[196,197,198,200,201,202,64],"179":[196,197,198,200,201,202,64],"180":[196,197,198,200,201,202,64],"185":[196,197,198,200,201,202,64],"193":[196,197,198,200,201,202,64],"195":[196,197,198,200,201,202,64],"196":[196,197,198,200,201,202,64],"200":[196,197,198,200,201,202,64]},"packages/@n8n/scheduler/src/core/materializer/misfire.ts":{"29":[196,197,198,200,201,202,64],"37":[196,197,198,200,201,202,64],"64":[196,197,198,200,201,202,64],"66":[196,197,198,200,201,202,64],"67":[196,197,198,200,201,202,64]},"packages/@n8n/scheduler/src/core/materializer/owner-key.ts":{"23":[196,197,198,200,201,202,64],"27":[196,197,198,200,201,202,64],"31":[196,197,198,200,201,202,64],"37":[196,197,198,200,201,202,64]},"packages/@n8n/scheduler/src/core/materializer/plan.ts":{"51":[196,197,198,200,201,202,64]},"packages/@n8n/scheduler/src/core/provisioning/index.ts":{"1":[196,197,198,200,201,202,64]},"packages/@n8n/scheduler/src/core/provisioning/provision.ts":{"36":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","42":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","44":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","45":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","64":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","65":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","69":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","70":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","75":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","81":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","93":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","96":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","103":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","111":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","114":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","116":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","119":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","120":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","121":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","133":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA="},"packages/@n8n/scheduler/src/core/provisioning/provisioner.ts":{"80":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","86":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","89":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","98":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","100":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","114":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA="},"packages/@n8n/scheduler/src/core/provisioning/schedule-identity.ts":{"14":[196,197,198,200,201,202,64],"49":[196,197,198,200,201,202,64],"68":[196,197,198,200,201,202,64]},"packages/@n8n/scheduler/src/core/reaper/reap.ts":{"108":[196,201],"165":[196,201]},"packages/@n8n/scheduler/src/core/reconciliation/owner.ts":{"32":[196,197,198,200,201,202,64],"44":[196,197,198,200,201,202,64],"61":[196,197,198,200,201,202,64],"66":[196,197,198,200,201,202,64],"71":[196,197,198,200,201,202,64]},"packages/@n8n/scheduler/src/core/recurrence/field.ts":{"14":[196,197,198,200,201,202,64]},"packages/@n8n/scheduler/src/core/recurrence/kinds/cron.ts":{"25":[196,197,198,200,201,202,64],"62":[196,197,198,200,201,202,64],"82":[196,197,198,200,201,202,64],"103":[196,197,198,200,201,202,64],"112":[196,197,198,200,201,202,64],"127":[196,197,198,200,201,202,64]},"packages/@n8n/scheduler/src/core/recurrence/next-run.ts":{"33":[196,197,198,200,201,202,64],"68":[196,197,198,200,201,202,64],"92":[196,197,198,200,201,202,64]},"packages/@n8n/scheduler/src/core/recurrence/resolve.ts":{"24":[196,197,198,200,201,202,64],"50":[196,197,198,200,201,202,64]},"packages/@n8n/scheduler/src/observability/attributes.ts":{"77":[196,197,198,201,202,64],"92":[196,197,198,201,202,64]},"packages/@n8n/scheduler/src/observability/executor-tracing.ts":{"22":[196,197,198,201,202,64],"24":[196,197,198,201,202,64],"36":[196,197,198,201,202,64],"67":[196,197,198,201,202,64],"71":[196,197,198,201,202,64],"78":[196,197,198,201,202,64],"91":[196,197,198,201,202,64]},"packages/@n8n/scheduler/src/observability/provisioner-tracing.ts":{"23":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","25":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","28":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","43":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","46":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","65":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","67":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","68":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","69":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA=","82":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABCeQeBAgA="},"packages/@n8n/utils/src/errors/error-chain.ts":{"4":[118,119,22,196],"13":[118,119,22,196]},"packages/cli/src/activation-errors.service.ts":{"9":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","11":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","15":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","19":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","27":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","35":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA="},"packages/cli/src/execution-lifecycle/execute-error-workflow.ts":{"23":"b:cAAAAGAAgECJAAAEAAABAEAAAAAAAGAI+wfAIQA=","42":"b:cAAAAGAAgECJAAAEAAABAEAAAAAAAGAI+wfAIQA=","121":"b:cAAAAGAAgECJAAAEAAABAEAAAAAAAGAI+wfAIQA=","129":"b:cAAAAGAAgECJAAAEAAABAEAAAAAAAGAI+wfAIQA=","145":"b:cAAAAGAAgECJAAAEAAABAEAAAAAAAGAI+wfAIQA=","150":"b:cAAAAGAAgECJAAAEAAABAEAAAAAAAGAI+wfAIQA=","158":"b:cAAAAGAAgECJAAAEAAABAEAAAAAAAGAI+wfAIQA="},"packages/cli/src/metrics/prometheus/scheduler-metrics.service.ts":{"45":[196,197,198,201,202,64],"51":[196,197,198,201,202,64],"55":[196,197,198,201,202,64],"61":[196,197,198,201,202,64],"171":[196,197,198,201,202,64],"183":[196,197,198,201,202,64],"184":[196,197,198,201,202,64],"191":[196,197,198,201,202,64],"192":[196,197,198,201,202,64],"199":[196,197,198,201,202,64],"200":[196,197,198,201,202,64],"207":[196,197,198,201,202,64],"209":[196,197,198,201,202,64],"223":[196,197,198,201,202,64],"229":[196,197,198,201,202,64],"235":[196,197,198,201,202,64],"241":[196,197,198,201,202,64],"247":[196,197,198,201,202,64],"253":[196,197,198,201,202,64],"259":[196,197,198,201,202,64],"266":[196,197,198,201,202,64],"277":[196,197,198,201,202,64],"283":[196,197,198,201,202,64],"293":[196,197,198,201,202,64],"299":[196,197,198,201,202,64],"305":[196,197,198,201,202,64]},"packages/cli/src/modules/workflow-reviews.ee/workflow-review-feature-gate.service.ts":{"17":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA=","22":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA=","26":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA=","33":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA="},"packages/cli/src/modules/workflow-reviews.ee/workflow-review-lifecycle.service.ts":{"51":"b:ABECAGAQgViJDAAEAAAAAEAAAAAAAEBL+wfAAQA=","62":"b:ABECAGAQgViJDAAEAAAAAEAAAAAAAEBL+wfAAQA=","67":"b:ABECAGAQgViJDAAEAAAAAEAAAAAAAEBL+wfAAQA=","73":"b:ABECAGAQgViJDAAEAAAAAEAAAAAAAEBL+wfAAQA=","89":"b:ABECAGAQgViJDAAEAAAAAEAAAAAAAEBL+wfAAQA=","99":"b:ABECAGAQgViJDAAEAAAAAEAAAAAAAEBL+wfAAQA=","130":"b:ABECAGAQgViJDAAEAAAAAEAAAAAAAEBL+wfAAQA=","170":"b:ABECAGAQgViJDAAEAAAAAEAAAAAAAEBL+wfAAQA=","175":"b:ABECAGAQgViJDAAEAAAAAEAAAAAAAEBL+wfAAQA=","202":"b:ABECAGAQgViJDAAEAAAAAEAAAAAAAEBL+wfAAQA=","209":"b:ABECAGAQgViJDAAEAAAAAEAAAAAAAEBL+wfAAQA=","239":"b:ABECAGAQgViJDAAEAAAAAEAAAAAAAEBL+wfAAQA=","245":"b:ABECAGAQgViJDAAEAAAAAEAAAAAAAEBL+wfAAQA=","249":"b:ABECAGAQgViJDAAEAAAAAEAAAAAAAEBL+wfAAQA=","280":"b:ABECAGAQgViJDAAEAAAAAEAAAAAAAEBL+wfAAQA=","285":"b:ABECAGAQgViJDAAEAAAAAEAAAAAAAEBL+wfAAQA=","328":"b:ABECAGAQgViJDAAEAAAAAEAAAAAAAEBL+wfAAQA="},"packages/cli/src/modules/workflow-reviews.ee/workflow-review-publish-guard.service.ts":{"12":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA=","17":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA="},"packages/cli/src/modules/workflow-reviews.ee/workflow-review-state-notifier.service.ts":{"8":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA=","14":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA=","17":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA=","22":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA="},"packages/cli/src/policy/enforce-workflow-publish.ts":{"20":"b:ABECAGAQgECJDwAEAAAAAEAAAAAAAEBK+wfAAQA="},"packages/cli/src/scheduling/desired-job-name.ts":{"11":[196,197,198,200,201,202,64],"17":[196,197,198,200,201,202,64]},"packages/cli/src/scheduling/durable-job-provisioner.ts":{"131":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","144":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","145":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","156":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","161":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","180":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","191":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","199":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","207":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","219":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","228":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","239":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","247":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","262":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","263":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","314":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","316":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","323":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","325":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","340":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","350":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","352":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","355":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","360":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","362":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","364":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","367":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","377":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","418":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","419":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","421":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","423":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","428":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","450":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA="},"packages/cli/src/scheduling/durable-scheduler.ts":{"37":[196,197,198,200,201,202,64],"110":[196,197,198,200,201,202,64],"111":[196,197,198,200,201,202,64],"113":[196,197,198,200,201,202,64],"125":[196,197,198,200,201,202,64],"129":[196,197,198,200,201,202,64],"142":[196,197,198,200,201,202,64],"147":[196,197,198,200,201,202,64],"153":[196,197,198,200,201,202,64],"180":[196,197,198,200,201,202,64],"194":[196,197,198,200,201,202,64],"199":[196,197,198,200,201,202,64],"201":[196,197,198,200,201,202,64],"203":[196,197,198,200,201,202,64],"207":[196,197,198,200,201,202,64],"209":[196,197,198,200,201,202,64],"210":[196,197,198,200,201,202,64],"213":[196,197,198,200,201,202,64]},"packages/cli/src/scheduling/poll-trigger-node/poll-trigger-job-registrar.ts":{"30":"b:AAECAAAAAAAAAAAAAAAAAAAAAAAAAABDeQOBAgA=","47":"b:AAECAAAAAAAAAAAAAAAAAAAAAAAAAABDeQOBAgA=","89":"b:AAECAAAAAAAAAAAAAAAAAAAAAAAAAABDeQOBAgA=","99":"b:AAECAAAAAAAAAAAAAAAAAAAAAAAAAABDeQOBAgA=","113":"b:AAECAAAAAAAAAAAAAAAAAAAAAAAAAABDeQOBAgA=","122":"b:AAECAAAAAAAAAAAAAAAAAAAAAAAAAABDeQOBAgA=","133":"b:AAECAAAAAAAAAAAAAAAAAAAAAAAAAABDeQOBAgA=","147":"b:AAECAAAAAAAAAAAAAAAAAAAAAAAAAABDeQOBAgA="},"packages/cli/src/scheduling/poll-trigger-node/poll-trigger-task-handler.ts":{"34":[196,197,198],"50":[196,197,198],"64":[196,197,198],"75":[196,197,198],"124":[196,197,198],"144":[196,197,198],"245":[196,197,198],"252":[196,197,198],"266":[196,197,198],"267":[196,197,198],"271":[196,197,198]},"packages/cli/src/scheduling/resolve-task-trigger-node.ts":{"24":[196,197,198,201,202,64],"30":[196,197,198,201,202,64]},"packages/cli/src/scheduling/schedule-columns.ts":{"23":[196,197,198,200,201,202,64],"64":[196,197,198,200,201,202,64]},"packages/cli/src/scheduling/schedule-trigger-node/schedule-trigger-job-registrar.ts":{"117":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEBD+QeBAwg=","145":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEBD+QeBAwg=","164":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEBD+QeBAwg=","173":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEBD+QeBAwg=","184":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEBD+QeBAwg=","236":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEBD+QeBAwg=","251":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEBD+QeBAwg=","278":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEBD+QeBAwg=","325":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEBD+QeBAwg=","366":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEBD+QeBAwg=","381":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEBD+QeBAwg=","400":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEBD+QeBAwg=","409":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEBD+QeBAwg=","411":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEBD+QeBAwg=","428":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEBD+QeBAwg=","432":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEBD+QeBAwg=","445":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEBD+QeBAwg=","456":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEBD+QeBAwg="},"packages/cli/src/scheduling/seeded-cron.ts":{"10":[196,197,198,200],"19":[196,197,198,200]},"packages/cli/src/scheduling/workflow-node-task-payload.ts":{"1":[196,197,198,201,202,64],"11":[196,197,198,201,202,64]},"packages/cli/src/scheduling/workflow-scheduled-job-owner.ts":{"16":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","19":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","24":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA=","28":"b:AAECAAAAAAABAAAAAAAAAAAAAAAAAABDeQeBAgA="},"packages/cli/src/workflows/publication/heal-node-ids.ts":{"54":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA=","64":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA=","92":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA=","95":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA=","105":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA=","116":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA="},"packages/cli/src/workflows/publication/publication-status-reporter.ts":{"43":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","57":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","92":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","109":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","148":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","153":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","160":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","163":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","179":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","189":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","193":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","203":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","205":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","212":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","226":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","231":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","238":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","252":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","258":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","274":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","279":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","293":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA="},"packages/cli/src/workflows/publication/trigger-diff.ts":{"11":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","48":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE="},"packages/cli/src/workflows/publication/workflow-publication-applier.ts":{"78":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","117":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","145":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","190":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","197":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","228":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","275":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","299":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","306":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","327":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","340":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","345":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","361":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","369":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","376":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","395":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","405":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","406":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","415":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","425":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","441":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","462":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","475":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","489":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","519":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","529":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","562":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","572":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","585":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","590":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","591":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","612":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","616":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","629":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","661":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","666":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","704":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg=","719":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwg="},"packages/cli/src/workflows/publication/workflow-publication-lifecycle-lock.ts":{"35":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","39":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","44":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","53":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","62":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","71":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","72":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","78":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","89":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA="},"packages/cli/src/workflows/publication/workflow-publication-notifier.ts":{"13":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA=","26":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA=","33":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA=","46":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA="},"packages/cli/src/workflows/triggers/enabled-trigger-nodes.ts":{"12":"b:ABECAGAQgECJDwAEAAAAAEAAAAAAAEBK+wfAAQA=","28":"b:ABECAGAQgECJDwAEAAAAAEAAAAAAAEBK+wfAAQA="},"packages/cli/src/workflows/triggers/engine-v2-active-triggers.ts":{"37":[55,195,196,197,198,199,200,227],"43":[55,195,196,197,198,199,200,227],"60":[55,195,196,197,198,199,200,227]},"packages/cli/src/workflows/triggers/non-webhook-trigger-registrar.ts":{"51":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAQg=","65":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAQg=","66":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAQg=","73":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAQg=","80":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAQg=","123":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAQg=","146":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAQg=","175":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAQg=","189":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAQg=","197":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAQg=","225":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAQg=","231":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAQg="},"packages/cli/src/workflows/triggers/poll-backoff-policy.ts":{"28":[196],"35":[196],"38":[196],"41":[196],"60":[196],"74":[196],"114":[196]},"packages/cli/src/workflows/triggers/poll-backoff.service.ts":{"17":[196,219,197,198,200],"32":[196,219,197,198,200],"44":[196,219,197,198,200],"61":[196,219,197,198,200],"75":[196,219,197,198,200],"121":[196,219,197,198,200],"134":[196,219,197,198,200],"145":[196,219,197,198,200]},"packages/cli/src/workflows/triggers/poll-cursor.service.ts":{"17":[196,197,198,199,200],"21":[196,197,198,199,200],"42":[196,197,198,199,200],"51":[196,197,198,199,200],"56":[196,197,198,199,200],"78":[196,197,198,199,200],"102":[196,197,198,199,200],"122":[196,197,198,199,200],"146":[196,197,198,199,200],"155":[196,197,198,199,200],"157":[196,197,198,199,200],"192":[196,197,198,199,200],"199":[196,197,198,199,200]},"packages/cli/src/workflows/triggers/trigger-activation-retry.ts":{"10":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","22":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA="},"packages/cli/src/workflows/triggers/trigger-count.service.ts":{"13":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAQg=","14":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAQg=","17":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAQg=","27":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAQg="},"packages/cli/src/workflows/triggers/trigger-execution-context.factory.ts":{"55":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","84":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","112":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","117":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","122":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","132":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","148":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","160":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","169":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","172":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","187":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","203":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","204":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","217":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","236":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","255":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","272":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","275":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","279":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","313":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","326":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","344":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","362":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","372":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","389":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","437":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","442":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","448":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","468":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","492":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","502":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","526":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","559":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","572":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","606":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg=","623":"b:AAECAAAAgAABDAAAAAAAAEAAAAAAAEAC+AcBCQg="},"packages/cli/src/workflows/triggers/webhook-trigger-registrar.ts":{"20":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwA=","26":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwA=","47":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwA=","67":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwA=","76":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwA=","92":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwA=","104":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwA=","151":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwA=","161":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwA=","178":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwA=","192":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwA=","205":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwA=","212":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwA=","241":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwA=","258":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwA=","262":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfRAwA="},"packages/cli/src/workflows/triggers/workflow-trigger-activator.ts":{"71":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","79":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","80":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","144":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","171":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","185":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","197":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","198":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","220":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","241":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","245":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","268":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","278":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","292":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","321":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","337":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","416":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","446":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","455":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","461":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","471":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","486":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","516":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","523":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","548":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","560":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","581":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","587":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","608":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","619":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","641":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","653":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","677":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","700":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","714":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","715":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","724":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","765":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","814":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","834":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","841":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","851":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","869":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","883":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","889":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","918":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","925":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","934":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","965":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","970":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","973":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","976":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","977":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","981":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","982":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","993":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg=","1030":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfRAwg="},"packages/cli/src/workflows/workflow-mutation-hooks-proxy.service.ts":{"54":"b:ABECAGAQgViJDAAEAAAAAEAAAAAAAEBL+wfAAQA=","57":"b:ABECAGAQgViJDAAEAAAAAEAAAAAAAEBL+wfAAQA=","61":"b:ABECAGAQgViJDAAEAAAAAEAAAAAAAEBL+wfAAQA=","65":"b:ABECAGAQgViJDAAEAAAAAEAAAAAAAEBL+wfAAQA=","69":"b:ABECAGAQgViJDAAEAAAAAEAAAAAAAEBL+wfAAQA=","73":"b:ABECAGAQgViJDAAEAAAAAEAAAAAAAEBL+wfAAQA=","77":"b:ABECAGAQgViJDAAEAAAAAEAAAAAAAEBL+wfAAQA="},"packages/cli/src/workflows/workflow-publish-guard-proxy.service.ts":{"13":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA=","16":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA=","20":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQA="},"packages/cli/src/workflows/workflow-published-data.service.ts":{"22":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQg=","26":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQg=","39":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQg=","50":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQg=","64":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQg=","84":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQg=","93":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQg="},"packages/cli/src/workflows/workflow-publisher.service.ts":{"20":"b:AAAAAHAAgECJAAAEAAAAAEAAAAAAAAAI+wfQgQA=","54":"b:AAAAAHAAgECJAAAEAAAAAEAAAAAAAAAI+wfQgQA=","69":"b:AAAAAHAAgECJAAAEAAAAAEAAAAAAAAAI+wfQgQA="},"packages/cli/src/workflows/workflow-push-notifier.service.ts":{"10":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","15":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA="},"packages/core/src/execution-engine/active-workflow-triggers.ts":{"37":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","49":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","68":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","82":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","89":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","94":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","101":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","110":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","126":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","139":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","159":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","172":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","173":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","199":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","300":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","332":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","366":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","393":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","446":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","458":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","513":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","522":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","536":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","559":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","569":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","580":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","597":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg="},"packages/core/src/execution-engine/node-execution-context/poll-context.ts":{"21":[196,197,198,199,200],"25":[196,197,198,199,200],"32":[196,197,198,199,200],"42":[196,197,198,199,200],"43":[196,197,198,199,200],"46":[196,197,198,199,200],"51":[196,197,198,199,200],"65":[196,197,198,199,200],"70":[196,197,198,199,200],"74":[196,197,198,199,200],"79":[196,197,198,199,200]},"packages/core/src/execution-engine/poll-cursor-hooks.ts":{"8":[196,219,197,198,199,200],"14":[196,219,197,198,199,200]},"packages/core/src/execution-engine/poll-trigger-executor.ts":{"21":[196,197,198,199,200],"39":[196,197,198,199,200],"45":[196,197,198,199,200],"62":[196,197,198,199,200],"94":[196,197,198,199,200]},"packages/core/src/execution-engine/scheduled-task-manager.ts":{"34":"b:ABECBGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","40":"b:ABECBGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","48":"b:ABECBGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","57":"b:ABECBGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","67":"b:ABECBGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","107":"b:ABECBGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","110":"b:ABECBGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","151":"b:ABECBGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","175":"b:ABECBGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","180":"b:ABECBGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","188":"b:ABECBGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","201":"b:ABECBGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","228":"b:ABECBGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","233":"b:ABECBGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","237":"b:ABECBGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","243":"b:ABECBGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","247":"b:ABECBGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","255":"b:ABECBGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","270":"b:ABECBGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg=","288":"b:ABECBGAQgECJDAAEAAAAAEAAAAAAAEBL+wfBAQg="},"packages/core/src/execution-engine/workflow-active-triggers-state.ts":{"14":"b:AAEAAAAAgAABDAAAAAAAAEAAAAAAAEAD+AcBCQg=","20":"b:AAEAAAAAgAABDAAAAAAAAEAAAAAAAEAD+AcBCQg=","25":"b:AAEAAAAAgAABDAAAAAAAAEAAAAAAAEAD+AcBCQg=","30":"b:AAEAAAAAgAABDAAAAAAAAEAAAAAAAEAD+AcBCQg=","35":"b:AAEAAAAAgAABDAAAAAAAAEAAAAAAAEAD+AcBCQg=","43":"b:AAEAAAAAgAABDAAAAAAAAEAAAAAAAEAD+AcBCQg=","48":"b:AAEAAAAAgAABDAAAAAAAAEAAAAAAAEAD+AcBCQg=","52":"b:AAEAAAAAgAABDAAAAAAAAEAAAAAAAEAD+AcBCQg=","63":"b:AAEAAAAAgAABDAAAAAAAAEAAAAAAAEAD+AcBCQg=","68":"b:AAEAAAAAgAABDAAAAAAAAEAAAAAAAEAD+AcBCQg=","73":"b:AAEAAAAAgAABDAAAAAAAAEAAAAAAAEAD+AcBCQg=","78":"b:AAEAAAAAgAABDAAAAAAAAEAAAAAAAEAD+AcBCQg=","83":"b:AAEAAAAAgAABDAAAAAAAAEAAAAAAAEAD+AcBCQg=","88":"b:AAEAAAAAgAABDAAAAAAAAEAAAAAAAEAD+AcBCQg=","97":"b:AAEAAAAAgAABDAAAAAAAAEAAAAAAAEAD+AcBCQg="},"packages/core/src/observability/tracing/noop-tracing.ts":{"4":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","11":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","15":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","19":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","23":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","27":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","31":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","35":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","39":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","43":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","47":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","51":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","59":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","62":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA=","66":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfQAQA="},"packages/nodes-base/nodes/E2eTest/E2eTestPollingTrigger.node.ts":{"15":[196,197,198,199,200],"16":[196,197,198,199,200],"48":[196,197,198,199,200],"69":[196,197,198,199,200]},"packages/nodes-base/nodes/NoOp/NoOp.node.ts":{"33":"b:AAFAABgAgBEBAqYAAAAAAAACCAAABAIA+gcAAAg="},"packages/workflow/src/common/get-executable-nodes.ts":{"23":"b:ABECAGAQgECJDwAEAAAIAEAAAAAAAABK+wfAAQA="},"packages/workflow/src/common/get-runnable-nodes.ts":{"14":"b:ABUCAGAQgECJDwAEAAAAAEAAAAAAAEBK+wfAgQA=","40":"b:ABUCAGAQgECJDwAEAAAAAEAAAAAAAEBK+wfAgQA=","79":"b:ABUCAGAQgECJDwAEAAAAAEAAAAAAAEBK+wfAgQA=","87":"b:ABUCAGAQgECJDwAEAAAAAEAAAAAAAEBK+wfAgQA=","92":"b:ABUCAGAQgECJDwAEAAAAAEAAAAAAAEBK+wfAgQA="},"packages/workflow/src/cron.ts":{"52":[196,197,198,199,200],"80":[196,197,198,199,200]},"packages/workflow/src/errors/policy-refusal.ts":{"5":[41,112,6,196,71,221]},"packages/workflow/src/node-validation.ts":{"32":"b:ABECAGAQgECJDwAEAAAAAEAAAAAAAEBK+wfAAQA=","59":"b:ABECAGAQgECJDwAEAAAAAEAAAAAAAEBK+wfAAQA=","74":"b:ABECAGAQgECJDwAEAAAAAEAAAAAAAEBK+wfAAQA=","115":"b:ABECAGAQgECJDwAEAAAAAEAAAAAAAEBK+wfAAQA="},"packages/workflow/src/workflow-diff.ts":{"28":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","42":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","74":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","79":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","84":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","114":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","118":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","136":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","148":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","161":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","168":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","170":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","186":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","200":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","204":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","217":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","225":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","233":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","247":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","248":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","258":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","259":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","271":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","273":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","274":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","276":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","295":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","324":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","332":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","336":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","342":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","343":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","346":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","397":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","426":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE=","427":"b:ABECAGAQgECJDAAEAAAAAEAAAAAAAEBK+wfAAQE="},"packages/workflow/src/workflow-validation.ts":{"16":"b:ABECAGAQgECJDwAEAAAAAEAAAAAAAEBK+wfAAQA="},"packages/@n8n/db/src/repositories/tag.repository.ts":{"15":[61,148,169,79,86,183,186,187],"19":[61,148,169,79,86,183,186,187],"27":[61,148,169,79,86,183,186,187],"38":[61,148,169,79,86,183,186,187],"44":[61,148,169,79,86,183,186,187],"59":[61,148,169,79,86,183,186,187],"68":[61,148,169,79,86,183,186,187],"80":[61,148,169,79,86,183,186,187],"103":[61,148,169,79,86,183,186,187],"117":[61,148,169,79,86,183,186,187],"129":[61,148,169,79,86,183,186,187]},"packages/@n8n/errors/src/unexpected.error.ts":{"15":"b:CQQEEARACGAAoDBACAAAAAAAAABABAAAAAAQAAA="},"packages/cli/src/eventbus/event-message-classes/event-message-runner.ts":{"23":"b:CQQEEAQACGAAoDBAAAAAAAAAAABABAAAAAAQAAA=","31":"b:CQQEEAQACGAAoDBAAAAAAAAAAABABAAAAAAQAAA="},"packages/cli/src/task-runners/default-task-runner-disconnect-analyzer.ts":{"18":"b:CQQEEAQACGAAoDBAAAAAAAAAAABABAAAAAAQAAA=","22":"b:CQQEEAQACGAAoDBAAAAAAAAAAABABAAAAAAQAAA="},"packages/cli/src/task-runners/errors/task-runner-disconnected-error.ts":{"7":"b:CQQEEAQACGAAoDBAAAAAAAAAAABABAAAAAAQAAA=","27":"b:CQQEEAQACGAAoDBAAAAAAAAAAABABAAAAAAQAAA="},"packages/cli/src/task-runners/task-broker/errors/task-deferred.error.ts":{"4":"b:CQQEEAQACGAAoDBAAAAAAAAAAABABAAAAAAQAAA="},"packages/cli/src/task-runners/task-broker/task-broker.service.ts":{"135":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","152":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","158":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","174":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","175":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","184":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","185":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","204":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","212":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","214":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","217":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","218":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","226":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","228":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","238":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","241":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","247":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","266":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","268":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","269":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","272":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","278":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","282":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","286":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","290":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","294":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","348":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","367":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","376":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","385":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","394":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","411":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","428":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","445":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","482":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","499":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","511":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","527":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","538":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","551":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","562":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","574":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","587":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","608":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","617":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","628":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","667":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","679":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","691":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","696":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","703":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","761":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","776":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","782":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","824":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","837":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","868":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","874":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","875":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","876":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","910":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","928":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","932":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","933":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","936":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","950":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","958":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","973":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","977":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","984":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","998":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","1003":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","1007":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","1017":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","1029":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","1046":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","1061":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","1065":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","1069":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","1073":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","1077":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","1081":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","1085":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","1089":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","1093":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","1097":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","1101":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","1105":"b:CQQEEAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA="},"packages/cli/src/task-runners/task-managers/data-request-response-builder.ts":{"17":"b:CQQEEAQACGAAoDBAAAAAAAAAAABABAAAAAAQAAA=","37":"b:CQQEEAQACGAAoDBAAAAAAAAAAABABAAAAAAQAAA=","57":"b:CQQEEAQACGAAoDBAAAAAAAAAAABABAAAAAAQAAA=","70":"b:CQQEEAQACGAAoDBAAAAAAAAAAABABAAAAAAQAAA="},"packages/cli/src/task-runners/task-managers/data-request-response-stripper.ts":{"18":"b:CQQEEAQAGGAAoDBAAAAAAAAAAABABAAAAAAQAAA=","32":"b:CQQEEAQAGGAAoDBAAAAAAAAAAABABAAAAAAQAAA=","43":"b:CQQEEAQAGGAAoDBAAAAAAAAAAABABAAAAAAQAAA=","64":"b:CQQEEAQAGGAAoDBAAAAAAAAAAABABAAAAAAQAAA=","68":"b:CQQEEAQAGGAAoDBAAAAAAAAAAABABAAAAAAQAAA=","72":"b:CQQEEAQAGGAAoDBAAAAAAAAAAABABAAAAAAQAAA=","86":"b:CQQEEAQAGGAAoDBAAAAAAAAAAABABAAAAAAQAAA=","94":"b:CQQEEAQAGGAAoDBAAAAAAAAAAABABAAAAAAQAAA=","118":"b:CQQEEAQAGGAAoDBAAAAAAAAAAABABAAAAAAQAAA=","138":"b:CQQEEAQAGGAAoDBAAAAAAAAAAABABAAAAAAQAAA="},"packages/cli/src/task-runners/task-managers/local-task-requester.ts":{"18":"b:CQQEEAQACGAAoDBAAAAAAAAAAABABAAAAAAQAAA=","29":"b:CQQEEAQACGAAoDBAAAAAAAAAAABABAAAAAAQAAA=","35":"b:CQQEEAQACGAAoDBAAAAAAAAAAABABAAAAAAQAAA=","36":"b:CQQEEAQACGAAoDBAAAAAAAAAAABABAAAAAAQAAA="},"packages/cli/src/task-runners/task-managers/task-requester.ts":{"73":"b:CQQEFAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","81":"b:CQQEFAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","85":"b:CQQEFAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","90":"b:CQQEFAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","138":"b:CQQEFAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","175":"b:CQQEFAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","199":"b:CQQEFAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","221":"b:CQQEFAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","227":"b:CQQEFAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","231":"b:CQQEFAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","250":"b:CQQEFAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","262":"b:CQQEFAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","264":"b:CQQEFAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","290":"b:CQQEFAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","304":"b:CQQEFAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","331":"b:CQQEFAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","339":"b:CQQEFAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","347":"b:CQQEFAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","355":"b:CQQEFAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","381":"b:CQQEFAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA=","396":"b:CQQEFAQACGAAoDBAAAAAABAgAABABAAMAAAQIAA="},"packages/core/src/execution-engine/node-execution-context/utils/normalize-items.ts":{"10":"b:CQAEEAQACGAAoDBAAAAAAAgAAABABAEAAAAQAAA=","17":"b:CQAEEAQACGAAoDBAAAAAAAgAAABABAEAAAAQAAA=","20":"b:CQAEEAQACGAAoDBAAAAAAAgAAABABAEAAAAQAAA=","24":"b:CQAEEAQACGAAoDBAAAAAAAgAAABABAEAAAAQAAA=","26":"b:CQAEEAQACGAAoDBAAAAAAAgAAABABAEAAAAQAAA=","27":"b:CQAEEAQACGAAoDBAAAAAAAgAAABABAEAAAAQAAA=","40":"b:CQAEEAQACGAAoDBAAAAAAAgAAABABAEAAAAQAAA=","44":"b:CQAEEAQACGAAoDBAAAAAAAgAAABABAEAAAAQAAA="},"packages/nodes-base/nodes/Code/Code.node.ts":{"24":"b:CQAEGAQACGAAsjBCAAAAAAAAAABABQAAAAAQAAA=","196":"b:CQAEGAQACGAAsjBCAAAAAAAAAABABQAAAAAQAAA="},"packages/nodes-base/nodes/Code/python-runner-unavailable.error.ts":{"11":"b:CQAEGAQACGAAsjBCAAAAAAAAAAAABQAAAAAAAAA="},"localhost-37425/assets/index-Dv_brJ4-.js":{"3":[79]},"localhost-37425/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[79],"9":[79],"10":[79],"19":[79],"23":[79],"29":[79],"33":[79],"34":[79]},"packages/@n8n/api-types/src/dto/executions/compare-execution-list-items.ts":{"3":[46,169,79,18,186,187,188],"26":[46,169,79,18,186,187,188]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/code.svg":{"11":"b:CQAEGAACAGAAsnBCAAAAABggGABlBwEcAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/composables/useAddExecutionToDataset.ts":{"15":[62,169,170,79,18,186,187,188]},"packages/frontend/editor-ui/src/features/execution/executions/components/workflow/ExecutionPreviewHost.vue":{"18":[62,169,170,79,18,186,187,188],"33":[62,169,170,79,18,186,187,188],"36":[62,169,170,79,18,186,187,188],"44":[62,169,170,79,18,186,187,188],"56":[62,169,170,79,18,186,187,188],"57":[62,169,170,79,18,186,187,188],"58":[62,169,170,79,18,186,187,188],"60":[62,169,170,79,18,186,187,188],"71":[62,169,170,79,18,186,187,188],"110":[62,169,170,79,18,186,187,188],"111":[62,169,170,79,18,186,187,188],"113":[169,170,187,188],"116":[62,169,170,79,18,186,187,188]},"packages/frontend/editor-ui/src/features/execution/executions/components/workflow/WorkflowExecutionsCard.vue":{"41":[62,169,170,79,18,186,187,188],"44":[62,169,170,79,18,186,187,188],"48":[62,169,170,79,18,186,187,188],"49":[169,186,187],"61":[62,169,170,79,18,186,187,188],"64":[62,169,170,79,18,186,187,188],"65":[62,169,170,79,18,186,187,188],"67":[62,169,170,79,18,186,187,188],"73":[62,169,170,79,18,186,187,188],"108":[62,169,170,79,18,186,187,188],"141":[62,169,170,79,18,186,187,188],"193":[62,169,170,79,18,186,187,188]},"packages/frontend/editor-ui/src/features/execution/executions/components/workflow/WorkflowExecutionsPreview.vue":{"55":[62,169,170,79,18,186,187,188],"59":[62,169,170,79,18,186,187,188],"63":[62,169,170,79,18,186,187,188],"64":[62,169,170,79,18,186,187,188],"65":[62,169,170,79,18,186,187,188],"68":[62,169,170,79,18,186,187,188],"79":[62,169,170,79,18,186,187,188],"85":[62,169,170,79,18,186,187,188],"93":[62,169,170,79,18,186,187,188],"102":[62,169,170,79,18,186,187,188],"126":[62,169,170,79,18,186,187,188],"130":[170],"141":[62,169,170,79,18,186,187,188],"147":[62,169,170,79,18,186,187,188],"157":[62,169,170,79,18,186,187,188],"169":[62,169,170,79,18,186,187,188],"191":[62,169,170,79,18,186,187,188],"197":[62,169,170,79,18,186,187,188],"199":[62,169,170,79,18,186,187,188],"226":[170],"317":[62,169,170,79,18,186,187,188],"337":[62,169,170,79,18,186,187,188],"368":[62,169,170,79,18,186,187,188],"380":[62,169,170,79,18,186,187,188],"415":[62,169,170,79,18,186,187,188],"430":[62,169,170,79,18,186,187,188],"433":[169],"459":[169,186],"462":[169,186],"465":[169,186]},"packages/frontend/editor-ui/src/features/execution/executions/composables/useExecutionPreviewDocument.ts":{"59":[62,169,170,79,18,186,187,188],"106":[62,169,170,79,18,186,187,188],"118":[62,169,170,79,18,186,187,188],"147":[62,169,170,79,18,186,187,188],"175":[169,186,187],"187":[169],"193":[62,169,170,79,18,186,187,188],"232":[187],"233":[187],"323":[62,169,170,79,18,186,187,188],"339":[169,170,187,188]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/background/CanvasBackgroundStripedPattern.vue":{"14":"b:AABMgAJAB0AAgAABAAMAAAAAAAACBwCdAAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/parts/CanvasNodeDisabledStrikeThrough.vue":{"6":[46,75,76,162,165,169,79,18,185,186,187,188],"10":[46,75,76,162,165,169,79,18,185,186,187,188],"19":[46,75,76,162,165,169,79,18,185,186,187,188]},"packages/cli/src/modules/external-secrets.ee/external-secrets-manager.ee.ts":{"34":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","55":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","58":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","75":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","85":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","89":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","97":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","101":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","105":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","112":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","118":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","131":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","158":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","182":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","186":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","190":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","194":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","202":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","213":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","225":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","276":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","285":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","294":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","329":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","343":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","361":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","369":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","373":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","392":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA="},"packages/cli/src/modules/external-secrets.ee/external-secrets-refresh.task.ts":{"24":"b:AAAAAAAAAAQgQBIAAAAEAoABQAAkUoFAAAAAAAA=","31":"b:AAAAAAAAAAQgQBIAAAAEAoABQAAkUoFAAAAAAAA="},"packages/cli/src/modules/external-secrets.ee/secrets-cache.service.ts":{"25":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","38":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","41":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","46":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","50":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","51":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","54":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","63":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","91":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","94":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","95":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","107":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","115":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","123":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA=","131":"b:AAAAAAAAAAQiQBIAAAAEAoABQAAkUoFAAAAGAAA="},"packages/cli/src/modules/instance-registry/checks/check.service.ts":{"44":"b:AAIGAAAARFQAEBIAEACMkAAFAQHkBAAAAAAAAAA=","54":"b:AAIGAAAARFQAEBIAEACMkAAFAQHkBAAAAAAAAAA=","58":"b:AAIGAAAARFQAEBIAEACMkAAFAQHkBAAAAAAAAAA=","73":"b:AAIGAAAARFQAEBIAEACMkAAFAQHkBAAAAAAAAAA=","84":"b:AAIGAAAARFQAEBIAEACMkAAFAQHkBAAAAAAAAAA=","94":"b:AAIGAAAARFQAEBIAEACMkAAFAQHkBAAAAAAAAAA=","99":"b:AAIGAAAARFQAEBIAEACMkAAFAQHkBAAAAAAAAAA=","106":"b:AAIGAAAARFQAEBIAEACMkAAFAQHkBAAAAAAAAAA=","138":"b:AAIGAAAARFQAEBIAEACMkAAFAQHkBAAAAAAAAAA=","156":"b:AAIGAAAARFQAEBIAEACMkAAFAQHkBAAAAAAAAAA=","170":"b:AAIGAAAARFQAEBIAEACMkAAFAQHkBAAAAAAAAAA=","181":"b:AAIGAAAARFQAEBIAEACMkAAFAQHkBAAAAAAAAAA=","187":"b:AAIGAAAARFQAEBIAEACMkAAFAQHkBAAAAAAAAAA=","196":"b:AAIGAAAARFQAEBIAEACMkAAFAQHkBAAAAAAAAAA=","219":"b:AAIGAAAARFQAEBIAEACMkAAFAQHkBAAAAAAAAAA=","243":"b:AAIGAAAARFQAEBIAEACMkAAFAQHkBAAAAAAAAAA="},"packages/nodes-base/nodes/HackerNews/GenericFunctions.ts":{"16":[13,172,81,180],"42":[13,172,81,180]},"packages/nodes-base/nodes/HackerNews/HackerNews.node.ts":{"264":[13,172,81,180]},"packages/frontend/editor-ui/src/app/utils/telemetryUtils.ts":{"5":[46,65,81,82,173,83,174,16,178,179],"13":[46,65,81,82,173,83,174,16,179],"14":[46,65,81,82,173,83,174,179],"21":[46,65,81,82,173,83,174,179],"27":[46,81,173,179],"28":[46,81,173,179],"71":[46,65,81,82,173,83,174,179],"78":[46],"79":[46]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FixedCollection/FixedCollectionParameter.vue":{"39":[90,103,54,56,81,82,83,16]},"packages/@n8n/db/src/entities/webhook-entity.ts":{"33":"b:ABACAGAQAECIAAAEAAAAAEAAAAAAAABKAwDQAQA=","39":"b:ABACAGAQAECIAAAEAAAAAEAAAAAAAABKAwDQAQA=","43":"b:ABACAGAQAECIAAAEAAAAAEAAAAAAAABKAwDQAQA=","44":"b:ABACAGAQAECIAAAEAAAAAEAAAAAAAABKAwDQAQA=","50":"b:ABACAGAQAECIAAAEAAAAAEAAAAAAAABKAwDQAQA=","51":"b:ABACAGAQAECIAAAEAAAAAEAAAAAAAABKAwDQAQA=","54":"b:ABACAGAQAECIAAAEAAAAAEAAAAAAAABKAwDQAQA="},"packages/@n8n/errors/src/response-errors/not-found.error.ts":{"4":"b:ABACAyAAAFiIAQAEAAMCAEAAAAAAAAAAAwDgAQA=","14":"b:ABACAyAAAFiIAQAEAAMCAEAAAAAAAAAAAwDgAQA="},"packages/@n8n/errors/src/response-errors/response.error.ts":{"19":"b:ABF4ByAAAkCIAAAUGAMBAEAAgAAAAAACA4DAAQA="},"packages/@n8n/expression-runtime/src/evaluator/error-classification.ts":{"5":[46,176,216]},"packages/cli/src/errors/response-errors/webhook-not-found.error.ts":{"3":[214,192,90,37,193,215,12,134,62,67,71,216],"36":[214,192,90,37,193,215,12,134,62,67,71,216]},"packages/cli/src/executions/execution.utils.ts":{"13":"b:AAAEBAAAQAAAAAAEAAAAAEAAAAAAAGAIAAAIoQA=","26":"b:AAAEBAAAQAAAAAAEAAAAAEAAAAAAAGAIAAAIoQA="},"packages/cli/src/executions/pre-execution-checks/subworkflow-policy-checker.ts":{"18":[26,221,181,182,216],"29":[26,221,181,182,216],"68":[26,221,181,182,216],"97":[26,221,181,182,216],"115":[26,221,181,182,216],"124":[26,221,181,182,216],"142":[26,221,181,182,216],"146":[26,221,181,182,216],"147":[26,221,181,182,216],"158":[26,221,181,182,216]},"packages/cli/src/modules/otel/otel.service.ts":{"43":[26,176,216],"55":[26,176,216],"62":[26,176,216],"67":[26,176,216],"73":[26,176,216],"87":[26,176,216],"96":[26,176,216],"98":[26,176,216],"99":[26,176,216],"100":[26,176,216],"107":[26,176,216],"108":[26,176,216],"126":[26,176,216],"127":[26,176,216],"134":[26,176,216],"152":[26,176,216],"166":[26,176,216],"178":[26,176,216],"187":[26,176,216],"210":[26,176,216],"219":[26,176,216],"230":[26,176,216],"240":[26,176,216],"259":[26,176,216],"267":[26,176,216],"276":[26,176,216],"289":[26,176,216],"316":[26,176,216],"320":[26,176,216],"321":[26,176,216],"322":[26,176,216],"323":[26,176,216],"324":[26,176,216],"331":[26,176,216],"336":[26,176,216],"360":[26,176,216],"369":[26,176,216],"379":[26,176,216],"380":[26,176,216]},"packages/cli/src/utils/cors.util.ts":{"3":[26,90,211,54,134,18,216,223,187]},"packages/cli/src/webhooks/live-webhooks.ts":{"44":"b:ABAAAGAAAECIAAAEAAAAAEAAAAAAAAAIAwDYAQA=","56":"b:ABAAAGAAAECIAAAEAAAAAEAAAAAAAAAIAwDYAQA=","60":"b:ABAAAGAAAECIAAAEAAAAAEAAAAAAAAAIAwDYAQA=","68":"b:ABAAAGAAAECIAAAEAAAAAEAAAAAAAAAIAwDYAQA=","73":"b:ABAAAGAAAECIAAAEAAAAAEAAAAAAAAAIAwDYAQA=","88":"b:ABAAAGAAAECIAAAEAAAAAEAAAAAAAAAIAwDYAQA=","109":"b:ABAAAGAAAECIAAAEAAAAAEAAAAAAAAAIAwDYAQA=","137":"b:ABAAAGAAAECIAAAEAAAAAEAAAAAAAAAIAwDYAQA=","160":"b:ABAAAGAAAECIAAAEAAAAAEAAAAAAAAAIAwDYAQA=","184":"b:ABAAAGAAAECIAAAEAAAAAEAAAAAAAAAIAwDYAQA=","197":"b:ABAAAGAAAECIAAAEAAAAAEAAAAAAAAAIAwDYAQA=","223":"b:ABAAAGAAAECIAAAEAAAAAEAAAAAAAAAIAwDYAQA=","243":"b:ABAAAGAAAECIAAAEAAAAAEAAAAAAAAAIAwDYAQA=","255":"b:ABAAAGAAAECIAAAEAAAAAEAAAAAAAAAIAwDYAQA=","269":"b:ABAAAGAAAECIAAAEAAAAAEAAAAAAAAAIAwDYAQA=","285":"b:ABAAAGAAAECIAAAEAAAAAEAAAAAAAAAIAwDYAQA="},"packages/cli/src/webhooks/waiting-webhooks.ts":{"47":[26,90,103,211,54,134,18,216,223,187],"59":[26,90,103,211,54,134,18,216,223,187],"67":[26,90,103,211,54,134,18,216,223,187],"71":[26,90,103,211,54,134,18,216,223,187],"75":[26,90,103,211,54,134,18,216,223,187],"79":[26,90,103,211,54,134,18,216,223,187],"89":[26,90,103,211,54,134,18,216,223,187],"102":[26,90,103,211,54,134,18,216,223,187],"108":[26,90,103,211,54,134,18,216,223,187],"127":[26,90,103,211,54,134,18,216,223,187],"140":[26,90,103,211,54,134,18,216,223,187],"153":[26,90,103,211,54,134,18,216,223,187],"164":[26,90,103,211,54,134,18,216,223,187],"190":[26,90,103,211,54,134,18,216,223,187],"211":[26,90,103,211,54,134,18,216,223,187],"236":[26,90,103,211,54,134,18,216,223,187],"244":[26,90,103,211,54,134,18,216,223,187],"340":[26,90,103,211,54,134,18,216,223,187],"353":[26,90,103,211,54,134,18,216,223,187],"404":[26,90,103,211,54,134,18,216,223,187],"431":[26,90,103,211,54,134,18,216,223,187],"434":[26,90,103,211,54,134,18,216,223,187],"447":[26,90,103,211,54,134,18,216,223,187]},"packages/cli/src/webhooks/webhook-on-received-response-extractor.ts":{"13":"b:AAAEBGAQQEGIAAAEAAAAAEAAAAAAAAAAAQCQAQA="},"packages/cli/src/webhooks/webhook-request-sanitizer.ts":{"48":"b:ABAEBGAQAEGIAAAEAAAAAEAAAAAAAAIAAwDQAQA=","54":"b:ABAEBGAQAEGIAAAEAAAAAEAAAAAAAAIAAwDQAQA=","60":"b:ABAEBGAQAEGIAAAEAAAAAEAAAAAAAAIAAwDQAQA=","61":"b:ABAEBGAQAEGIAAAEAAAAAEAAAAAAAAIAAwDQAQA=","74":"b:ABAEBGAQAEGIAAAEAAAAAEAAAAAAAAIAAwDQAQA=","82":"b:ABAEBGAQAEGIAAAEAAAAAEAAAAAAAAIAAwDQAQA="},"packages/core/src/binary-data/binary-data.service.ts":{"26":"b:EQACAAQAAAEAAAAAAAAAABAAAAAABGAAAABQIQA=","32":"b:EQACAAQAAAEAAAAAAAAAABAAAAAABGAAAABQIQA=","36":"b:EQACAAQAAAEAAAAAAAAAABAAAAAABGAAAABQIQA=","43":"b:EQACAAQAAAEAAAAAAAAAABAAAAAABGAAAABQIQA=","52":"b:EQACAAQAAAEAAAAAAAAAABAAAAAABGAAAABQIQA=","65":"b:EQACAAQAAAEAAAAAAAAAABAAAAAABGAAAABQIQA=","71":"b:EQACAAQAAAEAAAAAAAAAABAAAAAABGAAAABQIQA=","102":"b:EQACAAQAAAEAAAAAAAAAABAAAAAABGAAAABQIQA=","133":"b:EQACAAQAAAEAAAAAAAAAABAAAAAABGAAAABQIQA=","139":"b:EQACAAQAAAEAAAAAAAAAABAAAAAABGAAAABQIQA=","149":"b:EQACAAQAAAEAAAAAAAAAABAAAAAABGAAAABQIQA=","155":"b:EQACAAQAAAEAAAAAAAAAABAAAAAABGAAAABQIQA=","161":"b:EQACAAQAAAEAAAAAAAAAABAAAAAABGAAAABQIQA=","169":"b:EQACAAQAAAEAAAAAAAAAABAAAAAABGAAAABQIQA=","198":"b:EQACAAQAAAEAAAAAAAAAABAAAAAABGAAAABQIQA=","204":"b:EQACAAQAAAEAAAAAAAAAABAAAAAABGAAAABQIQA=","207":"b:EQACAAQAAAEAAAAAAAAAABAAAAAABGAAAABQIQA=","227":"b:EQACAAQAAAEAAAAAAAAAABAAAAAABGAAAABQIQA=","239":"b:EQACAAQAAAEAAAAAAAAAABAAAAAABGAAAABQIQA=","243":"b:EQACAAQAAAEAAAAAAAAAABAAAAAABGAAAABQIQA=","251":"b:EQACAAQAAAEAAAAAAAAAABAAAAAABGAAAABQIQA=","263":"b:EQACAAQAAAEAAAAAAAAAABAAAAAABGAAAABQIQA=","269":"b:EQACAAQAAAEAAAAAAAAAABAAAAAABGAAAABQIQA=","270":"b:EQACAAQAAAEAAAAAAAAAABAAAAAABGAAAABQIQA=","283":"b:EQACAAQAAAEAAAAAAAAAABAAAAAABGAAAABQIQA="},"packages/core/src/binary-data/utils.ts":{"3":[34,4,221,181,182,216],"13":[34,4,221,181,182,216],"18":[34,4,221,181,182,216],"28":[34,4,221,181,182,216]},"packages/core/src/execution-engine/node-execution-context/utils/extract-value.ts":{"21":[35,131,134,170,18,84,16,178,216],"40":[35,131,134,170,18,84,16,178,216],"61":[35,131,134,170,18,84,16,178,216],"69":[35,131,134,170,18,84,16,178,216],"78":[35,131,134,170,18,84,16,178,216],"111":[35,131,134,170,18,84,16,178,216],"131":[35,131,134,170,18,84,16,178,216],"165":[35,131,134,170,18,84,16,178,216]},"packages/core/src/execution-engine/node-execution-context/utils/webhook-helper-functions.ts":{"13":"b:AAAEBGAQAEGIAAAEAAAIAEAAAAAAAAKAAwDQAQA=","33":"b:AAAEBGAQAEGIAAAEAAAIAEAAAAAAAAKAAwDQAQA="},"packages/nodes-base/nodes/ExecuteWorkflow/ExecuteWorkflow/ExecuteWorkflow.node.ts":{"22":[60,221,181,182,216,87],"365":[60,221,181,182,216,87]},"packages/nodes-base/nodes/ExecuteWorkflow/ExecuteWorkflow/GenericFunctions.ts":{"10":[60,221,181,182,216,87],"29":[60,221,181,182,216,87]},"packages/nodes-base/nodes/ExecuteWorkflow/ExecuteWorkflow/methods/localResourceMapping.ts":{"5":[60,221,181,182,216,87]},"packages/nodes-base/nodes/ExecuteWorkflow/ExecuteWorkflowTrigger/ExecuteWorkflowTrigger.node.ts":{"223":[25,26,60,221,181,182,216,87],"229":[25,26,60,221,181,182,216,87],"248":[25,26,60,221,181,182,216,87],"249":[25,26,60,221,181,182,216,87],"251":[25,26,60,221,181,182,216,87],"254":[25,26,60,221,181,182,216,87]},"packages/nodes-base/nodes/Filter/Filter.node.ts":{"8":[137,170,216]},"packages/nodes-base/nodes/Filter/V1/FilterV1.node.ts":{"17":[137,170,216],"310":[137,170,216]},"packages/nodes-base/nodes/Filter/V1/GenericFunctions.ts":{"5":[137,170,216],"8":[137,170,216],"10":[137,170,216],"18":[137,170,216],"19":[137,170,216],"20":[137,170,216],"22":[137,170,216],"24":[137,170,216],"26":[137,170,216],"28":[137,170,216],"29":[137,170,216],"30":[137,170,216],"31":[137,170,216],"33":[137,170,216],"35":[137,170,216],"37":[137,170,216],"39":[137,170,216],"41":[137,170,216],"47":[137,170,216],"56":[137,170,216],"61":[137,170,216]},"packages/nodes-base/nodes/Filter/V2/FilterV2.node.ts":{"20":[137,170,216],"95":[137,170,216],"99":[137,170,216]},"packages/nodes-base/nodes/If/If.node.ts":{"8":[35,21,131,78,168,170,18,84,85,216]},"packages/nodes-base/nodes/If/V1/IfV1.node.ts":{"18":[35,21,131,78,168,170,18,175,84,85,216],"26":[35,21,131,78,168,170,18,175,84,85,216],"320":[35,21,131,78,168,170,18,175,84,85,216],"329":[35,21,131,78,168,170,18,175,84,85,216],"331":[35,21,131,78,168,170,18,175,84,85,216],"337":[35,21,131,78,168,170,18,175,84,85,216],"339":[35,21,131,78,168,170,18,175,84,85,216],"341":[35,21,131,78,168,170,18,175,84,85,216],"343":[35,21,131,78,168,170,18,175,84,85,216],"345":[35,21,131,78,168,170,18,175,84,85,216],"347":[35,21,131,78,168,170,18,175,84,85,216],"349":[35,21,131,78,168,170,18,175,84,85,216],"350":[35,21,131,78,168,170,18,175,84,85,216],"351":[35,21,131,78,168,170,18,175,84,85,216],"353":[35,21,131,78,168,170,18,175,84,85,216],"355":[35,21,131,78,168,170,18,175,84,85,216],"357":[35,21,131,78,168,170,18,175,84,85,216],"359":[35,21,131,78,168,170,18,175,84,85,216],"361":[35,21,131,78,168,170,18,175,84,85,216],"363":[35,21,131,78,168,170,18,175,84,85,216],"369":[35,21,131,78,168,170,18,175,84,85,216],"378":[35,21,131,78,168,170,18,175,84,85,216],"383":[35,21,131,78,168,170,18,175,84,85,216]},"packages/nodes-base/nodes/If/V2/IfV2.node.ts":{"20":[35,21,131,78,168,170,18,84,85,216],"95":[35,21,131,78,168,170,18,84,85,216],"99":[35,21,131,78,168,170,18,84,85,216]},"packages/nodes-base/nodes/If/V2/utils.ts":{"3":"b:AAAkAAgAAAAAYDQAAAAAAAgCAAAABQAAAAAAAQA=","7":"b:AAAkAAgAAAAAYDQAAAAAAAgCAAAABQAAAAAAAQA=","8":"b:AAAkAAgAAAAAYDQAAAAAAAgCAAAABQAAAAAAAQA="},"packages/nodes-base/nodes/Switch/Switch.node.ts":{"9":[77,82,84,85,216]},"packages/nodes-base/nodes/Switch/V1/SwitchV1.node.ts":{"17":[77,82,84,85,216],"25":[77,82,84,85,216],"533":[77,82,84,85,216],"548":[77,82,84,85,216],"550":[77,82,84,85,216],"552":[77,82,84,85,216],"554":[77,82,84,85,216],"556":[77,82,84,85,216],"558":[77,82,84,85,216],"560":[77,82,84,85,216],"561":[77,82,84,85,216],"562":[77,82,84,85,216],"564":[77,82,84,85,216],"566":[77,82,84,85,216],"568":[77,82,84,85,216],"570":[77,82,84,85,216],"572":[77,82,84,85,216],"575":[77,82,84,85,216],"580":[77,82,84,85,216],"601":[77,82,84,85,216]},"packages/nodes-base/nodes/Switch/V2/SwitchV2.node.ts":{"19":[77,82,84,85,216],"27":[77,82,84,85,216],"531":[77,82,84,85,216],"533":[77,82,84,85,216],"548":[77,82,84,85,216],"563":[77,82,84,85,216],"565":[77,82,84,85,216],"567":[77,82,84,85,216],"569":[77,82,84,85,216],"571":[77,82,84,85,216],"573":[77,82,84,85,216],"575":[77,82,84,85,216],"576":[77,82,84,85,216],"577":[77,82,84,85,216],"579":[77,82,84,85,216],"581":[77,82,84,85,216],"583":[77,82,84,85,216],"585":[77,82,84,85,216],"587":[77,82,84,85,216],"590":[77,82,84,85,216],"595":[77,82,84,85,216],"616":[77,82,84,85,216],"637":[77,82,84,85,216],"647":[77,82,84,85,216]},"packages/nodes-base/nodes/Switch/V3/SwitchV3.node.ts":{"21":[77,82,84,85,216],"25":[77,82,84,85,216],"31":[77,82,84,85,216],"51":[77,82,84,85,216],"347":[77,82,84,85,216],"377":[77,82,84,85,216],"383":[77,82,84,85,216],"409":[77,82,84,85,216],"422":[77,82,84,85,216]},"packages/nodes-base/nodes/Transform/SplitOut/SplitOut.node.ts":{"134":[216],"144":[216],"152":[216],"153":[216],"175":[216],"188":[216],"190":[216],"208":[216]},"packages/nodes-base/nodes/Transform/SplitOut/utils.ts":{"8":[216],"14":[216],"20":[216]},"packages/nodes-base/nodes/Transform/utils/utils.ts":{"8":[216],"18":[216],"22":[216],"23":[216]},"packages/nodes-base/nodes/Wait/Wait.node.ts":{"229":[26,90,36,50,137,170,18,216,223,185,187],"501":[26,90,36,50,137,170,18,216,223,185,187],"507":[26,90,36,50,137,170,18,216,223,185,187],"522":[26,90,36,50,137,170,18,216,223,185,187],"598":[26,90,36,50,137,170,18,216,223,185,187],"630":[26,90,36,50,137,170,18,216,223,185,187]},"packages/nodes-base/nodes/Wait/validation.ts":{"1":[26,90,36,50,137,170,18,216,223,185],"6":[26,90,36,50,137,170,18,216,223,185]},"packages/nodes-base/nodes/Webhook/Webhook.node.ts":{"213":"b:AAAEBHAQBEGIAAAEgAAAAEAAAAAAAAJCAwDQAQA=","225":"b:AAAEBHAQBEGIAAAEgAAAAEAAAAAAAAJCAwDQAQA=","367":"b:AAAEBHAQBEGIAAAEgAAAAEAAAAAAAAJCAwDQAQA=","371":"b:AAAEBHAQBEGIAAAEgAAAAEAAAAAAAAJCAwDQAQA="},"packages/nodes-base/nodes/Webhook/description.ts":{"58":"b:AAAEBHAQBEGIAAAEAAAAAEAAAAAAAAJCAwDAAQA=","95":"b:AAAEBHAQBEGIAAAEAAAAAEAAAAAAAAJCAwDAAQA=","138":"b:AAAEBHAQBEGIAAAEAAAAAEAAAAAAAAJCAwDAAQA="},"packages/nodes-base/nodes/Webhook/utils.ts":{"38":"b:ABIFpHAQZkGIACAGAAAIAEAAAAAAAAJAAwDQQQA=","55":"b:ABIFpHAQZkGIACAGAAAIAEAAAAAAAAJAAwDQQQA=","69":"b:ABIFpHAQZkGIACAGAAAIAEAAAAAAAAJAAwDQQQA=","80":"b:ABIFpHAQZkGIACAGAAAIAEAAAAAAAAJAAwDQQQA=","90":"b:ABIFpHAQZkGIACAGAAAIAEAAAAAAAAJAAwDQQQA=","107":"b:ABIFpHAQZkGIACAGAAAIAEAAAAAAAAJAAwDQQQA=","118":"b:ABIFpHAQZkGIACAGAAAIAEAAAAAAAAJAAwDQQQA=","120":"b:ABIFpHAQZkGIACAGAAAIAEAAAAAAAAJAAwDQQQA=","131":"b:ABIFpHAQZkGIACAGAAAIAEAAAAAAAAJAAwDQQQA=","141":"b:ABIFpHAQZkGIACAGAAAIAEAAAAAAAAJAAwDQQQA=","156":"b:ABIFpHAQZkGIACAGAAAIAEAAAAAAAAJAAwDQQQA=","167":"b:ABIFpHAQZkGIACAGAAAIAEAAAAAAAAJAAwDQQQA=","205":"b:ABIFpHAQZkGIACAGAAAIAEAAAAAAAAJAAwDQQQA=","210":"b:ABIFpHAQZkGIACAGAAAIAEAAAAAAAAJAAwDQQQA=","228":"b:ABIFpHAQZkGIACAGAAAIAEAAAAAAAAJAAwDQQQA=","229":"b:ABIFpHAQZkGIACAGAAAIAEAAAAAAAAJAAwDQQQA=","233":"b:ABIFpHAQZkGIACAGAAAIAEAAAAAAAAJAAwDQQQA=","242":"b:ABIFpHAQZkGIACAGAAAIAEAAAAAAAAJAAwDQQQA=","258":"b:ABIFpHAQZkGIACAGAAAIAEAAAAAAAAJAAwDQQQA=","393":"b:ABIFpHAQZkGIACAGAAAIAEAAAAAAAAJAAwDQQQA=","458":"b:ABIFpHAQZkGIACAGAAAIAEAAAAAAAAJAAwDQQQA=","476":"b:ABIFpHAQZkGIACAGAAAIAEAAAAAAAAJAAwDQQQA="},"packages/nodes-base/utils/workflow-backtracking.ts":{"24":[60,221,181,182,216,224,87],"44":[60,221,181,182,216,224,87]},"packages/nodes-base/utils/workflowInputsResourceMapping/GenericFunctions.ts":{"27":[25,26,60,221,181,182,216,87],"29":[25,26,60,221,181,182,216,87],"74":[25,26,60,221,181,182,216,87],"81":[25,26,60,221,181,182,216,87],"121":[25,26,60,221,181,182,216,87],"126":[25,26,60,221,181,182,216,87],"147":[25,26,60,221,181,182,216,87],"155":[25,26,60,221,181,182,216,87],"157":[25,26,60,221,181,182,216,87],"160":[25,26,60,221,181,182,216,87],"168":[25,26,60,221,181,182,216,87],"183":[25,26,60,221,181,182,216,87]},"packages/workflow/src/errors/expression.error.ts":{"33":[27,176,216],"57":[27,176,216]},"packages/workflow/src/node-parameters/filter-parameter.ts":{"28":[35,131,170,18,84,216],"36":[35,131,170,18,84,216],"70":[35,131,170,18,84,216],"75":[35,131,170,18,84,216],"110":[35,131,170,18,84,216],"122":[35,131,170,18,84,216],"128":[35,131,170,18,84,216],"200":[35,131,170,18,84,216],"202":[35,131,170,18,84,216],"219":[35,131,170,18,84,216],"237":[35,131,170,18,84,216],"250":[35,131,170,18,84,216],"276":[35,131,170,18,84,216],"451":[35,131,170,18,84,216],"460":[35,131,170,18,84,216],"468":[35,131,170,18,84,216],"481":[35,131,170,18,84,216],"520":[35,131,170,18,84,216],"524":[35,131,170,18,84,216],"538":[35,131,170,18,84,216],"543":[35,131,170,18,84,216]},"packages/workflow/src/workflow-data-proxy-paired-item-memo.ts":{"18":[32,3,35,4,5,6,170,85,182,216,223],"39":[32,3,35,4,5,6,170,85,182,216,223]},"packages/@n8n/agents/src/index.ts":{"119":[23,24,26,19,20,48,21,119,49,22,122],"121":[23,24,26,19,20,48,21,119,49,22,122],"167":[23,24,26,19,20,48,21,119,49,22,122],"196":[23,24,26,19,20,48,21,119,49,22,122],"197":[23,24,26,19,20,48,21,119,49,22,122],"198":[23,24,26,19,20,48,21,119,49,22,122],"200":[23,24,26,19,20,48,21,119,49,22,122],"260":[23,24,26,19,20,48,21,119,49,22,122],"364":[23,24,26,19,20,48,21,119,49,22,122],"368":[23,24,26,19,20,48,21,119,49,22,122],"370":[23,24,26,19,20,48,21,119,49,22,122],"430":[23,24,26,19,20,48,21,119,49,22,122],"477":[23,24,26,19,20,48,21,119,49,22,122],"478":[23,24,26,19,20,48,21,119,49,22,122],"479":[23,24,26,19,20,48,21,119,49,22,122],"486":[23,24,26,19,20,48,21,119,49,22,122],"523":[23,24,26,19,20,48,21,119,49,22,122]},"packages/@n8n/agents/src/runtime/tools/delegate-sub-agent-tool.ts":{"59":[23,24,26,19,20,21,49,22],"84":[23,24,26,19,20,21,49,22],"99":[23,24,26,19,20,21,49,22],"110":[23,24,26,19,20,21,49,22],"132":[23,24,26,19,20,21,49,22],"170":[23,24,26,19,20,21,49,22],"186":[23,24,26,19,20,21,49,22],"205":[23,24,26,19,20,21,49,22],"233":[23,24,26,19,20,21,49,22],"245":[23,24,26,19,20,21,49,22],"266":[23,24,26,19,20,21,49,22],"272":[23,24,26,19,20,21,49,22],"282":[23,24,26,19,20,21,49,22],"331":[23,24,26,19,20,21,49,22],"340":[23,24,26,19,20,21,49,22],"344":[23,24,26,19,20,21,49,22],"351":[23,24,26,19,20,21,49,22],"358":[23,24,26,19,20,21,49,22]},"packages/@n8n/agents/src/sdk/catalog.ts":{"132":[23,24,26,19,20,21,49,22],"146":[23,24,26,19,20,21,49,22],"178":[23,24,26,19,20,21,49,22],"269":[23,24,26,19,20,21,49,22],"273":[23,24,26,19,20,21,49,22],"277":[23,24,26,19,20,21,49,22],"295":[23,24,26,19,20,21,49,22],"311":[23,24,26,19,20,21,49,22],"331":[23,24,26,19,20,21,49,22]},"packages/@n8n/agents/src/sdk/guardrails/patterns.ts":{"21":[23,24,26],"37":[23,24,26],"51":[23,24,26]},"packages/@n8n/agents/src/sdk/guardrails/redactor.ts":{"13":[23,24,26,19,20,21,49,22],"21":[23,24,26,19,20,21,49,22],"29":[23,24,26,19,20,21,49,22],"41":[23,24,26,19,20,21,49,22],"50":[23,24,26,19,20,21,49,22],"62":[23,24,26,19,20,21,49,22]},"packages/@n8n/agents/src/types/index.ts":{"67":[23,24,26,19,20,21,49,22],"190":[23,24,26,19,20,21,49,22]},"packages/@n8n/agents/src/workspace/index.ts":{"1":[23,24,26,19,20,21,49,22],"13":[23,24,26,19,20,21,49,22],"14":[23,24,26,19,20,21,49,22]},"packages/@n8n/ai-utilities/src/json-schema/index.ts":{"6":[23,24,26,19,20,21,49,22,207,208,12],"7":[23,24,26,19,20,21,49,22,207,208,12],"15":[23,24,26,19,20,21,49,22,207,208,12]},"packages/@n8n/api-types/src/agents/agent-config-lifecycle.ts":{"8":[23,24,26,46],"13":[23,24,26,46]},"packages/@n8n/api-types/src/agents/agent-json-config.schema.ts":{"124":[23,24,26,46,207,208],"236":[23,24,26,46,207,208],"452":[23,24,26,46,207,208],"490":[23,24,26,46,207,208],"491":[23,24,26,46,207,208],"506":[23,24,26,46,207,208],"523":[46],"524":[23,24,26,46,207,208],"533":[23,24,26,46,207,208],"542":[46],"543":[23,24,26,46,207,208],"571":[23,24,26,46,207,208],"583":[23,24,26,46,207,208],"622":[23,24,26,207,208],"641":[23,24,26,207,208],"648":[23,24,26,207,208],"649":[23,24,26,207,208],"662":[23,24,26,207,208],"663":[23,24,26,207,208],"666":[23,24,26,207,208],"667":[23,24,26,207,208],"675":[23,24,26,207,208],"677":[23,24,26,207,208]},"packages/@n8n/api-types/src/agents/agent-personalisation.ts":{"9":[23,24,26,46],"11":[23,24,26,46],"15":[23,24,26,46],"17":[23,24,26,46],"20":[23,24,26,46],"27":[23,24,26,46],"31":[23,24,26,46],"51":[23,24,26,46],"66":[23,24,26,46],"74":[23,24,26,46],"86":[23,24,26,46]},"packages/cli/src/modules/agents/adapters/agents-credential-provider.ts":{"14":[23,24,26],"32":[23,24,26],"46":[23,24,26],"61":[23,24,26],"66":[23,24,26],"82":[23,24,26],"99":[23,24,26],"103":[23,24,26],"113":[23,24,26],"120":[23,24,26],"125":[23,24,26],"129":[23,24,26],"132":[23,24,26],"142":[23,24,26],"152":[23,24,26]},"packages/cli/src/modules/agents/agent-chat.controller.ts":{"72":[24,26],"88":[24,26],"91":[24,26],"97":[24,26],"102":[24,26],"110":[24,26],"154":[24,26],"160":[24,26],"166":[24,26],"186":[24,26],"205":[24,26],"222":[24,26],"239":[24,26],"240":[24,26],"247":[24,26],"253":[24,26],"261":[24,26],"297":[24,26],"320":[24,26],"344":[24,26],"361":[24,26],"413":[24,26],"435":[24,26],"454":[24,26],"474":[24,26],"494":[24,26],"517":[24,26],"541":[24,26],"575":[24,26],"602":[24,26],"615":[24,26],"637":[24,26],"660":[24,26],"682":[24,26],"698":[24,26],"716":[24,26],"735":[24,26],"759":[24,26],"780":[24,26],"794":[24,26],"817":[24,26],"841":[24,26],"858":[24,26],"881":[24,26],"903":[24,26],"909":[24,26],"915":[24,26],"916":[24,26],"940":[24,26],"959":[24,26],"981":[24,26],"1034":[24,26],"1065":[24,26],"1085":[24,26],"1133":[24,26]},"packages/cli/src/modules/agents/agent-config.service.ts":{"56":[23,24,25],"71":[23,24,25],"85":[23,24,25],"98":[23,24,25],"153":[23,24,25],"176":[23,24,25],"181":[23,24,25],"182":[23,24,25],"188":[23,24,25],"208":[23,24,25],"229":[23,24,25],"242":[23,24,25],"246":[23,24,25],"249":[23,24,25],"251":[23,24,25],"258":[23,24,25],"292":[23,24,25],"325":[23,24,25],"331":[23,24,25],"343":[23,24,25],"349":[23,24,25],"357":[23,24,25],"358":[23,24,25],"365":[23,24,25],"374":[23,24,25],"414":[23,24,25],"422":[23,24,25]},"packages/cli/src/modules/agents/agent-default-model-resolver.service.ts":{"26":[23,24],"40":[23,24],"46":[23,24],"64":[23,24],"78":[23,24],"90":[23,24],"94":[23,24],"105":[23,24],"127":[23,24],"152":[23,24]},"packages/cli/src/modules/agents/agent-definition.service.ts":{"20":[23,24],"27":[23,24],"34":[23,24],"38":[23,24],"42":[23,24],"50":[23,24],"55":[23,24]},"packages/cli/src/modules/agents/agent-execution-orchestrator.service.ts":{"333":[24,26],"352":[24,26],"363":[24,26],"380":[24,26],"384":[24,26],"388":[24,26],"394":[24,26],"427":[24,26],"432":[24,26],"492":[24,26],"517":[24,26],"532":[24,26],"533":[24,26],"537":[24,26],"616":[24,26],"669":[24,26],"682":[24,26],"683":[24,26],"692":[24,26],"712":[24,26],"737":[24,26],"752":[24,26],"784":[24,26],"807":[24,26],"829":[24,26],"835":[24,26],"868":[24,26],"877":[24,26],"897":[24,26],"924":[24,26],"937":[24,26],"955":[24,26],"978":[24,26],"1028":[24,26],"1029":[24,26],"1042":[24,26],"1067":[24,26],"1099":[24,26],"1124":[24,26],"1125":[24,26],"1129":[24,26],"1145":[24,26],"1155":[24,26],"1233":[24,26],"1274":[24,26],"1289":[24,26],"1292":[24,26],"1296":[24,26],"1326":[24,26],"1350":[24,26],"1366":[24,26],"1386":[24,26],"1413":[24,26],"1434":[24,26],"1448":[24,26],"1477":[24,26],"1506":[24,26],"1535":[24,26],"1571":[24,26],"1590":[24,26],"1620":[24,26],"1633":[24,26],"1689":[24,26],"1721":[24,26],"1764":[24,26],"1797":[24,26]},"packages/cli/src/modules/agents/agent-execution.service.ts":{"184":[23,24,26],"201":[23,24,26],"207":[23,24,26],"217":[23,24,26],"277":[23,24,26],"316":[23,24,26],"332":[23,24,26],"357":[23,24,26],"372":[23,24,26],"376":[23,24,26],"383":[23,24,26],"397":[23,24,26],"435":[23,24,26],"451":[23,24,26],"461":[23,24,26],"488":[23,24,26],"509":[23,24,26],"510":[23,24,26],"513":[23,24,26],"516":[23,24,26],"527":[23,24,26],"534":[23,24,26],"541":[23,24,26],"549":[23,24,26],"556":[23,24,26],"565":[23,24,26],"585":[23,24,26],"611":[23,24,26],"620":[23,24,26],"624":[23,24,26],"634":[23,24,26],"657":[23,24,26],"663":[23,24,26],"686":[23,24,26],"701":[23,24,26],"707":[23,24,26],"722":[23,24,26],"748":[23,24,26],"768":[23,24,26],"782":[23,24,26],"789":[23,24,26],"794":[23,24,26],"802":[23,24,26],"820":[23,24,26],"836":[23,24,26],"840":[23,24,26],"845":[23,24,26],"855":[23,24,26],"858":[23,24,26],"859":[23,24,26],"862":[23,24,26],"876":[23,24,26],"881":[23,24,26],"898":[23,24,26],"906":[23,24,26],"922":[23,24,26],"939":[23,24,26],"943":[23,24,26],"962":[23,24,26],"990":[23,24,26],"1004":[23,24,26],"1009":[23,24,26],"1010":[23,24,26],"1013":[23,24,26],"1062":[23,24,26],"1089":[23,24,26],"1096":[23,24,26],"1115":[23,24,26],"1144":[23,24,26],"1152":[23,24,26],"1199":[23,24,26],"1218":[23,24,26],"1231":[23,24,26],"1237":[23,24,26],"1259":[23,24,26],"1283":[23,24,26],"1291":[23,24,26],"1300":[23,24,26],"1308":[23,24,26]},"packages/cli/src/modules/agents/agent-integration-persistence.service.ts":{"60":[23,24],"68":[23,24],"73":[23,24],"82":[23,24],"84":[23,24],"85":[23,24],"90":[23,24],"104":[23,24],"105":[23,24],"110":[23,24],"131":[23,24],"168":[23,24],"179":[23,24],"200":[23,24],"213":[23,24],"241":[23,24]},"packages/cli/src/modules/agents/agent-integrations.controller.ts":{"29":[23,24],"42":[23,24],"73":[23,24],"103":[23,24],"119":[23,24],"124":[23,24],"128":[23,24],"139":[23,24],"160":[23,24],"175":[23,24],"283":[23,24],"285":[23,24],"297":[23,24]},"packages/cli/src/modules/agents/agent-message-queue.service.ts":{"66":[24,26],"82":[24,26],"100":[24,26],"138":[24,26],"184":[24,26],"195":[24,26],"198":[24,26],"202":[24,26],"211":[24,26],"212":[24,26],"227":[24,26],"236":[24,26],"239":[24,26],"259":[24,26],"269":[24,26],"288":[24,26],"297":[24,26],"319":[24,26],"341":[24,26],"350":[24,26],"397":[24,26],"398":[24,26],"410":[24,26],"430":[24,26],"437":[24,26],"460":[24,26]},"packages/cli/src/modules/agents/agent-policy.service.ts":{"13":[23,24,26],"31":[23,24,26],"34":[23,24,26],"51":[23,24,26]},"packages/cli/src/modules/agents/agent-publish.service.ts":{"72":[23,24,26],"77":[23,24,26],"78":[23,24,26],"88":[23,24,26],"111":[23,24,26],"132":[23,24,26],"157":[23,24,26],"195":[23,24,26],"252":[23,24,26],"261":[23,24,26],"293":[23,24,26],"307":[23,24,26],"351":[23,24,26],"375":[23,24,26],"399":[23,24,26],"422":[23,24,26],"431":[23,24,26],"442":[23,24,26],"477":[23,24,26],"485":[23,24,26],"501":[23,24,26],"511":[23,24,26],"528":[23,24,26],"538":[23,24,26],"544":[23,24,26],"563":[23,24,26],"583":[23,24,26],"589":[23,24,26],"600":[23,24,26],"605":[23,24,26],"606":[23,24,26],"629":[23,24,26],"639":[23,24,26],"646":[23,24,26],"664":[23,24,26],"684":[23,24,26],"699":[23,24,26]},"packages/cli/src/modules/agents/agent-runnable-state.service.ts":{"18":[23,24,26],"33":[23,24,26],"49":[23,24,26]},"packages/cli/src/modules/agents/agent-task.service.ts":{"49":[23,24,26],"68":[23,24,26],"87":[23,24,26],"89":[23,24,26],"97":[23,24,26],"113":[23,24,26],"130":[23,24,26],"150":[23,24,26],"153":[23,24,26],"168":[23,24,26],"179":[23,24,26],"181":[23,24,26],"191":[23,24,26],"202":[23,24,26],"220":[23,24,26],"235":[23,24,26],"247":[23,24,26],"251":[23,24,26],"263":[23,24,26],"266":[23,24,26],"280":[23,24,26],"298":[23,24,26],"321":[23,24,26],"326":[23,24,26],"331":[23,24,26],"342":[23,24,26],"366":[23,24,26],"371":[23,24,26],"386":[23,24,26],"401":[23,24,26],"419":[23,24,26],"420":[23,24,26],"439":[23,24,26],"461":[23,24,26],"499":[23,24,26],"500":[23,24,26],"503":[23,24,26],"511":[23,24,26],"521":[23,24,26],"557":[23,24,26],"580":[23,24,26],"610":[23,24,26],"620":[23,24,26],"645":[23,24,26],"653":[23,24,26],"659":[23,24,26],"666":[23,24,26],"672":[23,24,26],"684":[23,24,26],"715":[23,24,26],"733":[23,24,26]},"packages/cli/src/modules/agents/agent-tasks.controller.ts":{"23":[23,24],"31":[23,24],"42":[23,24],"67":[23,24],"93":[23,24],"119":[23,24]},"packages/cli/src/modules/agents/agent-threads.controller.ts":{"15":[23,24],"22":[23,24],"42":[23,24],"60":[23,24],"69":[23,24],"83":[23,24]},"packages/cli/src/modules/agents/agent-validation.service.ts":{"68":[23,24,26],"77":[23,24,26],"86":[23,24,26],"101":[23,24,26],"115":[23,24,26],"126":[23,24,26],"137":[23,24,26],"156":[23,24,26],"191":[23,24,26],"214":[23,24,26],"232":[23,24,26],"255":[23,24,26],"267":[23,24,26],"275":[23,24,26],"283":[23,24,26],"285":[23,24,26],"316":[23,24,26],"322":[23,24,26],"338":[23,24,26],"343":[23,24,26],"355":[23,24,26],"367":[23,24,26],"414":[23,24,26],"442":[23,24,26],"452":[23,24,26],"481":[23,24,26],"497":[23,24,26],"530":[23,24,26],"558":[23,24,26],"594":[23,24,26],"649":[23,24,26],"670":[23,24,26],"706":[23,24,26],"721":[23,24,26],"733":[23,24,26],"744":[23,24,26],"768":[23,24,26],"785":[23,24,26],"827":[23,24,26],"832":[23,24,26],"834":[23,24,26]},"packages/cli/src/modules/agents/agents-catalog.controller.ts":{"19":[23,24],"26":[23,24],"33":[23,24],"52":[23,24]},"packages/cli/src/modules/agents/agents-config.controller.ts":{"24":[23,24,25],"36":[23,24,25],"50":[23,24,25],"65":[23,24,25],"88":[23,24,25],"113":[23,24,25]},"packages/cli/src/modules/agents/agents-settings.service.ts":{"18":[23,24,26],"29":[23,24,26],"39":[23,24,26],"40":[23,24,26],"44":[23,24,26],"49":[23,24,26],"50":[23,24,26],"60":[23,24,26],"74":[23,24,26]},"packages/cli/src/modules/agents/agents.controller.ts":{"24":[23,24,25,26],"33":[23,24,25,26],"72":[23,24,25,26],"87":[23,24,25,26],"108":[23,24,25,26],"117":[23,24,25,26],"133":[23,24,25,26]},"packages/cli/src/modules/agents/agents.service.ts":{"83":[23,24,25,26,190],"121":[23,24,25,26,190],"130":[23,24,25,26,190],"200":[23,24,25,26,190],"210":[23,24,25,26,190],"222":[23,24,25,26,190],"228":[23,24,25,26,190],"232":[23,24,25,26,190],"239":[23,24,25,26,190],"243":[23,24,25,26,190],"253":[23,24,25,26,190],"266":[23,24,25,26,190],"272":[23,24,25,26,190],"274":[23,24,25,26,190],"293":[23,24,25,26,190],"295":[23,24,25,26,190],"309":[23,24,25,26,190],"323":[23,24,25,26,190],"329":[23,24,25,26,190],"347":[23,24,25,26,190],"372":[23,24,25,26,190],"384":[23,24,25,26,190],"388":[23,24,25,26,190],"394":[23,24,25,26,190],"408":[23,24,25,26,190],"427":[23,24,25,26,190],"438":[23,24,25,26,190],"448":[23,24,25,26,190],"453":[23,24,25,26,190],"461":[23,24,25,26,190],"463":[23,24,25,26,190],"473":[23,24,25,26,190],"476":[23,24,25,26,190],"513":[23,24,25,26,190],"538":[23,24,25,26,190],"556":[23,24,25,26,190],"557":[23,24,25,26,190],"581":[23,24,25,26,190],"586":[23,24,25,26,190],"588":[23,24,25,26,190],"595":[23,24,25,26,190],"606":[23,24,25,26,190],"617":[23,24,25,26,190],"629":[23,24,25,26,190],"642":[23,24,25,26,190]},"packages/cli/src/modules/agents/builder/agents-builder.service.ts":{"93":[24,26],"108":[24,26],"151":[24,26],"202":[24,26],"219":[24,26],"234":[24,26],"269":[24,26],"294":[24,26],"308":[24,26],"315":[24,26],"343":[24,26],"350":[24,26],"357":[24,26],"364":[24,26],"373":[24,26],"391":[24,26],"410":[24,26],"419":[24,26]},"packages/cli/src/modules/agents/integrations/agent-chat-integration.ts":{"111":[23,24,26],"117":[23,24,26],"133":[23,24,26],"225":[23,24,26],"278":[23,24,26],"279":[23,24,26],"283":[23,24,26],"284":[23,24,26],"362":[23,24,26],"639":[23,24,26],"642":[23,24,26],"646":[23,24,26],"650":[23,24,26],"656":[23,24,26],"661":[23,24,26],"662":[23,24,26]},"packages/cli/src/modules/agents/integrations/channel-status-report.ts":{"35":[23,24],"55":[23,24],"56":[23,24],"70":[23,24],"73":[23,24],"81":[23,24],"85":[23,24],"93":[23,24],"105":[23,24],"107":[23,24],"109":[23,24],"113":[23,24],"116":[23,24],"117":[23,24],"118":[23,24],"121":[23,24],"123":[23,24]},"packages/cli/src/modules/agents/integrations/n8n-checkpoint-storage.ts":{"25":[24,26],"52":[24,26],"64":[24,26],"66":[24,26],"67":[24,26],"68":[24,26],"70":[24,26],"72":[24,26],"79":[24,26],"106":[24,26],"108":[24,26],"132":[24,26],"138":[24,26],"156":[24,26],"162":[24,26],"183":[24,26],"198":[24,26],"211":[24,26],"215":[24,26],"231":[24,26],"249":[24,26],"268":[24,26],"297":[24,26],"305":[24,26],"324":[24,26],"340":[24,26],"356":[24,26],"374":[24,26],"379":[24,26]},"packages/cli/src/modules/agents/json-config/agent-config-composition.ts":{"11":[23,24,26],"25":[23,24,26]},"packages/cli/src/modules/agents/model-catalog.ts":{"3":[23,24]},"packages/cli/src/modules/agents/repositories/agent-channel-status.repository.ts":{"42":[23,24],"56":[23,24],"69":[23,24],"78":[23,24],"83":[23,24],"87":[23,24],"92":[23,24],"97":[23,24],"107":[23,24],"112":[23,24]},"packages/cli/src/modules/agents/repositories/agent-checkpoint.repository.ts":{"9":[24,26],"13":[24,26],"17":[24,26],"25":[24,26],"37":[24,26],"41":[24,26],"45":[24,26],"53":[24,26],"68":[24,26],"83":[24,26],"97":[24,26],"109":[24,26]},"packages/cli/src/modules/agents/repositories/agent-execution-thread.repository.ts":{"51":[23,24,26],"55":[23,24,26],"68":[23,24,26],"97":[23,24,26],"151":[23,24,26],"182":[23,24,26],"198":[23,24,26],"212":[23,24,26],"252":[23,24,26],"274":[23,24,26],"278":[23,24,26],"285":[23,24,26],"304":[23,24,26],"332":[23,24,26],"344":[23,24,26],"354":[23,24,26],"366":[23,24,26],"380":[23,24,26],"407":[23,24,26],"418":[23,24,26],"425":[23,24,26],"434":[23,24,26],"435":[23,24,26],"438":[23,24,26],"441":[23,24,26],"453":[23,24,26],"487":[23,24,26],"495":[23,24,26],"500":[23,24,26],"509":[23,24,26],"510":[23,24,26],"517":[23,24,26],"523":[23,24,26],"526":[23,24,26],"542":[23,24,26],"562":[23,24,26],"574":[23,24,26],"590":[23,24,26]},"packages/cli/src/modules/agents/repositories/agent-history.repository.ts":{"17":[23,24,26],"24":[23,24,26],"37":[23,24,26],"70":[23,24,26],"83":[23,24,26],"104":[23,24,26]},"packages/cli/src/modules/agents/repositories/agent-task.repository.ts":{"12":[23,24],"16":[23,24],"23":[23,24],"27":[23,24],"31":[23,24],"37":[23,24],"44":[23,24],"45":[23,24],"50":[23,24]},"packages/cli/src/modules/agents/repositories/agent.repository.ts":{"32":[23,24,25,26,4,6,123,190],"41":[23,24,25,26,4,6,123,190],"47":[23,24,25,26,4,6,123,190],"51":[23,24,25,26,4,6,123,190],"59":[23,24,25,26,4,6,123,190],"77":[23,24,25,26,4,6,123,190],"80":[23,24,25,26,4,6,123,190],"84":[23,24,25,26,4,6,123,190],"89":[23,24,25,26,4,6,123,190],"103":[23,24,25,26,4,6,123,190],"139":[23,24,25,26,4,6,123,190],"180":[23,24,25,26,4,6,123,190],"192":[23,24,25,26,4,6,123,190],"202":[23,24,25,26,4,6,123,190],"210":[23,24,25,26,4,6,123,190],"221":[23,24,25,26,4,6,123,190],"265":[23,24,25,26,4,6,123,190],"293":[23,24,25,26,4,6,123,190],"303":[23,24,25,26,4,6,123,190],"304":[23,24,25,26,4,6,123,190],"324":[23,24,25,26,4,6,123,190],"331":[23,24,25,26,4,6,123,190],"335":[23,24,25,26,4,6,123,190],"345":[23,24,25,26,4,6,123,190],"352":[23,24,25,26,4,6,123,190],"368":[23,24,25,26,4,6,123,190],"379":[23,24,25,26,4,6,123,190],"388":[23,24,25,26,4,6,123,190],"393":[23,24,25,26,4,6,123,190],"402":[23,24,25,26,4,6,123,190],"411":[23,24,25,26,4,6,123,190],"422":[23,24,25,26,4,6,123,190],"441":[23,24,25,26,4,6,123,190],"451":[23,24,25,26,4,6,123,190],"461":[23,24,25,26,4,6,123,190],"473":[23,24,25,26,4,6,123,190],"486":[23,24,25,26,4,6,123,190],"492":[23,24,25,26,4,6,123,190],"499":[23,24,25,26,4,6,123,190],"504":[23,24,25,26,4,6,123,190],"512":[23,24,25,26,4,6,123,190],"521":[23,24,25,26,4,6,123,190],"528":[23,24,25,26,4,6,123,190],"543":[23,24,25,26,4,6,123,190],"550":[23,24,25,26,4,6,123,190],"552":[23,24,25,26,4,6,123,190],"568":[23,24,25,26,4,6,123,190],"576":[23,24,25,26,4,6,123,190],"578":[23,24,25,26,4,6,123,190],"591":[23,24,25,26,4,6,123,190],"603":[23,24,25,26,4,6,123,190],"619":[23,24,25,26,4,6,123,190],"635":[23,24,25,26,4,6,123,190]},"packages/cli/src/modules/agents/tools/workflow-tool-workflow-resolver.ts":{"6":[23,24,26],"14":[23,24,26],"17":[23,24,26],"36":[23,24,26],"53":[23,24,26],"59":[23,24,26],"63":[23,24,26],"69":[23,24,26],"70":[23,24,26]},"packages/cli/src/modules/agents/utils/agent-config-hash.ts":{"5":[23,24,26],"6":[23,24,26],"14":[23,24,26],"23":[23,24,26],"28":[23,24,26],"32":[23,24,26]},"packages/cli/src/modules/agents/utils/agent-credential-provider.ts":{"7":[23,24,26]},"packages/cli/src/modules/agents/utils/agent-definition.ts":{"12":[23,24,26],"18":[23,24,26]},"packages/cli/src/modules/agents/utils/agent-missing-skill-ids.ts":{"3":[23,24,26]},"packages/cli/src/modules/agents/utils/extract-agent-workflow-refs.ts":{"8":[23,24,26],"12":[23,24,26]},"packages/cli/src/modules/agents/utils/get-agent-or-throw.ts":{"6":[23,24,25,26]},"packages/cli/src/modules/agents/utils/node-tool-validation.ts":{"20":[23,24],"23":[23,24],"55":[23,24],"67":[23,24],"71":[23,24],"112":[23,24]},"packages/cli/src/modules/agents/utils/parse-thread-list-limit.ts":{"2":[23,24]},"packages/cli/src/modules/provisioning.ee/provisioning.service.ee.ts":{"43":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","60":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","64":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","72":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","126":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","177":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","243":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","256":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","286":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","288":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","291":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","308":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","369":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","402":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","418":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","422":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","441":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","456":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","464":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","472":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","480":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","485":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","490":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","499":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","503":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","511":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","518":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","557":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","578":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","585":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","593":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","652":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","679":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","689":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","701":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","703":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","708":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","730":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","781":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","790":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","814":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","825":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA=","831":"b:AAKCo4D5CF5iBsABAAAAAAAAABAAAAAAAAAAAAA="},"packages/cli/src/services/ai-gateway.service.ts":{"57":[23,24,19,20,21,49,22,207,208],"71":[23,24,19,20,21,49,22,207,208],"79":[23,24,19,20,21,49,22,207,208],"88":[23,24,19,20,21,49,22,207,208],"121":[23,24,19,20,21,49,22,207,208],"149":[23,24,19,20,21,49,22,207,208],"174":[23,24,19,20,21,49,22,207,208],"251":[23,24,19,20,21,49,22,207,208],"259":[23,24,19,20,21,49,22,207,208],"273":[23,24,19,20,21,49,22,207,208],"302":[23,24,19,20,21,49,22,207,208],"321":[23,24,19,20,21,49,22,207,208],"355":[23,24,19,20,21,49,22,207,208],"375":[23,24,19,20,21,49,22,207,208],"382":[23,24,19,20,21,49,22,207,208],"394":[23,24,19,20,21,49,22,207,208],"404":[23,24,19,20,21,49,22,207,208],"448":[23,24,19,20,21,49,22,207,208],"466":[23,24,19,20,21,49,22,207,208],"483":[23,24,19,20,21,49,22,207,208],"488":[23,24,19,20,21,49,22,207,208],"495":[23,24,19,20,21,49,22,207,208],"511":[23,24,19,20,21,49,22,207,208],"531":[23,24,19,20,21,49,22,207,208]},"localhost-39643/assets/index-Dv_brJ4-.js":{"3":[24]},"localhost-39643/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[24],"9":[24],"10":[24],"19":[24],"23":[24],"29":[24],"33":[24],"34":[24]},"packages/frontend/@n8n/design-system/src/components/N8nAiModelSelectorDropdown/AiModelSelectorDropdown.vue":{"29":[23,24,4,111,5,112,6,17,46],"90":[46],"93":[23,24,4,111,5,112,6,17,46],"95":[23,24,4,111,5,112,6,17,46],"97":[46],"101":[111,5,112,46],"107":[46],"110":[46],"112":[23,24,4,111,5,112,6,17,46],"127":[23,24,4,111,5,112,6,17,46],"133":[23,24,4,111,5,112,6,17,46],"138":[23,24,4,111,5,112,6,17,46],"147":[46],"155":[46],"163":[4,111,5,112,6,46],"172":[111,5,112,46],"186":[111,5,112,46],"189":[46],"191":[46],"196":[46],"205":[111,5,112,46],"212":[46],"219":[46],"228":[46],"233":[111,5,112,46],"236":[46],"238":[46],"253":[46]},"packages/frontend/@n8n/design-system/src/components/N8nBreadcrumbs/Breadcrumbs.vue":{"34":[23,24,25,46,47,114,57,136],"60":[23,24,25,46,47,114,57,136],"66":[23,24,25,46,47,114,57,136],"70":[46,57],"74":[46,57],"75":[46,57],"82":[46,57],"108":[23,24,25,46,47,114,57,136],"109":[46,57],"115":[46,57],"124":[46,57],"125":[46,57],"143":[46,57],"144":[46,57],"151":[46],"152":[46],"159":[46,57],"166":[46],"171":[46],"173":[23,24,25,46,47,114,57,136],"212":[46,57],"219":[46,57],"234":[46],"246":[46],"247":[46,57],"254":[23,24,25,46,47,114,57,136],"266":[46,57],"267":[46,57],"268":[46,57],"270":[23,24,25,46,47,114,57,136],"271":[46]},"packages/frontend/@n8n/design-system/src/components/N8nDropdownMenu/composables/useDropdownSearch.ts":{"43":[46],"47":[46],"55":[46],"66":[46],"72":[46],"75":[46],"79":[46],"87":[46],"116":[46],"125":[46],"145":[23,24,46],"153":[46],"158":[23,24,46],"169":[46]},"packages/frontend/@n8n/design-system/src/components/N8nIconPicker/IconPicker.vue":{"54":[23,24,112,17,46,58,60],"102":[46,60],"104":[46,60],"106":[46,60],"108":[46,60],"111":[23,24,112,17,46,58,60],"114":[46,60],"119":[23,24,112,17,46,58,60],"126":[46,60],"130":[46,60],"138":[46,60],"143":[46,60],"151":[46,60],"160":[23,24,112,17,46,58,60],"183":[23,24,112,17,46,58,60],"184":[23,24,112,17,46,58,60],"189":[46,60],"194":[23,24,112,17,46,58,60],"197":[46,60],"200":[46,60],"204":[46,60],"208":[46,60],"212":[46,60],"225":[46,60],"234":[46,60],"242":[46,60],"251":[46,60],"256":[46,60],"269":[46,60],"274":[46,60],"280":[46,60],"285":[46],"291":[46,60],"300":[46,60],"308":[46,60],"316":[46],"320":[46,60],"326":[46,60],"333":[112,46,60],"338":[46],"346":[46],"347":[46],"355":[46,60],"364":[46],"371":[46],"389":[46],"402":[46],"443":[46],"451":[23,24,112,17,46,58,60],"462":[23,24,112,17,46,58,60],"475":[46],"477":[23,24,112,17,46,58,60],"493":[46,60],"506":[46],"507":[46,60],"513":[46,60],"552":[46,60],"561":[46],"563":[46,60],"575":[46],"577":[46,60],"581":[46],"584":[46,60],"595":[46],"596":[46,60],"620":[46,60],"623":[46,60],"628":[46,60],"641":[46],"643":[46],"645":[46],"646":[46,60],"669":[46,60],"672":[46,60],"677":[46,60],"689":[46,60],"691":[46,60],"693":[46,60],"694":[46,60]},"packages/frontend/@n8n/design-system/src/components/N8nIconPicker/useIconPickerSearch.ts":{"24":[23,24,112,17,46,58,60],"32":[46],"39":[46],"47":[46],"48":[46],"49":[46],"63":[23,24,112,17,46,58,60],"101":[46,60],"107":[46,60],"112":[46],"113":[46],"117":[46,60],"123":[46,60]},"packages/frontend/@n8n/design-system/src/components/N8nIconPicker/useIconPickerVirtualRows.ts":{"30":[46,60],"40":[23,24,112,17,46,58,60],"60":[46,60],"68":[46],"72":[46],"75":[46],"79":[46,60]},"packages/frontend/@n8n/design-system/src/components/N8nMarkdownEditor/MarkdownEditor.vue":{"19":[23,24,46],"40":[23,24,46],"46":[23,24,46],"50":[23,24,46],"53":[46],"56":[46],"58":[23,24,46],"64":[23,24,46],"68":[23,24,46],"77":[46],"83":[23,24,46],"84":[46],"92":[46],"98":[23,24,46],"109":[23,24,46],"112":[23,24,46],"115":[23,24,46],"119":[23,24,46],"126":[46],"148":[46],"166":[46],"175":[23,24,46],"186":[46],"188":[46],"191":[46],"196":[46],"202":[46],"229":[46],"235":[23,24,46],"245":[46],"246":[46],"271":[46],"279":[46],"283":[46],"287":[46],"293":[46],"302":[46],"311":[46],"315":[46],"325":[23,24,46],"381":[46],"389":[23,24,46],"399":[46],"414":[46],"422":[46],"445":[46],"449":[46]},"packages/frontend/@n8n/design-system/src/components/N8nMarkdownEditor/MarkdownEditorExpandedViewButton.vue":{"10":[23,24,46],"27":[23,24,46],"33":[23,24,46],"37":[23,24,46],"43":[46]},"packages/frontend/@n8n/design-system/src/components/N8nMarkdownEditor/MarkdownEditorToolbar.vue":{"21":[23,24,46],"51":[23,24,46],"53":[46],"62":[23,24,46],"67":[46],"73":[46],"79":[46],"85":[46],"89":[23,24,46],"94":[46],"100":[46],"104":[23,24,46],"109":[46],"115":[46],"121":[46],"125":[23,24,46],"130":[46],"136":[46],"140":[23,24,46],"163":[23,24,46],"167":[23,24,46],"168":[46],"171":[23,24,46],"176":[23,24,46],"177":[46],"182":[23,24,46],"186":[23,24,46],"187":[46],"190":[23,24,46],"199":[23,24,46],"201":[23,24,46],"205":[23,24,46],"213":[46],"219":[46],"227":[46],"237":[46],"242":[46],"247":[46],"278":[46],"297":[23,24,46],"314":[23,24,46],"321":[23,24,46],"328":[23,24,46],"343":[23,24,46],"345":[23,24,46],"351":[46],"365":[23,24,46],"367":[23,24,46],"373":[46],"380":[46],"382":[23,24,46],"392":[46],"395":[46],"419":[46],"425":[46],"434":[46],"457":[23,24,46],"459":[23,24,46],"465":[46],"478":[23,24,46],"480":[23,24,46],"486":[46],"503":[46],"509":[46]},"packages/frontend/@n8n/design-system/src/components/N8nMarkdownEditor/composables/useMarkdownEditor.ts":{"31":[23,24,46],"37":[23,24,46],"39":[46],"45":[23,24,46],"55":[23,24,46],"87":[46],"90":[46],"95":[23,24,46],"98":[46],"104":[46],"107":[46],"112":[23,24,46],"113":[46],"125":[23,24,46],"126":[23,46]},"packages/frontend/@n8n/design-system/src/components/N8nMarkdownEditor/markdownEditorUtils.ts":{"8":[23,24,46],"10":[46],"25":[46],"35":[46],"45":[46],"48":[46],"51":[46],"62":[46],"71":[46]},"packages/frontend/@n8n/design-system/src/components/N8nSwitch/Switch.vue":{"10":[23,24,113,46],"14":[23,24,113,46],"21":[23,24,113,46],"26":[23,24,113,46],"30":[23,24,113,46],"38":[23,24,113,46],"48":[23,24,113,46],"56":[46],"57":[46]},"packages/frontend/@n8n/design-system/src/components/N8nToggle/Toggle.vue":{"22":[23,24,46],"36":[23,24,46],"41":[23,24,46],"47":[23,24,46],"52":[23,24,46],"67":[23,24,46],"69":[46],"74":[23,24,46],"78":[23,24,46],"86":[23,24,46],"103":[23,24,46],"119":[46],"136":[46]},"packages/frontend/@n8n/design-system/src/components/N8nToggleGroup/ToggleGroup.vue":{"30":[23,24,46],"31":[23,24,46],"47":[46],"48":[23,24,46]},"packages/frontend/@n8n/design-system/src/components/N8nVisuallyHidden/VisuallyHidden.vue":{"10":[23,24,46],"11":[23,24,46]},"packages/frontend/editor-ui/src/app/layouts/DefaultLayout.vue":{"8":"b:AAKCI4CpAB5iAEALGBAEAoABAFEAAQDBAAAAAAA=","10":"b:AAKCI4CpAB5iAEALGBAEAoABAFEAAQDBAAAAAAA="},"packages/frontend/editor-ui/src/app/utils/rbac/middleware/custom.ts":{"4":"b:IAL6I4DpBx52AEAJHRj0D4ABwFMAAQDBAAAAAAA="},"packages/frontend/editor-ui/src/features/agents/agentEvals.store.ts":{"101":"b:AAD4AQAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","221":[23,24]},"packages/frontend/editor-ui/src/features/agents/agentSessions.store.ts":{"18":[23,24,25],"39":[23,24,25],"44":[23,24,25],"55":[23,24,25],"74":[23,24,25],"182":[24,25],"226":[23,24,25],"237":[23,24,25],"244":[23,24,25],"252":[23,24]},"packages/frontend/editor-ui/src/features/agents/agentTemplates.ts":{"59":[23,24]},"packages/frontend/editor-ui/src/features/agents/channels/n8nChat/useN8nChatChannel.ts":{"12":[23,24],"22":[23,24]},"packages/frontend/editor-ui/src/features/agents/channels/registry.ts":{"27":[23,24],"135":[23,24],"139":[23,24],"143":[23,24]},"packages/frontend/editor-ui/src/features/agents/channels/slack/useSlackChannelRuntime.ts":{"66":[23,24]},"packages/frontend/editor-ui/src/features/agents/components/AgentBuilderEditorColumn.vue":{"36":[23,24],"70":[23,24],"79":[23,24],"80":[23,24],"150":[23,24],"180":[23,24],"193":[23,24],"211":[23,24],"218":[23,24],"250":[23,24]},"packages/frontend/editor-ui/src/features/agents/components/AgentBuilderHeader.vue":{"34":[23,24],"72":[23,24],"73":[23,24],"78":[23,24],"83":[23,24],"92":[23,24],"100":[23,24],"102":[23,24],"135":[23,24],"152":[23,24],"158":[23,24],"170":[23,24],"173":[23,24],"181":[23,24],"214":[23,24],"262":[23,24]},"packages/frontend/editor-ui/src/features/agents/components/AgentBuilderTabPanel.vue":{"2":[23,24]},"packages/frontend/editor-ui/src/features/agents/components/AgentCapabilitiesSection.utils.ts":{"29":[46],"56":[46],"61":[46],"66":[46],"67":[46],"68":[46],"69":[46],"71":[46],"83":[23,24,46],"117":[46]},"packages/frontend/editor-ui/src/features/agents/components/AgentCapabilitiesSection.vue":{"46":[23,24,46],"79":[23,24,46],"80":[23,24,46],"104":[23,24,46],"112":[23,24,46],"113":[23,24,46],"114":[23,24,46],"115":[46],"117":[46],"118":[46],"119":[46],"121":[23,24,46],"122":[46],"123":[46],"140":[46],"144":[46],"146":[46],"147":[46],"151":[46],"152":[46],"154":[46],"155":[46],"157":[46],"158":[46],"161":[23,24,46],"163":[23,24,46],"164":[46],"169":[23,24,46],"170":[46],"173":[23,24,46],"174":[46],"191":[46],"203":[23,24,46],"204":[46],"210":[46],"218":[46],"239":[46],"247":[46],"263":[46],"278":[46],"284":[23,24,46],"286":[46],"311":[23,24,46],"313":[46],"319":[23,24,46],"321":[46],"324":[46],"327":[23,24,46],"334":[23,24,46],"335":[23,24,46],"342":[23,24,46],"343":[23,24,46],"347":[46],"352":[46],"371":[46],"374":[46],"388":[46],"396":[46],"402":[46],"406":[46],"410":[46],"413":[46],"417":[46],"420":[46],"421":[46],"424":[46],"426":[46],"429":[46],"438":[46],"439":[46],"447":[46],"458":[46],"459":[46],"469":[46],"472":[46],"476":[46],"488":[46],"504":[46],"506":[46],"514":[23,24,46],"520":[23,24,46],"528":[46],"529":[23,24,46],"530":[46],"538":[46],"540":[46],"541":[46],"542":[46],"552":[46],"554":[46],"562":[46],"567":[46],"568":[46],"569":[46],"576":[46],"584":[46],"600":[46],"601":[46],"620":[46],"621":[46],"622":[46],"633":[46],"635":[46],"637":[46],"651":[46],"652":[46],"666":[46],"667":[23,24,46],"669":[46],"676":[46],"677":[46],"678":[46],"689":[46],"690":[46],"703":[46],"704":[46],"705":[46],"706":[46],"717":[23,24,46],"718":[46],"722":[46],"723":[46],"724":[46],"733":[46],"734":[46],"746":[46]},"packages/frontend/editor-ui/src/features/agents/components/AgentChatEmptyState.vue":{"8":[24],"24":[24]},"packages/frontend/editor-ui/src/features/agents/components/AgentChatMessageList.vue":{"157":[24],"203":[24],"373":[24],"417":[24],"425":[24],"440":[24],"445":[24],"457":[24]},"packages/frontend/editor-ui/src/features/agents/components/AgentChatPanel.vue":{"193":[24],"203":[24],"221":[24],"224":[24],"231":[24],"389":[24],"390":[24],"391":[24],"392":[24],"393":[24],"394":[24],"396":[24],"399":[24],"435":[24],"438":[24],"503":[24],"512":[24],"527":[24],"593":[24],"597":[24],"621":[24],"625":[24],"634":[24],"635":[24],"636":[24],"637":[24],"679":[24],"684":[24],"688":[24],"743":[24],"752":[24],"804":[24],"805":[24],"810":[24],"813":[24],"819":[24],"824":[24],"827":[24],"836":[24],"840":[24],"881":[24],"889":[24],"900":[24],"945":[24],"948":[24],"953":[24],"957":[24],"965":[24],"966":[24],"967":[24],"971":[24],"974":[24],"981":[24],"1160":[24],"1202":[24],"1456":[24],"1487":[24]},"packages/frontend/editor-ui/src/features/agents/components/AgentChipRow.vue":{"4":[23,24,46],"26":[23,24,46],"33":[46],"41":[46],"48":[46],"50":[46],"63":[46],"64":[23,24,46]},"packages/frontend/editor-ui/src/features/agents/components/AgentCollaborationBanner.vue":{"10":[23,24],"14":[23,24],"39":[23],"52":[23],"65":[23],"66":[23],"67":[23],"73":[23],"78":[23,24],"91":[23],"98":[23],"102":[23]},"packages/frontend/editor-ui/src/features/agents/components/AgentIdentityHeader.vue":{"12":[23,24],"32":[23,24],"33":[23,24],"43":[23,24],"58":[23,24],"66":[23,24]},"packages/frontend/editor-ui/src/features/agents/components/AgentInfoPanel.vue":{"45":[23,24,46],"81":[23,24,46],"89":[23,24,46],"96":[23,24,46],"105":[23,24,46],"119":[23,24,46],"123":[23,24,46],"129":[46],"155":[23,24,46],"156":[23,24,46],"177":[23,24,46],"189":[23,24,46],"190":[46],"206":[46],"214":[46],"216":[46],"222":[46],"233":[46],"238":[46],"243":[46],"301":[23,24,46],"305":[46],"331":[23,24,46],"337":[23,24,46],"348":[46],"361":[23,24,46],"362":[46],"368":[46],"372":[46],"376":[46],"380":[46],"390":[23,24,46],"397":[23,24,46],"403":[23,24,46],"404":[23,24,46],"407":[23,24,46],"430":[46],"444":[46],"457":[46],"465":[46],"466":[46],"470":[46],"486":[23,24,46],"487":[23,24,46],"490":[23,24,46]},"packages/frontend/editor-ui/src/features/agents/components/AgentMemoryPanel.vue":{"22":[23,24],"35":[23,24],"36":[23,24],"92":[23,24],"100":[23,24],"102":[23,24],"103":[23,24],"109":[23,24],"112":[23,24]},"packages/frontend/editor-ui/src/features/agents/components/AgentModelSelector.vue":{"44":[23,24,46],"106":[23,24,46],"110":[46],"124":[23,24,46],"130":[23,24,46],"134":[46],"141":[23,24,46],"151":[23,24,46],"153":[23,24,46],"159":[23,24,46],"168":[23,24,46],"172":[23,24,46],"176":[23,24,46],"180":[46],"186":[46],"190":[23,24,46],"194":[23,24,46],"198":[23,24,46],"212":[46],"215":[23,24,46],"219":[46],"225":[23,24,46],"226":[23,24,46],"230":[23,24,46],"233":[23,24,46],"239":[46],"245":[46],"250":[23,24,46],"276":[46],"279":[46],"304":[23,24,46],"317":[46],"367":[46],"469":[23,24,46],"473":[23,24,46],"476":[46],"486":[23,24,46],"523":[23,24,46],"531":[46],"542":[46],"543":[46],"549":[46],"556":[23,24,46],"559":[46],"560":[46],"582":[46],"591":[23,24,46],"604":[46],"628":[46],"640":[46],"649":[46],"694":[46],"698":[46],"706":[23,24,46],"725":[23,24,46],"732":[46],"736":[46],"740":[46],"748":[46]},"packages/frontend/editor-ui/src/features/agents/components/AgentPanel.vue":{"13":[23,24,46],"19":[23,24,46],"32":[23,24,46]},"packages/frontend/editor-ui/src/features/agents/components/AgentPanelHeader.vue":{"18":[23,24,46],"24":[23,24,46],"27":[23,24,46],"28":[23,24,46]},"packages/frontend/editor-ui/src/features/agents/components/AgentPersonalisationIcon.vue":{"8":[24,46],"16":[24,46],"24":[24,46],"34":[24,46],"35":[24,46]},"packages/frontend/editor-ui/src/features/agents/components/AgentPreviewButton.vue":{"33":[23,24],"34":[23,24],"39":[23,24]},"packages/frontend/editor-ui/src/features/agents/components/AgentPreviewChatPage.vue":{"14":[23,24],"55":[24],"68":[23,24],"77":[23,24],"106":[24]},"packages/frontend/editor-ui/src/features/agents/components/AgentPreviewDock.vue":{"32":"b:AAD4AwAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","94":[23,24],"141":[24],"148":[24],"209":[23,24],"240":[23,24],"271":[23,24],"302":[24]},"packages/frontend/editor-ui/src/features/agents/components/AgentPreviewMoreMenu.vue":{"34":[23,24],"63":[23,24],"67":[23,24],"120":[24],"130":[24],"209":[24],"250":[23,24],"272":[24],"278":[23,24],"284":[23,24],"298":[23,24],"308":[24],"318":[24]},"packages/frontend/editor-ui/src/features/agents/components/AgentPublishButton.vue":{"14":[23,24],"53":[23,24],"62":[23,24],"65":[23,24],"69":[23,24],"96":[23,24],"105":[23,24],"107":[23,24],"172":[23,24],"182":[23,24],"190":[23,24],"214":[23,24]},"packages/frontend/editor-ui/src/features/agents/components/AgentSchedulesRow.vue":{"15":[23,24],"57":[23,24],"91":[23,24],"105":[23,24],"202":[23,24],"262":[23,24]},"packages/frontend/editor-ui/src/features/agents/components/AgentSessionHistoryDropdown.vue":{"19":[23,24],"45":[23,24],"61":[23,24],"72":[23,24],"89":[23,24]},"packages/frontend/editor-ui/src/features/agents/components/AgentSetupTasks/AgentSetupTasks.vue":{"10":[23,24],"25":[23,24],"40":[23,24],"42":[23,24],"43":[23,24],"46":[23,24],"47":[23,24],"50":[23,24],"56":[23,24],"57":[23,24],"60":[23,24],"100":[23,24],"115":[23,24],"122":[24],"150":[23,24],"153":[23,24]},"packages/frontend/editor-ui/src/features/agents/components/AgentSetupTasks/agentSetupTasks.registry.ts":{"55":[23,24],"61":[23,24],"67":[23,24],"73":[23,24],"81":[23,24],"85":[23,24],"100":[23,24],"109":[23,24],"119":[23,24],"137":[23,24],"146":[23,24]},"packages/frontend/editor-ui/src/features/agents/components/AgentSetupTasks/useAgentSetupTasks.ts":{"15":[23,24],"16":[23,24],"17":[23,24],"31":[23,24],"32":[23,24],"34":[23,24],"37":[23,24]},"packages/frontend/editor-ui/src/features/agents/components/AgentSkillsSection.vue":{"12":[23,24,46],"36":[46],"37":[46],"38":[46],"40":[23,24,46],"50":[46],"51":[23,24,46],"52":[46],"56":[46],"57":[46],"58":[46],"67":[46],"68":[46]},"packages/frontend/editor-ui/src/features/agents/components/AgentTriggersSection.vue":{"28":[23,24],"86":[23,24],"90":[23,24],"105":[23,24],"106":[23,24],"108":[23,24],"165":[23,24],"191":[23,24],"197":[23,24],"212":[23,24],"268":[23,24],"283":[23,24]},"packages/frontend/editor-ui/src/features/agents/components/AgentTypingIndicator.vue":{"2":[24]},"packages/frontend/editor-ui/src/features/agents/components/AgentValidationTooltip.vue":{"23":[23,24],"245":[23,24],"258":[23,24]},"packages/frontend/editor-ui/src/features/agents/components/AgentWebSearchSection.vue":{"55":[23,24,46],"62":[23,24,46],"68":[46],"85":[23,24,46],"86":[23,24,46],"87":[46],"88":[46],"94":[23,24,46],"121":[23,24,46],"122":[23,24,46],"140":[23,24,46],"157":[23,24,46],"158":[46],"173":[46],"178":[46],"195":[46],"209":[46],"211":[46],"212":[46],"220":[46],"223":[46],"226":[46],"231":[46],"252":[46],"268":[46],"272":[46],"277":[46],"301":[46],"316":[46],"328":[46],"331":[23,24,46],"340":[23,24,46],"343":[23,24,46],"356":[23,24,46],"358":[23,24,46],"377":[46],"380":[46],"406":[46],"409":[46],"432":[46],"435":[46],"452":[46],"455":[46]},"packages/frontend/editor-ui/src/features/agents/components/model-selector/ModelSelectorTriggerIcon.vue":{"12":[23,24,46]},"packages/frontend/editor-ui/src/features/agents/components/model-selector/menuItemId.ts":{"5":[23,24,46],"15":[46]},"packages/frontend/editor-ui/src/features/agents/composables/agentTelemetry.utils.ts":{"102":[24]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentApi.ts":{"44":[46],"48":[46],"68":[24,46],"80":[46],"108":[23,24,46],"121":[46],"129":[46],"155":[46],"180":[46],"194":[46],"217":[46],"229":[46],"242":[23,24,46],"263":[23,24,25,46],"275":[46],"303":[46],"320":[46],"330":[46],"338":[46],"350":[46],"369":[46],"382":[46],"401":[46],"424":[46],"440":[23,24,46],"452":[46],"464":[23,24,46],"476":[46],"490":[46],"505":[46],"541":[23,24,46],"552":[46],"566":[46],"580":[46],"592":[46],"604":[46],"618":[46],"632":[46],"644":[23,24,25,46],"662":[23,24,46],"674":[46],"686":[46],"701":[46],"715":[46],"731":[24,46],"745":[46],"761":[46],"775":[24,46],"789":[46],"806":[46],"823":[46],"838":[46],"855":[24,46],"870":[46],"879":[46],"891":[46],"903":[46],"917":[46],"945":[46],"958":[23,24,46],"969":[23,24,46]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentBackgroundJobs.ts":{"32":[24],"38":[24],"49":[24],"58":[24],"63":[24],"76":[24],"121":[24],"128":[24],"185":[24],"197":[24],"198":[24],"199":[24],"213":[24],"224":[24]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentBuilderMainTabs.ts":{"21":[23,24],"43":[23,24],"65":[23,24],"77":[23,24],"100":[23,24],"110":[23,24],"111":[23,24]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentBuilderSession.ts":{"46":[23,24,25],"55":[23,24,25],"67":[23,24],"73":[23,24],"77":[23,24,25],"83":[24],"98":[24],"109":[24],"131":[23,24,25],"139":[23,24,25],"149":[23,24,25],"170":[24,25],"188":[23,24,25],"195":[23,24],"203":[23,24],"208":[23,24],"214":[23,24],"215":[23,24],"220":[23,24],"237":[23,24,25]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentBuilderTelemetry.ts":{"39":[23,24],"65":[23,24],"128":[23,24]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentCapabilityIssueMessages.ts":{"9":[23,24,46],"14":[46],"20":[46],"24":[46],"27":[46],"38":[46]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentChannelRemoval.ts":{"14":[23,24],"38":[23]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentChatStream.ts":{"115":[24],"158":[24],"186":[24],"215":[24],"222":[24],"235":[24],"313":[24],"354":[24],"513":[24],"538":[24]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentConfigAutosave.ts":{"51":[23,24],"84":[23,24],"219":[23,24],"232":[23,24],"273":[23,24],"295":[23,24]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentConfigValidation.ts":{"13":[23,24],"20":[23,24],"29":[23,24],"45":[23,24]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentExecutionUpdates.ts":{"20":[24,25],"27":[24],"61":[24]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentIntegrationStatus.ts":{"61":[23,24],"101":[23,24],"156":[23,24],"166":[23,24],"170":[23,24],"177":[23,24]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentIntegrationsCatalog.ts":{"9":[23,24],"12":[23,24],"15":[23,24],"28":[23,24]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentModelCredentials.ts":{"16":[46],"34":[23,24,46],"42":[23,24,46],"44":[46],"57":[23,24,46],"62":[23,24,46],"66":[23,24,46],"80":[46],"85":[23,24,46],"100":[46],"112":[46],"116":[23,24,46],"118":[23,24,46]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentProjectBreadcrumb.ts":{"7":[23,24,25],"11":[23,24,25],"18":[23,24,25],"23":[23,24,25]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentProjectId.ts":{"14":[23,24,46],"20":[23,24,46]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentPublish.ts":{"16":[23,24]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentSessionLangSmithExport.ts":{"18":[23,24,25],"26":[23,24,25]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentThreadsApi.ts":{"49":[23,24,25],"122":[23,24,25],"125":[23,24,25],"150":[24,25]},"packages/frontend/editor-ui/src/features/agents/composables/useFixWithAssistantCalloutDismissal.ts":{"18":[24],"26":[24],"43":[24],"60":[23,24],"64":[23,24]},"packages/frontend/editor-ui/src/features/agents/composables/useModelCatalog.ts":{"38":[23,24,46],"46":[46],"60":[23,24,46],"64":[46],"70":[23,24,46],"74":[23,24,46],"82":[23,24,46],"85":[46],"88":[23,24,46],"97":[46],"100":[46],"109":[46],"120":[46],"135":[46],"142":[46],"147":[46],"155":[23,24,46],"182":[46],"183":[46],"191":[46],"205":[46]},"packages/frontend/editor-ui/src/features/agents/composables/useProjectAgentsList.ts":{"19":[23,24,46],"28":[23,24,25,46],"30":[23,24,46],"35":[23,24,46],"42":[23,24,46],"47":[46],"55":[46],"66":[23,24,46],"72":[46],"78":[46],"81":[46],"87":[46]},"packages/frontend/editor-ui/src/features/agents/model-providers.ts":{"65":[23,24,46]},"packages/frontend/editor-ui/src/features/agents/stores/agentCollaboration.store.ts":{"25":[23,24],"50":[23,24],"55":[23],"63":[23,24],"68":[23,24],"70":[23,24],"85":[23,24],"99":[23,24],"106":[23,24],"111":[23],"138":[23],"168":[23],"193":[23,24],"200":[23,24],"264":[23,24],"267":[23],"276":[23,24],"311":[23,24]},"packages/frontend/editor-ui/src/features/agents/utils/agent-plan.ts":{"94":[24],"181":[24]},"packages/frontend/editor-ui/src/features/agents/utils/agentSectionEditor.utils.ts":{"7":[23,24],"8":[23,24]},"packages/frontend/editor-ui/src/features/agents/utils/errors.ts":{"10":[24]},"packages/frontend/editor-ui/src/features/agents/utils/model-string.ts":{"15":[23,24,46],"22":[23,24,46],"31":[23,24,46],"44":[46]},"packages/frontend/editor-ui/src/features/agents/utils/nativeWebSearch.ts":{"17":[46],"23":[46],"34":[46],"43":[23,24,46],"49":[46],"58":[46],"59":[46],"65":[46],"94":[46],"138":[46]},"packages/frontend/editor-ui/src/features/agents/utils/relative-time.ts":{"102":[24]},"packages/frontend/editor-ui/src/features/agents/utils/validationIssues.ts":{"7":[23,24,46],"12":[23,24,46],"13":[23,24,46]},"packages/frontend/editor-ui/src/features/agents/views/AgentBuilderView.vue":{"246":[23,24],"254":[23,24],"255":[23,24],"258":[23,24],"265":[23,24],"269":[23,24],"273":[23,24],"283":[23,24],"287":[23,24],"291":[23,24],"303":[23,24],"317":[23,24],"318":[23,24],"328":[23,24],"332":[23,24],"340":[23,24],"371":[23,24],"376":[23,24],"487":[23,24],"533":[23,24],"550":[24],"592":[23,24],"607":[23,24],"617":[23,24],"618":[23,24],"635":[23,24],"642":[23,24],"643":[23,24],"772":[23,24],"794":[23,24],"801":[23,24],"804":[23,24],"823":[23,24],"885":[23,24],"888":[23,24],"894":[23,24],"918":[23,24],"921":[23,24],"931":[23,24],"947":[23,24],"975":[23,24],"989":[23,24],"1270":[24],"1275":[24],"1284":[23,24],"1611":[23,24],"1660":[23,24],"1691":[23],"1785":[24],"1875":[23],"2155":[23,24],"2239":[23,24],"2283":[23],"2302":[23,24],"2322":[23,24],"2339":[23,24],"2359":[23,24],"2615":[23,24],"2622":[23,24],"2628":[23,24],"2765":[23,24],"2772":[23,24],"2776":[23,24],"2841":[23,24],"2903":[23,24],"2911":[23,24],"2920":[24],"2966":[23,24],"2975":[23,24],"2983":[24],"3041":[24],"3113":[23,24],"3133":[23,24],"3143":[23,24]},"packages/frontend/editor-ui/src/features/agents/views/AgentView.vue":{"22":[23,24,25],"26":[23,24,25]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/composables/useAgentEvalsFlag.ts":{"21":"b:AAD4AQAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","24":"b:AAD4AQAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/shared/agentsChat/displayGroups.ts":{"80":[24],"84":[24],"205":[24]},"packages/frontend/editor-ui/src/features/ai/shared/agentsChat/messageMappers.ts":{"102":[24]},"packages/frontend/editor-ui/src/features/ai/shared/components/ChatHistoryDropdown.vue":{"17":"b:AAD4AQAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","70":"b:AAD4AQAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","85":"b:AAD4AQAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","112":"b:AAB4AAAABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","119":"b:AAD4AQAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","120":[116,118,119,120],"143":[19,20,117,48,118,119,49,120,22,50,121],"148":[120],"155":[120],"172":[21,120],"198":[120],"203":"b:AAD4AQAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","221":[120],"226":"b:AAD4AQAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","232":[120],"239":[120],"252":[120],"254":[120],"259":[120],"263":[120],"273":[120],"275":[120],"288":[120]},"packages/frontend/editor-ui/src/features/ai/shared/components/ChatHistoryDropdownTrigger.vue":{"10":"b:AAD4AQAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","29":"b:AAD4AQAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/shared/components/ChatInputBase.vue":{"92":"b:AAB4AQAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","133":"b:AAB4AQAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","138":[19,20,117,48,21,118,119,49,120,22,50],"150":[20,119],"151":[20,119],"157":[119],"197":[20,119],"198":[20,119],"201":[20,119],"207":[20,119],"216":[21],"226":[19,20,117,48,118,119,49,120,22,50],"240":"b:AAB4AQAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","287":[19,20,117,48,21,118,119,49,120,22,50],"290":"b:AAB4AQAABwAAAAAAAQDwBwAAAAAAAAAAAAAAAAA=","291":[24,19,20,117,48,118,119,49,120,22,50],"293":"b:AAB4AQAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","297":"b:AAB4AQAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","300":"b:AAB4AQAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","327":"b:AAB4AQAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA="},"packages/modules/mcp/frontend/src/composables/useMcp.ts":{"5":"b:AACAAYDAAF4ACEAJABAACoABAAAAAQDAAAAAAAA=","8":[46],"14":[46],"18":[46],"22":[46],"29":[46,123],"33":[46],"39":[46]},"packages/modules/type-availability-policies/frontend/src/components/ContactInstanceAdminModal.vue":{"18":[23,24,46,73],"26":[23,24,46,73],"31":[46],"37":[46],"38":[46],"45":[23,24,46,73],"51":[46],"57":[46],"59":[23,24,46,73],"70":[46],"77":[46],"80":[46],"82":[46],"94":[46]},"packages/nodes-base/nodes/Webhook/error.ts":{"4":"b:ABIFpHAQZkGIACAGAAAIAEAAAAAAAAJAAwCAAAA="},"packages/@n8n/ai-utilities/src/model-discovery/providers/anthropic.ts":{"5":[4,5,6],"15":[4,5,6],"16":[4,5,6]},"packages/@n8n/ai-utilities/src/utils/log-wrapper.ts":{"38":[0,3,4,5,6],"80":[0,3,4,5,6],"109":[0,3,4,5,6],"127":[0,3,4,5,6],"132":[0,3,4,5,6],"155":[0,3,4,5,6],"184":[0,3,4,5,6],"205":[0,3,4,5,6],"227":[0,3,4,5,6],"271":[0,3,4,5,6],"298":[0,3,4,5,6],"325":[0,3,4,5,6],"355":[0,3,4,5,6],"374":[0,3,4,5,6],"398":[0,3,4,5,6],"422":[0,3,4,5,6],"456":[0,3,4,5,6]},"packages/@n8n/api-types/src/schemas/timezone.schema.ts":{"3":[4,5,6,46,19,20,21,49,22]},"packages/@n8n/backend-common/src/modules/module-registry.ts":{"21":"b:cAB4AAAAAgAAAAAAAQAACAAAAAAAAAAAAMAJAgA=","24":"b:cAB4AAAAAgAAAAAAAQAACAAAAAAAAAAAAMAJAgA=","37":"b:cAB4AAAAAgAAAAAAAQAACAAAAAAAAAAAAMAJAgA=","93":"b:cAB4AAAAAgAAAAAAAQAACAAAAAAAAAAAAMAJAgA=","97":"b:cAB4AAAAAgAAAAAAAQAACAAAAAAAAAAAAMAJAgA=","100":"b:cAB4AAAAAgAAAAAAAQAACAAAAAAAAAAAAMAJAgA=","106":"b:cAB4AAAAAgAAAAAAAQAACAAAAAAAAAAAAMAJAgA=","117":"b:cAB4AAAAAgAAAAAAAQAACAAAAAAAAAAAAMAJAgA=","202":"b:cAB4AAAAAgAAAAAAAQAACAAAAAAAAAAAAMAJAgA=","250":"b:cAB4AAAAAgAAAAAAAQAACAAAAAAAAAAAAMAJAgA=","269":"b:cAB4AAAAAgAAAAAAAQAACAAAAAAAAAAAAMAJAgA=","285":"b:cAB4AAAAAgAAAAAAAQAACAAAAAAAAAAAAMAJAgA=","289":"b:cAB4AAAAAgAAAAAAAQAACAAAAAAAAAAAAMAJAgA="},"packages/@n8n/backend-network/src/http/binary-buffer.ts":{"16":[0,30,110,4,45,215,130,132,169],"20":[0,30,110,4,45,215,130,132,169],"25":[0,30,110,4,45,215,130,132,169],"29":[0,30,110,4,45,215,130,132,169],"32":[0,30,110,4,45,215,130,132,169],"34":[0,30,110,4,45,215,130,132,169],"42":[0,30,110,4,45,215,130,132,169],"46":[0,30,110,4,45,215,130,132,169],"47":[0,30,110,4,45,215,130,132,169],"48":[0,30,110,4,45,215,130,132,169],"58":[0,30,110,4,45,215,130,132,169],"59":[0,30,110,4,45,215,130,132,169],"61":[0,30,110,4,45,215,130,132,169],"81":[0,30,110,4,45,215,130,132,169]},"packages/@n8n/blob-storage/src/fs-byte-store.ts":{"20":[0,34,214,212,4,17,132,56,170],"22":[0,34,214,212,4,17,132,56,170],"26":[0,34,214,212,4,17,132,56,170],"41":[0,34,214,212,4,17,132,56,170],"46":[0,34,214,212,4,17,132,56,170],"56":[0,34,214,212,4,17,132,56,170],"69":[0,34,214,212,4,17,132,56,170],"74":[0,34,214,212,4,17,132,56,170],"80":[0,34,214,212,4,17,132,56,170],"87":[0,34,214,212,4,17,132,56,170],"95":[0,34,214,212,4,17,132,56,170],"96":[0,34,214,212,4,17,132,56,170],"97":[0,34,214,212,4,17,132,56,170],"98":[0,34,214,212,4,17,132,56,170],"99":[0,34,214,212,4,17,132,56,170],"103":[0,34,214,212,4,17,132,56,170],"119":[0,34,214,212,4,17,132,56,170],"132":[0,34,214,212,4,17,132,56,170]},"packages/@n8n/chat-hub/src/artifact.ts":{"3":[4,111,5,112,6,17,46],"19":[4,5,6,46]},"packages/@n8n/chat-hub/src/parser.ts":{"12":[4,111,5,112,6,17,46],"117":[4,111,5,112,6,17,46],"134":[4,111,5,112,6,17,46],"159":[4,5,6,46],"187":[4,5,6,46],"217":[4,5,6,46],"250":[4,111,5,112,6,17,46],"275":[4,5,6]},"packages/@n8n/db/src/repositories/project-secrets-provider-access.repository.ee.ts":{"9":[4,6,65],"12":[4,6,65],"21":[4,6,65],"28":[4,6,65],"35":[4,6,65],"43":[4,6,65],"54":[4,6,65]},"packages/@n8n/db/src/utils/transaction.ts":{"15":[4,5,6,47,114,69]},"packages/@n8n/decorators/src/module/module-metadata.ts":{"17":"b:cAB4AAAAAgAAAAAAAQAACAAAAAAAAAAAAMAJAgA=","20":"b:cAB4AAAAAgAAAAAAAQAACAAAAAAAAAAAAMAJAgA=","24":"b:cAB4AAAAAgAAAAAAAQAACAAAAAAAAAAAAMAJAgA=","28":"b:cAB4AAAAAgAAAAAAAQAACAAAAAAAAAAAAMAJAgA=","32":"b:cAB4AAAAAgAAAAAAAQAACAAAAAAAAAAAAMAJAgA=","33":"b:cAB4AAAAAgAAAAAAAQAACAAAAAAAAAAAAMAJAgA="},"packages/@n8n/nodes-langchain/nodes/llms/LMChatAnthropic/LmChatAnthropic.node.ts":{"100":[8,4,5,6,17,15],"126":[8,4,5,6,17,15],"194":[8,4,5,6,17,15],"557":[8,4,5,6,17,15],"673":[8,4,5,6,17,15],"691":[8,4,5,6,17,15],"709":[8,4,5,6,17,15],"745":[8,4,5,6,17,15]},"packages/@n8n/nodes-langchain/nodes/llms/LMChatAnthropic/methods/searchModels.ts":{"7":[8,4,5,6,15],"23":[8,4,5,6,15],"28":[8,4,5,6,15],"29":[8,4,5,6,15]},"packages/@n8n/nodes-langchain/nodes/memory/MemoryBufferWindow/MemoryBufferWindow.node.ts":{"30":[4,5,6],"34":[4,5,6],"41":[4,5,6],"63":[4,5,6],"75":[4,5,6],"158":[4,5,6]},"packages/@n8n/nodes-langchain/nodes/memory/MemoryManager/MemoryManager.node.ts":{"20":[4,5,6],"47":[4,5,6],"50":[4,5,6],"53":[4,5,6],"63":[4,5,6],"73":[4,5,6],"302":[4,5,6],"400":[4,5,6]},"packages/@n8n/utils/src/files/sanitize-filename.ts":{"55":[4,57]},"packages/cli/src/credentials/credential-connection-status-proxy.ts":{"19":[4,6,17,213,59],"23":[4,6,17,213,59],"31":[4,6,17,213,59],"36":[4,6,17,213,59],"41":[4,6,17,213,59],"50":[4,6,17,213,59]},"packages/cli/src/modules/chat-hub/chat-hub-agent.repository.ts":{"9":[4,5,112,6],"13":[4,5,112,6],"24":[4,5,112,6],"32":[4,5,112,6],"37":[4,5,112,6],"44":[4,5,112,6],"53":[4,5,112,6]},"packages/cli/src/modules/chat-hub/chat-hub-agent.service.ts":{"35":[4,5,112,6,69],"50":[4,5,112,6,69],"53":[4,5,112,6,69],"56":[4,5,112,6,69],"57":[4,5,112,6,69],"76":[4,5,112,6,69],"80":[4,5,112,6,69],"88":[4,5,112,6,69],"95":[4,5,112,6,69],"123":[4,5,112,6,69],"163":[4,5,112,6,69],"182":[4,5,112,6,69],"203":[4,5,112,6,69],"215":[4,5,112,6,69],"230":[4,5,112,6,69],"264":[4,5,112,6,69],"287":[4,5,112,6,69],"309":[4,5,112,6,69],"334":[4,5,112,6,69],"349":[4,5,112,6,69],"360":[4,5,112,6,69],"375":[4,5,112,6,69],"384":[4,5,112,6,69],"394":[4,5,112,6,69],"400":[4,5,112,6,69],"403":[4,5,112,6,69],"418":[4,5,112,6,69],"426":[4,5,112,6,69],"451":[4,5,112,6,69]},"packages/cli/src/modules/chat-hub/chat-hub-credentials.service.ts":{"17":[4,5,112,6,17],"24":[4,5,112,6,17],"37":[4,5,112,6,17],"48":[4,5,112,6,17],"61":[4,5,112,6,17],"70":[4,5,112,6,17],"90":[4,5,112,6,17]},"packages/cli/src/modules/chat-hub/chat-hub-execution.service.ts":{"50":[4,5,112,6,17],"67":[4,5,112,6,17],"78":[4,5,112,6,17],"90":[4,5,112,6,17],"155":[4,5,112,6,17],"206":[4,5,112,6,17],"227":[4,5,112,6,17],"250":[4,5,112,6,17],"253":[4,5,112,6,17],"263":[4,5,112,6,17],"273":[4,5,112,6,17],"302":[4,5,112,6,17],"367":[4,5,112,6,17],"446":[4,5,112,6,17],"488":[4,5,112,6,17],"496":[4,5,112,6,17],"497":[4,5,112,6,17],"498":[4,5,112,6,17],"540":[4,5,112,6,17],"569":[4,5,112,6,17],"609":[4,5,112,6,17],"623":[4,5,112,6,17],"628":[4,5,112,6,17],"630":[4,5,112,6,17],"634":[4,5,112,6,17],"640":[4,5,112,6,17],"652":[4,5,112,6,17],"658":[4,5,112,6,17],"660":[4,5,112,6,17],"661":[4,5,112,6,17],"662":[4,5,112,6,17],"663":[4,5,112,6,17],"666":[4,5,112,6,17],"673":[4,5,112,6,17],"692":[4,5,112,6,17],"713":[4,5,112,6,17],"733":[4,5,112,6,17],"746":[4,5,112,6,17]},"packages/cli/src/modules/chat-hub/chat-hub-extractor.ts":{"33":[4,5,6],"53":[4,5,6],"67":[4,5,6],"73":[4,5,6]},"packages/cli/src/modules/chat-hub/chat-hub-title.service.ts":{"39":[4,5,112,6,17],"53":[4,5,112,6,17],"80":[4,5,112,6,17],"88":[4,5,112,6,17],"124":[4,5,112,6,17],"152":[4,5,112,6,17],"186":[4,5,112,6,17],"259":[4,5,112,6,17],"260":[4,5,112,6,17],"262":[4,5,112,6,17],"272":[4,5,112,6,17]},"packages/cli/src/modules/chat-hub/chat-hub-tool.repository.ts":{"10":[4,5,112,6],"14":[4,5,112,6],"22":[4,5,112,6],"30":[4,5,112,6],"35":[4,5,112,6],"42":[4,5,112,6],"50":[4,5,112,6],"57":[4,5,112,6],"68":[4,5,112,6],"79":[4,5,112,6],"90":[4,5,112,6],"98":[4,5,112,6],"101":[4,5,112,6],"109":[4,5,112,6],"112":[4,5,112,6],"122":[4,5,112,6]},"packages/cli/src/modules/chat-hub/chat-hub-tool.service.ts":{"21":[4,5,112,6],"30":[4,5,112,6],"34":[4,5,112,6],"38":[4,5,112,6],"40":[4,5,112,6],"43":[4,5,112,6],"45":[4,5,112,6],"48":[4,5,112,6],"52":[4,5,112,6],"56":[4,5,112,6],"60":[4,5,112,6],"64":[4,5,112,6],"80":[4,5,112,6],"87":[4,5,112,6],"106":[4,5,112,6],"113":[4,5,112,6],"148":[4,5,112,6],"150":[4,5,112,6],"162":[4,5,112,6]},"packages/cli/src/modules/chat-hub/chat-hub-workflow.service.ts":{"88":[4,5,112,6,17],"105":[4,5,112,6,17],"111":[4,5,112,6,17],"172":[4,5,112,6,17],"196":[4,5,112,6,17],"213":[4,5,112,6,17],"262":[4,5,112,6,17],"285":[4,5,112,6,17],"300":[4,5,112,6,17],"314":[4,5,112,6,17],"330":[4,5,112,6,17],"333":[4,5,112,6,17],"340":[4,5,112,6,17],"341":[4,5,112,6,17],"355":[4,5,112,6,17],"402":[4,5,112,6,17],"418":[4,5,112,6,17],"468":[4,5,112,6,17],"469":[4,5,112,6,17],"532":[4,5,112,6,17],"602":[4,5,112,6,17],"667":[4,5,112,6,17],"679":[4,5,112,6,17],"760":[4,5,112,6,17],"768":[4,5,112,6,17],"794":[4,5,112,6,17],"956":[4,5,112,6,17],"971":[4,5,112,6,17],"993":[4,5,112,6,17],"1063":[4,5,112,6,17],"1123":[4,5,112,6,17],"1134":[4,5,112,6,17],"1148":[4,5,112,6,17],"1164":[4,5,112,6,17],"1165":[4,5,112,6,17],"1172":[4,5,112,6,17],"1197":[4,5,112,6,17],"1210":[4,5,112,6,17],"1245":[4,5,112,6,17],"1248":[4,5,112,6,17],"1259":[4,5,112,6,17],"1270":[4,5,112,6,17],"1328":[4,5,112,6,17],"1345":[4,5,112,6,17],"1374":[4,5,112,6,17],"1385":[4,5,112,6,17],"1401":[4,5,112,6,17],"1472":[4,5,112,6,17],"1486":[4,5,112,6,17],"1500":[4,5,112,6,17],"1530":[4,5,112,6,17],"1560":[4,5,112,6,17],"1568":[4,5,112,6,17],"1571":[4,5,112,6,17],"1625":[4,5,112,6,17],"1634":[4,5,112,6,17],"1638":[4,5,112,6,17],"1643":[4,5,112,6,17],"1656":[4,5,112,6,17],"1665":[4,5,112,6,17],"1683":[4,5,112,6,17],"1690":[4,5,112,6,17],"1719":[4,5,112,6,17],"1745":[4,5,112,6,17],"1866":[4,5,112,6,17],"1911":[4,5,112,6,17]},"packages/cli/src/modules/chat-hub/chat-hub.attachment.service.ts":{"18":[4,5,6],"27":[4,5,6],"54":[4,5,6],"84":[4,5,6],"128":[4,5,6],"131":[4,5,6],"137":[4,5,6],"145":[4,5,6],"151":[4,5,6],"153":[4,5,6],"157":[4,5,6],"169":[4,5,6],"173":[4,5,6],"195":[4,5,6],"196":[4,5,6],"211":[4,5,6]},"packages/cli/src/modules/chat-hub/chat-hub.constants.ts":{"694":[4,5,6],"719":[4,5,6]},"packages/cli/src/modules/chat-hub/chat-hub.controller.ts":{"62":[4,5,112,6],"72":[4,5,112,6],"86":[4,5,112,6],"96":[4,5,112,6],"111":[4,5,112,6],"121":[4,5,112,6],"159":[4,5,112,6],"168":[4,5,112,6],"194":[4,5,112,6],"224":[4,5,112,6],"249":[4,5,112,6],"283":[4,5,112,6],"308":[4,5,112,6],"342":[4,5,112,6],"358":[4,5,112,6],"374":[4,5,112,6],"389":[4,5,112,6],"401":[4,5,112,6],"403":[4,5,112,6],"408":[4,5,112,6],"420":[4,5,112,6],"435":[4,5,112,6],"446":[4,5,112,6],"452":[4,5,112,6],"462":[4,5,112,6],"473":[4,5,112,6],"487":[4,5,112,6],"510":[4,5,112,6],"520":[4,5,112,6]},"packages/cli/src/modules/chat-hub/chat-hub.models.service.ts":{"32":[4,5,6,17],"41":[4,5,6,17],"54":[4,5,6,17],"64":[4,5,6,17],"90":[4,5,6,17],"98":[4,5,6,17],"172":[4,5,6,17],"188":[4,5,6,17],"204":[4,5,6,17],"256":[4,5,6,17],"301":[4,5,6,17],"311":[4,5,6,17],"318":[4,5,6,17],"335":[4,5,6,17],"384":[4,5,6,17],"433":[4,5,6,17],"477":[4,5,6,17],"520":[4,5,6,17],"563":[4,5,6,17],"606":[4,5,6,17],"649":[4,5,6,17],"692":[4,5,6,17],"704":[4,5,6,17],"706":[4,5,6,17],"726":[4,5,6,17],"735":[4,5,6,17],"736":[4,5,6,17],"743":[4,5,6,17],"751":[4,5,6,17],"797":[4,5,6,17],"802":[4,5,6,17],"803":[4,5,6,17],"807":[4,5,6,17],"808":[4,5,6,17],"817":[4,5,6,17],"823":[4,5,6,17]},"packages/cli/src/modules/chat-hub/chat-hub.service.ts":{"56":[4,5,6,17],"77":[4,5,6,17],"88":[4,5,6,17],"114":[4,5,6,17],"179":[4,5,6,17],"203":[4,5,6,17],"210":[4,5,6,17],"214":[4,5,6,17],"241":[4,5,6,17],"249":[4,5,6,17],"265":[4,5,6,17],"278":[4,5,6,17],"287":[4,5,6,17],"297":[4,5,6,17],"309":[4,5,6,17],"317":[4,5,6,17],"334":[4,5,6,17],"338":[4,5,6,17],"347":[4,5,6,17],"391":[4,5,6,17],"392":[4,5,6,17],"399":[4,5,6,17],"438":[4,5,6,17],"452":[4,5,6,17],"476":[4,5,6,17],"490":[4,5,6,17],"522":[4,5,6,17],"566":[4,5,6,17],"603":[4,5,6,17],"631":[4,5,6,17],"644":[4,5,6,17],"723":[4,5,6,17],"761":[4,5,6,17],"776":[4,5,6,17],"789":[4,5,6,17],"795":[4,5,6,17],"868":[4,5,6,17],"894":[4,5,6,17],"914":[4,5,6,17],"927":[4,5,6,17],"933":[4,5,6,17],"1022":[4,5,6,17],"1049":[4,5,6,17],"1058":[4,5,6,17],"1070":[4,5,6,17],"1073":[4,5,6,17],"1129":[4,5,6,17],"1143":[4,5,6,17],"1155":[4,5,6,17],"1158":[4,5,6,17],"1217":[4,5,6,17],"1244":[4,5,6,17],"1287":[4,5,6,17],"1307":[4,5,6,17],"1314":[4,5,6,17]},"packages/cli/src/modules/chat-hub/chat-hub.settings.controller.ts":{"18":[4,5,113,6],"27":[4,5,113,6],"39":[4,5,113,6],"46":[4,5,113,6],"61":[4,5,113,6],"75":[4,5,113,6],"88":[4,5,113,6]},"packages/cli/src/modules/chat-hub/chat-hub.settings.service.ts":{"21":[4,5,112,113,6,69],"26":[4,5,112,113,6,69],"37":[4,5,112,113,6,69],"39":[4,5,112,113,6,69],"48":[4,5,112,113,6,69],"55":[4,5,112,113,6,69],"68":[4,5,112,113,6,69],"76":[4,5,112,113,6,69],"93":[4,5,112,113,6,69],"115":[4,5,112,113,6,69],"125":[4,5,112,113,6,69],"141":[4,5,112,113,6,69],"152":[4,5,112,113,6,69]},"packages/cli/src/modules/chat-hub/chat-message.repository.ts":{"19":[4,5,6],"27":[4,5,6],"40":[4,5,6],"50":[4,5,6],"76":[4,5,6],"110":[4,5,6],"119":[4,5,6],"124":[4,5,6],"132":[4,5,6]},"packages/cli/src/modules/chat-hub/chat-session.repository.ts":{"11":[4,5,6],"15":[4,5,6],"27":[4,5,6],"32":[4,5,6],"37":[4,5,6],"73":[4,5,6],"78":[4,5,6],"92":[4,5,6]},"packages/cli/src/modules/chat-hub/chat-stream-state.service.ts":{"68":[4,5,6],"89":[4,5,6],"115":[4,5,6],"131":[4,5,6],"151":[4,5,6],"177":[4,5,6],"187":[4,5,6],"205":[4,5,6],"233":[4,5,6],"245":[4,5,6],"251":[4,5,6],"268":[4,5,6],"283":[4,5,6],"287":[4,5,6],"291":[4,5,6],"304":[4,5,6],"319":[4,5,6],"329":[4,5,6],"342":[4,5,6],"357":[4,5,6],"367":[4,5,6],"370":[4,5,6],"380":[4,5,6]},"packages/cli/src/modules/chat-hub/chat-stream.service.ts":{"52":[4,5,6,17],"66":[4,5,6,17],"100":[4,5,6,17],"137":[4,5,6,17],"162":[4,5,6,17],"198":[4,5,6,17],"235":[4,5,6,17],"272":[4,5,6,17],"308":[4,5,6,17],"318":[4,5,6,17],"326":[4,5,6,17],"335":[4,5,6,17],"435":[4,5,6,17],"454":[4,5,6,17],"461":[4,5,6,17],"501":[4,5,6,17],"531":[4,5,6,17],"561":[4,5,6,17],"588":[4,5,6,17],"616":[4,5,6,17],"643":[4,5,6,17]},"packages/cli/src/modules/chat-hub/context-limits.ts":{"223":[4,5,6]},"packages/cli/src/modules/chat-hub/stream-capturer.ts":{"13":[4,5,6],"23":[4,5,6],"32":[4,5,6],"43":[4,5,6],"44":[4,5,6],"53":[4,5,6],"67":[4,5,6],"72":[4,5,6],"96":[4,5,6],"112":[4,5,6],"124":[4,5,6],"142":[4,5,6],"151":[4,5,6],"204":[4,5,6]},"packages/cli/src/modules/dynamic-credentials.ee/services/credential-connection-status.service.ts":{"34":[4,6,17,213,59],"50":[4,6,17,213,59],"61":[4,6,17,213,59],"79":[4,6,17,213,59],"101":[4,6,17,213,59],"126":[4,6,17,213,59],"136":[4,6,17,213,59],"140":[4,6,17,213,59],"145":[4,6,17,213,59],"163":[4,6,17,213,59],"172":[4,6,17,213,59],"183":[4,6,17,213,59],"193":[4,6,17,213,59],"196":[4,6,17,213,59],"201":[4,6,17,213,59],"204":[4,6,17,213,59],"206":[4,6,17,213,59],"211":[4,6,17,213,59],"215":[4,6,17,213,59],"219":[4,6,17,213,59],"241":[4,6,17,213,59],"260":[4,6,17,213,59],"266":[4,6,17,213,59]},"packages/cli/src/modules/favorites/favorites.event-relay.ts":{"10":[26,8,4,6,17,114,136,184,190],"17":[26,8,4,6,17,114,136,184,190],"19":[26,8,4,6,17,114,136,184,190],"21":[26,8,4,6,17,114,136,184,190],"23":[26,8,4,6,17,114,136,184,190],"25":[26,8,4,6,17,114,136,184,190],"27":[26,8,4,6,17,114,136,184,190]},"packages/cli/src/requests.ts":{"54":"b:cAJqIIDpA15CCcAJHBgECIAAgIAAAABIACAAAAA=","63":"b:cAJqIIDpA15CCcAJHBgECIAAgIAAAABIACAAAAA=","66":"b:cAJqIIDpA15CCcAJHBgECIAAgIAAAABIACAAAAA="},"packages/cli/src/webhooks/streaming-webhook-response-heartbeat.ts":{"21":[4,5,6],"22":[4,5,6],"34":[4,5,6]},"packages/core/src/binary-data/blob.manager.ts":{"21":[0,34,214,212,4,17,132,56,170],"39":[0,34,214,212,4,17,132,56,170],"44":[0,34,214,212,4,17,132,56,170],"48":[0,34,214,212,4,17,132,56,170],"59":[0,34,214,212,4,17,132,56,170],"63":[0,34,214,212,4,17,132,56,170],"69":[0,34,214,212,4,17,132,56,170],"75":[0,34,214,212,4,17,132,56,170],"87":[0,34,214,212,4,17,132,56,170],"93":[0,34,214,212,4,17,132,56,170],"94":[0,34,214,212,4,17,132,56,170],"112":[0,34,214,212,4,17,132,56,170],"130":[0,34,214,212,4,17,132,56,170],"142":[0,34,214,212,4,17,132,56,170],"151":[0,34,214,212,4,17,132,56,170],"155":[0,34,214,212,4,17,132,56,170],"168":[0,34,214,212,4,17,132,56,170],"185":[0,34,214,212,4,17,132,56,170],"186":[0,34,214,212,4,17,132,56,170],"191":[0,34,214,212,4,17,132,56,170],"196":[0,34,214,212,4,17,132,56,170],"199":[0,34,214,212,4,17,132,56,170],"204":[0,34,214,212,4,17,132,56,170],"214":[0,34,214,212,4,17,132,56,170],"219":[0,34,214,212,4,17,132,56,170]},"packages/nodes-base/nodes/Merge/Merge.node.ts":{"9":[4,5,6,77,170,15]},"packages/nodes-base/nodes/Merge/v1/MergeV1.node.ts":{"20":[4,5,6,77,170,15],"205":[4,5,6,77,170,15]},"packages/nodes-base/nodes/Merge/v2/MergeV2.node.ts":{"35":[4,5,6,77,170,15],"293":[4,5,6,77,170,15],"459":[4,5,6,77,170,15],"467":[4,5,6,77,170,15],"520":[4,5,6,77,170,15],"603":[4,5,6,77,170,15],"604":[4,5,6,77,170,15]},"packages/nodes-base/nodes/Merge/v2/utils.ts":{"31":[4,5,6,77,170,15],"32":[4,5,6,77,170,15],"34":[4,5,6,77,170,15],"41":[4,5,6,77,170,15],"47":[4,5,6,77,170,15],"72":[4,5,6,77,170,15],"78":[4,5,6,77,170,15],"103":[4,5,6,77,170,15],"128":[4,5,6,77,170,15],"150":[4,5,6,77,170,15],"151":[4,5,6,77,170,15],"159":[4,5,6,77,170,15],"176":[4,5,6,77,170,15],"187":[4,5,6,77,170,15],"191":[4,5,6,77,170,15],"197":[4,5,6,77,170,15],"203":[4,5,6,77,170,15],"210":[4,5,6,77,170,15],"213":[4,5,6,77,170,15],"216":[4,5,6,77,170,15],"219":[4,5,6,77,170,15],"243":[4,5,6,77,170,15],"246":[4,5,6,77,170,15],"250":[4,5,6,77,170,15],"268":[4,5,6,77,170,15],"273":[4,5,6,77,170,15],"279":[4,5,6,77,170,15],"285":[4,5,6,77,170,15],"288":[4,5,6,77,170,15],"292":[4,5,6,77,170,15],"307":[4,5,6,77,170,15],"327":[4,5,6,77,170,15],"334":[4,5,6,77,170,15],"349":[4,5,6,77,170,15],"350":[4,5,6,77,170,15]},"packages/nodes-base/nodes/Merge/v3/MergeV3.node.ts":{"15":[4,5,6,77,170,15],"26":[4,5,6,77,170,15]},"packages/nodes-base/nodes/Merge/v3/actions/mode/append.ts":{"21":[4,5,6,77,170,15]},"packages/nodes-base/nodes/Merge/v3/actions/mode/chooseBranch.ts":{"73":[4,5,6,77,170,15],"98":[4,5,6,77,170,15],"99":[4,5,6,77,170,15]},"packages/nodes-base/nodes/Merge/v3/actions/mode/combineAll.ts":{"35":[4,5,6,77,170,15]},"packages/nodes-base/nodes/Merge/v3/actions/mode/combineByFields.ts":{"261":[4,5,6,77,170,15],"274":[4,5,6,77,170,15],"297":[4,5,6,77,170,15],"305":[4,5,6,77,170,15],"358":[4,5,6,77,170,15]},"packages/nodes-base/nodes/Merge/v3/actions/mode/combineByPosition.ts":{"49":[4,5,6,77,170,15],"80":[4,5,6,77,170,15],"82":[4,5,6,77,170,15],"95":[4,5,6,77,170,15],"100":[4,5,6,77,170,15],"106":[4,5,6,77,170,15],"110":[4,5,6,77,170,15],"112":[4,5,6,77,170,15]},"packages/nodes-base/nodes/Merge/v3/actions/mode/combineBySql.ts":{"104":[4,5,6,77,170,15],"125":[4,5,6,77,170,15],"131":[4,5,6,77,170,15],"152":[4,5,6,77,170,15],"158":[4,5,6,77,170,15],"167":[4,5,6,77,170,15],"170":[4,5,6,77,170,15],"179":[4,5,6,77,170,15],"180":[4,5,6,77,170,15],"208":[4,5,6,77,170,15],"255":[4,5,6,77,170,15],"270":[4,5,6,77,170,15],"271":[4,5,6,77,170,15],"272":[4,5,6,77,170,15],"289":[4,5,6,77,170,15],"290":[4,5,6,77,170,15],"300":[4,5,6,77,170,15]},"packages/nodes-base/nodes/Merge/v3/actions/router.ts":{"7":[4,5,6,77,170,15]},"packages/nodes-base/nodes/Merge/v3/helpers/sandbox-utils.ts":{"13":[4,5,6,77,170,15],"29":[4,5,6,77,170,15],"41":[4,5,6,77,170,15],"49":[4,5,6,77,170,15],"100":[4,5,6,77,170,15],"120":[4,5,6,77,170,15],"135":[4,5,6,77,170,15],"156":[4,5,6,77,170,15],"181":[4,5,6,77,170,15]},"packages/nodes-base/nodes/Merge/v3/helpers/utils.ts":{"33":[4,5,6,77,170,15],"34":[4,5,6,77,170,15],"36":[4,5,6,77,170,15],"43":[4,5,6,77,170,15],"49":[4,5,6,77,170,15],"74":[4,5,6,77,170,15],"80":[4,5,6,77,170,15],"105":[4,5,6,77,170,15],"130":[4,5,6,77,170,15],"152":[4,5,6,77,170,15],"153":[4,5,6,77,170,15],"161":[4,5,6,77,170,15],"178":[4,5,6,77,170,15],"189":[4,5,6,77,170,15],"193":[4,5,6,77,170,15],"199":[4,5,6,77,170,15],"205":[4,5,6,77,170,15],"212":[4,5,6,77,170,15],"215":[4,5,6,77,170,15],"218":[4,5,6,77,170,15],"221":[4,5,6,77,170,15],"245":[4,5,6,77,170,15],"248":[4,5,6,77,170,15],"252":[4,5,6,77,170,15],"270":[4,5,6,77,170,15],"275":[4,5,6,77,170,15],"281":[4,5,6,77,170,15],"287":[4,5,6,77,170,15],"290":[4,5,6,77,170,15],"294":[4,5,6,77,170,15],"309":[4,5,6,77,170,15],"329":[4,5,6,77,170,15],"336":[4,5,6,77,170,15],"351":[4,5,6,77,170,15],"352":[4,5,6,77,170,15],"364":[4,5,6,77,170,15],"365":[4,5,6,77,170,15],"371":[4,5,6,77,170,15],"375":[4,5,6,77,170,15],"389":[4,5,6,77,170,15],"406":[4,5,6,77,170,15]},"packages/nodes-base/nodes/Merge/v3/methods/loadOptions.ts":{"3":[4,5,6,77,170,15],"36":[4,5,6,77,170,15]},"localhost-38757/assets/index-Dv_brJ4-.js":{"3":[4,111,112,113,17]},"localhost-38757/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[4,111,112,113,17],"9":[4,111,112,113,17],"10":[4,111,112,113,17],"19":[4,111,112,113,17],"23":[4,111,112,113,17],"29":[4,111,112,113,17],"33":[4,111,112,113,17],"34":[4,111,112,113,17]},"packages/@n8n/utils/src/retry.ts":{"15":[4,111,5,112,6,17,46,170,18],"46":[4,111,5,112,6,17,46]},"packages/frontend/@n8n/chat/src/components/ChatFile.vue":{"28":[4,20,119],"33":[4]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/filled-square.svg":{"10":"b:cABa+AJABwAAAAAAAIChBQAAAAAAAAAAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nLogo/Logo.vue":{"8":"b:cAACAABBABgAAACJEJgFAAAAAAAAAAAAAAAAAAA=","24":"b:cAACAABBABgAAACJEJgFAAAAAAAAAAAAAAAAAAA=","30":"b:cAACAABBABgAAACJEJgFAAAAAAAAAAAAAAAAAAA=","42":"b:cAACAABBABgAAACJEJgFAAAAAAAAAAAAAAAAAAA=","57":"b:cAACAABBABgAAACJEJgFAAAAAAAAAAAAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nLogo/logo-icon.svg":{"11":"b:cAACAABBABgAAACJEJgFAAAAAAAAAAAAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nLogo/logo-text.svg":{"11":"b:cAACAABBABgAAACJEJgFAAAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/app/layouts/ChatLayout.vue":{"8":[4,111,5,112,6,17],"10":[4,111,5,112,6,17]},"packages/frontend/editor-ui/src/app/utils/fileUtils.ts":{"4":[4,46,20,119],"10":[46],"19":[4,46,20,119],"26":[46],"27":[46],"31":[4,46,20,119],"33":[4,46,20,119],"34":[4,46,20,119],"46":[46]},"packages/frontend/editor-ui/src/app/utils/rbac/checks/hasRole.ts":{"5":[4,111,5,112,113,6,17,46]},"packages/frontend/editor-ui/src/features/ai/chatHub/ChatView.vue":{"76":[4,111,5,112,6,17],"84":[4,111,5,112,6,17],"91":[4,111,5,112,6,17],"94":[4,111,5,112,6,17],"96":[4,111,5,112,6,17],"99":[4,111,5,112,6,17],"101":[4,111,5,112,6,17],"106":[4,111,5,112,6,17],"108":[4,111,5,112,6,17],"134":[4],"141":[4,111,5,112,6,17],"146":[4,111,5,112,6,17],"150":[4,111,5,112,6,17],"182":[4,111,5,112,6,17],"214":[4,111,5,112,6,17],"218":[4,111,5,112,6,17],"225":[4,111,5,112,6],"236":[6],"245":[4,111,5,112,6,17],"253":[4,111,5,112,6,17],"258":[4,111,5,112,6,17],"267":[4,111,5,112,6,17],"293":[4,111,5,112,6,17],"308":[4,111,5,112,6,17],"323":[4,111,5,112,6,17],"335":[4,111,5,112,6,17],"363":[4,111,5,112,6,17],"364":[4,111,5,112,6,17],"382":[4,111,5,112,6,17],"400":[4,111,5,112,6,17],"408":[4,111,5,112,6,17],"417":[4,111,5,112,6,17],"428":[4,111,5,112,6,17],"448":[4,111,5,112,6,17],"464":[4,111,5,112,6,17],"472":[4,111,5,112,6,17],"483":[4,111,5,112,6,17],"576":[4,111,5,112,6],"600":[4,111,5,112,6],"628":[112],"706":[4,111,5,112,6,17],"735":[4,111,5,112,6,17],"747":[4,111,5,112,6,17]},"packages/frontend/editor-ui/src/features/ai/chatHub/chat.api.ts":{"32":[4,111,5,112,113,6,17,46],"44":[4,111,5,112,6,17,46],"62":[46],"79":[46],"99":[46],"120":[46],"140":[46],"160":[4,111,5,112,6,17,46],"174":[46],"183":[4,111,5,112,6,17,46],"202":[46],"216":[46],"224":[46],"232":[4,111,5,112,6,17,46],"240":[112,46],"248":[112,46],"256":[112,46],"265":[112,46],"270":[46],"287":[46],"299":[113,46],"309":[113,46],"322":[113,46],"333":[46],"342":[46],"349":[4,46],"362":[17,46],"377":[46],"392":[46],"404":[4,111,5,112,6,17,46],"408":[6,46],"415":[46],"428":[46]},"packages/frontend/editor-ui/src/features/ai/chatHub/chat.types.ts":{"114":[4]},"packages/frontend/editor-ui/src/features/ai/chatHub/chat.utils.ts":{"25":"b:cAB6AABABwAAAAAAAIDxBQAAAAAAAAAAAAAAAAA=","46":[4,111,5,112,6,17,46],"64":[4,111,5,112,6,17,46],"71":[4,111,112,17,46],"82":[112,17,46],"110":[4,111,5,112,6,17,46],"122":[4,111,5,112,6,17,46],"158":[112,17,46],"167":[46],"171":[46],"196":[4,111,5,112,6,17,46],"200":[111,5,112,46],"215":[4,111,5,112,6,17,46],"227":[4,111,5,112,6,17,46],"280":[4,111,5,112,6,17,46],"331":[4,111,5,112,6,17,46],"335":[4,111,5,112,6,17,46],"341":[4,111,5,112,6,17,46],"348":[17,46],"352":[4,111,5,112,6,46],"361":[4,111,5,112,6,46],"381":[4,111,5,112,6,17,46],"412":[4,111,5,112,46],"442":[4,111,5,112,6,17,46],"446":[4,111,5,112,6,17,46],"460":[4,111,5,112,6,17,46],"470":[4,111,5,112,6,17,46],"563":[4,111,5,112,6,17,46],"568":[46],"571":[46]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatAgentAvatar.vue":{"22":[4,111,5,112,6]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatConversationHeader.vue":{"47":[4,111,5,112,6,17],"65":[4,111,5,112,6,17],"67":[4,111,5,112,6,17],"85":[4,111,5,112,6,17]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatGreetings.vue":{"22":[4,111,5,112,6,17],"38":[112,17]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatMessage.vue":{"68":[4,111,5,112,6,17],"96":[4,111,5,112,6,17],"116":[4,111,5,112,6,17],"117":[4,111,5,112,6,17],"144":[4,111,5,112,6,17],"149":[4,111,5,112,6,17],"150":[4,111,5,112,6,17],"159":[4,111,5,112,6,17],"169":[4,111,5,112,6,17],"170":[4],"188":[4,111,5,112,6,17],"190":[4,111,5,112,6,17],"198":[4,111,5,112,6,17],"295":[4,111,5,112,6,17],"296":[4,111,5,112,6,17],"307":[4,111,5,112,6,17],"317":[4,111,5,112,6,17],"320":[4,111,5,112,6,17],"410":[4],"422":[4,111,5,112,6,17]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatMessageActions.vue":{"13":[4,111,5,112,6,17],"35":[4,111,5,112,6,17],"37":[4,111,5,112,6,17],"52":[4,111,5,112,6,17],"53":[4,111,5,112,6,17],"65":[4,111,5,112,6,17]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatPrompt.vue":{"18":[4,111,5,112,6,17],"59":[4,111,5,112,6,17],"71":[4,111,5,112,6,17],"75":[4,111,5,112,6,17],"79":[4,111,5,112,6,17],"81":[4,111,5,112,6,17],"82":[4,111,5,112,6,17],"104":[4],"150":[4,111,5,112,6,17],"211":[4,111,5,112,6,17],"212":[4,111,5,112,6,17],"228":[4,111,5,112,6,17],"289":[4,111,5,112,6,17]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatPromptCallouts.vue":{"19":[4,111,5,112,6,17],"35":[4,111,112],"45":[4,111,112]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatPromptFull.vue":{"10":[4,111,5,112,6,17],"55":[4],"71":[4,111,5,112,6,17],"75":[4,111,5,112,6,17],"87":[4,111,5,112,6,17],"103":[4,111,5,112,6,17],"112":[4,111,5,112,6,17],"125":[4,111,5,112,6,17]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatSessionMenuItem.vue":{"20":[4,111,5,112,6,17],"34":[4,111,5,112,6,17],"44":[4,111,5,112,6,17],"87":[4,111,5,112,6,17],"89":[4,111,5,112,6,17],"101":[4,111,5,112,6,17],"122":[4,111,5,112,6,17]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatSidebar.vue":{"19":[4,111,5,112,6,17],"49":[4,111,5,112,6,17],"59":[4,111,5,112,6,17],"60":[4,111,5,112,6,17],"69":[4,111,5,112,6,17]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatSidebarContent.vue":{"25":[4,111,5,112,6,17],"32":[4,111,5,112,6,17],"39":[4,111,5,112,6,17],"43":[4,111,5,112,6,17],"45":[4,111,5,112,6,17],"57":[4,111,5,112,6,17],"69":[4,111,5,112,6,17],"80":[4,111,5,112,6,17],"138":[4,111,5,112,6,17],"141":[4,111,5,112,6,17],"156":[4,111,5,112,6,17],"176":[4,111,5,112,6,17],"181":[4,111,5,112,6,17],"184":[4,111,5,112,6,17],"195":[4,111,5,112,6,17],"199":[4,111,5,112,6,17]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatSidebarLink.vue":{"25":[4,111,5,112,6,17],"44":[4,111,5,112,6,17],"61":[4,111,5,112,6,17]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatStarter.vue":{"36":[4,111,5,112,6,17],"38":[6],"42":[111,6],"46":[111,6],"47":[6],"49":[111,6],"59":[4,111,5,112,6,17],"67":[111,6],"80":[111,6],"97":[111,6],"111":[111,6],"133":[111,6],"148":[6],"159":[6]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatTypingIndicator.vue":{"2":[4,111,5,112,6,17]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/CopyButton.vue":{"9":[4,111,5,112,6,17],"12":[4,111,5,112,6,17],"22":[4,111,5,112,6,17]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ModelSelector.vue":{"54":[4,111,5,112,6,17],"78":[4,111,5,112,6,17],"84":[4,111,5,112,6,17],"85":[4,111,5,112,6,17],"93":[4,111,5,112,6,17],"103":[4,111,5,112,6,17],"105":[4,111,5,112,6,17],"109":[111],"113":[111,5],"144":[111,5,112],"184":[4,111,5,112,6,17],"201":[4,111,5,112,6,17],"209":[111,5,112]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/SkeletonMenuItem.vue":{"2":[4,111,5,112,6,17]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ToolsSelector.vue":{"32":[6],"34":[4,111,5,112,6,17],"36":[6],"39":[6],"41":[6],"45":[6],"50":[4,111,5,112,6,17],"53":[6],"62":[6],"104":[6],"108":[6],"116":[6],"153":[4,111,5,112,6,17],"166":[4,111,5,112,6,17],"175":[4,111,5,112,6,17],"197":[6],"204":[6],"207":[6]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useChatArtifacts.ts":{"6":[4,111,5,112,6,17],"12":[4,111,5,112,6,17],"13":[4,111,5,112,6,17],"21":[4,111,5,112,6,17],"26":[4,111,5,112,6,17],"30":[4,111,5,112,6,17],"39":[4,111,5,112,6,17]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useChatCredentials.ts":{"18":[4,111,5,112,6,17],"38":[4,111,5,112,6,17],"43":[4,111,5,112,6,17],"47":[4,111,5,112,6,17],"49":[4,111,5,112,6,17],"66":[17],"72":[112,17],"81":[4,111,5,112,6,17],"83":[4,111,5,112,6,17],"100":[4,111,5,112,6,17],"102":[4,111,5,112,6,17]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useChatHubMarkdownOptions.ts":{"25":[19,48,22,50],"40":"b:cAB6AAAABwAAAAAAAICxAQAAAAAAAAAAAAAAAAA=","56":"b:cAB6AAAABwAAAAAAAICxAQAAAAAAAAAAAAAAAAA=","75":"b:cAB6AAAABwAAAAAAAICxAQAAAAAAAAAAAAAAAAA=","86":[4],"139":"b:cAB6AAAABwAAAAAAAICxAQAAAAAAAAAAAAAAAAA=","140":"b:cAB6AAAABwAAAAAAAICxAQAAAAAAAAAAAAAAAAA=","142":[19,48,22,50],"145":[19,48,22,50],"157":"b:cAB6AAAABwAAAAAAAICxAQAAAAAAAAAAAAAAAAA=","162":[4],"180":"b:cAB6AAAABwAAAAAAAICxAQAAAAAAAAAAAAAAAAA=","200":"b:cAB6AAAABwAAAAAAAICxAQAAAAAAAAAAAAAAAAA=","207":"b:cAB6AAAABwAAAAAAAICxAQAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useChatInputFocus.ts":{"13":[4,111,5,112,6,17]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useChatPushHandler.ts":{"31":[4,111,5,112,6,17],"42":[4,111,5,112,6,17],"50":[4,111,5,112,6,17],"62":[4,111,5,112,6,17],"93":[4,111,5,112],"118":[4,111,5,112,6,17],"133":[6,17],"148":[4,111,5,112,6,17],"162":[4,111,5,112,6,17],"179":[4,111,5,112,6,17],"211":[4,111,5,112,6,17],"220":[4,111,5,112,6,17],"222":[4,111,5,112,6,17],"233":[112],"268":[4,111,17]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useChatSession.ts":{"29":[4,111,5,112,6,17],"37":[4,111,5,112,6,17],"41":[112],"46":[4,111,5,112,6,17],"47":[4,111,5,112,6,17],"51":[4,111,5,112,6,17],"71":[4,111,5,112,6,17],"78":[4],"85":[4,111,5,112,6,17],"95":[4,111,5,112,6,17],"111":[4,111,5,112,6,17],"112":[4,111,5,112,6,17]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useCustomAgent.ts":{"7":[4,111,5,112,6,17],"8":[4,111,5,112,6],"18":[4,111,5,112,6,17]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useDynamicCredentialsStatus.ts":{"33":[4,111,5,112,6,17],"39":[4,111,5,112,6,17],"40":[4,111,5,112,6,17],"50":[17],"196":[4,111,5,112,6,17]},"packages/frontend/editor-ui/src/features/ai/chatHub/model-selector.utils.ts":{"118":[4,111,5,112,6,17],"132":[4,111,5,112,6,17],"142":[112],"170":[17],"182":[17],"199":[4,111,5,112,6,17],"223":[4,111,5,112,6,17],"260":[17],"267":[4,111,5,112,6,17],"274":[4,111,5,112,6,17],"284":[4,111,5,112,6,17],"334":[4,111,5,112,6,17],"376":[4,111,5,112,6,17],"393":[4,111,5,112,6,17]},"packages/frontend/editor-ui/src/features/ai/shared/utils/fileAccept.ts":{"4":[4,111,5,112,6,17,46],"5":[4,111,5,112,6,17,46],"6":[4,111,5,112,6,17,46],"18":[4,46,20,119],"26":[4,46],"28":[4,46]},"packages/frontend/@n8n/design-system/src/components/N8nCard/Card.vue":{"9":"b:QAIAAoDpAB5WAEAJGJAEAoABAEIAAQDAAAAAAAA=","14":"b:QAIAAoDpAB5WAEAJGJAEAoABAEIAAQDAAAAAAAA=","19":"b:QAIAAoDpAB5WAEAJGJAEAoABAEIAAQDAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nDropdownMenu/DropdownMenu.utils.ts":{"6":[46],"11":[111,5,112,46,21,120],"17":[46,21],"35":[111,5,112,46,21,120],"39":[46],"56":[46],"63":[46]},"packages/frontend/@n8n/design-system/src/components/N8nDropdownMenu/DropdownMenuSearch.vue":{"18":[111,5,112,46,120],"33":[46],"39":[46],"43":[111,5,112,46,120],"48":[111,5,112,46,120]},"packages/frontend/@n8n/design-system/src/components/N8nDropdownMenu/DropdownMenuSearchableContent.vue":{"25":[111,5,112,46,21,120],"83":[111,5,112,46,21,120],"91":[46],"95":[46],"101":[46],"115":[46],"127":[111,5,112,46,120],"131":[46,21,120],"138":[46,21,120],"142":[46],"148":[46],"154":[111,5,112,46,120],"163":[111,5,112,46,120],"169":[46,21],"173":[46],"178":[111,5,112,46],"189":[46],"196":[46],"212":[46],"218":[111,5,112,46,120],"226":[111,5,112,46,120],"231":[111,5,112,46,21,120],"233":[111,5,112,46,21,120],"237":[46],"283":[46,21],"324":[46,21],"327":[46,21],"332":[111,5,112,46,120],"337":[111,5,112,46,21,120],"338":[111,5,112,46,21,120],"342":[111,5,112,46,21,120],"354":[111,5,112,46,21,120],"365":[111,5,112,46,21,120],"371":[111,5,112,46,21,120],"372":[46,21,120],"382":[111,5,112,46,21,120],"395":[46],"398":[46]},"packages/frontend/editor-ui/src/experiments/openWorkflowInAssistant/stores/openWorkflowInAssistant.store.ts":{"22":"b:IAB4AIDhBx4gAEAJAJjwB4ABAAAAAQDAAAAAAAA=","30":[46],"33":"b:IAB4AIDhBx4gAEAJAJjwB4ABAAAAAQDAAAAAAAA=","40":[46,121],"42":[46],"46":[46,121,60,168,88,190],"49":"b:AAAAAIDAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","53":[46],"66":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","75":[46,122],"99":[46],"107":[46],"130":[46],"134":[46],"141":[46],"154":[46]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatProviderAvatar.vue":{"13":[111,5,112],"23":[111,5,112]},"packages/@n8n/db/src/utils/is-entity-not-found-error.ts":{"6":[112]},"packages/@n8n/errors/src/response-errors/forbidden.error.ts":{"4":[112]},"packages/cli/src/errors/credential-not-found.error.ts":{"4":[112]},"packages/frontend/editor-ui/src/app/components/Modal.vue":{"11":"b:YAIAKADoAFh2CAAAAgAHAEABwPMgAMBjAAAAAAA=","61":"b:YAIAKADoAFh2CAAAAgAHAEABwPMgAMBjAAAAAAA=","83":"b:YAIAKADoAFh2CAAAAgAHAEABwPMgAMBjAAAAAAA=","92":"b:YAIAKADoAFhyCAACAAAHAEAAwOEgAMBjAAAAAAA=","99":[46,47],"104":"b:YAIAKADoAFh2CAAAAAAHAEAAwMMgAMBjAAAAAAA=","111":[46,47,165],"115":"b:YAIAIABoAFByCAAAAAACAEAAwOEgAMAjAAAAAAA=","127":[5,6,46,152,68,157,189],"131":"b:YAIAKADoAFh2CAACAgAHAEABwPMgAMBjAAAAAAA=","139":"b:YAIAKADoAFh2CAACAgAHAEABwPMgAMBjAAAAAAA=","164":"b:YAIAKADoAFh2CAACAgAHAEABwPMgAMBjAAAAAAA=","166":"b:YAIAKADoABhWCAACAgAHAEAAAEIAAABDAAAAAAA=","169":"b:AAAAAABAAEgiCAAAAAAAAEABwLEgAMBjAAAAAAA=","171":"b:AAAAAABAAEgiCAAAAAAAAEABwLEgAMBjAAAAAAA=","174":[46],"180":[46,59,165]},"packages/frontend/editor-ui/src/features/ai/chatHub/ChatPersonalAgentsView.vue":{"38":[112],"39":[112],"40":[112],"42":[112],"51":[112],"66":[112],"78":[112],"79":[112],"87":[112],"110":[112],"129":[112],"133":[112],"140":[112],"145":[112],"158":[112],"159":[112]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/AgentEditorModal.vue":{"116":[112],"119":[112],"125":[112],"126":[112],"127":[112],"132":[112],"138":[112],"145":[112],"152":[112],"156":[112],"162":[112],"172":[112],"195":[112],"197":[112],"210":[112],"238":[112],"243":[112],"426":[112],"435":[112],"449":[112],"471":[112],"485":[112],"520":[112],"540":[112],"555":[112],"571":[112],"581":[112],"600":[112],"686":[112],"689":[112]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatAgentCard.vue":{"24":[112,17],"30":[112,17],"36":[112],"43":[112,17],"53":[112,17],"56":[112,17],"74":[112],"76":[112]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatAgentSearchSort.vue":{"19":[112,17],"28":[112,17],"63":[112,17]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/SuggestedPromptsEditor.vue":{"9":[112],"51":[112],"92":[112]},"packages/@n8n/api-types/src/dto/project/list-projects-query.dto.ts":{"13":"b:AAAAAIBgABxiAAABAAAGAAABAGAAAAAAAAAAAAA=","14":"b:AAAAAIBgABxiAAABAAAGAAABAGAAAAAAAAAAAAA=","17":"b:AAAAAIBgABxiAAABAAAGAAABAGAAAAAAAAAAAAA=","26":"b:AAAAAIBgABxiAAABAAAGAAABAGAAAAAAAAAAAAA=","34":"b:AAAAAIBgABxiAAABAAAGAAABAGAAAAAAAAAAAAA=","35":"b:AAAAAIBgABxiAAABAAAGAAABAGAAAAAAAAAAAAA=","38":"b:AAAAAIBgABxiAAABAAAGAAABAGAAAAAAAAAAAAA=","41":"b:AAAAAIBgABxiAAABAAAGAAABAGAAAAAAAAAAAAA="},"packages/cli/src/credentials/credentials.service.ee.ts":{"30":"b:IAICgAAgAAhAAQACAAACAAAAAFAAAAAABAAgAAA=","44":"b:IAICgAAgAAhAAQACAAACAAAAAFAAAAAABAAgAAA=","83":"b:IAICgAAgAAhAAQACAAACAAAAAFAAAAAABAAgAAA=","85":"b:IAICgAAgAAhAAQACAAACAAAAAFAAAAAABAAgAAA=","89":"b:IAICgAAgAAhAAQACAAACAAAAAFAAAAAABAAgAAA=","100":"b:IAICgAAgAAhAAQACAAACAAAAAFAAAAAABAAgAAA=","104":"b:IAICgAAgAAhAAQACAAACAAAAAFAAAAAABAAgAAA=","196":"b:IAICgAAgAAhAAQACAAACAAAAAFAAAAAABAAgAAA=","209":"b:IAICgAAgAAhAAQACAAACAAAAAFAAAAAABAAgAAA=","266":"b:IAICgAAgAAhAAQACAAACAAAAAFAAAAAABAAgAAA=","268":"b:IAICgAAgAAhAAQACAAACAAAAAFAAAAAABAAgAAA="},"packages/cli/src/middlewares/list-query/filter.ts":{"11":"b:AAJoIIDpA15WAUALHBgGCAAAAAIAAAAIACAAAAA="},"packages/cli/src/middlewares/list-query/pagination.ts":{"10":"b:AAJoIIDpA15WAUALHBgGCAAAAAIAAAAIACAAAAA="},"packages/cli/src/middlewares/list-query/select.ts":{"11":"b:AAJoIIDpA15WAUALHBgGCAAAAAIAAAAIACAAAAA="},"packages/cli/src/middlewares/list-query/sort-by.ts":{"12":"b:AAJoIIDpA15WAUALHBgGCAAAAAIAAAAIACAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nAvatar/Avatar.vue":{"16":"b:AACCAABgABxgAAAhEAACAAAAAPQAAABAAAAAAAA=","29":"b:AACCAABgABxgAAAhEAACAAAAAPQAAABAAAAAAAA=","30":"b:AACCAABgABxgAAAhEAACAAAAAPQAAABAAAAAAAA=","32":"b:AACCAABgABxgAAAhEAACAAAAAPQAAABAAAAAAAA=","34":"b:AACCAABgABxgAAAhEAACAAAAAPQAAABAAAAAAAA=","37":"b:AACCAABgABxgAAAhEAACAAAAAPQAAABAAAAAAAA=","38":"b:AACCAABgABxgAAAhEAACAAAAAPQAAABAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nDataTableServer/N8nDataTableServer.vue":{"54":[113,17,46,58,60,69],"97":[113,17,46,58,60,69],"98":[113,17,46,58,60,69],"106":[113,17,46,58,60,69],"113":[113,17,46,58,60,69],"117":[113,17,46,58,60,69],"123":[113,17,46,58,60,69],"135":[113,17,46,58,60,69],"139":[113,17,46,58,60,69],"148":[113,17,46,58,60,69],"153":[113,17,46,58,60,69],"168":[46],"182":[113,17,46,58,60,69],"183":[113,17,46,58,60,69],"194":[17,46,58,60,69],"209":[46],"220":[113,17,46,58,60,69],"225":[46],"228":[46],"231":[46],"237":[46],"243":[113,17,46,58,60,69],"247":[46],"267":[46],"271":[46],"276":[46],"280":[46],"292":[113,17,46,58,60,69],"300":[46],"305":[46],"315":[46],"316":[46],"324":[46],"329":[46],"343":[113,17,46,58,60,69],"346":[113,17,46,58,60,69],"350":[46,69],"353":[46],"356":[46],"362":[46],"379":[46],"395":[113,17,46,58,60,69],"412":[113,17,46,58,60,69],"413":[113,17,46,58,60,69],"422":[46],"437":[46],"438":[46],"439":[46],"461":[46],"463":[46],"472":[113,17,46,58,60,69],"473":[113,17,46,58,60,69],"476":[46],"478":[113,17,46,58,60,69],"507":[46],"516":[113,46],"518":[113,46]},"packages/frontend/@n8n/design-system/src/components/N8nEmptyState/EmptyState.vue":{"35":"b:AAICIADoAB5WAACAAAAGAAABwFsAAABAAAAAAAA=","55":"b:AAIAIADoABpWAACAAAAGAAABwFsAAABAAAAAAAA=","61":[46],"64":"b:AAICIADoAB5SAACAAAAGAAABwFkAAABAAAAAAAA=","71":[46],"73":"b:AAIAIADoABpWAACAAAAEAAABwFsAAABAAAAAAAA=","81":[43,46,151,152,65,153,68],"92":[46],"94":[46]},"packages/frontend/@n8n/design-system/src/components/N8nIconPicker/types.ts":{"17":"b:AAJagIB4Bx5CAoABAAD2BYABAHAAAATAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nPagination/Pagination.vue":{"24":"b:AAAAAIDAAB4AAFAJABAGAoAFAAAAgQDAAAAAAAA=","25":"b:AAAAAIDAAB4AAFAJABAGAoAFAAAAgQDAAAAAAAA=","26":"b:AAAAAIDAAB4AAFAJABAGAoAFAAAAgQDAAAAAAAA=","51":"b:AAAAAIDAAB4AAFAJABAGAoAFAAAAgQDAAAAAAAA=","56":[46,114,138],"58":"b:AAAAAIDAAB4AAFAJABAGAoAFAAAAgQDAAAAAAAA=","63":[46,114],"65":"b:AAAAAIDAAB4AAFAJABAGAoAFAAAAgQDAAAAAAAA=","73":[46,47,114,138],"77":[46,47,114,138],"85":[46,47,114,138],"96":"b:AAAAAIDAAB4AAFAJABAGAoAFAAAAgQDAAAAAAAA=","98":"b:AAAAAIDAAB4AAFAJABAGAoAFAAAAgQDAAAAAAAA=","106":[46,138,175,84],"111":"b:AAAAAIDAAB4AAFAJABAGAoAFAAAAgQDAAAAAAAA=","115":"b:AAAAAIDAAB4AAFAJABAGAoAFAAAAgQDAAAAAAAA=","119":"b:AAAAAIDAAB4AAFAJABAGAoAFAAAAgQDAAAAAAAA=","123":"b:AAAAAIDAAB4AAEAJABAEAoABAAAAAQDAAAAAAAA=","124":"b:AAAAAIDAAB4AAEAJABAEAoABAAAAAQDAAAAAAAA=","130":[46,114,138],"138":[46,114],"150":[46],"173":[46],"179":[46],"186":[46],"192":[46],"201":[46],"212":[46],"224":"b:AAAAAIDAAB4AAFAJABAGAoAFAAAAgQDAAAAAAAA=","251":"b:AAAAAIDAAB4AAFAJABAGAoAFAAAAgQDAAAAAAAA=","257":"b:AAAAAIDAAB4AAFAJABAGAoAFAAAAgQDAAAAAAAA=","261":"b:AAAAAIDAAB4AAFAJABAGAoAFAAAAgQDAAAAAAAA=","263":"b:AAAAAIDAAB4AAFAJABAGAoAFAAAAgQDAAAAAAAA=","278":"b:AAAAAIDAAB4AAFAJABAGAoAFAAAAgQDAAAAAAAA=","286":[46],"294":"b:AAAAAIDAAB4AAFAJABAGAoAFAAAAgQDAAAAAAAA=","302":"b:AAAAAIDAAB4AAFAJABAGAoAFAAAAgQDAAAAAAAA=","304":"b:AAAAAIDAAB4AAFAJABAGAoAFAAAAgQDAAAAAAAA=","336":[46]},"packages/frontend/@n8n/design-system/src/components/N8nTimeAgo/TimeAgo.vue":{"22":"b:AAIAAIDoAB5CAEALABAGAoABAEAAAQDAAAAAAAA=","38":"b:AAIAAIDoAB5CAEALABAGAoABAEAAAQDAAAAAAAA=","50":"b:AAIAAIDoAB5CAEALABAGAoABAEAAAQDAAAAAAAA=","51":"b:AAIAAIDoAB5CAEALABAGAoABAEAAAQDAAAAAAAA="},"packages/frontend/@n8n/design-system/src/utils/labelUtil.ts":{"1":"b:AACCAABgABxgAAAhEAACAAAAAPQAAABAAAAAAAA=","4":"b:AACCAABgABxgAAAhEAACAAAAAPQAAABAAAAAAAA=","6":"b:AACCAABgABxgAAAhEAACAAAAAPQAAABAAAAAAAA=","11":"b:AACCAABgABxgAAAhEAACAAAAAPQAAABAAAAAAAA=","12":[46]},"packages/frontend/editor-ui/src/app/components/SettingsSidebar.vue":{"23":"b:AAAAAAAAAEA2AACgGAACCAAAwA4AAAAAAAAAAAA=","26":"b:AAAAAAAAAEA2AACgGAACCAAAwA4AAAAAAAAAAAA=","38":"b:AAAAAAAAAEA2AACgGAACCAAAwA4AAAAAAAAAAAA=","46":"b:AAAAAAAAAEA2AACgGAACCAAAwA4AAAAAAAAAAAA="},"packages/frontend/editor-ui/src/app/components/TimeAgo.vue":{"16":"b:AAIAAIDoAB5CAEALABAGAoABAEAAAQDAAAAAAAA=","17":"b:AAIAAIDoAB5CAEALABAGAoABAEAAAQDAAAAAAAA="},"packages/frontend/editor-ui/src/app/layouts/SettingsLayout.vue":{"27":"b:AAAAAAAAAEA2AACgGAACCAAAwA4AAAAAAAAAAAA=","34":"b:AAAAAAAAAEA2AACgGAACCAAAwA4AAAAAAAAAAAA=","36":"b:AAAAAAAAAEA2AACgGAACCAAAwA4AAAAAAAAAAAA="},"packages/frontend/editor-ui/src/app/utils/rbac/middleware/rbac.ts":{"11":[113,46,62,150,151,99,65,66,153,68,69,155]},"packages/frontend/editor-ui/src/app/utils/rbacUtils.ts":{"4":[113,46,62,150,151,99,65,66,153,68,69,155],"12":[113,46,62,150,151,99,65,66,153,68,69,155],"23":[113,46,62,150,151,99,65,66,153,68,69,155],"34":[46,65,69]},"packages/frontend/editor-ui/src/features/ai/chatHub/SettingsChatHubView.vue":{"26":[113],"41":[113],"43":[113],"60":[113],"68":[113],"76":[113],"94":[113],"115":[113],"126":[113],"133":[113],"141":[113]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatProvidersTable.vue":{"25":[113],"47":[113],"56":[113],"65":[113],"75":[113],"81":[113],"89":[113],"93":[113],"116":[113],"123":[113],"136":[113],"140":[113],"163":[113],"172":[113],"176":[113],"190":[113],"193":[113],"199":[113],"204":[113]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ProviderSettingsModal.vue":{"123":[113],"127":[113],"141":[113],"156":[113],"164":[113],"184":[113],"217":[113],"227":[113],"229":[113],"240":[113],"243":[113],"250":[113],"254":[113],"265":[113],"279":[113],"308":[113],"319":[113],"372":[113],"375":[113],"398":[113],"401":[113]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectSharing.vue":{"24":[113,45,46,59,69,156,157,158,70,159,190],"99":[113,45,46,59,69,156,157,158,70,159,190],"105":[46,158,70,159],"106":[46],"111":[46],"117":[113,45,46,59,69,157,158,70,159,190],"120":[113,45,46,59,69,157,158,70,159,190],"129":[113,45,46,59,69,157,158,70,159,190],"139":[113,45,46,59,158,70,159,190],"145":[113,45,46,158,70,159,190],"151":[113,45,46,59,69,157,158,70,159,190],"152":[113,45,46,59,69,157,158,70,159,190],"161":[113,45,46,59,69,157,158,70,159,190],"164":[113,45,46,59,69,157,158,70,159,190],"168":[113,45,46,59,69,157,158,70,159,190],"170":[113,45,46,59,69,157,158,70,159,190],"184":[113,45,46,59,69,156,157,158,70,159,190],"200":[113,45,46,59,69,158,70,159],"206":[113,45,46,59,69,156,157,158,70,159,190],"210":[113,45,46,59,69,158,70,159],"216":[46,59,69,158,70,159],"230":[113,45,46,156,158,70,159,190],"231":[113,45,46,158,70,159],"232":[46],"236":[113,45,46,158,70,159],"239":[45,46],"267":[46],"272":[113,45,46,59,69,156,157,158,70,159,190],"273":[113,45,46,59,69,156,157,158,70,159,190],"283":[113,45,46,59,69,156,157,158,70,159,190],"287":[46],"288":[113,45,46,59,69,156,157,158,70,159,190],"306":[46],"308":[113,45,46,59,69,157,158,70,159,190],"314":[46],"316":[113,45,46,59,69,157,158,70,159,190],"319":[113,45,46,59,69,157,158,70,159,190],"323":[113,45,46,59,69,157,158,70,159,190],"333":[46],"335":[46],"351":[113,45,46,156,158,70,159,190],"355":[113,45,46,156,158,70,159,190],"359":[113,45,46,158,70,159],"366":[46],"371":[113,45,46,158,70,159],"376":[46],"383":[46],"392":[46],"409":[46],"410":[113,45,46,158,70,159],"412":[113,45,46,158,70,159],"422":[113,45,46,158,70,159],"431":[45,46]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectSharingInfo.vue":{"13":[113,45,46,59,69,156,157,158,70,159,190],"15":[113,45,46,59,69,156,157,158,70,159,190],"26":[113,45,46,59,69,156,157,158,70,159,190],"32":[113,45,46,59,69,156,157,158,70,159,190]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialSharing.ee.vue":{"39":[113,45,46,158,70],"60":[113,45,46,158,70],"64":[113,45,46,158,70],"67":[46],"72":[46],"74":[113,45,46,158,70],"75":[113,45,46,158,70],"87":[113,45,46,158,70],"91":[113,45,46,158,70],"94":[46],"95":[46],"100":[113,45,46,158,70],"106":[113,45,46,158,70],"114":[113,45,46,158,70],"123":[113,45,46,158,70],"124":[113,45,46,158,70],"137":[113,45,46,158,70],"139":[46],"158":[113,45,46,158,70],"164":[113,45,46,158,70],"170":[46],"186":[46],"204":[46],"213":[46],"217":[46],"233":[46],"245":[46],"254":[46],"262":[46],"263":[46],"268":[113,45,46,158,70],"274":[113,45,46,158,70],"280":[46,158,70],"289":[46],"291":[113,45,46,158,70],"317":[113,45,46,158,70],"321":[46],"324":[46],"352":[113,45,46],"354":[46],"357":[46],"360":[46],"368":[46],"373":[46],"374":[46],"381":[46],"385":[46],"386":[46]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialPicker/CredentialPicker.vue":{"19":[5,113,46,97,89],"52":[5,113,46,97,89],"57":[46],"65":[5,113,46,97,89],"66":[5,113,46,89],"74":[5,113,46,97,89],"103":[5,113,46,97,89],"108":[5,113,46,97,89],"114":[113,46],"117":[46,89],"134":[113,46],"144":[46],"181":[46,89],"188":[46],"198":[46],"199":[46],"210":[5,113,46,89],"220":[5,113,46,97,89],"221":[5,113,46,97,89],"227":[5,113,46,97,89],"249":[5,113,46,89],"260":[113,46],"269":[5,46],"278":[46]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialPicker/CredentialsDropdown.vue":{"36":[5,113,46,89],"58":[46],"62":[5,113,46,89],"64":[46],"71":[5,113,46,89],"75":[5,113,46,89],"81":[5,113,46,89],"87":[5,113,46],"93":[5,113,46],"97":[113,46],"102":[113,46],"107":[46],"111":[5,113,46,89],"132":[5,113,46,89],"141":[46],"144":[46],"149":[46],"160":[5,113,46,89],"166":[5,113,46,89],"171":[5,113,46,89],"173":[5,113,46,89],"177":[5,113,46,89],"188":[5,113,46,89],"189":[5,113,46,89],"194":[5,113,46,89],"200":[46],"219":[46]},"packages/@n8n/blob-storage/src/json-store.ts":{"19":[17,170],"23":[17,170],"27":[17,170],"31":[17,170],"47":[17,170],"55":[17,170],"60":[17,170],"64":[17,170],"66":[17,170],"76":[17,170],"80":[17,170],"86":[17,170],"93":[17,170],"103":[17,170],"117":[17,170],"129":[17,170],"134":[17,170]},"packages/@n8n/db/src/repositories/workflow-review-lifecycle.repository.ts":{"29":[8,17,48,59,60,184,190],"39":[8,17,48,59,60,184,190],"47":[8,17,48,59,60,184,190],"84":[8,17,48,59,60,184,190],"101":[8,17,48,59,60,184,190]},"packages/@n8n/db/src/repositories/workflow-review-request.repository.ts":{"31":[8,17,48,59,60,74,184,190],"35":[8,17,48,59,60,74,184,190],"65":[8,17,48,59,60,74,184,190],"73":[8,17,48,59,60,74,184,190],"85":[8,17,48,59,60,74,184,190],"89":[8,17,48,59,60,74,184,190],"138":[8,17,48,59,60,74,184,190],"153":[8,17,48,59,60,74,184,190]},"packages/@n8n/db/src/utils/is-string-array.ts":{"1":"b:AABqAICBA14ACEAZHBgECIAAAAAAAABIACAAAAA=","2":"b:AABqAICBA14ACEAZHBgECIAAAAAAAABIACAAAAA="},"packages/cli/src/active-workflow-manager.ts":{"78":[17],"103":[17],"114":[17],"121":[17],"143":[17],"150":[17],"160":[17],"238":[17],"283":[17],"319":[17],"339":[17],"353":[17],"381":[17],"395":[17],"414":[17],"427":[17],"496":[17],"503":[17],"512":[17],"540":[17],"669":[17],"671":[17],"708":[17],"719":[17],"727":[17],"748":[17],"845":[17],"851":[17],"852":[17],"855":[17],"865":[17],"882":[17],"890":[17],"962":[17],"972":[17],"985":[17],"1029":[17],"1051":[17],"1071":[17],"1104":[17],"1141":[17],"1144":[17],"1187":[17],"1194":[17],"1210":[17]},"packages/cli/src/events/relays/workflow-failure-notification.event-relay.ts":{"15":[17,71,221],"24":[17,71,221],"26":[17,71,221],"35":[17,71,221]},"packages/cli/src/modules/dynamic-credentials.ee/services/credential-resolver-workflow.service.ts":{"33":[17,194,115,217],"49":[17,194,115,217],"59":[17,194,115,217],"100":[17,194,115,217],"139":[17,194,115,217],"143":[17,194,115,217],"147":[17,194,115,217],"170":[17,194,115,217],"212":[17,194,115,217],"239":[17,194,115,217],"265":[17,194,115,217],"280":[17,194,115,217],"293":[17,194,115,217]},"packages/cli/src/modules/dynamic-credentials.ee/services/dynamic-credential-cors.service.ts":{"12":[17,194],"30":[17,194],"31":[17,194],"53":[17,194],"61":[17,194]},"packages/cli/src/modules/dynamic-credentials.ee/services/dynamic-credential-web.service.ts":{"17":[17,194],"36":[17,194],"41":[17,194],"53":[17,194]},"packages/cli/src/modules/dynamic-credentials.ee/workflow-status.controller.ts":{"23":[17,194],"38":[17,194],"59":[17,194],"85":[17,194],"93":[17,194]},"packages/cli/src/modules/external-secrets.ee/external-secrets-providers.ee.ts":{"13":[39,17,114,58,60,209,65,210,88,190],"23":[39,17,114,58,60,209,65,210,88,190],"27":[39,17,114,58,60,209,65,210,88,190],"31":[39,17,114,58,60,209,65,210,88,190],"35":[39,17,114,58,60,209,65,210,88,190]},"packages/cli/src/modules/external-secrets.ee/providers/aws-secrets-manager.ts":{"114":[39,17,114,58,60,209,65,88,190],"122":[39,17,114,58,60,209,65,88,190],"162":[39,17,114,58,60,209,65,88,190],"177":[39,17,114,58,60,209,65,88,190],"192":[39,17,114,58,60,209,65,88,190],"196":[39,17,114,58,60,209,65,88,190],"203":[39,17,114,58,60,209,65,88,190],"217":[39,17,114,58,60,209,65,88,190],"221":[39,17,114,58,60,209,65,88,190],"225":[39,17,114,58,60,209,65,88,190],"229":[39,17,114,58,60,209,65,88,190],"235":[39,17,114,58,60,209,65,88,190],"245":[39,17,114,58,60,209,65,88,190],"254":[39,17,114,58,60,209,65,88,190],"281":[39,17,114,58,60,209,65,88,190],"282":[39,17,114,58,60,209,65,88,190],"287":[39,17,114,58,60,209,65,88,190],"291":[39,17,114,58,60,209,65,88,190],"295":[39,17,114,58,60,209,65,88,190],"320":[39,17,114,58,60,209,65,88,190],"338":[39,17,114,58,60,209,65,88,190]},"packages/cli/src/modules/external-secrets.ee/providers/azure-key-vault/azure-key-vault.ts":{"169":[39,17,114,58,60,65,88,190],"174":[39,17,114,58,60,65,88,190],"180":[39,17,114,58,60,65,88,190],"205":[39,17,114,58,60,65,88,190],"223":[39,17,114,58,60,65,88,190],"239":[39,17,114,58,60,65,88,190],"243":[39,17,114,58,60,65,88,190],"252":[39,17,114,58,60,65,88,190],"331":[39,17,114,58,60,65,88,190],"335":[39,17,114,58,60,65,88,190],"339":[39,17,114,58,60,65,88,190],"343":[39,17,114,58,60,65,88,190],"354":[39,17,114,58,60,65,88,190],"376":[39,17,114,58,60,65,88,190]},"packages/cli/src/modules/external-secrets.ee/providers/gcp-secrets-manager/gcp-secrets-manager.ts":{"47":[39,17,114,58,60,65,88,190],"52":[39,17,114,58,60,65,88,190],"64":[39,17,114,58,60,65,88,190],"89":[39,17,114,58,60,65,88,190],"104":[39,17,114,58,60,65,88,190],"108":[39,17,114,58,60,65,88,190],"116":[39,17,114,58,60,65,88,190],"129":[39,17,114,58,60,65,88,190],"182":[39,17,114,58,60,65,88,190],"209":[39,17,114,58,60,65,88,190],"213":[39,17,114,58,60,65,88,190],"217":[39,17,114,58,60,65,88,190],"221":[39,17,114,58,60,65,88,190],"245":[39,17,114,58,60,65,88,190],"256":[39,17,114,58,60,65,88,190]},"packages/cli/src/modules/external-secrets.ee/providers/infisical.ts":{"166":[39,17,114,58,60,65,88,190],"174":[39,17,114,58,60,65,88,190],"180":[39,17,114,58,60,65,88,190],"190":[39,17,114,58,60,65,88,190],"216":[39,17,114,58,60,65,88,190],"227":[39,17,114,58,60,65,88,190],"248":[39,17,114,58,60,65,88,190],"282":[39,17,114,58,60,65,88,190],"295":[39,17,114,58,60,65,88,190],"297":[39,17,114,58,60,65,88,190],"300":[39,17,114,58,60,65,88,190],"301":[39,17,114,58,60,65,88,190],"310":[39,17,114,58,60,65,88,190],"313":[39,17,114,58,60,65,88,190],"320":[39,17,114,58,60,65,88,190],"326":[39,17,114,58,60,65,88,190],"342":[39,17,114,58,60,65,88,190],"354":[39,17,114,58,60,65,88,190],"370":[39,17,114,58,60,65,88,190],"374":[39,17,114,58,60,65,88,190],"378":[39,17,114,58,60,65,88,190],"382":[39,17,114,58,60,65,88,190],"392":[39,17,114,58,60,65,88,190],"417":[39,17,114,58,60,65,88,190]},"packages/cli/src/modules/external-secrets.ee/providers/one-password.ts":{"61":[39,17,114,58,60,65,88,190],"66":[39,17,114,58,60,65,88,190],"92":[39,17,114,58,60,65,88,190],"118":[39,17,114,58,60,65,88,190],"137":[39,17,114,58,60,65,88,190],"141":[39,17,114,58,60,65,88,190],"188":[39,17,114,58,60,65,88,190],"192":[39,17,114,58,60,65,88,190],"196":[39,17,114,58,60,65,88,190],"197":[39,17,114,58,60,65,88,190],"198":[39,17,114,58,60,65,88,190],"202":[39,17,114,58,60,65,88,190],"206":[39,17,114,58,60,65,88,190]},"packages/cli/src/modules/external-secrets.ee/providers/vault.ts":{"306":[39,17,114,58,60,65,210,88,190],"316":[39,17,114,58,60,65,210,88,190],"322":[39,17,114,58,60,65,210,88,190],"332":[39,17,114,58,60,65,210,88,190],"381":[39,17,114,58,60,65,210,88,190],"387":[39,17,114,58,60,65,210,88,190],"394":[39,17,114,58,60,65,210,88,190],"412":[39,17,114,58,60,65,210,88,190],"417":[39,17,114,58,60,65,210,88,190],"429":[39,17,114,58,60,65,210,88,190],"463":[39,17,114,58,60,65,210,88,190],"489":[39,17,114,58,60,65,210,88,190],"512":[39,17,114,58,60,65,210,88,190],"526":[39,17,114,58,60,65,210,88,190],"537":[39,17,114,58,60,65,210,88,190],"557":[39,17,114,58,60,65,210,88,190],"566":[39,17,114,58,60,65,210,88,190],"593":[39,17,114,58,60,65,210,88,190],"598":[39,17,114,58,60,65,210,88,190],"604":[39,17,114,58,60,65,210,88,190],"607":[39,17,114,58,60,65,210,88,190],"612":[39,17,114,58,60,65,210,88,190],"621":[39,17,114,58,60,65,210,88,190],"630":[39,17,114,58,60,65,210,88,190],"639":[39,17,114,58,60,65,210,88,190],"649":[39,17,114,58,60,65,210,88,190],"652":[39,17,114,58,60,65,210,88,190],"660":[39,17,114,58,60,65,210,88,190],"663":[39,17,114,58,60,65,210,88,190],"679":[39,17,114,58,60,65,210,88,190],"687":[39,17,114,58,60,65,210,88,190],"712":[39,17,114,58,60,65,210,88,190],"720":[39,17,114,58,60,65,210,88,190],"728":[39,17,114,58,60,65,210,88,190],"733":[39,17,114,58,60,65,210,88,190],"739":[39,17,114,58,60,65,210,88,190],"754":[39,17,114,58,60,65,210,88,190],"787":[39,17,114,58,60,65,210,88,190],"791":[39,17,114,58,60,65,210,88,190],"795":[39,17,114,58,60,65,210,88,190],"796":[39,17,114,58,60,65,210,88,190],"802":[39,17,114,58,60,65,210,88,190],"814":[39,17,114,58,60,65,210,88,190],"825":[39,17,114,58,60,65,210,88,190],"833":[39,17,114,58,60,65,210,88,190],"841":[39,17,114,58,60,65,210,88,190]},"packages/cli/src/modules/external-secrets.ee/secrets-providers-connections.controller.ee.ts":{"32":[39,17,114,58,60,65,88,190],"41":[39,17,114,58,60,65,88,190],"81":[39,17,114,58,60,65,88,190],"104":[39,17,114,58,60,65,88,190],"122":[39,17,114,58,60,65,88,190],"135":[39,17,114,58,60,65,88,190],"138":[39,17,114,58,60,65,88,190],"145":[39,17,114,58,60,65,88,190],"157":[39,17,114,58,60,65,88,190],"172":[39,17,114,58,60,65,88,190]},"packages/cli/src/modules/external-secrets.ee/secrets-providers-project.controller.ee.ts":{"32":[39,17,114,58,60,65,88,190],"42":[39,17,114,58,60,65,88,190],"56":[39,17,114,58,60,65,88,190],"89":[39,17,114,58,60,65,88,190],"96":[39,17,114,58,60,65,88,190],"101":[39,17,114,58,60,65,88,190],"125":[39,17,114,58,60,65,88,190],"160":[39,17,114,58,60,65,88,190],"181":[39,17,114,58,60,65,88,190]},"packages/cli/src/modules/external-secrets.ee/secrets-providers-types.controller.ee.ts":{"15":[39,17,114,58,60,65,88,190],"24":[39,17,114,58,60,65,88,190],"40":[39,17,114,58,60,65,88,190],"43":[39,17,114,58,60,65,88,190],"50":[39,17,114,58,60,65,88,190]},"packages/cli/src/modules/external-secrets.ee/types.ts":{"34":[39,17,114,58,60,209,210,88,190],"60":[39,17,114,58,60,209,210,88,190],"87":[39,17,114,58,60,209,210,88,190],"105":[39,17,114,58,60,209,210,88,190],"106":[39,17,114,58,60,209,210,88,190],"112":[39,17,114,58,60,209,210,88,190]},"packages/cli/src/scheduling/scheduler-tracer.ts":{"13":[192,8,17,215,208,195,217,185,190],"15":[192,8,17,215,208,195,217,185,190]},"packages/cli/src/user-management/email/user-management-mailer.ts":{"33":"b:AAACAAAACFRgBAAhAAAAAAAAANAAAAAAABgABAA=","37":"b:AAACAAAACFRgBAAhAAAAAAAAANAAAAAAABgABAA=","71":"b:AAACAAAACFRgBAAhAAAAAAAAANAAAAAAABgABAA=","88":"b:AAACAAAACFRgBAAhAAAAAAAAANAAAAAAABgABAA=","99":"b:AAACAAAACFRgBAAhAAAAAAAAANAAAAAAABgABAA=","110":"b:AAACAAAACFRgBAAhAAAAAAAAANAAAAAAABgABAA=","120":"b:AAACAAAACFRgBAAhAAAAAAAAANAAAAAAABgABAA=","130":"b:AAACAAAACFRgBAAhAAAAAAAAANAAAAAAABgABAA=","158":"b:AAACAAAACFRgBAAhAAAAAAAAANAAAAAAABgABAA=","187":"b:AAACAAAACFRgBAAhAAAAAAAAANAAAAAAABgABAA=","210":"b:AAACAAAACFRgBAAhAAAAAAAAANAAAAAAABgABAA=","236":"b:AAACAAAACFRgBAAhAAAAAAAAANAAAAAAABgABAA=","257":"b:AAACAAAACFRgBAAhAAAAAAAAANAAAAAAABgABAA=","267":"b:AAACAAAACFRgBAAhAAAAAAAAANAAAAAAABgABAA=","284":"b:AAACAAAACFRgBAAhAAAAAAAAANAAAAAAABgABAA=","298":"b:AAACAAAACFRgBAAhAAAAAAAAANAAAAAAABgABAA=","312":"b:AAACAAAACFRgBAAhAAAAAAAAANAAAAAAABgABAA=","316":"b:AAACAAAACFRgBAAhAAAAAAAAANAAAAAAABgABAA=","321":"b:AAACAAAACFRgBAAhAAAAAAAAANAAAAAAABgABAA=","337":"b:AAACAAAACFRgBAAhAAAAAAAAANAAAAAAABgABAA=","341":"b:AAACAAAACFRgBAAhAAAAAAAAANAAAAAAABgABAA=","346":"b:AAACAAAACFRgBAAhAAAAAAAAANAAAAAAABgABAA=","362":"b:AAACAAAACFRgBAAhAAAAAAAAANAAAAAAABgABAA=","366":"b:AAACAAAACFRgBAAhAAAAAAAAANAAAAAAABgABAA=","371":"b:AAACAAAACFRgBAAhAAAAAAAAANAAAAAAABgABAA=","380":"b:AAACAAAACFRgBAAhAAAAAAAAANAAAAAAABgABAA=","385":"b:AAACAAAACFRgBAAhAAAAAAAAANAAAAAAABgABAA=","386":"b:AAACAAAACFRgBAAhAAAAAAAAANAAAAAAABgABAA=","399":"b:AAACAAAACFRgBAAhAAAAAAAAANAAAAAAABgABAA=","404":"b:AAACAAAACFRgBAAhAAAAAAAAANAAAAAAABgABAA=","409":"b:AAACAAAACFRgBAAhAAAAAAAAANAAAAAAABgABAA=","425":"b:AAACAAAACFRgBAAhAAAAAAAAANAAAAAAABgABAA="},"packages/frontend/@n8n/design-system/src/components/N8nFormInput/FormInput.vue":{"56":[107,108,17,46,58,60,99,152,100,182],"82":[107,108,17,46,58,60,99,152,100,182],"122":[108,46,58,60,99,152,100,182],"128":[108,46,58,60,99,152,100],"133":[107,108,46,58,60,99,152,100,182],"137":[46],"143":[107,108,17,46,58,60,99,152,100,182],"161":[107,108,17,46,58,60,99,152,100,182],"167":[107,108,17,46,58,60,99,152,100,182],"173":[108,46,58,152,100],"176":[107,108,17,46,58,60,99,152,100,182],"196":[46],"198":[46],"214":[107,108,17,46,58,60,99,152,100,182],"215":[46,58],"232":[46,99],"234":[46,99],"268":[46]},"packages/frontend/@n8n/design-system/src/components/N8nUserInfo/UserInfo.vue":{"22":[17,46,58,60,69],"29":[17,46,58,60,69],"35":[17,46,58,60,69],"44":[46],"45":[46],"50":[17,46,58,60,69],"54":[46],"58":[17,46,58,60,69]},"packages/frontend/@n8n/design-system/src/components/N8nUserSelect/UserSelect.vue":{"31":[17,46,58,60],"53":[17,46,58,60],"56":[17,46,58,60],"60":[46],"76":[17,46,58,60],"77":[17,46,58,60],"93":[17,46,58],"101":[17,46],"102":[17,46,58],"104":[46],"107":[46],"116":[17,46,58,60],"119":[17,46,58,60],"140":[17,46,58,60],"142":[17,46,58,60],"152":[17,46,58,60],"159":[17,46,58,60]},"packages/frontend/@n8n/rest-api-client/src/api/secretsProvider.ee.ts":{"11":[17,46,58,60,65],"17":[17,46,58,60,65],"23":[46],"30":[46],"43":[46],"60":[46],"74":[46],"85":[46],"96":[46,65],"107":[17,46,58,60],"118":[46],"130":[46],"148":[46],"164":[46],"176":[46]},"packages/frontend/editor-ui/src/app/composables/useLatestFetch.ts":{"4":"b:AAICIICpAB5iAEAJGBAEAoABAFEAAQDBAAAAAAA=","6":"b:AAAAAICBAB4AAEAJCBAEAoABABAAAQDAAAAAAAA="},"packages/frontend/editor-ui/src/app/utils/modules/tabUtils.ts":{"11":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","34":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","38":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/chatHub/ChatWorkflowAgentsView.vue":{"30":[17],"31":[17],"32":[17],"49":[17],"68":[17],"76":[17]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectDeleteDialog.vue":{"62":[17,58,60]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectExternalSecrets.vue":{"27":[17,58,60],"53":[17,58,60],"58":[17,58,60],"66":[17,58,60],"70":[17,58,60],"77":[17,58,60],"90":[17,58,60],"117":[17,58,60],"121":[17,58,60],"132":[17,58,60],"180":[17,58,60],"188":[17,58,60],"264":[17,58,60],"265":[17,58,60],"275":[17,58,60],"291":[17,58,60],"307":[17,58,60],"309":[17,58,60],"312":[17,58,60],"315":[17,58,60],"324":[17,58,60],"332":[17,58,60]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectHeader.vue":{"46":"b:AAICAIAIAB4CAAABAAAEAIABABAAAABAAAAAAAA=","48":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","50":"b:AAICAIAIAB4CAAABAAAEAIABABAAAABAAAAAAAA=","70":"b:AAICAIAIAB4CAAABAAAEAIABABAAAABAAAAAAAA=","82":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","84":[45,60,88],"86":"b:AAICIICoAB5CAAABAAAEAIABAFAAAABBAAAAAAA=","90":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","107":"b:AAICIICoAB5CAAABAAAEAIABAFAAAABBAAAAAAA=","110":[152],"113":[152],"117":[29,43,45,47,114,58,59,60,158,70,88],"121":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","132":"b:AAIAIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","139":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","149":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","152":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","157":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","170":"b:AAAAAICAAB4AAEAJABAEAoABABAAAQDBAAAAAAA=","180":[29,43,9,45,59,60,65,158,70],"190":[47,114],"200":[152],"218":"b:AAIAIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","225":"b:AAIAIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","241":"b:AAIAIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","314":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","320":[29,43,9,45,156,158,70,190],"330":[156,190],"341":[29,43,9,45,156,158,70,190],"354":[156,190],"364":[29,43,9,45,158,70],"376":[57,136],"379":[47,114],"385":[152],"394":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","414":"b:AAICAIAIAB4CAAABAAAEAIABABAAAABAAAAAAAA=","422":"b:AAICAIAIAB4CAAABAAAEAIABABAAAABAAAAAAAA=","432":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","446":[58],"457":"b:AAIAIACoAAJAAAAAAAAEAAABAFEAAABAAAAAAAA=","474":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","477":"b:AAAAIICoABxAAEAJABAEAgAAAEEAAQDBAAAAAAA=","482":[58],"509":"b:AAIAIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","516":[57,136],"517":"b:AAIAIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","522":[29,43,9,45,47,114,152,156,158,70,190]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectMembersAccessCell.vue":{"8":[17,58,60],"15":[17,58,60],"19":[17,58,60],"20":[17,58,60],"23":[17,58,60],"41":[17,58,60]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectMembersActionsCell.vue":{"6":[17,58,60],"17":[17,58,60]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectMembersRoleCell.vue":{"10":[17,58],"23":[17,58],"25":[17,58],"26":[17,58],"28":[17,58],"29":[17,58],"31":[17],"33":[17,58]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectMembersTable.vue":{"12":[17,58,60],"38":[17,58,60],"45":[17,58,60],"59":[17,58,60],"67":[17,58,60],"70":[17],"74":[17,58,60],"82":[17,58],"83":[17,58,60],"99":[17,58,60],"104":[17,58,60],"121":[17,58,60]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectRoleUpgradeDialog.vue":{"14":[17,58,60],"22":[17,58,60]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectTabs.vue":{"23":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","37":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","39":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","45":"b:AAICIICoAB5CAAABAAAEAIABAFAAAABBAAAAAAA=","47":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","90":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","103":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","124":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","144":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","145":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","161":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA="},"packages/frontend/editor-ui/src/features/collaboration/projects/views/ProjectSettings.vue":{"63":[17,58,60],"68":[17,58,60],"83":[17,58,60],"121":[17,58,60],"127":[17,58,60],"130":[17,58,60],"134":[17,58,60],"135":[17,58,60],"136":[17,58,60],"144":[17,58],"145":[17,58],"148":[17,58,60],"158":[17,58],"164":[17,58],"173":[17,58],"196":[17],"201":[17],"232":[58,60],"281":[17,58,60],"301":[58],"306":[58,60],"329":[58,60],"330":[58,60],"337":[58,60],"368":[58,60],"402":[58,60],"449":[17,58,60],"456":[60],"471":[17,58,60],"480":[17,58,60],"482":[17,58,60],"509":[17,58,60],"513":[17,58,60],"536":[17,58,60],"555":[17,58,60],"566":[17,58],"571":[17,58,60],"574":[17,58,60],"580":[17,58,60],"587":[17,58,60],"597":[17,58,60],"598":[17,58,60],"608":[17,58,60],"630":[17,58,60],"670":[17,58,60],"675":[17,58,60],"677":[17,58,60],"693":[17,58,60],"703":[17,58,60],"710":[17,58,60],"738":[17,58,60],"758":[17,58,60],"787":[17,58,60],"864":[17,58,60]},"packages/frontend/editor-ui/src/features/integrations/promotions.ee/components/PromotionBanners.vue":{"18":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","25":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","26":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","38":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","46":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","50":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","56":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","91":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","97":[47,114,121,58,60,156,168,86,88,184,190],"136":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA="},"packages/frontend/editor-ui/src/features/integrations/promotions.ee/composables/usePromotionChangeCount.ts":{"8":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","19":"b:AAICIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA="},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/composables/useSecretsProviderConnection.ee.ts":{"26":[17,46,58,60,65],"34":[46],"39":[46],"62":[46],"79":[46],"100":[46],"120":[46],"126":[46]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/composables/useSecretsProvidersList.ee.ts":{"21":[65],"22":[65],"24":[17,58,60,65],"35":[17,58,60,65],"64":[65],"68":[65],"72":[17,58,60,65],"77":[65]},"packages/frontend/editor-ui/src/features/roles/components/CustomRolesUpgradeModal.vue":{"16":[17,58,69]},"packages/frontend/editor-ui/src/features/roles/components/RoleContactAdminModal.vue":{"9":[17,58,69],"32":[17,58,69]},"packages/frontend/editor-ui/src/features/roles/components/RoleHoverPopover.vue":{"16":[17,58,69],"76":[17,58,69]},"packages/frontend/editor-ui/src/features/roles/components/RoleSelectDropdown.vue":{"18":[17,58,69],"21":[17,58,69],"81":[17,69],"84":[17,69],"96":[17,58,69],"97":[17,58,69],"101":[17,58,69],"109":[17,58,69],"138":[17,69],"140":[17,69],"165":[17,58,69],"182":[17,58,69],"196":[17,58,69],"205":[17,58,69],"211":[17,58,69],"220":[17,58,69],"226":[17,58],"231":[17,58,69],"242":[17,58,69],"252":[17,58,69],"260":[17,58,69]},"packages/frontend/editor-ui/src/features/roles/project/projectRoleScopes.ts":{"36":[17,58,60,69],"38":[17,58,60,69]},"packages/nodes-base/nodes/Files/ConvertToFile/ConvertToFile.node.ts":{"107":[214,56]},"packages/nodes-base/nodes/Files/ConvertToFile/actions/iCall.operation.ts":{"16":[214,56]},"packages/nodes-base/nodes/Files/ConvertToFile/actions/spreadsheet.operation.ts":{"94":[214,56]},"packages/nodes-base/nodes/Files/ConvertToFile/actions/toBinary.operation.ts":{"105":[214,56]},"packages/nodes-base/nodes/Files/ConvertToFile/actions/toJson.operation.ts":{"90":[214,56],"102":[214,56]},"packages/nodes-base/nodes/Files/ConvertToFile/actions/toText.operation.ts":{"78":[214,56]},"packages/nodes-base/nodes/HttpRequest/GenericFunctions.ts":{"31":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","42":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","56":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","71":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","80":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","81":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","84":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","90":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","103":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","154":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","156":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","167":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","260":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","265":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","270":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","277":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","303":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","317":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","319":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","321":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","333":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA="},"packages/nodes-base/nodes/HttpRequest/HttpRequest.node.ts":{"9":[30,42,110,9,45,194,130,56,76,169,80,15,177]},"packages/nodes-base/nodes/HttpRequest/V1/HttpRequestV1.node.ts":{"43":[30,42,110,9,45,194,130,56,76,169,80,15,177],"617":[30,42,110,9,45,194,130,56,76,169,80,15,177],"811":[30,42,110,9,45,194,130,56,76,169,80,15,177],"888":[30,42,110,9,45,194,130,56,76,169,80,15,177],"1002":[30,42,110,9,45,194,130,56,76,169,80,15,177],"1009":[30,42,110,9,45,194,130,56,76,169,80,15,177],"1014":[30,42,110,9,45,194,130,56,76,169,80,15,177],"1158":[30,42,110,9,45,194,130,56,76,169,80,15,177]},"packages/nodes-base/nodes/HttpRequest/V2/HttpRequestV2.node.ts":{"47":[30,42,110,9,45,194,130,56,76,169,80,15,177],"632":[30,42,110,9,45,194,130,56,76,169,80,15,177],"883":[30,42,110,9,45,194,130,56,76,169,80,15,177],"960":[30,42,110,9,45,194,130,56,76,169,80,15,177],"1083":[30,42,110,9,45,194,130,56,76,169,80,15,177],"1089":[30,42,110,9,45,194,130,56,76,169,80,15,177],"1094":[30,42,110,9,45,194,130,56,76,169,80,15,177],"1107":[30,42,110,9,45,194,130,56,76,169,80,15,177],"1250":[30,42,110,9,45,194,130,56,76,169,80,15,177]},"packages/nodes-base/nodes/HttpRequest/V3/Description.ts":{"11":[30,42,110,9,45,194,130,56,76,169,80,15,177],"1268":[30,42,110,9,45,194,130,56,76,169,80,15,177]},"packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts":{"55":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","62":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","66":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","75":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","110":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","400":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","517":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","653":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","695":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","755":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","774":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","785":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","790":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","805":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","811":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","834":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","836":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","837":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","981":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","1143":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","1206":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA="},"packages/nodes-base/nodes/HttpRequest/V3/utils/binaryData.ts":{"3":[30,42,110,9,45,194,130,56,76,169,80,15,177]},"packages/nodes-base/nodes/HttpRequest/V3/utils/buffer-decoding.ts":{"13":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","36":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA="},"packages/nodes-base/nodes/HttpRequest/V3/utils/error-details.ts":{"13":[30,42,110,9,45,194,130,56,76,169,80,15,177],"35":[30,42,110,9,45,194,130,56,76,169,80,15,177],"48":[30,42,110,9,45,194,130,56,76,169,80,15,177]},"packages/nodes-base/nodes/HttpRequest/V3/utils/parse.ts":{"1":[30,42,110,9,45,194,130,56,76,169,80,15,177]},"packages/nodes-base/nodes/HttpRequest/shared/optimizeResponse.ts":{"20":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","37":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","38":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","42":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","55":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","63":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","92":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","97":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","127":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","128":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","179":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","194":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","226":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA=","255":"b:AIIAQAAkAAEAEAEAAEAAAAQAAAAAAgIABACAAAA="},"packages/nodes-base/nodes/ICalendar/createEvent.operation.ts":{"275":[214,56]},"packages/nodes-base/nodes/RespondToWebhook/RespondToWebhook.node.ts":{"359":[214,222,212,56,224,185],"367":[214,222,212,56,224,185],"391":[214,222,212,56,224,185],"471":[214,222,212,56,224,185],"537":[214,222,212,56,224,185]},"packages/nodes-base/nodes/RespondToWebhook/utils/binary.ts":{"5":[214,222,56,224,185],"16":[214,222,56,224,185]},"packages/nodes-base/nodes/RespondToWebhook/utils/outputs.ts":{"1":[214,222,56,224,185]},"packages/nodes-base/utils/binary.ts":{"37":[214,53,132,56],"87":[214,53,132,56],"139":[214,53,132,56],"155":[214,53,132,56],"189":[214,53,132,56],"218":[214,53,132,56],"221":[214,53,132,56],"230":[214,53,132,56],"233":[214,53,132,56]},"packages/workflow/src/auth-redaction.ts":{"8":[10,54,12,56,217],"16":[10,54,12,56,217],"25":[10,54,12,56,217]},"packages/cli/src/modules/policy-infrastructure/policy-decision-audit.ts":{"68":[71,72,73],"84":[71,72,73],"90":[71,72,73],"150":[71,72,73],"166":[71,72,73],"180":[71,72,73]},"packages/cli/src/modules/type-availability-policies/credential-type-policy-instance.controller.ts":{"36":[71,72,73],"41":[71,72,73],"55":[71,72,73],"80":[71,72,73],"97":[71,72,73],"104":[71,72,73],"116":[71,72,73],"136":[71,72,73],"149":[71,72,73]},"packages/cli/src/modules/type-availability-policies/credential-type-policy.check.ts":{"36":[71,72,73],"66":[71,72,73],"78":[71,72,73],"90":[71,72,73],"97":[71,72,73],"102":[71,72,73],"117":[71,72,73],"130":[71,72,73],"142":[71,72,73],"157":[71,72,73],"174":[71,72,73],"192":[71,72,73],"193":[71,72,73],"194":[71,72,73],"208":[71,72,73],"211":[71,72,73],"217":[71,72,73],"227":[71,72,73],"243":[71,72,73],"244":[71,72,73]},"packages/cli/src/modules/type-availability-policies/database/repositories/type-availability-policy-attachment.repository.ts":{"19":[71,72,73],"30":[71,72,73],"39":[71,72,73],"53":[71,72,73],"82":[71,72,73],"87":[71,72,73],"95":[71,72,73],"118":[71,72,73],"133":[71,72,73],"138":[71,72,73],"156":[71,72,73],"161":[71,72,73]},"packages/cli/src/modules/type-availability-policies/database/repositories/type-availability-policy-scope.repository.ts":{"24":[71,72,73],"29":[71,72,73],"39":[71,72,73],"56":[71,72,73],"70":[71,72,73],"88":[71,72,73],"115":[71,72,73],"127":[71,72,73],"138":[71,72,73],"147":[71,72,73],"153":[71,72,73],"167":[71,72,73],"193":[71,72,73],"197":[71,72,73],"223":[71,72,73],"229":[71,72,73],"251":[71,72,73],"263":[71,72,73],"277":[71,72,73]},"packages/cli/src/modules/type-availability-policies/database/repositories/type-availability-policy.repository.ts":{"21":[71,72,73],"27":[71,72,73],"32":[71,72,73],"46":[71,72,73],"69":[71,72,73],"91":[71,72,73],"100":[71,72,73],"116":[71,72,73],"139":[71,72,73],"145":[71,72,73],"162":[71,72,73]},"packages/cli/src/modules/type-availability-policies/node-type-policy.check.ts":{"28":[71,72,73],"30":[71,72,73],"33":[71,72,73],"58":[71,72,73],"68":[71,72,73],"80":[71,72,73],"87":[71,72,73],"92":[71,72,73],"107":[71,72,73],"118":[71,72,73],"129":[71,72,73],"134":[71,72,73],"143":[71,72,73],"159":[71,72,73],"160":[71,72,73]},"packages/cli/src/modules/type-availability-policies/package-resolver.ts":{"25":[71,72,73],"28":[71,72,73],"45":[71,72,73],"58":[71,72,73],"63":[71,72,73],"80":[71,72,73],"86":[71,72,73],"89":[71,72,73],"97":[71,72,73],"112":[71,72,73]},"packages/cli/src/modules/type-availability-policies/policy-evaluator.ts":{"51":[71,72,73],"60":[71,72,73],"83":[71,72,73],"84":[71,72,73],"86":[71,72,73],"87":[71,72,73],"101":[71,72,73],"116":[71,72,73],"134":[71,72,73],"147":[71,72,73],"177":[71,72,73]},"packages/cli/src/modules/type-availability-policies/policy-shadow-lint.ts":{"24":[71,72,73],"38":[71,72,73],"72":[71,72,73],"75":[71,72,73],"86":[71,72,73],"88":[71,72,73]},"packages/cli/src/modules/type-availability-policies/type-availability-policy-instance.controller.ts":{"36":[71,72,73],"41":[71,72,73],"55":[71,72,73],"80":[71,72,73],"97":[71,72,73],"104":[71,72,73],"116":[71,72,73],"136":[71,72,73],"149":[71,72,73]},"packages/cli/src/modules/type-availability-policies/type-availability-policy.service.ts":{"97":[71,72,73],"105":[71,72,73],"107":[71,72,73],"114":[71,72,73],"116":[71,72,73],"159":[71,72,73],"193":[71,72,73],"194":[71,72,73],"197":[71,72,73],"198":[71,72,73],"214":[71,72,73],"234":[71,72,73],"262":[71,72,73],"279":[71,72,73],"284":[71,72,73],"294":[71,72,73],"304":[71,72,73],"331":[71,72,73],"377":[71,72,73],"409":[71,72,73],"418":[71,72,73],"474":[71,72,73],"493":[71,72,73],"531":[71,72,73],"547":[71,72,73],"594":[71,72,73],"633":[71,72,73],"634":[71,72,73],"663":[71,72,73],"667":[71,72,73],"672":[71,72,73],"700":[71,72,73],"708":[71,72,73],"722":[71,72,73],"726":[71,72,73],"735":[71,72,73],"780":[71,72,73],"804":[71,72,73],"861":[71,72,73],"1006":[71,72,73],"1026":[71,72,73],"1045":[71,72,73],"1062":[71,72,73],"1074":[71,72,73],"1081":[71,72,73],"1091":[71,72,73],"1095":[71,72,73],"1096":[71,72,73],"1109":[71,72,73],"1142":[71,72,73],"1156":[71,72,73],"1169":[71,72,73],"1207":[71,72,73],"1217":[71,72,73],"1240":[71,72,73],"1243":[71,72,73],"1251":[71,72,73],"1264":[71,72,73]},"packages/nodes-base/nodes/Postgres/Postgres.node.ts":{"8":[71,72,73,167]},"packages/nodes-base/nodes/Postgres/transport/index.ts":{"27":[71,72,73,167],"47":[71,72,73,167],"50":[71,72,73,167],"56":[71,72,73,167],"91":[71,72,73,167],"92":[71,72,73,167],"96":[71,72,73,167],"100":[71,72,73,167],"106":[71,72,73,167],"114":[71,72,73,167],"121":[71,72,73,167],"138":[71,72,73,167],"156":[71,72,73,167],"157":[71,72,73,167],"162":[71,72,73,167],"168":[71,72,73,167],"186":[71,72,73,167],"208":[71,72,73,167]},"packages/nodes-base/nodes/Postgres/v1/PostgresV1.node.ts":{"288":[71,72,73,167],"297":[71,72,73,167],"331":[71,72,73,167]},"packages/nodes-base/nodes/Postgres/v1/genericFunctions.ts":{"13":[71,72,73,167],"27":[71,72,73,167],"33":[71,72,73,167],"36":[71,72,73,167],"55":[71,72,73,167],"62":[71,72,73,167],"78":[71,72,73,167],"83":[71,72,73,167],"88":[71,72,73,167],"92":[71,72,73,167],"105":[71,72,73,167],"119":[71,72,73,167],"121":[71,72,73,167],"136":[71,72,73,167],"157":[71,72,73,167],"182":[71,72,73,167],"198":[71,72,73,167],"200":[71,72,73,167],"224":[71,72,73,167],"231":[71,72,73,167],"255":[71,72,73,167],"291":[71,72,73,167],"307":[71,72,73,167],"308":[71,72,73,167],"314":[71,72,73,167],"327":[71,72,73,167],"346":[71,72,73,167],"383":[71,72,73,167],"398":[71,72,73,167],"399":[71,72,73,167],"405":[71,72,73,167],"418":[71,72,73,167],"425":[71,72,73,167],"450":[71,72,73,167],"494":[71,72,73,167],"510":[71,72,73,167],"511":[71,72,73,167],"517":[71,72,73,167],"520":[71,72,73,167],"537":[71,72,73,167],"546":[71,72,73,167],"558":[71,72,73,167],"561":[71,72,73,167],"587":[71,72,73,167],"626":[71,72,73,167],"641":[71,72,73,167],"642":[71,72,73,167],"648":[71,72,73,167],"651":[71,72,73,167],"668":[71,72,73,167],"677":[71,72,73,167],"690":[71,72,73,167],"693":[71,72,73,167],"721":[71,72,73,167]},"packages/nodes-base/nodes/Postgres/v2/PostgresV2.node.ts":{"16":[71,72,73,167],"25":[71,72,73,167]},"packages/nodes-base/nodes/Postgres/v2/actions/database/deleteTable.operation.ts":{"88":[71,72,73,167]},"packages/nodes-base/nodes/Postgres/v2/actions/database/executeQuery.operation.ts":{"55":[71,72,73,167],"65":[71,72,73,167],"119":[71,72,73,167],"120":[71,72,73,167]},"packages/nodes-base/nodes/Postgres/v2/actions/database/insert.operation.ts":{"161":[71,72,73,167]},"packages/nodes-base/nodes/Postgres/v2/actions/database/select.operation.ts":{"79":[71,72,73,167]},"packages/nodes-base/nodes/Postgres/v2/actions/database/update.operation.ts":{"195":[71,72,73,167],"279":[71,72,73,167],"286":[71,72,73,167],"333":[71,72,73,167]},"packages/nodes-base/nodes/Postgres/v2/actions/database/upsert.operation.ts":{"194":[71,72,73,167],"286":[71,72,73,167],"298":[71,72,73,167]},"packages/nodes-base/nodes/Postgres/v2/actions/router.ts":{"15":[71,72,73,167]},"packages/nodes-base/nodes/Postgres/v2/helpers/utils.ts":{"27":[71,72,73,167],"36":[71,72,73,167],"46":[71,72,73,167],"50":[71,72,73,167],"51":[71,72,73,167],"54":[71,72,73,167],"58":[71,72,73,167],"63":[71,72,73,167],"70":[71,72,73,167],"79":[71,72,73,167],"87":[71,72,73,167],"138":[71,72,73,167],"144":[71,72,73,167],"165":[71,72,73,167],"194":[71,72,73,167],"206":[71,72,73,167],"221":[71,72,73,167],"240":[71,72,73,167],"248":[71,72,73,167],"325":[71,72,73,167],"328":[71,72,73,167],"329":[71,72,73,167],"336":[71,72,73,167],"367":[71,72,73,167],"370":[71,72,73,167],"373":[71,72,73,167],"380":[71,72,73,167],"390":[71,72,73,167],"406":[71,72,73,167],"427":[71,72,73,167],"467":[71,72,73,167],"509":[71,72,73,167],"515":[71,72,73,167],"531":[71,72,73,167],"532":[71,72,73,167],"540":[71,72,73,167],"541":[71,72,73,167],"544":[71,72,73,167],"551":[71,72,73,167],"554":[71,72,73,167],"561":[71,72,73,167],"576":[71,72,73,167],"606":[71,72,73,167],"622":[71,72,73,167],"627":[71,72,73,167],"634":[71,72,73,167],"639":[71,72,73,167],"642":[71,72,73,167],"659":[71,72,73,167],"666":[71,72,73,167],"687":[71,72,73,167],"690":[71,72,73,167],"708":[71,72,73,167],"725":[71,72,73,167],"766":[71,72,73,167],"768":[71,72,73,167],"780":[71,72,73,167],"786":[71,72,73,167],"795":[71,72,73,167]},"packages/nodes-base/nodes/Postgres/v2/methods/credentialTest.ts":{"10":[71,72,73,167]},"packages/nodes-base/nodes/Postgres/v2/methods/listSearch.ts":{"7":[71,72,73,167],"19":[71,72,73,167],"29":[71,72,73,167],"46":[71,72,73,167]},"packages/nodes-base/nodes/Postgres/v2/methods/loadOptions.ts":{"7":[71,72,73,167],"24":[71,72,73,167],"34":[71,72,73,167],"42":[71,72,73,167],"47":[71,72,73,167]},"packages/nodes-base/nodes/Postgres/v2/methods/resourceMapping.ts":{"67":[71,72,73,167],"82":[71,72,73,167],"105":[71,72,73,167],"107":[71,72,73,167]},"packages/nodes-base/utils/connection-pool-manager.ts":{"53":[71,72,73,167],"66":[71,72,73,167],"68":[71,72,73,167],"74":[71,72,73,167],"81":[71,72,73,167],"104":[71,72,73,167],"131":[71,72,73,167],"139":[71,72,73,167],"152":[71,72,73,167],"172":[71,72,73,167]},"packages/nodes-base/utils/postgres.ts":{"12":[71,72,73,167],"32":[71,72,73,167],"34":[71,72,73,167],"38":[71,72,73,167],"41":[71,72,73,167],"47":[71,72,73,167],"55":[71,72,73,167]},"localhost-37941/assets/index-Dv_brJ4-.js":{"3":[76]},"localhost-37941/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[76],"9":[76],"10":[76],"19":[76],"23":[76],"29":[76],"33":[76],"34":[76]},"localhost-37941/assets/verified-Dido3Ow4.js":{"8":[76]},"packages/@n8n/telemetry/src/validate.ts":{"19":"b:AAB8QABABwAAUFADAUDgDRACKAAkAEAAAEAAAAA=","23":[46,19,20,48,21,206,96,49,22],"27":"b:AAB8QABABwAAUFADAUDgDRACKAAkAEAAAEAAAAA=","31":"b:AAB8QABABwAAUFADAUDgDRACKAAkAEAAAEAAAAA=","35":"b:AAB8QABABwAAUFADAUDgDRACKAAkAEAAAEAAAAA=","39":"b:AAB8QABABwAAUFADAUDgDRACKAAkAEAAAEAAAAA=","43":"b:AAB8QABABwAAUFADAUDgDRACKAAkAEAAAEAAAAA=","54":"b:AAB8QABABwAAUFADAUDgDRACKAAkAEAAAEAAAAA=","58":[46,19,20,48,21,206,96,49,22],"62":"b:AAB8QABABwAAUFADAUDgDRACKAAkAEAAAEAAAAA=","74":"b:AAB8QABABwAAUFADAUDgDRACKAAkAEAAAEAAAAA=","104":[46,19,20,48,21,206,96,49,22,78],"111":[46,19,20,48,21,206,96,49,22],"117":[46,19,20,48,21,206,96,49,22],"121":[46,19,20,48,21,206,96,49,22],"122":[46,19,20,48,21,206,96,49,22],"130":"b:AAB8QABABwAAUFADAUDgDRACKAAkAEAAAEAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/compare-datasets.svg":{"11":[41,94,141,73,76,77,162,165,166,176]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/convert-to-file.svg":{"11":[41,94,56,141,73,76,77,162,165,166,167,176]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/extract-from-file.svg":{"11":[41,94,132,141,73,76,77,162,165,166,167,176]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/CodeNodeEditor.vue":{"34":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","54":[46,148,166,176],"55":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","56":[28,46,148,166,176],"59":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","60":[41,94,46,141,73,76,77,162,165,166,176],"61":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","68":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","69":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","70":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","73":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","80":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","83":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","92":"b:AAAAAABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","97":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","103":[28,46,148,166,176],"108":[28,46],"110":[46],"115":[28,46,148,166,176],"116":[28,46,148,166,176],"149":[46],"167":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","181":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA="},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/linter.ts":{"23":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","29":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","38":[28,46,148,166,176],"62":[46,166],"68":[46,166],"79":[46],"95":[46,148,166,176],"98":[46],"118":[46],"136":[46,148,166,176],"138":[46,148,166,176],"142":[46,148,166,176],"144":[46,148,166,176],"146":[46,148,166,176],"151":[46,166],"162":[46],"180":[46,166],"183":[46],"194":[46],"222":[46,166],"230":[46,166],"257":[46,148,166,176],"264":[46,166],"288":[46,148,166,176],"298":[46,166],"321":[46,148,166,176],"328":[46,166],"329":[46,166],"346":[46,166],"352":[46,166],"377":[46,148,166,176],"399":[46,148,166,176],"415":[46,148,166,176],"422":[46,166],"442":[46],"466":[46,166],"474":[46],"493":[46],"513":[46,148,166,176],"523":[46],"538":[46],"554":[46,148,166,176],"567":[46],"588":[46,148,166,176],"599":[46,166],"610":[46],"626":[46,166],"632":[46,166],"633":[46,166]},"packages/frontend/editor-ui/src/features/shared/editors/composables/useCodeEditor.ts":{"70":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","80":[46],"113":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","114":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","125":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","134":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","166":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEAAAAAAAA=","170":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","181":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","185":[28,94,46,148,166,176],"195":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEAAAAAAAA=","203":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEAAAAAAAA=","210":[46],"224":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","232":[46],"239":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","253":[28,46,148,166,176],"262":[46,176],"267":[46,176],"275":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","350":[46],"362":[46],"370":[28,41,94,46,141,73,76,77,162,165,166,176],"382":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","386":"b:AAAAAABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","403":[46],"408":[46],"417":[28,46,166,176],"431":[46],"443":[28,46,166,176],"453":[46],"455":[46]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/typescript/client/useTypescript.ts":{"28":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","37":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","44":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","57":[46,165],"68":[28,46,166],"85":[46],"89":[46],"117":[28,46,166],"125":[28,46,166],"135":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","136":"b:AAAAEABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA=","142":[46,166],"150":"b:AAAAAABCAAAAMgBAAAAAAAAgEABkAAEQAAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/edges/CanvasEdgeToolbar.vue":{"12":[46,60,146,147,148,76,162,78,165,18],"27":[46,60,146,147,148,76,162,78,165,18],"31":[46,60,146,147,148,76,162,78,165,18],"41":[46,146,147,76],"45":[46,76,78,165],"47":[46,60,146,147,148,76,162,78,165,18],"55":[46,60,146,147,148,76,162,78,165,18],"72":[46,60,146,147,148,76,162,78,165,18]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/edges/CanvasEdgeTooltip.vue":{"9":[46,60,146,147,148,76,162,78,165,18],"10":[46,60,146,147,148,76,162,78,165,18],"20":[46,60,146,147,148,76,162,78,165,18]},"packages/@n8n/api-types/src/dto/api-keys/create-api-key-request.dto.ts":{"5":[203,93,218,58,62,66,156,158,70,72,74]},"packages/@n8n/api-types/src/dto/api-keys/update-api-key-request.dto.ts":{"7":[203,93,218,58,62,66,156,158,70,72,74]},"packages/@n8n/api-types/src/schemas/credential-description.schema.ts":{"14":[203,46]},"packages/@n8n/api-types/src/schemas/scopes.schema.ts":{"14":[203,93,46,218,58,62,66,156,158,70,72,74]},"packages/@n8n/permissions/src/public-api-permissions.ee.ts":{"251":[203,92,93,218,58,62,66,69,156,158,70,72,74],"258":[203,92,93,218,58,62,66,69,156,158,70,72,74],"265":[203,92,93,218,58,62,66,69,156,158,70,72,74],"268":[203,92,93,218,58,62,66,69,156,158,70,72,74]},"packages/@n8n/permissions/src/types.ee.ts":{"75":[203,92,93,218,58,62,66,156,158,70,72,74],"129":[203,92,93,218,58,62,66,156,158,70,72,74]},"packages/cli/src/controllers/api-keys.controller.ts":{"26":[203,93,218,58,62,66,156,158,70,72,74],"36":[203,93,218,58,62,66,156,158,70,72,74],"43":[203,93,218,58,62,66,156,158,70,72,74],"68":[203,93,218,58,62,66,156,158,70,72,74],"82":[203,93,218,58,62,66,156,158,70,72,74],"97":[203,93,218,58,62,66,156,158,70,72,74],"115":[203,93,218,58,62,66,156,158,70,72,74],"131":[203,93,218,58,62,66,156,158,70,72,74]},"packages/cli/src/controllers/invitation.controller.ts":{"21":[203,93,218,58,62,69,158,70,74],"38":[203,93,218,58,62,69,158,70,74],"49":[203,93,218,58,62,69,158,70,74],"74":[203,93,218,58,62,69,158,70,74],"118":[203,93,218,58,62,69,158,70,74]},"packages/cli/src/public-api/media-types/content-type.ts":{"8":[203,92,93,218,58,62,156,158,70,72,74],"31":[203,92,93,218,58,62,156,158,70,72,74],"32":[203,92,93,218,58,62,156,158,70,72,74],"40":[203,92,93,218,58,62,156,158,70,72,74]},"packages/cli/src/public-api/media-types/request-body/json.request-body.ts":{"15":[203,92,93,218,58,62,156,158,70,72,74],"19":[203,92,93,218,58,62,156,158,70,72,74]},"packages/cli/src/public-api/public-api-controller.registry.ts":{"42":[203,92,93,218,58,62,156,158,70,72,74],"53":[203,92,93,218,58,62,156,158,70,72,74],"60":[203,92,93,218,58,62,156,158,70,72,74],"67":[203,92,93,218,58,62,156,158,70,72,74],"75":[203,92,93,218,58,62,156,158,70,72,74],"83":[203,92,93,218,58,62,156,158,70,72,74],"100":[203,92,93,218,58,62,156,158,70,72,74],"189":[203,92,93,218,58,62,156,158,70,72,74],"208":[203,92,93,218,58,62,156,158,70,72,74],"209":[203,92,93,218,58,62,156,158,70,72,74],"221":[203,92,93,218,58,62,156,158,70,72,74],"235":[203,92,93,218,58,62,156,158,70,72,74],"236":[203,92,93,218,58,62,156,158,70,72,74],"248":[203,92,93,218,58,62,156,158,70,72,74],"249":[203,92,93,218,58,62,156,158,70,72,74],"259":[203,92,93,218,58,62,156,158,70,72,74],"260":[203,92,93,218,58,62,156,158,70,72,74],"270":[203,92,93,218,58,62,156,158,70,72,74],"275":[203,92,93,218,58,62,156,158,70,72,74],"311":[203,92,93,218,58,62,156,158,70,72,74],"312":[203,92,93,218,58,62,156,158,70,72,74],"326":[203,92,93,218,58,62,156,158,70,72,74],"327":[203,92,93,218,58,62,156,158,70,72,74]},"packages/cli/src/public-api/public-api-route-resolver.ts":{"56":[203,92,93,218,58,62,156,158,70,72,74],"57":[203,92,93,218,58,62,156,158,70,72,74],"60":[203,92,93,218,58,62,156,158,70,72,74],"61":[203,92,93,218,58,62,156,158,70,72,74],"64":[203,92,93,218,58,62,156,158,70,72,74],"66":[203,92,93,218,58,62,156,158,70,72,74],"106":[203,92,93,218,58,62,156,158,70,72,74],"172":[203,92,93,218,58,62,156,158,70,72,74],"177":[203,92,93,218,58,62,156,158,70,72,74],"197":[203,92,93,218,58,62,156,158,70,72,74],"208":[203,92,93,218,58,62,156,158,70,72,74],"211":[203,92,93,218,58,62,156,158,70,72,74],"215":[203,92,93,218,58,62,156,158,70,72,74],"226":[203,92,93,218,58,62,156,158,70,72,74],"229":[203,92,93,218,58,62,156,158,70,72,74],"241":[203,92,93,218,58,62,156,158,70,72,74],"256":[203,92,93,218,58,62,156,158,70,72,74],"265":[203,92,93,218,58,62,156,158,70,72,74]},"packages/cli/src/public-api/v1/controllers/discover.public.controller.ts":{"26":[203]},"packages/cli/src/public-api/v1/controllers/users.public.controller.ts":{"48":[203,92,93,218,58,62,156,158,70,74],"60":[203,92,93,218,58,62,156,158,70,74],"74":[203,92,93,218,58,62,156,158,70,74],"100":[203,92,93,218,58,62,156,158,70,74],"113":[203,92,93,218,58,62,156,158,70,74],"140":[203,92,93,218,58,62,156,158,70,74],"155":[203,92,93,218,58,62,156,158,70,74],"172":[203,92,93,218,58,62,156,158,70,74]},"packages/cli/src/public-api/v1/handlers/discover/discover.service.ts":{"53":[203],"65":[203],"70":[203],"74":[203],"135":[203],"136":[203],"150":[203],"159":[203],"163":[203],"167":[203],"168":[203],"211":[203],"213":[203],"218":[203],"223":[203],"231":[203],"255":[203]},"packages/cli/src/public-api/v1/openapi-gen/decorator-routes.ts":{"51":[203],"76":[203],"89":[203],"95":[203],"124":[203],"153":[203],"161":[203],"186":[203],"203":[203],"227":[203],"253":[203],"329":[203],"334":[203]},"packages/cli/src/public-api/v1/openapi-gen/object-union-type.ts":{"13":[203],"15":[203],"28":[203],"35":[203]},"packages/cli/src/public-api/v1/openapi-gen/schema-modifiers.ts":{"6":[203]},"packages/cli/src/public-api/v1/openapi-gen/untyped-nullable.ts":{"14":[203],"16":[203],"26":[203]},"packages/cli/src/public-api/v1/shared/middlewares/global.middleware.ts":{"21":[203],"26":[203],"57":[203],"60":[203],"63":[203],"99":[203],"102":[203],"114":[203],"116":[203],"122":[203],"123":[203],"145":[203],"153":[203],"155":[203],"162":[203],"169":[203],"185":[203],"186":[203]},"packages/cli/src/public-api/v1/shared/public-api-scope-lookup.ts":{"9":[203],"19":[203],"27":[203],"33":[203],"43":[203],"63":[203],"75":[203]},"packages/cli/src/services/api-key-auth.strategy.ts":{"20":[203,93,218,208,58,62,156,158,70,72,74],"26":[203,93,218,208,58,62,156,158,70,72,74],"66":[203,93,218,208,58,62,156,158,70,72,74],"72":[203,93,218,208,58,62,156,158,70,72,74],"79":[203,93,218,208,58,62,156,158,70,72,74],"84":[203,93,218,208,58,62,156,158,70,72,74]},"packages/cli/src/services/auth-strategy.registry.ts":{"24":[203,92,93,218,208,58,62,156,158,70,72,74],"27":[203,92,93,218,208,58,62,156,158,70,72,74],"31":[203,92,93,218,208,58,62,156,158,70,72,74],"49":[203,92,93,218,208,58,62,156,158,70,72,74]},"packages/cli/src/services/public-api-key.service.ts":{"37":[203,93,218,58,62,66,69,156,158,70,72,74],"44":[203,93,218,58,62,66,69,156,158,70,72,74],"62":[203,93,218,58,62,66,69,156,158,70,72,74],"78":[203,93,218,58,62,66,69,156,158,70,72,74],"126":[203,93,218,58,62,66,69,156,158,70,72,74],"137":[203,93,218,58,62,66,69,156,158,70,72,74],"162":[203,93,218,58,62,66,69,156,158,70,72,74],"173":[203,93,218,58,62,66,69,156,158,70,72,74],"201":[203,93,218,58,62,66,69,156,158,70,72,74],"229":[203,93,218,58,62,66,69,156,158,70,72,74],"247":[203,93,218,58,62,66,69,156,158,70,72,74],"259":[203,93,218,58,62,66,69,156,158,70,72,74],"261":[203,93,218,58,62,66,69,156,158,70,72,74],"267":[203,93,218,58,62,66,69,156,158,70,72,74],"272":[203,93,218,58,62,66,69,156,158,70,72,74],"283":[203,93,218,58,62,66,69,156,158,70,72,74],"305":[203,93,218,58,62,66,69,156,158,70,72,74],"329":[203,93,218,58,62,66,69,156,158,70,72,74],"338":[203,93,218,58,62,66,69,156,158,70,72,74],"348":[203,93,218,58,62,66,69,156,158,70,72,74],"353":[203,93,218,58,62,66,69,156,158,70,72,74],"355":[203,93,218,58,62,66,69,156,158,70,72,74],"358":[203,93,218,58,62,66,69,156,158,70,72,74],"368":[203,93,218,58,62,66,69,156,158,70,72,74],"377":[203,93,218,58,62,66,69,156,158,70,72,74],"378":[203,93,218,58,62,66,69,156,158,70,72,74],"383":[203,93,218,58,62,66,69,156,158,70,72,74],"385":[203,93,218,58,62,66,69,156,158,70,72,74]},"packages/n8n-packages.handler.ts":{"32":[203],"65":[203],"75":[203],"77":[203],"78":[203],"89":[203],"99":[203],"108":[203]},"packages/@n8n/backend-network/src/http/parse-incoming-message.ts":{"3":[90,37,110,45,211,54],"5":[90,37,110,45,211,54],"55":[90,37,110,45,211,54],"77":[90,37,110,45,211,54],"108":[90,37,110,45,211,54]},"packages/cli/src/metrics/prometheus/active-workflow-metrics.service.ts":{"17":[37],"22":[37],"26":[37],"33":[37],"34":[37]},"packages/cli/src/metrics/prometheus/cached-metric-query.ts":{"19":[37],"37":[37],"51":[37],"57":[37],"69":[37],"83":[37],"91":[37],"96":[37],"102":[37]},"packages/cli/src/metrics/prometheus/database-metric-query.service.ts":{"33":[37],"42":[37],"46":[37],"50":[37],"54":[37],"58":[37],"62":[37],"66":[37],"70":[37],"81":[37],"85":[37],"89":[37],"93":[37],"97":[37]},"packages/cli/src/metrics/prometheus/instance-ai-metrics.service.ts":{"17":[37,19,20,116,117,21,49,22],"23":[37,19,20,116,117,21,49,22],"28":[37,19,20,116,117,21,49,22],"76":[37,19,20,116,117,21,49,22],"84":[37,19,20,116,117,21,49,22],"146":[37,19,20,116,117,21,49,22],"150":[37,19,20,116,117,21,49,22],"153":[37,19,20,116,117,21,49,22],"156":[37,19,20,116,117,21,49,22],"159":[37,19,20,116,117,21,49,22],"163":[37,19,20,116,117,21,49,22],"166":[37,19,20,116,117,21,49,22],"172":[37,19,20,116,117,21,49,22]},"packages/cli/src/metrics/prometheus/prometheus.service.ts":{"42":[37],"101":[37],"113":[37],"115":[37],"116":[37],"124":[37],"126":[37]},"packages/cli/src/metrics/prometheus/pss-metrics.service.ts":{"15":[37],"17":[37],"21":[37],"25":[37],"41":[37]},"packages/cli/src/modules/instance-ai/instance-ai-run-probe.ts":{"12":[37],"13":[37],"15":[37],"19":[37]},"packages/cli/src/modules/instance-ai/instance-ai.service.ts":{"286":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","300":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","306":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","317":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","341":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","367":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","378":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","382":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","402":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","405":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","411":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","429":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","449":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","457":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","520":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","534":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","552":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","559":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","564":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","573":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","577":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","584":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","589":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","642":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","710":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","722":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","726":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","742":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","833":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","878":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","881":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","895":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","923":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","926":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","935":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","949":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","961":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","962":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","963":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","972":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","989":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","993":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1002":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1012":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1025":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1032":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1045":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1055":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1071":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1092":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1109":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1120":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1167":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1180":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1197":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1212":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1240":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1244":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1253":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1260":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1274":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1278":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1313":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1314":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1327":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1331":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1367":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1410":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1423":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1435":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1439":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1440":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1450":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1454":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1485":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1523":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1592":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1603":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1611":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1616":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1624":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1644":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1726":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1735":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1766":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1770":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1783":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1799":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1813":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1820":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1824":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1828":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1847":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1859":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1878":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1886":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1958":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1959":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1960":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1962":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","1974":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2002":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2010":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2014":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2018":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2029":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2033":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2041":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2091":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2103":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2223":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2224":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2235":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2240":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2253":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2257":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2261":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2262":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2265":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2281":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2306":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2324":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2327":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2337":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2348":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2372":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2377":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2380":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2385":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2390":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2394":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2399":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2400":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2405":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2414":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2416":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2421":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2454":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2464":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2487":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2488":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2519":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2536":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2549":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2553":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2571":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2593":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2600":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2692":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2693":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2746":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2753":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2755":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2758":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2769":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2787":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2792":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2808":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2873":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2880":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2883":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2890":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2894":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2910":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2916":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2934":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2951":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2959":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2990":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2991":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2992":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2994":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","2996":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3027":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3037":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3057":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3069":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3088":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3112":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3141":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3153":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3165":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3176":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3227":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3270":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3292":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3302":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3311":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3340":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3344":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3397":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3454":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3458":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3468":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3481":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3494":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3512":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3529":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3592":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3595":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3600":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3619":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3621":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3625":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3627":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3631":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3633":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3647":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3649":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3660":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3675":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3686":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3705":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3719":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3721":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3729":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3746":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3748":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3750":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3757":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3774":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3819":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3853":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3860":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3864":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3868":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3887":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3902":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3923":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3957":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","3966":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","4156":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","4181":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","4262":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","4333":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","4337":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","4353":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","4425":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","4483":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","4508":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","4532":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","4540":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","4551":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","4563":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","5074":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","5083":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","5101":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","5130":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","5139":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","5172":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","5247":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","5266":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","5272":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","5311":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","5336":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","5377":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","5402":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","5501":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","5509":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","5528":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","5572":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","5576":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","5582":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","5600":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","5630":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","5658":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","5668":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","5688":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","5702":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","5712":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","5733":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","5753":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","5758":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","5766":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","5812":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","6001":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","6052":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","6110":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","6113":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","6122":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","6134":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","6678":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","6776":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","6794":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","6805":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","6821":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","6836":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","6865":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","6870":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","6876":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","6926":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","6933":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","6968":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","7017":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","7066":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","7081":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","7085":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","7093":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","7095":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","7108":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","7110":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","7121":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","7126":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","7140":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","7180":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","7221":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","7245":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","7263":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","7265":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","7269":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","7273":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","7311":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","7332":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","7354":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","7414":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","7441":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","7463":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","7466":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","7478":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","7483":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","7486":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA=","7492":"b:AAB4ACAAAwAAAAAAAQjwBQAAAAAAAAAAAEAAAAA="},"packages/cli/src/webhooks/webhook-blank-file-inputs.ts":{"10":[90,37,211,54,134],"23":[90,37,211,54,134],"45":[90,37,211,54,134]},"packages/cli/src/webhooks/webhook-form-data.ts":{"12":[90,37,211,54,134],"18":[90,37,211,54,134],"29":[90,37,211,54,134],"41":[90,37,211,54,134],"42":[90,37,211,54,134],"67":[90,37,211,54,134],"69":[90,37,211,54,134],"71":[90,37,211,54,134]},"packages/workflow/src/n8n-oauth2-auth.ts":{"25":[37,10,218],"32":[37,10,218],"36":[37,10,218],"45":[37,10,218],"80":[37,10,218]},"packages/@n8n/db/src/repositories/folder.repository.ts":{"16":"b:AAAAAICBAB4gAEAJHBgEAoABACAAAADAAAAAAAA=","20":"b:AAAAAICBAB4gAEAJHBgEAoABACAAAADAAAAAAAA=","31":"b:AAAAAICBAB4gAEAJHBgEAoABACAAAADAAAAAAAA=","45":"b:AAAAAICBAB4gAEAJHBgEAoABACAAAADAAAAAAAA=","53":"b:AAAAAICBAB4gAEAJHBgEAoABACAAAADAAAAAAAA=","58":"b:AAAAAICBAB4gAEAJHBgEAoABACAAAADAAAAAAAA=","69":"b:AAAAAICBAB4gAEAJHBgEAoABACAAAADAAAAAAAA=","81":"b:AAAAAICBAB4gAEAJHBgEAoABACAAAADAAAAAAAA=","86":"b:AAAAAICBAB4gAEAJHBgEAoABACAAAADAAAAAAAA=","96":"b:AAAAAICBAB4gAEAJHBgEAoABACAAAADAAAAAAAA=","115":"b:AAAAAICBAB4gAEAJHBgEAoABACAAAADAAAAAAAA=","128":"b:AAAAAICBAB4gAEAJHBgEAoABACAAAADAAAAAAAA=","134":"b:AAAAAICBAB4gAEAJHBgEAoABACAAAADAAAAAAAA=","166":"b:AAAAAICBAB4gAEAJHBgEAoABACAAAADAAAAAAAA=","170":"b:AAAAAICBAB4gAEAJHBgEAoABACAAAADAAAAAAAA=","174":"b:AAAAAICBAB4gAEAJHBgEAoABACAAAADAAAAAAAA=","178":"b:AAAAAICBAB4gAEAJHBgEAoABACAAAADAAAAAAAA=","195":"b:AAAAAICBAB4gAEAJHBgEAoABACAAAADAAAAAAAA=","228":"b:AAAAAICBAB4gAEAJHBgEAoABACAAAADAAAAAAAA=","239":"b:AAAAAICBAB4gAEAJHBgEAoABACAAAADAAAAAAAA=","255":"b:AAAAAICBAB4gAEAJHBgEAoABACAAAADAAAAAAAA=","265":"b:AAAAAICBAB4gAEAJHBgEAoABACAAAADAAAAAAAA=","279":"b:AAAAAICBAB4gAEAJHBgEAoABACAAAADAAAAAAAA=","294":"b:AAAAAICBAB4gAEAJHBgEAoABACAAAADAAAAAAAA=","304":"b:AAAAAICBAB4gAEAJHBgEAoABACAAAADAAAAAAAA=","320":"b:AAAAAICBAB4gAEAJHBgEAoABACAAAADAAAAAAAA=","339":"b:AAAAAICBAB4gAEAJHBgEAoABACAAAADAAAAAAAA=","356":"b:AAAAAICBAB4gAEAJHBgEAoABACAAAADAAAAAAAA=","396":"b:AAAAAICBAB4gAEAJHBgEAoABACAAAADAAAAAAAA=","430":"b:AAAAAICBAB4gAEAJHBgEAoABACAAAADAAAAAAAA=","439":"b:AAAAAICBAB4gAEAJHBgEAoABACAAAADAAAAAAAA=","473":"b:AAAAAICBAB4gAEAJHBgEAoABACAAAADAAAAAAAA="},"packages/@n8n/db/src/utils/list-query-sort.ts":{"8":"b:AAAgAICBAB4AAMAZHBgECoAAAAAAAABAAAAAAAA="},"packages/@n8n/db/src/utils/sql.ts":{"4":"b:AAAAIICpABxCAEAJHBAEAgAAAFAAAACAAAAAAAA="},"packages/@n8n/decorators/src/timed.ts":{"16":"b:AAAAAICBAB4AAEAJHBgEAoAAAAAAAADAAAAAAAA=","17":"b:AAAAAICBAB4AAEAJHBgEAoAAAAAAAADAAAAAAAA=","18":"b:AAAAAICBAB4AAEAJHBgEAoAAAAAAAADAAAAAAAA=","23":"b:AAAAAICBAB4AAEAJHBgEAoAAAAAAAADAAAAAAAA="},"packages/cli/src/middlewares/list-query/dtos/base.filter.dto.ts":{"7":"b:AAJoIIDpA15CCUAJHBgECAAAAAAAAAAIAAAAAAA=","23":"b:AAJoIIDpA15CCUAJHBgECAAAAAAAAAAIAAAAAAA="},"packages/cli/src/middlewares/list-query/dtos/pagination.dto.ts":{"6":"b:AAAgAICBAB4AAMAJHBgECoAAAAAAAABIAAAAAAA=","15":"b:AAAgAICBAB4AAMAJHBgECoAAAAAAAABIAAAAAAA="},"packages/cli/src/middlewares/list-query/dtos/workflow.filter.dto.ts":{"98":"b:AABoAICBA14ACEAJHBgECIAAAAAAAABIAAAAAAA="},"packages/cli/src/middlewares/list-query/dtos/workflow.sort-by.dto.ts":{"6":"b:AAAgAICBAB4AAMAJHBgECoAAAAAAAABAAAAAAAA=","13":"b:AAAgAICBAB4AAMAJHBgECoAAAAAAAABAAAAAAAA="},"packages/cli/src/modules/data-table/data-table-aggregate.service.ts":{"13":"b:AAAAAICBABwAAEAJHBgEAoAAAAAAAADAAAAAAAA=","21":"b:AAAAAICBABwAAEAJHBgEAoAAAAAAAADAAAAAAAA=","22":"b:AAAAAICBABwAAEAJHBgEAoAAAAAAAADAAAAAAAA=","24":"b:AAAAAICBABwAAEAJHBgEAoAAAAAAAADAAAAAAAA=","37":"b:AAAAAICBABwAAEAJHBgEAoAAAAAAAADAAAAAAAA="},"localhost-37657/assets/index-Dv_brJ4-.js":{"3":"b:ACAAAAAAAAAAAAAIACQAADD2ZiAKIAABAAAAAAA="},"localhost-37657/assets/rolldown-runtime-Bq5D3eIA.js":{"8":"b:ACAAAAAAAAAAAAAIACQAADD2ZiAKIAABAAAAAAA=","9":"b:ACAAAAAAAAAAAAAIACQAADD2ZiAKIAABAAAAAAA=","10":"b:ACAAAAAAAAAAAAAIACQAADD2ZiAKIAABAAAAAAA=","19":"b:ACAAAAAAAAAAAAAIACQAADD2ZiAKIAABAAAAAAA=","23":"b:ACAAAAAAAAAAAAAIACQAADD2ZiAKIAABAAAAAAA=","29":"b:ACAAAAAAAAAAAAAIACQAADD2ZiAKIAABAAAAAAA=","33":"b:ACAAAAAAAAAAAAAIACQAADD2ZiAKIAABAAAAAAA=","34":"b:ACAAAAAAAAAAAAAIACQAADD2ZiAKIAABAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/status-warning.svg":{"8":[91,46]},"packages/frontend/@n8n/design-system/src/components/N8nStatusDot/StatusDot.vue":{"13":[91,108,46,190,191]},"packages/frontend/@n8n/design-system/src/directives/n8n-truncate.ts":{"19":"b:AAIAAIDoAB5CAEAJABAEAgAAAEEAAQDAAAAAAAA="},"packages/frontend/@n8n/design-system/src/types/menu.ts":{"56":[91,46,165]},"packages/frontend/editor-ui/src/app/components/PublicationIndicator.vue":{"35":[91,108,190,191],"37":[91,108,190,191]},"packages/frontend/editor-ui/src/app/components/VersionUpdateCTA.vue":{"30":[91]},"packages/frontend/editor-ui/src/app/components/WorkflowCard.vue":{"61":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","141":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","144":"b:AAAAAICAABwAAEAJABAAAgAAAAAAAQDAAAAAAAA=","145":[190],"146":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","148":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","151":[60,88],"154":[60,88],"158":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","162":"b:AAAAAICAABwAAEAJABAAAgAAAAAAAQDAAAAAAAA=","173":"b:AAAAAICAABwAAEAJABAAAgAAAAAAAQDAAAAAAAA=","193":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","309":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","333":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","337":"b:AAAAAICAABwAAEAJABAAAgAAAAAAAQDAAAAAAAA=","343":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","368":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","380":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","384":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","386":[121,60,168,88,190],"415":[59,190],"501":[190],"511":[190],"547":[190],"551":[190],"589":[190],"638":[190],"678":[190],"680":[190],"682":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","693":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","705":[88],"725":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","755":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","772":"b:AAAAAICAABwAAEAJABAAAgAAAAAAAQDAAAAAAAA=","798":[190]},"packages/frontend/editor-ui/src/app/components/forms/ResourceFiltersDropdown.vue":{"22":"b:AAIAAIDoAB5CAEAJABAAAoABAEEAAQDAAAAAAAA=","51":[190],"63":"b:AAIAAIDoAB5CAEAJABAAAoABAEEAAQDAAAAAAAA=","66":"b:AAIAAICoAB5CAEAJABAAAoABAEEAAQDAAAAAAAA=","89":"b:AAIAAIDoAB5CAEAJABAAAoABAEEAAQDAAAAAAAA=","91":[190],"115":"b:AAIAAIDoAB5CAEAJABAAAoABAEEAAQDAAAAAAAA=","119":[190],"122":"b:AAIAAIDoAB5CAEAJABAAAoABAEEAAQDAAAAAAAA=","126":"b:AAIAAIDoAB5CAEAJABAAAoABAEEAAQDAAAAAAAA=","130":"b:AAIAAIDoAB5CAEAJABAAAoABAEEAAQDAAAAAAAA=","142":"b:AAIAAIDoAB5CAEAJABAAAoABAEEAAQDAAAAAAAA=","148":[190],"158":[190],"164":[190],"183":[190]},"packages/frontend/editor-ui/src/app/components/layouts/ResourcesListLayout.vue":{"150":"b:AAIAIIDoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","151":[46,190],"154":"b:AAIAIIDoAB5CAEAJABAEAoABAFEAAQDAAAAAAAA=","167":"b:AAIAIIDoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","177":"b:AAIAIIDoAB5CAEAJABAEAoABAFEAAQDAAAAAAAA=","181":"b:AAIAIIDoAB5CAEAJABAEAoABAEEAAQDAAAAAAAA=","185":[43,9,45,46,59,60,152,65,158,70],"210":[9,46,59,152,158,70],"254":"b:AAIAIIDoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","255":[46,190],"264":"b:AAIAIIDoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","265":[46],"271":"b:AAIAIIDoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","272":[46,47,135,57,136,59,88,190],"278":"b:AAIAIIDoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","279":[46],"285":"b:AAIAIIDoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","286":[46,57,152,190],"290":"b:AAIAIIDoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","291":[29,43,45,46,158,70],"297":"b:AAIAIIDoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","298":[46],"304":"b:AAIAIIDoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","311":"b:AAIAIIDoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","323":[46,47,114,121,58,60,156,168,86,88,184,190],"328":[43,9,46,57,136,152,65,158,70,190],"336":[46],"342":"b:AAIAIIDoAB5CAEAJABAEAoABAFEAAQDAAAAAAAA=","356":"b:AAIAAIDoAB5CAEAJABAAAoABAEEAAQDAAAAAAAA=","361":[190],"366":"b:AAIAIIDoAB5CAEAJABAEAoABAFEAAQDAAAAAAAA=","370":[46,114],"378":[9,46],"389":[29,43,45,46,47,114,135,57,136,59,158,70,88],"399":"b:AAAAIADoAApAAAABAAAEAIABAEAAAABAAAAAAAA=","407":[45,46,47,59,158,70,88],"414":"b:AAAAIADoAApAAAABAAAEAIABAEAAAABAAAAAAAA=","429":[46,152],"433":[46,190],"437":[29,43,45,46,47,114,135,57,136,59,158,70,88],"438":[29,43,45,46,47,114,135,57,136,59,158,70,88],"451":[43,9,45,46,59,60,65,158,70],"458":[46,152],"465":[9,46],"471":[46,190],"475":[46,57,152,190],"480":[46],"481":[46],"489":[9,46,114],"538":"b:AAIAIIDoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","588":"b:AAAAAIDAAB4AAEAJABAEAoABABAAAQDBAAAAAAA=","604":"b:AAIAIIDoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","622":"b:AAIAAIDoAB5CAEAJABAEAoABAEEAAQDAAAAAAAA=","637":"b:AAIAAIDoAB5CAEAJABAEAoABAEEAAQDAAAAAAAA=","647":[9],"648":"b:AAIAAIDoAB5CAEAJABAEAoABAEEAAQDAAAAAAAA=","650":"b:AAIAAICoAB5CAEAJABAEAoABAEEAAQDAAAAAAAA=","668":[190],"686":"b:AAIAAIDoAB5CAEAJABAAAoABAEEAAQDAAAAAAAA=","692":"b:AAIAAIDoAB5CAEAJABAAAoABAEEAAQDAAAAAAAA=","719":[43,9,45,46,59,60,65,158,70],"730":"b:AAAAAICAAB4AAEAJABAEAoABAAAAAQDAAAAAAAA=","760":[152],"764":[152],"775":[152,190]},"packages/frontend/editor-ui/src/app/composables/useAutoScrollOnDrag.ts":{"13":"b:AAAAAICBAB4gAEAJGBAEAoABABAAAQDBAAAAAAA=","20":"b:AAAAAICBAB4gAEAJGBAEAoABABAAAQDBAAAAAAA=","99":[135],"103":"b:AAAAAICBAB4gAEAJGBAEAoABABAAAQDBAAAAAAA=","108":"b:AAAAAICBAB4gAEAJGBAEAoABABAAAQDBAAAAAAA=","117":"b:AAAAAICAAB4AAEAJEBAEAoABABAAAQDBAAAAAAA=","125":"b:AAAAAACAABQAAEABEBAEAgAAABAAAQBBAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useN8nLocalStorage.ts":{"26":"b:AAIAIIDoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","29":"b:AAAAAIDAAB4AAEAJABAEAoABABAAAQDBAAAAAAA=","33":[46,114],"58":"b:AAAAAIDAAB4AAEAJABAEAoABABAAAQDBAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useResourcesListI18n.ts":{"8":"b:AAIAIIDoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","15":"b:AAIAAIDoAB5CAEAJABAEAoABAEEAAQDAAAAAAAA="},"packages/frontend/editor-ui/src/app/views/WorkflowsView.vue":{"187":"b:AAAAAICBAB4gAEAJGBAEAoABABAAAQDBAAAAAAA=","239":[135,57,136],"284":[135,57,136],"286":[135,57,136],"291":[135,57,136],"293":[135,57,136],"298":"b:AAAAAICAAB4AAEAJABAEAoABABAAAQDBAAAAAAA=","302":"b:AAAAAICBAB4gAEAJGBAEAoABABAAAQDBAAAAAAA=","306":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","308":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","312":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","316":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","323":"b:AAAAAICBAB4gAEAJGBAEAoABABAAAQDBAAAAAAA=","327":[47,135,57,136,59,88,190],"331":[47,135,57,136,59,88,190],"337":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","341":"b:AAAAAICBAB4gAEAJGBAEAoABABAAAQDBAAAAAAA=","345":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","349":"b:AAAAAICBAB4gAEAJGBAEAoABABAAAQDBAAAAAAA=","354":"b:AAAAAICBAB4gAEAJGBAEAoABABAAAQDBAAAAAAA=","361":[47,135,57,136,59,88,190],"367":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","373":[135,57,136],"379":[135,57,136],"384":[47,135,57,136,59,88,190],"390":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","392":[47,135,57,136,59,88,190],"396":[47,135,57,136,59,88,190],"405":[47,135,57,136,59,88,190],"430":[47,135,57,136,59,88,190],"453":[47,135,57,136,59,88,190],"465":[47,135,57,136,59,88,190],"493":[47,135,57,136,59,88,190],"502":[135,57,136],"506":"b:AAAAAICAAB4AAEAJABAEAoABABAAAQDBAAAAAAA=","507":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","546":[190],"561":"b:AAAAAICAAB4AAEAJABAEAoABABAAAQDBAAAAAAA=","575":[57,136,59,190],"586":[57,136,59],"595":[57,136,59],"601":[57,136,59],"605":"b:AAAAAICAAB4AAEAJABAEAoABABAAAQDBAAAAAAA=","618":"b:AAAAAICAAB4AAEAJABAEAoABABAAAQDBAAAAAAA=","622":"b:AAAAAICBAB4AAEAJCBAEAoABABAAAQDBAAAAAAA=","627":"b:AAAAAICAAB4AAEAJABAEAoABABAAAQDBAAAAAAA=","639":"b:AAAAAICBAB4gAEAJGBAEAoABABAAAQDBAAAAAAA=","649":"b:AAAAAICBAB4gAEAJGBAEAoABABAAAQDBAAAAAAA=","651":[135,57,136],"675":[59,190],"690":[136],"723":"b:AAAAAICAAB4AAEAJABAEAoABABAAAQDBAAAAAAA=","733":[114,57,136,59,156,190],"737":[114,57,136,59,156,190],"745":"b:AAAAAICBAB4gAEAJGBAEAoABABAAAQDBAAAAAAA=","767":"b:AAAAAACAABQAAEABEBAEAgAAABAAAQBBAAAAAAA=","787":"b:AAAAAICBABwgAEAJGBAAAgAAAAAAAADAAAAAAAA=","803":"b:AAAAAICBAB4gAEAJGBAEAoABABAAAQDBAAAAAAA=","860":"b:AAAAAICBAB4gAEAJGBAEAoABABAAAQDBAAAAAAA=","874":[190],"908":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","909":[135,57,136],"927":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","928":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","961":"b:AAAAAICBAB4gAEAJGBAEAoABABAAAQDBAAAAAAA=","982":[47,135,57,136,59,88,190],"990":[57,190],"1001":"b:AAAAAICAAB4AAEAJABAEAoABABAAAQDBAAAAAAA=","1031":[47,135,57,136,59,88,190],"1071":"b:AAAAAICBAB4gAEAJGBAEAoABABAAAQDBAAAAAAA=","1076":"b:AAAAAICBAB4gAEAJGBAEAoABABAAAQDBAAAAAAA=","1105":[190],"1286":[190],"1287":[190],"1311":[135,136],"1312":[135,136],"1318":[136],"1342":[135,57,136],"1387":[135],"1395":[135],"1414":[135],"1446":[57,136],"1677":[57,136],"1738":[57,136],"1776":[57],"1822":[136],"1857":[57,136],"1876":[136],"1892":[135],"2019":[59],"2046":[59],"2093":[135],"2106":[135],"2164":[136],"2247":"b:AAAAAICAAB4AAEAJABAEAoABABAAAQDBAAAAAAA=","2260":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","2327":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","2363":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","2373":[135,57,136],"2376":[135,57,136],"2377":[135,57,136],"2417":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","2420":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","2421":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","2460":[114,57,136,59,156,190],"2479":[190],"2492":[190],"2507":[190],"2523":[190],"2535":[57,59],"2537":[57,59]},"packages/frontend/editor-ui/src/experiments/credentialsAppSelection/stores/credentialsAppSelection.store.ts":{"14":"b:AAAAAICBAB4gAEAJGBAEAoABABAAAQDBAAAAAAA=","23":[40,60,99],"25":[40,60,99],"29":[40,60,99],"35":[40,60,99]},"packages/frontend/editor-ui/src/experiments/openWorkflowInAssistant/components/OpenInAssistantCardButton.vue":{"13":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","23":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","32":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA="},"packages/frontend/editor-ui/src/experiments/openWorkflowInAssistant/composables/useOpenInAssistantCard.ts":{"10":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","24":"b:AAAAAICAAB4AAEAJABAAAoABAAAAAQDAAAAAAAA=","28":[121,60,168,88,190]},"packages/frontend/editor-ui/src/experiments/personalizedTemplates/stores/personalizedTemplates.store.ts":{"66":"b:AAAAAICBAB4gAEAJGBAEAoABABAAAQDBAAAAAAA=","91":"b:AAAAAICAAB4AAEAJABAEAoABABAAAQDAAAAAAAA=","164":"b:AAAAAICBAB4gAEAJGBAEAoABABAAAQDBAAAAAAA="},"packages/frontend/editor-ui/src/experiments/personalizedTemplatesV3/stores/personalizedTemplatesV3.store.ts":{"13":"b:AAAAAIDBAB4gAEAJGBAEAoABABAAAQDBAAAAAAA=","27":"b:AAAAAIDAAA4AAEAIABAEAgABABAAAQDAAAAAAAA=","36":"b:AAAAAIDBAB4gAEAJGBAEAoABABAAAQDBAAAAAAA=","49":[46],"60":[46],"66":[46],"70":[46],"74":[46],"78":[46],"82":[46],"86":[46],"90":[46],"96":[46],"100":[46],"105":[46],"130":"b:AAAAAIDBAB4gAEAJGBAEAoABABAAAQDBAAAAAAA="},"packages/frontend/editor-ui/src/experiments/templateRecoV2/stores/templateRecoV2.store.ts":{"14":"b:AAAAAIDBAB4gAEAJGBAEAoABABAAAQDBAAAAAAA=","21":"b:AAAAAIDAAA4AAEAIABAEAgABABAAAQDAAAAAAAA=","28":[46],"40":[46],"44":[46],"48":[46],"55":[46],"58":[46],"64":[46],"70":[46],"76":[46],"82":[46]},"packages/frontend/editor-ui/src/features/agents/n8nChatPage/mergeRecentChats.ts":{"29":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","47":[91,95,114,59,60,100]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectCreateResource.vue":{"14":"b:AAIAIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","23":"b:AAIAIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","34":[57,136],"35":"b:AAIAIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/composables/useWorkflowsEmptyState.ts":{"19":"b:AAAAAICBABwAAEAJCBAAAgAAAAAAAQDAAAAAAAA=","20":"b:AAAAAICBAB4AAEAJCBAEAoABABAAAQDBAAAAAAA=","22":"b:AAAAAICBAB4AAEAJCBAEAoABABAAAQDBAAAAAAA=","28":[40,60,99],"32":[40,60,99],"40":[40,60,99]},"packages/frontend/editor-ui/src/features/workflows/readyToRun/components/ReadyToRunButton.vue":{"13":"b:AAIAIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","25":"b:AAIAIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","31":"b:AAIAIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA=","53":"b:AAIAIICoAB5CAEAJABAEAoABAFEAAQDBAAAAAAA="},"packages/modules/insights/frontend/src/components/InsightsSummary.vue":{"31":"b:AAAAIICoABxAAEAIABAEAgAAAEEAAQDAAAAAAAA=","44":"b:AAAAIICoABxAAEAIABAEAgAAAEEAAQDAAAAAAAA=","52":"b:AAAAIICoABxAAEAIABAEAgAAAEEAAQDAAAAAAAA=","54":"b:AAAAIICoABxAAEAIABAEAgAAAEEAAQDAAAAAAAA=","57":"b:AAAAIICoABxAAEAIABAEAgAAAEEAAQDAAAAAAAA=","58":"b:AAAAIICoABxAAEAIABAEAgAAAEEAAQDAAAAAAAA=","116":"b:AAAAIICoABxAAEAIABAEAgAAAEEAAQDAAAAAAAA=","131":"b:AAAAIICoABxAAEAIABAEAgAAAEEAAQDAAAAAAAA="},"packages/modules/insights/frontend/src/insights.api.ts":{"17":"b:AAAAIICoABxAAEAIHBAEAgAAAEEAAQDAAAAAAAA=","39":"b:AAAAIICoABxAAEAIHBAEAgAAAEEAAQDAAAAAAAA="},"packages/modules/insights/frontend/src/insights.constants.ts":{"21":"b:AAAAIICoABxAAEAIGBAEAgAAAEEAAQDAAAAAAAA=","22":"b:AAAAIICoABxAAEAIGBAEAgAAAEEAAQDAAAAAAAA=","23":"b:AAAAIICoABxAAEAIGBAEAgAAAEEAAQDAAAAAAAA=","24":"b:AAAAIICoABxAAEAIGBAEAgAAAEEAAQDAAAAAAAA=","25":"b:AAAAIICoABxAAEAIGBAEAgAAAEEAAQDAAAAAAAA="},"packages/modules/insights/frontend/src/insights.store.ts":{"13":"b:AAIAIICpAB5iAEAJHBgEAoABAFEAAQDBAAAAAAA=","18":"b:AAAAIICpABxgAEAJHBgEAgAAAEEAAQDAAAAAAAA=","22":"b:AAAAIICoABxAAEAIHBAEAgAAAEEAAQDAAAAAAAA=","26":"b:AAAAIICpABxgAEAJHBgEAgAAAEEAAQDAAAAAAAA=","31":"b:AAAAIICoABxAAEAIHBAEAgAAAEEAAQDAAAAAAAA="},"packages/modules/insights/frontend/src/insights.utils.ts":{"18":"b:AAAAIICoABxAAEAIGBAEAgAAAEEAAQDAAAAAAAA=","20":"b:AAAAIICoABxAAEAIGBAEAgAAAEEAAQDAAAAAAAA=","21":"b:AAAAIICoABxAAEAIGBAEAgAAAEEAAQDAAAAAAAA=","24":"b:AAAAIICoABxAAEAIGBAEAgAAAEEAAQDAAAAAAAA=","25":"b:AAAAIICoABxAAEAIGBAEAgAAAEEAAQDAAAAAAAA=","53":"b:AAAAIICoABxAAEAIGBAEAgAAAEEAAQDAAAAAAAA=","55":"b:AAAAIICoABxAAEAIGBAEAgAAAEEAAQDAAAAAAAA=","80":"b:AAAAIICoABxAAEAIABAEAgAAAEEAAQDAAAAAAAA=","97":"b:AAAAIICoABxAAEAIABAEAgAAAEEAAQDAAAAAAAA=","118":"b:AAAAIICoABxAAEAIABAEAgAAAEEAAQDAAAAAAAA="},"localhost-45085/assets/index-Dv_brJ4-.js":{"3":[56,170,183,187]},"localhost-45085/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[56,170,183,187],"9":[56,170,183,187],"10":[56,170,183,187],"19":[56,170,183,187],"23":[56,170,183,187],"29":[56,170,183,187],"33":[56,170,183,187],"34":[56,170,183,187]},"localhost-45085/assets/verified-Dido3Ow4.js":{"8":[56]},"packages/frontend/@n8n/design-system/src/components/N8nPulse/Pulse.vue":{"6":[103,46,54,56,170]},"packages/frontend/@n8n/design-system/src/components/N8nTree/Tree.vue":{"14":[3,105,46,131,56,169,18,82,174,175,84,85],"22":[3,105,46,131,56,169,18,82,174,175,84,85],"26":[3,105,46,131,56,169,18,82,174,175,84,85],"30":[3,105,46,131,56,169,18,82,174,175,84,85],"46":[3,105,46,131,56,169,18,82,174,175,84,85],"55":[3,105,46,131,56,169,18,82,174,175,84,85],"62":[3,105,46,131,56,169,18,82,174,175,84,85],"81":[46,18,82,175,85],"85":[46],"89":[46,18,82,175,85]},"packages/frontend/editor-ui/src/app/components/CopyInput.vue":{"21":[29,9,46,56,99,170],"39":[46,170],"50":[29,9,46,56,99,170],"56":[29,9,46,56,99,170]},"localhost-37657/assets/verified-Dido3Ow4.js":{"8":[109,141,143]},"packages/@n8n/db/src/entities/credentials-entity.ts":{"88":[213,9,158]},"packages/@n8n/backend-network/src/http/axios/legacy.ts":{"36":[30,110,45,215,130,134,169,172],"56":[30,110,45,215,130,134,169,172],"77":[30,110,45,215,130,134,169,172],"142":[30,110,45,215,130,134,169,172],"188":[30,110,45,215,130,134,169,172],"208":[30,110,45,215,130,134,169,172],"212":[30,110,45,215,130,134,169,172],"221":[30,110,45,215,130,134,169,172],"251":[30,110,45,215,130,134,169,172],"262":[30,110,45,215,130,134,169,172],"306":[30,110,45,215,130,134,169,172],"314":[30,110,45,215,130,134,169,172],"327":[30,110,45,215,130,134,169,172]},"packages/@n8n/backend-network/src/http/binary-string.ts":{"12":[30,110,45,215,130,169]},"packages/@n8n/backend-network/src/http/legacy-request.ts":{"48":[30,110,45,215,130,169,172]},"packages/cli/src/middlewares/list-query/dtos/credentials.filter.dto.ts":{"22":[29,43,9,45,46,59,60,65,70,72]},"packages/cli/src/modules/agents/repositories/agent-credential-dependency.repository.ts":{"17":[23,26,9,45,59,60,156,158,70],"24":[23,26,9,45,59,60,156,158,70],"25":[23,26,9,45,59,60,156,158,70],"70":[23,26,9,45,59,60,156,158,70],"71":[23,26,9,45,59,60,156,158,70],"79":[23,26,9,45,59,60,156,158,70],"83":[23,26,9,45,59,60,156,158,70],"94":[23,26,9,45,59,60,156,158,70],"108":[23,26,9,45,59,60,156,158,70]},"packages/core/src/execution-engine/node-execution-context/utils/request-helpers/legacy-request-adapter.ts":{"16":[30,110,45,215,130,169,172],"29":[30,110,45,215,130,169,172]},"packages/workflow/src/redaction-channels.ts":{"23":[30,110,45,130,62,169],"37":[30,110,45,130,62,169],"52":[30,110,45,130,62,169],"77":[30,110,45,130,62,169]},"localhost-36147/assets/index-Dv_brJ4-.js":{"3":[45]},"localhost-36147/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[45],"9":[45],"10":[45],"19":[45],"23":[45],"29":[45],"33":[45],"34":[45]},"packages/frontend/@n8n/design-system/src/components/N8nRecycleScroller/RecycleScroller.vue":{"8":[43,9,45,46,59,60,65,158,70],"24":[43,9,45,46,59,60,65,158,70],"25":[43,9,45,46,59,60,65,158,70],"44":[43,9,45,46,59,60,65,158,70],"46":[43,9,45,46,59,60,65,158,70],"56":[43,9,45,46,59,60,65,158,70],"57":[43,9,45,46,59,60,65,158,70],"68":[43,9,45,46,59,60,65,158,70],"72":[43,9,45,46,59,60,65,158,70],"73":[43,9,45,46,59,60,65,158,70],"75":[43,9,45,46,59,60,65,158,70],"77":[43,9,45,46,59,60,65,158,70],"90":[43,9,45,46,59,60,65,158,70],"100":[43,9,45,46,59,60,65,158,70],"104":[43,9,45,46,59,60,65,158,70],"114":[43,9,45,46,59,60,65,158,70],"118":[43,9,45,46,59,60,65,158,70],"131":[43,9,45,46,59,60,65,158,70],"141":[43,9,45,46,59,60,65,158,70],"147":[43,9,45,46,59,60,65,158,70],"148":[43,9,45,46,59,60,65,158,70],"167":[43,9,45,46,59,60,65,158,70],"170":[43,9,45,59,60,65,158,70],"205":[43,9,45,46,59,60,65,158,70],"212":[43,9,45,46,59,60,65,158,70],"214":[43,9,45,46,59,60,65,158,70]},"packages/frontend/editor-ui/src/app/components/DependencyPill.vue":{"31":[45,60,158,86,190,191],"33":[45,60,158,86,190,191],"39":[45,60,158,86,190,191],"41":[45,60,158,86,190,191],"45":[45,60,158,86,190,191],"51":[45,60,158,86,190,191],"109":[45,60,158,86,190,191],"112":[45,60,158,86,190,191]},"packages/frontend/editor-ui/src/app/components/layouts/ResourcesListEmptyState.vue":{"61":[152],"84":"b:AAIAIACoABpCAAAAAAAEAAABAFEAAABAAAAAAAA=","99":[43,152,65]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/sendConsoleMessage.ts":{"7":[110,45,130,62,169]},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useInstanceAiCredentialHelp.ts":{"21":[29,43,9,45,46,49,59,60,65,158,70],"38":[29,43,9,45,46,49,60,65,158,70],"42":[46],"50":[46]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialCard.vue":{"71":[43,9,45,46,59,60,65,158,70],"72":[43,9,45,46,59,60,65,158,70],"75":[43,9,45,46,59,60,65,158,70],"77":[43,9,45,46,59,60,65,158,70],"85":[43,9,45,46,59,60,65,158,70],"121":[43,9,45,46,59,60,65,158,70],"130":[43,9,45,46,59,60,65,158,70],"132":[45],"159":[59],"223":[59],"232":[43,9,45,46,59,60,65,158,70],"237":[43,9,45,46,59,60,65,158,70],"240":[43,9,45,46,59,60,65,158,70],"244":[45],"253":[43,9,45,46,59,60,65,158,70],"285":[43,9,45,46,59,60,65,158,70]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialsSelect.vue":{"21":[42,9,45,46],"36":[42,9,45,46],"37":[42,9,45,46],"43":[42,9,45,46],"44":[42,9,45,46],"47":[9,45,46],"57":[42,9,45,46],"87":[42,9,45,46],"95":[42,9,46],"104":[42,9,45,46],"105":[42,9,45,46],"128":[42,9,45,46],"142":[9,45,46],"143":[46],"144":[9,45,46],"145":[9,45,46],"146":[42,9,45,46],"148":[42,9,45,46],"154":[42,9,45,46],"176":[9,45,46]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialsSelectModal.vue":{"16":[29,43,9,45,46,60,65,158,70],"32":[29,43,9,45,46,60,65,158,70],"37":[29,43,9,45,46,60,65,158,70],"44":[29,43,9,45,46,60,65,158,70],"52":[29,43,9,45,46,60,65,158,70],"53":[29,43,9,45,46,60,65,158,70],"58":[29,43,9,45,46,60,65,158,70],"61":[29,43,9,45,46,60,65,158,70],"64":[29,43,9,45,46,60,65,158,70],"68":[29,43,9,45,46,60,65,158,70],"72":[29,43,9,45,46,60,65,158,70],"100":[29,43,9,45,46,60,65,158,70],"113":[29,43,9,45,46,60,65,158,70],"118":[29,43,9,45,46,60,65,158,70],"134":[29,43,9,45,46,60,65,158,70],"136":[29,43,9,45,46,60,65,158,70],"138":[29,43,9,45,46,60,65,158,70],"148":[29,43,9,45,46,60,65,158,70]},"packages/frontend/editor-ui/src/features/credentials/views/CredentialsView.vue":{"65":[29,43,45,46,158,70],"69":[46],"82":[43,9,45,46,59,60,65,158,70],"92":[43,9,45,46,59,60,65,158,70],"95":[29,43,9,45,46,59,60,65,158,70],"96":[43,9,45,46,59,60,65,158,70],"116":[46],"118":[46],"122":[29,43,9,45,46,59,60,65,158,70],"124":[29,43,9,45,46,59,60,65,158,70],"130":[46],"134":[46],"140":[43,45,46,65],"144":[43,9,45,46,60,65,158,70],"152":[43,46,65],"161":[29,43,9,45,46,59,60,65,158,70],"172":[43,9,45,46,59,60,65,158,70],"195":[29,43,9,45,46,59,60,65,158,70],"206":[29,43,9,45,46,59,60,65,158,70],"231":[29,43,9,45,46,59,60,65,158,70],"257":[9,45,46,59,60,158,70],"261":[29,43,9,45,46,59,60,65,158,70],"263":[43,9,45,46,60,65,158,70],"269":[46],"271":[46],"276":[29,43,9,45,46,59,60,65,158,70],"278":[29,43,9,45,46,59,60,65,158,70],"279":[29,43,9,45,46,60,65,158,70],"288":[29,43,9,45,46,59,60,65,158,70],"290":[46],"298":[29,43,9,45,46,59,60,65,158,70],"317":[29,43,9,45,46,59,60,65,158,70],"327":[43,9,45,46,59,60,65,158,70]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterIssues.vue":{"9":"b:QIIBQABkQBAAAIUEgAAAAAAIACCAAAUAAAAAAAA=","10":"b:QIIBQABkQBAAAIUEgAAAAAAIACCAAAUAAAAAAAA=","15":[46],"17":"b:QIABQABAQBAAAIUEgAAAAAAIACCAAAUAAAAAAAA="},"packages/@n8n/backend-common/src/utils/path-util.ts":{"9":[132],"27":[132],"40":[132],"46":[132],"55":[132],"63":[132]},"packages/cli/src/controllers/tags.controller.ts":{"20":[132,135,147,148,84,16,177,86,183,189,190],"24":[132,135,147,148,84,16,177,86,183,189,190],"30":[132,135,147,148,84,16,177,86,183,189,190],"43":[132,135,147,148,84,16,177,86,183,189,190],"56":[132,135,147,148,84,16,177,86,183,189,190]},"packages/core/src/utils/serialized-buffer.ts":{"10":[0,34,212,132,62],"14":[0,34,212,132,62]},"packages/nodes-base/nodes/Files/ExtractFromFile/ExtractFromFile.node.ts":{"117":[214,132]},"packages/nodes-base/nodes/Files/ExtractFromFile/actions/moveTo.operation.ts":{"106":[214,132]},"packages/nodes-base/nodes/Files/ExtractFromFile/actions/parseIcsCalendar.ts":{"4":[214,132]},"packages/nodes-base/nodes/Files/ExtractFromFile/actions/pdf.operation.ts":{"83":[214,132]},"packages/nodes-base/nodes/Files/ExtractFromFile/actions/spreadsheet.operation.ts":{"8":[214,132],"9":[214,132],"18":[214,132],"58":[214,132]},"packages/nodes-base/nodes/Files/ReadWriteFile/ReadWriteFile.node.ts":{"60":[132]},"packages/nodes-base/nodes/Files/ReadWriteFile/actions/read.operation.ts":{"96":[132]},"packages/nodes-base/nodes/Files/ReadWriteFile/actions/write.operation.ts":{"72":[132]},"packages/nodes-base/nodes/Files/ReadWriteFile/helpers/utils.ts":{"5":[132],"44":[132],"56":[132]},"packages/nodes-base/nodes/SpreadsheetFile/v2/fromFile.operation.ts":{"86":[214,132],"127":[214,132],"130":[214,132],"137":[214,132],"145":[214,132],"155":[214,132]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/read-write-files-from-disk.svg":{"11":[131,132]},"packages/@n8n/errors/src/response-errors/scope-forbidden.error.ts":{"4":[62]},"packages/@n8n/errors/src/response-errors/unprocessable.error.ts":{"4":[62]},"packages/cli/src/controllers/security-settings.controller.ts":{"14":[62,74],"24":[62,74],"40":[62,74],"82":[62,74],"86":[62,74],"91":[62,74]},"packages/cli/src/executions/execution-redaction.ts":{"44":[62]},"packages/cli/src/modules/redaction/executions/strategies/full-item-redaction.strategy.ts":{"17":[62],"20":[62],"25":[62],"82":[62],"95":[62],"113":[62]},"packages/cli/src/modules/redaction/instance-redaction-enforcement.service.ts":{"16":[62],"33":[62],"37":[62],"39":[62],"46":[62],"64":[62],"84":[62],"88":[62],"97":[62]},"packages/cli/src/modules/redaction/redaction-policy.ts":{"37":[62],"48":[62]},"packages/cli/src/public-api/v1/controllers/executions.public.controller.ts":{"54":[62],"60":[62],"91":[62],"106":[62],"172":[62],"228":[62],"255":[62],"281":[62],"298":[62],"311":[62],"316":[62],"355":[62],"394":[62],"436":[62],"445":[62],"469":[62],"494":[62],"504":[62],"521":[62],"531":[62],"540":[62],"550":[62]},"packages/cli/src/services/security-settings.service.ts":{"53":[62,74],"68":[62,74],"98":[62,74],"148":[62,74],"156":[62,74],"176":[62,74],"183":[62,74],"186":[62,74],"195":[62,74],"199":[62,74],"203":[62,74],"208":[62,74]},"packages/core/src/nodes-loader/output-schema-resolver.ts":{"53":"b:AAAAAAAAAgAAADAAAAAAAEAKCACAGCIAAAAAAAA=","61":"b:AAAAAAAAAgAAADAAAAAAAEAKCACAGCIAAAAAAAA=","65":"b:AAAAAAAAAgAAADAAAAAAAEAKCACAGCIAAAAAAAA=","81":"b:AAAAAAAAAgAAADAAAAAAAEAKCACAGCIAAAAAAAA=","82":"b:AAAAAAAAAgAAADAAAAAAAEAKCACAGCIAAAAAAAA=","83":"b:AAAAAAAAAgAAADAAAAAAAEAKCACAGCIAAAAAAAA=","85":"b:AAAAAAAAAgAAADAAAAAAAEAKCACAGCIAAAAAAAA=","88":"b:AAAAAAAAAgAAADAAAAAAAEAKCACAGCIAAAAAAAA=","90":"b:AAAAAAAAAgAAADAAAAAAAEAKCACAGCIAAAAAAAA=","91":"b:AAAAAAAAAgAAADAAAAAAAEAKCACAGCIAAAAAAAA=","92":"b:AAAAAAAAAgAAADAAAAAAAEAKCACAGCIAAAAAAAA=","93":"b:AAAAAAAAAgAAADAAAAAAAEAKCACAGCIAAAAAAAA=","94":"b:AAAAAAAAAgAAADAAAAAAAEAKCACAGCIAAAAAAAA=","109":"b:AAAAAAAAAgAAADAAAAAAAEAKCACAGCIAAAAAAAA=","114":"b:AAAAAAAAAgAAADAAAAAAAEAKCACAGCIAAAAAAAA=","116":"b:AAAAAAAAAgAAADAAAAAAAEAKCACAGCIAAAAAAAA=","127":"b:AAAAAAAAAgAAADAAAAAAAEAKCACAGCIAAAAAAAA=","160":"b:AAAAAAAAAgAAADAAAAAAAEAKCACAGCIAAAAAAAA="},"packages/nodes-base/nodes/Discourse/Discourse.node.ts":{"93":[137],"107":[137]},"packages/nodes-base/nodes/Discourse/GenericFunctions.ts":{"11":[137],"40":[137]},"packages/nodes-base/nodes/Form/utils/utils.ts":{"54":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","75":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","79":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","94":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","103":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","181":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","182":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","185":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","186":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","198":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","218":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","230":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","241":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","250":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","255":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","344":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","364":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","386":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","392":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","431":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","482":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","511":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","593":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","637":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","698":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","699":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","727":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","743":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","751":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","753":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","765":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","803":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","834":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","847":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","865":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","877":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","892":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","898":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","907":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","919":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","927":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","932":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","947":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","958":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","974":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","989":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","1012":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","1039":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","1064":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","1228":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","1255":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","1316":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","1323":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","1336":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","1340":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","1341":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","1361":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","1376":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","1624":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","1656":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","1659":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA=","1685":"b:AAIFpBAAZgAAACAGgAAIAEACAAAABAAAAQAIAAA="},"packages/nodes-base/nodes/SplitInBatches/SplitInBatches.node.ts":{"9":[137,147,18,82]},"packages/nodes-base/nodes/SplitInBatches/v1/SplitInBatchesV1.node.ts":{"62":[137,147,18,82],"97":[137,147,18,82],"111":[137,147,18,82],"128":[137,147,18,82]},"packages/nodes-base/nodes/SplitInBatches/v2/SplitInBatchesV2.node.ts":{"64":[137,147,18,82],"102":[137,147,18,82],"116":[137,147,18,82],"135":[137,147,18,82],"147":[137,147,18,82]},"packages/nodes-base/nodes/SplitInBatches/v3/SplitInBatchesV3.node.ts":{"88":[137,147,18,82],"126":[137,147,18,82],"140":[137,147,18,82],"159":[137,147,18,82],"171":[137,147,18,82]},"packages/nodes-base/nodes/StickyNote/StickyNote.node.ts":{"57":[137,147,78,170,181,185,191]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/filter.svg":{"11":[137,170]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/loop-over-items.svg":{"11":[126,137,146,147,165,18,82,189]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/wait.svg":{"11":[90,104,50,137,170,18]},"packages/frontend/@n8n/design-system/src/components/N8nMarkdown/Markdown.vue":{"38":[46,137,147,78,164,170,181,189,89,191],"73":[46,137,147,78,164,170,181,189,89,191],"94":[46,137,147,78,164,170,181,189,89,191],"101":[46,191],"121":[46,137,147,78,164,170,181,189,191],"125":[46,137,147,78,164,170,181,189,191],"126":[46],"159":[46,137,147,78,164,170,181,189,191],"167":[46,164,189,191],"200":[46,137,147,78,164,170,181,189,89,191],"207":[46],"225":[46],"244":[46],"257":[46],"266":[46],"275":[46,137,147,78,164,170,181,189,89,191],"293":[46,89,191]},"packages/frontend/@n8n/design-system/src/components/N8nMarkdown/youtube.ts":{"34":[46,137,147,78,164,170,181,189,89,191],"42":[46,137,164,170,181,189,191],"63":[46]},"packages/frontend/@n8n/design-system/src/components/N8nSticky/Sticky.vue":{"16":[46,137,147,78,164,170,181,189,191],"28":[46,137,147,78,164,170,181,189,191],"32":[46,137,147,78,164,170,181,189,191],"36":[46,137,147,78,164,170,181,189,191],"38":[46,137,147,78,164,170,181,189,191],"43":[46,137,147,78,164,170,181,189,191],"45":[46],"58":[46,137,147,78,164,170,181,189,191],"65":[46,137,147,78,164,170,181,189,191],"66":[46],"68":[46],"79":[46],"83":[46],"87":[46],"91":[46],"95":[46],"99":[46,137,147,78,164,170,181,189,191],"113":[46],"127":[46],"128":[46],"129":[46],"130":[46],"146":[46]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/CanvasNodeStickyNote.vue":{"15":[46,137,147,78,164,170,181,189,191],"27":[46,137,147,78,164,170,181,189,191],"29":[46,137,147,78,164,170,181,189,191],"39":[46],"57":[46],"63":[46],"75":[46],"83":[46,164],"91":[46,137,147,78,164,170,181,189,191],"95":[46,78],"98":[46,137,147,78,164,170,181,189,191]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/toolbar/CanvasNodeStickyColorSelector.vue":{"10":[46,137,147,78,164,170,181,189,191],"17":[46,164],"21":[46,164],"27":[46],"31":[46,164],"35":[46],"40":[46],"44":[46],"49":[46],"53":[46,164],"60":[46],"61":[46],"66":[46,137,147,78,164,170,181,189,191],"70":[46,78],"73":[46,137,147,78,164,170,181,189,191],"86":[46,137,147,78,164,170,181,189,191],"95":[46,164],"98":[46,164],"106":[46],"135":[46]},"packages/core/src/execution-engine/partial-execution-utils/clean-run-data.ts":{"12":[27,28,138,170,18,172,84,85]},"packages/core/src/execution-engine/partial-execution-utils/directed-graph.ts":{"40":[27,28,138,170,18,172,84,85],"45":[27,28,138,170,18,172,84,85],"49":[27,28,138,170,18,172,84,85],"58":[27,28,138,170,18,172,84,85],"72":[27,28,138,170,18,172,84,85],"86":[27,28,138,170,18,172,84,85],"91":[27,28,138,170,18,172,84,85],"116":[27,28,138,170,18,172,84,85],"172":[27,28,138,170,18,172,84,85],"201":[27,28,138,170,18,172,84,85],"216":[27,28,138,170,18,172,84,85],"233":[27,28,138,170,18,172,84,85],"255":[27,28,138,170,18,172,84,85],"259":[27,28,138,170,18,172,84,85],"276":[27,28,138,170,18,172,84,85],"293":[27,28,138,170,18,172,84,85],"297":[27,28,138,170,18,172,84,85],"347":[27,28,138,170,18,172,84,85],"355":[27,28,138,170,18,172,84,85],"366":[27,28,138,170,18,172,84,85],"414":[27,28,138,170,18,172,84,85],"454":[27,28,138,170,18,172,84,85],"458":[27,28,138,170,18,172,84,85],"466":[27,28,138,170,18,172,84,85],"499":[27,28,138,170,18,172,84,85],"537":[27,28,138,170,18,172,84,85],"543":[27,28,138,170,18,172,84,85],"566":[27,28,138,170,18,172,84,85]},"packages/core/src/execution-engine/partial-execution-utils/filter-disabled-nodes.ts":{"5":[27,28,138,170,18,172,84,85],"12":[27,28,138,170,18,172,84,85]},"packages/core/src/execution-engine/partial-execution-utils/find-start-nodes.ts":{"13":[27,28,138,170,18,172,84,85],"29":[27,28,138,170,18,172,84,85],"50":[27,28,138,170,18,172,84,85],"137":[27,28,138,170,18,172,84,85],"159":[27,28,138,170,18,172,84,85]},"packages/core/src/execution-engine/partial-execution-utils/find-subgraph.ts":{"6":[27,28,138,170,18,172,84,85],"39":[27,28,138,170,18,172,84,85],"45":[27,28,138,170,18,172,84,85],"88":[27,28,138,170,18,172,84,85]},"packages/core/src/execution-engine/partial-execution-utils/find-trigger-for-partial-execution.ts":{"12":[27,28,138,170,18,172,84,85],"14":[27,28,138,170,18,172,84,85],"17":[27,28,138,170,18,172,84,85],"29":[27,28,138,170,18,172,84,85],"30":[27,28,138,170,18,172,84,85],"31":[27,28,138,170,18,172,84,85],"36":[27,28,138,170,18,172,84,85],"61":[27,28,138,170,18,172,84,85],"78":[27,28,138,170,18,172,84,85],"98":[27,28,138,170,18,172,84,85],"112":[27,28,138,170,18,172,84,85],"115":[27,28,138,170,18,172,84,85],"121":[27,28,138,170,18,172,84,85]},"packages/core/src/execution-engine/partial-execution-utils/get-incoming-data.ts":{"3":[27,28,138,170,18,172,84,85],"13":[27,28,138,170,18,172,84,85],"17":[27,28,138,170,18,172,84,85]},"packages/core/src/execution-engine/partial-execution-utils/get-source-data-groups.ts":{"5":[27,28,138,170,18,172,84,85],"28":[27,28,138,170,18,172,84,85],"86":[27,28,138,170,18,172,84,85],"118":[27,28,138,170,18,172,84,85],"119":[27,28,138,170,18,172,84,85],"126":[27,28,138,170,18,172,84,85],"139":[27,28,138,170,18,172,84,85],"156":[27,28,138,170,18,172,84,85],"157":[27,28,138,170,18,172,84,85]},"packages/core/src/execution-engine/partial-execution-utils/handle-cycles.ts":{"15":[27,28,138,170,18,172,84,85],"26":[27,28,138,170,18,172,84,85],"41":[27,28,138,170,18,172,84,85]},"packages/core/src/execution-engine/partial-execution-utils/recreate-node-execution-stack.ts":{"20":[27,28,138,170,18,172,84,85],"39":[27,28,138,170,18,172,84,85],"72":[27,28,138,170,18,172,84,85],"103":[27,28,138,170,18,172,84,85]},"packages/core/src/execution-engine/partial-execution-utils/run-data-utils.ts":{"11":[27,28,138,170,18,172,84,85],"17":[27,28,138,170,18,172,84,85],"20":[27,28,138,170,18,172,84,85]},"packages/nodes-base/nodes/DebugHelper/DebugHelper.node.ts":{"255":[138,170,171,176,181],"346":[138,170,171,176,181]},"packages/nodes-base/nodes/DebugHelper/functions.ts":{"4":[138,170,171,176,181],"14":[138,170,171,176,181]},"packages/nodes-base/nodes/DebugHelper/randomData.ts":{"26":[138,170,171,176,181],"36":[138,170,171,176,181],"48":[138,170,171,176,181],"55":[138,170,171,176,181],"59":[138,170,171,176,181],"63":[138,170,171,176,181],"79":[138,170,171,176,181],"83":[138,170,171,176,181],"87":[138,170,171,176,181],"91":[138,170,171,176,181],"95":[138,170,171,176,181],"99":[138,170,171,176,181]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataPaginationBar.vue":{"11":[46,138,175,84],"15":[46,138,175,84],"26":[46,138],"34":[46],"36":[46,138,175,84],"37":[46,138,175,84]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/switch.svg":{"11":[131,140,77,165,82,84,85,189]},"localhost-36307/assets/index-Dv_brJ4-.js":{"3":[97]},"localhost-36307/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[97],"9":[97],"10":[97],"19":[97],"23":[97],"29":[97],"33":[97],"34":[97]},"packages/frontend/@n8n/rest-api-client/src/api/templates.ts":{"131":[46,191],"135":[46,191],"139":[46,191],"146":[46,191],"159":[46,191],"190":[46,89],"198":[46,89,191],"206":[46,97,89,191]},"packages/frontend/editor-ui/src/app/utils/formatters/listFormatter.ts":{"15":[46,97,89]},"packages/frontend/editor-ui/src/features/workflows/canvas/iconLuma.utils.ts":{"17":[31,41,9,46,124,97,176,178,180,189,89,191],"25":[31,41,9,46,124,97,176,178,180,189,89,191],"26":[31,41,9,46,124,97,176,178,180,189,89,191],"34":[31,41,9,46,124,97,176,178,180,189,89,191],"47":[31,41,9,46,124,97,176,178,180,189,89,191],"68":[31,41,9,46,124,97,176,178,180,189,89,191]},"packages/frontend/editor-ui/src/features/workflows/templates/components/AppsRequiringCredsNotice.vue":{"10":[46,97,89],"17":[46,97,89],"24":[46,97,89],"27":[46,97,89],"33":[46,97,89],"37":[46,97,89],"38":[46,97,89]},"packages/frontend/editor-ui/src/features/workflows/templates/components/IconSuccess.vue":{"2":[46,97,89]},"packages/frontend/editor-ui/src/features/workflows/templates/components/SetupTemplateFormStep.vue":{"18":[46,97,89],"42":[46,97,89],"44":[46,97,89],"48":[46,97,89],"52":[46,97,89],"53":[46,97,89],"60":[46,97,89],"71":[46,89],"77":[46,97,89],"85":[46,97,89],"98":[46,97,89]},"packages/frontend/editor-ui/src/features/workflows/templates/components/SetupWorkflowCredentialsModal.vue":{"13":[46,97],"29":[46,97],"46":[46,97],"52":[46,89],"61":[46,97],"65":[46,97,89],"67":[46,97,89],"71":[46,97,89],"83":[46,97],"90":[46,89],"91":[46],"98":[46,97,89],"105":[46,89]},"packages/frontend/editor-ui/src/features/workflows/templates/composables/useCredentialSetupState.ts":{"29":[46,97,89],"34":[46,97,89],"38":[46,97,89],"43":[46,97,89],"77":[46,97,89],"103":[46,97,89],"115":[46,97,89],"123":[46,97,89],"126":[46,97,89],"132":[46,97,89],"136":[46,97,89],"140":[46,97,89],"144":[46,89],"163":[46,97,89],"171":[46,89],"175":[46]},"packages/frontend/editor-ui/src/features/workflows/templates/composables/useSetupWorkflowCredentialsModalState.ts":{"9":[46,97],"15":[46,97],"34":[46,97,89],"40":[46],"52":[46,89],"66":[46],"89":[46],"97":[46]},"packages/frontend/editor-ui/src/features/workflows/templates/utils/templateTransforms.ts":{"38":[46,97,89],"47":[46,97,89],"55":[46,89],"73":[46,89],"99":[46,89],"122":[46,89],"127":[46,89],"150":[46],"165":[46],"168":[46]},"localhost-42627/assets/index-Dv_brJ4-.js":{"3":[62]},"localhost-42627/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[62],"9":[62],"10":[62],"19":[62],"23":[62],"29":[62],"33":[62],"34":[62]},"packages/frontend/@n8n/design-system/src/components/N8nAlertDialog/AlertDialog.vue":{"74":[95,46,123,62],"83":[46],"87":[46,62],"91":[46],"94":[95,46,123,62],"99":[95,46,123,62],"102":[46,62],"103":[46,62]},"packages/frontend/@n8n/design-system/src/components/N8nDialog/DialogDescription.vue":{"15":[46,123,62,100],"16":[46,123,62,100]},"packages/frontend/@n8n/design-system/src/components/N8nDialog/DialogFooter.vue":{"6":[46,96,62,100]},"packages/frontend/@n8n/design-system/src/components/N8nSettingsLayout/SettingsLayout.vue":{"28":[93,95,46,123,62,154,100],"29":[93,95,46,123,62,154,100],"33":[93,95,46,123,62,154,100],"40":[46],"42":[46],"44":[46]},"packages/frontend/@n8n/design-system/src/components/N8nSettingsPageHeader/SettingsPageHeader.vue":{"29":[93,95,46,123,62,154,100],"40":[93,95,46,123,62,154,100],"41":[93,95,46,123,62,154,100],"60":[46],"65":[93,95,46,123,62,154,100],"69":[93,46,123,62,154,100]},"packages/frontend/@n8n/design-system/src/components/N8nSettingsRow/SettingsRow.vue":{"67":[93,46,96,123,62,154,100],"107":[93,46,96,123,62,154,100],"112":[46],"116":[46],"120":[46],"125":[93,46,96,123,62,154,100],"133":[93,46,96,123,62,154,100],"138":[93,46,96,123,62,154,100],"151":[93,46,96,123,62,154,100],"157":[93,46,96,123,62,154,100],"159":[93,46,96,123,62,154,100],"166":[93,46,96,123,62,154,100],"174":[46],"183":[46,123,62,100],"189":[46,154,100],"201":[93,46,96,123,62,154,100],"236":[93,46,96,123,62,154,100],"244":[93,46,96,123,154,100],"251":[93,46,123,154,100],"268":[46,123,62,100],"279":[46],"285":[46]},"packages/frontend/@n8n/design-system/src/components/N8nSettingsRowGroup/SettingsRowGroup.vue":{"15":[93,46,96,123,62,154,100],"16":[93,46,123,62,154,100]},"packages/frontend/@n8n/design-system/src/components/N8nSettingsSection/SettingsSection.vue":{"18":[93,46,123,62,154,100],"26":[93,46,123,62,154,100],"29":[93,46,123,62,154,100],"36":[93,46,123,62,154,100],"41":[46]},"packages/frontend/@n8n/rest-api-client/src/api/security-settings.ts":{"6":[46,62],"10":[46,62]},"packages/frontend/editor-ui/src/app/stores/workflows.ee.store.ts":{"13":[46,62,156,159,75,190],"18":[46,62,75],"19":[46,62,75],"34":[46,159],"43":[46,159],"49":[46,159]},"packages/frontend/editor-ui/src/features/ndv/panel/components/RedactedDataState.vue":{"14":[46,62],"20":[46,62],"24":[46,62],"26":[46,62],"33":[46,62],"34":[46],"35":[46,62],"49":[46,62],"53":[46,62],"58":[46]},"packages/frontend/editor-ui/src/features/resolvers/composables/useCredentialResolvers.ts":{"26":[46,62,75],"38":[46],"51":[46],"59":[46],"109":[46],"111":[46],"120":[46]},"packages/frontend/editor-ui/src/features/settings/security/DataRedactionSection.vue":{"39":[62],"57":[62],"62":[62],"63":[62],"72":[62],"76":[62],"77":[62],"85":[62],"94":[62],"121":[62],"139":[62],"152":[62],"162":[62],"164":[62],"170":[62],"176":[62],"181":[62],"215":[62],"223":[62],"263":[62],"265":[62]},"packages/frontend/editor-ui/src/features/settings/security/SecuritySettings.vue":{"45":[62],"49":[62],"75":[62],"89":[62],"96":[62],"130":[62],"152":[62],"173":[62],"203":[62],"206":[62],"208":[62],"210":[62],"214":[62],"217":[62],"226":[62],"261":[62],"264":[62],"266":[62],"272":[62],"275":[62],"313":[62],"315":[62],"323":[62],"325":[62],"331":[62],"334":[62],"372":[62],"374":[62]},"packages/frontend/editor-ui/src/features/workflows/components/WorkflowSettings/RedactionMembersModal.vue":{"9":[46,62,75],"24":[46,62,75],"26":[46,62,75],"41":[46,62,75],"48":[46],"49":[46],"56":[46],"59":[46],"65":[46],"69":[46]},"packages/frontend/editor-ui/src/features/workflows/components/WorkflowSettings/WorkflowSettings.vue":{"74":[46,62,75],"160":[46],"164":[46],"167":[46],"175":[46],"178":[46],"182":[46],"190":[46],"216":[46,62,75],"223":[46,62,75],"226":[46,62,75],"229":[46,62,75],"230":[46,62,75],"231":[46,62,75],"232":[46,62,75],"235":[46,62,75],"240":[46,62,75],"242":[46,62],"244":[46,62],"250":[46,62,75],"254":[46,62,75],"256":[46,62,75],"260":[46,62,75],"265":[46,62,75],"280":[46,62,75],"284":[46,62,75],"288":[46,62,75],"289":[46,62,75],"293":[46],"297":[46,62,75],"301":[46],"316":[46,62,75],"321":[46],"332":[46,62,75],"336":[46,62],"348":[46,62,75],"352":[46,62],"363":[46,62],"374":[46],"378":[46],"382":[46,62,75],"384":[46,62,75],"389":[46,62,75],"393":[46,62,75],"404":[46,62,75],"418":[46,62,75],"421":[46],"427":[46,62],"434":[46],"443":[46,62,75],"473":[46,62,75],"497":[46,62,75],"521":[46,62,75],"544":[46,62,75],"567":[46,62,75],"594":[46,62,75],"600":[46],"618":[46],"624":[46],"631":[46],"635":[46],"638":[46],"650":[46,62,75],"661":[46],"674":[46,62],"760":[46,62],"799":[46],"809":[46],"813":[46],"817":[46],"826":[46],"838":[46,62,75],"877":[46],"965":[46],"983":[46],"995":[46,62],"999":[46,62,75],"1014":[46,62,75],"1022":[46,62,75],"1025":[46,62,75],"1033":[46,62,75],"1036":[46,62,75],"1040":[46,62,75],"1051":[46,62,75],"1052":[46,62,75],"1054":[46],"1056":[46,62,75],"1061":[46,62,75],"1071":[46,62,75],"1073":[46,62,75],"1078":[46,62,75],"1085":[46],"1094":[46],"1095":[46],"1097":[46],"1099":[46],"1104":[46],"1116":[46],"1118":[46],"1125":[46],"1152":[46,62,75],"1153":[46,62,75],"1155":[46],"1157":[46,62,75],"1163":[46,62,75],"1174":[46,62,75],"1176":[46,62,75],"1187":[46],"1192":[46],"1194":[46],"1199":[46],"1212":[46,62,75],"1214":[46],"1216":[46,62,75],"1221":[46,62,75],"1228":[46,62,75],"1230":[46,62,75],"1241":[46,62,75],"1243":[46],"1245":[46,62,75],"1250":[46,62,75],"1257":[46,62,75],"1259":[46,62,75],"1270":[46,62,75],"1272":[46],"1274":[46,62,75],"1279":[46,62,75],"1286":[46,62,75],"1288":[46,62,75],"1299":[46,62,75],"1301":[46],"1303":[46,62,75],"1308":[46,62,75],"1315":[46,62,75],"1317":[46,62,75],"1328":[46,62,75],"1330":[46],"1332":[46,62,75],"1337":[46,62,75],"1344":[46,62,75],"1346":[46,62,75],"1357":[46,62,75],"1360":[46,62,75],"1383":[46,75],"1387":[46],"1395":[46],"1397":[46,62,75],"1407":[46,62,75],"1413":[46,62],"1421":[46],"1424":[46,62,75],"1440":[46,62,75],"1442":[46,62,75],"1453":[46],"1455":[46],"1456":[46],"1464":[46,62,75],"1489":[46,75],"1493":[46],"1501":[46],"1503":[46,62,75],"1513":[46,62,75],"1522":[46,62],"1530":[46],"1538":[46,62,75],"1552":[46,62,75],"1554":[46,62,75],"1567":[46,62,75],"1569":[46],"1571":[46,62,75],"1576":[46,62,75],"1592":[46],"1593":[46],"1595":[46],"1597":[46],"1602":[46],"1606":[46],"1608":[46],"1612":[46],"1617":[46],"1619":[46],"1623":[46],"1628":[46],"1630":[46],"1636":[46],"1637":[46],"1640":[46],"1642":[46],"1648":[46],"1650":[46],"1652":[46],"1666":[46,62,75],"1669":[46],"1671":[46,62,75],"1677":[46,62,75],"1685":[46,62,75],"1687":[46,62,75],"1698":[46,62,75],"1718":[46],"1737":[46],"1768":[46],"1785":[46],"1789":[46,62,75],"1803":[46]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/AgentTool.node.ts":{"8":[13]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/V2/AgentToolV2.node.ts":{"19":[13],"99":[13]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/V2/utils.ts":{"11":[13],"23":[13],"26":[13],"86":[13],"89":[13]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/V3/AgentToolV3.node.ts":{"22":[13],"101":[13]},"packages/cli/src/tool-generation/index.ts":{"7":[6,9,10,13,15]},"packages/frontend/@n8n/design-system/src/components/N8nSelectableList/SelectableList.vue":{"7":[6,46,13],"35":[46],"37":[6,46,13],"39":[6,46,13],"43":[6,46,13],"45":[46],"52":[46],"56":[46],"61":[46],"63":[6,46,13],"70":[6,46,13],"74":[46],"76":[6,46,13],"84":[46],"95":[46]},"packages/frontend/@n8n/design-system/src/components/N8nTag/Tag.vue":{"15":[6,46,13,190,89]},"packages/frontend/editor-ui/src/features/ndv/panel/components/InputNodeSelect.vue":{"18":[2,9,46,13,143,18,82,175,176,84,16,85],"29":[2,9,46,13,143,18,82,175,176,84,16,85],"33":[2,9,46,13,143,18,82,175,176,84,16,85],"40":[2,9,46,13,143,18,82,175,176,84,16,85],"43":[46,13,18,82,175,176,84,85],"56":[46,13,18,82,175,176,84,85],"58":[46,13,18,82,175,176,84,85],"65":[46,13,18,82,175,176,84,85],"70":[46,13,18,82,175,176,84,85],"79":[46,13,18,82,175,176,84,85],"91":[46],"97":[46],"106":[46,13,18,82,175,176,84,85],"110":[46,13,18,82,175,176,84,85],"116":[46,82,85],"118":[2,9,46,13,143,18,82,175,176,84,16,85],"133":[2,9,46,13,143,18,82,175,176,84,16,85],"139":[2,9,46,13,143,18,82,175,176,84,16,85],"143":[46,13,18,82,175,176,84,85],"149":[46,13,18,82,175,176,84,85]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputOverrides/FromAiOverrideField.vue":{"11":[6,46,13],"12":[6,46,13],"22":[6,46,13],"25":[6,46,13],"34":[46]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputOverrides/ParameterOverrideSelectableList.vue":{"16":[6,46,13],"22":[6,46,13],"23":[6,46,13],"29":[46],"37":[46],"41":[46],"47":[6,46,13],"58":[46]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataJson.vue":{"22":[13,170,18,82,84],"59":[13,170,18,82,84],"61":[13,170,18,82,84],"63":[82],"71":[13,170,18,82,84],"82":[13,170,18,82,84],"83":[13,170,18,82,84],"85":[82],"98":[82],"122":[13,170,18,82,84],"126":[13,170,18,82,84],"130":[13,170,18,82,84],"166":[13,170,18,82,84],"181":[13,170,18,82,84]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataJsonActions.vue":{"64":[13,170,18,82,84]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasLayout.guards.ts":{"12":[31,46,145,160],"18":[31,46,145,160],"22":[31,46,145,160],"26":[31,46,145,160],"35":[46]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataHints.vue":{"18":[46,126,139,146,180,87],"35":[46,126,139,146,180,87],"39":[46,126,139,146,180,87],"83":[46,126,139,146,180,87],"102":[46,126,139,146,180,87],"106":[46],"110":[46],"114":[46],"120":[46],"121":[46],"124":[46],"128":[46],"138":[46,126,139,146,180,87],"144":[46,126,139,146,180,87],"149":[46,126,139,146,180,87],"156":[46],"159":[46],"168":[46],"169":[46],"182":[46]},"packages/@n8n/utils/src/sleep.ts":{"3":[204,46,50,67,170,18],"4":[204,46,50,67,170,18],"10":[204,46,50,67,170,18],"15":[204,46,50,67,170,18],"28":[204,46,50,67,170,18],"30":[204,46,50,67,170,18]},"packages/cli/src/execution-lifecycle/save-execution-progress.ts":{"8":[170]},"packages/cli/src/task-runners/task-runner-module.ts":{"43":[26,170,18,221],"52":[26,170,18,221],"60":[26,170,18,221],"68":[26,170,18,221],"77":[26,170,18,221],"84":[26,170,18,221],"94":[26,170,18,221],"103":[26,170,18,221],"113":[26,170,18,221],"156":[26,170,18,221]},"packages/nodes-base/nodes/Form/Form.node.ts":{"366":"b:AAIBoAAAYgAAACACgAAIQEAAAAAABAAAAAAIAAA=","454":"b:AAIBoAAAYgAAACACgAAIQEAAAAAABAAAAAAIAAA=","462":"b:AAIBoAAAYgAAACACgAAIQEAAAAAABAAAAAAIAAA=","472":"b:AAIBoAAAYgAAACACgAAIQEAAAAAABAAAAAAIAAA="},"packages/nodes-base/nodes/Form/utils/formCompletionUtils.ts":{"27":"b:AAIBoAAAYgAAACACgAAIQEAAAAAABAAAAAAIAAA=","43":"b:AAIBoAAAYgAAACACgAAIQEAAAAAABAAAAAAIAAA=","46":"b:AAIBoAAAYgAAACACgAAIQEAAAAAABAAAAAAIAAA=","52":"b:AAIBoAAAYgAAACACgAAIQEAAAAAABAAAAAAIAAA=","59":"b:AAIBoAAAYgAAACACgAAIQEAAAAAABAAAAAAIAAA=","62":"b:AAIBoAAAYgAAACACgAAIQEAAAAAABAAAAAAIAAA=","83":"b:AAIBoAAAYgAAACACgAAIQEAAAAAABAAAAAAIAAA="},"packages/nodes-base/nodes/Form/utils/formNodeUtils.ts":{"22":"b:AAIBoAAAYgAAACACgAAIQEAAAAAABAAAAAAIAAA=","105":"b:AAIBoAAAYgAAACACgAAIQEAAAAAABAAAAAAIAAA=","108":"b:AAIBoAAAYgAAACACgAAIQEAAAAAABAAAAAAIAAA="},"packages/nodes-base/nodes/Telegram/GenericFunctions.ts":{"84":[170,89],"146":[170,89],"220":[170,89],"260":[170,89],"273":[170,89],"277":[170,89],"283":[170,89],"304":[170,89]},"packages/nodes-base/nodes/Telegram/Telegram.node.ts":{"2043":[170,89],"2049":[170,89]},"packages/nodes-base/nodes/Telegram/hitl/setup.ts":{"11":[170,89],"24":[170,89],"41":[170,89],"67":[170,89]},"packages/nodes-base/nodes/Telegram/hitl/tokens.ts":{"17":[170,89]},"packages/nodes-base/nodes/Telegram/hitl/webhook.ts":{"12":[170,89],"21":[170,89],"25":[170,89],"36":[170,89],"51":[170,89],"88":[170,89],"133":[170,89]},"packages/nodes-base/utils/sendAndWait/configureWaitTillDate.util.ts":{"4":"b:AAIBoAAAYgAAACACgAAIQEAAAAAABAAAAAAIAAA="},"packages/nodes-base/utils/sendAndWait/email-templates.ts":{"82":[29,31,9,49,126,53,134,139,170,16,85,89],"147":[29,31,9,49,126,53,134,139,170,16,85,89]},"packages/nodes-base/utils/sendAndWait/utils.ts":{"59":[29,31,9,49,126,53,134,139,170,16,85,89],"155":[29,31,9,49,126,53,134,139,170,16,85,89],"311":[29,31,9,49,126,53,134,139,170,16,85,89],"341":[29,31,9,49,126,53,134,139,170,16,85,89],"351":[29,31,9,49,126,53,134,139,170,16,85,89],"354":[29,31,9,49,126,53,134,139,170,16,85,89],"501":[29,31,9,49,126,53,134,139,170,16,85,89],"506":[29,31,9,49,126,53,134,139,170,16,85,89],"513":[29,31,9,49,126,53,134,139,170,16,85,89],"584":[29,31,9,49,126,53,134,139,170,16,85,89],"592":[29,31,9,49,126,53,134,139,170,16,85,89],"626":[29,31,9,49,126,53,134,139,170,16,85,89]},"packages/workflow/src/errors/execution-cancelled.error.ts":{"9":[26,170,18,221],"19":[26,170,18,221],"26":[26,170,18,221],"33":[26,170,18,221]},"localhost-39389/assets/index-Dv_brJ4-.js":{"3":[98]},"localhost-39389/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[98],"9":[98],"10":[98],"19":[98],"23":[98],"29":[98],"33":[98],"34":[98]},"packages/frontend/@n8n/rest-api-client/src/api/communityNodes.ts":{"7":[46,129,150,151],"14":[46,150,151],"22":[46,150],"26":[46,150,151],"34":[46,150,151]},"packages/frontend/editor-ui/src/features/settings/communityNodes/communityNodes.utils.ts":{"4":[46,150,151],"25":[46,150,151],"53":[46,151]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/CommunityPackageCard.vue":{"44":[150,151],"47":[150,151],"60":[150,151],"77":[150],"95":[150,151],"100":[150,151],"101":[150,151],"102":[150,151],"111":[150,151],"126":[150,151],"133":[150,151],"142":[150,151],"156":[150,151]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/CommunityPackageInstallModal.vue":{"32":[46,150,151],"39":[46,150,151],"47":[46,150,151],"49":[46],"54":[46,150,151],"78":[46,150,151],"82":[46,150],"86":[46,150,151],"90":[46],"94":[46],"98":[46,150,151],"111":[46,150,151],"119":[46,150,151],"134":[46,150,151],"167":[46,150,151],"172":[46,150,151],"178":[46,150,151]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/CommunityPackageManageConfirmModal.vue":{"33":[46,150,151],"55":[46,150,151],"58":[46,150],"69":[46,150,151],"70":[46,150,151],"73":[46,150,151],"109":[46,150,151],"113":[46,150,151],"121":[46,150],"125":[46,150],"148":[46,150,151],"152":[46,150,151],"194":[46,150,151],"195":[46,150,151],"203":[46,150,151],"216":[46,150,151],"222":[46],"226":[46,150,151],"232":[46,150,151],"240":[46,150,151],"252":[46,150,151],"253":[46,150,151],"261":[46,150,151],"270":[46,150,151]},"packages/frontend/editor-ui/src/features/settings/communityNodes/composables/useInstallNode.ts":{"40":[6,46,129,150,151],"53":[46],"63":[46,150,151],"103":[46]},"packages/frontend/editor-ui/src/features/settings/communityNodes/views/SettingsCommunityNodesView.vue":{"40":[150,151],"44":[150,151],"48":[150,151],"56":[150,151],"77":[150,151],"82":[150,151],"90":[151],"94":[150,151],"104":[150,151],"110":[150,151],"117":[150,151],"122":[150,151],"126":[150,151],"130":[150,151],"178":[150,151]},"packages/@n8n/api-types/src/dto/folders/list-folder-query.dto.ts":{"46":[46,136,59,60,157],"72":[46,136,59,60,157],"73":[46,136,59,60,157],"81":[46,136,59,60,157],"82":[46,136,59,60,157],"91":[46,136,59,60,157],"99":[46],"100":[136,59,60,157]},"packages/cli/src/controllers/folder.controller.ts":{"34":[135,57,136,59,60,157],"41":[135,57,136,59,60,157],"59":[135,57,136,59,60,157],"80":[135,57,136,59,60,157],"100":[135,57,136,59,60,157],"124":[135,57,136,59,60,157],"146":[135,57,136,59,60,157],"168":[135,57,136,59,60,157],"183":[135,57,136,59,60,157],"205":[135,57,136,59,60,157]},"packages/cli/src/services/folder.service.ts":{"31":[135,57,136,59,60,69,157],"39":[135,57,136,59,60,69,157],"57":[135,57,136,59,60,69,157],"62":[135,57,136,59,60,69,157],"70":[135,57,136,59,60,69,157],"73":[135,57,136,59,60,69,157],"112":[135,57,136,59,60,69,157],"120":[135,57,136,59,60,69,157],"149":[135,57,136,59,60,69,157],"168":[135,57,136,59,60,69,157],"181":[135,57,136,59,60,69,157],"204":[135,57,136,59,60,69,157],"212":[135,57,136,59,60,69,157],"220":[135,57,136,59,60,69,157],"228":[135,57,136,59,60,69,157],"239":[135,57,136,59,60,69,157],"253":[135,57,136,59,60,69,157],"254":[135,57,136,59,60,69,157],"262":[135,57,136,59,60,69,157],"287":[135,57,136,59,60,69,157],"300":[135,57,136,59,60,69,157],"326":[135,57,136,59,60,69,157],"339":[135,57,136,59,60,69,157],"342":[135,57,136,59,60,69,157],"347":[135,57,136,59,60,69,157]},"packages/nodes-base/nodes/Notion/Notion.node.ts":{"9":[60,156,157,70,16,185]},"packages/nodes-base/nodes/Notion/shared/GenericFunctions.ts":{"33":[60,156,157,70,172,16,185],"54":[60,156,157,70,172,16,185],"90":[60,156,157,70,172,16,185],"124":[60,156,157,70,172,16,185],"145":[60,156,157,70,172,16,185],"166":[60,156,157,70,172,16,185],"211":[60,156,157,70,172,16,185],"219":[60,156,157,70,172,16,185],"225":[60,156,157,70,172,16,185],"231":[60,156,157,70,172,16,185],"255":[60,156,157,70,172,16,185],"302":[60,156,157,70,172,16,185],"311":[60,156,157,70,172,16,185],"327":[60,156,157,70,172,16,185],"334":[60,156,157,70,172,16,185],"338":[60,156,157,70,172,16,185],"345":[60,156,157,70,172,16,185],"364":[60,156,157,70,172,16,185],"373":[60,156,157,70,172,16,185],"376":[60,156,157,70,172,16,185],"377":[60,156,157,70,172,16,185],"379":[60,156,157,70,172,16,185],"382":[60,156,157,70,172,16,185],"400":[60,156,157,70,172,16,185],"402":[60,156,157,70,172,16,185],"403":[60,156,157,70,172,16,185],"420":[60,156,157,70,172,16,185],"479":[60,156,157,70,172,16,185],"491":[60,156,157,70,172,16,185],"503":[60,156,157,70,172,16,185],"511":[60,156,157,70,172,16,185],"513":[60,156,157,70,172,16,185],"517":[60,156,157,70,172,16,185],"518":[60,156,157,70,172,16,185],"524":[60,156,157,70,172,16,185],"525":[60,156,157,70,172,16,185],"534":[60,156,157,70,172,16,185],"535":[60,156,157,70,172,16,185],"583":[60,156,157,70,172,16,185],"590":[60,156,157,70,172,16,185],"611":[60,156,157,70,172,16,185],"617":[60,156,157,70,172,16,185],"619":[60,156,157,70,172,16,185],"623":[60,156,157,70,172,16,185],"642":[60,156,157,70,172,16,185],"650":[60,156,157,70,172,16,185],"658":[60,156,157,70,172,16,185],"660":[60,156,157,70,172,16,185],"666":[60,156,157,70,172,16,185],"668":[60,156,157,70,172,16,185],"678":[60,156,157,70,172,16,185],"731":[60,156,157,70,172,16,185],"740":[60,156,157,70,172,16,185],"827":[60,156,157,70,172,16,185],"845":[60,156,157,70,172,16,185],"861":[60,156,157,70,172,16,185],"882":[60,156,157,70,172,16,185],"922":[60,156,157,70,172,16,185],"931":[60,156,157,70,172,16,185],"957":[60,156,157,70,172,16,185],"970":[60,156,157,70,172,16,185],"1090":[60,156,157,70,172,16,185],"1104":[60,156,157,70,172,16,185],"1105":[60,156,157,70,172,16,185],"1118":[60,156,157,70,172,16,185],"1134":[60,156,157,70,172,16,185],"1139":[60,156,157,70,172,16,185],"1147":[60,156,157,70,172,16,185],"1164":[60,156,157,70,172,16,185],"1176":[60,156,157,70,172,16,185],"1216":[60,156,157,70,172,16,185]},"packages/nodes-base/nodes/Notion/shared/descriptions/Blocks.ts":{"164":[60,156,157,70,16,185],"171":[60,156,157,70,16,185],"407":[60,156,157,70,16,185],"459":[60,156,157,70,16,185],"475":[60,156,157,70,16,185],"491":[60,156,157,70,16,185],"501":[60,156,157,70,16,185],"511":[60,156,157,70,16,185],"526":[60,156,157,70,16,185],"602":[60,156,157,70,16,185]},"packages/nodes-base/nodes/Notion/shared/descriptions/Filters.ts":{"1":[60,156,157,70,172,16,185]},"packages/nodes-base/nodes/Notion/shared/methods/listSearch.ts":{"10":[60,156,157,70,172,16,185],"28":[60,156,157,70,172,16,185]},"packages/nodes-base/nodes/Notion/v1/NotionV1.node.ts":{"35":[60,156,157,70,16,185],"45":[60,156,157,70,16,185],"74":[60,156,157,70,16,185],"85":[60,156,157,70,16,185],"101":[60,156,157,70,16,185],"112":[60,156,157,70,16,185],"115":[60,156,157,70,16,185],"129":[60,156,157,70,16,185],"134":[60,156,157,70,16,185],"140":[60,156,157,70,16,185],"145":[60,156,157,70,16,185],"158":[60,156,157,70,16,185],"189":[60,156,157,70,16,185],"201":[60,156,157,70,16,185],"216":[60,156,157,70,16,185],"224":[60,156,157,70,16,185],"244":[60,156,157,70,16,185],"429":[60,156,157,70,16,185],"434":[60,156,157,70,16,185]},"packages/nodes-base/nodes/Notion/v2/NotionV2.node.ts":{"38":[60,156,157,70,16,185],"47":[60,156,157,70,16,185],"140":[60,156,157,70,16,185],"465":[60,156,157,70,16,185],"469":[60,156,157,70,16,185]},"packages/nodes-base/nodes/Notion/v2/methods/loadOptions.ts":{"12":[60,156,157,70,16,185],"42":[60,156,157,70,16,185],"54":[60,156,157,70,16,185],"72":[60,156,157,70,16,185],"84":[60,156,157,70,16,185],"88":[60,156,157,70,16,185],"104":[60,156,157,70,16,185],"112":[60,156,157,70,16,185],"118":[60,156,157,70,16,185],"124":[60,156,157,70,16,185],"138":[60,156,157,70,16,185],"171":[60,156,157,70,16,185],"183":[60,156,157,70,16,185],"202":[60,156,157,70,16,185],"210":[60,156,157,70,16,185]},"packages/nodes-base/nodes/Notion/v3/NotionV3.node.ts":{"15":[60,156,157,70,16,185],"24":[60,156,157,70,16,185]},"packages/nodes-base/nodes/Notion/v3/actions/block/Block.resource.ts":{"19":[60,156,157,70,16,185],"48":[60,156,157,70,16,185],"147":[60,156,157,70,16,185],"182":[60,156,157,70,16,185],"210":[60,156,157,70,16,185]},"packages/nodes-base/nodes/Notion/v3/actions/common.descriptions.ts":{"212":[60,156,157,70,16,185],"231":[60,156,157,70,16,185],"251":[60,156,157,70,16,185],"299":[60,156,157,70,16,185],"319":[60,156,157,70,16,185]},"packages/nodes-base/nodes/Notion/v3/actions/dataSource/DataSource.resource.ts":{"85":[60,156,157,70,16,185],"113":[60,156,157,70,16,185]},"packages/nodes-base/nodes/Notion/v3/actions/database/Database.resource.ts":{"52":[60,156,157,70,16,185]},"packages/nodes-base/nodes/Notion/v3/actions/databasePage/DataSourceFilters.ts":{"105":[60,156,157,70,16,185],"106":[60,156,157,70,16,185],"112":[60,156,157,70,16,185],"113":[60,156,157,70,16,185],"130":[60,156,157,70,16,185],"131":[60,156,157,70,16,185],"136":[60,156,157,70,16,185],"141":[60,156,157,70,16,185],"148":[60,156,157,70,16,185],"152":[60,156,157,70,16,185],"161":[60,156,157,70,16,185],"197":[60,156,157,70,16,185],"207":[60,156,157,70,16,185],"217":[60,156,157,70,16,185],"265":[60,156,157,70,16,185],"266":[60,156,157,70,16,185],"272":[60,156,157,70,16,185],"358":[60,156,157,70,16,185],"365":[60,156,157,70,16,185],"371":[60,156,157,70,16,185],"373":[60,156,157,70,16,185]},"packages/nodes-base/nodes/Notion/v3/actions/databasePage/DatabasePage.resource.ts":{"40":[60,156,157,70,16,185],"127":[60,156,157,70,16,185],"482":[60,156,157,70,16,185],"498":[60,156,157,70,16,185],"573":[60,156,157,70,16,185],"603":[60,156,157,70,16,185],"665":[60,156,157,70,16,185]},"packages/nodes-base/nodes/Notion/v3/actions/page/Page.resource.ts":{"211":[60,156,157,70,16,185],"235":[60,156,157,70,16,185],"266":[60,156,157,70,16,185],"290":[60,156,157,70,16,185],"324":[60,156,157,70,16,185]},"packages/nodes-base/nodes/Notion/v3/actions/router.ts":{"22":[60,156,157,70,16,185]},"packages/nodes-base/nodes/Notion/v3/actions/user/User.resource.ts":{"37":[60,156,157,70,16,185],"59":[60,156,157,70,16,185]},"packages/nodes-base/nodes/Notion/v3/helpers/utils.ts":{"12":[60,156,157,70,172,16,185],"38":[60,156,157,70,172,16,185],"48":[60,156,157,70,172,16,185],"74":[60,156,157,70,172,16,185],"78":[60,156,157,70,172,16,185],"79":[60,156,157,70,172,16,185],"102":[60,156,157,70,172,16,185],"106":[60,156,157,70,172,16,185],"113":[60,156,157,70,172,16,185],"119":[60,156,157,70,172,16,185],"150":[60,156,157,70,172,16,185],"156":[60,156,157,70,172,16,185],"190":[60,156,157,70,172,16,185],"199":[60,156,157,70,172,16,185],"237":[60,156,157,70,172,16,185],"245":[60,156,157,70,172,16,185],"253":[60,156,157,70,172,16,185],"261":[60,156,157,70,172,16,185],"285":[60,156,157,70,172,16,185],"309":[60,156,157,70,172,16,185],"324":[60,156,157,70,172,16,185],"340":[60,156,157,70,172,16,185],"360":[60,156,157,70,172,16,185],"371":[60,156,157,70,172,16,185],"389":[60,156,157,70,172,16,185],"398":[60,156,157,70,172,16,185],"420":[60,156,157,70,172,16,185]},"packages/nodes-base/nodes/Notion/v3/methods/listSearch.ts":{"10":[60,156,157,70,172,16,185],"15":[60,156,157,70,172,16,185],"21":[60,156,157,70,172,16,185],"26":[60,156,157,70,172,16,185],"32":[60,156,157,70,172,16,185],"38":[60,156,157,70,172,16,185],"47":[60,156,157,70,172,16,185],"64":[60,156,157,70,172,16,185],"68":[60,156,157,70,172,16,185],"88":[60,156,157,70,172,16,185]},"packages/nodes-base/nodes/Notion/v3/methods/loadOptions.ts":{"23":[60,156,157,70,172,16,185],"38":[60,156,157,70,172,16,185],"57":[60,156,157,70,172,16,185],"60":[60,156,157,70,172,16,185],"61":[60,156,157,70,172,16,185],"71":[60,156,157,70,172,16,185],"78":[60,156,157,70,172,16,185],"85":[60,156,157,70,172,16,185],"89":[60,156,157,70,172,16,185],"110":[60,156,157,70,172,16,185],"124":[60,156,157,70,172,16,185],"143":[60,156,157,70,172,16,185],"156":[60,156,157,70,172,16,185],"179":[60,156,157,70,172,16,185]},"packages/nodes-base/nodes/Notion/v3/transport/index.ts":{"17":[60,156,157,70,172,16,185],"21":[60,156,157,70,172,16,185],"54":[60,156,157,70,172,16,185],"88":[60,156,157,70,172,16,185]},"packages/frontend/editor-ui/src/app/components/MainHeader/utils.ts":{"1":[57,157,183]},"packages/frontend/editor-ui/src/features/core/folders/components/MoveToFolderDropdown.vue":{"40":[46,59,157],"41":[46,59],"42":[46,59],"54":[46,59,157],"64":[46],"94":[46,59,157],"95":[46,59,157],"105":[46,59,157],"107":[46],"109":[46,59,157],"128":[46,59,157],"130":[46,59,157],"132":[46,59,157],"137":[46,59,157],"141":[46,59,157],"145":[46],"148":[46],"151":[46],"169":[46]},"packages/frontend/editor-ui/src/features/core/folders/components/MoveToFolderModal.vue":{"67":[46,59,157],"84":[46,59,157],"87":[46,59,157],"93":[46,59,157],"103":[46,59,157],"104":[46,59,157],"108":[46],"111":[46,59,157],"112":[46,157],"132":[46,59,157],"135":[46,59,157],"139":[46,59,157],"148":[46,59,157],"158":[46,59,157],"172":[46,59,157],"173":[46,59],"179":[46,59,157],"180":[46,59,157],"187":[46,59,157],"191":[46,59],"197":[46,59],"205":[46,59],"236":[46],"290":[46],"359":[46],"384":[46,59,157],"387":[46,59,157],"394":[46,59,157],"400":[46,59,157],"402":[46],"408":[46,59,157],"412":[46,59,157],"444":[46,59,157],"454":[46,59,157],"463":[46,59,157],"465":[46,59,157],"479":[46,59],"484":[46,59],"505":[46,59,157],"524":[46],"533":[46],"543":[46],"559":[46],"567":[46],"572":[46],"587":[46],"596":[46],"604":[46],"606":[46],"616":[46,59,157]},"packages/frontend/editor-ui/src/features/core/folders/folders.api.ts":{"11":[46,57,136],"23":[46,57,136],"35":[46,136],"46":[46,136],"57":[46,59,157],"87":[46],"100":[46,135],"111":[46,136]},"packages/@n8n/db/src/repositories/deployment-key.repository.ts":{"36":[211,115,207,217],"40":[211,115,207,217],"49":[211,115,207,217],"71":[211,115,207,217],"111":[211,115,207,217],"125":[211,115,207,217],"126":[211,115,207,217],"145":[211,115,207,217],"149":[211,115,207,217],"153":[211,115,207,217],"157":[211,115,207,217],"161":[211,115,207,217],"165":[211,115,207,217],"169":[211,115,207,217],"175":[211,115,207,217],"184":[211,115,207,217],"190":[211,115,207,217],"201":[211,115,207,217],"240":[211,115,207,217],"247":[211,115,207,217],"257":[211,115,207,217],"268":[211,115,207,217],"269":[211,115,207,217],"285":[211,115,207,217],"289":[211,115,207,217],"295":[211,115,207,217],"305":[211,115,207,217],"312":[211,115,207,217],"320":[211,115,207,217]},"packages/@n8n/db/src/repositories/webhook.repository.ts":{"8":[218,217],"16":[218,217],"25":[218,217],"36":[218,217]},"packages/@n8n/errors/src/response-errors/auth.error.ts":{"4":[92,207,100,217]},"packages/cli/src/eventbus/event-message-classes/event-message-mcp.ts":{"44":[211,123,207,208,217],"52":[211,123,207,208,217]},"packages/cli/src/modules/dynamic-credentials.ee/services/credential-check-proxy.service.ts":{"24":[211,115,217],"29":[211,115,217],"41":[211,115,217],"70":[211,115,217],"96":[211,115,217],"117":[211,115,217],"148":[211,115,217],"159":[211,115,217],"165":[211,115,217],"171":[211,115,217]},"packages/cli/src/modules/inbound-auth-core/grant-authorization.ts":{"11":[211,115,217]},"packages/cli/src/modules/mcp/dto/update-mcp-settings.dto.ts":{"12":[211,123,207,208,217],"17":[211,123,207,208,217],"21":[211,123,207,208,217],"25":[211,123,207,208,217]},"packages/cli/src/modules/mcp/mcp-protected-resource.ts":{"66":[211,115,123,207,208,217],"76":[211,115,123,207,208,217],"78":[211,115,123,207,208,217],"85":[211,115,123,207,208,217],"103":[211,115,123,207,208,217],"104":[211,115,123,207,208,217],"107":[211,115,123,207,208,217],"118":[211,115,123,207,208,217],"134":[211,115,123,207,208,217],"145":[211,115,123,207,208,217],"150":[211,115,123,207,208,217],"156":[211,115,123,207,208,217],"173":[211,115,123,207,208,217],"187":[211,115,123,207,208,217],"193":[211,115,123,207,208,217],"202":[211,115,123,207,208,217],"206":[211,115,123,207,208,217]},"packages/cli/src/modules/mcp/mcp-tool-availability.ts":{"19":[211,115,123,207,208,217],"23":[211,115,123,207,208,217],"51":[211,115,123,207,208,217]},"packages/cli/src/modules/mcp/mcp.settings.controller.ts":{"21":[211,123,207,208,217],"33":[211,123,207,208,217],"64":[211,123,207,208,217],"70":[211,123,207,208,217],"76":[211,123,207,208,217],"83":[211,123,207,208,217],"94":[211,123,207,208,217],"114":[211,123,207,208,217],"129":[211,123,207,208,217]},"packages/cli/src/modules/mcp/mcp.settings.service.ts":{"54":[211,123,207,208,217],"64":[211,123,207,208,217],"80":[211,123,207,208,217],"89":[211,123,207,208,217],"105":[211,123,207,208,217],"114":[211,123,207,208,217],"134":[211,123,207,208,217],"143":[211,123,207,208,217],"201":[211,123,207,208,217],"230":[211,123,207,208,217],"240":[211,123,207,208,217],"266":[211,123,207,208,217],"290":[211,123,207,208,217],"295":[211,123,207,208,217],"311":[211,123,207,208,217],"314":[211,123,207,208,217],"334":[211,123,207,208,217],"354":[211,123,207,208,217]},"packages/cli/src/modules/oauth-server/database/repositories/oauth-access-token.repository.ts":{"15":[211,115,207,217],"19":[211,115,207,217]},"packages/cli/src/modules/oauth-server/database/repositories/oauth-refresh-token.repository.ts":{"18":[211,115,207,217],"22":[211,115,207,217],"31":[211,115,207,217],"45":[211,115,207,217]},"packages/cli/src/modules/oauth-server/oauth-authorization-code.service.ts":{"17":[211,115,207,217],"23":[211,115,207,217],"55":[211,115,207,217],"83":[211,115,207,217],"111":[211,115,207,217],"138":[211,115,207,217],"151":[211,115,207,217],"157":[211,115,207,217]},"packages/cli/src/modules/oauth-server/oauth-consent.controller.ts":{"14":[211,115,207,217],"21":[211,115,207,217],"81":[211,115,207,217],"122":[211,115,207,217],"129":[211,115,207,217],"136":[211,115,207,217]},"packages/cli/src/modules/oauth-server/oauth-consent.service.ts":{"58":[211,115,207,217],"72":[211,115,207,217],"170":[211,115,207,217],"178":[211,115,207,217],"180":[211,115,207,217],"188":[211,115,207,217],"198":[211,115,207,217],"206":[211,115,207,217],"263":[211,115,207,217],"279":[211,115,207,217],"328":[211,115,207,217],"349":[211,115,207,217],"361":[211,115,207,217],"390":[211,115,207,217],"400":[211,115,207,217]},"packages/cli/src/modules/oauth-server/oauth-server.service.ts":{"71":[211,115,10,123,207,217],"120":[211,115,10,123,207,217],"126":[211,115,10,123,207,217],"127":[211,115,10,123,207,217],"143":[211,115,10,123,207,217],"159":[211,115,10,123,207,217],"161":[211,115,10,123,207,217],"195":[211,115,10,123,207,217],"219":[211,115,10,123,207,217],"224":[211,115,10,123,207,217],"242":[211,115,10,123,207,217],"262":[211,115,10,123,207,217],"314":[211,115,10,123,207,217],"316":[211,115,10,123,207,217],"317":[211,115,10,123,207,217],"320":[211,115,10,123,207,217],"376":[211,115,10,123,207,217],"392":[211,115,10,123,207,217],"409":[211,115,10,123,207,217],"413":[211,115,10,123,207,217],"461":[211,115,10,123,207,217],"503":[211,115,10,123,207,217],"513":[211,115,10,123,207,217],"600":[211,115,10,123,207,217],"614":[211,115,10,123,207,217],"618":[211,115,10,123,207,217],"648":[211,115,10,123,207,217],"655":[211,115,10,123,207,217],"667":[211,115,10,123,207,217],"682":[211,115,10,123,207,217],"687":[211,115,10,123,207,217],"722":[211,115,10,123,207,217],"748":[211,115,10,123,207,217],"749":[211,115,10,123,207,217],"767":[211,115,10,123,207,217],"805":[211,115,10,123,207,217],"817":[211,115,10,123,207,217],"871":[211,115,10,123,207,217],"886":[211,115,10,123,207,217]},"packages/cli/src/modules/oauth-server/oauth-session.service.ts":{"29":[211,115,207,217],"34":[211,115,207,217],"54":[211,115,207,217],"62":[211,115,207,217],"69":[211,115,207,217]},"packages/cli/src/modules/oauth-server/oauth-signing-key.service.ts":{"83":[211,115,207,217],"95":[211,115,207,217],"115":[211,115,207,217],"132":[211,115,207,217],"134":[211,115,207,217],"142":[211,115,207,217],"163":[211,115,207,217],"179":[211,115,207,217],"181":[211,115,207,217],"185":[211,115,207,217],"189":[211,115,207,217],"199":[211,115,207,217],"204":[211,115,207,217],"208":[211,115,207,217],"212":[211,115,207,217],"219":[211,115,207,217],"222":[211,115,207,217],"223":[211,115,207,217],"238":[211,115,207,217],"250":[211,115,207,217],"291":[211,115,207,217],"313":[211,115,207,217],"321":[211,115,207,217],"322":[211,115,207,217],"323":[211,115,207,217]},"packages/cli/src/modules/oauth-server/oauth-token.service.ts":{"48":[211,115,207,217],"61":[211,115,207,217],"70":[211,115,207,217],"109":[211,115,207,217],"117":[211,115,207,217],"138":[211,115,207,217],"143":[211,115,207,217],"228":[211,115,207,217],"235":[211,115,207,217],"278":[211,115,207,217],"291":[211,115,207,217],"370":[211,115,207,217],"377":[211,115,207,217],"392":[211,115,207,217],"416":[211,115,207,217],"428":[211,115,207,217],"446":[211,115,207,217],"458":[211,115,207,217],"472":[211,115,207,217],"492":[211,115,207,217],"509":[211,115,207,217]},"packages/cli/src/modules/oauth-server/oauth.controller.ts":{"46":[211,115,10,207,217],"73":[211,115,10,207,217],"75":[211,115,10,207,217],"97":[211,115,10,207,217],"138":[211,115,10,207,217],"148":[211,115,10,207,217],"155":[211,115,10,207,217],"172":[211,115,10,207,217],"183":[211,115,10,207,217],"193":[211,115,10,207,217],"208":[211,115,10,207,217],"218":[211,115,10,207,217],"233":[211,115,10,207,217],"263":[211,115,10,207,217],"291":[211,115,10,207,217],"303":[211,115,10,207,217]},"packages/cli/src/modules/oauth-server/oauth.errors.ts":{"8":[207,217],"20":[207,217],"28":[207,217],"35":[207,217]},"packages/cli/src/modules/oauth-server/oauth.helpers.ts":{"13":[211,115,207,217],"34":[211,115,207,217],"58":[211,115,207,217]},"packages/cli/src/modules/oauth-server/protected-resource-resolvers/chat-trigger-resource.base.ts":{"40":[211,218,207,217],"60":[211,218,207,217],"66":[211,218,207,217],"105":[211,218,207,217],"106":[211,218,207,217],"107":[211,218,207,217]},"packages/cli/src/modules/oauth-server/protected-resource-resolvers/chat-trigger-resource.resolver.ts":{"14":[211,218,207,217],"27":[211,218,207,217],"31":[211,218,207,217],"40":[211,218,207,217],"54":[211,218,207,217]},"packages/cli/src/modules/oauth-server/protected-resource-resolvers/chat-trigger-test-resource.resolver.ts":{"13":[211,218,207,217],"25":[211,218,207,217],"29":[211,218,207,217],"39":[211,218,207,217],"50":[211,218,207,217]},"packages/cli/src/modules/oauth-server/protected-resource-resolvers/form-trigger-resource.resolver.ts":{"23":[211,115,207,217],"35":[211,115,207,217],"45":[211,115,207,217],"67":[211,115,207,217],"87":[211,115,207,217],"88":[211,115,207,217],"89":[211,115,207,217]},"packages/cli/src/modules/oauth-server/protected-resource-resolvers/form-trigger-test-resource.resolver.ts":{"22":[211,115,218,207,217],"33":[211,115,218,207,217],"43":[211,115,218,207,217],"65":[211,115,218,207,217],"89":[211,115,218,207,217],"90":[211,115,218,207,217],"91":[211,115,218,207,217]},"packages/cli/src/modules/oauth-server/protected-resource-resolvers/utils.ts":{"41":[211,115,218,207,217],"54":[211,115,218,207,217],"61":[211,115,218,207,217],"84":[211,115,218,207,217],"109":[211,115,218,207,217],"127":[211,115,218,207,217],"138":[211,115,218,207,217],"143":[211,115,218,207,217],"157":[211,115,218,207,217]},"packages/cli/src/modules/oauth-server/protected-resource-resolvers/workflow-mcp-test-trigger-resource.resolver.ts":{"20":[211,115,207,217],"31":[211,115,207,217],"41":[211,115,207,217],"66":[211,115,207,217],"86":[211,115,207,217],"87":[211,115,207,217]},"packages/cli/src/modules/oauth-server/protected-resource-resolvers/workflow-mcp-trigger-resource.resolver.ts":{"21":[211,115,10,207,217],"33":[211,115,10,207,217],"43":[211,115,10,207,217],"86":[211,115,10,207,217],"106":[211,115,10,207,217],"107":[211,115,10,207,217]},"packages/cli/src/modules/oauth-server/protected-resource-resolvers/workflow-webhook-test-trigger-resource.resolver.ts":{"42":[211,207,217],"53":[211,207,217],"64":[211,207,217],"89":[211,207,217],"105":[211,207,217],"109":[211,207,217],"120":[211,207,217],"126":[211,207,217],"141":[211,207,217],"142":[211,207,217],"150":[211,207,217],"151":[211,207,217]},"packages/cli/src/modules/oauth-server/protected-resource-resolvers/workflow-webhook-trigger-resource.resolver.ts":{"58":[211,218,207,217],"70":[211,218,207,217],"81":[211,218,207,217],"100":[211,218,207,217],"113":[211,218,207,217],"124":[211,218,207,217],"141":[211,218,207,217],"156":[211,218,207,217],"157":[211,218,207,217],"171":[211,218,207,217],"175":[211,218,207,217]},"packages/cli/src/modules/oauth-server/resource-gate.ts":{"16":[211,115,217],"21":[211,115,217],"22":[211,115,217]},"packages/cli/src/modules/oauth-server/resource-identity.ts":{"14":[211,115,217]},"packages/cli/src/services/oauth-token-verifier-proxy.service.ts":{"95":[211,115,207,217],"98":[211,115,207,217],"102":[211,115,207,217]},"packages/cli/src/services/protected-resource.registry.ts":{"46":[211,115,123,207,217],"49":[211,115,123,207,217],"54":[211,115,123,207,217],"68":[211,115,123,207,217],"70":[211,115,123,207,217],"74":[211,115,123,207,217],"78":[211,115,123,207,217],"83":[211,115,123,207,217],"86":[211,115,123,207,217],"102":[211,115,123,207,217],"137":[211,115,123,207,217],"143":[211,115,123,207,217],"148":[211,115,123,207,217],"164":[211,115,123,207,217],"173":[211,115,123,207,217]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/if.svg":{"11":"b:AAAkgAAAAAAAQDAAAAAAAAgAAAAAhQGgAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/merge.svg":{"11":[90,77,170,15]},"packages/frontend/editor-ui/src/app/composables/useReportWorkflowFailuresToParent.ts":{"33":[104,105,160,161]},"packages/frontend/editor-ui/src/app/layouts/DemoLayout.vue":{"18":[104,105,160,161],"62":[104,105,160,161],"89":[104,105,160,161]},"packages/frontend/editor-ui/src/features/execution/logs/components/DemoFooter.vue":{"9":[104,105,160,161],"10":[104,105,160,161],"11":[104,105,160,161]},"packages/frontend/editor-ui/src/app/components/FocusPanel.vue":{"57":[148,163],"89":[148,163],"93":[148,163],"113":[148,163],"129":[148,163],"137":[148,163],"140":[148,163],"142":[148,163],"196":[148,163],"202":[148,163],"213":[148,163],"215":[148,163],"233":[148,163],"235":[163],"241":[163],"369":[148,163],"373":[148,163],"374":[148,163],"395":[148,163],"600":[163],"603":[163]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/components/ExperimentalCanvasNodeSettings.vue":{"21":[46,148,163],"31":[46,148,163],"32":[46,148,163],"35":[46,148,163],"36":[46,148,163],"41":[46,148,163],"43":[46],"49":[46],"70":[46,148,163],"91":[46],"93":[46]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/components/ExperimentalEmbeddedNdvMapper.vue":{"19":[31,46,148,163],"39":[31,46,148,163],"43":[31,46,148,163],"45":[46,163],"54":[46,163],"67":[46],"80":[31,46,148,163],"87":[46,148,163],"96":[31,46,148,163],"111":[46,163]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/components/ExperimentalFocusPanelHeader.vue":{"18":[148,163],"27":[148,163],"28":[148,163],"32":[148,163]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/components/ExperimentalNodeDetailsDrawer.vue":{"21":[148,163],"26":[148,163],"27":[148],"33":[148,163],"36":[148,163],"37":[148],"46":[148,163],"51":[148],"53":[148],"58":[148]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/composables/useExpressionResolveCtx.ts":{"7":[31,46,148,163],"12":[31,46,148,163],"21":[31,46,148,163]},"packages/cli/src/task-runners/errors/task-cancelled.error.ts":{"4":[221]},"packages/cli/src/utils/object-to-error.ts":{"10":[221]},"packages/frontend/editor-ui/src/app/utils/forceParse.ts":{"9":[28,46,166,173]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ExpressionEditorModal/ExpressionEditorModalInput.vue":{"29":[46,173],"42":[46,173],"52":[46,173],"60":[46,173],"66":[46,173],"69":[46,173],"70":[46,173],"76":[46,173],"83":[46,173],"89":[46,173],"94":[46,173],"97":[46,173]},"packages/@n8n/errors/src/response-errors/bad-request.error.ts":{"4":[192,8,19,20,21,49,22,99,224,185],"8":[192,8,19,20,21,49,22,99,224,185]},"packages/cli/src/errors/response-errors/workflow-activation-bad-request.error.ts":{"8":[8,224]},"packages/cli/src/errors/response-errors/workflow-validation.error.ts":{"9":[8,224]},"packages/nodes-base/nodes/StopAndError/StopAndError.node.ts":{"82":[27,28,223]},"packages/nodes-base/nodes/StopAndError/utils.ts":{"14":[27,28,223],"18":[27,28,223]},"packages/@n8n/db/src/utils/separate.ts":{"1":[36,184],"5":[36,184]},"packages/frontend/editor-ui/src/app/components/CharacterCount.vue":{"11":[46,134,75,184,185],"12":[46,134,75,184,185],"20":[46,134,75,184,185]},"packages/frontend/editor-ui/src/app/components/WorkflowVersionForm.vue":{"18":[46,134,75,184,185],"28":[46,134,75,184,185],"32":[46],"39":[46,134,75,184,185],"48":[46,134,75,184,185],"68":[46,134,75,184,185]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/workflowActivated.ts":{"12":[134,75,182,87,184,185]},"packages/frontend/editor-ui/src/app/composables/workflowPublicationConfirmation.ts":{"43":[46,134,75,184,185],"46":[46],"59":[46,134,75,182,87,184,185],"77":[46,134,75,184,185]},"packages/frontend/editor-ui/src/features/workflows/components/ActivationModal.vue":{"22":[46,134,75,184,185],"31":[46,134,75,184,185],"33":[46,134,75,184,185],"71":[46],"81":[46],"85":[46],"90":[46],"94":[46,75],"98":[46,134,75,184,185],"103":[46,134,75,184,185],"105":[46,134,75,184,185],"110":[46,134,75,184,185],"122":[46,134,75,184,185],"125":[46,134,75,184,185]},"packages/frontend/editor-ui/src/features/workflows/components/WorkflowPublishModal.vue":{"31":[46,134,75,184,185],"46":[46,134,75,184,185],"50":[46,134,75,184,185],"54":[46,134,75,184,185],"60":[46,134,75,184,185],"68":[46],"70":[46,134,75,184,185],"72":[46,134,75,184,185],"81":[46,134,75,184,185],"87":[46,134,75,184,185],"109":[46,134,75,184,185],"113":[46,134,75,184,185],"131":[46,134,75,184,185],"135":[46,134,75,184,185],"138":[46,134],"144":[46],"145":[46],"160":[46,134,75,184,185],"173":[46],"203":[46,134,75,184,185],"230":[46,134,75,184,185],"264":[46,134,75,184,185],"278":[46,134,75,184,185],"279":[46,134,75,184,185],"281":[46,134,75,184,185],"288":[46],"296":[46],"304":[46],"308":[46],"309":[46],"318":[46],"325":[46],"343":[46]},"packages/frontend/editor-ui/src/features/workflows/workflowHistory/utils.ts":{"9":[46,168],"12":[46],"15":[46,134,75,184,185],"19":[46,168],"37":[46,168],"69":[46,168],"74":[46,168],"114":[46,168]},"packages/@n8n/ai-utilities/src/agent-config/config-normalization.ts":{"64":[23],"88":[23],"107":[23],"124":[23],"143":[23],"156":[23],"166":[23],"177":[23],"183":[23],"204":[23]},"packages/@n8n/ai-utilities/src/agent-config/model-id.ts":{"2":[23,26,19,20,21,49,22],"15":[23,26,19,20,21,49,22]},"packages/@n8n/ai-utilities/src/agent-config/native-web-search-provider-tools.ts":{"12":[23,26],"16":[23,26],"20":[23,26],"34":[23,26],"59":[23,26]},"packages/@n8n/api-types/src/agents/sanitize-agent-json-config.ts":{"13":[23,26],"17":[23,26],"21":[23,26],"25":[23,26],"29":[23,26],"33":[23,26],"37":[23,26],"41":[23,26],"45":[23,26],"49":[23,26],"55":[23,26],"61":[23,26],"75":[23,26],"79":[23,26],"94":[23,26],"102":[23,26],"103":[23,26],"109":[23,26],"119":[23,26],"124":[23,26],"144":[23,26],"153":[23,26],"162":[23,26],"169":[23,26],"197":[23,26],"213":[23,26],"243":[23,26],"247":[23,26]},"packages/cli/src/modules/agents/agent-change-publisher.service.ts":{"23":[23,26],"29":[23,26]},"packages/cli/src/modules/agents/agent-config-preparation.service.ts":{"28":[23],"34":[23],"42":[23],"60":[23],"61":[23],"70":[23],"103":[23],"110":[23],"126":[23],"129":[23]},"packages/cli/src/modules/agents/agent-modification-telemetry.service.ts":{"66":[23],"73":[23],"98":[23],"108":[23],"131":[23],"150":[23],"152":[23],"175":[23]},"packages/cli/src/modules/agents/agent-push-recipients.service.ts":{"8":[23,26],"13":[23,26],"17":[23,26]},"packages/cli/src/modules/agents/agent-runtime-cache.service.ts":{"107":[23,26],"118":[23,26],"127":[23,26],"148":[23,26],"160":[23,26],"186":[23,26],"195":[23,26],"201":[23,26],"209":[23,26],"215":[23,26],"235":[23,26],"261":[23,26],"273":[23,26],"304":[23,26],"372":[23,26],"394":[23,26],"398":[23,26],"411":[23,26]},"packages/cli/src/modules/agents/agent-save-completion.service.ts":{"13":[23],"19":[23],"30":[23],"40":[23],"44":[23],"52":[23]},"packages/cli/src/modules/agents/agent-setup-completion.service.ts":{"36":[23],"47":[23],"75":[23],"88":[23],"92":[23],"98":[23]},"packages/cli/src/modules/agents/agent-skills.service.ts":{"35":[23],"41":[23],"52":[23],"60":[23],"76":[23],"92":[23],"107":[23],"133":[23],"143":[23],"147":[23],"156":[23],"218":[23],"240":[23],"248":[23],"249":[23],"251":[23],"262":[23],"271":[23],"282":[23],"289":[23],"297":[23],"301":[23],"316":[23],"320":[23],"325":[23]},"packages/cli/src/modules/agents/agent-update-broadcaster.ts":{"17":[23],"27":[23],"28":[23],"36":[23],"51":[23]},"packages/cli/src/modules/agents/integrations/chat-integration.service.ts":{"122":[23],"145":[23],"181":[23],"203":[23],"216":[23],"230":[23],"248":[23],"266":[23],"283":[23],"310":[23],"329":[23],"371":[23],"431":[23],"442":[23],"474":[23],"482":[23],"528":[23],"547":[23],"562":[23],"596":[23],"613":[23],"619":[23],"645":[23],"656":[23],"668":[23],"672":[23],"682":[23],"690":[23],"712":[23],"726":[23],"734":[23],"740":[23],"765":[23],"787":[23],"807":[23],"808":[23],"811":[23],"830":[23],"852":[23],"912":[23],"922":[23],"943":[23],"961":[23],"971":[23],"975":[23],"1003":[23],"1012":[23],"1013":[23],"1022":[23],"1032":[23],"1037":[23],"1063":[23],"1099":[23],"1114":[23],"1122":[23],"1123":[23],"1133":[23],"1140":[23],"1149":[23],"1168":[23],"1172":[23],"1254":[23],"1273":[23],"1279":[23],"1285":[23],"1293":[23],"1308":[23],"1325":[23],"1331":[23],"1339":[23],"1352":[23],"1382":[23]},"packages/cli/src/modules/agents/integrations/integrations-sync.ts":{"18":[23]},"packages/cli/src/modules/agents/json-config/node-tool-ai-gateway.service.ts":{"16":[23],"21":[23]},"packages/cli/src/modules/agents/json-config/prune-missing-config-references.ts":{"6":[23],"12":[23],"14":[23],"20":[23],"23":[23],"31":[23]},"packages/cli/src/modules/agents/json-config/reconcile-node-tool-gateway-credentials.ts":{"14":[23],"22":[23],"35":[23],"53":[23],"59":[23],"71":[23],"93":[23],"110":[23],"133":[23],"166":[23],"169":[23],"185":[23],"199":[23],"201":[23],"207":[23],"250":[23]},"packages/cli/src/modules/agents/json-config/sanitize-unknown-agent-credentials.ts":{"7":[23,26],"14":[23,26]},"packages/cli/src/modules/agents/utils/agent-capabilities.ts":{"28":[23],"32":[23],"38":[23],"41":[23],"45":[23],"46":[23],"50":[23],"54":[23],"63":[23],"84":[23]},"packages/cli/src/modules/agents/utils/agent-draft.utils.ts":{"14":[23],"26":[23]},"packages/cli/src/modules/agents/utils/extract-agent-credential-ids.ts":{"7":[23,26],"9":[23,26]},"packages/cli/src/modules/agents/utils/visit-agent-credential-references.ts":{"37":[23,26],"49":[23,26],"79":[23,26],"86":[23,26]},"packages/cli/src/utils/ttl-map.ts":{"24":[23,26],"30":[23,26],"34":[23,26],"44":[23,26],"49":[23,26],"56":[23,26],"65":[23,26],"73":[23,26],"78":[23,26],"84":[23,26],"94":[23,26],"99":[23,26],"104":[23,26],"109":[23,26],"117":[23,26]},"localhost-45279/assets/index-Dv_brJ4-.js":{"3":[23]},"localhost-45279/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[23],"9":[23],"10":[23],"19":[23],"23":[23],"29":[23],"33":[23],"34":[23]},"packages/frontend/@n8n/design-system/src/components/N8nHoverCard/HoverCard.vue":{"61":"b:AAD4AgBABwAAAAABAADwBwAAAAAAAAAAAAAAAAA=","89":"b:AAD4AgBABwAAAAABAADwBwAAAAAAAAAAAAAAAAA=","91":"b:AAD4AgBABwAAAAABAADwBwAAAAAAAAAAAAAAAAA=","96":[46],"101":[46],"105":"b:AAD4AgBABwAAAAABAADwBwAAAAAAAAAAAAAAAAA=","106":[46],"115":"b:AAD4AgBABwAAAAABAADwBwAAAAAAAAAAAAAAAAA=","124":"b:AAD4AgBABwAAAAABAADwBwAAAAAAAAAAAAAAAAA=","128":"b:AAD4AgBABwAAAAABAADwBwAAAAAAAAAAAAAAAAA=","133":"b:AAD4AgBABwAAAAABAADwBwAAAAAAAAAAAAAAAAA=","145":[46],"152":[46]},"packages/frontend/@n8n/design-system/src/components/N8nUserStack/UserStack.vue":{"11":[23,46,88],"26":[46],"28":[46],"40":[46],"44":[23,46,88],"54":[23,46,88],"60":[23,46,88],"64":[46],"67":[23,46,88],"72":[23,46,88],"75":[23,46,88],"92":[46],"94":[46],"96":[46],"103":[46]},"packages/cli/src/services/heap-diagnostics.service.ts":{"18":[193],"23":[193],"40":[193],"64":[193]},"packages/cli/src/services/process-internals.service.ts":{"19":[193],"24":[193],"27":[193]},"packages/core/src/execution-engine/node-execution-context/utils/create-node-as-tool.ts":{"43":[6,10],"89":[6,10],"97":[6,10],"109":[6,10],"115":[6,10],"125":[6,10],"139":[6,10]},"packages/workflow/src/from-ai-parse-utils.ts":{"27":[6,10],"59":[6,10],"110":[6,10],"120":[6,10],"148":[6,10],"199":[6,10],"251":[6,10],"327":[6,10],"330":[6,10],"332":[6,10],"334":[6,10],"338":[6,10],"345":[6,10],"347":[6,10],"365":[6,10],"463":[6,10],"494":[6,10],"514":[6,10],"530":[6,10]},"packages/workflow/src/schemas.ts":{"89":[6,19,48,49,22],"102":[6,19,48,49,22],"166":[6,19,48,49,22],"240":[6,19,48,49,22],"265":[6,19,48,49,22],"431":[6,19,48,49,22],"508":[6,19,48,49,22],"509":[6,19,48,49,22],"522":[6,19,48,49,22]},"packages/workflow/src/tool-helpers.ts":{"10":[6,10,12]},"localhost-43777/assets/index-Dv_brJ4-.js":{"3":[6,18]},"localhost-43777/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[6,18],"9":[6,18],"10":[6,18],"19":[6,18],"23":[6,18],"29":[6,18],"33":[6,18],"34":[6,18]},"packages/@n8n/api-types/src/push/heartbeat.ts":{"9":[6,46]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ToolListItem.vue":{"32":[6],"39":[6],"46":[6],"52":[6],"57":[6],"58":[6],"75":[6],"92":[6],"106":[6],"116":[6],"127":[6],"168":[6]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ToolsManagerModal.vue":{"55":[6],"56":[6],"60":[6],"67":[6],"87":[6],"90":[6],"91":[6],"98":[6],"122":[6],"124":[6],"132":[6],"140":[6],"154":[6],"159":[6],"160":[6],"166":[6],"173":[6],"177":[6],"191":[6],"227":[6],"228":[6],"231":[6],"235":[6],"292":[6],"315":[6],"328":[6],"357":[6],"366":[6],"386":[6],"389":[6],"411":[6],"424":[6],"433":[6],"441":[6],"456":[6],"464":[6],"471":[6],"492":[6],"493":[6]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/composables/useRestrictedNodeWarning.ts":{"13":[6]},"packages/frontend/editor-ui/src/features/shared/toolConfig/NodeToolSettingsContent.vue":{"87":[6],"92":[6],"94":[6],"108":[6],"112":[6],"116":[6],"126":[6],"131":[6],"134":[6],"142":[6],"143":[6],"146":[6],"160":[6],"178":[6],"181":[6],"193":[6],"205":[6],"214":[6],"223":[6],"300":[6],"320":[6],"321":[6],"382":[6],"383":[6],"398":[6],"403":[6],"412":[6],"413":[6],"421":[6],"455":[6],"493":[6]},"packages/@n8n/agents/src/runtime/guardrails/guardrail-runner.ts":{"19":[26,19,20,21,49,22],"25":[26,19,20,21,49,22],"33":[26,19,20,21,49,22],"37":[26,19,20,21,49,22],"46":[26,19,20,21,49,22],"54":[26,19,20,21,49,22],"60":[26,19,20,21,49,22],"68":[26,19,20,21,49,22]},"packages/@n8n/agents/src/runtime/loop/agent-runtime.ts":{"88":[26,19,20,48,21,118,119,49,22],"90":[26,19,20,48,21,118,119,49,22],"98":[26,19,20,48,21,118,119,49,22],"104":[26,19,20,48,21,118,119,49,22],"105":[26,19,20,48,21,118,119,49,22],"106":[26,19,20,48,21,118,119,49,22],"110":[26,19,20,48,21,118,119,49,22],"198":[26,19,20,48,21,118,119,49,22],"234":[26,19,20,48,21,118,119,49,22],"248":[26,19,20,48,21,118,119,49,22],"256":[26,19,20,48,21,118,119,49,22],"262":[26,19,20,48,21,118,119,49,22],"267":[26,19,20,48,21,118,119,49,22],"278":[26,19,20,48,21,118,119,49,22],"293":[26,19,20,48,21,118,119,49,22],"322":[26,19,20,48,21,118,119,49,22],"330":[26,19,20,48,21,118,119,49,22],"345":[26,19,20,48,21,118,119,49,22],"367":[26,19,20,48,21,118,119,49,22],"433":[26,19,20,48,21,118,119,49,22],"483":[26,19,20,48,21,118,119,49,22],"520":[26,19,20,48,21,118,119,49,22],"526":[26,19,20,48,21,118,119,49,22],"545":[26,19,20,48,21,118,119,49,22],"554":[26,19,20,48,21,118,119,49,22],"575":[26,19,20,48,21,118,119,49,22],"578":[26,19,20,48,21,118,119,49,22],"581":[26,19,20,48,21,118,119,49,22],"592":[26,19,20,48,21,118,119,49,22],"605":[26,19,20,48,21,118,119,49,22],"611":[26,19,20,48,21,118,119,49,22],"620":[26,19,20,48,21,118,119,49,22],"624":[26,19,20,48,21,118,119,49,22],"628":[26,19,20,48,21,118,119,49,22],"655":[26,19,20,48,21,118,119,49,22],"682":[26,19,20,48,21,118,119,49,22],"701":[26,19,20,48,21,118,119,49,22],"709":[26,19,20,48,21,118,119,49,22],"712":[26,19,20,48,21,118,119,49,22],"725":[26,19,20,48,21,118,119,49,22],"738":[26,19,20,48,21,118,119,49,22],"746":[26,19,20,48,21,118,119,49,22],"750":[26,19,20,48,21,118,119,49,22],"751":[26,19,20,48,21,118,119,49,22],"752":[26,19,20,48,21,118,119,49,22],"753":[26,19,20,48,21,118,119,49,22],"754":[26,19,20,48,21,118,119,49,22],"755":[26,19,20,48,21,118,119,49,22],"756":[26,19,20,48,21,118,119,49,22],"757":[26,19,20,48,21,118,119,49,22],"762":[26,19,20,48,21,118,119,49,22],"797":[26,19,20,48,21,118,119,49,22],"858":[26,19,20,48,21,118,119,49,22],"889":[26,19,20,48,21,118,119,49,22],"920":[26,19,20,48,21,118,119,49,22],"927":[26,19,20,48,21,118,119,49,22],"929":[26,19,20,48,21,118,119,49,22],"931":[26,19,20,48,21,118,119,49,22],"933":[26,19,20,48,21,118,119,49,22],"937":[26,19,20,48,21,118,119,49,22],"941":[26,19,20,48,21,118,119,49,22],"947":[26,19,20,48,21,118,119,49,22],"961":[26,19,20,48,21,118,119,49,22],"965":[26,19,20,48,21,118,119,49,22],"999":[26,19,20,48,21,118,119,49,22],"1053":[26,19,20,48,21,118,119,49,22],"1086":[26,19,20,48,21,118,119,49,22],"1091":[26,19,20,48,21,118,119,49,22],"1098":[26,19,20,48,21,118,119,49,22],"1105":[26,19,20,48,21,118,119,49,22],"1134":[26,19,20,48,21,118,119,49,22],"1145":[26,19,20,48,21,118,119,49,22],"1187":[26,19,20,48,21,118,119,49,22],"1204":[26,19,20,48,21,118,119,49,22],"1226":[26,19,20,48,21,118,119,49,22],"1246":[26,19,20,48,21,118,119,49,22],"1263":[26,19,20,48,21,118,119,49,22],"1265":[26,19,20,48,21,118,119,49,22],"1281":[26,19,20,48,21,118,119,49,22],"1287":[26,19,20,48,21,118,119,49,22],"1293":[26,19,20,48,21,118,119,49,22],"1294":[26,19,20,48,21,118,119,49,22],"1295":[26,19,20,48,21,118,119,49,22],"1296":[26,19,20,48,21,118,119,49,22],"1301":[26,19,20,48,21,118,119,49,22],"1321":[26,19,20,48,21,118,119,49,22],"1361":[26,19,20,48,21,118,119,49,22],"1382":[26,19,20,48,21,118,119,49,22],"1404":[26,19,20,48,21,118,119,49,22],"1405":[26,19,20,48,21,118,119,49,22],"1412":[26,19,20,48,21,118,119,49,22],"1417":[26,19,20,48,21,118,119,49,22],"1422":[26,19,20,48,21,118,119,49,22],"1433":[26,19,20,48,21,118,119,49,22],"1448":[26,19,20,48,21,118,119,49,22]},"packages/@n8n/agents/src/runtime/loop/execution-counter.ts":{"14":[26,19,20,21,49,22],"22":[26,19,20,21,49,22],"24":[26,19,20,21,49,22],"32":[26,19,20,21,49,22],"34":[26,19,20,21,49,22],"35":[26,19,20,21,49,22],"36":[26,19,20,21,49,22],"40":[26,19,20,21,49,22],"42":[26,19,20,21,49,22],"45":[26,19,20,21,49,22],"54":[26,19,20,21,49,22]},"packages/@n8n/agents/src/runtime/loop/hydrate-file-parts.ts":{"24":[26,19,20,21,49,22]},"packages/@n8n/agents/src/runtime/loop/run-output-sink.ts":{"15":[26,19,20,21,49,22]},"packages/@n8n/agents/src/runtime/loop/runtime-context.ts":{"44":[26,19,20,21,49,22],"46":[26,19,20,21,49,22],"49":[26,19,20,21,49,22],"72":[26,19,20,21,49,22],"77":[26,19,20,21,49,22],"82":[26,19,20,21,49,22],"107":[26,19,20,21,49,22],"119":[26,19,20,21,49,22],"128":[26,19,20,21,49,22],"152":[26,19,20,21,49,22],"166":[26,19,20,21,49,22],"167":[26,19,20,21,49,22],"178":[26,19,20,21,49,22],"206":[26,19,20,21,49,22],"211":[26,19,20,21,49,22],"233":[26,19,20,21,49,22],"251":[26,19,20,21,49,22],"266":[26,19,20,21,49,22],"282":[26,19,20,21,49,22],"296":[26,19,20,21,49,22],"304":[26,19,20,21,49,22],"331":[26,19,20,21,49,22],"342":[26,19,20,21,49,22],"344":[26,19,20,21,49,22],"362":[26,19,20,21,49,22],"364":[26,19,20,21,49,22],"374":[26,19,20,21,49,22],"386":[26,19,20,21,49,22]},"packages/@n8n/agents/src/runtime/loop/runtime-helpers.ts":{"15":[26,19,20,21,49,22],"23":[26,19,20,21,49,22],"34":[26,19,20,21,49,22],"65":[26,19,20,21,49,22],"67":[26,19,20,21,49,22],"71":[26,19,20,21,49,22],"79":[26,19,20,21,49,22],"81":[26,19,20,21,49,22],"85":[26,19,20,21,49,22],"90":[26,19,20,21,49,22],"109":[26,19,20,21,49,22],"148":[26,19,20,21,49,22],"169":[26,19,20,21,49,22],"171":[26,19,20,21,49,22],"172":[26,19,20,21,49,22],"180":[26,19,20,21,49,22],"183":[26,19,20,21,49,22],"184":[26,19,20,21,49,22],"185":[26,19,20,21,49,22],"190":[26,19,20,21,49,22]},"packages/@n8n/agents/src/runtime/loop/stream-sink.ts":{"58":[26,19,20,48,21,118,119,49,22],"61":[26,19,20,48,21,118,119,49,22],"64":[26,19,20,48,21,118,119,49,22],"73":[26,19,20,48,21,118,119,49,22],"91":[26,19,20,48,21,118,119,49,22],"97":[26,19,20,48,21,118,119,49,22],"109":[26,19,20,48,21,118,119,49,22],"125":[26,19,20,48,21,118,119,49,22],"139":[26,19,20,48,21,118,119,49,22],"155":[26,19,20,48,21,118,119,49,22],"159":[26,19,20,48,21,118,119,49,22],"161":[26,19,20,48,21,118,119,49,22],"173":[26,19,20,48,21,118,119,49,22],"185":[26,19,20,48,21,118,119,49,22],"205":[26,19,20,48,21,118,119,49,22],"226":[26,19,20,48,21,118,119,49,22],"235":[26,19,20,48,21,118,119,49,22],"251":[26,19,20,48,21,118,119,49,22],"266":[26,19,20,48,21,118,119,49,22],"267":[26,19,20,48,21,118,119,49,22],"268":[26,19,20,48,21,118,119,49,22],"283":[26,19,20,48,21,118,119,49,22],"329":[26,19,20,48,21,118,119,49,22],"347":[26,19,20,48,21,118,119,49,22],"372":[26,19,20,48,21,118,119,49,22],"381":[26,19,20,48,21,118,119,49,22],"383":[26,19,20,48,21,118,119,49,22],"408":[26,19,20,48,21,118,119,49,22],"434":[26,19,20,48,21,118,119,49,22],"461":[26,19,20,48,21,118,119,49,22]},"packages/@n8n/agents/src/runtime/mcp/mcp-tool-resolver.ts":{"30":[26,19,20,21,49,22],"31":[26,19,20,21,49,22],"34":[26,19,20,21,49,22],"38":[26,19,20,21,49,22],"49":[26,19,20,21,49,22],"52":[26,19,20,21,49,22],"74":[26,19,20,21,49,22],"75":[26,19,20,21,49,22],"94":[26,19,20,21,49,22],"98":[26,19,20,21,49,22],"99":[26,19,20,21,49,22],"102":[26,19,20,21,49,22],"119":[26,19,20,21,49,22],"124":[26,19,20,21,49,22],"140":[26,19,20,21,49,22],"151":[26,19,20,21,49,22]},"packages/@n8n/agents/src/runtime/memory/episodic-memory-capture.ts":{"83":[26,19,20,21,49,22],"105":[26,19,20,21,49,22],"118":[26,19,20,21,49,22],"192":[26,19,20,21,49,22],"204":[26,19,20,21,49,22],"223":[26,19,20,21,49,22],"264":[26,19,20,21,49,22],"278":[26,19,20,21,49,22],"281":[26,19,20,21,49,22],"290":[26,19,20,21,49,22],"307":[26,19,20,21,49,22],"311":[26,19,20,21,49,22],"319":[26,19,20,21,49,22],"326":[26,19,20,21,49,22],"344":[26,19,20,21,49,22],"356":[26,19,20,21,49,22],"361":[26,19,20,21,49,22],"364":[26,19,20,21,49,22],"400":[26,19,20,21,49,22],"401":[26,19,20,21,49,22],"409":[26,19,20,21,49,22],"420":[26,19,20,21,49,22],"424":[26,19,20,21,49,22],"449":[26,19,20,21,49,22],"463":[26,19,20,21,49,22],"479":[26,19,20,21,49,22],"486":[26,19,20,21,49,22],"487":[26,19,20,21,49,22],"493":[26,19,20,21,49,22],"501":[26,19,20,21,49,22],"506":[26,19,20,21,49,22],"515":[26,19,20,21,49,22],"522":[26,19,20,21,49,22],"526":[26,19,20,21,49,22]},"packages/@n8n/agents/src/runtime/memory/episodic-memory.ts":{"69":[19,20,21,49,22],"75":[19,20,21,49,22],"88":[19,20,21,49,22],"92":[19,20,21,49,22],"95":[19,20,21,49,22],"117":[19,20,21,49,22],"134":[19,20,21,49,22],"150":[19,20,21,49,22],"153":[19,20,21,49,22],"165":[19,20,21,49,22],"170":[19,20,21,49,22],"178":[19,20,21,49,22],"179":[19,20,21,49,22],"185":[19,20,21,49,22],"186":[19,20,21,49,22],"194":[19,20,21,49,22],"201":[19,20,21,49,22],"204":[19,20,21,49,22],"205":[19,20,21,49,22],"211":[19,20,21,49,22],"218":[19,20,21,49,22],"221":[19,20,21,49,22],"222":[19,20,21,49,22],"225":[19,20,21,49,22],"226":[19,20,21,49,22],"252":[19,20,21,49,22],"253":[19,20,21,49,22],"261":[19,20,21,49,22],"268":[19,20,21,49,22],"272":[19,20,21,49,22],"276":[19,20,21,49,22],"283":[19,20,21,49,22],"289":[19,20,21,49,22],"293":[19,20,21,49,22],"297":[19,20,21,49,22],"298":[19,20,21,49,22],"301":[19,20,21,49,22],"304":[19,20,21,49,22],"308":[19,20,21,49,22],"322":[19,20,21,49,22],"326":[19,20,21,49,22],"336":[19,20,21,49,22]},"packages/@n8n/agents/src/runtime/memory/memory-orchestrator.ts":{"65":[26,19,20,48,21,119,49,22],"73":[26,19,20,48,21,119,49,22],"88":[26,19,20,48,21,119,49,22],"92":[26,19,20,48,21,119,49,22],"95":[26,19,20,48,21,119,49,22],"103":[26,19,20,48,21,119,49,22],"115":[26,19,20,48,21,119,49,22],"123":[26,19,20,48,21,119,49,22],"173":[26,19,20,48,21,119,49,22],"181":[26,19,20,48,21,119,49,22],"195":[26,19,20,48,21,119,49,22],"196":[26,19,20,48,21,119,49,22],"216":[26,19,20,48,21,119,49,22],"218":[26,19,20,48,21,119,49,22],"219":[26,19,20,48,21,119,49,22],"220":[26,19,20,48,21,119,49,22],"229":[26,19,20,48,21,119,49,22],"254":[26,19,20,48,21,119,49,22],"266":[26,19,20,48,21,119,49,22],"267":[26,19,20,48,21,119,49,22],"272":[26,19,20,48,21,119,49,22],"273":[26,19,20,48,21,119,49,22],"280":[26,19,20,48,21,119,49,22],"306":[26,19,20,48,21,119,49,22],"329":[26,19,20,48,21,119,49,22],"376":[26,19,20,48,21,119,49,22],"389":[26,19,20,48,21,119,49,22],"431":[26,19,20,48,21,119,49,22],"485":[26,19,20,48,21,119,49,22],"504":[26,19,20,48,21,119,49,22],"513":[26,19,20,48,21,119,49,22],"523":[26,19,20,48,21,119,49,22],"600":[26,19,20,48,21,119,49,22],"610":[26,19,20,48,21,119,49,22],"622":[26,19,20,48,21,119,49,22],"623":[26,19,20,48,21,119,49,22],"633":[26,19,20,48,21,119,49,22],"651":[26,19,20,48,21,119,49,22],"672":[26,19,20,48,21,119,49,22],"692":[26,19,20,48,21,119,49,22],"706":[26,19,20,48,21,119,49,22],"715":[26,19,20,48,21,119,49,22],"721":[26,19,20,48,21,119,49,22],"743":[26,19,20,48,21,119,49,22],"762":[26,19,20,48,21,119,49,22],"775":[26,19,20,48,21,119,49,22],"785":[26,19,20,48,21,119,49,22],"805":[26,19,20,48,21,119,49,22],"814":[26,19,20,48,21,119,49,22],"827":[26,19,20,48,21,119,49,22],"836":[26,19,20,48,21,119,49,22],"849":[26,19,20,48,21,119,49,22],"851":[26,19,20,48,21,119,49,22],"862":[26,19,20,48,21,119,49,22],"890":[26,19,20,48,21,119,49,22],"902":[26,19,20,48,21,119,49,22],"911":[26,19,20,48,21,119,49,22],"916":[26,19,20,48,21,119,49,22],"935":[26,19,20,48,21,119,49,22],"946":[26,19,20,48,21,119,49,22]},"packages/@n8n/agents/src/runtime/memory/memory-store.ts":{"54":[19,20,21,49,22],"62":[19,20,21,49,22],"66":[19,20,21,49,22],"82":[19,20,21,49,22],"96":[19,20,21,49,22],"103":[19,20,21,49,22],"126":[19,20,21,49,22],"128":[19,20,21,49,22],"130":[19,20,21,49,22],"131":[19,20,21,49,22],"133":[19,20,21,49,22],"135":[19,20,21,49,22],"137":[19,20,21,49,22],"139":[19,20,21,49,22],"142":[19,20,21,49,22],"144":[19,20,21,49,22],"149":[19,20,21,49,22],"154":[19,20,21,49,22],"169":[19,20,21,49,22],"178":[19,20,21,49,22],"179":[19,20,21,49,22],"182":[19,20,21,49,22],"185":[19,20,21,49,22],"189":[19,20,21,49,22],"203":[19,20,21,49,22],"213":[19,20,21,49,22],"217":[19,20,21,49,22],"219":[19,20,21,49,22],"226":[19,20,21,49,22],"236":[19,20,21,49,22],"242":[19,20,21,49,22],"262":[19,20,21,49,22],"267":[19,20,21,49,22],"278":[19,20,21,49,22],"284":[19,20,21,49,22],"288":[19,20,21,49,22],"322":[19,20,21,49,22],"329":[19,20,21,49,22],"331":[19,20,21,49,22],"336":[19,20,21,49,22],"339":[19,20,21,49,22],"348":[19,20,21,49,22],"361":[19,20,21,49,22],"373":[19,20,21,49,22],"382":[19,20,21,49,22],"402":[19,20,21,49,22],"408":[19,20,21,49,22],"413":[19,20,21,49,22],"422":[19,20,21,49,22],"429":[19,20,21,49,22],"433":[19,20,21,49,22],"439":[19,20,21,49,22],"443":[19,20,21,49,22],"454":[19,20,21,49,22],"475":[19,20,21,49,22],"480":[19,20,21,49,22],"491":[19,20,21,49,22],"495":[19,20,21,49,22],"513":[19,20,21,49,22],"519":[19,20,21,49,22],"521":[19,20,21,49,22],"527":[19,20,21,49,22],"537":[19,20,21,49,22],"551":[19,20,21,49,22],"559":[19,20,21,49,22],"590":[19,20,21,49,22],"596":[19,20,21,49,22],"622":[19,20,21,49,22],"632":[19,20,21,49,22],"643":[19,20,21,49,22],"649":[19,20,21,49,22],"655":[19,20,21,49,22],"665":[19,20,21,49,22],"670":[19,20,21,49,22],"671":[19,20,21,49,22],"675":[19,20,21,49,22],"681":[19,20,21,49,22],"682":[19,20,21,49,22],"688":[19,20,21,49,22],"704":[19,20,21,49,22],"705":[19,20,21,49,22],"720":[19,20,21,49,22],"731":[19,20,21,49,22],"750":[19,20,21,49,22],"763":[19,20,21,49,22],"779":[19,20,21,49,22],"789":[19,20,21,49,22],"799":[19,20,21,49,22],"803":[19,20,21,49,22]},"packages/@n8n/agents/src/runtime/memory/observation-log-defaults.ts":{"139":[19,20,21,49,22],"154":[19,20,21,49,22],"158":[19,20,21,49,22],"298":[19,20,21,49,22],"310":[19,20,21,49,22],"314":[19,20,21,49,22],"316":[19,20,21,49,22],"317":[19,20,21,49,22],"318":[19,20,21,49,22],"319":[19,20,21,49,22],"321":[19,20,21,49,22],"347":[19,20,21,49,22],"355":[19,20,21,49,22]},"packages/@n8n/agents/src/runtime/memory/observation-log-observer.ts":{"65":[19,20,21,49,22],"111":[19,20,21,49,22],"144":[19,20,21,49,22],"157":[19,20,21,49,22],"158":[19,20,21,49,22],"192":[19,20,21,49,22],"222":[19,20,21,49,22],"267":[19,20,21,49,22],"281":[19,20,21,49,22],"332":[19,20,21,49,22],"334":[19,20,21,49,22],"337":[19,20,21,49,22],"341":[19,20,21,49,22],"345":[19,20,21,49,22],"351":[19,20,21,49,22],"363":[19,20,21,49,22],"377":[19,20,21,49,22],"388":[19,20,21,49,22],"408":[19,20,21,49,22],"432":[19,20,21,49,22],"456":[19,20,21,49,22],"461":[19,20,21,49,22],"469":[19,20,21,49,22],"477":[19,20,21,49,22]},"packages/@n8n/agents/src/runtime/memory/observation-log-reflector.ts":{"77":[19,20,21,22],"92":[19,20,21,22],"93":[19,20,21,22],"94":[19,20,21,22],"119":[19,20,21,22],"123":[19,20,21,22],"124":[19,20,21,22],"133":[19,20,21,22],"135":[19,20,21,22],"139":[19,20,21,22],"140":[19,20,21,22],"143":[19,20,21,22],"144":[19,20,21,22],"145":[19,20,21,22],"146":[19,20,21,22],"156":[19,20,21,22],"172":[19,20,21,22],"179":[19,20,21,22],"220":[19,20,21,22],"253":[19,20,21,22],"255":[19,20,21,22],"265":[19,20,21,22],"278":[19,20,21,22],"292":[19,20,21,22],"301":[19,20,21,22],"313":[19,20,21,22],"318":[19,20,21,22],"335":[19,20,21,22],"354":[19,20,21,22],"360":[19,20,21,22],"363":[19,20,21,22],"370":[19,20,21,22],"371":[19,20,21,22],"374":[19,20,21,22],"380":[19,20,21,22]},"packages/@n8n/agents/src/runtime/memory/observation-log-renderer.ts":{"35":[19,20,21,49,22],"41":[19,20,21,49,22],"47":[19,20,21,49,22],"51":[19,20,21,49,22],"55":[19,20,21,49,22],"56":[19,20,21,49,22],"99":[19,20,21,49,22],"137":[19,20,21,49,22],"141":[19,20,21,49,22]},"packages/@n8n/agents/src/runtime/memory/observation-log-store.ts":{"21":[19,20,21,49,22],"28":[19,20,21,49,22],"31":[19,20,21,49,22],"34":[19,20,21,49,22],"37":[19,20,21,49,22]},"packages/@n8n/agents/src/runtime/memory/scoped-memory-task-runner.ts":{"73":[19,20,21,22],"84":[19,20,21,22],"88":[19,20,21,22],"89":[19,20,21,22],"96":[19,20,21,22],"97":[19,20,21,22],"103":[19,20,21,22],"107":[19,20,21,22],"123":[19,20,21,22],"124":[19,20,21,22],"135":[19,20,21,22],"189":[19,20,21,22],"194":[19,20,21,22],"216":[19,20,21,22],"218":[19,20,21,22],"225":[19,20,21,22],"231":[19,20,21,22],"242":[19,20,21,22],"253":[19,20,21,22],"266":[19,20,21,22],"274":[19,20,21,22]},"packages/@n8n/agents/src/runtime/memory/strip-orphaned-tool-messages.ts":{"21":[26,19,20,21,119,49,22],"22":[26,19,20,21,119,49,22],"24":[26,19,20,21,119,49,22],"28":[26,19,20,21,119,49,22],"41":[26,19,20,21,119,49,22],"64":[26,19,20,21,119,49,22],"73":[26,19,20,21,119,49,22]},"packages/@n8n/agents/src/runtime/memory/title-generation.ts":{"74":[19,20,21,22],"81":[19,20,21,22],"117":[19,20,21,22],"161":[19,20,21,22],"225":[19,20,21,22],"249":[19,20,21,22],"253":[19,20,21,22],"254":[19,20,21,22],"306":[19,20,21,22]},"packages/@n8n/agents/src/runtime/memory/tool-result-memory.ts":{"17":[26,19,20,21,49,22],"26":[26,19,20,21,49,22],"35":[26,19,20,21,49,22],"38":[26,19,20,21,49,22],"46":[26,19,20,21,49,22],"66":[26,19,20,21,49,22],"69":[26,19,20,21,49,22]},"packages/@n8n/agents/src/runtime/model/lazy-ai.ts":{"5":[26,19,20,21,49,22]},"packages/@n8n/agents/src/runtime/model/message-list.ts":{"48":[26,19,20,48,21,119,49,22],"65":[26,19,20,48,21,119,49,22],"121":[26,19,20,48,21,119,49,22],"157":[26,19,20,48,21,119,49,22],"180":[26,19,20,48,21,119,49,22],"186":[26,19,20,48,21,119,49,22],"187":[26,19,20,48,21,119,49,22],"220":[26,19,20,48,21,119,49,22],"226":[26,19,20,48,21,119,49,22],"234":[26,19,20,48,21,119,49,22],"242":[26,19,20,48,21,119,49,22],"257":[26,19,20,48,21,119,49,22],"291":[26,19,20,48,21,119,49,22],"313":[26,19,20,48,21,119,49,22],"328":[26,19,20,48,21,119,49,22],"339":[26,19,20,48,21,119,49,22],"346":[26,19,20,48,21,119,49,22],"354":[26,19,20,48,21,119,49,22],"357":[26,19,20,48,21,119,49,22],"368":[26,19,20,48,21,119,49,22],"408":[26,19,20,48,21,119,49,22],"424":[26,19,20,48,21,119,49,22],"427":[26,19,20,48,21,119,49,22],"441":[26,19,20,48,21,119,49,22],"442":[26,19,20,48,21,119,49,22],"449":[26,19,20,48,21,119,49,22],"450":[26,19,20,48,21,119,49,22],"457":[26,19,20,48,21,119,49,22],"458":[26,19,20,48,21,119,49,22],"461":[26,19,20,48,21,119,49,22],"463":[26,19,20,48,21,119,49,22],"471":[26,19,20,48,21,119,49,22],"475":[26,19,20,48,21,119,49,22],"476":[26,19,20,48,21,119,49,22],"486":[26,19,20,48,21,119,49,22]},"packages/@n8n/agents/src/runtime/model/messages.ts":{"35":[26,19,20,21,49,22],"39":[26,19,20,21,49,22],"43":[26,19,20,21,49,22],"47":[26,19,20,21,49,22],"51":[26,19,20,21,49,22],"55":[26,19,20,21,49,22],"63":[26,19,20,21,49,22],"69":[26,19,20,21,49,22],"98":[26,19,20,21,49,22],"102":[26,19,20,21,49,22],"106":[26,19,20,21,49,22],"110":[26,19,20,21,49,22],"114":[26,19,20,21,49,22],"119":[26,19,20,21,49,22],"121":[26,19,20,21,49,22],"126":[26,19,20,21,49,22],"129":[26,19,20,21,49,22],"135":[26,19,20,21,49,22],"141":[26,19,20,21,49,22],"149":[26,19,20,21,49,22],"164":[26,19,20,21,49,22],"186":[26,19,20,21,49,22],"197":[26,19,20,21,49,22],"203":[26,19,20,21,49,22],"212":[26,19,20,21,49,22],"270":[26,19,20,21,49,22],"306":[26,19,20,21,49,22],"318":[26,19,20,21,49,22],"398":[26,19,20,21,49,22],"403":[26,19,20,21,49,22],"412":[26,19,20,21,49,22],"489":[26,19,20,21,49,22],"490":[26,19,20,21,49,22],"505":[26,19,20,21,49,22],"523":[26,19,20,21,49,22],"529":[26,19,20,21,49,22],"571":[26,19,20,21,49,22],"595":[26,19,20,21,49,22]},"packages/@n8n/agents/src/runtime/model/model-factory.ts":{"35":[26,19,20,21,49,22],"51":[26,19,20,21,49,22],"53":[26,19,20,21,49,22],"60":[26,19,20,21,49,22],"93":[26,19,20,21,49,22],"135":[26,19,20,21,49,22],"151":[26,19,20,21,49,22],"177":[26,19,20,21,49,22],"179":[26,19,20,21,49,22],"191":[26,19,20,21,49,22],"218":[26,19,20,21,49,22],"223":[26,19,20,21,49,22],"244":[26,19,20,21,49,22],"250":[26,19,20,21,49,22],"262":[26,19,20,21,49,22],"290":[26,19,20,21,49,22],"297":[26,19,20,21,49,22],"303":[26,19,20,21,49,22],"321":[26,19,20,21,49,22],"336":[26,19,20,21,49,22],"350":[26,19,20,21,49,22],"356":[26,19,20,21,49,22],"362":[26,19,20,21,49,22],"368":[26,19,20,21,49,22],"374":[26,19,20,21,49,22],"380":[26,19,20,21,49,22],"386":[26,19,20,21,49,22],"394":[26,19,20,21,49,22],"401":[26,19,20,21,49,22],"413":[26,19,20,21,49,22],"424":[26,19,20,21,49,22],"486":[26,19,20,21,49,22],"506":[26,19,20,21,49,22],"550":[26,19,20,21,49,22],"585":[26,19,20,21,49,22]},"packages/@n8n/agents/src/runtime/model/model-token-counter.ts":{"6":[26,19,20,21,49,22],"7":[26,19,20,21,49,22],"19":[26,19,20,21,49,22]},"packages/@n8n/agents/src/runtime/model/prompt-cache.ts":{"14":[26,19,20,21,49,22],"17":[26,19,20,21,49,22],"30":[26,19,20,21,49,22],"40":[26,19,20,21,49,22],"50":[26,19,20,21,49,22],"59":[26,19,20,21,49,22],"72":[26,19,20,21,49,22],"86":[26,19,20,21,49,22],"93":[26,19,20,21,49,22],"105":[26,19,20,21,49,22],"120":[26,19,20,21,49,22],"145":[26,19,20,21,49,22],"162":[26,19,20,21,49,22],"175":[26,19,20,21,49,22],"215":[26,19,20,21,49,22]},"packages/@n8n/agents/src/runtime/model/provider-quirks.ts":{"35":[26,19,20,21,49,22],"70":[26,19,20,21,49,22],"77":[26,19,20,21,49,22],"82":[26,19,20,21,49,22],"138":[26,19,20,21,49,22],"158":[26,19,20,21,49,22],"171":[26,19,20,21,49,22],"181":[26,19,20,21,49,22],"198":[26,19,20,21,49,22],"207":[26,19,20,21,49,22]},"packages/@n8n/agents/src/runtime/model/raw-error.ts":{"36":[26,19,20,21,49,22],"44":[26,19,20,21,49,22],"55":[26,19,20,21,49,22],"63":[26,19,20,21,49,22]},"packages/@n8n/agents/src/runtime/model/raw-usage.ts":{"32":[19,20,21,118,119,49,22],"43":[19,20,21,118,119,49,22],"46":[19,20,21,118,119,49,22],"76":[19,20,21,118,119,49,22],"77":[19,20,21,118,119,49,22],"85":[19,20,21,118,119,49,22]},"packages/@n8n/agents/src/runtime/skills/active-skills.ts":{"44":[26,19,20,48,21,49,22],"50":[26,19,20,48,21,49,22],"67":[26,19,20,48,21,49,22],"69":[26,19,20,48,21,49,22],"79":[26,19,20,48,21,49,22],"83":[26,19,20,48,21,49,22],"87":[26,19,20,48,21,49,22],"108":[26,19,20,48,21,49,22],"110":[26,19,20,48,21,49,22],"132":[26,19,20,48,21,49,22],"140":[26,19,20,48,21,49,22],"144":[26,19,20,48,21,49,22],"179":[26,19,20,48,21,49,22],"198":[26,19,20,48,21,49,22],"208":[26,19,20,48,21,49,22],"226":[26,19,20,48,21,49,22],"240":[26,19,20,48,21,49,22],"242":[26,19,20,48,21,49,22],"246":[26,19,20,48,21,49,22],"270":[26,19,20,48,21,49,22],"286":[26,19,20,48,21,49,22],"292":[26,19,20,48,21,49,22],"293":[26,19,20,48,21,49,22],"303":[26,19,20,48,21,49,22],"304":[26,19,20,48,21,49,22]},"packages/@n8n/agents/src/runtime/skills/skill-dependency-tools.ts":{"9":[26,19,20,21,49,22],"12":[26,19,20,21,49,22],"14":[26,19,20,21,49,22],"20":[26,19,20,21,49,22]},"packages/@n8n/agents/src/runtime/state/background-task-tracker.ts":{"1":[26,19,20,21,49,22],"4":[26,19,20,21,49,22],"8":[26,19,20,21,49,22],"10":[26,19,20,21,49,22],"16":[26,19,20,21,49,22]},"packages/@n8n/agents/src/runtime/state/event-bus.ts":{"1":[26,19,20,21,49,22],"18":[26,19,20,21,49,22],"29":[26,19,20,21,49,22],"31":[26,19,20,21,49,22],"34":[26,19,20,21,49,22],"38":[26,19,20,21,49,22],"42":[26,19,20,21,49,22],"46":[26,19,20,21,49,22],"70":[26,19,20,21,49,22],"79":[26,19,20,21,49,22],"88":[26,19,20,21,49,22],"92":[26,19,20,21,49,22],"100":[26,19,20,21,49,22],"107":[26,19,20,21,49,22],"108":[26,19,20,21,49,22],"124":[26,19,20,21,49,22],"133":[26,19,20,21,49,22],"135":[26,19,20,21,49,22],"141":[26,19,20,21,49,22],"145":[26,19,20,21,49,22],"153":[26,19,20,21,49,22]},"packages/@n8n/agents/src/runtime/state/run-state.ts":{"11":[26,19,20,48,21,49,22],"25":[26,19,20,48,21,49,22],"28":[26,19,20,48,21,49,22],"32":[26,19,20,48,21,49,22],"36":[26,19,20,48,21,49,22],"43":[26,19,20,48,21,49,22],"56":[26,19,20,48,21,49,22],"61":[26,19,20,48,21,49,22],"71":[26,19,20,48,21,49,22],"81":[26,19,20,48,21,49,22],"89":[26,19,20,48,21,49,22],"98":[26,19,20,48,21,49,22],"112":[26,19,20,48,21,49,22],"117":[26,19,20,48,21,49,22],"123":[26,19,20,48,21,49,22]},"packages/@n8n/agents/src/runtime/streaming/stream-session.ts":{"45":[26,19,20,21,118,119,49,22],"52":[26,19,20,21,118,119,49,22],"61":[26,19,20,21,118,119,49,22],"71":[26,19,20,21,118,119,49,22],"76":[26,19,20,21,118,119,49,22],"81":[26,19,20,21,118,119,49,22],"94":[26,19,20,21,118,119,49,22],"95":[26,19,20,21,118,119,49,22],"120":[26,19,20,21,118,119,49,22]},"packages/@n8n/agents/src/runtime/streaming/stream-stall.ts":{"49":[26,19,20,21,49,22],"59":[26,19,20,21,49,22],"83":[26,19,20,21,49,22],"95":[26,19,20,21,49,22],"106":[26,19,20,21,49,22],"107":[26,19,20,21,49,22],"120":[26,19,20,21,49,22],"130":[26,19,20,21,49,22],"131":[26,19,20,21,49,22],"132":[26,19,20,21,49,22]},"packages/@n8n/agents/src/runtime/streaming/stream-writer-guard.ts":{"18":[26,19,20,21,118,119,49,22],"19":[26,19,20,21,118,119,49,22],"26":[26,19,20,21,118,119,49,22],"30":[26,19,20,21,118,119,49,22],"35":[26,19,20,21,118,119,49,22],"46":[26,19,20,21,118,119,49,22],"63":[26,19,20,21,118,119,49,22]},"packages/@n8n/agents/src/runtime/streaming/stream.ts":{"12":[26,19,20,21,119,49,22],"21":[26,19,20,21,119,49,22],"74":[26,19,20,21,119,49,22]},"packages/@n8n/agents/src/runtime/telemetry/runtime-telemetry.ts":{"38":[26,19,20,21,49,22],"46":[26,19,20,21,49,22],"54":[26,19,20,21,49,22],"62":[26,19,20,21,49,22],"73":[26,19,20,21,49,22],"85":[26,19,20,21,49,22],"96":[26,19,20,21,49,22],"103":[26,19,20,21,49,22],"107":[26,19,20,21,49,22],"108":[26,19,20,21,49,22],"118":[26,19,20,21,49,22],"179":[26,19,20,21,49,22],"193":[26,19,20,21,49,22],"226":[26,19,20,21,49,22],"240":[26,19,20,21,49,22],"268":[26,19,20,21,49,22],"276":[26,19,20,21,49,22],"287":[26,19,20,21,49,22],"292":[26,19,20,21,49,22],"300":[26,19,20,21,49,22],"326":[26,19,20,21,49,22],"340":[26,19,20,21,49,22],"371":[26,19,20,21,49,22],"394":[26,19,20,21,49,22],"431":[26,19,20,21,49,22],"436":[26,19,20,21,49,22],"440":[26,19,20,21,49,22]},"packages/@n8n/agents/src/runtime/telemetry/telemetry-options.ts":{"11":[26,19,20,21,49,22]},"packages/@n8n/agents/src/runtime/tools/deferred-tool-manager.ts":{"42":[19,20,21,49,22],"47":[19,20,21,49,22],"52":[19,20,21,49,22],"100":[19,20,21,49,22],"122":[19,20,21,49,22],"126":[19,20,21,49,22],"130":[19,20,21,49,22],"134":[19,20,21,49,22],"140":[19,20,21,49,22],"144":[19,20,21,49,22],"146":[19,20,21,49,22],"147":[19,20,21,49,22],"150":[19,20,21,49,22],"165":[19,20,21,49,22],"172":[19,20,21,49,22],"179":[19,20,21,49,22],"186":[19,20,21,49,22],"193":[19,20,21,49,22],"197":[19,20,21,49,22],"201":[19,20,21,49,22],"206":[19,20,21,49,22],"210":[19,20,21,49,22],"214":[19,20,21,49,22],"253":[19,20,21,49,22],"261":[19,20,21,49,22],"272":[19,20,21,49,22]},"packages/@n8n/agents/src/runtime/tools/tool-adapter.ts":{"38":[26,19,20,48,21,49,22],"51":[26,19,20,48,21,49,22],"73":[26,19,20,48,21,49,22],"108":[26,19,20,48,21,49,22],"145":[26,19,20,48,21,49,22],"151":[26,19,20,48,21,49,22],"155":[26,19,20,48,21,49,22],"176":[26,19,20,48,21,49,22],"179":[26,19,20,48,21,49,22],"197":[26,19,20,48,21,49,22],"203":[26,19,20,48,21,49,22]},"packages/@n8n/agents/src/runtime/tools/tool-call-executor.ts":{"52":[26,19,20,48,21,49,22],"57":[26,19,20,48,21,49,22],"61":[26,19,20,48,21,49,22],"65":[26,19,20,48,21,49,22],"74":[26,19,20,48,21,49,22],"82":[26,19,20,48,21,49,22],"129":[26,19,20,48,21,49,22],"134":[26,19,20,48,21,49,22],"139":[26,19,20,48,21,49,22],"140":[26,19,20,48,21,49,22],"166":[26,19,20,48,21,49,22],"191":[26,19,20,48,21,49,22],"197":[26,19,20,48,21,49,22],"217":[26,19,20,48,21,49,22],"230":[26,19,20,48,21,49,22],"268":[26,19,20,48,21,49,22],"281":[26,19,20,48,21,49,22],"298":[26,19,20,48,21,49,22],"317":[26,19,20,48,21,49,22],"332":[26,19,20,48,21,49,22],"348":[26,19,20,48,21,49,22],"374":[26,19,20,48,21,49,22],"404":[26,19,20,48,21,49,22],"430":[26,19,20,48,21,49,22],"454":[26,19,20,48,21,49,22],"487":[26,19,20,48,21,49,22],"508":[26,19,20,48,21,49,22],"517":[26,19,20,48,21,49,22],"548":[26,19,20,48,21,49,22]},"packages/@n8n/agents/src/runtime/tools/tool-call-runner.ts":{"48":[26,19,20,48,21,49,22],"52":[26,19,20,48,21,49,22],"59":[26,19,20,48,21,49,22],"72":[26,19,20,48,21,49,22],"74":[26,19,20,48,21,49,22],"78":[26,19,20,48,21,49,22],"82":[26,19,20,48,21,49,22],"96":[26,19,20,48,21,49,22],"159":[26,19,20,48,21,49,22],"173":[26,19,20,48,21,49,22],"200":[26,19,20,48,21,49,22],"217":[26,19,20,48,21,49,22],"221":[26,19,20,48,21,49,22],"238":[26,19,20,48,21,49,22],"251":[26,19,20,48,21,49,22],"268":[26,19,20,48,21,49,22],"293":[26,19,20,48,21,49,22],"299":[26,19,20,48,21,49,22],"301":[26,19,20,48,21,49,22],"307":[26,19,20,48,21,49,22],"324":[26,19,20,48,21,49,22],"348":[26,19,20,48,21,49,22],"364":[26,19,20,48,21,49,22],"389":[26,19,20,48,21,49,22],"391":[26,19,20,48,21,49,22],"396":[26,19,20,48,21,49,22],"411":[26,19,20,48,21,49,22],"442":[26,19,20,48,21,49,22],"510":[26,19,20,48,21,49,22],"534":[26,19,20,48,21,49,22],"542":[26,19,20,48,21,49,22]},"packages/@n8n/agents/src/runtime/tools/tool-result-guard.ts":{"59":[26,19,20,49,22],"100":[26,19,20,49,22],"106":[26,19,20,49,22],"129":[26,19,20,49,22],"138":[26,19,20,49,22],"145":[26,19,20,49,22],"157":[26,19,20,49,22],"159":[26,19,20,49,22],"167":[26,19,20,49,22],"195":[26,19,20,49,22],"202":[26,19,20,49,22],"231":[26,19,20,49,22]},"packages/@n8n/agents/src/sdk/abort.ts":{"6":[26,19,20,21,49,22],"12":[26,19,20,21,49,22],"20":[26,19,20,21,49,22],"35":[26,19,20,21,49,22],"39":[26,19,20,21,49,22],"46":[26,19,20,21,49,22],"47":[26,19,20,21,49,22]},"packages/@n8n/agents/src/sdk/agent.ts":{"106":[26,19,20,48,21,49,22],"247":[26,19,20,48,21,49,22],"251":[26,19,20,48,21,49,22],"255":[26,19,20,48,21,49,22],"271":[26,19,20,48,21,49,22],"284":[26,19,20,48,21,49,22],"290":[26,19,20,48,21,49,22],"297":[26,19,20,48,21,49,22],"303":[26,19,20,48,21,49,22],"305":[26,19,20,48,21,49,22],"314":[26,19,20,48,21,49,22],"322":[26,19,20,48,21,49,22],"340":[26,19,20,48,21,49,22],"349":[26,19,20,48,21,49,22],"360":[26,19,20,48,21,49,22],"366":[26,19,20,48,21,49,22],"371":[26,19,20,48,21,49,22],"397":[26,19,20,48,21,49,22],"403":[26,19,20,48,21,49,22],"409":[26,19,20,48,21,49,22],"416":[26,19,20,48,21,49,22],"422":[26,19,20,48,21,49,22],"428":[26,19,20,48,21,49,22],"450":[26,19,20,48,21,49,22],"480":[26,19,20,48,21,49,22],"502":[26,19,20,48,21,49,22],"517":[26,19,20,48,21,49,22],"537":[26,19,20,48,21,49,22],"543":[26,19,20,48,21,49,22],"556":[26,19,20,48,21,49,22],"567":[26,19,20,48,21,49,22],"579":[26,19,20,48,21,49,22],"602":[26,19,20,48,21,49,22],"617":[26,19,20,48,21,49,22],"632":[26,19,20,48,21,49,22],"634":[26,19,20,48,21,49,22],"657":[26,19,20,48,21,49,22],"663":[26,19,20,48,21,49,22],"671":[26,19,20,48,21,49,22],"688":[26,19,20,48,21,49,22],"704":[26,19,20,48,21,49,22],"731":[26,19,20,48,21,49,22],"746":[26,19,20,48,21,49,22],"763":[26,19,20,48,21,49,22],"769":[26,19,20,48,21,49,22],"774":[26,19,20,48,21,49,22],"789":[26,19,20,48,21,49,22],"816":[26,19,20,48,21,49,22],"840":[26,19,20,48,21,49,22],"860":[26,19,20,48,21,49,22],"876":[26,19,20,48,21,49,22],"888":[26,19,20,48,21,49,22],"898":[26,19,20,48,21,49,22],"915":[26,19,20,48,21,49,22],"920":[26,19,20,48,21,49,22],"925":[26,19,20,48,21,49,22],"933":[26,19,20,48,21,49,22],"946":[26,19,20,48,21,49,22],"952":[26,19,20,48,21,49,22],"953":[26,19,20,48,21,49,22],"966":[26,19,20,48,21,49,22],"980":[26,19,20,48,21,49,22],"990":[26,19,20,48,21,49,22],"996":[26,19,20,48,21,49,22],"1002":[26,19,20,48,21,49,22],"1024":[26,19,20,48,21,49,22],"1025":[26,19,20,48,21,49,22],"1026":[26,19,20,48,21,49,22],"1036":[26,19,20,48,21,49,22],"1048":[26,19,20,48,21,49,22],"1073":[26,19,20,48,21,49,22],"1074":[26,19,20,48,21,49,22],"1086":[26,19,20,48,21,49,22],"1178":[26,19,20,48,21,49,22],"1189":[26,19,20,48,21,49,22],"1204":[26,19,20,48,21,49,22],"1209":[26,19,20,48,21,49,22],"1211":[26,19,20,48,21,49,22],"1225":[26,19,20,48,21,49,22],"1237":[26,19,20,48,21,49,22],"1264":[26,19,20,48,21,49,22],"1280":[26,19,20,48,21,49,22],"1408":[26,19,20,48,21,49,22],"1417":[26,19,20,48,21,49,22],"1422":[26,19,20,48,21,49,22],"1428":[26,19,20,48,21,49,22],"1439":[26,19,20,48,21,49,22],"1442":[26,19,20,48,21,49,22],"1447":[26,19,20,48,21,49,22],"1462":[26,19,20,48,21,49,22],"1468":[26,19,20,48,21,49,22],"1477":[26,19,20,48,21,49,22],"1481":[26,19,20,48,21,49,22],"1486":[26,19,20,48,21,49,22],"1489":[26,19,20,48,21,49,22]},"packages/@n8n/agents/src/sdk/cancellation.ts":{"18":[26,19,20,49,22],"22":[26,19,20,49,22]},"packages/@n8n/agents/src/sdk/memory.ts":{"13":[19,20,21,49,22],"37":[19,20,21,49,22],"60":[19,20,21,49,22],"83":[19,20,21,49,22],"122":[19,20,21,49,22],"177":[19,20,21,49,22],"187":[19,20,21,49,22],"205":[19,20,21,49,22],"216":[19,20,21,49,22],"224":[19,20,21,49,22]},"packages/@n8n/agents/src/sdk/message.ts":{"3":[26,19,20,21,49,22],"19":[26,19,20,21,49,22],"23":[26,19,20,21,49,22]},"packages/@n8n/agents/src/sdk/telemetry.ts":{"29":[26,19,20,21,49,22],"31":[26,19,20,21,49,22],"54":[26,19,20,21,49,22],"66":[26,19,20,21,49,22],"70":[26,19,20,21,49,22],"74":[26,19,20,21,49,22],"78":[26,19,20,21,49,22],"84":[26,19,20,21,49,22],"95":[26,19,20,21,49,22],"103":[26,19,20,21,49,22],"110":[26,19,20,21,49,22],"123":[26,19,20,21,49,22],"132":[26,19,20,21,49,22],"140":[26,19,20,21,49,22],"149":[26,19,20,21,49,22],"198":[26,19,20,21,49,22],"233":[26,19,20,21,49,22],"239":[26,19,20,21,49,22],"247":[26,19,20,21,49,22],"252":[26,19,20,21,49,22],"258":[26,19,20,21,49,22],"264":[26,19,20,21,49,22],"270":[26,19,20,21,49,22],"276":[26,19,20,21,49,22],"282":[26,19,20,21,49,22],"292":[26,19,20,21,49,22],"298":[26,19,20,21,49,22],"309":[26,19,20,21,49,22],"321":[26,19,20,21,49,22],"327":[26,19,20,21,49,22],"343":[26,19,20,21,49,22],"352":[26,19,20,21,49,22],"378":[26,19,20,21,49,22],"385":[26,19,20,21,49,22]},"packages/@n8n/agents/src/sdk/tool.ts":{"47":[26,19,20,21,49,22],"61":[26,19,20,21,49,22],"67":[26,19,20,21,49,22],"78":[26,19,20,21,49,22],"91":[26,19,20,21,49,22],"98":[26,19,20,21,49,22],"112":[26,19,20,21,49,22],"175":[26,19,20,21,49,22],"256":[26,19,20,21,49,22],"261":[26,19,20,21,49,22],"275":[26,19,20,21,49,22],"281":[26,19,20,21,49,22],"288":[26,19,20,21,49,22],"295":[26,19,20,21,49,22],"302":[26,19,20,21,49,22],"312":[26,19,20,21,49,22],"322":[26,19,20,21,49,22],"334":[26,19,20,21,49,22],"340":[26,19,20,21,49,22],"346":[26,19,20,21,49,22],"355":[26,19,20,21,49,22],"361":[26,19,20,21,49,22],"367":[26,19,20,21,49,22],"378":[26,19,20,21,49,22],"389":[26,19,20,21,49,22],"459":[26,19,20,21,49,22],"496":[26,19,20,21,49,22]},"packages/@n8n/agents/src/skills/prompt.ts":{"7":[26,19,20,21,49,22],"11":[26,19,20,21,49,22],"16":[26,19,20,21,49,22],"57":[26,19,20,21,49,22],"69":[26,19,20,21,49,22],"73":[26,19,20,21,49,22]},"packages/@n8n/agents/src/skills/registry.ts":{"24":[26,19,20,21,49,22],"39":[26,19,20,21,49,22],"41":[26,19,20,21,49,22],"45":[26,19,20,21,49,22],"52":[26,19,20,21,49,22],"69":[26,19,20,21,49,22],"86":[26,19,20,21,49,22],"89":[26,19,20,21,49,22],"99":[26,19,20,21,49,22],"103":[26,19,20,21,49,22],"110":[26,19,20,21,49,22],"116":[26,19,20,21,49,22],"120":[26,19,20,21,49,22],"148":[26,19,20,21,49,22],"156":[26,19,20,21,49,22],"158":[26,19,20,21,49,22],"161":[26,19,20,21,49,22],"170":[26,19,20,21,49,22],"178":[26,19,20,21,49,22],"185":[26,19,20,21,49,22],"194":[26,19,20,21,49,22],"197":[26,19,20,21,49,22],"227":[26,19,20,21,49,22],"232":[26,19,20,21,49,22],"237":[26,19,20,21,49,22],"278":[26,19,20,21,49,22],"279":[26,19,20,21,49,22],"293":[26,19,20,21,49,22],"294":[26,19,20,21,49,22],"311":[26,19,20,21,49,22],"317":[26,19,20,21,49,22],"322":[26,19,20,21,49,22],"326":[26,19,20,21,49,22],"335":[26,19,20,21,49,22],"341":[26,19,20,21,49,22],"375":[26,19,20,21,49,22],"404":[26,19,20,21,49,22],"428":[26,19,20,21,49,22],"457":[26,19,20,21,49,22],"463":[26,19,20,21,49,22],"481":[26,19,20,21,49,22],"498":[26,19,20,21,49,22],"509":[26,19,20,21,49,22],"520":[26,19,20,21,49,22],"525":[26,19,20,21,49,22],"528":[26,19,20,21,49,22],"531":[26,19,20,21,49,22],"540":[26,19,20,21,49,22],"546":[26,19,20,21,49,22],"563":[26,19,20,21,49,22],"581":[26,19,20,21,49,22],"585":[26,19,20,21,49,22],"590":[26,19,20,21,49,22],"594":[26,19,20,21,49,22],"598":[26,19,20,21,49,22],"602":[26,19,20,21,49,22],"612":[26,19,20,21,49,22],"619":[26,19,20,21,49,22],"626":[26,19,20,21,49,22],"633":[26,19,20,21,49,22],"638":[26,19,20,21,49,22],"639":[26,19,20,21,49,22],"640":[26,19,20,21,49,22],"646":[26,19,20,21,49,22],"652":[26,19,20,21,49,22],"656":[26,19,20,21,49,22]},"packages/@n8n/agents/src/skills/tools.ts":{"52":[19,20,48,21,49,22],"66":[19,20,48,21,49,22],"104":[19,20,48,21,49,22],"108":[19,20,48,21,49,22],"117":[19,20,48,21,49,22],"131":[19,20,48,21,49,22],"137":[19,20,48,21,49,22],"162":[19,20,48,21,49,22],"231":[19,20,48,21,49,22],"245":[19,20,48,21,49,22],"260":[19,20,48,21,49,22],"267":[19,20,48,21,49,22],"268":[19,20,48,21,49,22],"277":[19,20,48,21,49,22],"293":[19,20,48,21,49,22],"297":[19,20,48,21,49,22],"301":[19,20,48,21,49,22],"311":[19,20,48,21,49,22],"318":[19,20,48,21,49,22],"325":[19,20,48,21,49,22],"329":[19,20,48,21,49,22],"334":[19,20,48,21,49,22],"339":[19,20,48,21,49,22],"345":[19,20,48,21,49,22],"360":[19,20,48,21,49,22],"365":[19,20,48,21,49,22],"371":[19,20,48,21,49,22],"382":[19,20,48,21,49,22],"386":[19,20,48,21,49,22]},"packages/@n8n/agents/src/skills/validator.ts":{"44":[19,20,21,49,22],"57":[19,20,21,49,22],"87":[19,20,21,49,22],"124":[19,20,21,49,22],"144":[19,20,21,49,22],"192":[19,20,21,49,22],"209":[19,20,21,49,22],"218":[19,20,21,49,22],"238":[19,20,21,49,22],"259":[19,20,21,49,22],"260":[19,20,21,49,22],"273":[19,20,21,49,22],"292":[19,20,21,49,22],"311":[19,20,21,49,22],"362":[19,20,21,49,22],"386":[19,20,21,49,22],"407":[19,20,21,49,22],"423":[19,20,21,49,22],"465":[19,20,21,49,22],"485":[19,20,21,49,22],"489":[19,20,21,49,22]},"packages/@n8n/agents/src/types/sdk/agent.ts":{"40":[19,20,21,49,22],"41":[19,20,21,49,22]},"packages/@n8n/agents/src/utils/model.ts":{"3":[26,19,20,21,49,22],"22":[26,19,20,21,49,22]},"packages/@n8n/agents/src/utils/parse.ts":{"27":[26,19,20,48,49,22],"31":[26,19,20,48,49,22],"40":[26,19,20,48,49,22],"48":[26,19,20,48,49,22],"51":[26,19,20,48,49,22],"60":[26,19,20,48,49,22],"97":[26,19,20,48,49,22],"105":[26,19,20,48,49,22]},"packages/@n8n/agents/src/workspace/filesystem/base-filesystem.ts":{"39":[19,20,21,49,22],"44":[19,20,21,49,22],"64":[19,20,21,49,22],"83":[19,20,21,49,22],"87":[19,20,21,49,22],"96":[19,20,21,49,22],"114":[19,20,21,49,22],"139":[19,20,21,49,22]},"packages/@n8n/agents/src/workspace/filesystem/n8n-sandbox-filesystem.ts":{"22":[19,20,48,21,49,22],"37":[19,20,48,21,49,22],"45":[19,20,48,21,49,22],"53":[19,20,48,21,49,22],"61":[19,20,48,21,49,22],"67":[19,20,48,21,49,22],"68":[19,20,48,21,49,22],"77":[19,20,48,21,49,22],"78":[19,20,48,21,49,22],"89":[19,20,48,21,49,22],"90":[19,20,48,21,49,22],"95":[19,20,48,21,49,22],"96":[19,20,48,21,49,22],"104":[19,20,48,21,49,22],"105":[19,20,48,21,49,22],"115":[19,20,48,21,49,22],"116":[19,20,48,21,49,22],"125":[19,20,48,21,49,22],"126":[19,20,48,21,49,22],"131":[19,20,48,21,49,22],"135":[19,20,48,21,49,22],"136":[19,20,48,21,49,22],"138":[19,20,48,21,49,22],"146":[19,20,48,21,49,22],"158":[19,20,48,21,49,22],"159":[19,20,48,21,49,22]},"packages/@n8n/agents/src/workspace/lifecycle.ts":{"14":[19,20,21,49,22]},"packages/@n8n/agents/src/workspace/sandbox/base-sandbox.ts":{"28":[26,19,20,21,49,22],"46":[26,19,20,21,49,22],"50":[26,19,20,21,49,22],"70":[26,19,20,21,49,22],"74":[26,19,20,21,49,22],"86":[26,19,20,21,49,22],"94":[26,19,20,21,49,22],"95":[26,19,20,21,49,22],"118":[26,19,20,21,49,22],"123":[26,19,20,21,49,22],"128":[26,19,20,21,49,22],"132":[26,19,20,21,49,22],"135":[26,19,20,21,49,22],"142":[26,19,20,21,49,22],"153":[26,19,20,21,49,22],"162":[26,19,20,21,49,22],"166":[26,19,20,21,49,22],"182":[26,19,20,21,49,22],"198":[26,19,20,21,49,22]},"packages/@n8n/agents/src/workspace/sandbox/create-workspace.ts":{"13":[26,19,20,21,49,22],"20":[26,19,20,21,49,22],"79":[26,19,20,21,49,22]},"packages/@n8n/agents/src/workspace/sandbox/index.ts":{"22":[26,19,20,48,21,49,22]},"packages/@n8n/agents/src/workspace/sandbox/n8n-sandbox-sandbox.ts":{"43":[19,20,117,21,49,22],"53":[19,20,117,21,49,22],"57":[19,20,117,21,49,22],"63":[19,20,117,21,49,22],"73":[19,20,117,21,49,22],"78":[19,20,117,21,49,22],"95":[19,20,117,21,49,22],"103":[19,20,117,21,49,22],"132":[19,20,117,21,49,22],"136":[19,20,117,21,49,22],"146":[19,20,117,21,49,22],"152":[19,20,117,21,49,22],"157":[19,20,117,21,49,22],"163":[19,20,117,21,49,22],"168":[19,20,117,21,49,22]},"packages/@n8n/agents/src/workspace/sandbox/run-in-sandbox.ts":{"39":[19,20,21,49,22],"56":[19,20,21,49,22]},"packages/@n8n/agents/src/workspace/sandbox/shell-command.ts":{"13":[19,20,21,49,22],"18":[19,20,21,49,22],"20":[19,20,21,49,22]},"packages/@n8n/agents/src/workspace/sandbox/workspace-root.ts":{"10":[19,20,21,49,22],"19":[19,20,21,49,22],"33":[19,20,21,49,22],"44":[19,20,21,49,22],"51":[19,20,21,49,22],"56":[19,20,21,49,22]},"packages/@n8n/agents/src/workspace/scoped-workspace.ts":{"22":[19,20,48,21,49,22],"27":[19,20,48,21,49,22],"51":[19,20,48,21,49,22],"57":[19,20,48,21,49,22],"61":[19,20,48,21,49,22],"65":[19,20,48,21,49,22],"69":[19,20,48,21,49,22],"73":[19,20,48,21,49,22],"77":[19,20,48,21,49,22],"81":[19,20,48,21,49,22],"85":[19,20,48,21,49,22],"99":[19,20,48,21,49,22],"100":[19,20,48,21,49,22],"105":[19,20,48,21,49,22],"110":[19,20,48,21,49,22],"114":[19,20,48,21,49,22],"118":[19,20,48,21,49,22],"122":[19,20,48,21,49,22],"126":[19,20,48,21,49,22],"131":[19,20,48,21,49,22],"136":[19,20,48,21,49,22],"140":[19,20,48,21,49,22],"144":[19,20,48,21,49,22],"148":[19,20,48,21,49,22],"152":[19,20,48,21,49,22],"160":[19,20,48,21,49,22],"168":[19,20,48,21,49,22],"184":[19,20,48,21,49,22],"188":[19,20,48,21,49,22],"192":[19,20,48,21,49,22],"196":[19,20,48,21,49,22],"200":[19,20,48,21,49,22],"204":[19,20,48,21,49,22],"208":[19,20,48,21,49,22],"214":[19,20,48,21,49,22],"225":[19,20,48,21,49,22],"229":[19,20,48,21,49,22],"238":[19,20,48,21,49,22]},"packages/@n8n/agents/src/workspace/tools/append-file.ts":{"7":[19,20,21,49,22],"21":[19,20,21,49,22]},"packages/@n8n/agents/src/workspace/tools/copy-file.ts":{"7":[19,20,21,49,22],"25":[19,20,21,49,22]},"packages/@n8n/agents/src/workspace/tools/delete-file.ts":{"7":[19,20,21,49,22],"25":[19,20,21,49,22]},"packages/@n8n/agents/src/workspace/tools/execute-command.ts":{"7":[19,20,21,49,22],"26":[19,20,21,49,22]},"packages/@n8n/agents/src/workspace/tools/file-stat.ts":{"7":[19,20,21,49,22],"25":[19,20,21,49,22]},"packages/@n8n/agents/src/workspace/tools/list-files.ts":{"7":[19,20,21,49,22],"29":[19,20,21,49,22]},"packages/@n8n/agents/src/workspace/tools/mkdir.ts":{"7":[19,20,21,49,22],"21":[19,20,21,49,22]},"packages/@n8n/agents/src/workspace/tools/move-file.ts":{"7":[19,20,21,49,22],"25":[19,20,21,49,22]},"packages/@n8n/agents/src/workspace/tools/read-file.ts":{"7":[19,20,21,49,22],"25":[19,20,21,49,22]},"packages/@n8n/agents/src/workspace/tools/read-tool-result.ts":{"114":[19,20,21,49,22],"124":[19,20,21,49,22],"129":[19,20,21,49,22],"159":[19,20,21,49,22],"194":[19,20,21,49,22],"207":[19,20,21,49,22],"235":[19,20,21,49,22],"256":[19,20,21,49,22],"293":[19,20,21,49,22],"314":[19,20,21,49,22],"343":[19,20,21,49,22],"372":[19,20,21,49,22],"379":[19,20,21,49,22],"383":[19,20,21,49,22],"393":[19,20,21,49,22],"397":[19,20,21,49,22]},"packages/@n8n/agents/src/workspace/tools/rmdir.ts":{"7":[19,20,21,49,22],"25":[19,20,21,49,22]},"packages/@n8n/agents/src/workspace/tools/str-replace-file.ts":{"45":[19,20,21,49,22],"52":[19,20,21,49,22],"58":[19,20,21,49,22],"65":[19,20,21,49,22]},"packages/@n8n/agents/src/workspace/tools/workspace-tools.ts":{"31":[19,20,21,49,22]},"packages/@n8n/agents/src/workspace/tools/write-file.ts":{"7":[19,20,21,49,22],"29":[19,20,21,49,22]},"packages/@n8n/agents/src/workspace/workspace.ts":{"24":[19,20,21,49,22],"31":[19,20,21,49,22],"35":[19,20,21,49,22],"39":[19,20,21,49,22],"43":[19,20,21,49,22],"59":[19,20,21,49,22],"80":[19,20,21,49,22],"93":[19,20,21,49,22],"97":[19,20,21,49,22],"126":[19,20,21,49,22]},"packages/@n8n/ai-utilities/src/node-catalog/index.ts":{"14":[19,20,21,49,22,50,207,208],"34":[19,20,21,49,22,50,207,208],"84":[19,20,21,49,22,50,207,208]},"packages/@n8n/ai-utilities/src/node-catalog/suggested.ts":{"25":[19,20,21,49,22,50,207,208],"34":[19,20,21,49,22,50,207,208],"59":[19,20,21,49,22,50,207,208],"93":[19,20,21,49,22,50,207,208]},"packages/@n8n/db/src/repositories/ai-builder-temporary-workflow.repository.ts":{"9":[19,20,48,21,49,22],"13":[19,20,48,21,49,22],"23":[19,20,48,21,49,22],"27":[19,20,48,21,49,22],"34":[19,20,48,21,49,22]},"packages/@n8n/db/src/repositories/instance-credential-assignment.repository.ts":{"11":[26,107,19,20,21,206,96,49,22],"15":[26,107,19,20,21,206,96,49,22],"29":[26,107,19,20,21,206,96,49,22],"54":[26,107,19,20,21,206,96,49,22],"55":[26,107,19,20,21,206,96,49,22],"64":[26,107,19,20,21,206,96,49,22],"69":[26,107,19,20,21,206,96,49,22],"78":[26,107,19,20,21,206,96,49,22],"84":[26,107,19,20,21,206,96,49,22],"87":[26,107,19,20,21,206,96,49,22],"102":[26,107,19,20,21,206,96,49,22]},"packages/@n8n/db/src/services/db-lock.service.ts":{"14":[19,20,21,206,49,22],"53":[19,20,21,206,49,22],"106":[19,20,21,206,49,22],"129":[19,20,21,206,49,22],"138":[19,20,21,206,49,22],"145":[19,20,21,206,49,22],"179":[19,20,21,206,49,22],"184":[19,20,21,206,49,22],"197":[19,20,21,206,49,22],"205":[19,20,21,206,49,22],"211":[19,20,21,206,49,22],"232":[19,20,21,206,49,22],"253":[19,20,21,206,49,22],"256":[19,20,21,206,49,22],"264":[19,20,21,206,49,22],"287":[19,20,21,206,49,22],"309":[19,20,21,206,49,22],"310":[19,20,21,206,49,22],"329":[19,20,21,206,49,22]},"packages/@n8n/instance-ai/src/agent/apply-agent-thinking.ts":{"11":[19,20,21,49,22],"17":[19,20,21,49,22],"26":[19,20,21,49,22],"28":[19,20,21,49,22],"31":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/agent/computer-use-prompt.ts":{"98":[19,20,21,49,22],"105":[19,20,21,49,22],"110":[19,20,21,49,22],"111":[19,20,21,49,22],"117":[19,20,21,49,22],"120":[19,20,21,49,22],"128":[19,20,21,49,22],"129":[19,20,21,49,22],"132":[19,20,21,49,22],"133":[19,20,21,49,22],"134":[19,20,21,49,22],"135":[19,20,21,49,22],"138":[19,20,21,49,22],"154":[19,20,21,49,22],"164":[19,20,21,49,22],"181":[19,20,21,49,22],"188":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/agent/instance-agent.ts":{"42":[19,20,21,49,22],"48":[19,20,21,49,22],"49":[19,20,21,49,22],"61":[19,20,21,49,22],"82":[19,20,21,49,22],"124":[19,20,21,49,22],"134":[19,20,21,49,22],"142":[19,20,21,49,22],"200":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/agent/mcp-tool-name-validation.ts":{"8":[19,20,21,49,22],"20":[19,20,21,49,22],"29":[19,20,21,49,22],"36":[19,20,21,49,22],"47":[19,20,21,49,22],"55":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/agent/model-config-identity.ts":{"4":[19,20,21,49,22],"8":[19,20,21,49,22],"13":[19,20,21,49,22],"18":[19,20,21,49,22],"23":[19,20,21,49,22],"35":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/agent/runtime-workspace.ts":{"10":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/agent/sanitize-mcp-descriptions.ts":{"71":[19,20,21,49,22],"107":[19,20,21,49,22],"114":[19,20,21,49,22],"116":[19,20,21,49,22],"125":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/agent/sanitize-mcp-schemas.ts":{"55":[19,20,21,49,22],"127":[19,20,21,49,22],"156":[19,20,21,49,22],"165":[19,20,21,49,22],"172":[19,20,21,49,22],"179":[19,20,21,49,22],"269":[19,20,21,49,22],"292":[19,20,21,49,22],"311":[19,20,21,49,22],"329":[19,20,21,49,22],"346":[19,20,21,49,22],"363":[19,20,21,49,22],"382":[19,20,21,49,22],"418":[19,20,21,49,22],"419":[19,20,21,49,22],"422":[19,20,21,49,22],"425":[19,20,21,49,22],"432":[19,20,21,49,22],"446":[19,20,21,49,22],"460":[19,20,21,49,22],"461":[19,20,21,49,22],"466":[19,20,21,49,22],"475":[19,20,21,49,22],"483":[19,20,21,49,22],"497":[19,20,21,49,22],"531":[19,20,21,49,22],"532":[19,20,21,49,22],"556":[19,20,21,49,22],"571":[19,20,21,49,22],"573":[19,20,21,49,22],"592":[19,20,21,49,22],"608":[19,20,21,49,22],"629":[19,20,21,49,22],"633":[19,20,21,49,22],"654":[19,20,21,49,22],"806":[19,20,21,49,22],"827":[19,20,21,49,22],"846":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/agent/shared-prompts.ts":{"22":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/agent/system-prompt.ts":{"33":[19,20,21,49,22],"42":[19,20,21,49,22],"81":[19,20,21,49,22],"130":[19,20,21,49,22],"150":[19,20,21,49,22],"157":[19,20,21,49,22],"171":[19,20,21,49,22],"178":[19,20,21,49,22],"186":[19,20,21,49,22],"190":[19,20,21,49,22],"212":[19,20,21,49,22],"232":[19,20,21,49,22],"244":[19,20,21,49,22],"245":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/domain-access/domain-access-tracker.ts":{"60":[19,20,21,49,22],"74":[19,20,21,49,22],"85":[19,20,21,49,22],"90":[19,20,21,49,22],"95":[19,20,21,49,22],"99":[19,20,21,49,22],"108":[19,20,21,49,22],"113":[19,20,21,49,22],"119":[19,20,21,49,22],"124":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/domain-access/domain-gating.ts":{"69":[19,20,21,49,22],"122":[19,20,21,49,22],"161":[19,20,21,49,22],"203":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/domain-access/index.ts":{"1":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/error-formatting.ts":{"10":[19,20,21,49,22],"21":[19,20,21,49,22],"36":[19,20,21,49,22],"53":[19,20,21,49,22],"54":[19,20,21,49,22],"57":[19,20,21,49,22],"71":[19,20,21,49,22],"82":[19,20,21,49,22],"91":[19,20,21,49,22],"98":[19,20,21,49,22],"102":[19,20,21,49,22],"109":[19,20,21,49,22],"113":[19,20,21,49,22],"138":[19,20,21,49,22],"152":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/errors/index.ts":{"3":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/errors/workflow-snapshot-changed.error.ts":{"8":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/index.ts":{"51":[19,20,117,48,21,118,119,49,120,22],"53":[19,20,117,48,21,118,119,49,120,22],"56":[19,20,117,48,21,118,119,49,120,22],"57":[19,20,117,48,21,118,119,49,120,22],"62":[19,20,117,48,21,118,119,49,120,22],"64":[19,20,117,48,21,118,119,49,120,22],"71":[19,20,117,48,21,118,119,49,120,22],"81":[19,20,117,48,21,118,119,49,120,22],"90":[19,20,117,48,21,118,119,49,120,22],"93":[19,20,117,48,21,118,119,49,120,22],"96":[19,20,117,48,21,118,119,49,120,22],"99":[19,20,117,48,21,118,119,49,120,22],"102":[19,20,117,48,21,118,119,49,120,22],"105":[19,20,117,48,21,118,119,49,120,22],"107":[19,20,117,48,21,118,119,49,120,22],"109":[19,20,117,48,21,118,119,49,120,22],"112":[19,20,117,48,21,118,119,49,120,22],"115":[19,20,117,48,21,118,119,49,120,22],"118":[19,20,117,48,21,118,119,49,120,22],"120":[19,20,117,48,21,118,119,49,120,22],"122":[19,20,117,48,21,118,119,49,120,22],"125":[19,20,117,48,21,118,119,49,120,22],"127":[19,20,117,48,21,118,119,49,120,22],"128":[19,20,117,48,21,118,119,49,120,22],"130":[19,20,117,48,21,118,119,49,120,22],"132":[19,20,117,48,21,118,119,49,120,22],"135":[19,20,117,48,21,118,119,49,120,22],"138":[19,20,117,48,21,118,119,49,120,22],"142":[19,20,117,48,21,118,119,49,120,22],"145":[19,20,117,48,21,118,119,49,120,22],"148":[19,20,117,48,21,118,119,49,120,22],"150":[19,20,117,48,21,118,119,49,120,22],"151":[19,20,117,48,21,118,119,49,120,22],"152":[19,20,117,48,21,118,119,49,120,22],"154":[19,20,117,48,21,118,119,49,120,22],"157":[19,20,117,48,21,118,119,49,120,22],"160":[19,20,117,48,21,118,119,49,120,22],"163":[19,20,117,48,21,118,119,49,120,22],"166":[19,20,117,48,21,118,119,49,120,22],"169":[19,20,117,48,21,118,119,49,120,22],"172":[19,20,117,48,21,118,119,49,120,22],"175":[19,20,117,48,21,118,119,49,120,22],"178":[19,20,117,48,21,118,119,49,120,22],"181":[19,20,117,48,21,118,119,49,120,22],"184":[19,20,117,48,21,118,119,49,120,22],"186":[19,20,117,48,21,118,119,49,120,22],"188":[19,20,117,48,21,118,119,49,120,22],"191":[19,20,117,48,21,118,119,49,120,22],"194":[19,20,117,48,21,118,119,49,120,22],"197":[19,20,117,48,21,118,119,49,120,22],"200":[19,20,117,48,21,118,119,49,120,22],"205":[19,20,117,48,21,118,119,49,120,22],"219":[19,20,117,48,21,118,119,49,120,22],"220":[19,20,117,48,21,118,119,49,120,22],"248":[19,20,117,48,21,118,119,49,120,22],"252":[19,20,117,48,21,118,119,49,120,22],"260":[19,20,117,48,21,118,119,49,120,22],"271":[19,20,117,48,21,118,119,49,120,22],"274":[19,20,117,48,21,118,119,49,120,22],"276":[19,20,117,48,21,118,119,49,120,22],"279":[19,20,117,48,21,118,119,49,120,22],"282":[19,20,117,48,21,118,119,49,120,22],"285":[19,20,117,48,21,118,119,49,120,22],"289":[19,20,117,48,21,118,119,49,120,22],"293":[19,20,117,48,21,118,119,49,120,22],"297":[19,20,117,48,21,118,119,49,120,22],"300":[19,20,117,48,21,118,119,49,120,22],"304":[19,20,117,48,21,118,119,49,120,22],"307":[19,20,117,48,21,118,119,49,120,22],"311":[19,20,117,48,21,118,119,49,120,22],"315":[19,20,117,48,21,118,119,49,120,22],"319":[19,20,117,48,21,118,119,49,120,22],"332":[19,20,117,48,21,118,119,49,120,22],"334":[19,20,117,48,21,118,119,49,120,22],"336":[19,20,117,48,21,118,119,49,120,22],"338":[19,20,117,48,21,118,119,49,120,22],"342":[19,20,117,48,21,118,119,49,120,22],"344":[19,20,117,48,21,118,119,49,120,22],"347":[19,20,117,48,21,118,119,49,120,22],"368":[19,20,117,48,21,118,119,49,120,22],"372":[19,20,117,48,21,118,119,49,120,22],"375":[19,20,117,48,21,118,119,49,120,22],"377":[19,20,117,48,21,118,119,49,120,22],"381":[19,20,117,48,21,118,119,49,120,22],"384":[19,20,117,48,21,118,119,49,120,22],"386":[19,20,117,48,21,118,119,49,120,22],"391":[19,20,117,48,21,118,119,49,120,22],"395":[19,20,117,48,21,118,119,49,120,22],"399":[19,20,117,48,21,118,119,49,120,22],"403":[19,20,117,48,21,118,119,49,120,22],"405":[19,20,117,48,21,118,119,49,120,22],"408":[19,20,117,48,21,118,119,49,120,22],"411":[19,20,117,48,21,118,119,49,120,22],"415":[19,20,117,48,21,118,119,49,120,22],"428":[19,20,117,48,21,118,119,49,120,22],"431":[19,20,117,48,21,118,119,49,120,22],"435":[19,20,117,48,21,118,119,49,120,22],"438":[19,20,117,48,21,118,119,49,120,22],"441":[19,20,117,48,21,118,119,49,120,22],"444":[19,20,117,48,21,118,119,49,120,22],"447":[19,20,117,48,21,118,119,49,120,22],"450":[19,20,117,48,21,118,119,49,120,22],"453":[19,20,117,48,21,118,119,49,120,22],"456":[19,20,117,48,21,118,119,49,120,22],"458":[19,20,117,48,21,118,119,49,120,22],"461":[19,20,117,48,21,118,119,49,120,22],"463":[19,20,117,48,21,118,119,49,120,22],"466":[19,20,117,48,21,118,119,49,120,22],"468":[19,20,117,48,21,118,119,49,120,22],"469":[19,20,117,48,21,118,119,49,120,22],"472":[19,20,117,48,21,118,119,49,120,22],"476":[19,20,117,48,21,118,119,49,120,22],"480":[19,20,117,48,21,118,119,49,120,22],"484":[19,20,117,48,21,118,119,49,120,22],"486":[19,20,117,48,21,118,119,49,120,22],"487":[19,20,117,48,21,118,119,49,120,22],"490":[19,20,117,48,21,118,119,49,120,22],"494":[19,20,117,48,21,118,119,49,120,22],"496":[19,20,117,48,21,118,119,49,120,22],"499":[19,20,117,48,21,118,119,49,120,22],"501":[19,20,117,48,21,118,119,49,120,22],"502":[19,20,117,48,21,118,119,49,120,22],"503":[19,20,117,48,21,118,119,49,120,22],"506":[19,20,117,48,21,118,119,49,120,22],"510":[19,20,117,48,21,118,119,49,120,22],"513":[19,20,117,48,21,118,119,49,120,22],"517":[19,20,117,48,21,118,119,49,120,22],"520":[19,20,117,48,21,118,119,49,120,22],"524":[19,20,117,48,21,118,119,49,120,22],"526":[19,20,117,48,21,118,119,49,120,22],"532":[19,20,117,48,21,118,119,49,120,22],"535":[19,20,117,48,21,118,119,49,120,22],"539":[19,20,117,48,21,118,119,49,120,22],"544":[19,20,117,48,21,118,119,49,120,22],"546":[19,20,117,48,21,118,119,49,120,22],"557":[19,20,117,48,21,118,119,49,120,22],"559":[19,20,117,48,21,118,119,49,120,22],"584":[19,20,117,48,21,118,119,49,120,22],"591":[19,20,117,48,21,118,119,49,120,22],"605":[19,20,117,48,21,118,119,49,120,22],"607":[19,20,117,48,21,118,119,49,120,22],"609":[19,20,117,48,21,118,119,49,120,22],"612":[19,20,117,48,21,118,119,49,120,22],"614":[19,20,117,48,21,118,119,49,120,22],"617":[19,20,117,48,21,118,119,49,120,22],"620":[19,20,117,48,21,118,119,49,120,22],"624":[19,20,117,48,21,118,119,49,120,22],"639":[19,20,117,48,21,118,119,49,120,22],"642":[19,20,117,48,21,118,119,49,120,22],"644":[19,20,117,48,21,118,119,49,120,22],"646":[19,20,117,48,21,118,119,49,120,22],"648":[19,20,117,48,21,118,119,49,120,22],"650":[19,20,117,48,21,118,119,49,120,22],"652":[19,20,117,48,21,118,119,49,120,22],"671":[19,20,117,48,21,118,119,49,120,22],"675":[19,20,117,48,21,118,119,49,120,22],"794":[19,20,117,48,21,118,119,49,120,22],"803":[19,20,117,48,21,118,119,49,120,22],"806":[19,20,117,48,21,118,119,49,120,22],"808":[19,20,117,48,21,118,119,49,120,22],"810":[19,20,117,48,21,118,119,49,120,22],"819":[19,20,117,48,21,118,119,49,120,22],"821":[19,20,117,48,21,118,119,49,120,22],"823":[19,20,117,48,21,118,119,49,120,22],"825":[19,20,117,48,21,118,119,49,120,22],"828":[19,20,117,48,21,118,119,49,120,22],"830":[19,20,117,48,21,118,119,49,120,22],"833":[19,20,117,48,21,118,119,49,120,22]},"packages/@n8n/instance-ai/src/knowledge-base/build-templates-index.ts":{"36":[19,20,48,21,49,22],"40":[19,20,48,21,49,22],"41":[19,20,48,21,49,22],"49":[19,20,48,21,49,22],"56":[19,20,48,21,49,22],"60":[19,20,48,21,49,22],"64":[19,20,48,21,49,22],"87":[19,20,48,21,49,22],"108":[19,20,48,21,49,22],"118":[19,20,48,21,49,22],"126":[19,20,48,21,49,22],"129":[19,20,48,21,49,22],"141":[19,20,48,21,49,22],"151":[19,20,48,21,49,22],"152":[19,20,48,21,49,22],"161":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/knowledge-base/extract-builder-templates-archive.ts":{"8":[19,20,48,21,49,22],"13":[19,20,48,21,49,22],"14":[19,20,48,21,49,22],"17":[19,20,48,21,49,22],"23":[19,20,48,21,49,22],"32":[19,20,48,21,49,22],"73":[19,20,48,21,49,22],"86":[19,20,48,21,49,22],"98":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/knowledge-base/materialize-knowledge-base.ts":{"105":[19,20,48,21,49,22],"184":[19,20,48,21,49,22],"215":[19,20,48,21,49,22],"216":[19,20,48,21,49,22],"228":[19,20,48,21,49,22],"303":[19,20,48,21,49,22],"323":[19,20,48,21,49,22],"329":[19,20,48,21,49,22],"333":[19,20,48,21,49,22],"339":[19,20,48,21,49,22],"343":[19,20,48,21,49,22],"348":[19,20,48,21,49,22],"349":[19,20,48,21,49,22],"351":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/mcp/connected-mcp-services.ts":{"6":[19,20,21,49,22],"19":[19,20,21,49,22],"20":[19,20,21,49,22],"21":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/mcp/mcp-client-manager.ts":{"32":[19,20,21,49,22],"78":[19,20,21,49,22],"88":[19,20,21,49,22],"91":[19,20,21,49,22],"114":[19,20,21,49,22],"118":[19,20,21,49,22],"119":[19,20,21,49,22],"133":[19,20,21,49,22],"134":[19,20,21,49,22],"145":[19,20,21,49,22],"146":[19,20,21,49,22],"155":[19,20,21,49,22],"160":[19,20,21,49,22],"185":[19,20,21,49,22],"190":[19,20,21,49,22],"210":[19,20,21,49,22],"223":[19,20,21,49,22],"228":[19,20,21,49,22],"231":[19,20,21,49,22],"243":[19,20,21,49,22],"257":[19,20,21,49,22],"285":[19,20,21,49,22],"306":[19,20,21,49,22],"307":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/memory/title-utils.ts":{"13":[19,20,21,49,22],"21":[19,20,21,49,22],"35":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/parsers/docx-parser.ts":{"17":[20]},"packages/@n8n/instance-ai/src/parsers/html-parser.ts":{"35":[20]},"packages/@n8n/instance-ai/src/parsers/ooxml-guard.ts":{"24":[20],"35":[20],"76":[20]},"packages/@n8n/instance-ai/src/parsers/pdf-parser.ts":{"19":[20]},"packages/@n8n/instance-ai/src/parsers/structured-file-parser.ts":{"18":[20],"31":[20],"35":[20],"66":[20],"150":[20],"155":[20],"177":[20],"179":[20],"216":[20],"217":[20],"220":[20],"221":[20],"225":[20],"229":[20],"232":[20],"240":[20],"261":[20],"268":[20],"299":[20],"313":[20],"366":[20],"412":[20],"416":[20],"425":[20],"452":[20],"455":[20],"460":[20],"527":[20],"528":[20],"553":[20],"583":[20],"593":[20]},"packages/@n8n/instance-ai/src/parsers/validate-attachments.ts":{"31":[20],"39":[20],"43":[20],"68":[20],"69":[20],"81":[20],"83":[20],"84":[20],"121":[20],"133":[20],"151":[20],"161":[20],"184":[20],"185":[20],"188":[20],"189":[20]},"packages/@n8n/instance-ai/src/parsers/xlsx-parser.ts":{"18":[20]},"packages/@n8n/instance-ai/src/planned-tasks/planned-task-service.ts":{"20":[19,20,21,49,22],"26":[19,20,21,49,22],"27":[19,20,21,49,22],"30":[19,20,21,49,22],"35":[19,20,21,49,22],"36":[19,20,21,49,22],"50":[19,20,21,49,22],"63":[19,20,21,49,22],"83":[19,20,21,49,22],"87":[19,20,21,49,22],"104":[19,20,21,49,22],"109":[19,20,21,49,22],"118":[19,20,21,49,22],"120":[19,20,21,49,22],"139":[19,20,21,49,22],"156":[19,20,21,49,22],"157":[19,20,21,49,22],"172":[19,20,21,49,22],"173":[19,20,21,49,22],"181":[19,20,21,49,22],"185":[19,20,21,49,22],"190":[19,20,21,49,22],"191":[19,20,21,49,22],"202":[19,20,21,49,22],"207":[19,20,21,49,22],"208":[19,20,21,49,22],"219":[19,20,21,49,22],"224":[19,20,21,49,22],"225":[19,20,21,49,22],"232":[19,20,21,49,22],"261":[19,20,21,49,22],"268":[19,20,21,49,22],"269":[19,20,21,49,22],"283":[19,20,21,49,22],"311":[19,20,21,49,22],"318":[19,20,21,49,22],"325":[19,20,21,49,22],"332":[19,20,21,49,22],"333":[19,20,21,49,22],"347":[19,20,21,49,22],"361":[19,20,21,49,22],"374":[19,20,21,49,22],"375":[19,20,21,49,22],"393":[19,20,21,49,22],"422":[19,20,21,49,22],"427":[19,20,21,49,22],"428":[19,20,21,49,22],"437":[19,20,21,49,22],"448":[19,20,21,49,22],"454":[19,20,21,49,22],"478":[19,20,21,49,22],"501":[19,20,21,49,22],"504":[19,20,21,49,22],"514":[19,20,21,49,22],"520":[19,20,21,49,22],"534":[19,20,21,49,22],"549":[19,20,21,49,22],"550":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/prompts/prompt-profiles.ts":{"58":[19,20,21,49,22],"59":[19,20,21,49,22],"64":[19,20,21,49,22],"65":[19,20,21,49,22],"71":[19,20,21,49,22],"75":[19,20,21,49,22],"81":[19,20,21,49,22],"83":[19,20,21,49,22],"88":[19,20,21,49,22],"95":[19,20,21,49,22],"106":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/prompts/skill-variants.ts":{"20":[19,20,21,49,22],"47":[19,20,21,49,22],"54":[19,20,21,49,22],"55":[19,20,21,49,22],"84":[19,20,21,49,22],"85":[19,20,21,49,22],"88":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/runtime/memory-task-registry.ts":{"11":[19,20,117,21,49,22],"43":[19,20,117,21,49,22],"47":[19,20,117,21,49,22]},"packages/@n8n/instance-ai/src/runtime/orchestrator-identity.ts":{"6":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/runtime/orchestrator-run-control.ts":{"20":[19,20,48,21,49,22],"26":[19,20,48,21,49,22],"29":[19,20,48,21,49,22],"32":[19,20,48,21,49,22],"38":[19,20,48,21,49,22],"44":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/runtime/resumable-stream-executor.ts":{"92":[19,20,48,21,49,22],"100":[19,20,48,21,49,22],"108":[19,20,48,21,49,22],"112":[19,20,48,21,49,22],"116":[19,20,48,21,49,22],"126":[19,20,48,21,49,22],"136":[19,20,48,21,49,22],"168":[19,20,48,21,49,22],"181":[19,20,48,21,49,22],"199":[19,20,48,21,49,22],"219":[19,20,48,21,49,22],"253":[19,20,48,21,49,22],"317":[19,20,48,21,49,22],"487":[19,20,48,21,49,22],"588":[19,20,48,21,49,22],"603":[19,20,48,21,49,22],"613":[19,20,48,21,49,22],"617":[19,20,48,21,49,22],"632":[19,20,48,21,49,22],"633":[19,20,48,21,49,22],"654":[19,20,48,21,49,22],"662":[19,20,48,21,49,22],"673":[19,20,48,21,49,22],"687":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/runtime/stream-runner.ts":{"47":[19,20,48,21,49,22],"59":[19,20,48,21,49,22],"71":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/runtime/terminal-response-guard.ts":{"48":[19,20,48,21,49,22],"52":[19,20,48,21,49,22],"64":[19,20,48,21,49,22],"74":[19,20,48,21,49,22],"76":[19,20,48,21,49,22],"177":[19,20,48,21,49,22],"219":[19,20,48,21,49,22],"227":[19,20,48,21,49,22],"233":[19,20,48,21,49,22],"237":[19,20,48,21,49,22],"240":[19,20,48,21,49,22],"244":[19,20,48,21,49,22],"246":[19,20,48,21,49,22],"251":[19,20,48,21,49,22],"256":[19,20,48,21,49,22],"262":[19,20,48,21,49,22],"282":[19,20,48,21,49,22],"303":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/skills/materialize-runtime-skills.ts":{"96":[19,20,48,21,119,49,22],"100":[19,20,48,21,119,49,22],"109":[19,20,48,21,119,49,22],"127":[19,20,48,21,119,49,22],"131":[19,20,48,21,119,49,22],"146":[19,20,48,21,119,49,22],"165":[19,20,48,21,119,49,22],"169":[19,20,48,21,119,49,22],"202":[19,20,48,21,119,49,22],"214":[19,20,48,21,119,49,22],"217":[19,20,48,21,119,49,22],"226":[19,20,48,21,119,49,22],"229":[19,20,48,21,119,49,22],"237":[19,20,48,21,119,49,22],"240":[19,20,48,21,119,49,22],"245":[19,20,48,21,119,49,22],"257":[19,20,48,21,119,49,22],"275":[19,20,48,21,119,49,22],"310":[19,20,48,21,119,49,22],"318":[19,20,48,21,119,49,22],"334":[19,20,48,21,119,49,22],"346":[19,20,48,21,119,49,22],"365":[19,20,48,21,119,49,22],"387":[19,20,48,21,119,49,22],"414":[19,20,48,21,119,49,22],"422":[19,20,48,21,119,49,22],"433":[19,20,48,21,119,49,22],"434":[19,20,48,21,119,49,22],"437":[19,20,48,21,119,49,22],"454":[19,20,48,21,119,49,22],"465":[19,20,48,21,119,49,22],"467":[19,20,48,21,119,49,22],"485":[19,20,48,21,119,49,22],"488":[19,20,48,21,119,49,22],"494":[19,20,48,21,119,49,22],"499":[19,20,48,21,119,49,22],"533":[19,20,48,21,119,49,22],"535":[19,20,48,21,119,49,22],"592":[19,20,48,21,119,49,22],"602":[19,20,48,21,119,49,22],"606":[19,20,48,21,119,49,22],"613":[19,20,48,21,119,49,22],"615":[19,20,48,21,119,49,22],"623":[19,20,48,21,119,49,22],"635":[19,20,48,21,119,49,22],"648":[19,20,48,21,119,49,22],"651":[19,20,48,21,119,49,22],"654":[19,20,48,21,119,49,22],"662":[19,20,48,21,119,49,22],"665":[19,20,48,21,119,49,22],"674":[19,20,48,21,119,49,22],"682":[19,20,48,21,119,49,22]},"packages/@n8n/instance-ai/src/skills/runtime-skills.ts":{"30":[19,20,21,49,22],"32":[19,20,21,49,22],"37":[19,20,21,49,22],"45":[19,20,21,49,22],"51":[19,20,21,49,22],"64":[19,20,21,49,22],"76":[19,20,21,49,22],"84":[19,20,21,49,22],"87":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/skills/skill-gates.ts":{"27":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/storage/index.ts":{"2":[19,20,21,49,22],"11":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/storage/iteration-log.ts":{"30":[19,20,21,49,22],"33":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/storage/planned-task-storage.ts":{"38":[19,20,21,49,22],"44":[19,20,21,49,22],"46":[19,20,21,49,22],"52":[19,20,21,49,22],"55":[19,20,21,49,22],"68":[19,20,21,49,22],"76":[19,20,21,49,22],"96":[19,20,21,49,22],"99":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/storage/terminal-outcome-storage.ts":{"26":[19,20,116,21,49,22],"28":[19,20,116,21,49,22],"31":[19,20,116,21,49,22],"46":[19,20,116,21,49,22],"49":[19,20,116,21,49,22],"70":[19,20,116,21,49,22],"73":[19,20,116,21,49,22],"77":[19,20,116,21,49,22]},"packages/@n8n/instance-ai/src/storage/thread-iteration-log-storage.ts":{"12":[19,20,21,49,22],"14":[19,20,21,49,22],"17":[19,20,21,49,22],"34":[19,20,21,49,22],"42":[19,20,21,49,22],"45":[19,20,21,49,22],"53":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/storage/thread-patch.ts":{"21":[19,20,21,49,22],"30":[19,20,21,49,22],"37":[19,20,21,49,22],"44":[19,20,21,49,22],"53":[19,20,21,49,22],"64":[19,20,21,49,22],"90":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/storage/thread-task-storage.ts":{"10":[19,20,21,49,22],"12":[19,20,21,49,22],"19":[19,20,21,49,22],"22":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/storage/workflow-loop-storage.ts":{"36":[19,20,48,21,49,22],"44":[19,20,48,21,49,22],"53":[19,20,48,21,49,22],"60":[19,20,48,21,49,22],"62":[19,20,48,21,49,22],"70":[19,20,48,21,49,22],"78":[19,20,48,21,49,22],"91":[19,20,48,21,49,22],"99":[19,20,48,21,49,22],"115":[19,20,48,21,49,22],"125":[19,20,48,21,49,22],"130":[19,20,48,21,49,22],"141":[19,20,48,21,49,22],"146":[19,20,48,21,49,22],"154":[19,20,48,21,49,22],"180":[19,20,48,21,49,22],"189":[19,20,48,21,49,22],"216":[19,20,48,21,49,22],"223":[19,20,48,21,49,22],"243":[19,20,48,21,49,22],"249":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/stream/consume-with-hitl.ts":{"56":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/stream/instance-context-reach.ts":{"19":[19,20,48,21,49,22],"37":[19,20,48,21,49,22],"49":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/stream/map-chunk.ts":{"24":[19,20,48,21,118,119,49,22],"29":[19,20,48,21,118,119,49,22],"37":[19,20,48,21,118,119,49,22],"45":[19,20,48,21,118,119,49,22],"49":[19,20,48,21,118,119,49,22],"51":[19,20,48,21,118,119,49,22],"61":[19,20,48,21,118,119,49,22],"65":[19,20,48,21,118,119,49,22],"112":[19,20,48,21,118,119,49,22],"125":[19,20,48,21,118,119,49,22],"135":[19,20,48,21,118,119,49,22],"145":[19,20,48,21,118,119,49,22],"161":[19,20,48,21,118,119,49,22],"222":[19,20,48,21,118,119,49,22],"226":[19,20,48,21,118,119,49,22],"229":[19,20,48,21,118,119,49,22],"230":[19,20,48,21,118,119,49,22],"231":[19,20,48,21,118,119,49,22],"235":[19,20,48,21,118,119,49,22],"241":[19,20,48,21,118,119,49,22],"247":[19,20,48,21,118,119,49,22],"262":[19,20,48,21,118,119,49,22],"269":[19,20,48,21,118,119,49,22],"278":[19,20,48,21,118,119,49,22],"293":[19,20,48,21,118,119,49,22],"312":[19,20,48,21,118,119,49,22],"411":[19,20,48,21,118,119,49,22],"424":[19,20,48,21,118,119,49,22],"441":[19,20,48,21,118,119,49,22],"452":[19,20,48,21,118,119,49,22],"458":[19,20,48,21,118,119,49,22],"463":[19,20,48,21,118,119,49,22],"481":[19,20,48,21,118,119,49,22]},"packages/@n8n/instance-ai/src/stream/usage-accumulator.ts":{"83":[19,20,21,49,22],"119":[19,20,21,49,22],"124":[19,20,21,49,22],"150":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/stream/work-summary-accumulator.ts":{"31":[19,20,21,49,22],"57":[19,20,21,49,22],"115":[19,20,21,49,22],"116":[19,20,21,49,22],"120":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tool-registry.ts":{"5":[19,20,21,49,22],"15":[19,20,21,49,22],"23":[19,20,21,49,22],"36":[19,20,21,49,22],"49":[19,20,21,49,22],"53":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/agent-context.tool.ts":{"82":[19,20,21,49,22],"83":[19,20,21,49,22],"85":[19,20,21,49,22],"106":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/approval-copy.ts":{"22":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/attachments/parse-file.tool.ts":{"62":[20],"111":[20],"112":[20],"115":[20],"119":[20],"129":[20],"138":[20],"156":[20],"171":[20]},"packages/@n8n/instance-ai/src/tools/credentials.tool.ts":{"136":[19,20,21,49,22],"148":[19,20,21,49,22],"158":[19,20,21,49,22],"179":[19,20,21,49,22],"184":[19,20,21,49,22],"214":[19,20,21,49,22],"242":[19,20,21,49,22],"262":[19,20,21,49,22],"289":[19,20,21,49,22],"300":[19,20,21,49,22],"310":[19,20,21,49,22],"511":[19,20,21,49,22],"515":[19,20,21,49,22],"518":[19,20,21,49,22],"522":[19,20,21,49,22],"558":[19,20,21,49,22],"562":[19,20,21,49,22],"563":[19,20,21,49,22],"570":[19,20,21,49,22],"624":[19,20,21,49,22],"671":[19,20,21,49,22],"691":[19,20,21,49,22],"706":[19,20,21,49,22],"719":[19,20,21,49,22],"751":[19,20,21,49,22],"758":[19,20,21,49,22],"775":[19,20,21,49,22],"793":[19,20,21,49,22],"800":[19,20,21,49,22],"839":[19,20,21,49,22],"849":[19,20,21,49,22],"853":[19,20,21,49,22],"869":[19,20,21,49,22],"889":[19,20,21,49,22],"900":[19,20,21,49,22],"909":[19,20,21,49,22],"915":[19,20,21,49,22],"955":[19,20,21,49,22],"956":[19,20,21,49,22],"966":[19,20,21,49,22],"987":[19,20,21,49,22],"1006":[19,20,21,49,22],"1016":[19,20,21,49,22],"1077":[19,20,21,49,22],"1085":[19,20,21,49,22],"1109":[19,20,21,49,22],"1116":[19,20,21,49,22],"1120":[19,20,21,49,22],"1136":[19,20,21,49,22],"1148":[19,20,21,49,22],"1170":[19,20,21,49,22],"1173":[19,20,21,49,22],"1192":[19,20,21,49,22],"1205":[19,20,21,49,22],"1216":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/data-tables.tool.ts":{"67":[19,20,21,49,22],"71":[19,20,21,49,22],"86":[19,20,21,49,22],"119":[19,20,21,49,22],"123":[19,20,21,49,22],"135":[19,20,21,49,22],"154":[19,20,21,49,22],"157":[19,20,21,49,22],"165":[19,20,21,49,22],"167":[19,20,21,49,22],"361":[19,20,21,49,22],"388":[19,20,21,49,22],"405":[19,20,21,49,22],"406":[19,20,21,49,22],"418":[19,20,21,49,22],"426":[19,20,21,49,22],"442":[19,20,21,49,22],"447":[19,20,21,49,22],"449":[19,20,21,49,22],"465":[19,20,21,49,22],"514":[19,20,21,49,22],"530":[19,20,21,49,22],"571":[19,20,21,49,22],"608":[19,20,21,49,22],"655":[19,20,21,49,22],"699":[19,20,21,49,22],"744":[19,20,21,49,22],"761":[19,20,21,49,22],"801":[19,20,21,49,22],"856":[19,20,21,49,22],"912":[19,20,21,49,22],"929":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/executions.tool.ts":{"256":[19,20,21,49,22],"274":[19,20,21,49,22],"292":[19,20,21,49,22],"296":[19,20,21,49,22],"300":[19,20,21,49,22],"314":[19,20,21,49,22],"322":[19,20,21,49,22],"329":[19,20,21,49,22],"356":[19,20,21,49,22],"359":[19,20,21,49,22],"360":[19,20,21,49,22],"457":[19,20,21,49,22],"509":[19,20,21,49,22],"510":[19,20,21,49,22],"541":[19,20,21,49,22],"545":[19,20,21,49,22],"555":[19,20,21,49,22],"569":[19,20,21,49,22],"575":[19,20,21,49,22],"594":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/filesystem/create-tools-from-mcp-server.ts":{"24":[19,20,21,49,22],"79":[19,20,21,49,22],"85":[19,20,21,49,22],"98":[19,20,21,49,22],"110":[19,20,21,49,22],"115":[19,20,21,49,22],"116":[19,20,21,49,22],"160":[19,20,21,49,22],"162":[19,20,21,49,22],"163":[19,20,21,49,22],"175":[19,20,21,49,22],"191":[19,20,21,49,22],"192":[19,20,21,49,22],"203":[19,20,21,49,22],"204":[19,20,21,49,22],"218":[19,20,21,49,22],"219":[19,20,21,49,22],"245":[19,20,21,49,22],"315":[19,20,21,49,22],"317":[19,20,21,49,22],"331":[19,20,21,49,22],"386":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/index.ts":{"10":[19,20,21,49,22],"12":[19,20,21,49,22],"16":[19,20,21,49,22],"19":[19,20,21,49,22],"22":[19,20,21,49,22],"25":[19,20,21,49,22],"28":[19,20,21,49,22],"31":[19,20,21,49,22],"33":[19,20,21,49,22],"35":[19,20,21,49,22],"38":[19,20,21,49,22],"41":[19,20,21,49,22],"44":[19,20,21,49,22],"47":[19,20,21,49,22],"50":[19,20,21,49,22],"53":[19,20,21,49,22],"57":[19,20,21,49,22],"61":[19,20,21,49,22],"65":[19,20,21,49,22],"68":[19,20,21,49,22],"72":[19,20,21,49,22],"76":[19,20,21,49,22],"79":[19,20,21,49,22],"82":[19,20,21,49,22],"86":[19,20,21,49,22],"89":[19,20,21,49,22],"93":[19,20,21,49,22],"97":[19,20,21,49,22],"100":[19,20,21,49,22],"105":[19,20,21,49,22],"109":[19,20,21,49,22],"110":[19,20,21,49,22],"111":[19,20,21,49,22],"112":[19,20,21,49,22],"113":[19,20,21,49,22],"114":[19,20,21,49,22],"115":[19,20,21,49,22],"116":[19,20,21,49,22],"117":[19,20,21,49,22],"118":[19,20,21,49,22],"121":[19,20,21,49,22],"130":[19,20,21,49,22],"139":[19,20,21,49,22],"149":[19,20,21,49,22],"159":[19,20,21,49,22],"167":[19,20,21,49,22],"173":[19,20,21,49,22],"176":[19,20,21,49,22],"187":[19,20,21,49,22],"194":[19,20,21,49,22],"202":[19,20,21,49,22],"203":[19,20,21,49,22],"207":[19,20,21,49,22],"209":[19,20,21,49,22],"219":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/mcp-servers.tool.ts":{"133":[19,20,21,49,22],"139":[19,20,21,49,22],"140":[19,20,21,49,22],"144":[19,20,21,49,22],"147":[19,20,21,49,22],"150":[19,20,21,49,22],"155":[19,20,21,49,22],"159":[19,20,21,49,22],"169":[19,20,21,49,22],"176":[19,20,21,49,22],"192":[19,20,21,49,22],"197":[19,20,21,49,22],"200":[19,20,21,49,22],"216":[19,20,21,49,22],"237":[19,20,21,49,22],"247":[19,20,21,49,22],"254":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/models/model-catalog.service.ts":{"25":[19,20,21,49,22],"55":[19,20,21,49,22],"71":[19,20,21,49,22],"86":[19,20,21,49,22],"113":[19,20,21,49,22],"119":[19,20,21,49,22],"134":[19,20,21,49,22],"136":[19,20,21,49,22],"139":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/n8n-docs/ranking.ts":{"24":[19,20,21,49,22],"32":[19,20,21,49,22],"35":[19,20,21,49,22],"53":[19,20,21,49,22],"71":[19,20,21,49,22],"75":[19,20,21,49,22],"76":[19,20,21,49,22],"79":[19,20,21,49,22],"85":[19,20,21,49,22],"90":[19,20,21,49,22],"94":[19,20,21,49,22],"98":[19,20,21,49,22],"102":[19,20,21,49,22],"113":[19,20,21,49,22],"203":[19,20,21,49,22],"210":[19,20,21,49,22],"211":[19,20,21,49,22],"212":[19,20,21,49,22],"215":[19,20,21,49,22],"221":[19,20,21,49,22],"226":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/n8n-docs/registry.ts":{"53":[19,20,21,49,22],"68":[19,20,21,49,22],"83":[19,20,21,49,22],"88":[19,20,21,49,22],"113":[19,20,21,49,22],"133":[19,20,21,49,22],"137":[19,20,21,49,22],"166":[19,20,21,49,22],"171":[19,20,21,49,22],"214":[19,20,21,49,22],"230":[19,20,21,49,22],"266":[19,20,21,49,22],"284":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/n8n-docs.tool.ts":{"13":[19,20,21,49,22],"16":[19,20,21,49,22],"19":[19,20,21,49,22],"53":[19,20,21,49,22],"58":[19,20,21,49,22],"67":[19,20,21,49,22],"95":[19,20,21,49,22],"104":[19,20,21,49,22],"126":[19,20,21,49,22],"147":[19,20,21,49,22],"167":[19,20,21,49,22],"180":[19,20,21,49,22],"199":[19,20,21,49,22],"200":[19,20,21,49,22],"226":[19,20,21,49,22],"232":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/nodes/model-selection.ts":{"11":[19,20,21,49,22,50],"15":[19,20,21,49,22,50],"18":[19,20,21,49,22,50],"26":[19,20,21,49,22,50],"29":[19,20,21,49,22,50]},"packages/@n8n/instance-ai/src/tools/nodes/preferred-chat-model.ts":{"48":[19,20,48,21,49,22],"52":[19,20,48,21,49,22],"61":[19,20,48,21,49,22],"72":[19,20,48,21,49,22],"73":[19,20,48,21,49,22],"76":[19,20,48,21,49,22],"80":[19,20,48,21,49,22],"88":[19,20,48,21,49,22],"92":[19,20,48,21,49,22],"95":[19,20,48,21,49,22],"98":[19,20,48,21,49,22],"108":[19,20,48,21,49,22],"113":[19,20,48,21,49,22],"133":[19,20,48,21,49,22],"141":[19,20,48,21,49,22],"153":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/nodes/setup-preference.ts":{"23":[19,20,21,49,22],"28":[19,20,21,49,22],"29":[19,20,21,49,22],"30":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/nodes.tool.ts":{"228":[19,20,21,49,22,50],"235":[19,20,21,49,22,50],"237":[19,20,21,49,22,50],"245":[19,20,21,49,22,50],"256":[19,20,21,49,22,50],"281":[19,20,21,49,22,50],"294":[19,20,21,49,22,50],"295":[19,20,21,49,22,50],"307":[19,20,21,49,22,50],"311":[19,20,21,49,22,50],"326":[19,20,21,49,22,50],"351":[19,20,21,49,22,50],"357":[19,20,21,49,22,50],"366":[19,20,21,49,22,50],"402":[19,20,21,49,22,50],"417":[19,20,21,49,22,50],"429":[19,20,21,49,22,50],"445":[19,20,21,49,22,50],"461":[19,20,21,49,22,50],"488":[19,20,21,49,22,50],"506":[19,20,21,49,22,50],"524":[19,20,21,49,22,50],"526":[19,20,21,49,22,50],"531":[19,20,21,49,22,50],"532":[19,20,21,49,22,50],"550":[19,20,21,49,22,50],"572":[19,20,21,49,22,50],"581":[19,20,21,49,22,50],"587":[19,20,21,49,22,50],"641":[19,20,21,49,22,50],"683":[19,20,21,49,22,50],"701":[19,20,21,49,22,50]},"packages/@n8n/instance-ai/src/tools/orchestration/agent-preview-session-binding.ts":{"22":[19,20,21,49,22],"27":[19,20,21,49,22],"41":[19,20,21,49,22],"55":[19,20,21,49,22],"69":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/orchestration/build-agent.tool.ts":{"88":[19,20,21,49,22],"94":[19,20,21,49,22],"101":[19,20,21,49,22],"106":[19,20,21,49,22],"110":[19,20,21,49,22],"111":[19,20,21,49,22],"118":[19,20,21,49,22],"126":[19,20,21,49,22],"128":[19,20,21,49,22],"139":[19,20,21,49,22],"154":[19,20,21,49,22],"164":[19,20,21,49,22],"191":[19,20,21,49,22],"349":[19,20,21,49,22],"378":[19,20,21,49,22],"399":[19,20,21,49,22],"409":[19,20,21,49,22],"440":[19,20,21,49,22],"483":[19,20,21,49,22],"500":[19,20,21,49,22],"538":[19,20,21,49,22],"565":[19,20,21,49,22],"715":[19,20,21,49,22],"733":[19,20,21,49,22],"778":[19,20,21,49,22],"843":[19,20,21,49,22],"859":[19,20,21,49,22],"864":[19,20,21,49,22],"885":[19,20,21,49,22],"1066":[19,20,21,49,22],"1093":[19,20,21,49,22],"1133":[19,20,21,49,22],"1174":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/orchestration/complete-checkpoint.tool.ts":{"44":[19,20,21,49,22],"49":[19,20,21,49,22],"55":[19,20,21,49,22],"58":[19,20,21,49,22],"61":[19,20,21,49,22],"68":[19,20,21,49,22],"73":[19,20,21,49,22],"74":[19,20,21,49,22],"75":[19,20,21,49,22],"80":[19,20,21,49,22],"110":[19,20,21,49,22],"119":[19,20,21,49,22],"129":[19,20,21,49,22],"130":[19,20,21,49,22],"164":[19,20,21,49,22],"174":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/orchestration/parent-handoff-state.ts":{"19":[19,20,21,49,22],"23":[19,20,21,49,22],"27":[19,20,21,49,22],"31":[19,20,21,49,22],"44":[19,20,21,49,22],"49":[19,20,21,49,22],"53":[19,20,21,49,22],"91":[19,20,21,49,22],"95":[19,20,21,49,22],"107":[19,20,21,49,22],"123":[19,20,21,49,22],"130":[19,20,21,49,22],"139":[19,20,21,49,22],"145":[19,20,21,49,22],"147":[19,20,21,49,22],"156":[19,20,21,49,22],"172":[19,20,21,49,22],"177":[19,20,21,49,22],"194":[19,20,21,49,22],"209":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/orchestration/plan.tool.ts":{"57":[19,20,21,49,22],"70":[19,20,21,49,22],"71":[19,20,21,49,22],"76":[19,20,21,49,22],"77":[19,20,21,49,22],"80":[19,20,21,49,22],"101":[19,20,21,49,22],"151":[19,20,21,49,22],"174":[19,20,21,49,22],"253":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/orchestration/report-verification-verdict.tool.ts":{"74":[19,20,21,49,22],"107":[19,20,21,49,22],"120":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/orchestration/tracing-utils.ts":{"18":[19,20,21,49,22],"41":[19,20,21,49,22],"53":[19,20,21,49,22],"62":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/orchestration/verification/analyze-result.ts":{"38":[19,20,48,21,49,22],"64":[19,20,48,21,49,22],"73":[19,20,48,21,49,22],"87":[19,20,48,21,49,22],"91":[19,20,48,21,49,22],"104":[19,20,48,21,49,22],"114":[19,20,48,21,49,22],"117":[19,20,48,21,49,22],"124":[19,20,48,21,49,22],"135":[19,20,48,21,49,22],"142":[19,20,48,21,49,22],"162":[19,20,48,21,49,22],"168":[19,20,48,21,49,22],"178":[19,20,48,21,49,22],"188":[19,20,48,21,49,22],"196":[19,20,48,21,49,22],"200":[19,20,48,21,49,22],"210":[19,20,48,21,49,22],"213":[19,20,48,21,49,22],"215":[19,20,48,21,49,22],"228":[19,20,48,21,49,22],"240":[19,20,48,21,49,22],"241":[19,20,48,21,49,22],"244":[19,20,48,21,49,22],"251":[19,20,48,21,49,22],"263":[19,20,48,21,49,22],"267":[19,20,48,21,49,22],"277":[19,20,48,21,49,22],"291":[19,20,48,21,49,22],"297":[19,20,48,21,49,22],"302":[19,20,48,21,49,22],"410":[19,20,48,21,49,22],"417":[19,20,48,21,49,22],"431":[19,20,48,21,49,22],"493":[19,20,48,21,49,22],"497":[19,20,48,21,49,22],"505":[19,20,48,21,49,22],"527":[19,20,48,21,49,22],"567":[19,20,48,21,49,22],"569":[19,20,48,21,49,22],"570":[19,20,48,21,49,22],"574":[19,20,48,21,49,22],"579":[19,20,48,21,49,22],"583":[19,20,48,21,49,22],"584":[19,20,48,21,49,22],"585":[19,20,48,21,49,22],"615":[19,20,48,21,49,22],"624":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/orchestration/verification/claim.ts":{"45":[19,20,48,21,49,22],"50":[19,20,48,21,49,22],"51":[19,20,48,21,49,22],"84":[19,20,48,21,49,22],"94":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/orchestration/verification/finalize-result.ts":{"25":[19,20,48,21,49,22],"37":[19,20,48,21,49,22],"106":[19,20,48,21,49,22],"167":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/orchestration/verification/prepare-run.ts":{"18":[19,20,48,21,49,22],"26":[19,20,48,21,49,22],"27":[19,20,48,21,49,22],"30":[19,20,48,21,49,22],"43":[19,20,48,21,49,22],"76":[19,20,48,21,49,22],"88":[19,20,48,21,49,22],"104":[19,20,48,21,49,22],"112":[19,20,48,21,49,22],"114":[19,20,48,21,49,22],"144":[19,20,48,21,49,22],"145":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/orchestration/verification/publish-state.ts":{"12":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/orchestration/verification/reconcile-plan.ts":{"15":[19,20,48,21,49,22],"36":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/orchestration/verification/record-live-run.ts":{"24":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/orchestration/verification/resolve-target.ts":{"33":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/orchestration/verification/resolved-parameter-warnings.ts":{"42":[19,20,48,21,49,22],"49":[19,20,48,21,49,22],"50":[19,20,48,21,49,22],"58":[19,20,48,21,49,22],"59":[19,20,48,21,49,22],"68":[19,20,48,21,49,22],"81":[19,20,48,21,49,22],"95":[19,20,48,21,49,22],"98":[19,20,48,21,49,22],"105":[19,20,48,21,49,22],"125":[19,20,48,21,49,22],"140":[19,20,48,21,49,22],"162":[19,20,48,21,49,22],"172":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/orchestration/verification/scripted-gate-run.ts":{"53":[19,20,21,49,22],"98":[19,20,21,49,22],"100":[19,20,21,49,22],"105":[19,20,21,49,22],"107":[19,20,21,49,22],"135":[19,20,21,49,22],"144":[19,20,21,49,22],"146":[19,20,21,49,22],"147":[19,20,21,49,22],"148":[19,20,21,49,22],"149":[19,20,21,49,22],"157":[19,20,21,49,22],"174":[19,20,21,49,22],"179":[19,20,21,49,22],"181":[19,20,21,49,22],"182":[19,20,21,49,22],"185":[19,20,21,49,22],"190":[19,20,21,49,22],"197":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/orchestration/verification/tool-simulation-preflight.ts":{"26":[19,20,48,21,49,22],"49":[19,20,48,21,49,22],"51":[19,20,48,21,49,22],"64":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/orchestration/verify-built-workflow.tool.ts":{"53":[19,20,48,21,49,22],"215":[19,20,48,21,49,22],"226":[19,20,48,21,49,22],"263":[19,20,48,21,49,22],"269":[19,20,48,21,49,22],"284":[19,20,48,21,49,22],"317":[19,20,48,21,49,22],"321":[19,20,48,21,49,22],"355":[19,20,48,21,49,22],"385":[19,20,48,21,49,22],"398":[19,20,48,21,49,22],"417":[19,20,48,21,49,22],"418":[19,20,48,21,49,22],"457":[19,20,48,21,49,22],"461":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/research.tool.ts":{"20":[19,20,21,49,22],"88":[19,20,21,49,22],"143":[19,20,21,49,22],"220":[19,20,21,49,22],"249":[19,20,21,49,22],"263":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/search-models.tool.ts":{"9":[19,20,21,49,22],"23":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/shared/ask-user.tool.ts":{"7":[19,20,21,49,22],"51":[19,20,21,49,22],"63":[19,20,21,49,22],"70":[19,20,21,49,22],"116":[19,20,21,49,22],"136":[19,20,21,49,22],"143":[19,20,21,49,22],"145":[19,20,21,49,22],"155":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/shared/safe-error-message.ts":{"3":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/task-control.tool.ts":{"57":[19,20,21,49,22],"72":[19,20,21,49,22],"83":[19,20,21,49,22],"110":[19,20,21,49,22],"116":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/web-research/sanitize-web-content.ts":{"13":[19,20,48,21,49,22],"23":[19,20,48,21,49,22],"44":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/apply-workflow-credentials.tool.ts":{"29":[19,20,21,49,22],"44":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/build-workflow.tool.ts":{"149":[19,20,48,21,49,22],"160":[19,20,48,21,49,22],"256":[19,20,48,21,49,22],"267":[19,20,48,21,49,22],"270":[19,20,48,21,49,22],"312":[19,20,48,21,49,22],"330":[19,20,48,21,49,22],"356":[19,20,48,21,49,22],"362":[19,20,48,21,49,22],"366":[19,20,48,21,49,22],"377":[19,20,48,21,49,22],"387":[19,20,48,21,49,22],"411":[19,20,48,21,49,22],"477":[19,20,48,21,49,22],"499":[19,20,48,21,49,22],"523":[19,20,48,21,49,22],"573":[19,20,48,21,49,22],"610":[19,20,48,21,49,22],"619":[19,20,48,21,49,22],"635":[19,20,48,21,49,22],"1033":[19,20,48,21,49,22],"1242":[19,20,48,21,49,22],"1251":[19,20,48,21,49,22],"1267":[19,20,48,21,49,22],"1279":[19,20,48,21,49,22],"1420":[19,20,48,21,49,22],"1480":[19,20,48,21,49,22],"1481":[19,20,48,21,49,22],"1483":[19,20,48,21,49,22],"1493":[19,20,48,21,49,22],"1497":[19,20,48,21,49,22],"1499":[19,20,48,21,49,22],"1520":[19,20,48,21,49,22],"1535":[19,20,48,21,49,22],"1553":[19,20,48,21,49,22],"1730":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/chat-model-validation.ts":{"30":[19,20,48,21,49,22],"38":[19,20,48,21,49,22],"45":[19,20,48,21,49,22],"56":[19,20,48,21,49,22],"66":[19,20,48,21,49,22],"79":[19,20,48,21,49,22],"85":[19,20,48,21,49,22],"90":[19,20,48,21,49,22],"93":[19,20,48,21,49,22],"98":[19,20,48,21,49,22],"103":[19,20,48,21,49,22],"148":[19,20,48,21,49,22],"153":[19,20,48,21,49,22],"154":[19,20,48,21,49,22],"164":[19,20,48,21,49,22],"176":[19,20,48,21,49,22],"184":[19,20,48,21,49,22],"195":[19,20,48,21,49,22],"241":[19,20,48,21,49,22],"250":[19,20,48,21,49,22],"268":[19,20,48,21,49,22],"282":[19,20,48,21,49,22],"304":[19,20,48,21,49,22],"337":[19,20,48,21,49,22],"360":[19,20,48,21,49,22],"392":[19,20,48,21,49,22],"424":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/classify-node-destructiveness.service.ts":{"83":[19,20,48,21,49,22],"193":[19,20,48,21,49,22],"200":[19,20,48,21,49,22],"208":[19,20,48,21,49,22],"288":[19,20,48,21,49,22],"317":[19,20,48,21,49,22],"348":[19,20,48,21,49,22],"355":[19,20,48,21,49,22],"364":[19,20,48,21,49,22],"376":[19,20,48,21,49,22],"389":[19,20,48,21,49,22],"398":[19,20,48,21,49,22],"406":[19,20,48,21,49,22],"443":[19,20,48,21,49,22],"444":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/detect-array-input-collapse.ts":{"31":[19,20,48,21,49,22],"43":[19,20,48,21,49,22],"54":[19,20,48,21,49,22],"77":[19,20,48,21,49,22],"89":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/detect-python-code-constraints.ts":{"11":[19,20,48,21,49,22],"20":[19,20,48,21,49,22],"34":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/detect-slack-blocks-shape.ts":{"15":[19,20,48,21,49,22],"34":[19,20,48,21,49,22],"47":[19,20,48,21,49,22],"63":[19,20,48,21,49,22],"79":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/detect-unparseable-openai-schema.ts":{"14":[19,20,48,21,49,22],"38":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/detect-wrong-kind-locator.ts":{"7":[19,20,48,21,49,22],"8":[19,20,48,21,49,22],"12":[19,20,48,21,49,22],"15":[19,20,48,21,49,22],"18":[19,20,48,21,49,22],"19":[19,20,48,21,49,22],"22":[19,20,48,21,49,22],"31":[19,20,48,21,49,22],"36":[19,20,48,21,49,22],"45":[19,20,48,21,49,22],"65":[19,20,48,21,49,22],"111":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/generate-simulation-fixtures.service.ts":{"98":[19,20,48,21,49,22],"125":[19,20,48,21,49,22],"134":[19,20,48,21,49,22],"135":[19,20,48,21,49,22],"138":[19,20,48,21,49,22],"146":[19,20,48,21,49,22],"187":[19,20,48,21,49,22],"199":[19,20,48,21,49,22],"200":[19,20,48,21,49,22],"203":[19,20,48,21,49,22],"208":[19,20,48,21,49,22],"215":[19,20,48,21,49,22],"222":[19,20,48,21,49,22],"223":[19,20,48,21,49,22],"227":[19,20,48,21,49,22],"260":[19,20,48,21,49,22],"277":[19,20,48,21,49,22],"278":[19,20,48,21,49,22],"303":[19,20,48,21,49,22],"321":[19,20,48,21,49,22],"354":[19,20,48,21,49,22],"360":[19,20,48,21,49,22],"372":[19,20,48,21,49,22],"380":[19,20,48,21,49,22],"393":[19,20,48,21,49,22],"397":[19,20,48,21,49,22],"402":[19,20,48,21,49,22],"405":[19,20,48,21,49,22],"412":[19,20,48,21,49,22],"423":[19,20,48,21,49,22],"435":[19,20,48,21,49,22],"471":[19,20,48,21,49,22],"472":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/plan-verification-simulation.ts":{"81":[19,20,48,21,49,22],"85":[19,20,48,21,49,22],"118":[19,20,48,21,49,22],"124":[19,20,48,21,49,22],"127":[19,20,48,21,49,22],"153":[19,20,48,21,49,22],"160":[19,20,48,21,49,22],"169":[19,20,48,21,49,22],"186":[19,20,48,21,49,22],"193":[19,20,48,21,49,22],"196":[19,20,48,21,49,22],"202":[19,20,48,21,49,22],"214":[19,20,48,21,49,22],"239":[19,20,48,21,49,22],"245":[19,20,48,21,49,22],"248":[19,20,48,21,49,22],"251":[19,20,48,21,49,22],"261":[19,20,48,21,49,22],"266":[19,20,48,21,49,22],"270":[19,20,48,21,49,22],"277":[19,20,48,21,49,22],"278":[19,20,48,21,49,22],"316":[19,20,48,21,49,22],"325":[19,20,48,21,49,22],"330":[19,20,48,21,49,22],"341":[19,20,48,21,49,22],"372":[19,20,48,21,49,22],"398":[19,20,48,21,49,22],"399":[19,20,48,21,49,22],"400":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/prepare-workflow-setup.ts":{"25":[19,20,21,49,22],"30":[19,20,21,49,22],"40":[19,20,21,49,22],"54":[19,20,21,49,22],"81":[19,20,21,49,22],"84":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/preserve-node-positions.ts":{"38":[19,20,48,21,49,22],"42":[19,20,48,21,49,22],"43":[19,20,48,21,49,22],"48":[19,20,48,21,49,22],"51":[19,20,48,21,49,22],"62":[19,20,48,21,49,22],"63":[19,20,48,21,49,22],"64":[19,20,48,21,49,22],"75":[19,20,48,21,49,22],"77":[19,20,48,21,49,22],"80":[19,20,48,21,49,22],"81":[19,20,48,21,49,22],"85":[19,20,48,21,49,22],"100":[19,20,48,21,49,22],"103":[19,20,48,21,49,22],"124":[19,20,48,21,49,22],"125":[19,20,48,21,49,22],"135":[19,20,48,21,49,22],"137":[19,20,48,21,49,22],"149":[19,20,48,21,49,22],"157":[19,20,48,21,49,22],"158":[19,20,48,21,49,22],"159":[19,20,48,21,49,22],"160":[19,20,48,21,49,22],"165":[19,20,48,21,49,22],"171":[19,20,48,21,49,22],"172":[19,20,48,21,49,22],"176":[19,20,48,21,49,22],"177":[19,20,48,21,49,22],"184":[19,20,48,21,49,22],"185":[19,20,48,21,49,22],"188":[19,20,48,21,49,22],"197":[19,20,48,21,49,22],"213":[19,20,48,21,49,22],"231":[19,20,48,21,49,22],"239":[19,20,48,21,49,22],"240":[19,20,48,21,49,22],"247":[19,20,48,21,49,22],"269":[19,20,48,21,49,22],"270":[19,20,48,21,49,22],"271":[19,20,48,21,49,22],"272":[19,20,48,21,49,22],"277":[19,20,48,21,49,22],"283":[19,20,48,21,49,22],"291":[19,20,48,21,49,22],"324":[19,20,48,21,49,22],"331":[19,20,48,21,49,22],"336":[19,20,48,21,49,22],"338":[19,20,48,21,49,22],"339":[19,20,48,21,49,22],"341":[19,20,48,21,49,22],"344":[19,20,48,21,49,22],"346":[19,20,48,21,49,22],"350":[19,20,48,21,49,22],"351":[19,20,48,21,49,22],"355":[19,20,48,21,49,22],"358":[19,20,48,21,49,22],"360":[19,20,48,21,49,22],"361":[19,20,48,21,49,22],"367":[19,20,48,21,49,22],"369":[19,20,48,21,49,22],"370":[19,20,48,21,49,22],"374":[19,20,48,21,49,22],"394":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/reconcile-simulation-plan.ts":{"41":[19,20,21,49,22],"51":[19,20,21,49,22],"55":[19,20,21,49,22],"59":[19,20,21,49,22],"77":[19,20,21,49,22],"89":[19,20,21,49,22],"95":[19,20,21,49,22],"100":[19,20,21,49,22],"103":[19,20,21,49,22],"105":[19,20,21,49,22],"106":[19,20,21,49,22],"116":[19,20,21,49,22],"121":[19,20,21,49,22],"136":[19,20,21,49,22],"143":[19,20,21,49,22],"163":[19,20,21,49,22],"165":[19,20,21,49,22],"187":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/resolve-credentials.ts":{"50":[19,20,48,21,49,22],"95":[19,20,48,21,49,22],"152":[19,20,48,21,49,22],"156":[19,20,48,21,49,22],"157":[19,20,48,21,49,22],"180":[19,20,48,21,49,22],"197":[19,20,48,21,49,22],"203":[19,20,48,21,49,22],"208":[19,20,48,21,49,22],"213":[19,20,48,21,49,22],"228":[19,20,48,21,49,22],"234":[19,20,48,21,49,22],"242":[19,20,48,21,49,22],"257":[19,20,48,21,49,22],"264":[19,20,48,21,49,22],"292":[19,20,48,21,49,22],"330":[19,20,48,21,49,22],"336":[19,20,48,21,49,22],"353":[19,20,48,21,49,22],"363":[19,20,48,21,49,22],"384":[19,20,48,21,49,22],"393":[19,20,48,21,49,22],"410":[19,20,48,21,49,22],"440":[19,20,48,21,49,22],"599":[19,20,48,21,49,22],"608":[19,20,48,21,49,22],"617":[19,20,48,21,49,22],"628":[19,20,48,21,49,22],"637":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/saved-workflow-state.ts":{"19":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/setup-credential-selections.ts":{"25":[19,20,48,21,49,22],"34":[19,20,48,21,49,22],"40":[19,20,48,21,49,22],"50":[19,20,48,21,49,22],"70":[19,20,48,21,49,22],"71":[19,20,48,21,49,22],"81":[19,20,48,21,49,22],"87":[19,20,48,21,49,22],"98":[19,20,48,21,49,22],"113":[19,20,48,21,49,22],"124":[19,20,48,21,49,22],"132":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/setup-items.ts":{"24":[19,20,21,49,22],"31":[19,20,21,49,22],"32":[19,20,21,49,22],"35":[19,20,21,49,22],"59":[19,20,21,49,22],"77":[19,20,21,49,22],"84":[19,20,21,49,22],"85":[19,20,21,49,22],"104":[19,20,21,49,22],"113":[19,20,21,49,22],"121":[19,20,21,49,22],"134":[19,20,21,49,22],"146":[19,20,21,49,22],"157":[19,20,21,49,22],"174":[19,20,21,49,22],"201":[19,20,21,49,22],"208":[19,20,21,49,22],"220":[19,20,21,49,22],"229":[19,20,21,49,22],"236":[19,20,21,49,22],"241":[19,20,21,49,22],"255":[19,20,21,49,22],"272":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/setup-skip-state.ts":{"23":[19,20,48,21,49,22],"37":[19,20,48,21,49,22],"48":[19,20,48,21,49,22],"52":[19,20,48,21,49,22],"57":[19,20,48,21,49,22],"61":[19,20,48,21,49,22],"70":[19,20,48,21,49,22],"75":[19,20,48,21,49,22],"85":[19,20,48,21,49,22],"109":[19,20,48,21,49,22],"119":[19,20,48,21,49,22],"121":[19,20,48,21,49,22],"156":[19,20,48,21,49,22],"175":[19,20,48,21,49,22],"190":[19,20,48,21,49,22],"193":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/setup-workflow.service.ts":{"58":[19,20,48,21,49,22,50],"62":[19,20,48,21,49,22,50],"75":[19,20,48,21,49,22,50],"146":[19,20,48,21,49,22,50],"160":[19,20,48,21,49,22,50],"184":[19,20,48,21,49,22,50],"216":[19,20,48,21,49,22,50],"237":[19,20,48,21,49,22,50],"242":[19,20,48,21,49,22,50],"249":[19,20,48,21,49,22,50],"259":[19,20,48,21,49,22,50],"278":[19,20,48,21,49,22,50],"286":[19,20,48,21,49,22,50],"309":[19,20,48,21,49,22,50],"325":[19,20,48,21,49,22,50],"336":[19,20,48,21,49,22,50],"340":[19,20,48,21,49,22,50],"341":[19,20,48,21,49,22,50],"392":[19,20,48,21,49,22,50],"405":[19,20,48,21,49,22,50],"409":[19,20,48,21,49,22,50],"413":[19,20,48,21,49,22,50],"423":[19,20,48,21,49,22,50],"441":[19,20,48,21,49,22,50],"445":[19,20,48,21,49,22,50],"463":[19,20,48,21,49,22,50],"485":[19,20,48,21,49,22,50],"519":[19,20,48,21,49,22,50],"525":[19,20,48,21,49,22,50],"534":[19,20,48,21,49,22,50],"547":[19,20,48,21,49,22,50],"586":[19,20,48,21,49,22,50],"643":[19,20,48,21,49,22,50],"658":[19,20,48,21,49,22,50],"660":[19,20,48,21,49,22,50],"743":[19,20,48,21,49,22,50],"784":[19,20,48,21,49,22,50],"803":[19,20,48,21,49,22,50],"869":[19,20,48,21,49,22,50],"877":[19,20,48,21,49,22,50],"901":[19,20,48,21,49,22,50],"923":[19,20,48,21,49,22,50],"944":[19,20,48,21,49,22,50],"964":[19,20,48,21,49,22,50],"971":[19,20,48,21,49,22,50],"972":[19,20,48,21,49,22,50],"977":[19,20,48,21,49,22,50],"1005":[19,20,48,21,49,22,50],"1012":[19,20,48,21,49,22,50],"1028":[19,20,48,21,49,22,50],"1034":[19,20,48,21,49,22,50],"1051":[19,20,48,21,49,22,50],"1103":[19,20,48,21,49,22,50],"1161":[19,20,48,21,49,22,50],"1177":[19,20,48,21,49,22,50],"1199":[19,20,48,21,49,22,50],"1238":[19,20,48,21,49,22,50],"1263":[19,20,48,21,49,22,50],"1327":[19,20,48,21,49,22,50],"1384":[19,20,48,21,49,22,50],"1417":[19,20,48,21,49,22,50],"1434":[19,20,48,21,49,22,50],"1443":[19,20,48,21,49,22,50]},"packages/@n8n/instance-ai/src/tools/workflows/sticky-note-wrapping.ts":{"20":[19,20,21,49,22],"27":[19,20,21,49,22],"36":[19,20,21,49,22],"37":[19,20,21,49,22],"38":[19,20,21,49,22],"39":[19,20,21,49,22],"40":[19,20,21,49,22],"44":[19,20,21,49,22],"45":[19,20,21,49,22],"48":[19,20,21,49,22],"51":[19,20,21,49,22],"71":[19,20,21,49,22],"73":[19,20,21,49,22],"74":[19,20,21,49,22],"78":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/summarize-workflow.ts":{"16":[19,20,21,49,22],"23":[19,20,21,49,22],"29":[19,20,21,49,22],"40":[19,20,21,49,22],"50":[19,20,21,49,22],"59":[19,20,21,49,22],"69":[19,20,21,49,22],"88":[19,20,21,49,22],"97":[19,20,21,49,22],"111":[19,20,21,49,22],"113":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/validate-workflow.service.ts":{"46":[19,20,21,49,22],"50":[19,20,21,49,22],"62":[19,20,21,49,22],"63":[19,20,21,49,22],"70":[19,20,21,49,22],"75":[19,20,21,49,22],"82":[19,20,21,49,22],"87":[19,20,21,49,22],"92":[19,20,21,49,22],"101":[19,20,21,49,22],"114":[19,20,21,49,22],"138":[19,20,21,49,22],"186":[19,20,21,49,22],"232":[19,20,21,49,22],"236":[19,20,21,49,22],"257":[19,20,21,49,22],"303":[19,20,21,49,22],"318":[19,20,21,49,22],"335":[19,20,21,49,22],"419":[19,20,21,49,22],"429":[19,20,21,49,22],"456":[19,20,21,49,22],"466":[19,20,21,49,22],"475":[19,20,21,49,22],"479":[19,20,21,49,22],"500":[19,20,21,49,22],"520":[19,20,21,49,22],"603":[19,20,21,49,22],"646":[19,20,21,49,22],"687":[19,20,21,49,22],"705":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/verification-graph.ts":{"13":[19,20,48,21,49,22],"24":[19,20,48,21,49,22],"30":[19,20,48,21,49,22],"33":[19,20,48,21,49,22],"38":[19,20,48,21,49,22],"39":[19,20,48,21,49,22],"48":[19,20,48,21,49,22],"49":[19,20,48,21,49,22],"52":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/wait-gate-script.ts":{"34":[19,20,48,21,49,22],"40":[19,20,48,21,49,22],"56":[19,20,48,21,49,22],"67":[19,20,48,21,49,22],"83":[19,20,48,21,49,22],"105":[19,20,48,21,49,22],"109":[19,20,48,21,49,22],"112":[19,20,48,21,49,22],"120":[19,20,48,21,49,22],"136":[19,20,48,21,49,22],"144":[19,20,48,21,49,22],"145":[19,20,48,21,49,22],"156":[19,20,48,21,49,22],"172":[19,20,48,21,49,22],"176":[19,20,48,21,49,22],"181":[19,20,48,21,49,22],"201":[19,20,48,21,49,22],"229":[19,20,48,21,49,22],"237":[19,20,48,21,49,22],"259":[19,20,48,21,49,22],"263":[19,20,48,21,49,22],"267":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/workflow-build-context.ts":{"11":[19,20,48,21,49,22],"23":[19,20,48,21,49,22],"34":[19,20,48,21,49,22],"45":[19,20,48,21,49,22],"53":[19,20,48,21,49,22],"64":[19,20,48,21,49,22],"94":[19,20,48,21,49,22],"134":[19,20,48,21,49,22],"138":[19,20,48,21,49,22],"139":[19,20,48,21,49,22],"143":[19,20,48,21,49,22],"150":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/workflow-build-remediation.ts":{"15":[19,20,21,49,22],"19":[19,20,21,49,22],"34":[19,20,21,49,22],"44":[19,20,21,49,22],"56":[19,20,21,49,22],"64":[19,20,21,49,22],"74":[19,20,21,49,22],"134":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/workflow-build-reporting.ts":{"8":[19,20,48,21,49,22],"54":[19,20,48,21,49,22],"69":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/workflow-build-routing.ts":{"18":[19,20,48,21,49,22],"29":[19,20,48,21,49,22],"34":[19,20,48,21,49,22],"57":[19,20,48,21,49,22],"73":[19,20,48,21,49,22],"129":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/workflow-build-telemetry.ts":{"18":[19,20,48,21,49,22],"82":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/workflow-file-bindings.ts":{"36":[19,20,48,21,49,22],"40":[19,20,48,21,49,22],"50":[19,20,48,21,49,22],"55":[19,20,48,21,49,22],"65":[19,20,48,21,49,22],"90":[19,20,48,21,49,22],"111":[19,20,48,21,49,22],"124":[19,20,48,21,49,22],"130":[19,20,48,21,49,22],"147":[19,20,48,21,49,22],"169":[19,20,48,21,49,22],"184":[19,20,48,21,49,22],"196":[19,20,48,21,49,22],"213":[19,20,48,21,49,22],"233":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/workflow-json-utils.ts":{"37":[19,20,48,21,49,22],"46":[19,20,48,21,49,22],"58":[19,20,48,21,49,22],"68":[19,20,48,21,49,22],"100":[19,20,48,21,49,22],"110":[19,20,48,21,49,22],"114":[19,20,48,21,49,22],"137":[19,20,48,21,49,22],"180":[19,20,48,21,49,22],"192":[19,20,48,21,49,22],"221":[19,20,48,21,49,22],"263":[19,20,48,21,49,22],"317":[19,20,48,21,49,22],"332":[19,20,48,21,49,22],"342":[19,20,48,21,49,22],"349":[19,20,48,21,49,22],"358":[19,20,48,21,49,22],"369":[19,20,48,21,49,22],"389":[19,20,48,21,49,22],"393":[19,20,48,21,49,22],"399":[19,20,48,21,49,22],"410":[19,20,48,21,49,22],"414":[19,20,48,21,49,22],"422":[19,20,48,21,49,22],"430":[19,20,48,21,49,22],"448":[19,20,48,21,49,22],"464":[19,20,48,21,49,22],"480":[19,20,48,21,49,22],"500":[19,20,48,21,49,22],"501":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/workflow-node-diff.ts":{"30":[19,20,48,21,49,22],"37":[19,20,48,21,49,22],"42":[19,20,48,21,49,22],"52":[19,20,48,21,49,22],"59":[19,20,48,21,49,22],"70":[19,20,48,21,49,22],"90":[19,20,48,21,49,22],"102":[19,20,48,21,49,22],"110":[19,20,48,21,49,22],"124":[19,20,48,21,49,22],"146":[19,20,48,21,49,22],"167":[19,20,48,21,49,22],"180":[19,20,48,21,49,22],"186":[19,20,48,21,49,22],"196":[19,20,48,21,49,22],"198":[19,20,48,21,49,22],"232":[19,20,48,21,49,22],"233":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/workflow-source-compiler.ts":{"61":[19,20,48,21,49,22],"70":[19,20,48,21,49,22],"75":[19,20,48,21,49,22],"83":[19,20,48,21,49,22],"85":[19,20,48,21,49,22],"88":[19,20,48,21,49,22],"111":[19,20,48,21,49,22],"148":[19,20,48,21,49,22],"149":[19,20,48,21,49,22],"152":[19,20,48,21,49,22],"160":[19,20,48,21,49,22],"184":[19,20,48,21,49,22],"198":[19,20,48,21,49,22],"207":[19,20,48,21,49,22],"215":[19,20,48,21,49,22],"216":[19,20,48,21,49,22],"225":[19,20,48,21,49,22],"232":[19,20,48,21,49,22],"257":[19,20,48,21,49,22],"259":[19,20,48,21,49,22],"262":[19,20,48,21,49,22],"268":[19,20,48,21,49,22],"272":[19,20,48,21,49,22],"287":[19,20,48,21,49,22],"291":[19,20,48,21,49,22],"315":[19,20,48,21,49,22],"316":[19,20,48,21,49,22],"336":[19,20,48,21,49,22],"420":[19,20,48,21,49,22],"456":[19,20,48,21,49,22],"466":[19,20,48,21,49,22],"480":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/workflow-source-diagnostics.ts":{"14":[19,20,21,49,22],"25":[19,20,21,49,22],"31":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/workflow-source-materializer.ts":{"48":[19,20,48,21,49,22],"59":[19,20,48,21,49,22],"73":[19,20,48,21,49,22],"89":[19,20,48,21,49,22],"97":[19,20,48,21,49,22],"105":[19,20,48,21,49,22],"131":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows/workflow-validation-warnings.ts":{"38":[19,20,48,21,49,22],"60":[19,20,48,21,49,22],"71":[19,20,48,21,49,22],"83":[19,20,48,21,49,22],"104":[19,20,48,21,49,22],"118":[19,20,48,21,49,22],"149":[19,20,48,21,49,22],"167":[19,20,48,21,49,22],"173":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/workflows.tool.ts":{"195":[19,20,48,21,49,22],"481":[19,20,48,21,49,22],"485":[19,20,48,21,49,22],"516":[19,20,48,21,49,22],"522":[19,20,48,21,49,22],"526":[19,20,48,21,49,22],"557":[19,20,48,21,49,22],"568":[19,20,48,21,49,22],"574":[19,20,48,21,49,22],"575":[19,20,48,21,49,22],"582":[19,20,48,21,49,22],"634":[19,20,48,21,49,22],"637":[19,20,48,21,49,22],"654":[19,20,48,21,49,22],"692":[19,20,48,21,49,22],"708":[19,20,48,21,49,22],"746":[19,20,48,21,49,22],"747":[19,20,48,21,49,22],"766":[19,20,48,21,49,22],"805":[19,20,48,21,49,22],"820":[19,20,48,21,49,22],"825":[19,20,48,21,49,22],"909":[19,20,48,21,49,22],"948":[19,20,48,21,49,22],"989":[19,20,48,21,49,22],"1011":[19,20,48,21,49,22],"1041":[19,20,48,21,49,22],"1048":[19,20,48,21,49,22],"1050":[19,20,48,21,49,22],"1058":[19,20,48,21,49,22],"1064":[19,20,48,21,49,22],"1065":[19,20,48,21,49,22],"1074":[19,20,48,21,49,22],"1081":[19,20,48,21,49,22],"1102":[19,20,48,21,49,22],"1121":[19,20,48,21,49,22],"1127":[19,20,48,21,49,22],"1133":[19,20,48,21,49,22],"1153":[19,20,48,21,49,22],"1174":[19,20,48,21,49,22],"1248":[19,20,48,21,49,22],"1258":[19,20,48,21,49,22],"1264":[19,20,48,21,49,22],"1265":[19,20,48,21,49,22],"1267":[19,20,48,21,49,22],"1274":[19,20,48,21,49,22],"1279":[19,20,48,21,49,22],"1306":[19,20,48,21,49,22],"1345":[19,20,48,21,49,22],"1348":[19,20,48,21,49,22],"1357":[19,20,48,21,49,22],"1358":[19,20,48,21,49,22],"1377":[19,20,48,21,49,22],"1425":[19,20,48,21,49,22],"1453":[19,20,48,21,49,22],"1482":[19,20,48,21,49,22],"1540":[19,20,48,21,49,22],"1581":[19,20,48,21,49,22],"1620":[19,20,48,21,49,22],"1648":[19,20,48,21,49,22],"1666":[19,20,48,21,49,22],"1667":[19,20,48,21,49,22],"1668":[19,20,48,21,49,22],"1696":[19,20,48,21,49,22],"1713":[19,20,48,21,49,22],"1724":[19,20,48,21,49,22],"1732":[19,20,48,21,49,22],"1733":[19,20,48,21,49,22],"1734":[19,20,48,21,49,22],"1740":[19,20,48,21,49,22],"1779":[19,20,48,21,49,22],"1780":[19,20,48,21,49,22],"1785":[19,20,48,21,49,22],"1842":[19,20,48,21,49,22],"1875":[19,20,48,21,49,22],"1899":[19,20,48,21,49,22],"2013":[19,20,48,21,49,22],"2027":[19,20,48,21,49,22],"2058":[19,20,48,21,49,22],"2069":[19,20,48,21,49,22],"2076":[19,20,48,21,49,22],"2083":[19,20,48,21,49,22],"2127":[19,20,48,21,49,22],"2138":[19,20,48,21,49,22],"2156":[19,20,48,21,49,22],"2209":[19,20,48,21,49,22],"2265":[19,20,48,21,49,22],"2270":[19,20,48,21,49,22],"2271":[19,20,48,21,49,22],"2278":[19,20,48,21,49,22],"2293":[19,20,48,21,49,22],"2311":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/tools/workspace.tool.ts":{"110":[19,20,21,49,22],"145":[19,20,21,49,22],"153":[19,20,21,49,22],"160":[19,20,21,49,22],"165":[19,20,21,49,22],"197":[19,20,21,49,22],"232":[19,20,21,49,22],"240":[19,20,21,49,22],"298":[19,20,21,49,22],"334":[19,20,21,49,22],"368":[19,20,21,49,22],"375":[19,20,21,49,22],"389":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tracing/agent-snapshot-event.ts":{"36":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tracing/langsmith-tracing.ts":{"102":[19,20,117,48,21,118,49,22],"110":[19,20,117,48,21,118,49,22],"113":[19,20,117,48,21,118,49,22],"121":[19,20,117,48,21,118,49,22],"126":[19,20,117,48,21,118,49,22],"130":[19,20,117,48,21,118,49,22],"136":[19,20,117,48,21,118,49,22],"137":[19,20,117,48,21,118,49,22],"150":[19,20,117,48,21,118,49,22],"152":[19,20,117,48,21,118,49,22],"162":[19,20,117,48,21,118,49,22],"206":[19,20,117,48,21,118,49,22],"214":[19,20,117,48,21,118,49,22],"221":[19,20,117,48,21,118,49,22],"226":[19,20,117,48,21,118,49,22],"230":[19,20,117,48,21,118,49,22],"243":[19,20,117,48,21,118,49,22],"263":[19,20,117,48,21,118,49,22],"269":[19,20,117,48,21,118,49,22],"295":[19,20,117,48,21,118,49,22],"333":[19,20,117,48,21,118,49,22],"341":[19,20,117,48,21,118,49,22],"406":[19,20,117,48,21,118,49,22],"471":[19,20,117,48,21,118,49,22],"493":[19,20,117,48,21,118,49,22],"503":[19,20,117,48,21,118,49,22],"526":[19,20,117,48,21,118,49,22],"528":[19,20,117,48,21,118,49,22],"532":[19,20,117,48,21,118,49,22],"547":[19,20,117,48,21,118,49,22],"557":[19,20,117,48,21,118,49,22],"573":[19,20,117,48,21,118,49,22],"585":[19,20,117,48,21,118,49,22],"589":[19,20,117,48,21,118,49,22],"596":[19,20,117,48,21,118,49,22],"608":[19,20,117,48,21,118,49,22],"635":[19,20,117,48,21,118,49,22],"641":[19,20,117,48,21,118,49,22],"653":[19,20,117,48,21,118,49,22],"668":[19,20,117,48,21,118,49,22],"687":[19,20,117,48,21,118,49,22],"706":[19,20,117,48,21,118,49,22],"715":[19,20,117,48,21,118,49,22],"718":[19,20,117,48,21,118,49,22],"785":[19,20,117,48,21,118,49,22],"793":[19,20,117,48,21,118,49,22],"797":[19,20,117,48,21,118,49,22],"821":[19,20,117,48,21,118,49,22],"828":[19,20,117,48,21,118,49,22],"829":[19,20,117,48,21,118,49,22],"834":[19,20,117,48,21,118,49,22],"855":[19,20,117,48,21,118,49,22],"882":[19,20,117,48,21,118,49,22],"893":[19,20,117,48,21,118,49,22],"908":[19,20,117,48,21,118,49,22],"924":[19,20,117,48,21,118,49,22],"937":[19,20,117,48,21,118,49,22],"947":[19,20,117,48,21,118,49,22],"960":[19,20,117,48,21,118,49,22],"966":[19,20,117,48,21,118,49,22],"974":[19,20,117,48,21,118,49,22],"991":[19,20,117,48,21,118,49,22],"1047":[19,20,117,48,21,118,49,22],"1067":[19,20,117,48,21,118,49,22],"1073":[19,20,117,48,21,118,49,22],"1079":[19,20,117,48,21,118,49,22],"1127":[19,20,117,48,21,118,49,22],"1171":[19,20,117,48,21,118,49,22],"1186":[19,20,117,48,21,118,49,22],"1225":[19,20,117,48,21,118,49,22],"1238":[19,20,117,48,21,118,49,22],"1257":[19,20,117,48,21,118,49,22],"1269":[19,20,117,48,21,118,49,22],"1273":[19,20,117,48,21,118,49,22],"1292":[19,20,117,48,21,118,49,22],"1295":[19,20,117,48,21,118,49,22],"1299":[19,20,117,48,21,118,49,22],"1306":[19,20,117,48,21,118,49,22],"1316":[19,20,117,48,21,118,49,22],"1321":[19,20,117,48,21,118,49,22],"1329":[19,20,117,48,21,118,49,22],"1339":[19,20,117,48,21,118,49,22],"1353":[19,20,117,48,21,118,49,22],"1356":[19,20,117,48,21,118,49,22],"1360":[19,20,117,48,21,118,49,22],"1364":[19,20,117,48,21,118,49,22],"1365":[19,20,117,48,21,118,49,22],"1368":[19,20,117,48,21,118,49,22],"1383":[19,20,117,48,21,118,49,22],"1392":[19,20,117,48,21,118,49,22],"1395":[19,20,117,48,21,118,49,22],"1399":[19,20,117,48,21,118,49,22],"1403":[19,20,117,48,21,118,49,22],"1428":[19,20,117,48,21,118,49,22],"1436":[19,20,117,48,21,118,49,22],"1452":[19,20,117,48,21,118,49,22],"1460":[19,20,117,48,21,118,49,22],"1472":[19,20,117,48,21,118,49,22],"1503":[19,20,117,48,21,118,49,22],"1510":[19,20,117,48,21,118,49,22],"1518":[19,20,117,48,21,118,49,22],"1563":[19,20,117,48,21,118,49,22],"1587":[19,20,117,48,21,118,49,22],"1607":[19,20,117,48,21,118,49,22],"1608":[19,20,117,48,21,118,49,22],"1609":[19,20,117,48,21,118,49,22],"1610":[19,20,117,48,21,118,49,22],"1611":[19,20,117,48,21,118,49,22],"1612":[19,20,117,48,21,118,49,22],"1613":[19,20,117,48,21,118,49,22],"1635":[19,20,117,48,21,118,49,22],"1644":[19,20,117,48,21,118,49,22],"1670":[19,20,117,48,21,118,49,22],"1671":[19,20,117,48,21,118,49,22],"1685":[19,20,117,48,21,118,49,22],"1718":[19,20,117,48,21,118,49,22],"1727":[19,20,117,48,21,118,49,22],"1737":[19,20,117,48,21,118,49,22],"1783":[19,20,117,48,21,118,49,22],"1800":[19,20,117,48,21,118,49,22],"1823":[19,20,117,48,21,118,49,22],"1853":[19,20,117,48,21,118,49,22],"1863":[19,20,117,48,21,118,49,22],"1887":[19,20,117,48,21,118,49,22],"1909":[19,20,117,48,21,118,49,22],"1946":[19,20,117,48,21,118,49,22],"1997":[19,20,117,48,21,118,49,22],"2011":[19,20,117,48,21,118,49,22],"2041":[19,20,117,48,21,118,49,22],"2044":[19,20,117,48,21,118,49,22],"2070":[19,20,117,48,21,118,49,22],"2081":[19,20,117,48,21,118,49,22],"2092":[19,20,117,48,21,118,49,22],"2107":[19,20,117,48,21,118,49,22],"2123":[19,20,117,48,21,118,49,22]},"packages/@n8n/instance-ai/src/tracing/sandbox-tracing.ts":{"17":[19,20,21,49,22],"39":[19,20,21,49,22],"43":[19,20,21,49,22],"47":[19,20,21,49,22],"51":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tracing/thread-provenance.ts":{"23":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tracing/trace-labels.ts":{"1":[19,20,21,49,22],"9":[19,20,21,49,22],"13":[19,20,21,49,22],"24":[19,20,21,49,22],"28":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tracing/trace-payloads.ts":{"61":[19,20,21,49,22],"78":[19,20,21,49,22],"113":[19,20,21,49,22],"121":[19,20,21,49,22],"135":[19,20,21,49,22],"136":[19,20,21,49,22],"138":[19,20,21,49,22],"141":[19,20,21,49,22],"144":[19,20,21,49,22],"157":[19,20,21,49,22],"179":[19,20,21,49,22],"202":[19,20,21,49,22],"216":[19,20,21,49,22],"228":[19,20,21,49,22],"264":[19,20,21,49,22],"277":[19,20,21,49,22],"292":[19,20,21,49,22],"299":[19,20,21,49,22],"306":[19,20,21,49,22],"322":[19,20,21,49,22],"349":[19,20,21,49,22],"383":[19,20,21,49,22],"420":[19,20,21,49,22],"445":[19,20,21,49,22],"447":[19,20,21,49,22],"451":[19,20,21,49,22],"453":[19,20,21,49,22],"460":[19,20,21,49,22],"464":[19,20,21,49,22],"474":[19,20,21,49,22],"489":[19,20,21,49,22],"515":[19,20,21,49,22],"546":[19,20,21,49,22],"557":[19,20,21,49,22],"572":[19,20,21,49,22],"586":[19,20,21,49,22],"593":[19,20,21,49,22],"606":[19,20,21,49,22],"624":[19,20,21,49,22],"646":[19,20,21,49,22],"674":[19,20,21,49,22],"726":[19,20,21,49,22],"771":[19,20,21,49,22],"808":[19,20,21,49,22],"821":[19,20,21,49,22],"829":[19,20,21,49,22],"862":[19,20,21,49,22],"867":[19,20,21,49,22],"877":[19,20,21,49,22],"886":[19,20,21,49,22],"897":[19,20,21,49,22],"934":[19,20,21,49,22],"968":[19,20,21,49,22],"977":[19,20,21,49,22],"992":[19,20,21,49,22],"996":[19,20,21,49,22],"1011":[19,20,21,49,22],"1042":[19,20,21,49,22],"1051":[19,20,21,49,22],"1075":[19,20,21,49,22],"1082":[19,20,21,49,22],"1086":[19,20,21,49,22],"1094":[19,20,21,49,22],"1117":[19,20,21,49,22],"1135":[19,20,21,49,22],"1158":[19,20,21,49,22],"1185":[19,20,21,49,22],"1217":[19,20,21,49,22],"1226":[19,20,21,49,22],"1228":[19,20,21,49,22],"1243":[19,20,21,49,22],"1255":[19,20,21,49,22],"1265":[19,20,21,49,22],"1266":[19,20,21,49,22],"1272":[19,20,21,49,22],"1281":[19,20,21,49,22],"1294":[19,20,21,49,22],"1307":[19,20,21,49,22],"1329":[19,20,21,49,22],"1347":[19,20,21,49,22],"1359":[19,20,21,49,22],"1371":[19,20,21,49,22],"1384":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/tracing/trace-replay.ts":{"45":[19,20,117,48,21,118,49,22],"61":[19,20,117,48,21,118,49,22],"76":[19,20,117,48,21,118,49,22],"96":[19,20,117,48,21,118,49,22],"137":[19,20,117,48,21,118,49,22],"152":[19,20,117,48,21,118,49,22],"158":[19,20,117,48,21,118,49,22],"162":[19,20,117,48,21,118,49,22],"200":[19,20,117,48,21,118,49,22],"224":[19,20,117,48,21,118,49,22],"240":[19,20,117,48,21,118,49,22],"262":[19,20,117,48,21,118,49,22],"267":[19,20,117,48,21,118,49,22],"275":[19,20,117,48,21,118,49,22],"279":[19,20,117,48,21,118,49,22],"303":[19,20,117,48,21,118,49,22],"312":[19,20,117,48,21,118,49,22],"328":[19,20,117,48,21,118,49,22],"346":[19,20,117,48,21,118,49,22],"364":[19,20,117,48,21,118,49,22],"368":[19,20,117,48,21,118,49,22],"369":[19,20,117,48,21,118,49,22],"377":[19,20,117,48,21,118,49,22],"383":[19,20,117,48,21,118,49,22]},"packages/@n8n/instance-ai/src/utils/custom-model-defaults.ts":{"52":[19,20,21,49,22],"61":[19,20,21,49,22],"75":[19,20,21,49,22],"79":[19,20,21,49,22],"93":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/utils/eval-agents.ts":{"39":[19,20,21,49,22],"54":[19,20,21,49,22],"60":[19,20,21,49,22],"91":[19,20,21,49,22],"97":[19,20,21,49,22],"101":[19,20,21,49,22],"108":[19,20,21,49,22],"143":[19,20,21,49,22],"158":[19,20,21,49,22],"188":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/utils/eval-usage.ts":{"13":[19,20,21,49,22],"17":[19,20,21,49,22],"31":[19,20,21,49,22],"32":[19,20,21,49,22],"37":[19,20,21,49,22],"44":[19,20,21,49,22],"52":[19,20,21,49,22],"70":[19,20,21,49,22],"72":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/utils/format-timestamp.ts":{"2":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/utils/generate-validated-json.ts":{"34":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/utils/modal-session.ts":{"7":[19,20,21,49,22],"25":[19,20,21,49,22],"35":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/utils/model-config-id.ts":{"6":[19,20,21,49,22],"22":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/utils/node-keyed-items.ts":{"12":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/utils/quota-error.ts":{"7":[19,20,21,118,119,49,22],"11":[19,20,21,118,119,49,22],"32":[19,20,21,118,119,49,22]},"packages/@n8n/instance-ai/src/utils/stream-helpers.ts":{"20":[19,20,48,21,49,22],"46":[19,20,48,21,49,22],"50":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/workflow-builder/build-failure-tracker.ts":{"7":[19,20,48,21,49,22],"9":[19,20,48,21,49,22],"36":[19,20,48,21,49,22],"63":[19,20,48,21,49,22],"85":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/workflow-loop/guidance.ts":{"15":[19,20,21,49,22],"57":[19,20,21,49,22],"63":[19,20,21,49,22],"67":[19,20,21,49,22],"75":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/workflow-loop/index.ts":{"61":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/workflow-loop/remediation.ts":{"11":[19,20,48,21,49,22],"22":[19,20,48,21,49,22],"29":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/workflow-loop/render-claim.ts":{"11":[19,20,48,21,49,22],"16":[19,20,48,21,49,22],"47":[19,20,48,21,49,22],"55":[19,20,48,21,49,22],"75":[19,20,48,21,49,22],"87":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/workflow-loop/runtime.ts":{"10":[19,20,48,21,49,22],"29":[19,20,48,21,49,22],"31":[19,20,48,21,49,22],"46":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/workflow-loop/setup-verification-policy.ts":{"8":[19,20,48,21,49,22,50],"14":[19,20,48,21,49,22,50],"19":[19,20,48,21,49,22,50],"33":[19,20,48,21,49,22,50],"69":[19,20,48,21,49,22,50],"78":[19,20,48,21,49,22,50]},"packages/@n8n/instance-ai/src/workflow-loop/verification-obligation.ts":{"49":[19,20,48,21,49,22,50],"70":[19,20,48,21,49,22,50],"84":[19,20,48,21,49,22,50],"88":[19,20,48,21,49,22,50],"99":[19,20,48,21,49,22,50],"144":[19,20,48,21,49,22,50],"153":[19,20,48,21,49,22,50],"221":[19,20,48,21,49,22,50],"225":[19,20,48,21,49,22,50],"268":[19,20,48,21,49,22,50],"280":[19,20,48,21,49,22,50]},"packages/@n8n/instance-ai/src/workflow-loop/verification-progress.ts":{"8":[19,20,48,21,49,22],"15":[19,20,48,21,49,22],"16":[19,20,48,21,49,22],"17":[19,20,48,21,49,22],"22":[19,20,48,21,49,22],"23":[19,20,48,21,49,22],"25":[19,20,48,21,49,22],"26":[19,20,48,21,49,22],"30":[19,20,48,21,49,22],"38":[19,20,48,21,49,22],"40":[19,20,48,21,49,22],"43":[19,20,48,21,49,22],"47":[19,20,48,21,49,22],"56":[19,20,48,21,49,22],"57":[19,20,48,21,49,22],"58":[19,20,48,21,49,22],"61":[19,20,48,21,49,22],"62":[19,20,48,21,49,22],"67":[19,20,48,21,49,22],"68":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/workflow-loop/workflow-loop-controller.ts":{"38":[19,20,48,21,49,22],"66":[19,20,48,21,49,22],"230":[19,20,48,21,49,22],"397":[19,20,48,21,49,22],"487":[19,20,48,21,49,22],"491":[19,20,48,21,49,22],"495":[19,20,48,21,49,22],"506":[19,20,48,21,49,22],"522":[19,20,48,21,49,22],"537":[19,20,48,21,49,22],"539":[19,20,48,21,49,22],"544":[19,20,48,21,49,22],"549":[19,20,48,21,49,22],"564":[19,20,48,21,49,22],"567":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/workflow-loop/workflow-loop-state.ts":{"47":[19,20,48,21,49,22],"57":[19,20,48,21,49,22],"63":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/workflow-loop/workflow-task-service.ts":{"23":[19,20,48,21,49,22],"34":[19,20,48,21,49,22],"41":[19,20,48,21,49,22],"45":[19,20,48,21,49,22],"49":[19,20,48,21,49,22],"54":[19,20,48,21,49,22],"59":[19,20,48,21,49,22],"60":[19,20,48,21,49,22],"61":[19,20,48,21,49,22],"66":[19,20,48,21,49,22],"71":[19,20,48,21,49,22],"75":[19,20,48,21,49,22],"82":[19,20,48,21,49,22],"87":[19,20,48,21,49,22],"122":[19,20,48,21,49,22],"127":[19,20,48,21,49,22],"152":[19,20,48,21,49,22],"158":[19,20,48,21,49,22],"167":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/workspace/builder-templates-service.ts":{"144":[19,20,48,21,49,22],"158":[19,20,48,21,49,22],"162":[19,20,48,21,49,22],"166":[19,20,48,21,49,22],"171":[19,20,48,21,49,22],"194":[19,20,48,21,49,22],"202":[19,20,48,21,49,22],"213":[19,20,48,21,49,22],"221":[19,20,48,21,49,22],"226":[19,20,48,21,49,22],"235":[19,20,48,21,49,22],"280":[19,20,48,21,49,22],"289":[19,20,48,21,49,22],"298":[19,20,48,21,49,22],"308":[19,20,48,21,49,22],"344":[19,20,48,21,49,22],"366":[19,20,48,21,49,22],"446":[19,20,48,21,49,22],"479":[19,20,48,21,49,22],"511":[19,20,48,21,49,22],"517":[19,20,48,21,49,22],"526":[19,20,48,21,49,22],"535":[19,20,48,21,49,22],"541":[19,20,48,21,49,22],"546":[19,20,48,21,49,22],"561":[19,20,48,21,49,22],"569":[19,20,48,21,49,22],"586":[19,20,48,21,49,22],"603":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/workspace/compute-workspace-content-hash.ts":{"4":[19,20,48,21,49,22],"6":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/workspace/create-workspace.ts":{"38":[19,20,21,49,22],"39":[19,20,21,49,22],"40":[19,20,21,49,22],"41":[19,20,21,49,22],"45":[19,20,21,49,22],"49":[19,20,21,49,22],"67":[19,20,21,49,22],"79":[19,20,21,49,22],"162":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/workspace/lazy-runtime-workspace.ts":{"53":[19,20,48,21,49,22],"70":[19,20,48,21,49,22],"71":[19,20,48,21,49,22],"83":[19,20,48,21,49,22],"85":[19,20,48,21,49,22],"89":[19,20,48,21,49,22],"94":[19,20,48,21,49,22],"98":[19,20,48,21,49,22],"100":[19,20,48,21,49,22],"104":[19,20,48,21,49,22],"118":[19,20,48,21,49,22],"122":[19,20,48,21,49,22],"128":[19,20,48,21,49,22],"140":[19,20,48,21,49,22],"149":[19,20,48,21,49,22],"158":[19,20,48,21,49,22],"167":[19,20,48,21,49,22],"180":[19,20,48,21,49,22],"185":[19,20,48,21,49,22],"188":[19,20,48,21,49,22],"193":[19,20,48,21,49,22],"197":[19,20,48,21,49,22],"201":[19,20,48,21,49,22],"207":[19,20,48,21,49,22],"211":[19,20,48,21,49,22],"228":[19,20,48,21,49,22],"234":[19,20,48,21,49,22],"236":[19,20,48,21,49,22],"240":[19,20,48,21,49,22],"247":[19,20,48,21,49,22],"253":[19,20,48,21,49,22],"260":[19,20,48,21,49,22],"266":[19,20,48,21,49,22],"270":[19,20,48,21,49,22],"276":[19,20,48,21,49,22],"286":[19,20,48,21,49,22],"292":[19,20,48,21,49,22],"302":[19,20,48,21,49,22],"308":[19,20,48,21,49,22],"312":[19,20,48,21,49,22],"318":[19,20,48,21,49,22],"322":[19,20,48,21,49,22],"328":[19,20,48,21,49,22],"332":[19,20,48,21,49,22],"336":[19,20,48,21,49,22],"340":[19,20,48,21,49,22],"342":[19,20,48,21,49,22],"349":[19,20,48,21,49,22],"360":[19,20,48,21,49,22],"365":[19,20,48,21,49,22],"368":[19,20,48,21,49,22],"373":[19,20,48,21,49,22],"379":[19,20,48,21,49,22],"386":[19,20,48,21,49,22],"390":[19,20,48,21,49,22],"408":[19,20,48,21,49,22],"415":[19,20,48,21,49,22],"417":[19,20,48,21,49,22],"426":[19,20,48,21,49,22],"441":[19,20,48,21,49,22],"442":[19,20,48,21,49,22],"447":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/workspace/pack-workspace-sdk.ts":{"76":[19,20,21,49,22],"84":[19,20,21,49,22],"143":[19,20,21,49,22],"175":[19,20,21,49,22],"194":[19,20,21,49,22],"202":[19,20,21,49,22],"235":[19,20,21,49,22],"261":[19,20,21,49,22],"266":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/workspace/prebaked-workspace-bundle.ts":{"31":[19,20,21,119,49,22],"41":[19,20,21,119,49,22],"45":[19,20,21,119,49,22],"85":[19,20,21,119,49,22],"88":[19,20,21,119,49,22],"97":[19,20,21,119,49,22],"126":[19,20,21,119,49,22],"134":[19,20,21,119,49,22],"141":[19,20,21,119,49,22],"147":[19,20,21,119,49,22]},"packages/@n8n/instance-ai/src/workspace/sandbox-fs.ts":{"61":[19,20,48,21,49,22,50],"65":[19,20,48,21,49,22,50],"67":[19,20,48,21,49,22,50],"68":[19,20,48,21,49,22,50],"72":[19,20,48,21,49,22,50],"81":[19,20,48,21,49,22,50],"87":[19,20,48,21,49,22,50],"110":[19,20,48,21,49,22,50],"124":[19,20,48,21,49,22,50],"139":[19,20,48,21,49,22,50],"160":[19,20,48,21,49,22,50],"172":[19,20,48,21,49,22,50],"174":[19,20,48,21,49,22,50],"175":[19,20,48,21,49,22,50],"225":[19,20,48,21,49,22,50],"235":[19,20,48,21,49,22,50],"239":[19,20,48,21,49,22,50],"241":[19,20,48,21,49,22,50],"258":[19,20,48,21,49,22,50]},"packages/@n8n/instance-ai/src/workspace/sandbox-setup.ts":{"74":[19,20,48,21,49,22],"83":[19,20,48,21,49,22],"96":[19,20,48,21,49,22],"141":[19,20,48,21,49,22],"181":[19,20,48,21,49,22],"197":[19,20,48,21,49,22],"238":[19,20,48,21,49,22],"245":[19,20,48,21,49,22],"252":[19,20,48,21,49,22],"276":[19,20,48,21,49,22],"295":[19,20,48,21,49,22],"337":[19,20,48,21,49,22],"354":[19,20,48,21,49,22],"365":[19,20,48,21,49,22],"368":[19,20,48,21,49,22],"374":[19,20,48,21,49,22],"380":[19,20,48,21,49,22],"393":[19,20,48,21,49,22],"409":[19,20,48,21,49,22],"430":[19,20,48,21,49,22],"443":[19,20,48,21,49,22],"453":[19,20,48,21,49,22],"470":[19,20,48,21,49,22],"475":[19,20,48,21,49,22],"494":[19,20,48,21,49,22],"500":[19,20,48,21,49,22],"501":[19,20,48,21,49,22],"504":[19,20,48,21,49,22],"511":[19,20,48,21,49,22],"530":[19,20,48,21,49,22],"539":[19,20,48,21,49,22],"544":[19,20,48,21,49,22],"548":[19,20,48,21,49,22],"579":[19,20,48,21,49,22],"585":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/workspace/sandbox-typescript.ts":{"27":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/workspace/snapshot-image-context.ts":{"18":[19,20,21,49,22],"30":[19,20,21,49,22],"48":[19,20,21,49,22],"62":[19,20,21,49,22],"68":[19,20,21,49,22],"78":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/workspace/snapshot-manager.ts":{"89":[19,20,21,49,22],"103":[19,20,21,49,22],"114":[19,20,21,49,22],"126":[19,20,21,49,22],"138":[19,20,21,49,22],"148":[19,20,21,49,22],"152":[19,20,21,49,22],"166":[19,20,21,49,22],"176":[19,20,21,49,22],"189":[19,20,21,49,22],"198":[19,20,21,49,22],"203":[19,20,21,49,22],"230":[19,20,21,49,22],"261":[19,20,21,49,22],"323":[19,20,21,49,22],"383":[19,20,21,49,22],"420":[19,20,21,49,22],"457":[19,20,21,49,22],"502":[19,20,21,49,22],"599":[19,20,21,49,22],"624":[19,20,21,49,22],"629":[19,20,21,49,22],"631":[19,20,21,49,22],"633":[19,20,21,49,22],"638":[19,20,21,49,22],"659":[19,20,21,49,22],"663":[19,20,21,49,22],"677":[19,20,21,49,22],"707":[19,20,21,49,22],"712":[19,20,21,49,22],"719":[19,20,21,49,22],"728":[19,20,21,49,22],"730":[19,20,21,49,22],"738":[19,20,21,49,22],"747":[19,20,21,49,22],"752":[19,20,21,49,22],"762":[19,20,21,49,22],"767":[19,20,21,49,22],"785":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/workspace/template-telemetry.ts":{"59":[19,20,48,21,49,22],"74":[19,20,48,21,49,22],"78":[19,20,48,21,49,22],"88":[19,20,48,21,49,22],"97":[19,20,48,21,49,22],"125":[19,20,48,21,49,22],"144":[19,20,48,21,49,22],"149":[19,20,48,21,49,22],"159":[19,20,48,21,49,22],"166":[19,20,48,21,49,22],"176":[19,20,48,21,49,22],"187":[19,20,48,21,49,22],"195":[19,20,48,21,49,22],"200":[19,20,48,21,49,22],"224":[19,20,48,21,49,22],"229":[19,20,48,21,49,22],"260":[19,20,48,21,49,22],"279":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/workspace/workspace-file-content.ts":{"2":[19,20,21,49,22],"7":[19,20,21,49,22]},"packages/@n8n/instance-ai/src/workspace/workspace-files.ts":{"39":[19,20,48,21,49,22],"43":[19,20,48,21,49,22],"47":[19,20,48,21,49,22],"57":[19,20,48,21,49,22],"67":[19,20,48,21,49,22],"71":[19,20,48,21,49,22],"79":[19,20,48,21,49,22],"129":[19,20,48,21,49,22],"138":[19,20,48,21,49,22],"145":[19,20,48,21,49,22],"160":[19,20,48,21,49,22],"192":[19,20,48,21,49,22],"203":[19,20,48,21,49,22],"206":[19,20,48,21,49,22],"208":[19,20,48,21,49,22]},"packages/@n8n/instance-ai/src/workspace/workspace-manifest.ts":{"17":[19,20,21,119,49,22]},"packages/@n8n/instance-ai/src/workspace/workspace-paths.ts":{"12":[19,20,48,21,49,22],"21":[19,20,48,21,49,22],"31":[19,20,48,21,49,22],"39":[19,20,48,21,49,22],"50":[19,20,48,21,49,22]},"packages/@n8n/telemetry/src/index.ts":{"3":[19,20,48,21,206,96,49,22],"14":[19,20,48,21,206,96,49,22],"16":[19,20,48,21,206,96,49,22]},"packages/@n8n/telemetry/src/redaction.ts":{"57":[46,19,20,48,21,49,22],"81":[46,19,20,48,21,49,22],"88":[46,19,20,48,21,49,22],"92":[46,19,20,48,21,49,22],"109":[46,19,20,48,21,49,22],"135":[46,19,20,48,21,49,22]},"packages/@n8n/utils/src/json/to-json-value.ts":{"16":[26,19,20,48,49,22],"49":[26,19,20,48,49,22]},"packages/@n8n/utils/src/lazy-import.ts":{"15":[33,19,20,21,49,22,207,208]},"packages/@n8n/utils/src/redaction/redact-text.ts":{"40":[26,46,10,19,20,48,21,49,22,12],"54":[26,46,10,19,20,48,21,49,22,12],"55":[26,46,10,19,20,48,21,49,22,12],"64":[26,46,10,19,20,21,49,22,12],"84":[26,46,10,19,20,21,49,22,12],"95":[26,46,10,19,20,21,49,22,12],"101":[26,46,10,19,20,21,49,22,12],"106":[26,46,10,19,20,21,49,22,12],"119":[26,10,19,20,21,49,22,12],"163":[26,10,19,20,21,49,22,12],"171":[26,10,19,20,21,49,22,12],"198":[26,10,19,20,21,49,22,12]},"packages/@n8n/utils/src/redaction/sensitive-key.ts":{"7":[26,10,19,20,21,49,22,12]},"packages/@n8n/utils/src/scrub-secrets.ts":{"123":[26,46,19,20,21,49,22]},"packages/@n8n/workflow-sdk/src/codegen/index.ts":{"66":[19,20,48,21,49,22,50,207,208],"67":[19,20,48,21,49,22,50,207,208],"69":[19,20,48,21,49,22,50,207,208],"87":[19,20,48,21,49,22,50,207,208],"114":[19,20,48,21,49,22,50,207,208]},"packages/@n8n/workflow-sdk/src/index.ts":{"114":[19,20,48,21,49,22,50,207,208],"127":[19,20,48,21,49,22,50,207,208],"194":[19,20,48,21,49,22,50,207,208],"199":[19,20,48,21,49,22,50,207,208],"276":[19,20,48,21,49,22,50,207,208]},"packages/@n8n/workflow-sdk/src/prompts/sdk-reference/index.ts":{"3":[19,20,21,49,22]},"packages/@n8n/workflow-sdk/src/validation/node-parameter-schema/schema-validator.ts":{"45":[19,20,48,21,49,22,50,207,208],"53":[19,20,48,21,49,22,50,207,208],"66":[19,20,48,21,49,22,50,207,208],"78":[19,20,48,21,49,22,50,207,208],"92":[19,20,48,21,49,22,50,207,208],"107":[19,20,48,21,49,22,50,207,208],"126":[19,20,48,21,49,22,50,207,208],"152":[19,20,48,21,49,22,50,207,208],"173":[19,20,48,21,49,22,50,207,208],"193":[19,20,48,21,49,22,50,207,208],"225":[19,20,48,21,49,22,50,207,208],"234":[19,20,48,21,49,22,50,207,208],"254":[19,20,48,21,49,22,50,207,208],"308":[19,20,48,21,49,22,50,207,208],"336":[19,20,48,21,49,22,50,207,208],"352":[19,20,48,21,49,22,50,207,208],"365":[19,20,48,21,49,22,50,207,208],"387":[19,20,48,21,49,22,50,207,208],"411":[19,20,48,21,49,22,50,207,208],"412":[19,20,48,21,49,22,50,207,208],"422":[19,20,48,21,49,22,50,207,208],"423":[19,20,48,21,49,22,50,207,208],"435":[19,20,48,21,49,22,50,207,208],"480":[19,20,48,21,49,22,50,207,208],"505":[19,20,48,21,49,22,50,207,208],"517":[19,20,48,21,49,22,50,207,208],"519":[19,20,48,21,49,22,50,207,208],"526":[19,20,48,21,49,22,50,207,208],"529":[19,20,48,21,49,22,50,207,208],"532":[19,20,48,21,49,22,50,207,208],"585":[19,20,48,21,49,22,50,207,208],"593":[19,20,48,21,49,22,50,207,208],"596":[19,20,48,21,49,22,50,207,208],"617":[19,20,48,21,49,22,50,207,208],"630":[19,20,48,21,49,22,50,207,208],"633":[19,20,48,21,49,22,50,207,208],"635":[19,20,48,21,49,22,50,207,208],"654":[19,20,48,21,49,22,50,207,208],"663":[19,20,48,21,49,22,50,207,208],"665":[19,20,48,21,49,22,50,207,208],"673":[19,20,48,21,49,22,50,207,208],"688":[19,20,48,21,49,22,50,207,208],"703":[19,20,48,21,49,22,50,207,208],"705":[19,20,48,21,49,22,50,207,208],"725":[19,20,48,21,49,22,50,207,208],"745":[19,20,48,21,49,22,50,207,208],"746":[19,20,48,21,49,22,50,207,208],"759":[19,20,48,21,49,22,50,207,208],"776":[19,20,48,21,49,22,50,207,208],"802":[19,20,48,21,49,22,50,207,208],"803":[19,20,48,21,49,22,50,207,208]},"packages/cli/src/credentials/instance-credential-broker.ts":{"28":[26,107,19,20,21,206,96,49,22],"35":[26,107,19,20,21,206,96,49,22],"39":[26,107,19,20,21,206,96,49,22],"44":[26,107,19,20,21,206,96,49,22],"62":[26,107,19,20,21,206,96,49,22],"67":[26,107,19,20,21,206,96,49,22],"75":[26,107,19,20,21,206,96,49,22],"103":[26,107,19,20,21,206,96,49,22]},"packages/cli/src/modules/agents/instance-ai-agent-context.adapter.ts":{"35":[19,20,21,49,22],"51":[19,20,21,49,22],"53":[19,20,21,49,22],"68":[19,20,21,49,22],"78":[19,20,21,49,22],"89":[19,20,21,49,22],"92":[19,20,21,49,22],"109":[19,20,21,49,22],"117":[19,20,21,49,22],"147":[19,20,21,49,22],"185":[19,20,21,49,22],"189":[19,20,21,49,22],"207":[19,20,21,49,22],"211":[19,20,21,49,22]},"packages/cli/src/modules/agents/instance-ai-builder-delegate.adapter.ts":{"46":[19,20,117,21,49,22],"55":[19,20,117,21,49,22],"60":[19,20,117,21,49,22],"64":[19,20,117,21,49,22],"69":[19,20,117,21,49,22],"97":[19,20,117,21,49,22],"108":[19,20,117,21,49,22],"128":[19,20,117,21,49,22],"143":[19,20,117,21,49,22],"150":[19,20,117,21,49,22],"165":[19,20,117,21,49,22],"179":[19,20,117,21,49,22],"187":[19,20,117,21,49,22],"202":[19,20,117,21,49,22],"210":[19,20,117,21,49,22],"218":[19,20,117,21,49,22],"219":[19,20,117,21,49,22],"222":[19,20,117,21,49,22],"227":[19,20,117,21,49,22],"231":[19,20,117,21,49,22],"236":[19,20,117,21,49,22],"259":[19,20,117,21,49,22]},"packages/cli/src/modules/agents/model-stream-stall-options.ts":{"16":[26,19,20,21,49,22],"29":[26,19,20,21,49,22]},"packages/cli/src/modules/instance-ai/browser/composite-local-mcp-server.ts":{"4":[19,20,21,49,22],"7":[19,20,21,49,22],"25":[19,20,21,49,22],"26":[19,20,21,49,22],"29":[19,20,21,49,22],"33":[19,20,21,49,22],"37":[19,20,21,49,22],"43":[19,20,21,49,22],"58":[19,20,21,49,22],"59":[19,20,21,49,22],"62":[19,20,21,49,22]},"packages/cli/src/modules/instance-ai/browser/instance-ai-browser-session.service.ts":{"66":[107,19,20,21,96,49,22],"78":[107,19,20,21,96,49,22],"96":[107,19,20,21,96,49,22],"105":[107,19,20,21,96,49,22],"114":[107,19,20,21,96,49,22],"119":[107,19,20,21,96,49,22],"123":[107,19,20,21,96,49,22],"132":[107,19,20,21,96,49,22],"143":[107,19,20,21,96,49,22],"158":[107,19,20,21,96,49,22],"167":[107,19,20,21,96,49,22],"174":[107,19,20,21,96,49,22],"175":[107,19,20,21,96,49,22],"190":[107,19,20,21,96,49,22],"213":[107,19,20,21,96,49,22],"226":[107,19,20,21,96,49,22],"250":[107,19,20,21,96,49,22],"262":[107,19,20,21,96,49,22],"277":[107,19,20,21,96,49,22],"282":[107,19,20,21,96,49,22],"294":[107,19,20,21,96,49,22],"305":[107,19,20,21,96,49,22],"321":[107,19,20,21,96,49,22],"326":[107,19,20,21,96,49,22],"330":[107,19,20,21,96,49,22],"337":[107,19,20,21,96,49,22],"340":[107,19,20,21,96,49,22],"345":[107,19,20,21,96,49,22],"348":[107,19,20,21,96,49,22]},"packages/cli/src/modules/instance-ai/computer-use-availability.ts":{"8":[19,20,21,49,22],"11":[19,20,21,49,22],"14":[19,20,21,49,22],"35":[19,20,21,49,22],"62":[19,20,21,49,22]},"packages/cli/src/modules/instance-ai/eval/thread-credential-allowlist.service.ts":{"10":[19,20,117,21,49,22],"17":[19,20,117,21,49,22],"25":[19,20,117,21,49,22],"29":[19,20,117,21,49,22],"40":[19,20,117,21,49,22],"44":[19,20,117,21,49,22]},"packages/cli/src/modules/instance-ai/event-bus/durable-event-log.ts":{"70":[19,20,116,117,21,49,22],"74":[19,20,116,117,21,49,22],"76":[19,20,116,117,21,49,22],"139":[19,20,116,117,21,49,22],"148":[19,20,116,117,21,49,22],"159":[19,20,116,117,21,49,22],"162":[19,20,116,117,21,49,22],"164":[19,20,116,117,21,49,22],"183":[19,20,116,117,21,49,22],"232":[19,20,116,117,21,49,22],"244":[19,20,116,117,21,49,22],"248":[19,20,116,117,21,49,22],"253":[19,20,116,117,21,49,22],"259":[19,20,116,117,21,49,22],"269":[19,20,116,117,21,49,22],"281":[19,20,116,117,21,49,22],"302":[19,20,116,117,21,49,22],"317":[19,20,116,117,21,49,22],"332":[19,20,116,117,21,49,22],"344":[19,20,116,117,21,49,22],"357":[19,20,116,117,21,49,22],"362":[19,20,116,117,21,49,22],"372":[19,20,116,117,21,49,22],"390":[19,20,116,117,21,49,22],"392":[19,20,116,117,21,49,22],"418":[19,20,116,117,21,49,22],"421":[19,20,116,117,21,49,22],"500":[19,20,116,117,21,49,22],"510":[19,20,116,117,21,49,22],"535":[19,20,116,117,21,49,22],"611":[19,20,116,117,21,49,22],"625":[19,20,116,117,21,49,22],"651":[19,20,116,117,21,49,22],"667":[19,20,116,117,21,49,22],"672":[19,20,116,117,21,49,22],"697":[19,20,116,117,21,49,22],"710":[19,20,116,117,21,49,22],"745":[19,20,116,117,21,49,22],"753":[19,20,116,117,21,49,22],"767":[19,20,116,117,21,49,22]},"packages/cli/src/modules/instance-ai/event-bus/durable-log-metrics.ts":{"61":[19,20,116,117,21,49,22],"63":[19,20,116,117,21,49,22],"70":[19,20,116,117,21,49,22],"77":[19,20,116,117,21,49,22],"82":[19,20,116,117,21,49,22],"87":[19,20,116,117,21,49,22],"98":[19,20,116,117,21,49,22],"105":[19,20,116,117,21,49,22],"109":[19,20,116,117,21,49,22],"113":[19,20,116,117,21,49,22]},"packages/cli/src/modules/instance-ai/event-bus/in-process-event-bus.ts":{"24":[19,20,117,21,49,22],"44":[19,20,117,21,49,22],"51":[19,20,117,21,49,22],"59":[19,20,117,21,49,22],"73":[19,20,117,21,49,22],"89":[19,20,117,21,49,22],"104":[19,20,117,21,49,22],"111":[19,20,117,21,49,22],"113":[19,20,117,21,49,22],"117":[19,20,117,21,49,22],"122":[19,20,117,21,49,22],"128":[19,20,117,21,49,22]},"packages/cli/src/modules/instance-ai/filesystem/local-gateway-registry.ts":{"27":[107,19,20,21,206,96,49,22],"34":[107,19,20,21,206,96,49,22],"42":[107,19,20,21,206,96,49,22],"56":[107,19,20,21,206,96,49,22],"72":[107,19,20,21,206,96,49,22],"86":[107,19,20,21,206,96,49,22],"98":[107,19,20,21,206,96,49,22],"110":[107,19,20,21,206,96,49,22],"124":[107,19,20,21,206,96,49,22],"129":[107,19,20,21,206,96,49,22],"137":[107,19,20,21,206,96,49,22],"142":[107,19,20,21,206,96,49,22],"147":[107,19,20,21,206,96,49,22],"155":[107,19,20,21,206,96,49,22],"165":[107,19,20,21,206,96,49,22],"170":[107,19,20,21,206,96,49,22],"193":[107,19,20,21,206,96,49,22],"198":[107,19,20,21,206,96,49,22],"208":[107,19,20,21,206,96,49,22],"216":[107,19,20,21,206,96,49,22],"218":[107,19,20,21,206,96,49,22],"219":[107,19,20,21,206,96,49,22],"223":[107,19,20,21,206,96,49,22]},"packages/cli/src/modules/instance-ai/instance-ai-credit-display.ts":{"26":[107,19,20,21,96,49,22]},"packages/cli/src/modules/instance-ai/instance-ai-credit.service.ts":{"57":[107,19,20,21,96,49,22],"71":[107,19,20,21,96,49,22],"100":[107,19,20,21,96,49,22],"146":[107,19,20,21,96,49,22],"178":[107,19,20,21,96,49,22],"315":[107,19,20,21,96,49,22],"333":[107,19,20,21,96,49,22],"349":[107,19,20,21,96,49,22],"368":[107,19,20,21,96,49,22],"399":[107,19,20,21,96,49,22],"406":[107,19,20,21,96,49,22],"430":[107,19,20,21,96,49,22]},"packages/cli/src/modules/instance-ai/instance-ai-error-reporter.service.ts":{"25":[19,20,21,118,119,49,22,122],"37":[19,20,21,118,119,49,22,122],"51":[19,20,21,118,119,49,22,122],"58":[19,20,21,118,119,49,22,122],"64":[19,20,21,118,119,49,22,122],"69":[19,20,21,118,119,49,22,122],"73":[19,20,21,118,119,49,22,122],"123":[19,20,21,118,119,49,22,122],"137":[19,20,21,118,119,49,22,122]},"packages/cli/src/modules/instance-ai/instance-ai-gateway.service.ts":{"26":[107,19,20,21,206,96,49,22],"36":[107,19,20,21,206,96,49,22],"42":[107,19,20,21,206,96,49,22],"46":[107,19,20,21,206,96,49,22],"50":[107,19,20,21,206,96,49,22],"54":[107,19,20,21,206,96,49,22],"58":[107,19,20,21,206,96,49,22],"62":[107,19,20,21,206,96,49,22],"66":[107,19,20,21,206,96,49,22],"70":[107,19,20,21,206,96,49,22],"75":[107,19,20,21,206,96,49,22],"79":[107,19,20,21,206,96,49,22],"83":[107,19,20,21,206,96,49,22],"87":[107,19,20,21,206,96,49,22],"96":[107,19,20,21,206,96,49,22],"101":[107,19,20,21,206,96,49,22],"108":[107,19,20,21,206,96,49,22],"112":[107,19,20,21,206,96,49,22],"122":[107,19,20,21,206,96,49,22],"126":[107,19,20,21,206,96,49,22]},"packages/cli/src/modules/instance-ai/instance-ai-model.service.ts":{"40":[107,19,20,21,96,49,22],"47":[107,19,20,21,96,49,22],"65":[107,19,20,21,96,49,22],"69":[107,19,20,21,96,49,22],"90":[107,19,20,21,96,49,22],"115":[107,19,20,21,96,49,22],"140":[107,19,20,21,96,49,22],"147":[107,19,20,21,96,49,22]},"packages/cli/src/modules/instance-ai/instance-ai-setup-telemetry.service.ts":{"41":[19,20,21,206,96,49,22],"63":[19,20,21,206,96,49,22],"76":[19,20,21,206,96,49,22],"87":[19,20,21,206,96,49,22],"91":[19,20,21,206,96,49,22],"98":[19,20,21,206,96,49,22],"102":[19,20,21,206,96,49,22],"110":[19,20,21,206,96,49,22],"121":[19,20,21,206,96,49,22],"127":[19,20,21,206,96,49,22],"148":[19,20,21,206,96,49,22],"175":[19,20,21,206,96,49,22],"186":[19,20,21,206,96,49,22],"209":[19,20,21,206,96,49,22],"227":[19,20,21,206,96,49,22],"250":[19,20,21,206,96,49,22],"278":[19,20,21,206,96,49,22]},"packages/cli/src/modules/instance-ai/instance-ai-temporary-workflow.service.ts":{"32":[19,20,117,21,22],"48":[19,20,117,21,22],"72":[19,20,117,21,22],"85":[19,20,117,21,22],"142":[19,20,117,21,22],"146":[19,20,117,21,22]},"packages/cli/src/modules/instance-ai/instance-ai-terminal-outcome.service.ts":{"33":[19,20,116,48,21,49,22],"131":[19,20,116,48,21,49,22],"143":[19,20,116,48,21,49,22],"176":[19,20,116,48,21,49,22],"196":[19,20,116,48,21,49,22],"209":[19,20,116,48,21,49,22],"263":[19,20,116,48,21,49,22],"268":[19,20,116,48,21,49,22],"298":[19,20,116,48,21,49,22],"322":[19,20,116,48,21,49,22],"325":[19,20,116,48,21,49,22],"333":[19,20,116,48,21,49,22],"339":[19,20,116,48,21,49,22],"362":[19,20,116,48,21,49,22],"393":[19,20,116,48,21,49,22],"397":[19,20,116,48,21,49,22],"418":[19,20,116,48,21,49,22]},"packages/cli/src/modules/instance-ai/instance-ai-test.controller.ts":{"18":[19,20,116,21,206,49,22],"28":[19,20,116,21,206,49,22],"40":[19,20,116,21,206,49,22],"46":[19,20,116,21,206,49,22],"52":[19,20,116,21,206,49,22],"66":[19,20,116,21,206,49,22],"73":[19,20,116,21,206,49,22],"92":[19,20,116,21,206,49,22],"119":[19,20,116,21,206,49,22]},"packages/cli/src/modules/instance-ai/instance-ai-thread-tabs.service.ts":{"18":[19,20,48,21,49,22],"27":[19,20,48,21,49,22],"31":[19,20,48,21,49,22],"46":[19,20,48,21,49,22],"59":[19,20,48,21,49,22],"61":[19,20,48,21,49,22],"65":[19,20,48,21,49,22],"68":[19,20,48,21,49,22],"84":[19,20,48,21,49,22],"91":[19,20,48,21,49,22],"96":[19,20,48,21,49,22],"109":[19,20,48,21,49,22],"115":[19,20,48,21,49,22],"121":[19,20,48,21,49,22],"137":[19,20,48,21,49,22]},"packages/cli/src/modules/instance-ai/instance-ai.adapter.service.ts":{"255":[19,20,48,21,49,22,50],"287":[19,20,48,21,49,22,50],"300":[19,20,48,21,49,22,50],"310":[19,20,48,21,49,22,50],"342":[19,20,48,21,49,22,50],"355":[19,20,48,21,49,22,50],"393":[19,20,48,21,49,22,50],"398":[19,20,48,21,49,22,50],"402":[19,20,48,21,49,22,50],"408":[19,20,48,21,49,22,50],"468":[19,20,48,21,49,22,50],"473":[19,20,48,21,49,22,50],"624":[19,20,48,21,49,22,50],"642":[19,20,48,21,49,22,50],"667":[19,20,48,21,49,22,50],"693":[19,20,48,21,49,22,50],"703":[19,20,48,21,49,22,50],"772":[19,20,48,21,49,22,50],"782":[19,20,48,21,49,22,50],"791":[19,20,48,21,49,22,50],"796":[19,20,48,21,49,22,50],"801":[19,20,48,21,49,22,50],"817":[19,20,48,21,49,22,50],"831":[19,20,48,21,49,22,50],"835":[19,20,48,21,49,22,50],"837":[19,20,48,21,49,22,50],"838":[19,20,48,21,49,22,50],"842":[19,20,48,21,49,22,50],"848":[19,20,48,21,49,22,50],"853":[19,20,48,21,49,22,50],"854":[19,20,48,21,49,22,50],"856":[19,20,48,21,49,22,50],"859":[19,20,48,21,49,22,50],"864":[19,20,48,21,49,22,50],"869":[19,20,48,21,49,22,50],"872":[19,20,48,21,49,22,50],"877":[19,20,48,21,49,22,50],"885":[19,20,48,21,49,22,50],"907":[19,20,48,21,49,22,50],"911":[19,20,48,21,49,22,50],"916":[19,20,48,21,49,22,50],"933":[19,20,48,21,49,22,50],"944":[19,20,48,21,49,22,50],"947":[19,20,48,21,49,22,50],"954":[19,20,48,21,49,22,50],"958":[19,20,48,21,49,22,50],"979":[19,20,48,21,49,22,50],"988":[19,20,48,21,49,22,50],"996":[19,20,48,21,49,22,50],"1000":[19,20,48,21,49,22,50],"1003":[19,20,48,21,49,22,50],"1007":[19,20,48,21,49,22,50],"1014":[19,20,48,21,49,22,50],"1020":[19,20,48,21,49,22,50],"1033":[19,20,48,21,49,22,50],"1073":[19,20,48,21,49,22,50],"1084":[19,20,48,21,49,22,50],"1096":[19,20,48,21,49,22,50],"1109":[19,20,48,21,49,22,50],"1131":[19,20,48,21,49,22,50],"1152":[19,20,48,21,49,22,50],"1195":[19,20,48,21,49,22,50],"1197":[19,20,48,21,49,22,50],"1201":[19,20,48,21,49,22,50],"1216":[19,20,48,21,49,22,50],"1251":[19,20,48,21,49,22,50],"1264":[19,20,48,21,49,22,50],"1276":[19,20,48,21,49,22,50],"1298":[19,20,48,21,49,22,50],"1319":[19,20,48,21,49,22,50],"1394":[19,20,48,21,49,22,50],"1402":[19,20,48,21,49,22,50],"1407":[19,20,48,21,49,22,50],"1415":[19,20,48,21,49,22,50],"1423":[19,20,48,21,49,22,50],"1424":[19,20,48,21,49,22,50],"1426":[19,20,48,21,49,22,50],"1439":[19,20,48,21,49,22,50],"1457":[19,20,48,21,49,22,50],"1485":[19,20,48,21,49,22,50],"1497":[19,20,48,21,49,22,50],"1507":[19,20,48,21,49,22,50],"1515":[19,20,48,21,49,22,50],"1526":[19,20,48,21,49,22,50],"1545":[19,20,48,21,49,22,50],"1575":[19,20,48,21,49,22,50],"1583":[19,20,48,21,49,22,50],"1593":[19,20,48,21,49,22,50],"1598":[19,20,48,21,49,22,50],"1604":[19,20,48,21,49,22,50],"1616":[19,20,48,21,49,22,50],"1628":[19,20,48,21,49,22,50],"1653":[19,20,48,21,49,22,50],"1680":[19,20,48,21,49,22,50],"1730":[19,20,48,21,49,22,50],"1816":[19,20,48,21,49,22,50],"1910":[19,20,48,21,49,22,50],"1923":[19,20,48,21,49,22,50],"1936":[19,20,48,21,49,22,50],"1956":[19,20,48,21,49,22,50],"1968":[19,20,48,21,49,22,50],"1991":[19,20,48,21,49,22,50],"2003":[19,20,48,21,49,22,50],"2022":[19,20,48,21,49,22,50],"2031":[19,20,48,21,49,22,50],"2053":[19,20,48,21,49,22,50],"2092":[19,20,48,21,49,22,50],"2105":[19,20,48,21,49,22,50],"2236":[19,20,48,21,49,22,50],"2256":[19,20,48,21,49,22,50],"2325":[19,20,48,21,49,22,50],"2346":[19,20,48,21,49,22,50],"2412":[19,20,48,21,49,22,50],"2439":[19,20,48,21,49,22,50],"2547":[19,20,48,21,49,22,50],"2567":[19,20,48,21,49,22,50],"2570":[19,20,48,21,49,22,50],"2575":[19,20,48,21,49,22,50],"2589":[19,20,48,21,49,22,50],"2647":[19,20,48,21,49,22,50],"2656":[19,20,48,21,49,22,50],"2665":[19,20,48,21,49,22,50],"2689":[19,20,48,21,49,22,50],"2694":[19,20,48,21,49,22,50],"2709":[19,20,48,21,49,22,50],"2734":[19,20,48,21,49,22,50],"2746":[19,20,48,21,49,22,50],"2749":[19,20,48,21,49,22,50],"2758":[19,20,48,21,49,22,50],"2760":[19,20,48,21,49,22,50],"2781":[19,20,48,21,49,22,50],"2784":[19,20,48,21,49,22,50],"2801":[19,20,48,21,49,22,50],"2810":[19,20,48,21,49,22,50],"2820":[19,20,48,21,49,22,50],"2824":[19,20,48,21,49,22,50],"2869":[19,20,48,21,49,22,50],"2873":[19,20,48,21,49,22,50],"2884":[19,20,48,21,49,22,50],"2908":[19,20,48,21,49,22,50],"2924":[19,20,48,21,49,22,50],"2926":[19,20,48,21,49,22,50],"2928":[19,20,48,21,49,22,50],"2943":[19,20,48,21,49,22,50],"2952":[19,20,48,21,49,22,50],"2955":[19,20,48,21,49,22,50],"2968":[19,20,48,21,49,22,50],"2982":[19,20,48,21,49,22,50],"2987":[19,20,48,21,49,22,50],"2994":[19,20,48,21,49,22,50],"3006":[19,20,48,21,49,22,50],"3050":[19,20,48,21,49,22,50],"3069":[19,20,48,21,49,22,50],"3083":[19,20,48,21,49,22,50],"3094":[19,20,48,21,49,22,50],"3140":[19,20,48,21,49,22,50],"3147":[19,20,48,21,49,22,50],"3156":[19,20,48,21,49,22,50],"3161":[19,20,48,21,49,22,50],"3183":[19,20,48,21,49,22,50],"3187":[19,20,48,21,49,22,50],"3192":[19,20,48,21,49,22,50],"3197":[19,20,48,21,49,22,50],"3199":[19,20,48,21,49,22,50],"3214":[19,20,48,21,49,22,50],"3222":[19,20,48,21,49,22,50],"3227":[19,20,48,21,49,22,50],"3232":[19,20,48,21,49,22,50],"3237":[19,20,48,21,49,22,50],"3249":[19,20,48,21,49,22,50],"3262":[19,20,48,21,49,22,50],"3270":[19,20,48,21,49,22,50],"3272":[19,20,48,21,49,22,50],"3289":[19,20,48,21,49,22,50],"3297":[19,20,48,21,49,22,50],"3303":[19,20,48,21,49,22,50],"3321":[19,20,48,21,49,22,50],"3331":[19,20,48,21,49,22,50],"3349":[19,20,48,21,49,22,50],"3356":[19,20,48,21,49,22,50],"3360":[19,20,48,21,49,22,50],"3367":[19,20,48,21,49,22,50],"3376":[19,20,48,21,49,22,50],"3382":[19,20,48,21,49,22,50],"3392":[19,20,48,21,49,22,50],"3401":[19,20,48,21,49,22,50],"3409":[19,20,48,21,49,22,50],"3418":[19,20,48,21,49,22,50],"3434":[19,20,48,21,49,22,50],"3444":[19,20,48,21,49,22,50],"3456":[19,20,48,21,49,22,50],"3469":[19,20,48,21,49,22,50],"3490":[19,20,48,21,49,22,50],"3511":[19,20,48,21,49,22,50],"3541":[19,20,48,21,49,22,50],"3557":[19,20,48,21,49,22,50],"3576":[19,20,48,21,49,22,50],"3609":[19,20,48,21,49,22,50],"3638":[19,20,48,21,49,22,50],"3653":[19,20,48,21,49,22,50],"3662":[19,20,48,21,49,22,50],"3677":[19,20,48,21,49,22,50],"3689":[19,20,48,21,49,22,50],"3706":[19,20,48,21,49,22,50],"3716":[19,20,48,21,49,22,50],"3720":[19,20,48,21,49,22,50],"3723":[19,20,48,21,49,22,50],"3725":[19,20,48,21,49,22,50],"3728":[19,20,48,21,49,22,50],"3730":[19,20,48,21,49,22,50],"3732":[19,20,48,21,49,22,50],"3733":[19,20,48,21,49,22,50],"3737":[19,20,48,21,49,22,50],"3743":[19,20,48,21,49,22,50],"3750":[19,20,48,21,49,22,50],"3754":[19,20,48,21,49,22,50],"3764":[19,20,48,21,49,22,50],"3771":[19,20,48,21,49,22,50],"3786":[19,20,48,21,49,22,50],"3789":[19,20,48,21,49,22,50],"3792":[19,20,48,21,49,22,50],"3796":[19,20,48,21,49,22,50],"3799":[19,20,48,21,49,22,50],"3853":[19,20,48,21,49,22,50],"3860":[19,20,48,21,49,22,50],"3868":[19,20,48,21,49,22,50],"3886":[19,20,48,21,49,22,50],"3895":[19,20,48,21,49,22,50],"3898":[19,20,48,21,49,22,50],"3904":[19,20,48,21,49,22,50],"3921":[19,20,48,21,49,22,50],"3926":[19,20,48,21,49,22,50],"3943":[19,20,48,21,49,22,50],"3949":[19,20,48,21,49,22,50],"3991":[19,20,48,21,49,22,50],"4008":[19,20,48,21,49,22,50],"4065":[19,20,48,21,49,22,50],"4066":[19,20,48,21,49,22,50],"4100":[19,20,48,21,49,22,50],"4103":[19,20,48,21,49,22,50],"4108":[19,20,48,21,49,22,50],"4119":[19,20,48,21,49,22,50],"4124":[19,20,48,21,49,22,50],"4130":[19,20,48,21,49,22,50],"4132":[19,20,48,21,49,22,50],"4143":[19,20,48,21,49,22,50],"4148":[19,20,48,21,49,22,50],"4153":[19,20,48,21,49,22,50],"4160":[19,20,48,21,49,22,50],"4178":[19,20,48,21,49,22,50],"4190":[19,20,48,21,49,22,50],"4206":[19,20,48,21,49,22,50],"4220":[19,20,48,21,49,22,50],"4241":[19,20,48,21,49,22,50],"4246":[19,20,48,21,49,22,50],"4249":[19,20,48,21,49,22,50],"4258":[19,20,48,21,49,22,50],"4287":[19,20,48,21,49,22,50],"4368":[19,20,48,21,49,22,50],"4374":[19,20,48,21,49,22,50],"4407":[19,20,48,21,49,22,50],"4414":[19,20,48,21,49,22,50],"4436":[19,20,48,21,49,22,50],"4449":[19,20,48,21,49,22,50],"4462":[19,20,48,21,49,22,50],"4494":[19,20,48,21,49,22,50],"4538":[19,20,48,21,49,22,50],"4547":[19,20,48,21,49,22,50],"4558":[19,20,48,21,49,22,50],"4580":[19,20,48,21,49,22,50],"4593":[19,20,48,21,49,22,50],"4607":[19,20,48,21,49,22,50],"4615":[19,20,48,21,49,22,50],"4623":[19,20,48,21,49,22,50],"4630":[19,20,48,21,49,22,50],"4655":[19,20,48,21,49,22,50],"4664":[19,20,48,21,49,22,50],"4665":[19,20,48,21,49,22,50],"4669":[19,20,48,21,49,22,50],"4672":[19,20,48,21,49,22,50],"4688":[19,20,48,21,49,22,50],"4714":[19,20,48,21,49,22,50],"4767":[19,20,48,21,49,22,50],"4770":[19,20,48,21,49,22,50],"4771":[19,20,48,21,49,22,50],"4781":[19,20,48,21,49,22,50],"4837":[19,20,48,21,49,22,50],"4874":[19,20,48,21,49,22,50],"4888":[19,20,48,21,49,22,50],"4911":[19,20,48,21,49,22,50],"4946":[19,20,48,21,49,22,50],"4972":[19,20,48,21,49,22,50],"4985":[19,20,48,21,49,22,50],"5009":[19,20,48,21,49,22,50],"5017":[19,20,48,21,49,22,50],"5031":[19,20,48,21,49,22,50],"5080":[19,20,48,21,49,22,50],"5083":[19,20,48,21,49,22,50],"5085":[19,20,48,21,49,22,50],"5099":[19,20,48,21,49,22,50],"5154":[19,20,48,21,49,22,50],"5156":[19,20,48,21,49,22,50],"5157":[19,20,48,21,49,22,50],"5161":[19,20,48,21,49,22,50],"5168":[19,20,48,21,49,22,50],"5180":[19,20,48,21,49,22,50],"5181":[19,20,48,21,49,22,50],"5184":[19,20,48,21,49,22,50],"5198":[19,20,48,21,49,22,50],"5202":[19,20,48,21,49,22,50],"5207":[19,20,48,21,49,22,50],"5208":[19,20,48,21,49,22,50],"5217":[19,20,48,21,49,22,50],"5232":[19,20,48,21,49,22,50],"5260":[19,20,48,21,49,22,50],"5293":[19,20,48,21,49,22,50],"5297":[19,20,48,21,49,22,50],"5299":[19,20,48,21,49,22,50],"5345":[19,20,48,21,49,22,50],"5357":[19,20,48,21,49,22,50],"5372":[19,20,48,21,49,22,50],"5387":[19,20,48,21,49,22,50],"5404":[19,20,48,21,49,22,50],"5419":[19,20,48,21,49,22,50],"5430":[19,20,48,21,49,22,50],"5431":[19,20,48,21,49,22,50],"5437":[19,20,48,21,49,22,50],"5460":[19,20,48,21,49,22,50],"5473":[19,20,48,21,49,22,50],"5503":[19,20,48,21,49,22,50],"5517":[19,20,48,21,49,22,50],"5531":[19,20,48,21,49,22,50]},"packages/cli/src/modules/instance-ai/instance-context.service.ts":{"169":[19,20,21,49,22],"186":[19,20,21,49,22],"219":[19,20,21,49,22],"238":[19,20,21,49,22],"257":[19,20,21,49,22],"276":[19,20,21,49,22],"340":[19,20,21,49,22],"374":[19,20,21,49,22],"393":[19,20,21,49,22],"457":[19,20,21,49,22],"471":[19,20,21,49,22],"508":[19,20,21,49,22],"509":[19,20,21,49,22],"520":[19,20,21,49,22],"557":[19,20,21,49,22],"581":[19,20,21,49,22],"594":[19,20,21,49,22],"602":[19,20,21,49,22],"609":[19,20,21,49,22],"617":[19,20,21,49,22],"664":[19,20,21,49,22],"767":[19,20,21,49,22],"789":[19,20,21,49,22],"801":[19,20,21,49,22],"823":[19,20,21,49,22],"829":[19,20,21,49,22],"833":[19,20,21,49,22],"842":[19,20,21,49,22],"855":[19,20,21,49,22],"866":[19,20,21,49,22],"886":[19,20,21,49,22],"911":[19,20,21,49,22],"926":[19,20,21,49,22],"934":[19,20,21,49,22],"950":[19,20,21,49,22],"969":[19,20,21,49,22],"972":[19,20,21,49,22],"996":[19,20,21,49,22],"1035":[19,20,21,49,22],"1040":[19,20,21,49,22],"1062":[19,20,21,49,22],"1085":[19,20,21,49,22],"1117":[19,20,21,49,22],"1121":[19,20,21,49,22],"1135":[19,20,21,49,22],"1145":[19,20,21,49,22],"1157":[19,20,21,49,22],"1178":[19,20,21,49,22],"1186":[19,20,21,49,22],"1195":[19,20,21,49,22],"1206":[19,20,21,49,22],"1211":[19,20,21,49,22],"1216":[19,20,21,49,22],"1219":[19,20,21,49,22]},"packages/cli/src/modules/instance-ai/internal-messages.ts":{"73":[19,20,117,21,119,49,22],"121":[19,20,117,21,119,49,22],"141":[19,20,117,21,119,49,22],"159":[19,20,117,21,119,49,22],"163":[19,20,117,21,119,49,22],"167":[19,20,117,21,119,49,22],"171":[19,20,117,21,119,49,22],"188":[19,20,117,21,119,49,22],"196":[19,20,117,21,119,49,22],"198":[19,20,117,21,119,49,22],"199":[19,20,117,21,119,49,22],"209":[19,20,117,21,119,49,22],"217":[19,20,117,21,119,49,22],"227":[19,20,117,21,119,49,22],"236":[19,20,117,21,119,49,22],"253":[19,20,117,21,119,49,22],"254":[19,20,117,21,119,49,22],"271":[19,20,117,21,119,49,22],"272":[19,20,117,21,119,49,22],"288":[19,20,117,21,119,49,22],"290":[19,20,117,21,119,49,22],"308":[19,20,117,21,119,49,22],"325":[19,20,117,21,119,49,22],"328":[19,20,117,21,119,49,22],"334":[19,20,117,21,119,49,22],"350":[19,20,117,21,119,49,22],"353":[19,20,117,21,119,49,22],"363":[19,20,117,21,119,49,22],"376":[19,20,117,21,119,49,22],"395":[19,20,117,21,119,49,22],"406":[19,20,117,21,119,49,22],"418":[19,20,117,21,119,49,22],"422":[19,20,117,21,119,49,22],"439":[19,20,117,21,119,49,22],"456":[19,20,117,21,119,49,22],"480":[19,20,117,21,119,49,22],"481":[19,20,117,21,119,49,22],"483":[19,20,117,21,119,49,22],"504":[19,20,117,21,119,49,22],"518":[19,20,117,21,119,49,22],"522":[19,20,117,21,119,49,22],"540":[19,20,117,21,119,49,22],"545":[19,20,117,21,119,49,22],"564":[19,20,117,21,119,49,22],"569":[19,20,117,21,119,49,22],"579":[19,20,117,21,119,49,22],"597":[19,20,117,21,119,49,22]},"packages/cli/src/modules/instance-ai/mcp/instance-ai-mcp-connection.controller.ts":{"35":[107,19,20,21,96,49,22],"42":[107,19,20,21,96,49,22],"50":[107,19,20,21,96,49,22],"56":[107,19,20,21,96,49,22],"58":[107,19,20,21,96,49,22],"59":[107,19,20,21,96,49,22],"82":[107,19,20,21,96,49,22],"101":[107,19,20,21,96,49,22],"107":[107,19,20,21,96,49,22],"117":[107,19,20,21,96,49,22],"143":[107,19,20,21,96,49,22],"148":[107,19,20,21,96,49,22]},"packages/cli/src/modules/instance-ai/mcp/instance-ai-mcp-registry.service.ts":{"50":[107,19,20,21,96,49,22],"62":[107,19,20,21,96,49,22],"67":[107,19,20,21,96,49,22],"77":[107,19,20,21,96,49,22],"88":[107,19,20,21,96,49,22],"103":[107,19,20,21,96,49,22],"107":[107,19,20,21,96,49,22],"178":[107,19,20,21,96,49,22],"191":[107,19,20,21,96,49,22],"213":[107,19,20,21,96,49,22],"222":[107,19,20,21,96,49,22],"225":[107,19,20,21,96,49,22],"240":[107,19,20,21,96,49,22],"267":[107,19,20,21,96,49,22],"294":[107,19,20,21,96,49,22],"300":[107,19,20,21,96,49,22],"310":[107,19,20,21,96,49,22],"316":[107,19,20,21,96,49,22],"317":[107,19,20,21,96,49,22],"319":[107,19,20,21,96,49,22],"392":[107,19,20,21,96,49,22],"428":[107,19,20,21,96,49,22],"475":[107,19,20,21,96,49,22],"503":[107,19,20,21,96,49,22],"524":[107,19,20,21,96,49,22],"543":[107,19,20,21,96,49,22],"548":[107,19,20,21,96,49,22]},"packages/cli/src/modules/instance-ai/observability.ts":{"17":[19,20,21,118,119,49,22],"46":[19,20,21,118,119,49,22]},"packages/cli/src/modules/instance-ai/planned-task-action-runner.ts":{"94":[19,20,21,22],"96":[19,20,21,22],"115":[19,20,21,22],"131":[19,20,21,22],"157":[19,20,21,22],"169":[19,20,21,22],"194":[19,20,21,22],"212":[19,20,21,22],"234":[19,20,21,22],"252":[19,20,21,22]},"packages/cli/src/modules/instance-ai/repositories/instance-ai-event-log.repository.ts":{"22":[19,20,116,117,21,49,22],"27":[19,20,116,117,21,49,22],"42":[19,20,116,117,21,49,22],"48":[19,20,116,117,21,49,22],"67":[19,20,116,117,21,49,22],"72":[19,20,116,117,21,49,22],"77":[19,20,116,117,21,49,22],"80":[19,20,116,117,21,49,22],"87":[19,20,116,117,21,49,22],"94":[19,20,116,117,21,49,22],"104":[19,20,116,117,21,49,22],"121":[19,20,116,117,21,49,22],"132":[19,20,116,117,21,49,22],"140":[19,20,116,117,21,49,22],"145":[19,20,116,117,21,49,22],"166":[19,20,116,117,21,49,22],"174":[19,20,116,117,21,49,22],"175":[19,20,116,117,21,49,22],"180":[19,20,116,117,21,49,22],"182":[19,20,116,117,21,49,22],"195":[19,20,116,117,21,49,22],"207":[19,20,116,117,21,49,22],"212":[19,20,116,117,21,49,22],"221":[19,20,116,117,21,49,22],"232":[19,20,116,117,21,49,22],"238":[19,20,116,117,21,49,22],"251":[19,20,116,117,21,49,22],"268":[19,20,116,117,21,49,22],"275":[19,20,116,117,21,49,22],"294":[19,20,116,117,21,49,22]},"packages/cli/src/modules/instance-ai/repositories/instance-ai-thread-grant.repository.ts":{"8":[19,20,21,49,22],"16":[19,20,21,49,22],"25":[19,20,21,49,22],"30":[19,20,21,49,22],"35":[19,20,21,49,22]},"packages/cli/src/modules/instance-ai/repositories/instance-ai-thread-tabs.repository.ts":{"10":[19,20,48,21,49,22],"15":[19,20,48,21,49,22],"21":[19,20,48,21,49,22],"33":[19,20,48,21,49,22],"38":[19,20,48,21,49,22]},"packages/cli/src/modules/instance-ai/repositories/instance-ai-thread.repository.ts":{"10":[107,19,20,21,96,49,22],"15":[107,19,20,21,96,49,22],"21":[107,19,20,21,96,49,22],"54":[107,19,20,21,96,49,22],"64":[107,19,20,21,96,49,22]},"packages/cli/src/modules/instance-ai/run-trace-metadata.ts":{"33":[19,20,21,22],"40":[19,20,21,22],"48":[19,20,21,22],"83":[19,20,21,22],"95":[19,20,21,22]},"packages/cli/src/modules/instance-ai/sandbox/instance-ai-sandbox.service.ts":{"47":[19,20,117,48,21,206,96,49,22],"51":[19,20,117,48,21,206,96,49,22],"59":[19,20,117,48,21,206,96,49,22],"67":[19,20,117,48,21,206,96,49,22],"71":[19,20,117,48,21,206,96,49,22],"84":[19,20,117,48,21,206,96,49,22],"105":[19,20,117,48,21,206,96,49,22],"114":[19,20,117,48,21,206,96,49,22],"206":[19,20,117,48,21,206,96,49,22],"208":[19,20,117,48,21,206,96,49,22],"212":[19,20,117,48,21,206,96,49,22],"216":[19,20,117,48,21,206,96,49,22],"274":[19,20,117,48,21,206,96,49,22],"283":[19,20,117,48,21,206,96,49,22],"292":[19,20,117,48,21,206,96,49,22],"295":[19,20,117,48,21,206,96,49,22],"331":[19,20,117,48,21,206,96,49,22],"340":[19,20,117,48,21,206,96,49,22],"348":[19,20,117,48,21,206,96,49,22],"353":[19,20,117,48,21,206,96,49,22],"406":[19,20,117,48,21,206,96,49,22],"416":[19,20,117,48,21,206,96,49,22],"423":[19,20,117,48,21,206,96,49,22],"426":[19,20,117,48,21,206,96,49,22],"433":[19,20,117,48,21,206,96,49,22],"455":[19,20,117,48,21,206,96,49,22],"462":[19,20,117,48,21,206,96,49,22],"491":[19,20,117,48,21,206,96,49,22],"505":[19,20,117,48,21,206,96,49,22],"513":[19,20,117,48,21,206,96,49,22],"536":[19,20,117,48,21,206,96,49,22],"538":[19,20,117,48,21,206,96,49,22],"544":[19,20,117,48,21,206,96,49,22],"561":[19,20,117,48,21,206,96,49,22],"580":[19,20,117,48,21,206,96,49,22],"596":[19,20,117,48,21,206,96,49,22],"619":[19,20,117,48,21,206,96,49,22],"633":[19,20,117,48,21,206,96,49,22],"635":[19,20,117,48,21,206,96,49,22],"638":[19,20,117,48,21,206,96,49,22],"642":[19,20,117,48,21,206,96,49,22],"646":[19,20,117,48,21,206,96,49,22],"650":[19,20,117,48,21,206,96,49,22],"656":[19,20,117,48,21,206,96,49,22],"664":[19,20,117,48,21,206,96,49,22],"673":[19,20,117,48,21,206,96,49,22],"685":[19,20,117,48,21,206,96,49,22]},"packages/cli/src/modules/instance-ai/sandbox-provider.ts":{"6":[19,20,21,49,22],"14":[19,20,21,49,22]},"packages/cli/src/modules/instance-ai/storage/typeorm-agent-checkpoint-store.ts":{"13":[19,20,48,21,49,22],"15":[19,20,48,21,49,22],"47":[19,20,48,21,49,22],"56":[19,20,48,21,49,22],"60":[19,20,48,21,49,22],"68":[19,20,48,21,49,22],"84":[19,20,48,21,49,22],"93":[19,20,48,21,49,22],"107":[19,20,48,21,49,22],"119":[19,20,48,21,49,22],"126":[19,20,48,21,49,22]},"packages/cli/src/modules/instance-ai/storage/typeorm-agent-memory.ts":{"46":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","62":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","67":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","77":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","88":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","92":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","98":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","103":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","123":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","131":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","138":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","143":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","149":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","155":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","172":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","179":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","198":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","201":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","204":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","207":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","212":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","226":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","241":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","247":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","255":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","260":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","269":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","294":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","295":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","298":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","325":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","343":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","347":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","374":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","380":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","383":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","388":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","392":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","397":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","403":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","404":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","408":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","421":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","430":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","437":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","457":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","470":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","476":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","501":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","509":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","516":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","534":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","539":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","548":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","569":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","575":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","581":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","585":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","592":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","596":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","600":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","607":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","611":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","615":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","627":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","631":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","636":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA=","648":"b:AAB4AAAAAwAgAAAAAQiwAQAAAAAAAAAAAAAAAAA="},"packages/cli/src/modules/instance-ai/storage/typeorm-observation-log-store.ts":{"30":[19,20,21,49,22],"47":[19,20,21,49,22],"55":[19,20,21,49,22],"61":[19,20,21,49,22],"76":[19,20,21,49,22],"79":[19,20,21,49,22],"85":[19,20,21,49,22],"100":[19,20,21,49,22],"103":[19,20,21,49,22],"127":[19,20,21,49,22],"134":[19,20,21,49,22],"140":[19,20,21,49,22],"146":[19,20,21,49,22],"150":[19,20,21,49,22],"162":[19,20,21,49,22],"169":[19,20,21,49,22],"209":[19,20,21,49,22],"210":[19,20,21,49,22],"215":[19,20,21,49,22],"228":[19,20,21,49,22],"243":[19,20,21,49,22],"294":[19,20,21,49,22]},"packages/cli/src/modules/instance-ai/trace-replay-state.ts":{"12":[19,20,21,206,49,22],"19":[19,20,21,206,49,22],"23":[19,20,21,206,49,22],"28":[19,20,21,206,49,22],"32":[19,20,21,206,49,22],"63":[19,20,21,206,49,22],"81":[19,20,21,206,49,22],"85":[19,20,21,206,49,22],"90":[19,20,21,206,49,22],"94":[19,20,21,206,49,22],"98":[19,20,21,206,49,22],"118":[19,20,21,206,49,22],"128":[19,20,21,206,49,22],"154":[19,20,21,206,49,22],"166":[19,20,21,206,49,22]},"packages/cli/src/modules/instance-ai/tracing/instance-ai-tracing.service.ts":{"116":[19,20,116,117,48,21,206,49,22],"124":[19,20,116,117,48,21,206,49,22],"150":[19,20,116,117,48,21,206,49,22],"154":[19,20,116,117,48,21,206,49,22],"158":[19,20,116,117,48,21,206,49,22],"159":[19,20,116,117,48,21,206,49,22],"162":[19,20,116,117,48,21,206,49,22],"166":[19,20,116,117,48,21,206,49,22],"175":[19,20,116,117,48,21,206,49,22],"177":[19,20,116,117,48,21,206,49,22],"180":[19,20,116,117,48,21,206,49,22],"190":[19,20,116,117,48,21,206,49,22],"240":[19,20,116,117,48,21,206,49,22],"244":[19,20,116,117,48,21,206,49,22],"284":[19,20,116,117,48,21,206,49,22],"290":[19,20,116,117,48,21,206,49,22],"329":[19,20,116,117,48,21,206,49,22],"344":[19,20,116,117,48,21,206,49,22],"361":[19,20,116,117,48,21,206,49,22],"370":[19,20,116,117,48,21,206,49,22],"377":[19,20,116,117,48,21,206,49,22],"428":[19,20,116,117,48,21,206,49,22],"464":[19,20,116,117,48,21,206,49,22],"484":[19,20,116,117,48,21,206,49,22],"505":[19,20,116,117,48,21,206,49,22],"510":[19,20,116,117,48,21,206,49,22],"553":[19,20,116,117,48,21,206,49,22],"557":[19,20,116,117,48,21,206,49,22],"561":[19,20,116,117,48,21,206,49,22],"565":[19,20,116,117,48,21,206,49,22]},"packages/cli/src/modules/instance-ai/workflow-verification-task-projector.ts":{"46":[19,20,21,49,22],"50":[19,20,21,49,22],"58":[19,20,21,49,22],"63":[19,20,21,49,22],"89":[19,20,21,49,22],"104":[19,20,21,49,22],"119":[19,20,21,49,22],"131":[19,20,21,49,22],"149":[19,20,21,49,22],"165":[19,20,21,49,22],"174":[19,20,21,49,22],"182":[19,20,21,49,22],"192":[19,20,21,49,22],"201":[19,20,21,49,22],"218":[19,20,21,49,22],"226":[19,20,21,49,22],"244":[19,20,21,49,22],"285":[19,20,21,49,22],"293":[19,20,21,49,22],"318":[19,20,21,49,22],"340":[19,20,21,49,22],"386":[19,20,21,49,22],"396":[19,20,21,49,22],"402":[19,20,21,49,22]},"packages/cli/src/node-catalog/node-catalog.service.ts":{"23":[19,20,21,49,22,50,207,208],"29":[19,20,21,49,22,50,207,208],"32":[19,20,21,49,22,50,207,208],"33":[19,20,21,49,22,50,207,208],"35":[19,20,21,49,22,50,207,208],"41":[19,20,21,49,22,50,207,208],"44":[19,20,21,49,22,50,207,208],"52":[19,20,21,49,22,50,207,208],"134":[19,20,21,49,22,50,207,208],"137":[19,20,21,49,22,50,207,208],"222":[19,20,21,49,22,50,207,208],"227":[19,20,21,49,22,50,207,208],"230":[19,20,21,49,22,50,207,208],"235":[19,20,21,49,22,50,207,208],"242":[19,20,21,49,22,50,207,208],"256":[19,20,21,49,22,50,207,208],"266":[19,20,21,49,22,50,207,208],"288":[19,20,21,49,22,50,207,208],"312":[19,20,21,49,22,50,207,208],"322":[19,20,21,49,22,50,207,208],"347":[19,20,21,49,22,50,207,208],"359":[19,20,21,49,22,50,207,208],"375":[19,20,21,49,22,50,207,208],"389":[19,20,21,49,22,50,207,208],"405":[19,20,21,49,22,50,207,208],"421":[19,20,21,49,22,50,207,208],"428":[19,20,21,49,22,50,207,208],"458":[19,20,21,49,22,50,207,208],"485":[19,20,21,49,22,50,207,208],"486":[19,20,21,49,22,50,207,208],"487":[19,20,21,49,22,50,207,208],"488":[19,20,21,49,22,50,207,208],"515":[19,20,21,49,22,50,207,208],"520":[19,20,21,49,22,50,207,208],"567":[19,20,21,49,22,50,207,208],"603":[19,20,21,49,22,50,207,208],"613":[19,20,21,49,22,50,207,208],"636":[19,20,21,49,22,50,207,208],"665":[19,20,21,49,22,50,207,208],"676":[19,20,21,49,22,50,207,208],"695":[19,20,21,49,22,50,207,208],"718":[19,20,21,49,22,50,207,208],"737":[19,20,21,49,22,50,207,208],"746":[19,20,21,49,22,50,207,208],"758":[19,20,21,49,22,50,207,208],"792":[19,20,21,49,22,50,207,208],"839":[19,20,21,49,22,50,207,208],"845":[19,20,21,49,22,50,207,208],"848":[19,20,21,49,22,50,207,208],"853":[19,20,21,49,22,50,207,208],"858":[19,20,21,49,22,50,207,208],"862":[19,20,21,49,22,50,207,208]},"packages/cli/src/telemetry/index.ts":{"128":[26,19,20,21,206,96,49,22,207,208],"140":[26,19,20,21,206,96,49,22,207,208],"185":[26,19,20,21,206,96,49,22,207,208],"215":[26,19,20,21,206,96,49,22,207,208],"226":[26,19,20,21,206,96,49,22,207,208],"242":[26,19,20,21,206,96,49,22,207,208],"267":[26,19,20,21,206,96,49,22,207,208],"283":[26,19,20,21,206,96,49,22,207,208],"284":[26,19,20,21,206,96,49,22,207,208],"308":[26,19,20,21,206,96,49,22,207,208],"316":[26,19,20,21,206,96,49,22,207,208],"317":[26,19,20,21,206,96,49,22,207,208],"339":[26,19,20,21,206,96,49,22,207,208],"349":[26,19,20,21,206,96,49,22,207,208],"363":[26,19,20,21,206,96,49,22,207,208],"374":[26,19,20,21,206,96,49,22,207,208],"378":[26,19,20,21,206,96,49,22,207,208],"379":[26,19,20,21,206,96,49,22,207,208],"380":[26,19,20,21,206,96,49,22,207,208],"381":[26,19,20,21,206,96,49,22,207,208],"382":[26,19,20,21,206,96,49,22,207,208],"383":[26,19,20,21,206,96,49,22,207,208],"387":[26,19,20,21,206,96,49,22,207,208],"434":[26,19,20,21,206,96,49,22,207,208],"447":[26,19,20,21,206,96,49,22,207,208],"486":[26,19,20,21,206,96,49,22,207,208],"524":[26,19,20,21,206,96,49,22,207,208],"548":[26,19,20,21,206,96,49,22,207,208],"553":[26,19,20,21,206,96,49,22,207,208],"590":[26,19,20,21,206,96,49,22,207,208],"615":[26,19,20,21,206,96,49,22,207,208],"621":[26,19,20,21,206,96,49,22,207,208],"685":[26,19,20,21,206,96,49,22,207,208],"694":[26,19,20,21,206,96,49,22,207,208],"698":[26,19,20,21,206,96,49,22,207,208],"702":[26,19,20,21,206,96,49,22,207,208],"706":[26,19,20,21,206,96,49,22,207,208]},"packages/cli/src/utils/ai-proxy-fetch.ts":{"14":[26,102,33,19,20,21,49,22],"33":[26,102,33,19,20,21,49,22],"51":[26,102,33,19,20,21,49,22],"67":[26,102,33,19,20,21,49,22]},"packages/cli/src/utils/node-definition-dirs.ts":{"9":[19,20,21,49,22]},"localhost-33169/assets/index-Dv_brJ4-.js":{"3":[20,117,48,119,120,121]},"localhost-33169/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[20,117,48,119,120,121],"9":[20,117,48,119,120,121],"10":[20,117,48,119,120,121],"19":[20,117,48,119,120,121],"23":[20,117,48,119,120,121],"29":[20,117,48,119,120,121],"33":[20,117,48,119,120,121],"34":[20,117,48,119,120,121]},"packages/@n8n/api-types/src/schemas/agent-run-reducer.ts":{"32":[46,19,116,117,21],"69":"b:AAB4AABABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","82":"b:AAB4AABABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","99":"b:AAB4AABABwAAAAAAAADwAQAAAAAAAAAAAAAAAAA=","108":[46,19,20,116,117,48,21,119,49,120,22,50],"116":[46,19,20,116,117,48,21,49,22,50],"121":[46,19,20,116,117,48,21,119,49,120,22,50],"139":[46,19,20,116,117,48,21,49,120,22,50],"157":[46,19,116,117,21,120],"158":[46,19,116,117,21],"163":[19,116,117,21],"178":"b:AAB4AABABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","203":"b:AAB4AABABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","494":[46],"495":[19,116,117,21],"604":[46,19,20,117,48,119,120,22,50],"605":[19,116,117,21],"646":"b:AAB4AABABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","657":[46,19,116,117,21,120],"672":[46,19,116,117,21,120],"686":[46,19,116,117,21,120],"697":[46,19,116,117,21],"700":[46,19,116,117,21],"703":[46,19,116,117,21,120]},"packages/frontend/@n8n/design-system/src/components/N8nAiActivityStepChevron/AiActivityStepChevron.vue":{"16":[46,19,20,116,117,48,21,49,120,22,50]},"packages/frontend/@n8n/design-system/src/components/N8nAnimatedCollapsibleContent/AnimatedCollapsibleContent.vue":{"12":[46,19,20,116,117,48,21,49,120,22,50],"13":[46]},"packages/frontend/@n8n/design-system/src/components/N8nChatActions/ChatActions.vue":{"21":[46,19,20,116,117,48,21,118,119,120,22,50],"39":[46,19,20,116,117,48,21,118,119,120,22,50],"42":[46,19,20,116,117,48,21,119,120,22,50],"48":[46],"54":[46],"62":[46],"68":[46],"78":[46],"85":[46,19,20,116,117,48,21,118,119,120,22,50],"88":[46],"96":[46,19,20,116,117,48,21,118,119,120,22,50],"99":[46],"104":[46,120],"108":[46,19,20,116,117,48,21,118,119,120,22,50],"118":[46,19,20,116,117,48,21,119,120,22,50],"129":[46,19,20,116,117,48,21,119,120,22,50],"134":[46,19,20,116,117,48,21,119,120,22,50],"143":[46,19,20,116,117,48,21,119,120,22,50],"159":[46,19,20,116,117,48,21,118,119,120,22,50],"167":[46],"174":[46,19,20,116,117,48,21,118,119,120,22,50],"182":[46]},"packages/frontend/@n8n/design-system/src/components/N8nChatInput/useChatInputAutoFocus.ts":{"16":[46],"28":[46],"32":[46],"36":"b:AABYAABABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","42":[46],"43":[46],"45":[46]},"packages/frontend/@n8n/design-system/src/components/N8nChatMessage/ChatMessage.vue":{"9":"b:AAB4AABABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","14":"b:AAB4AABABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","32":"b:AAB4AABABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/useApprovalCardLabels.ts":{"5":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","7":[48,22]},"packages/frontend/editor-ui/src/app/layouts/InstanceAiLayout.vue":{"21":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","29":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","30":[19,48,22,50],"37":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","49":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/experiments/instanceAiFreeNudge/components/InstanceAiFreeNudge.vue":{"9":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","24":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","25":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","34":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/experiments/instanceAiFreeNudge/stores/instanceAiFreeNudge.store.ts":{"25":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","31":[19,20,117,48,96,118,119,49,120,22,50],"34":[19,20,117,48,96,118,119,49,120,22,50],"47":[19,20,117,48,96,118,119,49,120,22,50],"56":[19,20,117,48,96,118,119,49,120,22,50],"59":[19,20,117,48,96,118,119,49,120,22,50]},"packages/frontend/editor-ui/src/experiments/instanceAiInspirationFromTaxonomy/metadata.ts":{"47":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","53":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/experiments/instanceAiInspirationFromTaxonomy/useInstanceAiInspirationFromTaxonomyExperiment.ts":{"6":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","9":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","12":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/experiments/instanceAiPersonalizedPromptSuggestions/profileOverride.ts":{"60":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","73":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","106":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","114":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","130":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/experiments/instanceAiPersonalizedPromptSuggestions/useInstanceAiPersonalizedPromptSuggestionsExperiment.ts":{"8":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","11":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","14":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","29":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/experiments/instanceAiProactiveAgent/useInstanceAiProactiveAgentExperiment.ts":{"6":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","9":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/experiments/instanceAiPromptSuggestionsV2/useInstanceAiPromptSuggestionsV2Experiment.ts":{"6":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","9":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/experiments/instanceAiSplitEmptyState/useInstanceAiSplitEmptyStateExperiment.ts":{"5":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","7":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","10":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/experiments/instanceAiWorkflowPreviewSuggestions/components/WorkflowPreviewSuggestions.vue":{"11":"b:AABYAAAABwAAAAAAAQDgBwAAAAAAAAAAAAAAAAA=","42":[19,20,117,48,118,119,49,120,22,50],"59":[19,20,117,48,118,119,49,120,22,50],"113":"b:AABYAAAABwAAAAAAAQDgBwAAAAAAAAAAAAAAAAA=","128":"b:AABYAAAABwAAAAAAAQDgBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/experiments/openWorkflowInAssistant/components/ManualEditorButton.vue":{"11":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","18":[121],"19":[121],"30":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/experiments/openWorkflowInAssistant/components/OpenWorkflowInAssistantNotification.vue":{"10":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","16":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","22":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/experiments/testAgentPreview/useTestAgentPreviewExperiment.ts":{"7":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/agents/composables/useAgentCapabilitySummary.ts":{"19":[46],"33":[46],"48":[46],"57":[46],"63":[46],"77":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","88":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/agents/n8nChatPage/useMergedChatHistory.ts":{"26":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","34":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","39":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","50":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","105":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/agents/n8nChatPage/usePagedN8nChatThreads.ts":{"87":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","123":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/assistant-at-mentions/assistantAtMentions.telemetry.ts":{"19":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","25":[21],"29":[21]},"packages/frontend/editor-ui/src/features/ai/assistant-at-mentions/composables/useAssistantAtMentions.ts":{"22":[21],"26":[21],"33":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","51":[19,20,117,48,21,118,119,49,120,22,50],"57":[21],"64":[19,20,117,48,118,119,49,120,22,50],"81":[19,20,117,48,21,118,119,49,120,22,50],"90":[21],"115":[19,20,117,48,21,118,119,49,120,22,50],"163":[19,20,117,48,21,118,119,49,120,22,50],"233":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","234":[21],"240":[19,20,117,48,21,118,119,49,120,22,50]},"packages/frontend/editor-ui/src/features/ai/assistant-at-mentions/composables/useAssistantMentionAttachments.ts":{"35":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","213":[19,20,117,48,118,119,49,120,22,50],"217":[19,20,117,48,118,119,49,120,22,50],"226":[19,20,117,48,118,119,49,120,22,50],"230":[19,20,117,48,118,119,49,120,22,50],"244":[19,20,117,48,118,119,49,120,22,50],"249":[19,20,117,48,118,119,49,120,22,50],"267":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","268":[116,117,21,120,122],"276":[19,20,117,48,118,119,49,120,22,50,121]},"packages/frontend/editor-ui/src/features/ai/assistant-at-mentions/composables/useAssistantMentionAvailability.ts":{"8":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","18":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","19":[21],"23":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","56":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","57":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/assistant-at-mentions/composables/useIsAssistantAtMentionsEnabled.ts":{"9":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/InstanceAiEmptyView.vue":{"134":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","143":[19,20,117,48,118,119,49,120,22,50],"152":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","185":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","202":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","208":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","212":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","223":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","233":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","252":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","260":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","270":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","314":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","349":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","356":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","380":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","401":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","416":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","421":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","426":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","521":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","548":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","552":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","555":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","563":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","573":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","598":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","623":[107,19,20,117,48,118,119,49,120,22,50],"627":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","628":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","642":[19,20,117,48,118,119,49,120,22,50],"912":[19,20,117,48,118,119,49,120,22,50]},"packages/frontend/editor-ui/src/features/ai/instanceAi/InstanceAiThreadView.vue":{"92":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","113":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","140":[120],"150":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","159":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","160":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","164":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","203":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","242":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","244":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","251":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","257":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","266":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","269":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","270":[48,49,22,50],"276":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","285":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","291":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","309":[119,122],"332":[19],"371":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","372":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","377":"b:AAB4AAAABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","380":"b:AAB4AAAABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","385":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","392":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","399":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","403":[19,50],"438":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","443":[116,117,21,120,122],"451":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","454":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","457":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","461":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","467":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","476":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","479":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","482":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","485":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","503":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","511":[19,48,21,49,22,50,121],"521":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","522":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","523":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","526":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","537":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","540":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","551":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","562":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","586":[19,48,21,49,22,50,121],"594":[19],"600":[19,48,21,49,22,50,121],"620":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","643":[116,117,21,120,121,122],"651":[48,119,120,22],"659":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","669":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","670":[116,117,21,120,121,122],"681":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","685":[120,121],"867":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","877":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","882":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","909":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","929":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","968":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","977":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","979":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","989":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","996":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","1012":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","1042":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","1066":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/InstanceAiView.vue":{"30":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","44":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","52":[96],"69":[96],"74":[21],"90":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","116":"b:AAB4AAAABwAAAAAAAQDwBQAAAAAAAAAAAAAAAAA=","118":"b:AAB4AAAABwAAAAAAAQDwBQAAAAAAAAAAAAAAAAA=","131":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","149":[121]},"packages/frontend/editor-ui/src/features/ai/instanceAi/agentTimeline.utils.ts":{"77":[19,20,48,49,22,50],"103":[19,20,116,117,48,21,118,119,49,120,22,50],"117":[19,20,117,48,21,49,120,22,50],"123":[19,20,116,117,48,21,119,49,120,22,50],"134":[19,20,116,117,48,21,119,49,120,22,50],"155":[19,20,116,117,48,21,119,49,120,22,50],"185":[19,20,116,117,48,21,119,49,120,22,50],"190":[19,20,117,48,21,49,120,22,50],"198":[19,20,116,117,48,21,119,49,120,22,50],"305":[19,20,116,117,48,21,119,49,120,22,50],"362":[116]},"packages/frontend/editor-ui/src/features/ai/instanceAi/builderAgents.ts":{"18":[116],"30":"b:AAB4AAAABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","39":[116],"47":[116],"48":[116],"56":[116],"71":"b:AAB4AAAABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","82":"b:AAB4AAAABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","145":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","147":"b:AAB4AAAABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/canvasPreview.utils.ts":{"65":"b:AAB4AABABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","104":[46],"108":[46],"132":[46,19,116,48,21,22,50],"144":"b:AAB4AABABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","174":"b:AAB4AABABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","204":"b:AAB4AABABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","242":"b:AAB4AABABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","292":[46,19,48,21,49,22,50],"299":[46],"313":[46,48,22],"369":[46],"403":[46],"404":[46],"405":[46],"406":[46],"407":[46],"408":[46],"409":[46],"410":[46],"413":[46],"439":"b:AAB4AABABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","463":"b:AAB4AABABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","489":[46],"520":[46],"551":[46],"576":[46],"594":"b:AAB4AABABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","620":[46,19,48,21,49,22,50],"628":[46,19,48,21,49,22,50],"667":[46,19,48,50],"670":[46],"673":[46]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/AgentActivityTree.vue":{"10":[19,20,116,117,48,21,118,119,49,120,22,50]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/AgentTimeline.vue":{"33":[19,20,116,117,48,21,118,119,49,120,22,50],"120":[19,20,116,117,48,21,118,119,49,120,22,50],"123":[19,20,116,117,48,21,118,119,49,120,22,50],"132":[19,20,116,117,48,21,118,119,49,120,22,50],"146":[19,117,48,50],"154":[19,20,116,117,48,21,118,119,49,120,22,50],"164":[116],"175":[19,20,117,48,21,49,120,22,50],"196":[19,20,116,117,48,21,49,120,22,50],"293":[19,20,116,117,48,21,118,119,49,120,22,50]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/AttachmentPreview.vue":{"10":[20,21,119],"25":[20,21,119],"30":[20,21,119],"33":[20,119],"36":[20,119],"40":[20,119],"41":[119],"42":[20,119],"44":[20,119],"51":[119],"59":[20,119],"77":[20,119],"82":[20,21,119]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiArtifactsPanel.vue":{"25":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","30":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","34":[19,20,116,117,48,118,119,49,120,22,50,122],"74":[19],"94":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","95":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","96":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","112":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","128":[19,48,22,50,121],"144":[19,48,22,50,121],"175":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","214":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","224":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","290":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","296":[19,48,22,50,121],"302":[19]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiConfirmationPanel.vue":{"45":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","55":[48,22],"65":[48,22],"121":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","182":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","185":[48,22],"202":[48,22],"238":[48,22],"261":[48,22],"273":[48,22],"289":[48,22],"311":[48],"350":[22],"456":[19,48,21,49,22,50],"525":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","729":[48,22]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiConversation.vue":{"149":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","170":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","175":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","177":[19,48,21,49,22,50,121],"178":[19,48,21,49,22,50,121],"183":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","208":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","216":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","217":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","221":[19,20,117,48,119,49,120,22,50,122],"228":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","237":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","241":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","247":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","266":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","267":[19,20,116,117,21,119,49,120,22,122],"278":[120,121],"287":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","299":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","304":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","308":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","392":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","394":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","405":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","416":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","427":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","428":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","434":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","449":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","453":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","470":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","484":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","490":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","498":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","508":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","512":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","524":[116,117,21,120,121,122],"527":[116,117,21,120,122],"544":[122],"567":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","578":[19,20,117,48,118,119,49,120,22,50,121,122],"606":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","611":[120,121],"630":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","636":[119],"733":[119],"748":[119],"901":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","934":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","942":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","997":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","1029":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiEmptyState.vue":{"5":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA=","22":"b:AABYAAAABwAAAAAAAQjgBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiInput.vue":{"175":[21],"197":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","200":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","209":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","210":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","231":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","263":[19,20,117,48,118,119,49,120,22,50],"285":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","290":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","292":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","295":[21],"329":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","330":[20,119],"332":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","334":[19,20,117,48,21,118,119,49,120,22,50],"335":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","338":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","343":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","348":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","349":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","351":[21],"352":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","359":[19,20,117,48,21,118,119,49,120,22,50],"363":[19,20,117,48,21,118,119,49,120,22,50],"379":[21],"386":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","420":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","426":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","434":"b:AABYAAAABwAAAAAAAQDgBwAAAAAAAAAAAAAAAAA=","437":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","441":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","443":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","472":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","489":[19,20,117,48,21,118,119,49,120,22,50],"496":[19,20,117,48,118,119,49,120,22,50],"524":[19,20,117,48,118,119,49,120,22,50],"537":[19,20,117,48,118,119,49,120,22,50],"545":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","572":[19,20,117,48,118,119,49,120,22,50],"578":[19,20,117,48,118,119,49,120,22,50],"601":[19,20,117,48,118,119,49,120,22,50],"649":[19,20,117,48,118,119,49,120,22,50],"680":[19,20,117,48,118,119,49,120,22,50],"706":[20,119],"737":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","738":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","766":[21],"784":[20,119],"821":[19,20,117,48,118,119,49,120,22,50],"834":[19,20,117,48,118,119,49,120,22,50],"901":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","911":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","919":[19,20,117,48,118,119,49,120,22,50],"920":[19,20,117,48,118,119,49,120,22,50],"921":[21],"947":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","970":[20,119],"981":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","989":[21],"1009":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","1016":[19,20,117,48,118,119,49,120,22,50],"1020":[19,20,117,48,118,119,49,120,22,50]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiInputMenu.vue":{"21":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","32":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","70":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","84":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiMarkdown.vue":{"12":[19,20,116,117,48,21,119,49,120,22,50],"52":[19,48,21,49,22,50],"70":[19,48,22,50],"88":[19,20,116,117,48,21,119,49,120,22,50],"90":[19,48,22,50],"102":[19,48,49,22,50],"144":[19,48,21,49,22,50],"175":[19,20,116,117,48,21,119,49,120,22,50],"181":[19,48,21,49,22,50],"186":[19,48,21,49,22,50],"207":[19,48,22,50],"217":[19,20,116,117,48,21,119,49,120,22,50],"248":[19,48,22,50],"259":[19,48,22,50],"277":[19,48,22,50],"311":[19,20,116,117,48,21,119,49,120,22,50],"338":[19,48,22,50],"447":[19,117,48,119,22,50],"454":[19,20,116,117,48,21,119,49,120,22,50]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiMessage.vue":{"25":"b:AAB4AAAABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","35":"b:AAB4AAAABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","36":[19,20,116,117,48,21,118,119,49,120,22,50],"37":[19,20,116,117,48,21,118,119,49,120,22,50],"39":[19,20,116,117,48,21,119,49,120,22,50],"45":[19,20,116,117,48,21,118,119,49,120,22,50],"51":[119,22],"54":[19,20,116,117,48,21,118,119,49,120,22,50],"60":[118],"69":[118],"76":[19,20,116,117,48,21,118,119,49,120,22,50],"90":[119,22],"97":[119,22],"107":[19,20,117,48,21,118,119,49,120,22,50,122],"108":[20,21,119],"120":"b:AAB4AAAABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","132":[19,20,116,117,48,21,118,119,49,120,22,50],"139":[19,20,116,117,48,21,118,119,49,120,22,50],"145":[19,20,116,117,48,21,118,119,49,120,22,50],"147":"b:AAB4AAAABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","154":"b:AAB4AAAABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","158":"b:AAB4AAAABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","182":"b:AAB4AAAABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","190":"b:AAB4AAAABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","195":[20,21,119],"217":[118],"223":[118],"231":[119,22],"243":[119,22],"278":[19,20,116,117,48,21,118,119,120,22,50]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiPreviewTabBar.vue":{"35":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","65":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","76":[19,48,21,49,22,50,121],"82":[19,48,21,49,22,50,121],"87":[19,48,21,49,22,50,121],"114":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","115":[19,48,21,49,22,50,121],"118":[19,48,21,49,22,50,121],"147":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","150":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","258":"b:AAB4AAAABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","260":"b:AAB4AAAABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","287":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","307":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","308":[19,48,21,49,22,50,121],"310":[19,48,21,49,22,50,121],"332":[19,48,21,49,22,50,121],"392":"b:AAB4AAAABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiStatusBar.vue":{"19":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","26":[19,20,119,49,120,22,122],"32":[19,20,119,49,120,22,122],"57":[22],"66":[19,20,119,49,120,22,122],"76":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","80":"b:AAB4AAAABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","84":[19,20,117,48,119,49,120,22,50],"95":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","102":[19,20,119,49,120,22,122],"111":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","126":[120,121],"131":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiThreadList.vue":{"72":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","74":[120],"83":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","88":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","101":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","128":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","130":[120],"134":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","147":"b:AAB4AAAABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","148":"b:AAB4AAAABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","152":[120],"157":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","160":[120],"164":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","165":"b:AAB4AAAABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","192":[120],"200":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","207":[120],"219":[120],"229":[21,120],"241":[120],"250":[120],"278":[120],"282":[120],"284":[120],"288":[120],"294":[120],"299":[120],"315":[120],"324":[120],"336":[120],"350":[120],"351":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","376":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","391":[120],"412":[120],"423":[120],"427":[120],"432":[120],"437":[120],"446":[120],"468":[120]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiViewHeader.vue":{"14":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","45":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","60":[120],"62":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","77":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/LimitedModeNotice.vue":{"14":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/ThinkingBlock.vue":{"19":[19,20,117,48,21,49,120,22,50],"32":[19,20,48,49,22,50],"40":[19,20,117,48,21,49,120,22,50],"44":[19,20,117,48,21,49,120,22,50],"52":[19,20,117,48,21,49,120,22,50],"61":[19,20,117,48,21,49,120,22,50],"62":[19,20,117,48,21,49,120,22,50],"68":[19,20,117,48,21,49,120,22,50],"87":[19,20,117,48,21,49,120,22,50]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/TimelineTextSegment.vue":{"10":[19,20,116,117,48,21,119,49,120,22,50]},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useAgentMutationRefresh.ts":{"12":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","13":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","24":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useBrowserUseConnection.ts":{"24":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useBuildingArtifactIds.ts":{"21":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","24":[19,48,21,49,22,50,121]},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useCreditWarningBanner.ts":{"9":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","12":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","23":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useInstanceAiInputMenuItems.ts":{"29":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","41":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","42":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","50":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","51":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","71":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","136":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","156":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useInstanceAiThreadHistory.ts":{"20":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","22":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","27":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","46":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","54":[19,20,117,48,118,119,49,120,22,50,121]},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useIsAgentWorking.ts":{"22":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","25":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useMcpServerConnect.ts":{"44":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useOpenArtifactTabs.ts":{"28":[19,48,21,49,22,50],"36":[48,49,22,50],"58":[19,48,49,22,50],"67":[21],"78":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","98":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","103":[19,48,21,49,22,50],"125":[19,48,49,22,50],"129":[19,48,22],"131":[19,48,22],"159":[19,48,49,22,50],"167":[48,22],"212":[49,22,50],"213":[49,22,50],"230":[49,120,22,50,121],"242":[19,48,49,22,50],"247":[49,22,50],"260":[19,48,21,49,22,50],"268":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","290":[120,121]},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useProjectResourceSearch.ts":{"14":[19,48,21,49,22,50],"23":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","38":"b:AAB4AAAABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useTabDragReorder.ts":{"37":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","123":[120,121],"203":[120,121]},"packages/frontend/editor-ui/src/features/ai/instanceAi/constants.ts":{"44":[46,19,20,117,48,118,119,49,120,22,50,122],"60":[46,121],"66":[46]},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAi.api.ts":{"32":[46,19,20,117,48,118,119,49,120,22,50,122],"59":"b:AABYAABABwAAAAAAAADgBwAAAAAAAAAAAAAAAAA=","77":[46],"86":[46],"104":[46],"117":[46,48,22],"135":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","143":[46],"163":[46],"172":[46],"186":"b:AAB4AABABwAAAAAAAQDwBQAAAAAAAAAAAAAAAAA=","200":[46],"208":[46,96],"230":[46],"250":[46]},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAi.handoffContext.ts":{"20":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAi.mcp.api.ts":{"26":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAi.reducer.ts":{"53":[46,19,20,117,48,118,119,49,120,22,50],"60":[46,19,20,117,48,118,119,49,120,22,50,122],"65":[46,19,20,117,48,118,119,49,120,22,50,122],"110":[46,19,20,117,48,118,119,49,120,22,50,122],"119":[46,19,116,117,21,120],"127":[46,19,20,117,48,118,119,49,120,22,50,122],"144":[46,19,20,117,48,118,119,49,120,22,50,122],"149":[46,19,20,117,48,118,119,49,120,22,50,122],"179":[46,19,20,117,48,118,119,49,120,22,50],"193":[46,19,20,117,48,118,119,49,120,22,50,122]},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAi.responseTiming.ts":{"2":[46,19,20,117,48,118,119,49,120,22,50,122]},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAi.settings.api.ts":{"16":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","22":[46,96],"29":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","35":[46],"42":"b:AAB4AABABwAAAAAAAQDwBwAAAAAAAAAAAAAAAAA=","48":"b:AAB4AABABwAAAAAAAQDwBwAAAAAAAAAAAAAAAAA=","54":[46],"60":[46],"67":[46],"74":[46,96]},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAi.threadRuntime.ts":{"196":[46,19,20,117,48,49,120,22,50,122],"203":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","208":[46,19,20,116,117,48,49,120,22,50,122],"213":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","227":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","232":[46],"243":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","253":[46],"262":[46],"271":[46],"292":"b:AAB4AABABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","320":[46,48,49,22],"330":[46,19,20,117,48,118,119,49,120,22,50,122],"345":[46],"348":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","366":[46,19,116,117,21,120],"391":[46],"396":[46],"404":[46],"464":[46,116,117,21,120],"496":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","509":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","511":[46,120,121],"561":[46],"564":[46,19,48,21,49,22,50,121],"575":[46,121],"578":[46],"584":[46],"587":[46],"596":[46,22,50],"603":[46,19,48,21,49,22,50],"606":[46,19,48,50],"638":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","639":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","640":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","641":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","649":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","650":[46,19,48,21,49,22,50,121],"651":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","652":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","653":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","657":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","658":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","659":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","668":[46],"673":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","681":[46],"685":[46],"708":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","720":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","721":[46,19,48,49,22,50],"739":[46,19,20,117,48,118,119,49,120,22,50,122],"741":[46,48,49,22],"752":[46,19,20,117,48,119,49,120,22,50],"756":[46,19,20,117,48,119,49,120,22,50],"761":[46,19,20,117,48,118,119,49,120,22,50],"770":[46,19,20,117,48,118,119,49,120,22,50],"778":[46,19,20,117,48,119,49,120,22,50],"795":[46,19,20,117,48,118,119,49,120,22,50,122],"815":[46,19,20,117,48,118,119,49,120,22,50,122],"832":[46,19,20,117,48,118,119,49,120,22,50,122],"835":[46,19,20,117,48,118,119,49,120,22,50,122],"842":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","844":[46,19,20,117,48,118,119,49,120,22,50,122],"851":[46,19,20,117,48,118,119,49,120,22,50,122],"854":[46],"868":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","871":"b:AAB4AABABQAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","877":[46,116],"888":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","898":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","915":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","932":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","934":[46,48,22],"942":[46,49],"951":[46,48,22],"973":[46,48,22],"990":[46,48,22],"1037":[46,22],"1050":[46,48,22],"1058":[46,48,49,22],"1074":[46,48,49,22],"1093":"b:AAB4AABABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","1143":[46,19,20,117,48,118,119,49,120,22,50,122],"1155":[46,19,20,117,48,118,119,49,120,22,50,122],"1281":[46,19,117],"1301":[46,19,117],"1306":[46,19,117],"1367":"b:AAB4AABABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","1385":"b:AAB4AABABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","1390":[46,19,20,117,48,118,119,49,120,22,50,122],"1397":[46,19,117],"1402":[46,116,117,21,120],"1414":[46,120],"1422":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","1426":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","1431":[46,120],"1461":[46,120],"1467":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","1478":[46,116,117,21,120,121,122],"1501":[46,116,117,21,120],"1502":[46,116,117,21,120],"1528":[46,116,117,48,21,120,22,122],"1560":[46,19,20,117,48,118,119,49,120,22,50,122],"1571":[46,19,20,117,48,118,119,49,120,22,50,122],"1590":[46],"1597":[46,19,20,117,48,118,119,49,120,22,50,122],"1616":[46,19,20,117,48,118,119,49,120,22,50,122],"1644":[46,19,20,117,48,118,119,49,120,22,50,122],"1707":[46,19,20,117,48,118,119,49,120,22,50,122],"1733":[46,119],"1771":[46],"1785":[46],"1794":[46],"1815":[46],"1836":[46],"1840":[46],"1849":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","1850":[46],"1861":[46,19,20,117,48,118,119,49,120,22,50,122],"1869":[46,48,22],"1914":[46],"1924":[46]},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAiBrowserUse.telemetry.ts":{"9":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAiMcp.store.ts":{"34":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","63":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","68":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","73":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","156":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAiMcp.telemetry.ts":{"13":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAiPromptSuggestions.telemetry.ts":{"45":"b:AABYAAAABwAAAAAAAQDgBwAAAAAAAAAAAAAAAAA=","48":"b:AABYAAAABwAAAAAAAQDgBwAAAAAAAAAAAAAAAAA=","63":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","68":"b:AABYAAAABwAAAAAAAQDgBwAAAAAAAAAAAAAAAAA=","117":"b:AAB4AAAABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceContextLabels.ts":{"45":[19,20,117,48,21,49,120,22,50]},"packages/frontend/editor-ui/src/features/ai/instanceAi/threadArtifacts.ts":{"18":[46],"22":[46],"46":[46,19,20,117,48,118,119,49,120,22,50,122],"60":[46],"62":[46],"72":[46]},"packages/frontend/editor-ui/src/features/ai/instanceAi/toolLabels.ts":{"160":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","163":[19,20,48,49,22,50]},"packages/frontend/editor-ui/src/features/ai/instanceAi/useArtifactTabSummaries.ts":{"23":[19,48,21,49,22,50,121],"27":[19,48,21,49,22,50,121],"35":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","40":[19,48,21,49,22,50,121],"47":[19,48,21,49,22,50],"91":[19,48,21,49,22,50,121],"93":[19,48,21,49,22,50,121],"96":[19,48,21,49,22,50],"98":[19,48,21,49,22,50],"99":[19,48,21,49,22,50],"115":[19,48,21,49,22,50,121],"118":[19,48,21,49,22,50,121],"119":[19,48,21,49,22,50,121],"125":[19,48,21,49,22,50,121],"129":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","134":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","136":[19,48,21,49,22,50,121],"145":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","146":[19,48,21,49,22,50,121],"148":[19,48,49,22,50],"149":[19,48,49,50],"160":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","161":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","179":[19,48,21,49,22,50,121]},"packages/frontend/editor-ui/src/features/ai/instanceAi/useCanvasPreview.ts":{"55":[20,21,119],"61":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","68":[19,48,21,49,22,50,121],"84":[19,20,116,117,48,21,119,120,22,50,121,122],"89":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","129":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","131":[49,22,50],"136":[19,48,21,49,22,50,121],"137":[19,48,21,49,22,50,121],"141":[19,48,21,49,22,50,121],"142":[19,48,21,49,22,50,121],"151":[19,48,21,49,22,50,121],"152":[19,48,21,49,22,50,121],"166":[19,48,21,49,22,50,121],"177":[19,48,21,49,22,50,121],"184":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","188":[19,48,21,49,22,50,121],"195":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","196":[19,48,21,49,22,50,121],"209":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","210":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","216":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","228":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","238":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","255":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","265":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","280":[19],"310":[19,50],"318":[19,48,49,22,50],"332":[19],"365":[19,48,21,49,22,50,121],"367":[19,48,21,49,22,50],"377":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","397":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","398":[19,48,49,22,50],"420":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","431":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","448":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","459":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","481":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","492":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","512":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","523":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","541":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","552":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","569":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/useResourceRegistry.ts":{"70":[46,19,20,48,21,49,22,50,121],"100":[46,19,48,21,49,22,50,121],"135":[46,48,22],"139":[46,48,22],"182":[46,19,20,48,49,22,50],"189":[46],"208":[46,19,20,48,49,22,50],"372":"b:AAB4AABABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","390":"b:AAB4AABABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","413":"b:AAB4AABABwAAAAAAAADwBQAAAAAAAAAAAAAAAAA=","445":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","474":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","498":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","516":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","543":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","593":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","614":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","661":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","671":[46,19,20,117,48,118,119,49,120,22,50,122],"692":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","705":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","723":[46,19,48,21,49,22,50,121]},"packages/frontend/editor-ui/src/features/ai/instanceAi/useResponseFeedback.ts":{"12":[46,19,20,116,117,48,21,118,119,120,22,50],"14":[46,116],"17":[46,19,20,116,117,48,21,118,119,120,22,50],"18":[46,19,20,48,22,50],"19":[46,116],"22":[46,19,20,116,117,48,21,118,119,120,22,50],"23":[46,19,20,48,22,50],"25":[46,116],"48":"b:AAB4AABABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","73":"b:AAB4AABABwAAAAAAAADwAQAAAAAAAAAAAAAAAAA=","113":[46],"157":[46],"165":[46,120]},"packages/frontend/editor-ui/src/features/ai/instanceAi/useTransitionGate.ts":{"3":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","7":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","9":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","10":"b:AAB4AAAABwAAAAAAAADwBwAAAAAAAAAAAAAAAAA=","18":[116,117,21,120,121,122],"23":[116,117,21,120,122]},"packages/frontend/editor-ui/src/features/ai/instanceAi/utils/browserUseSupport.ts":{"6":"b:AAB4AABABwAAAAAAAQjwBwAAAAAAAAAAAAAAAAA=","16":[46]},"packages/frontend/editor-ui/src/features/ai/instanceAi/utils/buildNodesAttachment.ts":{"29":[46],"31":[46],"36":[46],"41":[46],"72":[46],"79":[46],"80":[46],"81":[46],"82":[46],"86":[46],"111":[46],"120":[46],"121":[46],"127":[46],"134":[46],"136":[46],"150":[46],"157":[46],"158":[46],"160":[46],"161":[46],"171":[46],"187":[46,19,20,117,48,118,119,49,120,22,50],"189":[46,20,119],"190":[46]},"packages/frontend/editor-ui/src/features/ai/shared/components/AiThinkingBlock.vue":{"8":[19,20,117,48,21,49,120,22,50],"27":[19,20,117,48,21,49,120,22,50],"29":[19,20,117,48,21,49,120,22,50],"30":[19,20,117,48,49,120,22,50],"41":[19,20,117,48,21,49,120,22,50],"49":[19,20,117,48,21,49,120,22,50],"52":[19,20,117,48,21,49,120,22,50],"57":[19,48,49,22,50],"73":[120],"77":[19,20,48,49,22,50],"82":[19,20,117,48,49,120,22,50],"86":[19,20,117,48,21,49,120,22,50],"117":[19,20,117,48,21,49,120,22,50],"124":[19,20,117,48,21,49,120,22,50],"126":[19,20,117,48,21,49,120,22,50],"133":[19,20,117,48,21,49,120,22,50]},"packages/frontend/editor-ui/src/features/ai/shared/thinking.utils.ts":{"2":[19,20,117,48,49,120,22,50]},"packages/frontend/editor-ui/src/features/core/dataTable/components/dataGrid/ColumnHeader.vue":{"27":[47,114],"41":[47,114],"42":[47,114],"44":"b:AAB4AACABwAAAAAAAAD0BwAAAAAAAAAAAAAAAAA=","67":[47],"77":[47],"81":[47],"85":[47],"89":[47,114],"99":[47,114],"103":[47,114],"111":[47,114],"116":[47,114],"127":[47,114],"136":[47,114],"138":[47],"144":[47,114],"164":[47,114],"168":[47,114],"186":[47],"196":[47,114],"208":[47,114],"214":[47,114],"268":[47]},"packages/@n8n/instance-ai/src/tools/orchestration/builder-thread-id.ts":{"6":[19,117,21,22]},"packages/@n8n/instance-ai/src/utils/agent-tree.ts":{"4":[19,117,21],"12":[19,117,21]},"packages/cli/src/modules/instance-ai/message-parser.ts":{"47":[19,116,117,21],"53":[19,116,117,21],"59":[19,116,117,21],"61":[19,116,117,21],"68":[19,116,117,21],"70":[19,116,117,21],"82":[19,116,117,21],"98":[19,116,117,21],"102":[19,116,117,21],"106":[19,116,117,21],"110":[19,116,117,21],"121":[19,116,117,21],"147":[19,116,117,21],"155":[19,116,117,21],"168":[19,116,117,21],"176":[19,116,117,21],"189":[19,116,117,21],"348":[19,116,117,21],"358":[19,116,117,21],"388":[19,116,117,21],"397":[19,116,117,21],"403":[19,116,117,21],"420":[19,116,117,21],"426":[19,116,117,21],"438":[19,116,117,21]},"packages/cli/src/modules/instance-ai/repositories/instance-ai-checkpoint.repository.ts":{"11":[116,117,48,21,22],"24":[116,117,48,21,22],"36":[116,117,48,21,22],"40":[116,117,48,21,22],"68":[116,117,48,21,22]},"packages/cli/src/modules/instance-ai/repositories/instance-ai-pending-confirmation.repository.ts":{"8":[19,117,48,21,22],"21":[19,117,48,21,22],"25":[19,117,48,21,22],"48":[19,117,48,21,22],"53":[19,117,48,21,22],"58":[19,117,48,21,22],"63":[19,117,48,21,22],"76":[19,117,48,21,22],"81":[19,117,48,21,22],"87":[19,117,48,21,22],"96":[19,117,48,21,22]},"packages/cli/src/modules/instance-ai/suspended-thread-persistence.service.ts":{"47":[19,117,48,21,49,22],"53":[19,117,48,21,49,22],"68":[19,117,48,21,49,22],"81":[19,117,48,21,49,22],"117":[19,117,48,21,49,22],"128":[19,117,48,21,49,22]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/TimelineActivityIndicator.vue":{"7":[19,117,48,50],"29":[19,117,48,50],"30":[19,117,48,50],"41":[19,48,50],"49":[19,117,48,50],"54":[19,117,48,50]},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAi.liveRunState.ts":{"9":[46,116,117,48,21,120,22,122],"15":[46],"16":[46],"19":[46,49],"33":[46],"44":[46,48,22],"61":[46,48,22],"73":[46,48,22],"89":[46,48,22]},"packages/@n8n/agents/src/runtime/loop/checkpoint-data.ts":{"12":[48,49,22],"22":[48,49,22],"47":[48,49,22],"59":[48,49,22],"79":[48,49,22]},"packages/@n8n/agents/src/sdk/untrusted-content.ts":{"9":[19,48],"13":[19,48],"30":[19,48]},"packages/@n8n/instance-ai/src/runtime/confirmation-payload.ts":{"28":[48,22],"79":[48,22]},"packages/@n8n/instance-ai/src/runtime/liveness-policy.ts":{"41":[19,48,22],"69":[19,48,22],"71":[19,48,22],"72":[19,48,22],"75":[19,48,22],"106":[19,48,22]},"packages/@n8n/instance-ai/src/tools/workflows/credential-url-resolver.ts":{"24":[19,48,49,22],"32":[19,48,49,22],"33":[19,48,49,22],"41":[19,48,49,22],"43":[19,48,49,22],"78":[19,48,49,22],"94":[19,48,49,22]},"packages/@n8n/workflow-sdk/src/ast-interpreter/parser.ts":{"20":[48,22]},"packages/@n8n/workflow-sdk/src/codegen/code-generator.ts":{"109":[48,22],"127":[48,22],"136":[48,22],"144":[48,22],"195":[48,22],"224":[48,22],"235":[48,22],"259":[48,22],"263":[48,22],"308":[48,22],"339":[48,22],"390":[48,22],"419":[48,22],"430":[48,22],"454":[48,22],"469":[48,22],"521":[48,22],"527":[48,22],"543":[48,22],"577":[48,22],"592":[48,22],"628":[48,22],"673":[48,22],"719":[48,22],"740":[48,22],"766":[48,22],"781":[48,22],"801":[48,22],"808":[48,22],"816":[48,22],"827":[48,22],"861":[48,22],"874":[48,22],"889":[48,22],"894":[48,22],"909":[48,22],"914":[48,22],"930":[48,22],"949":[48,22],"964":[48,22],"1019":[48,22],"1027":[48,22],"1037":[48,22],"1055":[48,22],"1065":[48,22],"1093":[48,22],"1120":[48,22],"1148":[48,22],"1230":[48,22],"1242":[48,22],"1252":[48,22],"1260":[48,22],"1274":[48,22],"1290":[48,22],"1346":[48,22],"1401":[48,22],"1534":[48,22]},"packages/@n8n/workflow-sdk/src/codegen/composite-builder.ts":{"50":[48,22],"77":[48,22],"144":[48,22],"185":[48,22],"328":[48,22],"355":[48,22],"387":[48,22],"454":[48,22],"491":[48,22],"528":[48,22],"586":[48,22],"701":[48,22],"814":[48,22],"969":[48,22],"1067":[48,22],"1162":[48,22],"1196":[48,22],"1275":[48,22],"1284":[48,22]},"packages/@n8n/workflow-sdk/src/codegen/composite-handlers/build-utils.ts":{"19":[48,22],"42":[48,22],"53":[48,22],"65":[48,22],"75":[48,22],"82":[48,22],"89":[48,22],"103":[48,22],"134":[48,22],"142":[48,22],"146":[48,22],"157":[48,22],"166":[48,22],"171":[48,22]},"packages/@n8n/workflow-sdk/src/codegen/emit-instance-ai.ts":{"21":[48,22],"84":[48,22],"101":[48,22],"110":[48,22],"124":[48,22],"148":[48,22],"149":[48,22],"162":[48,22],"170":[48,22],"186":[48,22],"205":[48,22]},"packages/@n8n/workflow-sdk/src/codegen/execution-status.ts":{"17":[48,22],"46":[48,22],"61":[48,22],"63":[48,22]},"packages/@n8n/workflow-sdk/src/codegen/expression-annotator.ts":{"11":[48,22],"35":[48,22]},"packages/@n8n/workflow-sdk/src/codegen/graph-annotator.ts":{"16":[48,22],"20":[48,22],"79":[48,22],"104":[48,22],"114":[48,22],"141":[48,22],"157":[48,22]},"packages/@n8n/workflow-sdk/src/codegen/locate-node-declarations.ts":{"26":[48,22],"35":[48,22],"51":[48,22],"64":[48,22],"70":[48,22],"83":[48,22]},"packages/@n8n/workflow-sdk/src/codegen/node-type-utils.ts":{"10":[48,22],"17":[48,22],"24":[48,22],"32":[48,22],"39":[48,22]},"packages/@n8n/workflow-sdk/src/codegen/output-utils.ts":{"24":[48,22],"41":[48,22],"62":[48,22],"75":[48,22],"92":[48,22],"107":[48,22],"114":[48,22]},"packages/@n8n/workflow-sdk/src/codegen/semantic-graph.ts":{"20":[48,22],"44":[48,22],"52":[48,22],"60":[48,22],"98":[48,22],"139":[48,22],"148":[48,22],"151":[48,22],"168":[48,22],"206":[48,22],"240":[48,22],"329":[48,22],"352":[48,22],"384":[48,22]},"packages/@n8n/workflow-sdk/src/codegen/semantic-registry.ts":{"42":[48,22],"48":[48,22],"57":[48,22],"60":[48,22],"76":[48,22],"85":[48,22],"105":[48,22],"137":[48,22],"158":[48,22],"169":[48,22],"199":[48,22]},"packages/@n8n/workflow-sdk/src/codegen/string-utils.ts":{"9":[48,22],"27":[48,22],"38":[48,22],"48":[48,22],"62":[48,22],"107":[48,22],"113":[48,22],"124":[48,22],"132":[48,22],"139":[48,22],"147":[48,22],"155":[48,22]},"packages/@n8n/workflow-sdk/src/codegen/subnode-generator.ts":{"33":[48,22],"42":[48,22],"95":[48,22],"113":[48,22],"120":[48,22],"123":[48,22],"133":[48,22],"138":[48,22],"141":[48,22],"150":[48,22],"159":[48,22],"187":[48,22],"192":[48,22],"201":[48,22],"210":[48,22],"218":[48,22],"226":[48,22],"246":[48,22],"255":[48,22],"298":[48,22],"328":[48,22],"347":[48,22],"373":[48,22],"382":[48,22],"403":[48,22],"425":[48,22],"434":[48,22]},"packages/@n8n/workflow-sdk/src/codegen/variable-names.ts":{"102":[48,22],"115":[48,22],"120":[48,22],"151":[48,22],"162":[48,22]},"packages/@n8n/workflow-sdk/src/constants/node-types.ts":{"24":[19,48,49,22],"31":[19,48,49,22],"38":[19,48,49,22],"45":[19,48,49,22],"52":[19,48,49,22],"59":[19,48,49,22],"66":[19,48,49,22],"73":[19,48,49,22]},"packages/@n8n/workflow-sdk/src/generate-types/index.ts":{"82":[48,49,22,50,207,208]},"packages/@n8n/workflow-sdk/src/lint/ast-walk.ts":{"5":[48,22],"13":[48,22],"41":[48,22]},"packages/@n8n/workflow-sdk/src/lint/sdk/workflow-sdk-lint.ts":{"65":[48,22],"70":[48,22],"71":[48,22],"106":[48,22],"111":[48,22],"115":[48,22],"124":[48,22],"143":[48,22],"145":[48,22],"160":[48,22],"204":[48,22],"224":[48,22],"238":[48,22],"316":[48,22],"333":[48,22],"341":[48,22],"354":[48,22],"376":[48,22],"544":[48,22],"552":[48,22]},"packages/@n8n/workflow-sdk/src/mock-data/context.ts":{"23":[19,48,49,22],"29":[19,48,49,22],"75":[19,48,49,22],"89":[19,48,49,22],"97":[19,48,49,22],"115":[19,48,49,22],"136":[19,48,49,22],"179":[19,48,49,22],"198":[19,48,49,22],"224":[19,48,49,22],"257":[19,48,49,22]},"packages/@n8n/workflow-sdk/src/mock-data/index.ts":{"40":[19,48,49,22,50,207,208]},"packages/@n8n/workflow-sdk/src/prompts/best-practices/guides/chatbot.ts":{"4":[19,48,49,22],"125":[19,48,49,22]},"packages/@n8n/workflow-sdk/src/prompts/best-practices/guides/content-generation.ts":{"4":[19,48,49,22],"111":[19,48,49,22]},"packages/@n8n/workflow-sdk/src/prompts/best-practices/guides/data-extraction.ts":{"4":[19,48,49,22],"118":[19,48,49,22]},"packages/@n8n/workflow-sdk/src/prompts/best-practices/guides/data-persistence.ts":{"4":[19,48,49,22],"193":[19,48,49,22]},"packages/@n8n/workflow-sdk/src/prompts/best-practices/guides/data-transformation.ts":{"4":[19,48,49,22],"142":[19,48,49,22]},"packages/@n8n/workflow-sdk/src/prompts/best-practices/guides/document-processing.ts":{"4":[19,48,49,22],"328":[19,48,49,22]},"packages/@n8n/workflow-sdk/src/prompts/best-practices/guides/form-input.ts":{"4":[19,48,49,22],"169":[19,48,49,22]},"packages/@n8n/workflow-sdk/src/prompts/best-practices/guides/notification.ts":{"4":[19,48,49,22],"131":[19,48,49,22]},"packages/@n8n/workflow-sdk/src/prompts/best-practices/guides/scheduling.ts":{"4":[19,48,49,22],"148":[19,48,49,22]},"packages/@n8n/workflow-sdk/src/prompts/best-practices/guides/scraping-and-research.ts":{"4":[19,48,49,22],"154":[19,48,49,22]},"packages/@n8n/workflow-sdk/src/prompts/best-practices/guides/triage.ts":{"4":[19,48,49,22],"145":[19,48,49,22]},"packages/@n8n/workflow-sdk/src/prompts/best-practices/guides/web-app.ts":{"4":[19,48,49,22],"200":[19,48,49,22]},"packages/@n8n/workflow-sdk/src/prompts/best-practices/index.ts":{"1":[19,48,49,22],"4":[19,48,49,22],"7":[19,48,49,22],"8":[19,48,49,22],"14":[19,48,49,22],"19":[19,48,49,22],"20":[19,48,49,22]},"packages/@n8n/workflow-sdk/src/types/base.ts":{"173":[19,48,49,22],"204":[19,48,49,22],"243":[19,48,49,22],"290":[19,48,49,22],"669":[19,48,49,22],"685":[19,48,49,22],"708":[19,48,49,22],"712":[19,48,49,22]},"packages/@n8n/workflow-sdk/src/utils/trigger-detection.ts":{"30":[19,48,49,22]},"packages/@n8n/workflow-sdk/src/utils/workflow-json-engine-helpers.ts":{"32":[19,48,49,22],"40":[19,48,49,22],"41":[19,48,49,22],"58":[19,48,49,22],"59":[19,48,49,22],"70":[19,48,49,22]},"packages/@n8n/workflow-sdk/src/validation/display-options.ts":{"77":[19,48,49,22],"90":[19,48,49,22],"98":[19,48,49,22],"115":[19,48,49,22],"156":[19,48,49,22],"157":[19,48,49,22],"167":[19,48,49,22],"231":[19,48,49,22],"274":[19,48,49,22],"289":[19,48,49,22],"311":[19,48,49,22],"332":[19,48,49,22],"333":[19,48,49,22],"349":[19,48,49,22]},"packages/@n8n/workflow-sdk/src/validation/issue-severity.ts":{"13":[19,48,49,22],"20":[19,48,49,22]},"packages/@n8n/workflow-sdk/src/validation/node-parameter-schema/resolve-schema.ts":{"17":[19,48,49,22,50],"65":[19,48,49,22,50],"74":[19,48,49,22,50],"86":[19,48,49,22,50],"95":[19,48,49,22,50],"142":[19,48,49,22,50],"150":[19,48,49,22,50],"166":[19,48,49,22,50],"202":[19,48,49,22,50],"220":[19,48,49,22,50],"223":[19,48,49,22,50],"225":[19,48,49,22,50]},"packages/@n8n/workflow-sdk/src/validation/node-parameter-schema/schema-helpers.ts":{"8":[19,48,49,22],"33":[19,48,49,22]},"packages/@n8n/workflow-sdk/src/validation/node-port-resolvers/resolve-main-input-count.ts":{"16":[19,48,49,22],"31":[19,48,49,22]},"packages/@n8n/workflow-sdk/src/validation/node-port-resolvers/resolve-main-output-count.ts":{"16":[19,48,49,22],"31":[19,48,49,22]},"packages/@n8n/workflow-sdk/src/validation/validate-workflow.ts":{"71":[19,48,49,22],"102":[19,48,49,22],"121":[19,48,49,22],"221":[19,48,49,22],"293":[19,48,49,22],"356":[19,48,49,22],"391":[19,48,49,22],"411":[19,48,49,22],"429":[19,48,49,22],"470":[19,48,49,22],"483":[19,48,49,22],"485":[19,48,49,22],"486":[19,48,49,22],"487":[19,48,49,22],"506":[19,48,49,22],"542":[19,48,49,22],"600":[19,48,49,22],"624":[19,48,49,22],"711":[19,48,49,22],"797":[19,48,49,22],"852":[19,48,49,22],"885":[19,48,49,22],"946":[19,48,49,22],"954":[19,48,49,22],"955":[19,48,49,22],"977":[19,48,49,22],"990":[19,48,49,22],"1004":[19,48,49,22],"1026":[19,48,49,22],"1109":[19,48,49,22],"1148":[19,48,49,22],"1183":[19,48,49,22],"1195":[19,48,49,22],"1219":[19,48,49,22],"1251":[19,48,49,22],"1281":[19,48,49,22],"1294":[19,48,49,22],"1301":[19,48,49,22],"1309":[19,48,49,22],"1314":[19,48,49,22],"1321":[19,48,49,22],"1348":[19,48,49,22],"1406":[19,48,49,22],"1450":[19,48,49,22],"1499":[19,48,49,22]},"packages/@n8n/workflow-sdk/src/workflow-builder/layout-utils.ts":{"67":[19,48,49,22],"84":[19,48,49,22],"140":[19,48,49,22],"144":[19,48,49,22],"159":[19,48,49,22],"172":[19,48,49,22],"179":[19,48,49,22],"180":[19,48,49,22],"187":[19,48,49,22],"195":[19,48,49,22],"212":[19,48,49,22],"232":[19,48,49,22],"268":[19,48,49,22],"272":[19,48,49,22],"282":[19,48,49,22],"302":[19,48,49,22],"313":[19,48,49,22],"316":[19,48,49,22],"318":[19,48,49,22],"327":[19,48,49,22],"332":[19,48,49,22],"340":[19,48,49,22],"350":[19,48,49,22],"379":[19,48,49,22],"387":[19,48,49,22],"398":[19,48,49,22],"402":[19,48,49,22],"404":[19,48,49,22],"415":[19,48,49,22],"424":[19,48,49,22],"430":[19,48,49,22],"434":[19,48,49,22],"449":[19,48,49,22],"458":[19,48,49,22],"466":[19,48,49,22],"475":[19,48,49,22],"496":[19,48,49,22],"516":[19,48,49,22],"524":[19,48,49,22],"529":[19,48,49,22],"532":[19,48,49,22],"536":[19,48,49,22],"537":[19,48,49,22],"543":[19,48,49,22],"550":[19,48,49,22],"553":[19,48,49,22],"563":[19,48,49,22],"567":[19,48,49,22],"569":[19,48,49,22],"580":[19,48,49,22],"588":[19,48,49,22],"606":[19,48,49,22],"624":[19,48,49,22],"633":[19,48,49,22],"635":[19,48,49,22],"638":[19,48,49,22],"647":[19,48,49,22],"655":[19,48,49,22],"660":[19,48,49,22],"661":[19,48,49,22],"667":[19,48,49,22],"668":[19,48,49,22],"686":[19,48,49,22],"691":[19,48,49,22],"693":[19,48,49,22],"695":[19,48,49,22],"705":[19,48,49,22],"712":[19,48,49,22],"722":[19,48,49,22],"734":[19,48,49,22],"738":[19,48,49,22],"748":[19,48,49,22],"757":[19,48,49,22],"766":[19,48,49,22],"795":[19,48,49,22],"814":[19,48,49,22],"819":[19,48,49,22],"820":[19,48,49,22],"823":[19,48,49,22],"824":[19,48,49,22],"832":[19,48,49,22],"833":[19,48,49,22],"851":[19,48,49,22],"862":[19,48,49,22],"870":[19,48,49,22],"871":[19,48,49,22],"897":[19,48,49,22],"901":[19,48,49,22],"906":[19,48,49,22],"918":[19,48,49,22],"921":[19,48,49,22],"942":[19,48,49,22],"949":[19,48,49,22],"962":[19,48,49,22],"971":[19,48,49,22],"980":[19,48,49,22],"981":[19,48,49,22],"983":[19,48,49,22],"1010":[19,48,49,22],"1017":[19,48,49,22],"1056":[19,48,49,22],"1083":[19,48,49,22],"1090":[19,48,49,22],"1120":[19,48,49,22],"1122":[19,48,49,22],"1126":[19,48,49,22]},"packages/@n8n/workflow-sdk/src/workflow-builder/workflow-import.ts":{"45":[19,48,49,22],"98":[19,48,49,22],"101":[19,48,49,22],"104":[19,48,49,22],"107":[19,48,49,22],"110":[19,48,49,22],"128":[19,48,49,22],"139":[19,48,49,22],"180":[19,48,49,22],"202":[19,48,49,22],"206":[19,48,49,22]},"packages/cli/src/middlewares/list-query/dtos/base.select.dto.ts":{"7":[19,48,21,49,22,187,190],"12":[19,48,21,49,22,187,190]},"packages/cli/src/middlewares/list-query/dtos/workflow.select.dto.ts":{"4":[19,48,21,49,22,187,190],"22":[19,48,21,49,22,187,190]},"packages/cli/src/modules/instance-ai/instance-ai-execution-wait.ts":{"17":[19,48],"29":[19,48],"30":[19,48],"39":[19,48],"40":[19,48]},"packages/cli/src/modules/instance-ai/instance-ai-run-pin-data.ts":{"28":[19,48,49,22],"94":[19,48,49,22],"97":[19,48,49,22],"99":[19,48,49,22],"104":[19,48,49,22],"145":[19,48,49,22],"180":[19,48,49,22],"195":[19,48,49,22],"210":[19,48,49,22],"247":[19,48,49,22]},"packages/cli/src/modules/instance-ai/onboarding.ts":{"69":[48,22],"71":[48,22],"76":[48,22],"83":[48,22],"96":[48,22],"103":[48,22],"105":[48,22],"110":[48,22],"111":[48,22],"112":[48,22],"113":[48,22],"129":[48,22],"140":[48,22],"161":[48,22],"169":[48,22],"229":[48,22],"249":[48,22],"250":[48,22],"269":[48,22],"272":[48,22],"286":[48,22],"292":[48,22],"306":[48,22],"328":[48,22]},"packages/cli/src/modules/instance-ai/trigger-run-data.ts":{"10":[19,48],"14":[19,48]},"packages/cli/src/modules/instance-ai/workflow-verification-obligation-service.ts":{"19":[19,48,22],"27":[19,48,22],"29":[19,48,22],"32":[19,48,22],"36":[19,48,22],"42":[19,48,22],"52":[19,48,22],"63":[19,48,22],"77":[19,48,22],"88":[19,48,22]},"packages/cli/src/node-catalog/index.ts":{"1":[19,48,49,22]},"packages/cli/src/node-catalog/module-gated-node-types.ts":{"8":[19,48,49,22],"13":[19,48,49,22],"18":[19,48,49,22],"20":[19,48,49,22],"21":[19,48,49,22],"25":[19,48,49,22]},"packages/frontend/@n8n/design-system/src/components/N8nApprovalCard/ApprovalCard.vue":{"68":[46,48,22],"74":[46,48,22],"82":[46,48,22],"94":[46,48,22],"122":[46,48,22],"123":[46],"129":[46,48,22],"133":[46,48,22],"139":[46],"155":[46,48,22],"162":[46,48,22],"193":[46],"210":[46,48,22],"224":[46,48,22],"225":[46,48]},"packages/frontend/editor-ui/src/app/components/WorkflowCanvasHost.vue":{"9":[19,48,21,49,22,50,121],"35":[19,48,21,49,22,50,121],"45":[19,48,21,49,22,50,121],"50":[19,48,21,49,22,50,121],"60":[19,48,21,49,22,50]},"packages/frontend/editor-ui/src/app/components/WorkflowCanvasHostBody.vue":{"20":[19,48,21,49,22,50,121],"53":[19,48,21,49,22,50],"72":[19,48,21,49,22,50],"90":[19,48,21,49,22,50,121],"100":[19,48,21,49,22,50,121],"107":[19,50],"121":[19,48,21,49,22,50,121],"127":[19,48,21,49,22,50,121],"128":[19,48,21,49,22,50,121]},"packages/frontend/editor-ui/src/features/ai/instanceAi/approvalDetails.ts":{"5":[48,22]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiWorkflowPreview.vue":{"39":[19,48,21,49,22,50,121],"60":[19,48,21,49,22,50,121],"117":[19,48,21,49,22,50,121],"118":[19,48,21,49,22,50,121],"120":[19,48,22,50],"125":[19,48,21,49,22,50],"157":[19,48,21,22,50],"174":[19,48,21,49,22,50],"191":[19,48,21,49,22,50],"215":[19,48,21,49,22,50,121]},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useInstanceAiWorkflowPreviewExecution.ts":{"26":[48],"30":[48],"50":[19,48,21,49,22,50,121],"72":[19,48,22,50],"83":[19,48,22,50],"88":[19,48,22,50],"103":[19,48,22,50],"113":[19,48,22,50],"124":[19,48,21,49,22,50,121],"125":[19,48,22,50],"134":[48],"149":[19,48,21,49,22,50],"153":[48],"168":[19,48,21,49,22,50],"176":[19,48,21,49,22,50,121],"208":[19,48,21,49,22,50],"221":[19,48,21,49,22,50],"249":[19,48,21,49,22,50],"261":[19,48,21,49,22,50,121],"262":[19,48,21,49,22,50,121],"269":[19,48,21,49,22,50,121],"276":[19,48,21,49,22,50],"282":[19,50]},"packages/frontend/editor-ui/src/features/ai/instanceAi/confirmationKinds.ts":{"16":[48,49,22]},"packages/frontend/editor-ui/src/features/ai/instanceAi/embed/instanceAiEmbed.types.ts":{"30":[19,48,21,49,22,50]},"packages/frontend/editor-ui/src/features/shared/tags/components/TagsDropdown.vue":{"58":[46,183,190],"72":[46,183,190],"73":[46,183,190],"78":[46,183,190],"79":[46,183,190],"82":[46,183,190],"86":[46,183,190],"95":[46,183,190],"96":[46,183,190],"104":[46,183,190],"112":[46,183],"130":[46,183,190],"134":[46],"139":[46,183,190],"141":[46,183,190],"144":[46,183],"160":[46,183,190],"161":[46,183,190],"162":[46,183,190],"171":[46,183,190],"180":[46,183,190],"191":[46,183],"198":[46,183,190],"207":[46,183],"208":[46,183],"214":[46,183,190],"220":[46,183,190],"223":[46],"241":[46,183,190],"248":[46,183],"255":[46,183,190],"269":[46,183,190],"279":[46,183,190]},"packages/frontend/editor-ui/src/features/shared/tags/components/TagsManager/NoTagsView.vue":{"21":[46,183],"22":[46,183],"27":[46,183],"31":[46,183],"41":[46,183]},"packages/frontend/editor-ui/src/features/shared/tags/components/TagsManager/TagsManager.vue":{"31":[46,183],"44":[46,183],"48":[46,183],"50":[46,183],"51":[46,183],"53":[46,183],"57":[46,183],"61":[46,183],"65":[46,183],"69":[46,183],"86":[46],"91":[46],"111":[46],"119":[46,183],"120":[46,183],"132":[46,183],"135":[46,183],"143":[46],"150":[46,183],"163":[46,183],"189":[46,183]},"packages/frontend/editor-ui/src/features/shared/tags/components/TagsManager/TagsView/TagsTable.vue":{"33":[46,183],"42":[46,183],"46":[46,183],"65":[46],"73":[46,183],"80":[46],"84":[46,183],"88":[46,183],"92":[46,183],"93":[46,183],"100":[46,183],"101":[46,183],"109":[46,183],"118":[46,183],"119":[46,183],"127":[46,183],"132":[46,183],"145":[46,183],"147":[46,183],"148":[46,183],"150":[46,183],"169":[46,183],"171":[46,183],"181":[46,183],"183":[46,183],"228":[46],"235":[46,183]},"packages/frontend/editor-ui/src/features/shared/tags/components/TagsManager/TagsView/TagsTableHeader.vue":{"21":[46,183],"30":[46,183],"34":[46],"36":[46,183],"41":[46,183],"42":[46,183],"50":[46,183],"56":[46,183]},"packages/frontend/editor-ui/src/features/shared/tags/components/TagsManager/TagsView/TagsView.vue":{"12":[46,183],"35":[46,183],"48":[46,183],"52":[46,183],"53":[46,183],"60":[46,183],"61":[46,183],"76":[46,183],"80":[46],"85":[46,183],"89":[46],"93":[46],"98":[46],"101":[46],"112":[46,183],"116":[46,183],"120":[46,183],"122":[46,183],"132":[46,183],"137":[46,183],"142":[46,183],"145":[46,183],"156":[46,183],"168":[46],"177":[46,183]},"packages/frontend/editor-ui/src/features/shared/tags/components/TagsManager/WorkflowTagsManager.vue":{"11":[46,183],"16":[46,183],"17":[46,183],"19":[46,183],"29":[46,183],"44":[46],"64":[46,183],"85":[46,183]},"packages/frontend/editor-ui/src/features/shared/tags/components/WorkflowTagsDropdown.vue":{"18":[46,183,190],"36":[46,183,190],"37":[46,183,190],"40":[46,183,190],"41":[46,183,190],"42":[46,183,190],"44":[46,183,190],"45":[46,183,190],"48":[46,183,190],"50":[46,183,190],"54":[46,183],"58":[46,183],"62":[46],"66":[46,183,190],"72":[46,183,190]},"packages/frontend/editor-ui/src/features/shared/tags/useTagPermissions.ts":{"4":[46,183,190],"5":[46],"6":[46,183,190],"7":[46,183],"8":[46,183],"11":[46,183,190],"16":[46],"17":[46],"20":[46],"23":[46],"28":[46]},"packages/frontend/editor-ui/src/features/workflows/components/WorkflowDescriptionModal.vue":{"21":[46,183],"51":[46,183],"55":[46,183],"57":[46,183],"58":[46,183],"60":[46,183],"63":[46,183],"66":[46,183],"70":[46,183],"76":[46,183],"82":[46,183],"138":[46,183],"169":[46],"173":[46,183],"178":[46],"198":[46,183],"199":[46,183],"203":[46,183],"214":[46,183],"220":[46,183],"230":[46,183],"234":[46,183],"243":[46,183]},"packages/cli/src/workflows/node-group-rules-flag-gate.ts":{"16":[21,78],"19":[21,78]},"packages/workflow/src/graph/graph-utils.ts":{"41":[21,78],"62":[21,78],"80":[21,78],"88":[21,78],"95":[21,78],"103":[21,78],"114":[21,78],"115":[21,78],"123":[21,78],"133":[21,78],"134":[21,78],"145":[21,78],"157":[21,78],"170":[21,78],"174":[21,78],"199":[21,78],"203":[21,78],"213":[21,78],"217":[21,78],"239":[21,78],"249":[21,78],"264":[21,78]},"localhost-36283/assets/index-Dv_brJ4-.js":{"3":[0,21]},"localhost-36283/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[0,21],"9":[0,21],"10":[0,21],"19":[0,21],"23":[0,21],"29":[0,21],"33":[0,21],"34":[0,21]},"packages/frontend/editor-ui/src/features/ai/assistant-at-mentions/AssistantAtMentionPicker.vue":{"46":[21],"87":[21],"89":[21],"92":[21],"94":[21],"95":[21],"98":[21],"103":[21],"104":[21],"105":[21],"112":[21],"116":[21],"119":[21],"161":[21],"163":[21],"166":[21],"169":[21],"171":[21],"174":[21],"215":[21],"219":[21],"223":[21],"260":[21],"269":[21],"270":[21],"280":[21],"301":[21],"302":[21],"315":[21],"333":[21],"349":[21],"367":[21],"370":[21],"422":[21],"446":[21],"479":[21],"496":[21],"516":[21],"522":[21],"530":[21],"536":[21]},"packages/frontend/editor-ui/src/features/ai/assistant-at-mentions/AssistantMentionBreadcrumbs.vue":{"6":[21],"20":[21],"21":[21],"22":[21]},"packages/frontend/editor-ui/src/features/ai/assistant-at-mentions/composables/useArtifactMentionIndex.ts":{"52":[21],"56":[21],"57":[21],"63":[21],"65":[21],"68":[21],"70":[21],"71":[21],"91":[21],"94":[21],"95":[21],"105":[21],"107":[21],"120":[21],"129":[21],"135":[21],"143":[21],"149":[21],"187":[21],"197":[21],"215":[21],"252":[21],"257":[21],"263":[21],"270":[21],"273":[21],"277":[21],"295":[21],"296":[21],"305":[21],"327":[21],"333":[21]},"packages/frontend/editor-ui/src/features/ai/assistant-at-mentions/composables/useAssistantMentionSources.ts":{"24":[21],"32":[21],"39":[21],"54":[21],"62":[21],"73":[21],"85":[21],"100":[21],"105":[21],"134":[21],"162":[21],"179":[21],"181":[21],"184":[21],"189":[21],"193":[21],"194":[21],"200":[21],"210":[21],"221":[21],"227":[21],"258":[21],"269":[21],"274":[21],"308":[21],"325":[21],"333":[21]},"packages/frontend/editor-ui/src/features/ai/assistant-at-mentions/utils/buildMentionItems.ts":{"17":[21],"42":[21],"102":[21],"116":[21],"117":[21],"118":[21],"141":[21],"156":[21]},"packages/frontend/editor-ui/src/features/ai/assistant-at-mentions/utils/searchMentionItems.ts":{"14":[21],"24":[21],"37":[21],"47":[21]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiResourceChip.vue":{"10":[21,121],"30":[21,121]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/NodeChip.vue":{"10":[21],"59":[21]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/NodesAttachmentChips.vue":{"33":[21],"46":[21],"75":[21],"79":[21],"87":[21],"90":[21],"242":[21],"247":[21],"284":[21],"286":[21],"291":[21],"309":[21],"311":[21],"316":[21]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/groups/CanvasNodeGroupTitleBar.vue":{"38":[46,21,78],"84":[46,21,78],"85":[46,21,78],"88":[46,21,78],"89":[46,21,78],"90":[46,21,78],"91":[46,21,78],"92":[46,21,78],"93":[46,21,78],"105":[46,21,78],"107":[46,21,78],"122":[46,78],"133":[46,78],"140":[46,21,78],"154":[46,21,78],"156":[46,21,78],"163":[46,78],"167":[46],"171":[46,78],"175":[46],"179":[46],"185":[46,21,78],"192":[46,78],"196":[46],"211":[46,78],"218":[46,21,78],"233":[46,21,78],"237":[46,21,78],"238":[46,21,78],"244":[46,21,78],"267":[46,21,78],"268":[46,21,78],"271":[46,21,78],"275":[46,21,78],"278":[46,21,78],"285":[46,21,78],"292":[46,78],"297":[46,78],"298":[46],"304":[46],"306":[46],"313":[46],"319":[46,78],"323":[46,78],"327":[46],"334":[46],"338":[46],"345":[46],"354":[46],"358":[46],"363":[46],"372":[46],"385":[46],"399":[46,78],"412":[46],"416":[46,21,78],"431":[46],"446":[46,21,78],"458":[46,21,78],"472":[46,21,78],"487":[46,21,78],"501":[46],"535":[46,21,78],"664":[46],"685":[46],"692":[46],"699":[46],"715":[46],"733":[46]},"packages/@n8n/agents/src/runtime/model/attachment-validation-error.ts":{"31":[118,119,22],"32":[118,119,22],"35":[118,119,22],"39":[118,119,22],"42":[118,119,22],"43":[118,119,22],"45":[118,119,22],"49":[118,119,22],"59":[118,119,22],"61":[118,119,22]},"packages/@n8n/utils/src/errors/get-error-message.ts":{"2":[46,118,119,22,208]},"packages/cli/src/modules/instance-ai/drop-rejected-attachments.ts":{"12":[119,22],"28":[119,22],"34":[119,22],"74":[119,22]},"packages/cli/src/modules/instance-ai/stream-transport-error.ts":{"13":[119,22,122]},"packages/@n8n/instance-ai/src/tools/orchestration/agent-persistence.ts":{"3":[120]},"packages/frontend/editor-ui/src/experiments/openWorkflowInAssistant/launchWorkflowThread.ts":{"24":[46,121,122]},"packages/@n8n/db/src/repositories/activity-event.repository.ts":{"36":[7,18,176],"83":[7,18,176],"88":[7,18,176],"103":[7,18,176],"112":[7,18,176],"132":[7,18,176],"168":[7,18,176],"184":[7,18,176],"211":[7,18,176],"250":[7,18,176],"259":[7,18,176],"291":[7,18,176],"323":[7,18,176],"334":[7,18,176]},"packages/cli/src/modules/breaking-changes/owners/migration-owner-suggestion.service.ts":{"44":[7,18,176],"53":[7,18,176],"59":[7,18,176],"71":[7,18,176],"89":[7,18,176],"105":[7,18,176],"111":[7,18,176],"112":[7,18,176],"122":[7,18,176],"131":[7,18,176],"137":[7,18,176],"145":[7,18,176],"161":[7,18,176]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/status-waiting.svg":{"8":[46,18]},"packages/frontend/editor-ui/src/features/execution/executions/components/ViewSubExecution.vue":{"9":[3,90,46,18,181,182],"23":[3,90,46,18,181,182],"27":[46,181,182],"41":[3,90,46,18,181,182],"55":[46]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsViewConsumedTokenCountText.vue":{"8":[18]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataParsedAiContent.vue":{"31":[18],"33":[18],"54":[18],"63":[18],"72":[18],"76":[18]},"packages/frontend/editor-ui/src/features/ndv/runData/components/ai/utils.ts":{"38":[18],"51":[18],"52":[18],"53":[18]},"packages/core/src/execution-engine/node-execution-context/utils/request-helpers/authentication.ts":{"44":[41,215,134,176],"56":[41,215,134,176],"203":[41,215,134,176]},"packages/nodes-base/nodes/Linear/GenericFunctions.ts":{"16":[41],"66":[41],"70":[41],"100":[41],"126":[41]},"packages/nodes-base/nodes/Linear/Linear.node.ts":{"109":[41],"119":[41],"136":[41],"154":[41],"172":[41],"220":[41]},"packages/nodes-base/nodes/Linear/Queries.ts":{"2":[41],"15":[41],"28":[41],"41":[41],"95":[41],"102":[41],"138":[41],"147":[41],"189":[41],"245":[41],"255":[41]},"localhost-44191/assets/index-Dv_brJ4-.js":{"3":[25]},"localhost-44191/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[25],"9":[25],"10":[25],"19":[25],"23":[25],"29":[25],"33":[25],"34":[25]},"packages/frontend/@n8n/design-system/src/components/TableBase/TableBase.vue":{"8":[25,46,152],"22":[46],"23":[46],"26":[25,46,152],"31":[25,46,152]},"packages/frontend/editor-ui/src/features/agents/components/AgentSessionTimelineHeader.vue":{"55":[25],"65":[25],"68":[25],"77":[25],"145":[25]},"packages/frontend/editor-ui/src/features/agents/components/AgentSessionTimelinePanel.vue":{"38":[25],"59":[25],"72":[25],"79":[25],"83":[25],"84":[25],"90":[25],"91":[25],"93":[25],"146":[25],"159":[25],"168":[25],"184":[25],"213":[25],"269":[25],"280":[25],"284":[25],"315":[25],"319":[25],"329":[25],"352":[25],"353":[25],"359":[25],"374":[25],"386":[25],"426":[25]},"packages/frontend/editor-ui/src/features/agents/components/AgentSessionsFilter.vue":{"15":[25],"49":[25],"65":[25],"77":[25]},"packages/frontend/editor-ui/src/features/agents/components/SessionDetailPanel.vue":{"47":[25],"66":[25],"90":[25],"163":[25],"166":[25],"180":[25],"202":[25],"225":[25],"241":[25],"251":[25],"269":[25],"277":[25]},"packages/frontend/editor-ui/src/features/agents/components/SessionEventFilter.vue":{"24":[25],"28":[25],"29":[25],"30":[25],"62":[25],"96":[25],"101":[25]},"packages/frontend/editor-ui/src/features/agents/components/SessionTimelineChart.vue":{"58":[25],"65":[25],"85":[25],"89":[25],"95":[25],"108":[25],"136":[25],"165":[25],"192":[25],"194":[25],"224":[25],"246":[25],"290":[25],"291":[25],"297":[25],"301":[25],"317":[25],"381":[25]},"packages/frontend/editor-ui/src/features/agents/components/SessionTimelinePill.vue":{"7":[25],"19":[25],"48":[25],"49":[25]},"packages/frontend/editor-ui/src/features/agents/components/SessionTimelineRow.vue":{"25":[25],"36":[25],"43":[25],"44":[25],"46":[25],"51":[25],"57":[25],"85":[25],"87":[25],"97":[25],"124":[25],"129":[25]},"packages/frontend/editor-ui/src/features/agents/components/SessionTimelineTable.vue":{"13":[25],"78":[25],"84":[25],"99":[25],"102":[25],"103":[25],"104":[25],"109":[25],"113":[25],"124":[25],"136":[25],"139":[25],"142":[25],"150":[25],"168":[25],"192":[25],"202":[25],"210":[25],"211":[25],"220":[25],"229":[25],"248":[25],"257":[25]},"packages/frontend/editor-ui/src/features/agents/components/ToolIoView.vue":{"45":[25],"47":[25],"60":[25],"183":[25],"184":[25],"186":[25]},"packages/frontend/editor-ui/src/features/agents/components/WorkflowExecutionLogViewer.vue":{"24":[25],"40":[25],"52":[25],"57":[25],"59":[25],"68":[25],"69":[25],"72":[25],"84":[25],"92":[25],"94":[25],"98":[25],"109":[25],"130":[25],"138":[25],"161":[25],"175":[25],"187":[25],"195":[25]},"packages/frontend/editor-ui/src/features/agents/composables/useBackOrFallback.ts":{"9":[25]},"packages/frontend/editor-ui/src/features/agents/composables/useSubAgentNames.ts":{"12":[25],"25":[25]},"packages/frontend/editor-ui/src/features/agents/session-timeline.styles.ts":{"6":[25],"41":[25]},"packages/frontend/editor-ui/src/features/agents/session-timeline.utils.ts":{"33":[25],"38":[25],"81":[25],"109":[25],"196":[25],"220":[25],"242":[25],"253":[25],"326":[25],"335":[25],"342":[25],"343":[25],"348":[25],"351":[25],"394":[25],"494":[25],"498":[25],"514":[25],"519":[25],"589":[25],"689":[25],"719":[25]},"packages/frontend/editor-ui/src/features/agents/utils/background-job-labels.ts":{"10":[25]},"packages/frontend/editor-ui/src/features/agents/utils/thread-title.ts":{"27":[25],"38":[25]},"packages/frontend/editor-ui/src/features/agents/views/AgentSessionTimelineView.vue":{"50":[25],"51":[25],"52":[25],"76":[25],"84":[25],"91":[25],"96":[25],"112":[25],"128":[25],"135":[25],"140":[25],"150":[25],"168":[25],"179":[25],"190":[25],"195":[25],"196":[25],"201":[25],"202":[25],"203":[25],"222":[25],"228":[25],"244":[25],"268":[25],"301":[25],"307":[25]},"packages/frontend/editor-ui/src/features/agents/views/AgentSessionsListView.vue":{"58":[25],"59":[25],"60":[25],"75":[25],"100":[25],"133":[25],"178":[25],"283":[25],"324":[25],"346":[25]},"packages/frontend/editor-ui/src/features/ndv/runData/components/StandaloneRunData.vue":{"26":[25]},"packages/frontend/editor-ui/src/features/ndv/runData/components/StandaloneRunDataHost.vue":{"38":[25],"59":[25],"86":[25],"99":[25],"132":[25],"155":[25],"156":[25],"161":[25],"169":[25],"172":[25]},"localhost-34483/assets/index-Dv_brJ4-.js":{"3":[30,39,93,152,165,168,181,189]},"localhost-34483/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[30,39,93,152,165,168,181,189],"9":[30,39,93,152,165,168,181,189],"10":[30,39,93,152,165,168,181,189],"19":[30,39,93,152,165,168,181,189],"23":[30,39,93,152,165,168,181,189],"29":[30,39,93,152,165,168,181,189],"33":[30,39,93,152,165,168,181,189],"34":[30,39,93,152,165,168,181,189]},"packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/BaseMessage.vue":{"16":[27,28,29,30,31,33,46],"22":[46],"23":[46],"29":[46],"31":[27,28,29,30,31,33,46]},"packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/MessageWrapper.vue":{"22":[27,28,29,30,31,33,46],"30":[27,28,29,30,31,33,46],"33":[27,28,29,30,31,33,46],"47":[28,46],"48":[28,46],"49":[46],"51":[46]},"packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/TextMessage.vue":{"31":[30,46],"40":[27,28,29,30,31,33,46],"42":[27,28,29,30,31,33,46],"48":[46],"52":[27,28,29,30,31,33,46],"53":[27,28,29,30,31,33,46],"58":[27,28,29,30,31,33,46],"59":[46],"61":[46],"67":[46],"70":[46],"73":[46],"77":[46],"80":[27,28,29,30,31,33,46],"88":[46],"89":[27,28,29,30,31,33,46],"112":[46],"136":[46],"137":[30,46]},"packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/ThinkingMessage.vue":{"14":[27,28,29,30,31,33,46],"21":[27,28,29,30,31,33,46],"23":[27,28,29,30,31,33,46],"24":[46],"32":[27,28,29,30,31,33,46],"34":[46],"38":[27,28,29,30,31,33,46],"48":[27,28,29,30,31,33,46],"64":[27,28,29,30,31,33,46],"65":[27,28,29,30,31,33,46]},"packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/helpers.ts":{"9":[27,28,29,30,31,33,46]},"packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/useMarkdown.ts":{"6":[27,28,29,30,31,33,46],"22":[46],"29":[27,28,29,30,31,33,46]},"packages/frontend/@n8n/design-system/src/components/BlinkingCursor/BlinkingCursor.vue":{"2":[27,28,29,30,31,46]},"packages/frontend/@n8n/design-system/src/types/assistant.ts":{"165":[27,28,29,30,31,33,46],"221":[27,28,29,30,31,33,46],"227":[27,28,29,30,31,33,46],"239":[27,28,29,30,31,33,46]},"packages/frontend/editor-ui/src/features/ai/assistant/assistant.api.ts":{"19":[31,33,46],"46":[27,28,29,30,46],"75":[28,46],"88":[46],"100":[46],"110":[46],"130":[31,102,33,46],"137":[46],"141":[46],"145":[46],"153":[46],"162":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Chat/AskAssistantChat.vue":{"13":[27,28,29,30,46,63],"27":[27,28,29,30,46,63],"32":[27,28,29,30,46,63],"34":[27,28,29,30,46,63],"39":[27,30,46],"50":[27,30,46],"65":[28,46],"72":[28,46],"80":[27,28,30,46,63],"84":[27,28,29,30,46,63],"87":[27,30,46],"96":[27,46],"103":[46],"105":[46],"108":[27,28,29,30,46,63]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Chat/AskModeEmptyState.vue":{"5":[27,28,29,30,46,63],"6":[27,28,29,30,46,63]},"packages/frontend/editor-ui/src/app/components/VersionCard.vue":{"14":[39,46],"16":[46],"18":[39,46],"42":[39,46],"46":[46],"65":[46]},"packages/@n8n/api-types/src/dto/invitation/invite-users-request.dto.ts":{"12":[93,69]},"packages/cli/src/public-api/v1/shared/services/pagination.service.ts":{"12":[92,93],"20":[92,93],"48":[92,93],"60":[92,93],"72":[92,93],"81":[92,93]},"packages/frontend/@n8n/design-system/src/components/N8nExternalLink/ExternalLink.vue":{"20":[93,46,154,100],"27":[93,46,154,100]},"packages/frontend/editor-ui/src/app/utils/rbac/checks/isInstanceOwner.ts":{"4":[93,95,46,154,100]},"packages/frontend/editor-ui/src/features/core/auth/views/SettingsPersonalView.vue":{"66":[93,154,100],"69":[93,154,100],"71":[93,154,100],"75":[93,154,100],"85":[93,154,100],"89":[93,154,100],"90":[93,154,100],"100":[93,154,100],"101":[93,154,100],"102":[93,154,100],"106":[93,154,100],"112":[93,154,100],"116":[93,154,100],"175":[93,154,100],"188":[93,154,100],"215":[154,100],"234":[93,154,100],"238":[93,154,100],"255":[93,154,100],"264":[154,100],"274":[154,100],"283":[154,100],"290":[154,100],"291":[154,100],"295":[154,100],"317":[100],"330":[100],"341":[100],"351":[100],"393":[100],"404":[100],"412":[100],"439":[93,154,100],"446":[93,154,100],"456":[93,154,100],"480":[154,100],"511":[93,154,100],"514":[93,154,100],"515":[93,154,100],"526":[93,154,100],"538":[93,154,100],"549":[93,154,100],"564":[93,154,100],"569":[93,154,100]},"packages/cli/src/environments.ee/variables/variables.controller.ee.ts":{"18":[152],"21":[152],"31":[152],"49":[152],"59":[152],"79":[152]},"packages/frontend/@n8n/design-system/src/components/N8nCommandBar/CommandBarItem.vue":{"9":[46,187],"21":[46,187],"35":[46],"42":[46,187],"56":[46],"58":[46],"59":[46,187]},"packages/frontend/@n8n/design-system/src/components/N8nDatatable/Datatable.vue":{"16":[46,152],"30":[46,152],"34":[46],"38":[46,152],"47":[46],"51":[46],"65":[46],"69":[46,152],"73":[46,152],"82":[46,152],"92":[46,152],"94":[46],"95":[46],"125":[46,152],"126":[46,152],"127":[46,152]},"packages/frontend/editor-ui/src/features/collaboration/projects/views/ProjectVariables.vue":{"67":[152],"77":[152],"81":[152],"86":[152],"90":[152],"92":[152],"93":[152],"108":[152],"113":[152],"149":[152],"183":[152],"192":[152],"196":[152],"215":[152],"221":[152],"268":[152],"280":[152],"289":[152],"313":[152],"399":[152],"433":[152],"434":[152],"450":[152],"451":[152],"462":[152]},"packages/frontend/editor-ui/src/features/settings/environments.ee/components/VariableModal.vue":{"58":[46,152],"63":[46,152],"89":[46,152],"94":[46,152],"101":[46,152],"105":[46],"108":[46,152],"109":[46,152],"112":[46,152],"125":[46,152],"151":[46,152],"152":[46,152],"169":[46,152],"170":[46,152],"174":[46,152],"184":[46,152],"188":[46,152],"197":[46],"202":[46],"207":[46,152],"243":[46,152],"248":[46,152],"265":[46,152],"275":[46,152],"278":[46,152],"280":[46],"281":[46],"294":[46,152],"301":[46,152],"309":[46],"325":[46,152],"330":[46,152],"336":[46,152],"340":[46],"343":[46,152],"345":[46,152],"351":[46,152],"354":[46],"365":[46,152]},"packages/frontend/editor-ui/src/features/settings/environments.ee/environments.api.ts":{"10":[46,152,165,168,181,189],"21":[46,152],"29":[46,152],"41":[46,152]},"packages/cli/src/modules/instance-registry/instance-registry.controller.ts":{"9":[165],"16":[165],"24":[165],"39":[165]},"packages/cli/src/modules/instance-registry/instance-registry.service.ts":{"27":[165],"36":[165],"50":[165],"68":[165],"73":[165],"82":[165],"87":[165],"97":[165],"106":[165],"110":[165],"114":[165],"118":[165],"137":[165]},"localhost-34483/assets/verified-Dido3Ow4.js":{"8":[165]},"packages/frontend/@n8n/rest-api-client/src/api/instance-registry.ts":{"6":[46,165]},"packages/frontend/editor-ui/src/app/components/AboutModal.vue":{"16":[46,165],"24":[46,165],"28":[46,165],"32":[46],"49":[46],"57":[46,165],"68":[46,165],"72":[46,165],"75":[46,165],"80":[46,165],"83":[46,165],"88":[46,165],"91":[46,165],"92":[46,165],"98":[46,165],"101":[46,165],"102":[46,165],"108":[46,165],"111":[46,165],"116":[46,165],"119":[46,165],"120":[46,165],"127":[46,165]},"packages/frontend/editor-ui/src/features/workflows/components/ImportWorkflowUrlModal.vue":{"10":[46,165,189],"16":[46,165,189],"20":[46,165,189],"24":[46,189],"29":[46,165,189],"32":[46,165,189],"45":[46,165,189],"60":[46,165,189],"68":[46,165,189],"76":[46,165,189]},"packages/frontend/editor-ui/src/app/components/WorkflowPreviewHost.vue":{"45":[168,191],"50":[168,191],"61":[168,191],"76":[168,191],"90":[168,191],"122":[168,191],"124":[168,191],"128":[168,191]},"packages/frontend/editor-ui/src/features/workflows/workflowHistory/components/WorkflowHistoryContent.vue":{"40":[168],"55":[168],"70":[168],"81":[168],"84":[168],"97":[168],"101":[168],"107":[168],"129":[168],"130":[168],"135":[168],"150":[168],"152":[168],"172":[168]},"packages/frontend/editor-ui/src/features/workflows/workflowHistory/components/WorkflowHistoryList.vue":{"22":[168],"49":[168],"61":[168],"73":[168],"82":[168],"86":[168],"92":[168],"119":[168],"151":[168],"179":[168],"184":[168]},"packages/frontend/editor-ui/src/features/workflows/workflowHistory/components/WorkflowHistoryListItem.vue":{"26":[168],"58":[168],"63":[168],"74":[168],"83":[168],"99":[168],"165":[168],"172":[168],"203":[168],"211":[168],"214":[168]},"packages/frontend/editor-ui/src/features/workflows/workflowHistory/views/WorkflowHistory.vue":{"61":[168],"78":[168],"81":[168],"92":[168],"93":[168],"100":[168],"101":[168],"106":[168],"112":[168],"117":[168],"127":[168],"128":[168],"143":[168],"154":[168],"169":[168],"177":[168],"181":[168],"199":[168],"228":[168],"573":[168],"588":[168],"625":[168],"644":[168]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/execute-sub-workflow.svg":{"11":[128,181,182,87]},"packages/@n8n/imap/src/connection-options.ts":{"34":[89]},"packages/@n8n/imap/src/errors.ts":{"2":[89],"8":[89],"14":[89]},"packages/@n8n/imap/src/headers.ts":{"3":[89],"7":[89],"9":[89]},"packages/@n8n/imap/src/imap-simple.ts":{"68":[89],"72":[89],"76":[89],"77":[89],"103":[89],"107":[89],"157":[89],"166":[89],"178":[89],"184":[89],"190":[89],"195":[89],"201":[89],"207":[89],"216":[89],"218":[89],"221":[89],"226":[89],"229":[89],"233":[89],"237":[89],"244":[89],"257":[89],"262":[89],"263":[89],"278":[89],"283":[89],"286":[89],"289":[89],"304":[89],"321":[89],"325":[89],"334":[89],"363":[89],"373":[89],"387":[89],"392":[89],"396":[89],"405":[89],"406":[89],"407":[89],"414":[89],"425":[89],"444":[89],"457":[89],"484":[89],"499":[89],"513":[89],"528":[89],"554":[89],"564":[89],"569":[89],"576":[89],"585":[89],"586":[89],"588":[89],"593":[89],"594":[89]},"packages/@n8n/imap/src/message.ts":{"4":[89],"6":[89],"24":[89],"25":[89],"34":[89],"38":[89],"40":[89],"45":[89],"47":[89]},"packages/cli/src/controllers/oauth/oauth1-credential.controller.ts":{"13":[89],"22":[89],"37":[89]},"packages/cli/src/oauth/oauth-browser-binding.service.ts":{"16":[46,194,178,89],"19":[46,194,178,89],"31":[46,194,178,89],"48":[46,194,178,89],"58":[46,194,178,89],"72":[46,194,178,89]},"packages/cli/src/oauth/oauth.service.ts":{"109":[46,194,178,89],"119":[46,194,178,89],"123":[46,194,178,89],"130":[46,194,178,89],"140":[46,194,178,89],"176":[46,194,178,89],"180":[46,194,178,89],"184":[46,194,178,89],"193":[46,194,178,89],"221":[46,194,178,89],"225":[46,194,178,89],"234":[46,194,178,89],"248":[46,194,178,89],"287":[46,194,178,89],"292":[46,194,178,89],"329":[46,194,178,89],"357":[46,194,178,89],"364":[46,194,178,89],"374":[46,194,178,89],"381":[46,194,178,89],"396":[46,194,178,89],"411":[46,194,178,89],"437":[46,194,178,89],"453":[46,194,178,89],"472":[46,194,178,89],"481":[46,194,178,89],"489":[46,194,178,89],"497":[46,194,178,89],"591":[46,194,178,89],"604":[46,194,178,89],"643":[46,194,178,89],"658":[46,194,178,89],"674":[46,194,178,89],"705":[46,194,178,89],"706":[46,194,178,89],"709":[46,194,178,89],"719":[46,194,178,89],"728":[46,194,178,89],"743":[46,194,178,89],"762":[46,194,178,89],"768":[46,194,178,89],"777":[46,194,178,89],"788":[46,194,178,89],"803":[46,194,178,89],"812":[46,194,178,89],"830":[46,194,178,89],"903":[46,194,178,89],"917":[46,194,178,89],"920":[46,194,178,89],"927":[46,194,178,89],"1006":[46,194,178,89],"1017":[46,194,178,89],"1106":[46,194,178,89],"1167":[46,194,178,89],"1219":[46,194,178,89],"1237":[46,194,178,89],"1256":[46,194,178,89],"1282":[46,194,178,89],"1355":[46,194,178,89],"1367":[46,194,178,89],"1411":[46,194,178,89],"1439":[46,194,178,89],"1452":[46,194,178,89],"1470":[46,194,178,89],"1515":[46,194,178,89],"1534":[46,194,178,89],"1590":[46,194,178,89],"1601":[46,194,178,89],"1627":[46,194,178,89]},"packages/cli/src/oauth/validate-oauth-url.ts":{"12":[46,194,178,89]},"packages/nodes-base/nodes/EmailReadImap/EmailReadImap.node.ts":{"8":[89]},"packages/nodes-base/nodes/EmailReadImap/connection-events.ts":{"6":[89],"7":[89]},"packages/nodes-base/nodes/EmailReadImap/credentials.ts":{"6":[89]},"packages/nodes-base/nodes/EmailReadImap/search-criteria.ts":{"27":[89],"28":[89],"29":[89],"30":[89],"31":[89],"32":[89],"33":[89],"37":[89],"38":[89],"39":[89],"40":[89],"41":[89],"42":[89],"46":[89],"47":[89],"51":[89],"52":[89],"57":[89],"67":[89],"75":[89],"92":[89],"106":[89],"107":[89],"108":[89],"112":[89],"115":[89],"228":[89],"242":[89],"248":[89],"249":[89],"251":[89],"252":[89],"257":[89],"268":[89],"271":[89],"277":[89],"284":[89]},"packages/nodes-base/nodes/EmailReadImap/v1/EmailReadImapV1.node.ts":{"31":[89],"63":[89],"68":[89],"74":[89],"86":[89],"106":[89],"112":[89],"121":[89],"130":[89],"302":[89],"311":[89],"339":[89],"353":[89],"385":[89],"410":[89],"458":[89],"462":[89],"468":[89],"471":[89],"475":[89]},"packages/nodes-base/nodes/EmailReadImap/v2/EmailReadImapV2.node.ts":{"193":[89],"202":[89],"234":[89],"276":[89],"319":[89],"343":[89],"347":[89],"351":[89],"357":[89],"362":[89],"366":[89]},"packages/nodes-base/nodes/EmailReadImap/v2/utils.ts":{"30":[89],"68":[89],"95":[89],"137":[89],"142":[89],"148":[89],"163":[89],"189":[89],"195":[89],"204":[89],"214":[89]},"packages/nodes-base/nodes/NextCloud/GenericFunctions.ts":{"14":[89]},"packages/nodes-base/nodes/NextCloud/NextCloud.node.ts":{"872":[89],"1103":[89],"1190":[89],"1198":[89],"1284":[89],"1292":[89],"1326":[89],"1334":[89],"1364":[89],"1372":[89],"1392":[89],"1397":[89],"1405":[89]},"packages/nodes-base/nodes/Shopify/GenericFunctions.ts":{"12":[89],"85":[89],"124":[89]},"packages/nodes-base/nodes/Shopify/ShopifyTrigger.node.ts":{"335":[89],"350":[89],"373":[89],"389":[89]},"packages/nodes-base/nodes/Twitter/Twitter.node.ts":{"8":[89]},"packages/nodes-base/nodes/Twitter/V1/GenericFunctions.ts":{"14":[89],"46":[89],"69":[89],"81":[89]},"packages/nodes-base/nodes/Twitter/V1/TwitterV1.node.ts":{"27":[89],"76":[89],"92":[89],"123":[89],"164":[89],"171":[89]},"packages/nodes-base/nodes/Twitter/V2/GenericFunctions.ts":{"13":[89],"60":[89],"83":[89],"105":[89]},"packages/nodes-base/nodes/Twitter/V2/TwitterV2.node.ts":{"31":[89],"100":[89],"116":[89]},"packages/@n8n/api-types/src/dto/workflows/base-workflow-public.dto.ts":{"60":[92,46],"110":[46],"111":[92],"136":[46],"137":[92],"166":[46],"168":[92]},"packages/@n8n/api-types/src/dto/workflows/workflow-public.dto.ts":{"29":[46],"30":[92],"37":[46],"38":[92]},"packages/cli/src/metrics/prometheus/token-exchange-metrics.service.ts":{"21":[92],"26":[92],"30":[92],"71":[92],"75":[92],"80":[92],"84":[92],"89":[92],"93":[92]},"packages/cli/src/modules/token-exchange/controllers/embed-auth.controller.ts":{"21":[92],"36":[92],"54":[92],"65":[92]},"packages/cli/src/modules/token-exchange/controllers/token-exchange.controller.ts":{"21":[92],"42":[92]},"packages/cli/src/modules/token-exchange/database/repositories/token-exchange-jti.repository.ts":{"14":[92],"18":[92],"31":[92],"32":[92],"80":[92],"81":[92]},"packages/cli/src/modules/token-exchange/database/repositories/trusted-key.repository.ts":{"8":[92],"12":[92],"16":[92]},"packages/cli/src/modules/token-exchange/services/identity-resolution.service.ts":{"32":[92],"36":[92],"44":[92],"57":[92],"72":[92],"96":[92],"158":[92],"176":[92],"209":[92],"223":[92],"266":[92],"320":[92],"366":[92]},"packages/cli/src/modules/token-exchange/services/jti-store.service.ts":{"25":[92],"34":[92]},"packages/cli/src/modules/token-exchange/services/scoped-jwt.strategy.ts":{"17":[92],"22":[92],"67":[92],"74":[92],"97":[92],"104":[92]},"packages/cli/src/modules/token-exchange/services/token-exchange.service.ts":{"34":[92],"56":[92],"142":[92],"156":[92]},"packages/cli/src/modules/token-exchange/services/trusted-key.service.ts":{"72":[92],"95":[92],"102":[92],"117":[92],"169":[92],"177":[92],"181":[92],"187":[92],"213":[92],"217":[92],"242":[92],"251":[92],"252":[92],"254":[92],"255":[92],"300":[92],"325":[92],"340":[92],"366":[92],"370":[92],"373":[92],"395":[92],"412":[92],"431":[92],"447":[92],"459":[92],"468":[92],"508":[92],"553":[92]},"packages/cli/src/modules/token-exchange/token-exchange.errors.ts":{"10":[92],"23":[92]},"packages/cli/src/modules/token-exchange/token-exchange.schemas.ts":{"29":[92]},"packages/cli/src/public-api/v1/controllers/workflows.public.controller.ts":{"96":[92],"102":[92],"103":[92],"106":[92],"115":[92],"125":[92],"137":[92],"147":[92],"163":[92],"178":[92],"189":[92],"199":[92],"207":[92],"219":[92],"223":[92],"235":[92],"278":[92],"314":[92],"348":[92],"401":[92],"450":[92],"476":[92],"499":[92],"521":[92],"535":[92],"564":[92],"574":[92],"583":[92],"594":[92],"616":[92],"642":[92],"670":[92],"688":[92],"706":[92],"725":[92],"752":[92],"795":[92],"823":[92],"831":[92],"852":[92]},"packages/cli/src/public-api/v1/shared/project.mapper.ts":{"5":[92],"9":[92]},"packages/cli/src/utils/validate-redirect-url.ts":{"8":[40,92]},"localhost-33755/assets/index-Dv_brJ4-.js":{"3":[89]},"localhost-33755/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[89],"9":[89],"10":[89],"19":[89],"23":[89],"29":[89],"33":[89],"34":[89]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/email-trigger.svg":{"11":[89]},"packages/frontend/@n8n/design-system/src/components/N8nTags/Tags.vue":{"21":[46,190,89],"37":[46,190,89],"45":[46,190],"47":[46],"50":[46,190,89],"56":[46,190,89],"60":[46],"68":[46]},"packages/frontend/editor-ui/src/app/components/GoBackButton.vue":{"11":[89]},"packages/frontend/editor-ui/src/app/components/NodeList.vue":{"19":[89,191],"23":[191],"27":[89,191],"31":[89,191],"36":[89,191],"42":[89,191]},"packages/frontend/editor-ui/src/features/workflows/templates/components/TemplateCard.vue":{"12":[89,191],"37":[89],"41":[191],"43":[89,191],"65":[89,191],"71":[89,191],"75":[89,191]},"packages/frontend/editor-ui/src/features/workflows/templates/components/TemplateDetails.vue":{"21":[89],"32":[89],"34":[89],"49":[89],"59":[89],"62":[89],"79":[89],"86":[89],"89":[89]},"packages/frontend/editor-ui/src/features/workflows/templates/components/TemplateList.vue":{"38":[89,191],"47":[89,191],"71":[191],"74":[89],"83":[89,191],"90":[89,191],"97":[191],"98":[89]},"packages/frontend/editor-ui/src/features/workflows/templates/setupTemplate.store.ts":{"39":[89],"56":[89],"60":[89],"80":[89],"98":[89],"115":[89],"128":[89],"149":[89],"176":[89]},"packages/frontend/editor-ui/src/features/workflows/templates/utils/templateActions.ts":{"30":[89],"72":[89],"100":[191],"128":[89,191],"132":[89,191],"137":[89,191]},"packages/frontend/editor-ui/src/features/workflows/templates/views/SetupWorkflowFromTemplateView.vue":{"22":[89],"25":[89],"26":[89],"28":[89],"49":[89],"57":[89],"79":[89],"89":[89],"109":[89],"135":[89],"143":[89],"151":[89]},"packages/frontend/editor-ui/src/features/workflows/templates/views/TemplatesCollectionView.vue":{"32":[89],"37":[89],"39":[89],"44":[89],"45":[89],"48":[89],"49":[89],"64":[89],"87":[89],"88":[89],"98":[89],"117":[89],"121":[89],"124":[89]},"packages/@n8n/agents/src/runtime/memory/memory-lifecycle.ts":{"8":[26],"12":[26],"16":[26],"23":[26],"28":[26],"33":[26],"38":[26],"49":[26],"64":[26],"76":[26]},"packages/@n8n/agents/src/runtime/tools/sdk-owned-tool.ts":{"5":[26],"9":[26]},"packages/@n8n/agents/src/runtime/tools/todos-core.ts":{"12":[26],"19":[26],"35":[26],"44":[26]},"packages/@n8n/agents/src/runtime/tools/write-todos-tool.ts":{"21":[26],"48":[26],"52":[26],"90":[26]},"packages/@n8n/agents/src/sdk/metadata-enriched-tracer.ts":{"6":[26],"11":[26],"34":[26],"59":[26],"66":[26]},"packages/@n8n/agents/src/workspace/sandbox/daytona-auth-manager.ts":{"54":[26],"71":[26],"82":[26],"86":[26],"91":[26],"97":[26]},"packages/@n8n/agents/src/workspace/sandbox/daytona-sandbox.ts":{"165":[26],"170":[26],"182":[26],"196":[26],"226":[26],"243":[26],"250":[26],"271":[26],"293":[26],"338":[26],"350":[26],"374":[26],"388":[26],"394":[26],"399":[26],"400":[26],"433":[26],"437":[26],"438":[26],"452":[26],"456":[26],"478":[26],"496":[26],"511":[26],"533":[26],"556":[26],"572":[26],"573":[26],"576":[26],"582":[26],"587":[26],"595":[26],"635":[26],"675":[26],"691":[26],"717":[26],"726":[26],"738":[26],"754":[26],"761":[26],"764":[26],"770":[26],"776":[26],"835":[26],"850":[26],"858":[26],"864":[26]},"packages/@n8n/api-types/src/agents/model-providers.ts":{"27":[26,46],"58":[26]},"packages/@n8n/api-types/src/agents/sanitize-agent-tool-name.ts":{"4":[26,46]},"packages/@n8n/api-types/src/agents/types.ts":{"63":[26,46],"73":[26,46],"84":[26,46],"89":[26,46],"90":[26,46],"93":[26,46],"108":[26,46]},"packages/@n8n/backend-common/src/locking/in-process-lock.service.ts":{"24":[26],"27":[26],"36":[26],"37":[26],"52":[26],"69":[26],"72":[26],"80":[26],"97":[26],"101":[26]},"packages/@n8n/backend-common/src/locking/lock.service.ts":{"10":[26],"14":[26],"18":[26]},"packages/@n8n/errors/src/response-errors/conflict.error.ts":{"4":[26,192,185]},"packages/cli/src/modules/agents/agent-chat-attachment.service.ts":{"43":[26],"60":[26],"67":[26],"103":[26],"114":[26],"133":[26],"141":[26],"149":[26],"159":[26],"163":[26],"168":[26],"176":[26],"182":[26],"184":[26],"196":[26],"198":[26],"232":[26]},"packages/cli/src/modules/agents/agent-chat-execution.service.ts":{"61":[26],"73":[26],"83":[26],"95":[26],"103":[26],"120":[26],"124":[26],"155":[26],"165":[26],"175":[26],"185":[26],"189":[26],"196":[26],"210":[26],"229":[26],"237":[26],"247":[26],"293":[26]},"packages/cli/src/modules/agents/agent-conversation-state.service.ts":{"9":[26],"15":[26],"31":[26]},"packages/cli/src/modules/agents/agent-execution-update-broadcaster.ts":{"20":[26],"31":[26],"32":[26],"41":[26],"57":[26],"58":[26],"63":[26],"80":[26],"81":[26],"86":[26],"102":[26],"106":[26],"110":[26],"114":[26],"122":[26]},"packages/cli/src/modules/agents/agent-knowledge.service.ts":{"33":[26],"42":[26],"64":[26],"70":[26],"73":[26],"76":[26],"83":[26],"94":[26],"108":[26],"114":[26],"119":[26],"129":[26],"134":[26],"147":[26],"155":[26],"174":[26],"188":[26],"192":[26],"193":[26],"197":[26],"201":[26],"215":[26],"222":[26],"225":[26],"228":[26],"235":[26],"237":[26],"265":[26],"271":[26],"279":[26],"280":[26],"283":[26],"286":[26]},"packages/cli/src/modules/agents/agent-message-mapper.ts":{"4":[26],"26":[26],"41":[26]},"packages/cli/src/modules/agents/agent-message-steering.service.ts":{"31":[26],"42":[26],"49":[26],"50":[26],"58":[26],"63":[26],"86":[26],"102":[26],"106":[26],"124":[26],"134":[26],"156":[26],"186":[26],"192":[26],"229":[26],"235":[26],"242":[26],"245":[26]},"packages/cli/src/modules/agents/agent-queued-preview-stream.service.ts":{"36":[26],"44":[26],"47":[26],"53":[26],"55":[26],"68":[26],"75":[26],"81":[26],"91":[26],"97":[26],"101":[26],"108":[26],"114":[26],"115":[26],"127":[26],"141":[26]},"packages/cli/src/modules/agents/agent-run-tracing.service.ts":{"46":[26],"59":[26],"65":[26],"77":[26],"114":[26]},"packages/cli/src/modules/agents/agent-runtime-reconstruction.service.ts":{"214":[26],"233":[26],"263":[26],"270":[26],"292":[26],"384":[26],"432":[26],"438":[26],"448":[26],"449":[26],"452":[26],"458":[26],"484":[26],"493":[26],"497":[26],"501":[26],"505":[26],"519":[26],"543":[26],"577":[26],"608":[26],"616":[26],"628":[26],"677":[26],"683":[26],"689":[26],"696":[26],"704":[26],"713":[26],"718":[26],"747":[26],"748":[26],"756":[26],"763":[26],"771":[26],"789":[26],"795":[26],"816":[26],"871":[26],"892":[26],"912":[26],"952":[26],"976":[26],"984":[26],"998":[26],"1021":[26],"1080":[26],"1090":[26],"1147":[26],"1154":[26],"1175":[26],"1180":[26],"1232":[26]},"packages/cli/src/modules/agents/agent-sandbox-principal.ts":{"38":[26],"42":[26],"51":[26],"74":[26]},"packages/cli/src/modules/agents/agent-sandbox-runtime.service.ts":{"71":[26],"83":[26],"94":[26],"107":[26],"116":[26],"122":[26],"130":[26],"139":[26],"144":[26],"164":[26],"179":[26],"215":[26],"243":[26],"267":[26],"276":[26],"287":[26],"291":[26],"298":[26],"315":[26],"345":[26],"365":[26],"401":[26],"442":[26],"445":[26],"454":[26],"477":[26]},"packages/cli/src/modules/agents/agent-sse-stream.ts":{"21":[26],"31":[26],"35":[26],"45":[26],"51":[26],"59":[26],"63":[26],"77":[26],"88":[26],"104":[26],"111":[26],"149":[26],"231":[26],"305":[26],"317":[26],"328":[26]},"packages/cli/src/modules/agents/agent-telemetry.ts":{"15":[26],"20":[26],"24":[26],"34":[26],"40":[26],"45":[26],"46":[26],"53":[26],"74":[26],"87":[26]},"packages/cli/src/modules/agents/agent-test-chat.service.ts":{"10":[26],"17":[26],"26":[26],"33":[26],"38":[26],"49":[26],"56":[26]},"packages/cli/src/modules/agents/agent-test-run.service.ts":{"135":[26],"140":[26],"153":[26],"175":[26],"182":[26],"221":[26],"235":[26],"241":[26],"244":[26],"256":[26],"262":[26],"268":[26],"283":[26],"311":[26],"339":[26],"348":[26],"352":[26],"366":[26],"403":[26],"437":[26],"451":[26]},"packages/cli/src/modules/agents/agent-tool-approval.service.ts":{"15":[26],"20":[26],"32":[26],"33":[26]},"packages/cli/src/modules/agents/agent-turn-execution.service.ts":{"86":[26],"101":[26],"110":[26],"114":[26],"125":[26],"158":[26],"168":[26],"175":[26],"179":[26],"199":[26],"208":[26],"247":[26],"255":[26],"264":[26],"292":[26],"294":[26],"301":[26],"318":[26],"331":[26],"355":[26],"377":[26],"386":[26],"396":[26],"413":[26],"427":[26],"453":[26],"479":[26],"512":[26],"518":[26]},"packages/cli/src/modules/agents/background/agent-background-job.service.ts":{"74":[26],"83":[26],"86":[26],"90":[26],"117":[26],"132":[26],"136":[26],"137":[26],"138":[26],"150":[26],"169":[26],"189":[26],"210":[26],"227":[26],"252":[26],"279":[26],"284":[26],"296":[26],"311":[26],"318":[26],"324":[26],"328":[26],"333":[26],"347":[26],"363":[26],"370":[26],"381":[26],"382":[26],"388":[26],"394":[26],"402":[26],"411":[26],"434":[26],"450":[26],"466":[26],"476":[26],"483":[26],"513":[26],"547":[26],"560":[26],"566":[26],"576":[26],"589":[26],"604":[26],"608":[26],"615":[26],"625":[26],"628":[26],"650":[26],"658":[26],"663":[26],"666":[26],"669":[26],"689":[26],"694":[26],"718":[26],"759":[26],"777":[26],"786":[26],"794":[26],"799":[26],"814":[26],"828":[26],"864":[26],"890":[26],"922":[26],"939":[26],"944":[26],"952":[26],"954":[26],"974":[26],"999":[26],"1050":[26],"1054":[26],"1065":[26],"1089":[26],"1117":[26]},"packages/cli/src/modules/agents/background/agent-wake.service.ts":{"54":[26],"71":[26],"84":[26],"89":[26],"95":[26],"99":[26],"109":[26],"118":[26],"126":[26],"143":[26],"145":[26],"153":[26],"160":[26],"168":[26],"170":[26],"177":[26],"182":[26],"189":[26],"194":[26],"214":[26],"229":[26],"260":[26],"299":[26],"307":[26],"318":[26],"329":[26],"345":[26]},"packages/cli/src/modules/agents/background/background-job-messages.ts":{"12":[26],"15":[26],"17":[26],"20":[26],"24":[26],"25":[26],"31":[26],"36":[26],"46":[26]},"packages/cli/src/modules/agents/background/background-job-tools.ts":{"43":[26],"47":[26],"50":[26],"78":[26],"133":[26],"155":[26],"166":[26],"168":[26],"171":[26],"183":[26],"190":[26],"204":[26],"242":[26],"256":[26],"270":[26],"275":[26],"284":[26]},"packages/cli/src/modules/agents/background/sub-agent-background-runner.ts":{"68":[26],"78":[26],"110":[26],"141":[26],"156":[26],"163":[26],"196":[26],"210":[26],"215":[26],"226":[26],"243":[26],"245":[26],"249":[26],"256":[26],"304":[26],"322":[26],"323":[26],"333":[26],"356":[26],"358":[26],"361":[26],"368":[26],"373":[26],"375":[26],"389":[26],"392":[26],"422":[26]},"packages/cli/src/modules/agents/budget-guardrail.ts":{"33":[26],"38":[26],"52":[26],"71":[26],"82":[26],"96":[26],"97":[26],"103":[26],"144":[26],"149":[26],"184":[26],"193":[26],"207":[26],"213":[26],"227":[26],"232":[26]},"packages/cli/src/modules/agents/execution-recorder.ts":{"33":[26],"35":[26],"46":[26],"52":[26],"77":[26],"104":[26],"114":[26],"124":[26],"127":[26],"128":[26],"146":[26],"156":[26],"173":[26],"179":[26],"198":[26],"203":[26],"288":[26],"301":[26],"347":[26],"351":[26],"358":[26],"370":[26],"475":[26],"479":[26],"484":[26],"503":[26],"526":[26],"549":[26],"551":[26],"579":[26],"623":[26],"638":[26],"650":[26],"656":[26],"671":[26],"684":[26],"742":[26],"747":[26]},"packages/cli/src/modules/agents/integrations/integration-action-executor.ts":{"70":[26],"76":[26],"85":[26],"169":[26],"184":[26],"235":[26],"273":[26],"297":[26],"335":[26],"360":[26],"393":[26],"408":[26],"424":[26],"436":[26],"440":[26],"444":[26],"458":[26]},"packages/cli/src/modules/agents/integrations/integration-context-query-executor.ts":{"21":[26],"27":[26],"95":[26]},"packages/cli/src/modules/agents/integrations/integration-message-context.service.ts":{"25":[26],"31":[26],"37":[26],"44":[26],"56":[26],"75":[26],"85":[26],"93":[26],"99":[26],"105":[26],"120":[26],"144":[26],"148":[26],"168":[26],"196":[26],"207":[26]},"packages/cli/src/modules/agents/integrations/integration-message-context.ts":{"15":[26],"22":[26],"31":[26],"41":[26],"53":[26],"75":[26],"88":[26],"100":[26],"112":[26],"118":[26],"124":[26]},"packages/cli/src/modules/agents/integrations/integration-tool-descriptions.ts":{"4":[26],"12":[26],"18":[26],"26":[26],"47":[26]},"packages/cli/src/modules/agents/integrations/integration-tool-factory.ts":{"75":[26],"82":[26],"90":[26],"106":[26],"107":[26],"119":[26],"125":[26],"134":[26],"138":[26],"164":[26],"178":[26],"239":[26],"253":[26],"262":[26]},"packages/cli/src/modules/agents/integrations/integration-tool-schema.ts":{"35":[26],"37":[26],"52":[26],"60":[26],"87":[26],"89":[26],"104":[26],"112":[26],"139":[26],"146":[26],"153":[26],"179":[26],"183":[26],"197":[26],"204":[26]},"packages/cli/src/modules/agents/integrations/n8n-memory.ts":{"83":[26],"96":[26],"121":[26],"136":[26],"138":[26],"140":[26],"141":[26],"143":[26],"145":[26],"147":[26],"149":[26],"152":[26],"153":[26],"159":[26],"165":[26],"176":[26],"210":[26],"221":[26],"234":[26],"235":[26],"245":[26],"247":[26],"257":[26],"267":[26],"279":[26],"280":[26],"291":[26],"304":[26],"307":[26],"317":[26],"323":[26],"329":[26],"344":[26],"347":[26],"353":[26],"369":[26],"372":[26],"380":[26],"383":[26],"388":[26],"396":[26],"400":[26],"411":[26],"417":[26],"460":[26],"461":[26],"468":[26],"482":[26],"500":[26],"556":[26],"560":[26],"571":[26],"584":[26],"593":[26],"596":[26],"600":[26],"611":[26],"657":[26],"665":[26],"675":[26],"745":[26],"770":[26],"781":[26],"795":[26],"803":[26],"806":[26],"812":[26],"817":[26],"829":[26],"834":[26],"840":[26],"853":[26],"913":[26],"914":[26],"941":[26],"944":[26],"962":[26],"980":[26],"987":[26],"993":[26],"1001":[26],"1015":[26],"1032":[26],"1052":[26],"1067":[26],"1077":[26],"1088":[26]},"packages/cli/src/modules/agents/json-config/credential-field-mapping.ts":{"18":[26],"20":[26],"22":[26],"24":[26],"26":[26],"28":[26],"30":[26],"32":[26],"34":[26],"43":[26],"45":[26],"47":[26],"49":[26],"51":[26],"59":[26],"85":[26],"100":[26],"108":[26],"117":[26]},"packages/cli/src/modules/agents/json-config/from-json-config.ts":{"156":[26],"268":[26],"273":[26],"277":[26],"286":[26],"302":[26],"306":[26],"309":[26],"325":[26],"341":[26],"380":[26],"401":[26],"413":[26],"416":[26],"417":[26],"431":[26],"433":[26],"446":[26],"463":[26],"471":[26],"522":[26],"592":[26],"627":[26],"641":[26]},"packages/cli/src/modules/agents/json-config/model-config.ts":{"18":[26]},"packages/cli/src/modules/agents/repositories/agent-background-job.repository.ts":{"56":[26],"64":[26],"65":[26],"80":[26],"100":[26],"109":[26],"116":[26],"136":[26],"141":[26],"152":[26],"168":[26],"186":[26],"195":[26],"208":[26],"215":[26],"218":[26],"226":[26],"230":[26],"241":[26],"249":[26],"263":[26],"285":[26],"291":[26],"306":[26],"314":[26],"320":[26],"333":[26],"363":[26],"383":[26],"390":[26],"396":[26],"405":[26],"407":[26],"428":[26],"436":[26],"442":[26],"461":[26],"469":[26],"475":[26],"494":[26],"515":[26],"524":[26]},"packages/cli/src/modules/agents/repositories/agent-execution.repository.ts":{"30":[26],"34":[26],"39":[26],"43":[26],"50":[26],"54":[26],"58":[26],"65":[26],"69":[26],"77":[26],"93":[26],"104":[26],"114":[26],"126":[26],"130":[26],"143":[26],"160":[26],"167":[26],"178":[26],"212":[26],"221":[26],"245":[26],"246":[26],"260":[26],"276":[26],"279":[26],"314":[26],"326":[26],"334":[26],"353":[26],"362":[26],"369":[26],"374":[26]},"packages/cli/src/modules/agents/repositories/agent-file.repository.ts":{"8":[26],"12":[26],"21":[26],"25":[26]},"packages/cli/src/modules/agents/repositories/agent-message-queue.repository.ts":{"12":[26],"16":[26],"37":[26],"45":[26],"52":[26],"67":[26],"71":[26],"72":[26],"77":[26],"90":[26],"100":[26],"108":[26],"121":[26],"133":[26],"141":[26],"148":[26],"153":[26],"162":[26],"177":[26],"184":[26],"190":[26],"193":[26],"207":[26],"212":[26],"216":[26],"229":[26]},"packages/cli/src/modules/agents/repositories/agent-message.repository.ts":{"29":[26],"36":[26],"40":[26],"96":[26],"117":[26],"126":[26],"134":[26],"143":[26],"160":[26],"167":[26],"170":[26],"187":[26],"196":[26],"207":[26],"209":[26],"218":[26],"219":[26],"240":[26],"241":[26],"242":[26],"262":[26],"295":[26],"297":[26],"302":[26],"310":[26],"315":[26],"343":[26],"358":[26]},"packages/cli/src/modules/agents/repositories/agent-thread-grant.repository.ts":{"9":[26],"13":[26],"17":[26],"19":[26]},"packages/cli/src/modules/agents/runtime/agent-secure-runtime.ts":{"37":[26],"60":[26],"62":[26],"92":[26],"135":[26],"156":[26],"164":[26],"205":[26],"212":[26],"223":[26],"251":[26],"256":[26],"288":[26],"291":[26],"350":[26],"356":[26],"388":[26],"390":[26],"397":[26],"410":[26],"417":[26]},"packages/cli/src/modules/agents/sub-agents/delegate-sub-agent-tool.ts":{"31":[26],"53":[26],"109":[26],"145":[26],"161":[26],"168":[26],"174":[26],"194":[26],"206":[26]},"packages/cli/src/modules/agents/sub-agents/sub-agent-cleanup.service.ts":{"11":[26],"22":[26],"36":[26],"42":[26],"48":[26]},"packages/cli/src/modules/agents/sub-agents/sub-agent-runner.ts":{"165":[26],"174":[26],"186":[26],"208":[26],"228":[26],"240":[26],"306":[26],"397":[26],"408":[26],"464":[26],"474":[26],"506":[26],"514":[26],"556":[26],"562":[26],"590":[26],"597":[26],"605":[26],"615":[26],"637":[26],"667":[26]},"packages/cli/src/modules/agents/sub-agents/sub-agent-source-resolver.ts":{"36":[26],"46":[26],"134":[26]},"packages/cli/src/modules/agents/tool-registry.ts":{"28":[26]},"packages/cli/src/modules/agents/tools/environment-tool.ts":{"13":[26],"19":[26]},"packages/cli/src/modules/agents/tools/mark-session-failed.tool.ts":{"12":[26],"18":[26]},"packages/cli/src/modules/agents/tools/workflow-tool-factory.ts":{"144":[26],"198":[26],"211":[26],"222":[26],"232":[26],"233":[26],"260":[26],"261":[26],"291":[26],"297":[26],"313":[26],"325":[26],"330":[26],"338":[26],"364":[26],"378":[26],"401":[26],"415":[26],"455":[26],"506":[26],"514":[26],"517":[26],"533":[26],"534":[26],"588":[26],"596":[26],"616":[26],"646":[26],"666":[26],"690":[26],"701":[26],"727":[26],"830":[26],"846":[26],"868":[26],"878":[26],"909":[26],"952":[26],"962":[26],"967":[26],"987":[26],"1001":[26],"1011":[26],"1020":[26],"1050":[26],"1089":[26],"1167":[26]},"packages/cli/src/modules/agents/tools/workflow-tool-workflow-loader.service.ts":{"26":[26],"32":[26],"63":[26]},"packages/cli/src/modules/agents/types/agent-queued-message.ts":{"26":[26],"66":[26]},"packages/cli/src/modules/agents/utils/agent-execution-counter.ts":{"6":[26],"17":[26],"25":[26],"33":[26]},"packages/cli/src/modules/agents/utils/agent-memory-scope.ts":{"6":[26],"14":[26],"23":[26],"27":[26],"31":[26],"37":[26],"43":[26],"51":[26],"58":[26],"64":[26],"68":[26]},"packages/cli/src/modules/agents/utils/agent-runtime-assets.ts":{"8":[26]},"packages/cli/src/modules/agents/utils/agent-stream.ts":{"3":[26]},"packages/cli/src/modules/agents/utils/agent-thread-access.ts":{"13":[26],"19":[26],"33":[26],"42":[26],"47":[26],"59":[26]},"packages/cli/src/modules/agents/utils/decrypt-agent-credential.ts":{"6":[26]},"packages/cli/src/modules/agents/utils/execution-failure-summary.ts":{"26":[26],"32":[26],"36":[26],"44":[26],"58":[26]},"packages/cli/src/modules/agents/utils/execution-input.ts":{"5":[26],"17":[26]},"packages/cli/src/modules/agents/utils/execution-to-message-mapper.ts":{"27":[26],"32":[26],"37":[26],"41":[26],"51":[26],"66":[26],"86":[26],"114":[26],"139":[26],"151":[26],"152":[26],"157":[26],"161":[26],"165":[26],"177":[26],"194":[26],"228":[26],"258":[26],"294":[26],"298":[26]},"packages/cli/src/modules/agents/utils/fatal-session-outcome.ts":{"11":[26],"33":[26],"48":[26]},"packages/cli/src/modules/agents/utils/inbound-attachments.ts":{"8":[26],"26":[26],"52":[26],"75":[26],"84":[26],"85":[26],"87":[26]},"packages/cli/src/modules/agents/utils/mcp-attribution.ts":{"14":[26],"22":[26],"35":[26]},"packages/cli/src/modules/agents/utils/messages-envelope.ts":{"13":[26],"24":[26],"41":[26],"58":[26],"88":[26],"96":[26],"97":[26],"105":[26],"107":[26],"116":[26],"117":[26],"126":[26]},"packages/cli/src/modules/agents/utils/queued-message-id.ts":{"8":[26]},"packages/cli/src/modules/agents/utils/sub-agent-resolver.ts":{"8":[26]},"packages/cli/src/services/sandbox-settings.service.ts":{"25":[26],"39":[26],"50":[26],"60":[26],"92":[26],"103":[26],"107":[26],"111":[26],"118":[26],"141":[26],"169":[26],"178":[26],"184":[26]},"packages/workflow/src/constants.ts":{"21":[26]},"localhost-44277/assets/index-Dv_brJ4-.js":{"3":[27,166,174,16,86]},"localhost-44277/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[27,166,174,16,86],"9":[27,166,174,16,86],"10":[27,166,174,16,86],"19":[27,166,174,16,86],"23":[27,166,174,16,86],"29":[27,166,174,16,86],"33":[27,166,174,16,86],"34":[27,166,174,16,86]},"packages/frontend/@n8n/design-system/src/components/AskAssistantButton/AskAssistantButton.vue":{"8":[27,28,29,46],"18":[46],"20":[46],"24":[46],"26":[27,28,29,46]},"packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/EventMessage.vue":{"24":[27,46],"40":[27,46],"44":[27,46]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/stop-and-error.svg":{"11":[27,28]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Chat/AskAssistantFloatingButton.vue":{"14":[27,28,29],"25":[27,28,29],"63":[27,28,29],"80":[27,28,29]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Chat/NewAssistantSessionModal.vue":{"14":[27,46],"27":[27,46],"31":[27,46],"44":[27,46],"56":[27,46],"62":[27,46],"65":[27,46],"68":[27,46],"72":[27,46]},"packages/cli/src/modules/type-availability-policies/available-credential-types.controller.ts":{"18":[72,73],"41":[72,73],"49":[72,73]},"packages/cli/src/public-api/v1/controllers/credential-type-policies.public.controller.ts":{"53":[72],"73":[72],"75":[72],"96":[72],"119":[72],"152":[72],"182":[72],"214":[72],"244":[72],"267":[72],"293":[72],"323":[72],"343":[72],"357":[72]},"localhost-44277/assets/verified-Dido3Ow4.js":{"8":[166,16]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/utils.ts":{"10":[46,148,166,176],"19":[46,148,166,176],"30":[46,148,166,176],"40":[46],"50":[46],"53":[46],"66":[46],"67":[46],"70":[46],"82":[46],"91":[46],"94":[46]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/typescript/client/completions.ts":{"19":[46,166],"30":[46,166],"53":[46],"54":[46],"97":[46],"101":[46],"131":[46],"135":[46],"137":[46]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/typescript/client/linter.ts":{"4":[46,166],"8":[46,166]},"packages/cli/src/modules/external-secrets.ee/external-secrets-provider-connection-manager.ee.ts":{"49":[209,65,210],"64":[209,65,210],"68":[209,65,210],"71":[209,65,210],"74":[209,65,210],"88":[209,65,210],"103":[209,65,210],"120":[209,65,210],"131":[209,65,210],"158":[209,65,210],"168":[209,65,210],"193":[209,65,210],"225":[209,65,210],"233":[209,65,210],"246":[209,65,210],"272":[209,65,210],"305":[209,65,210],"314":[209,65,210],"315":[209,65,210],"327":[209,65,210],"347":[209,65,210],"427":[209,65,210],"466":[209,65,210],"486":[209,65,210],"491":[209,65,210],"500":[209,65,210]},"packages/cli/src/modules/external-secrets.ee/external-secrets.controller.ee.ts":{"13":[209,210],"22":[209,210],"34":[209,210],"40":[209,210],"47":[209,210],"60":[209,210],"68":[209,210],"76":[209,210],"90":[209,210]},"packages/cli/src/modules/external-secrets.ee/external-secrets.service.ee.ts":{"10":[209,210],"15":[209,210],"30":[209,210],"31":[209,210],"44":[209,210],"50":[209,210],"54":[209,210],"61":[209,210],"66":[209,210],"70":[209,210],"77":[209,210]},"packages/cli/src/modules/external-secrets.ee/provider-lifecycle.service.ts":{"25":[209,210],"36":[209,210],"78":[209,210],"112":[209,210],"127":[209,210]},"packages/cli/src/modules/external-secrets.ee/redaction.service.ee.ts":{"15":[209,210],"19":[209,210],"20":[209,210],"42":[209,210],"53":[209,210],"62":[209,210]},"packages/cli/src/modules/external-secrets.ee/retry-manager.service.ts":{"28":[209,65,210],"31":[209,65,210],"32":[209,65,210],"43":[209,65,210],"63":[209,65,210],"76":[209,65,210],"113":[209,65,210],"128":[209,65,210],"139":[209,65,210],"146":[209,65,210]},"packages/cli/src/modules/external-secrets.ee/settings-store.service.ts":{"18":[209,210],"26":[209,210],"38":[209,210],"54":[209,210],"61":[209,210],"80":[209,210],"108":[209,210],"116":[209,210],"127":[209,210],"142":[209,210]},"packages/cli/src/modules/external-secrets.ee/with-timeout.ts":{"12":[209,210],"14":[209,210],"15":[209,210]},"packages/@n8n/ai-utilities/src/utils/vector-store/createVectorStoreNode/createVectorStoreNode.ts":{"50":[0,3,7,8,16],"53":[0,3,7,8,16],"417":[0,3,7,8,16],"479":[0,3,7,8,16]},"packages/@n8n/ai-utilities/src/utils/vector-store/createVectorStoreNode/utils.ts":{"12":[0,3,7,8,16],"16":[0,3,7,8,16],"26":[0,3,7,8,16],"36":[0,3,7,8,16],"41":[0,3,7,8,16],"47":[0,3,7,8,16]},"packages/@n8n/nodes-langchain/nodes/embeddings/EmbeddingsHuggingFaceInference/EmbeddingsHuggingFaceInference.node.ts":{"16":[16],"86":[16],"94":[16],"132":[16],"142":[16]},"packages/@n8n/nodes-langchain/nodes/memory/MemoryXata/MemoryXata.node.ts":{"23":[16],"105":[16]},"packages/@n8n/nodes-langchain/nodes/output_parser/OutputParserStructured/OutputParserStructured.node.ts":{"32":[8,16],"198":[8,16]},"packages/@n8n/nodes-langchain/nodes/text_splitters/TextSplitterTokenSplitter/TextSplitterTokenSplitter.node.ts":{"13":[16],"62":[16]},"packages/@n8n/nodes-langchain/nodes/text_splitters/TextSplitterTokenSplitter/TokenTextSplitter.ts":{"16":[16],"28":[16],"36":[16]},"packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreQdrant/Qdrant.utils.ts":{"9":[16],"28":[16]},"packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreSupabase/VectorStoreSupabase.node.ts":{"67":[16],"84":[16]},"packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreWeaviate/Weaviate.utils.ts":{"22":[16],"68":[16],"127":[16]},"packages/@n8n/nodes-langchain/nodes/vector_store/shared/methods/listSearch.ts":{"10":[16],"19":[16],"27":[16],"58":[16],"65":[16],"73":[16],"87":[16],"95":[16],"102":[16]},"packages/@n8n/nodes-langchain/nodes/vector_store/shared/supabase.ts":{"7":[16]},"packages/nodes-base/nodes/Discord/Discord.node.ts":{"8":[16]},"packages/nodes-base/nodes/Discord/v1/DiscordV1.node.ts":{"124":[16],"131":[16]},"packages/nodes-base/nodes/Discord/v2/DiscordV2.node.ts":{"17":[16],"32":[16]},"packages/nodes-base/nodes/Discord/v2/actions/channel/create.operation.ts":{"157":[16]},"packages/nodes-base/nodes/Discord/v2/actions/channel/deleteChannel.operation.ts":{"27":[16]},"packages/nodes-base/nodes/Discord/v2/actions/channel/get.operation.ts":{"27":[16]},"packages/nodes-base/nodes/Discord/v2/actions/channel/getAll.operation.ts":{"58":[16],"77":[16]},"packages/nodes-base/nodes/Discord/v2/actions/channel/update.operation.ts":{"106":[16]},"packages/nodes-base/nodes/Discord/v2/actions/member/ban.operation.ts":{"32":[16]},"packages/nodes-base/nodes/Discord/v2/actions/member/getAll.operation.ts":{"46":[16]},"packages/nodes-base/nodes/Discord/v2/actions/member/kick.operation.ts":{"22":[16]},"packages/nodes-base/nodes/Discord/v2/actions/member/roleAdd.operation.ts":{"22":[16]},"packages/nodes-base/nodes/Discord/v2/actions/member/roleRemove.operation.ts":{"22":[16]},"packages/nodes-base/nodes/Discord/v2/actions/member/timeout.operation.ts":{"33":[16]},"packages/nodes-base/nodes/Discord/v2/actions/member/unban.operation.ts":{"22":[16]},"packages/nodes-base/nodes/Discord/v2/actions/message/deleteMessage.operation.ts":{"27":[16]},"packages/nodes-base/nodes/Discord/v2/actions/message/get.operation.ts":{"43":[16]},"packages/nodes-base/nodes/Discord/v2/actions/message/getAll.operation.ts":{"44":[16]},"packages/nodes-base/nodes/Discord/v2/actions/message/react.operation.ts":{"38":[16]},"packages/nodes-base/nodes/Discord/v2/actions/message/send.operation.ts":{"94":[16]},"packages/nodes-base/nodes/Discord/v2/actions/message/sendAndWait.operation.ts":{"26":[16],"28":[16]},"packages/nodes-base/nodes/Discord/v2/actions/router.ts":{"12":[16]},"packages/nodes-base/nodes/Discord/v2/actions/webhook/sendLegacy.operation.ts":{"103":[16]},"packages/nodes-base/nodes/Discord/v2/helpers/utils.ts":{"13":[16],"14":[16],"26":[16],"52":[16],"82":[16],"97":[16],"111":[16],"132":[16],"134":[16],"184":[16],"187":[16],"244":[16],"250":[16],"262":[16],"288":[16],"291":[16],"302":[16],"403":[16],"423":[16]},"packages/nodes-base/nodes/Discord/v2/methods/listSearch.ts":{"10":[16],"30":[16],"40":[16],"46":[16],"69":[16],"77":[16],"83":[16],"84":[16],"92":[16],"101":[16],"102":[16],"110":[16],"117":[16],"118":[16],"126":[16],"159":[16]},"packages/nodes-base/nodes/Discord/v2/methods/loadOptions.ts":{"6":[16],"36":[16],"42":[16],"43":[16]},"packages/nodes-base/nodes/Discord/v2/transport/discord.api.ts":{"15":[16],"52":[16]},"packages/nodes-base/nodes/Discord/v2/transport/helpers.ts":{"16":[16],"34":[16],"40":[16],"48":[16],"54":[16]},"packages/nodes-base/nodes/E2eTest/E2eTest.node.ts":{"175":[16,178,179],"180":[16,178,179],"188":[16,178,179],"201":[16,178,179],"207":[16,178,179]},"packages/nodes-base/nodes/E2eTest/mock.ts":{"66":[16,178,179]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/basic-llm-chain.svg":{"11":[2,15,16]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/contextual-compression-retriever.svg":{"11":[16]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/default-data-loader.svg":{"11":[0,3,16]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/guardrails.svg":{"11":[16]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/information-extractor.svg":{"11":[43,9,131,156,70,16,185]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/multiquery-retriever.svg":{"11":[16]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/question-and-answer-chain.svg":{"11":[3,16]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/sentiment-analysis.svg":{"11":[16]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/simple-vector-store.svg":{"11":[0,3,127,82,16]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/summarization-chain.svg":{"11":[16]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/text-classifier.svg":{"11":[131,16]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/token-splitter.svg":{"11":[16]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/vector-store-retriever.svg":{"11":[3,16]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/workflow-retriever.svg":{"11":[16]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/LinkItem.vue":{"13":[16]},"packages/@n8n/ai-utilities/src/json-schema/draft-2020-12.ts":{"30":[207,208,12],"33":[207,208,12],"37":[207,208,12],"58":[207,208,12],"117":[207,208,12]},"packages/@n8n/ai-utilities/src/node-catalog/discriminator-utils.ts":{"44":[49,50,207,208],"55":[49,50,207,208],"70":[49,50,207,208],"81":[49,50,207,208],"117":[49,50,207,208],"128":[49,50,207,208],"139":[49,50,207,208],"151":[49,50,207,208],"161":[49,50,207,208],"178":[49,50,207,208]},"packages/@n8n/ai-utilities/src/node-catalog/dynamic-node-parameters.ts":{"47":[49,50,207,208],"51":[49,50,207,208],"55":[49,50,207,208],"59":[49,50,207,208],"63":[49,50,207,208],"73":[49,50,207,208],"107":[49,50,207,208],"114":[49,50,207,208],"119":[49,50,207,208],"151":[49,50,207,208],"183":[49,50,207,208],"187":[49,50,207,208],"188":[49,50,207,208],"195":[49,50,207,208],"199":[49,50,207,208],"214":[49,50,207,208],"226":[49,50,207,208],"230":[49,50,207,208],"237":[49,50,207,208],"241":[49,50,207,208],"251":[49,50,207,208],"260":[49,50,207,208],"274":[49,50,207,208]},"packages/@n8n/ai-utilities/src/node-catalog/get.ts":{"17":[49,50,207,208],"45":[49,50,207,208],"53":[49,50,207,208],"66":[49,50,207,208],"68":[49,50,207,208],"82":[49,50,207,208],"106":[49,50,207,208],"119":[49,50,207,208],"129":[49,50,207,208],"166":[49,50,207,208],"202":[49,50,207,208],"214":[49,50,207,208],"251":[49,50,207,208],"272":[49,50,207,208],"282":[49,50,207,208],"285":[49,50,207,208],"286":[49,50,207,208],"335":[49,50,207,208],"336":[49,50,207,208],"353":[49,50,207,208],"363":[49,50,207,208],"365":[49,50,207,208],"370":[49,50,207,208],"413":[49,50,207,208],"521":[49,50,207,208],"535":[49,50,207,208],"563":[49,50,207,208],"633":[49,50,207,208]},"packages/@n8n/ai-utilities/src/node-catalog/lean-node-type.ts":{"62":[49,50,207,208],"66":[49,50,207,208],"88":[49,50,207,208]},"packages/@n8n/ai-utilities/src/node-catalog/node-type-parser.ts":{"39":[49,50,207,208],"48":[49,50,207,208],"64":[49,50,207,208],"80":[49,50,207,208],"87":[49,50,207,208],"109":[49,50,207,208],"118":[49,50,207,208],"126":[49,50,207,208],"145":[49,50,207,208]},"packages/@n8n/ai-utilities/src/node-catalog/resource-operation-extractor.ts":{"56":[49,50,207,208],"82":[49,50,207,208],"87":[49,50,207,208],"98":[49,50,207,208],"122":[49,50,207,208],"127":[49,50,207,208],"152":[49,50,207,208],"171":[49,50,207,208],"198":[49,50,207,208],"216":[49,50,207,208],"250":[49,50,207,208],"288":[49,50,207,208],"295":[49,50,207,208],"305":[49,50,207,208]},"packages/@n8n/ai-utilities/src/node-catalog/search-engine.ts":{"69":[49,50,207,208],"80":[49,50,207,208],"103":[49,50,207,208],"107":[49,50,207,208],"112":[49,50,207,208],"115":[49,50,207,208],"122":[49,50,207,208],"140":[49,50,207,208],"142":[49,50,207,208],"169":[49,50,207,208],"189":[49,50,207,208],"194":[49,50,207,208],"202":[49,50,207,208],"217":[49,50,207,208],"232":[49,50,207,208],"238":[49,50,207,208],"265":[49,50,207,208],"286":[49,50,207,208],"292":[49,50,207,208],"299":[49,50,207,208],"303":[49,50,207,208],"311":[49,50,207,208],"315":[49,50,207,208],"332":[49,50,207,208],"342":[49,50,207,208],"346":[49,50,207,208],"355":[49,50,207,208],"368":[49,50,207,208],"379":[49,50,207,208],"383":[49,50,207,208],"390":[49,50,207,208],"392":[49,50,207,208],"398":[49,50,207,208],"402":[49,50,207,208],"404":[49,50,207,208],"418":[49,50,207,208],"476":[49,50,207,208],"489":[49,50,207,208],"503":[49,50,207,208],"530":[49,50,207,208],"531":[49,50,207,208],"540":[49,50,207,208],"566":[49,50,207,208],"574":[49,50,207,208]},"packages/@n8n/ai-utilities/src/node-catalog/search.ts":{"48":[49,50,207,208],"62":[49,50,207,208],"71":[49,50,207,208],"77":[49,50,207,208],"84":[49,50,207,208],"91":[49,50,207,208],"105":[49,50,207,208],"181":[49,50,207,208],"227":[49,50,207,208],"241":[49,50,207,208],"242":[49,50,207,208],"247":[49,50,207,208],"248":[49,50,207,208],"262":[49,50,207,208],"263":[49,50,207,208],"281":[49,50,207,208],"317":[49,50,207,208],"336":[49,50,207,208],"338":[49,50,207,208],"355":[49,50,207,208],"379":[49,50,207,208],"431":[49,50,207,208],"446":[49,50,207,208],"533":[49,50,207,208],"539":[49,50,207,208],"545":[49,50,207,208],"547":[49,50,207,208],"548":[49,50,207,208]},"packages/@n8n/ai-workflow-builder.ee/src/code-builder/index.ts":{"14":[207,208],"21":[207,208],"22":[207,208],"23":[207,208],"25":[207,208]},"packages/@n8n/ai-workflow-builder.ee/src/index.ts":{"7":[102,33,207,208],"44":[102,33,207,208]},"packages/@n8n/api-types/src/schemas/json-value.schema.ts":{"12":[46,207,208]},"packages/cli/src/middlewares/content-security-policy.ts":{"26":[207,208],"34":[207,208],"38":[207,208],"39":[207,208],"42":[207,208],"44":[207,208],"47":[207,208],"49":[207,208],"62":[207,208],"75":[207,208],"108":[207,208],"112":[207,208],"116":[207,208],"131":[207,208]},"packages/cli/src/modules/data-table/data-table-proxy.service.ts":{"46":[207,208],"52":[207,208],"62":[207,208],"70":[207,208],"76":[207,208],"81":[207,208],"92":[207,208],"120":[207,208],"127":[207,208],"130":[207,208],"132":[207,208],"136":[207,208],"141":[207,208],"148":[207,208],"154":[207,208],"164":[207,208],"170":[207,208],"176":[207,208],"188":[207,208],"195":[207,208],"205":[207,208],"216":[207,208],"230":[207,208],"248":[207,208],"256":[207,208],"259":[207,208],"263":[207,208],"271":[207,208],"275":[207,208],"281":[207,208],"289":[207,208],"293":[207,208],"298":[207,208],"302":[207,208],"306":[207,208],"310":[207,208],"315":[207,208],"319":[207,208],"326":[207,208],"336":[207,208],"346":[207,208],"356":[207,208]},"packages/cli/src/modules/mcp/mcp-scopes.ts":{"192":[207,208],"201":[207,208]},"packages/cli/src/modules/mcp/mcp-server-middleware.service.ts":{"32":[207,208],"44":[207,208],"72":[207,208],"73":[207,208],"93":[207,208],"94":[207,208],"137":[207,208],"150":[207,208],"163":[207,208]},"packages/cli/src/modules/mcp/mcp.controller.ts":{"32":[207,208],"33":[207,208],"39":[207,208],"48":[207,208],"82":[207,208],"103":[207,208],"123":[207,208],"213":[207,208],"220":[207,208],"223":[207,208],"238":[207,208],"241":[207,208],"252":[207,208]},"packages/cli/src/modules/mcp/mcp.service.ts":{"170":[207,208],"184":[207,208],"219":[207,208],"233":[207,208],"277":[207,208],"294":[207,208],"308":[207,208],"356":[207,208],"362":[207,208],"367":[207,208],"419":[207,208],"420":[207,208],"438":[207,208],"445":[207,208],"495":[207,208],"690":[207,208],"833":[207,208],"861":[207,208],"889":[207,208],"907":[207,208],"973":[207,208],"1088":[207,208],"1110":[207,208],"1118":[207,208],"1133":[207,208],"1147":[207,208],"1158":[207,208],"1181":[207,208],"1196":[207,208]},"packages/cli/src/modules/mcp/mcp.typeguards.ts":{"22":[207,208],"45":[207,208],"56":[207,208],"74":[207,208]},"packages/cli/src/modules/mcp/mcp.utils.ts":{"19":[207,208],"28":[207,208],"37":[207,208],"57":[207,208],"68":[207,208],"85":[207,208],"103":[207,208],"106":[207,208],"113":[207,208],"120":[207,208],"125":[207,208]},"packages/cli/src/modules/mcp/tool-schema.util.ts":{"12":[207,208],"31":[207,208],"36":[207,208],"43":[207,208],"44":[207,208]},"packages/cli/src/modules/mcp/tools/agents/agent-slack-setup.ts":{"32":[207,208],"43":[207,208],"65":[207,208],"66":[207,208],"69":[207,208],"83":[207,208],"114":[207,208],"134":[207,208],"148":[207,208],"161":[207,208]},"packages/cli/src/modules/mcp/tools/agents/agent-tools.service.ts":{"98":[207,208],"106":[207,208],"112":[207,208],"130":[207,208],"141":[207,208],"207":[207,208],"217":[207,208],"414":[207,208],"425":[207,208],"435":[207,208],"468":[207,208],"475":[207,208],"504":[207,208],"516":[207,208],"531":[207,208],"532":[207,208],"546":[207,208],"559":[207,208],"574":[207,208],"579":[207,208],"591":[207,208],"606":[207,208],"607":[207,208],"664":[207,208],"679":[207,208],"684":[207,208],"730":[207,208],"748":[207,208],"749":[207,208],"774":[207,208],"789":[207,208],"797":[207,208],"807":[207,208],"822":[207,208],"827":[207,208],"861":[207,208],"876":[207,208],"881":[207,208],"911":[207,208],"926":[207,208],"927":[207,208],"941":[207,208],"955":[207,208],"956":[207,208],"976":[207,208],"990":[207,208],"991":[207,208],"1001":[207,208],"1016":[207,208],"1021":[207,208],"1033":[207,208],"1048":[207,208],"1053":[207,208],"1058":[207,208],"1073":[207,208],"1083":[207,208],"1088":[207,208],"1103":[207,208],"1104":[207,208],"1113":[207,208],"1122":[207,208],"1147":[207,208],"1149":[207,208],"1150":[207,208],"1163":[207,208],"1174":[207,208],"1192":[207,208],"1200":[207,208],"1207":[207,208],"1211":[207,208],"1217":[207,208],"1221":[207,208],"1234":[207,208],"1333":[207,208],"1366":[207,208],"1487":[207,208],"1530":[207,208],"1535":[207,208],"1552":[207,208],"1565":[207,208],"1575":[207,208],"1581":[207,208],"1592":[207,208],"1602":[207,208],"1622":[207,208],"1638":[207,208],"1652":[207,208],"1664":[207,208],"1680":[207,208],"1689":[207,208],"1713":[207,208],"1722":[207,208],"1755":[207,208],"1768":[207,208],"1777":[207,208],"1802":[207,208],"1828":[207,208],"1845":[207,208],"1909":[207,208],"1945":[207,208],"1949":[207,208],"1953":[207,208],"1969":[207,208],"1980":[207,208],"1986":[207,208]},"packages/cli/src/modules/mcp/tools/create-folder.tool.ts":{"29":[207,208],"49":[207,208]},"packages/cli/src/modules/mcp/tools/data-table/add-data-table-column.tool.ts":{"30":[207,208],"48":[207,208],"82":[207,208]},"packages/cli/src/modules/mcp/tools/data-table/add-data-table-rows.tool.ts":{"31":[207,208],"50":[207,208],"84":[207,208]},"packages/cli/src/modules/mcp/tools/data-table/create-data-table.tool.ts":{"36":[207,208],"55":[207,208],"73":[207,208]},"packages/cli/src/modules/mcp/tools/data-table/delete-data-table-column.tool.ts":{"20":[207,208],"39":[207,208],"67":[207,208]},"packages/cli/src/modules/mcp/tools/data-table/get-data-table-rows.tool.ts":{"48":[207,208],"82":[207,208],"87":[207,208],"89":[207,208],"95":[207,208],"114":[207,208],"152":[207,208]},"packages/cli/src/modules/mcp/tools/data-table/index.ts":{"1":[207,208],"2":[207,208],"3":[207,208],"5":[207,208],"6":[207,208]},"packages/cli/src/modules/mcp/tools/data-table/rename-data-table-column.tool.ts":{"29":[207,208],"47":[207,208],"83":[207,208]},"packages/cli/src/modules/mcp/tools/data-table/rename-data-table.tool.ts":{"20":[207,208],"38":[207,208],"66":[207,208]},"packages/cli/src/modules/mcp/tools/data-table/search-data-tables.tool.ts":{"29":[207,208],"48":[207,208],"74":[207,208],"80":[207,208],"100":[207,208]},"packages/cli/src/modules/mcp/tools/execute-workflow.tool.ts":{"82":[207,208],"105":[207,208],"184":[207,208],"223":[207,208],"266":[207,208],"335":[207,208],"341":[207,208],"357":[207,208],"387":[207,208],"394":[207,208],"407":[207,208],"426":[207,208],"439":[207,208],"440":[207,208],"446":[207,208],"455":[207,208],"474":[207,208],"554":[207,208],"563":[207,208],"590":[207,208]},"packages/cli/src/modules/mcp/tools/get-execution.tool.ts":{"66":[207,208],"87":[207,208],"215":[207,208],"248":[207,208],"252":[207,208]},"packages/cli/src/modules/mcp/tools/get-workflow-details.tool.ts":{"50":[207,208],"51":[207,208],"53":[207,208],"55":[207,208],"67":[207,208],"85":[207,208],"113":[207,208],"164":[207,208],"201":[207,208]},"packages/cli/src/modules/mcp/tools/get-workflow-history.tool.ts":{"61":[207,208],"81":[207,208],"136":[207,208],"147":[207,208]},"packages/cli/src/modules/mcp/tools/get-workflow-version.tool.ts":{"76":[207,208],"96":[207,208],"158":[207,208]},"packages/cli/src/modules/mcp/tools/get-workflow-versions-diff.tool.ts":{"125":[207,208],"134":[207,208],"144":[207,208],"145":[207,208],"149":[207,208],"152":[207,208],"153":[207,208],"164":[207,208],"193":[207,208],"213":[207,208],"273":[207,208],"294":[207,208],"319":[207,208]},"packages/cli/src/modules/mcp/tools/list-credentials.tool.ts":{"69":[207,208],"121":[207,208],"145":[207,208],"186":[207,208],"195":[207,208],"226":[207,208]},"packages/cli/src/modules/mcp/tools/list-n8n-gateway-services.tool.ts":{"53":[207,208],"72":[207,208]},"packages/cli/src/modules/mcp/tools/list-tags.tool.ts":{"61":[207,208],"79":[207,208],"109":[207,208],"116":[207,208]},"packages/cli/src/modules/mcp/tools/move-workflows-to-folder.tool.ts":{"63":[207,208],"84":[207,208],"108":[207,208]},"packages/cli/src/modules/mcp/tools/prepare-workflow-pin-data.tool.ts":{"57":[207,208],"79":[207,208],"137":[207,208],"147":[207,208],"150":[207,208],"223":[207,208]},"packages/cli/src/modules/mcp/tools/publish-workflow.tool.ts":{"53":[207,208],"61":[207,208],"82":[207,208],"100":[207,208]},"packages/cli/src/modules/mcp/tools/schemas.ts":{"37":[207,208],"40":[207,208],"54":[207,208],"66":[207,208],"71":[207,208],"72":[207,208],"75":[207,208],"79":[207,208],"104":[207,208],"169":[207,208],"173":[207,208],"174":[207,208],"177":[207,208]},"packages/cli/src/modules/mcp/tools/search-executions.tool.ts":{"71":[207,208],"91":[207,208],"140":[207,208]},"packages/cli/src/modules/mcp/tools/search-folders.tool.ts":{"46":[207,208],"66":[207,208],"104":[207,208],"123":[207,208]},"packages/cli/src/modules/mcp/tools/search-projects.tool.ts":{"63":[207,208],"83":[207,208],"115":[207,208],"116":[207,208],"120":[207,208],"128":[207,208],"136":[207,208],"143":[207,208],"175":[207,208]},"packages/cli/src/modules/mcp/tools/search-workflows.tool.ts":{"50":[207,208],"111":[207,208],"132":[207,208],"225":[207,208],"247":[207,208],"262":[207,208],"296":[207,208]},"packages/cli/src/modules/mcp/tools/test-workflow.tool.ts":{"71":[207,208],"94":[207,208],"170":[207,208],"195":[207,208],"215":[207,208],"216":[207,208]},"packages/cli/src/modules/mcp/tools/unpublish-workflow.tool.ts":{"32":[207,208],"53":[207,208],"69":[207,208]},"packages/cli/src/modules/mcp/tools/update-folder.tool.ts":{"32":[207,208],"52":[207,208]},"packages/cli/src/modules/mcp/tools/workflow-builder/create-workflow-from-code.tool.ts":{"72":[207,208],"230":[207,208],"319":[207,208],"348":[207,208],"417":[207,208],"447":[207,208],"522":[207,208],"561":[207,208]},"packages/cli/src/modules/mcp/tools/workflow-builder/delete-workflow.tool.ts":{"27":[207,208],"47":[207,208],"65":[207,208]},"packages/cli/src/modules/mcp/tools/workflow-builder/explore-node-resources.tool.ts":{"99":[207,208],"121":[207,208],"142":[207,208]},"packages/cli/src/modules/mcp/tools/workflow-builder/get-workflow-best-practices.tool.ts":{"53":[207,208],"54":[207,208],"60":[207,208],"67":[207,208],"85":[207,208],"110":[207,208],"128":[207,208]},"packages/cli/src/modules/mcp/tools/workflow-builder/get-workflow-node-types.tool.ts":{"63":[207,208],"85":[207,208]},"packages/cli/src/modules/mcp/tools/workflow-builder/get-workflow-sdk-reference.tool.ts":{"41":[207,208],"59":[207,208]},"packages/cli/src/modules/mcp/tools/workflow-builder/install-community-node.tool.ts":{"58":[207],"87":[207],"112":[207],"125":[207],"220":[207]},"packages/cli/src/modules/mcp/tools/workflow-builder/mcp-instructions.ts":{"61":[207,208]},"packages/cli/src/modules/mcp/tools/workflow-builder/restore-workflow-version.tool.ts":{"49":[207,208],"71":[207,208],"111":[207,208]},"packages/cli/src/modules/mcp/tools/workflow-builder/search-workflow-nodes.tool.ts":{"76":[207,208],"102":[207,208]},"packages/cli/src/modules/mcp/tools/workflow-builder/update-workflow.tool.ts":{"79":[207,208],"126":[207,208],"248":[207,208],"254":[207,208],"382":[207,208],"446":[207,208],"453":[207,208],"454":[207,208],"469":[207,208],"509":[207,208],"530":[207,208],"548":[207,208],"558":[207,208],"578":[207,208],"620":[207,208],"643":[207,208],"657":[207,208],"664":[207,208],"666":[207,208],"705":[207,208],"732":[207,208],"735":[207,208],"755":[207,208],"761":[207,208],"780":[207,208],"804":[207,208],"839":[207,208],"887":[207,208],"911":[207,208],"926":[207,208],"953":[207,208],"980":[207,208],"991":[207,208],"1018":[207,208],"1033":[207,208],"1047":[207,208],"1051":[207,208],"1052":[207,208],"1060":[207,208],"1073":[207,208],"1124":[207,208],"1161":[207,208],"1163":[207,208],"1230":[207,208],"1305":[207,208],"1365":[207,208],"1404":[207,208],"1415":[207,208]},"packages/cli/src/modules/mcp/tools/workflow-builder/validate-node.tool.ts":{"80":[207,208],"98":[207,208],"108":[207,208],"125":[207,208],"126":[207,208],"127":[207,208]},"packages/cli/src/modules/mcp/tools/workflow-builder/validate-workflow-code.tool.ts":{"55":[207,208],"74":[207,208],"95":[207,208],"112":[207,208],"121":[207,208]},"packages/cli/src/modules/oauth-server/oauth-local-authorization-server.ts":{"20":[207],"37":[207],"64":[207]},"packages/cli/src/services/ai-workflow-builder.service.ts":{"47":[102,33,49,50,11,207,208,151],"65":[102,33,49,50,11,207,208,151],"73":[102,33,49,50,11,207,208,151],"80":[102,33,49,50,11,207,208,151],"88":[102,33,49,50,11,207,208,151],"104":[102,33,49,50,11,207,208,151],"110":[102,33,49,50,11,207,208,151],"124":[102,33,49,50,11,207,208,151],"129":[102,33,49,50,11,207,208,151],"130":[102,33,49,50,11,207,208,151],"191":[102,33,49,50,11,207,208,151],"208":[102,33,49,50,11,207,208,151],"213":[102,33,49,50,11,207,208,151],"219":[102,33,49,50,11,207,208,151],"224":[102,33,49,50,11,207,208,151],"229":[102,33,49,50,11,207,208,151]},"packages/@n8n/api-types/src/schemas/folder.schema.ts":{"10":[46,135,57]},"localhost-45399/assets/index-Dv_brJ4-.js":{"3":[57,136,85,178,185]},"localhost-45399/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[57,136,85,178,185],"9":[57,136,85,178,185],"10":[57,136,85,178,185],"19":[57,136,85,178,185],"23":[57,136,85,178,185],"29":[57,136,85,178,185],"33":[57,136,85,178,185],"34":[57,136,85,178,185]},"packages/frontend/editor-ui/src/features/core/folders/components/FolderCard.vue":{"68":[135,57,136],"72":[57],"74":[135,57,136],"98":[135,57,136],"106":[135,57,136],"119":[135,57,136],"130":[135,57,136],"134":[135,57,136],"145":[57],"165":[57],"169":[135,57,136],"180":[135,57,136],"213":[135,57,136],"220":[135,57,136],"221":[135,57,136],"230":[135,57,136],"233":[135,57,136],"240":[135,57,136],"248":[135,136],"259":[135,57],"271":[135,57,136],"280":[135,57,136],"286":[135,57,136],"287":[135,57,136],"299":[57],"329":[135,57,136],"339":[135,57,136],"360":[135,57,136]},"packages/frontend/editor-ui/src/features/workflow-reviews/components/WorkflowPublishChoiceDialog.vue":{"17":[57],"26":[57],"31":[57],"34":[57],"42":[57],"43":[57],"45":[57],"48":[57],"53":[57],"60":[57],"64":[57]},"packages/frontend/editor-ui/src/features/workflow-reviews/components/WorkflowReviewRequiredToggle.vue":{"9":[57],"17":[57],"20":[57],"21":[57],"26":[57],"39":[57],"41":[57],"46":[57],"58":[57]},"packages/frontend/editor-ui/src/features/workflow-reviews/components/WorkflowReviewStatusBanner.vue":{"29":[57],"54":[57],"63":[57],"74":[57],"80":[57],"138":[57],"140":[57],"149":[57],"152":[57],"157":[57],"160":[57],"173":[57],"182":[57],"194":[57],"202":[57],"208":[57]},"packages/frontend/editor-ui/src/features/workflow-reviews/components/WorkflowReviewSubmittedDialog.vue":{"21":[57],"34":[57],"35":[57],"39":[57],"44":[57],"54":[57],"59":[57],"64":[57]},"packages/frontend/editor-ui/src/features/workflow-reviews/components/WorkflowSubmitForReviewDialog.vue":{"35":[57],"71":[57],"77":[57],"79":[57],"86":[57],"87":[57],"95":[57],"113":[57],"114":[57],"132":[57],"137":[57],"139":[57],"142":[57],"145":[57],"148":[57],"153":[57],"161":[57],"239":[57],"259":[57],"283":[57],"301":[57],"321":[57],"333":[57],"347":[57],"354":[57],"365":[57],"373":[57]},"packages/frontend/editor-ui/src/features/workflow-reviews/components/WorkflowUpdateReviewDialog.vue":{"30":[57],"64":[57],"68":[57],"74":[57],"77":[57],"79":[57],"81":[57],"87":[57],"98":[57],"119":[57],"120":[57],"138":[57],"143":[57],"148":[57],"153":[57],"158":[57],"232":[57],"246":[57],"252":[57],"255":[57],"259":[57],"289":[57],"313":[57],"321":[57],"332":[57],"340":[57]},"packages/frontend/editor-ui/src/features/workflow-reviews/composables/useReviewVersionName.ts":{"11":[57],"22":[57],"30":[57],"39":[57]},"packages/frontend/editor-ui/src/features/core/folders/components/DeleteFolderModal.vue":{"16":[46,136],"41":[46,136],"46":[46,136],"50":[46,136],"55":[46,136],"74":[46,136],"82":[46,136],"105":[46],"141":[46],"143":[46,136],"155":[46,136],"158":[46],"162":[46,136],"165":[46],"168":[46,136],"176":[46],"181":[46],"194":[46],"197":[46,136],"199":[46,136],"208":[46],"227":[46,136]},"packages/@n8n/scheduler/src/observability/materializer-tracing.ts":{"17":[198,201,64],"28":[198,201,64]},"packages/cli/src/scheduling/schedule-trigger-node/schedule-trigger-task-handler.ts":{"37":[201,202,64],"51":[201,202,64],"149":[201,202,64],"164":[201,202,64]},"packages/cli/src/scheduling/schedule-trigger-node/schedule-trigger-task.ts":{"14":[201,202,64],"24":[201,202,64]},"packages/cli/src/modules/external-secrets.ee/errors/secrets-provider-errors.ts":{"24":[65,210],"59":[65,210],"79":[65,210],"96":[65,210]},"packages/cli/src/modules/external-secrets.ee/secret-provider-access-check.service.ee.ts":{"16":[65],"23":[65],"33":[65],"76":[65],"97":[65],"99":[65]},"packages/nodes-base/nodes/Google/Gmail/GenericFunctions.ts":{"30":[29,85,180],"146":[29,85,180],"209":[29,85,180],"233":[29,85,180],"258":[29,85,180],"281":[29,85,180],"289":[29,85,180],"343":[29,85,180],"400":[29,85,180],"408":[29,85,180],"428":[29,85,180],"468":[29,85,180],"501":[29,85,180],"502":[29,85,180],"512":[29,85,180],"517":[29,85,180],"521":[29,85,180],"523":[29,85,180],"530":[29,85,180],"542":[29,85,180],"559":[29,85,180]},"packages/nodes-base/nodes/Google/Gmail/Gmail.node.ts":{"8":[29,85]},"packages/nodes-base/nodes/Google/Gmail/utils/descriptions.ts":{"3":[29,85,180]},"packages/nodes-base/nodes/Google/Gmail/utils/replyToEmail.ts":{"16":[29,85],"71":[29,85],"76":[29,85],"95":[29,85],"98":[29,85],"107":[29,85]},"packages/nodes-base/nodes/Google/Gmail/v1/GmailV1.node.ts":{"134":[29,85],"147":[29,85],"260":[29,85],"267":[29,85],"275":[29,85],"347":[29,85],"354":[29,85],"362":[29,85],"417":[29,85],"421":[29,85],"587":[29,85],"595":[29,85],"603":[29,85]},"packages/nodes-base/nodes/Google/Gmail/v2/GmailV2.node.ts":{"157":[29,85],"174":[29,85]},"packages/nodes-base/nodes/Google/Gmail/v2/loadOptions.ts":{"5":[29,85],"29":[29,85]},"packages/nodes-base/nodes/Google/Gmail/v2/utils/draft.ts":{"7":[29,85],"14":[29,85],"21":[29,85],"32":[29,85]},"packages/nodes-base/nodes/Transform/Sort/Sort.node.ts":{"164":[84,85],"221":[84,85],"226":[84,85]},"packages/nodes-base/nodes/Transform/Sort/utils.ts":{"8":[84,85]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/sort.svg":{"11":[82,84,85]},"packages/@n8n/client-oauth2/src/client-oauth2-token.ts":{"28":[194,215,178],"43":[194,215,178],"75":[194,215,178],"132":[194,215,178]},"packages/@n8n/client-oauth2/src/client-oauth2.ts":{"70":[46,194,178],"88":[46,194,178],"96":[46,194,178],"109":[46,194,178],"122":[46,194,178],"125":[46,194,178],"145":[46,194,178],"197":[46,194,178]},"packages/@n8n/client-oauth2/src/code-flow.ts":{"40":[46,194,178],"45":[46,194,178],"89":[46,194,178]},"packages/@n8n/client-oauth2/src/credential-options.ts":{"22":[194,178]},"packages/@n8n/client-oauth2/src/credentials-flow.ts":{"25":[46,194,178],"30":[46,194,178]},"packages/@n8n/client-oauth2/src/index.ts":{"2":[46,194,178],"5":[46,194,178]},"packages/@n8n/client-oauth2/src/utils.ts":{"8":[46,194,178],"22":[46,194,178],"34":[46,194,178],"51":[46,194,178],"62":[46,194,178],"69":[46,194,178],"76":[46,194,178]},"packages/cli/src/controllers/oauth/oauth2-credential.controller.ts":{"22":[46,194,178],"33":[46,194,178],"41":[46,194,178],"185":[46,194,178]},"packages/core/src/execution-engine/node-execution-context/utils/request-helpers/oauth.ts":{"48":[215,178],"55":[215,178],"77":[215,178],"94":[215,178],"118":[215,178],"129":[215,178],"135":[215,178],"152":[215,178],"163":[215,178],"302":[215,178],"311":[215,178],"321":[215,178],"328":[215,178],"344":[215,178],"349":[215,178],"353":[215,178],"356":[215,178],"364":[215,178],"366":[215,178],"369":[215,178],"381":[215,178],"395":[215,178],"503":[215,178],"522":[215,178],"547":[215,178],"550":[215,178],"551":[215,178],"562":[215,178],"573":[215,178],"576":[215,178],"577":[215,178],"596":[215,178],"620":[215,178],"662":[215,178],"668":[215,178]},"packages/nodes-base/nodes/Google/Sheet/GoogleSheets.node.ts":{"8":[178,191]},"packages/nodes-base/nodes/Google/Sheet/v1/GenericFunctions.ts":{"20":[178,191],"72":[178,191],"96":[178,191],"99":[178,191]},"packages/nodes-base/nodes/Google/Sheet/v1/GoogleSheet.ts":{"48":[178,191],"66":[178,191],"78":[178,191],"97":[178,191],"119":[178,191],"138":[178,191],"156":[178,191],"175":[178,191],"194":[178,191],"218":[178,191],"250":[178,191],"270":[178,191],"286":[178,191],"300":[178,191],"386":[178,191],"470":[178,191],"542":[178,191],"574":[178,191],"576":[178,191]},"packages/nodes-base/nodes/Google/Sheet/v1/GoogleSheetsV1.node.ts":{"32":[178,191],"42":[178,191],"68":[178,191],"96":[178,191],"125":[178,191],"227":[178,191],"299":[178,191],"413":[178,191]},"packages/nodes-base/nodes/Google/Sheet/v2/GoogleSheetsV2.node.ts":{"15":[178,191],"29":[178,191]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/router.ts":{"9":[178,191]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/append.operation.ts":{"213":[178,191],"326":[178,191]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/appendOrUpdate.operation.ts":{"264":[178,191],"365":[178,191],"374":[178,191],"392":[178,191],"424":[178,191],"447":[178,191],"521":[178,191]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/clear.operation.ts":{"160":[178,191]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/create.operation.ts":{"77":[178,191]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/delete.operation.ts":{"114":[178,191]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/read.operation.ts":{"170":[178,191]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/remove.operation.ts":{"7":[178,191]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/update.operation.ts":{"253":[178,191],"345":[178,191],"354":[178,191],"371":[178,191],"403":[178,191],"430":[178,191],"496":[178,191]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/spreadsheet/create.operation.ts":{"118":[178,191]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/spreadsheet/delete.operation.ts":{"68":[178,191]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/utils/readOperation.ts":{"12":[178,191],"110":[178,191]},"packages/nodes-base/nodes/Google/Sheet/v2/helpers/GoogleSheet.ts":{"39":[178,191],"47":[178,191],"58":[178,191],"74":[178,191],"93":[178,191],"117":[178,191],"136":[178,191],"149":[178,191],"165":[178,191],"178":[178,191],"186":[178,191],"204":[178,191],"220":[178,191],"264":[178,191],"287":[178,191],"333":[178,191],"367":[178,191],"380":[178,191],"394":[178,191],"411":[178,191],"441":[178,191],"446":[178,191],"461":[178,191],"480":[178,191],"494":[178,191],"545":[178,191],"627":[178,191],"675":[178,191],"803":[178,191],"833":[178,191],"835":[178,191],"857":[178,191],"880":[178,191]},"packages/nodes-base/nodes/Google/Sheet/v2/helpers/GoogleSheets.utils.ts":{"24":[178,191],"50":[178,191],"56":[178,191],"69":[178,191],"79":[178,191],"82":[178,191],"99":[178,191],"101":[178,191],"106":[178,191],"108":[178,191],"115":[178,191],"117":[178,191],"120":[178,191],"128":[178,191],"134":[178,191],"135":[178,191],"146":[178,191],"149":[178,191],"151":[178,191],"156":[178,191],"161":[178,191],"162":[178,191],"166":[178,191],"199":[178,191],"206":[178,191],"208":[178,191],"211":[178,191],"238":[178,191],"272":[178,191],"281":[178,191],"282":[178,191],"305":[178,191],"310":[178,191],"311":[178,191],"326":[178,191],"334":[178,191],"336":[178,191],"351":[178,191],"358":[178,191],"364":[178,191],"368":[178,191],"369":[178,191],"371":[178,191]},"packages/nodes-base/nodes/Google/Sheet/v2/methods/credentialTest.ts":{"9":[178,191]},"packages/nodes-base/nodes/Google/Sheet/v2/methods/listSearch.ts":{"15":[178,191],"44":[178,191],"53":[178,191]},"packages/nodes-base/nodes/Google/Sheet/v2/methods/loadOptions.ts":{"8":[178,191],"39":[178,191],"87":[178,191],"96":[178,191],"99":[178,191],"103":[178,191],"113":[178,191],"117":[178,191]},"packages/nodes-base/nodes/Google/Sheet/v2/methods/resourceMapping.ts":{"12":[178,191],"58":[178,191],"60":[178,191]},"packages/nodes-base/nodes/Google/Sheet/v2/transport/index.ts":{"16":[178,191],"84":[178,191]},"packages/nodes-base/utils/query-escaping.ts":{"19":[29,178,191],"27":[29,178,191],"38":[29,178,191],"52":[29,178,191],"67":[29,178,191],"77":[29,178,191],"94":[29,178,191],"117":[29,178,191],"142":[29,178,191],"150":[29,178,191]},"packages/frontend/editor-ui/src/features/credentials/composables/oauthCallback.ts":{"32":[46,178],"47":[46],"62":[46,178],"69":[46],"81":[46],"133":[46,178],"141":[46],"147":[46],"160":[46],"165":[46]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ResourceMapper/MappingModeSelect.vue":{"20":[46,178,179],"54":[46,178,179],"55":[46],"61":[46,178,179],"89":[46],"94":[46],"103":[46,178,179],"113":[46,178,179],"121":[46,178,179],"123":[46,178,179],"128":[46,178,179],"140":[46,178,179],"150":[46,178,179],"153":[46,178,179]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ResourceMapper/ResourceMapper.vue":{"55":[46,178,179,182,87],"99":[46,179],"119":[46,178,179,182,87],"121":[46,179],"146":[46],"150":[46,179],"171":[46,178,179,182,87],"173":[46,179],"185":[46,178,179,182,87],"221":[46,179],"262":[46,179],"266":[46,178,179,182,87],"273":[46,178,179,182,87],"277":[46,178,179,182,87],"281":[46,178,179,182,87],"285":[46,178,179,182,87],"293":[46,178,179,182,87],"303":[46,179],"313":[46,179],"320":[46],"329":[46,178,179,182,87],"332":[46,179],"340":[46,182,87],"347":[46,178,179,182,87],"375":[46,178,179,182,87],"400":[46,178,179,182,87],"423":[46,178,179,182,87],"433":[46,179],"434":[46,179],"457":[46],"467":[46,178,179,182,87],"470":[46,179],"490":[46,178,179,182,87],"503":[46,178,179,182,87],"509":[46,179],"520":[46,179],"540":[46,179],"546":[46,179],"554":[46,179],"555":[46,179],"572":[46,179],"580":[46],"588":[46],"603":[46],"605":[46],"619":[46,178,179,182,87],"631":[46,178,179,182,87],"637":[46,179],"648":[46,178,179,182,87],"681":[46,179],"684":[46,182,87],"711":[46],"717":[46,182,87],"722":[46],"728":[46],"729":[46]},"packages/frontend/editor-ui/src/features/ndv/parameters/composables/useNodeSpecificationValues.ts":{"5":[46,178,179],"6":[46,178,179],"10":[46,178,179],"16":[46,179],"20":[46,178,179],"24":[46,179]},"packages/nodes-base/nodes/Form/FormTrigger.node.ts":{"8":[192,103,211,115,54,185]},"packages/nodes-base/nodes/Form/v1/FormTriggerV1.node.ts":{"91":[192,103,211,115,54,185],"98":[192,103,211,115,54,185]},"packages/nodes-base/nodes/Form/v2/FormTriggerV2.node.ts":{"166":[192,103,211,115,54,185],"288":[192,103,211,115,54,185],"295":[192,103,211,115,54,185]},"localhost-45399/assets/verified-Dido3Ow4.js":{"8":[185]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/workflowDeactivated.ts":{"10":[185]},"localhost-41437/assets/index-Dv_brJ4-.js":{"3":[32,101,105,44,114,125,129,154,171]},"localhost-41437/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[32,101,105,44,114,125,129,154,171],"9":[32,101,105,44,114,125,129,154,171],"10":[32,101,105,44,114,125,129,154,171],"19":[32,101,105,44,114,125,129,154,171],"23":[32,101,105,44,114,125,129,154,171],"29":[32,101,105,44,114,125,129,154,171],"33":[32,101,105,44,114,125,129,154,171],"34":[32,101,105,44,114,125,129,154,171]},"packages/@n8n/db/src/repositories/evaluation-config.repository.ts":{"9":[101],"13":[101],"17":[101],"21":[101],"36":[101],"47":[101],"52":[101],"56":[101]},"packages/cli/src/evaluation.ee/evaluation-config.controller.ts":{"16":[101],"22":[101],"35":[101],"41":[101],"49":[101],"60":[101],"77":[101],"84":[101],"99":[101]},"packages/cli/src/evaluation.ee/evaluation-config.service.ts":{"13":[101],"19":[101],"23":[101],"27":[101],"55":[101],"71":[101],"75":[101],"79":[101]},"localhost-45433/assets/index-Dv_brJ4-.js":{"3":[65]},"localhost-45433/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[65],"9":[65],"10":[65],"19":[65],"23":[65],"29":[65],"33":[65],"34":[65]},"packages/frontend/editor-ui/src/features/integrations/externalSecrets.ee/assets/images/aws-secrets-manager.svg":{"8":[46,65]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/components/DeleteSecretsProviderModal.ee.vue":{"28":[46,65],"41":[46,65],"43":[46,65],"47":[46,65],"54":[46,65],"64":[46,65],"74":[46,65],"90":[46,65],"126":[46],"128":[46,65],"142":[46,65],"145":[46,65],"157":[46,65],"162":[46,65],"163":[46,65],"179":[46,65],"190":[46,65],"195":[46,65],"198":[46,65],"206":[46,65]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/components/SecretsProviderConnectionCard.ee.vue":{"49":[65],"57":[65],"61":[65],"63":[65],"74":[65],"85":[65],"95":[65],"115":[65],"156":[65],"167":[65],"180":[65],"183":[65],"198":[65],"224":[65],"230":[65]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/components/SecretsProviderImage.ee.vue":{"17":[46,65],"21":[46,65]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/components/SecretsProvidersEmptyState.ee.vue":{"8":[65],"16":[65],"45":[65],"56":[65],"64":[65],"73":[65],"95":[65],"101":[65],"108":[65],"112":[65]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/views/SettingsSecretsProviders.ee.vue":{"47":[65],"49":[65],"52":[65],"97":[65],"101":[65],"137":[65],"138":[65],"193":[65],"194":[65],"205":[65],"212":[65],"237":[65],"243":[65],"251":[65],"266":[65],"269":[65],"285":[65],"298":[65],"310":[65]},"packages/@n8n/api-types/src/schemas/eval-collections.schema.ts":{"74":[101,46],"107":[101,46],"123":[101,46],"129":[101,46]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/components/Compare/AiInsightsCard.vue":{"9":[101],"24":[101],"25":[101],"30":[101],"36":[101],"40":[101],"48":[101],"50":[101],"64":[101],"71":[101],"77":[101],"83":[101],"94":[101],"104":[101],"126":[101],"139":[101],"146":[101],"159":[101]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/components/Compare/CasesTable.vue":{"27":[101],"44":[101],"49":[101],"56":[101],"57":[101],"62":[101],"65":[101],"70":[101],"73":[101],"81":[101],"87":[101],"91":[101],"92":[101],"97":[101],"116":[101],"144":[101],"149":[101],"162":[101],"166":[101],"173":[101],"184":[101],"188":[101]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/components/Compare/CompareHeader.vue":{"27":[101],"28":[101],"34":[101],"51":[101],"63":[101],"64":[101],"72":[101],"95":[101],"104":[101],"124":[101],"127":[101]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/components/Compare/CompareTabs.vue":{"16":[101],"36":[101],"43":[101],"46":[101],"49":[101],"52":[101],"68":[101]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/components/Compare/DatasetMismatchBanner.vue":{"8":[101],"14":[101],"15":[101],"19":[101]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/components/Compare/MetricCriteria.vue":{"19":[101],"21":[101],"44":[101],"49":[101]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/components/Compare/OutputsTab.vue":{"20":[101],"47":[101],"48":[101],"51":[101],"56":[101],"65":[101],"75":[101],"82":[101],"84":[101],"92":[101],"99":[101],"107":[101],"125":[101],"134":[101]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/components/Compare/ScoreChart.vue":{"21":[101],"25":[101],"36":[101],"37":[101],"43":[101],"50":[101],"57":[101],"63":[101]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/components/shared/GroupedMetricChart.vue":{"48":[101],"54":[101],"59":[101],"81":[101],"91":[101],"125":[101],"126":[101]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/components/shared/VersionAvatar.vue":{"10":[101],"22":[101],"24":[101],"25":[101]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/components/shared/versionPalette.ts":{"15":[101],"21":[101]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/composables/useCompareCases.ts":{"42":[101],"45":[101],"46":[101],"56":[101],"79":[101],"103":[101],"114":[101],"124":[101],"127":[101],"133":[101],"136":[101],"142":[101],"148":[101],"149":[101],"154":[101],"158":[101],"162":[101],"164":[101],"168":[101],"172":[101],"173":[101],"191":[101],"197":[101],"202":[101],"213":[101],"214":[101],"215":[101],"227":[101],"239":[101],"241":[101]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/composables/useCompareData.ts":{"47":[101],"50":[101],"52":[101],"67":[101],"68":[101],"78":[101],"79":[101],"82":[101]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/composables/useEvalCollectionsFlag.ts":{"24":[101]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/evalCollections.api.ts":{"16":[101],"34":[101],"141":[101]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/evalCollections.store.ts":{"24":[101],"27":[101],"28":[101],"30":[101],"49":[101],"64":[101],"66":[101],"85":[101],"261":[101],"339":[101]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/evaluation.api.ts":{"70":[101,46],"74":[101,46],"79":[46],"92":[46],"119":[46],"135":[46],"143":[101,46],"147":[101,46],"162":[46],"178":[101,46],"186":[46],"200":[46],"213":[46],"228":[46],"243":[46]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/evaluation.utils.ts":{"21":[101,46],"42":[46],"90":[101,46],"94":[101,46],"99":[46],"104":[46],"105":[46],"108":[101,46],"115":[101,46],"118":[101,46],"130":[101,46],"133":[101,46],"136":[101,46],"145":[46],"146":[46],"155":[101,46],"165":[101,46],"178":[101,46],"180":[101,46],"181":[101,46],"187":[101,46],"189":[101,46],"203":[101,46],"213":[46],"220":[46],"230":[101,46],"244":[101,46],"251":[101,46],"272":[46],"282":[101,46],"304":[101,46],"309":[46],"336":[101,46],"341":[46],"347":[46],"371":[46],"375":[46],"379":[46],"388":[101,46],"405":[46],"424":[46],"440":[46]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/views/CompareCollectionView.vue":{"38":[101],"42":[101],"58":[101],"69":[101],"70":[101],"86":[101],"89":[101],"92":[101],"98":[101],"112":[101],"137":[101],"151":[101],"187":[101]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/views/EvaluationsRootView.vue":{"44":[101,75],"46":[101],"47":[101],"52":[101],"56":[101],"91":[101],"101":[101,75],"118":[101,75]},"packages/@n8n/ai-workflow-builder.ee/src/agents/planner.agent.ts":{"62":[33],"64":[33],"109":[33],"136":[33]},"packages/@n8n/ai-workflow-builder.ee/src/agents/responder.agent.ts":{"78":[33],"104":[33],"108":[33],"112":[33],"121":[33],"186":[33],"231":[33],"269":[33]},"packages/@n8n/ai-workflow-builder.ee/src/agents/supervisor.agent.ts":{"23":[33],"66":[33],"74":[33],"122":[33]},"packages/@n8n/ai-workflow-builder.ee/src/ai-workflow-builder-agent.service.ts":{"39":[102,33],"64":[102,33],"69":[102,33],"90":[102,33],"106":[102,33],"163":[102,33],"171":[102,33],"175":[102,33],"184":[102,33],"190":[102,33],"200":[102,33],"237":[102,33],"248":[102,33],"271":[102,33],"330":[102,33],"367":[102,33],"369":[102,33],"376":[102,33],"378":[102,33],"383":[102,33],"384":[102,33],"389":[102,33],"404":[102,33],"427":[102,33],"433":[102,33],"451":[102,33],"470":[102,33],"486":[102,33],"505":[102,33],"545":[102,33]},"packages/@n8n/ai-workflow-builder.ee/src/llm-config.ts":{"26":[33],"28":[33],"43":[33],"45":[33],"64":[33],"66":[33],"90":[33],"92":[33],"112":[33],"114":[33],"144":[33],"145":[33],"147":[33],"243":[33]},"packages/@n8n/ai-workflow-builder.ee/src/multi-agent-workflow-subgraphs.ts":{"56":[33],"73":[33],"113":[33],"118":[33],"187":[33],"194":[33],"211":[33],"252":[33],"275":[33],"286":[33],"353":[33],"379":[33],"391":[33],"392":[33],"402":[33],"403":[33],"406":[33],"433":[33],"444":[33],"452":[33],"506":[33],"525":[33],"527":[33],"536":[33],"544":[33]},"packages/@n8n/ai-workflow-builder.ee/src/prompts/agents/discovery.prompt.ts":{"30":[33],"32":[33],"36":[33],"38":[33],"347":[33],"358":[33],"368":[33],"372":[33]},"packages/@n8n/ai-workflow-builder.ee/src/prompts/agents/planner.prompt.ts":{"73":[33],"98":[33],"109":[33],"122":[33],"129":[33],"130":[33]},"packages/@n8n/ai-workflow-builder.ee/src/prompts/agents/responder.prompt.ts":{"168":[33],"178":[33],"188":[33],"200":[33],"205":[33],"226":[33],"232":[33],"244":[33]},"packages/@n8n/ai-workflow-builder.ee/src/prompts/builder/prompt-builder.ts":{"17":[33],"30":[33],"44":[33],"55":[33],"79":[33],"116":[33],"129":[33],"149":[33],"175":[33],"197":[33],"228":[33],"252":[33],"268":[33],"282":[33],"302":[33],"330":[33],"357":[33]},"packages/@n8n/ai-workflow-builder.ee/src/prompts/index.ts":{"31":[33],"45":[33],"47":[33]},"packages/@n8n/ai-workflow-builder.ee/src/session-manager.service.ts":{"36":[102,33],"54":[102,33],"62":[102,33],"72":[102,33],"83":[102,33],"87":[102,33],"96":[102,33],"104":[102,33],"118":[102,33],"132":[102,33],"160":[102,33],"166":[102,33],"174":[102,33],"180":[102,33],"185":[102,33],"200":[102,33],"222":[102,33],"270":[102,33],"275":[102,33],"279":[102,33],"283":[102,33],"300":[102,33],"312":[102,33],"335":[102,33],"363":[102,33],"378":[102,33],"427":[102,33],"440":[102,33],"532":[102,33],"564":[102,33],"583":[102,33],"666":[102,33],"674":[102,33]},"packages/@n8n/ai-workflow-builder.ee/src/subgraphs/discovery.subgraph.ts":{"104":[33],"105":[33],"110":[33],"111":[33],"116":[33],"117":[33],"122":[33],"123":[33],"128":[33],"129":[33],"134":[33],"135":[33],"140":[33],"141":[33],"146":[33],"147":[33],"152":[33],"153":[33],"176":[33],"177":[33],"182":[33],"188":[33],"194":[33],"200":[33],"201":[33],"206":[33],"207":[33],"212":[33],"213":[33],"218":[33],"219":[33],"224":[33],"225":[33],"230":[33],"231":[33],"238":[33],"239":[33],"277":[33],"305":[33],"308":[33],"352":[33],"378":[33],"397":[33],"441":[33],"448":[33],"495":[33],"502":[33],"562":[33],"564":[33],"592":[33],"660":[33],"671":[33],"710":[33],"722":[33],"770":[33],"796":[33]},"packages/@n8n/ai-workflow-builder.ee/src/tools/get-documentation.tool.ts":{"60":[33],"81":[33],"88":[33],"113":[33],"115":[33],"136":[33],"146":[33]},"packages/@n8n/ai-workflow-builder.ee/src/tools/node-search.tool.ts":{"46":[33],"91":[33],"105":[33],"121":[33],"123":[33],"170":[33]},"packages/@n8n/ai-workflow-builder.ee/src/tools/utils/ssrf-guard.ts":{"27":[102,33],"37":[102,33],"39":[102,33],"40":[102,33],"42":[102,33],"52":[102,33],"62":[102,33]},"packages/@n8n/ai-workflow-builder.ee/src/tools/utils/web-fetch-security.ts":{"35":[33],"48":[33],"55":[33],"61":[33],"64":[33],"67":[33],"70":[33],"111":[33],"112":[33],"120":[33],"121":[33],"122":[33],"123":[33],"127":[33],"131":[33],"144":[33],"146":[33],"163":[33],"167":[33]},"packages/@n8n/ai-workflow-builder.ee/src/tools/web-fetch.tool.ts":{"30":[33],"69":[33],"83":[33],"86":[33]},"packages/@n8n/ai-workflow-builder.ee/src/utils/thread-id.ts":{"7":[33]},"packages/@n8n/ai-workflow-builder.ee/src/utils/workflow-sanitization.ts":{"12":[33],"25":[33],"31":[33],"53":[33]},"packages/@n8n/ai-workflow-builder.ee/src/workflow-builder-agent.ts":{"167":[33],"185":[33],"197":[33],"205":[33],"215":[33],"236":[33],"317":[33],"346":[33],"364":[33],"394":[33],"412":[33],"443":[33],"465":[33],"478":[33],"517":[33],"589":[33],"604":[33],"620":[33],"670":[33],"688":[33],"692":[33]},"packages/@n8n/api-types/src/dto/ai/ai-build-request.dto.ts":{"41":[33],"51":[33],"61":[33],"63":[33],"72":[33],"75":[33],"86":[33],"95":[33]},"packages/cli/src/controllers/ai.controller.ts":{"45":[102,33],"54":[102,33],"70":[102,33],"87":[102,33],"96":[102,33],"170":[102,33],"175":[102,33],"184":[102,33],"205":[102,33],"224":[102,33],"238":[102,33],"248":[102,33],"267":[102,33],"278":[102,33],"289":[102,33],"304":[102,33],"317":[102,33],"337":[102,33],"352":[102,33]},"packages/cli/src/modules/workflow-builder/workflow-builder-session.repository.ts":{"22":[33],"26":[33],"46":[33],"73":[33],"78":[33]},"localhost-36301/assets/index-Dv_brJ4-.js":{"3":[33]},"localhost-36301/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[33],"9":[33],"10":[33],"19":[33],"23":[33],"29":[33],"33":[33],"34":[33]},"packages/frontend/@n8n/design-system/src/components/CanvasPill/CanvasPill.vue":{"8":[31,33,46],"9":[31,33,46]},"packages/frontend/@n8n/design-system/src/components/CanvasThinkingPill/CanvasThinkingPill.vue":{"17":[31,33,46],"23":[31,33,46],"27":[31,33,46],"30":[31,33,46],"40":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/assistant.types.ts":{"422":[31,33,46],"439":[31,46],"445":[46],"458":[31,33,46],"464":[31,33,46],"468":[31,46],"492":[31,46],"499":[46],"505":[31,46],"511":[31,46],"523":[31,46],"529":[31,46],"535":[31,46],"545":[31,46],"551":[31,46],"555":[31,46],"561":[31,46],"573":[31,33,46],"579":[31,46]},"packages/frontend/editor-ui/src/features/ai/assistant/builder.utils.ts":{"19":[31,33,46],"23":[31,33,46],"27":[31,33,46],"121":[46],"122":[46],"130":[31,33,46],"141":[31,33,46],"152":[46],"161":[46],"165":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/components/HubSwitcher.vue":{"11":[31,102,33,46],"19":[31,102,33,46],"24":[46],"26":[31,102,33,46]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/CanvasNodeChoicePrompt.vue":{"21":[31,102,33,46],"30":[31,102,33,46],"41":[31,102,33,46],"44":[31,102,33,46],"46":[31,102,33,46],"50":[46],"61":[46],"65":[31,102,33,46],"75":[46],"83":[31,102,33,46],"87":[31,102,33,46],"112":[46]},"packages/@n8n/api-types/src/dto/data-table/list-data-table-content-query.dto.ts":{"15":[46,47,114],"42":[46,47,114]},"packages/cli/src/modules/data-table/data-table-column.repository.ts":{"22":[47,114],"33":[47,114],"35":[47,114],"46":[47,114],"65":[47,114],"75":[47,114],"79":[47,114],"91":[47,114],"101":[47,114],"103":[47,114],"128":[47,114],"130":[47,114],"144":[47,114],"150":[47,114],"155":[47,114],"178":[47,114],"185":[47,114],"204":[47,114],"211":[47,114],"231":[47,114],"233":[47,114],"238":[47,114]},"packages/cli/src/modules/data-table/data-table-ddl.service.ts":{"23":[47,114],"25":[47,114],"31":[47,114],"45":[47,114],"47":[47,114],"55":[47,114],"67":[47,114],"74":[47,114],"76":[47,114],"84":[47,114],"91":[47,114],"96":[47,114],"103":[47,114],"108":[47,114],"116":[47,114]},"packages/cli/src/modules/data-table/data-table-rows.repository.ts":{"56":[47,114],"147":[47,114],"149":[47,114],"156":[47,114],"177":[47,114],"218":[47,114],"226":[47,114],"232":[47,114],"233":[47,114],"272":[47,114],"284":[47,114],"305":[47,114],"314":[47,114],"319":[47,114],"320":[47,114],"354":[47,114],"359":[47,114],"378":[47,114],"384":[47,114],"421":[47,114],"430":[47,114],"462":[47,114],"468":[47,114],"469":[47,114],"490":[47,114],"492":[47,114],"499":[47,114],"507":[47,114],"522":[47,114],"536":[47,114],"557":[47,114],"569":[47,114],"587":[47,114],"596":[47,114],"597":[47,114],"616":[47,114],"641":[47,114],"652":[47,114],"678":[47,114],"687":[47,114],"706":[47,114],"721":[47,114],"729":[47,114]},"packages/cli/src/modules/data-table/data-table.controller.ts":{"54":[47,114],"60":[47,114],"80":[47,114],"89":[47,114],"106":[47,114],"134":[47,114],"148":[47,114],"172":[47,114],"193":[47,114],"213":[47,114],"229":[47,114],"245":[47,114],"267":[47,114],"289":[47,114],"314":[47,114],"355":[47,114],"384":[47,114],"414":[47,114],"445":[47,114],"476":[47,114]},"packages/frontend/@n8n/design-system/src/components/N8nSelectedItemsInfo/SelectedItemsInfo.vue":{"11":[46,47,114],"20":[46,47],"27":[46,47],"31":[46,47],"33":[46,47,114]},"packages/frontend/editor-ui/src/features/core/dataTable/DataTableDetailsView.vue":{"49":[47,114],"51":[47,114],"69":[47,114],"88":[47],"96":[47],"103":[47],"111":[47],"143":[47,114],"150":[47,114],"157":[114],"200":[47,114],"203":[47,114],"207":[47,114],"218":[47,114]},"packages/frontend/editor-ui/src/features/core/dataTable/DataTableView.vue":{"64":[47,114],"65":[47,114],"73":[47,114],"82":[47,114],"84":[47,114],"110":[47,114],"130":[47,114],"135":[47,114],"171":[47,114],"176":[47,114],"180":[47,114],"181":[47,114],"216":[47,114],"226":[47,114]},"packages/frontend/editor-ui/src/features/core/dataTable/components/AddDataTableModal.vue":{"120":[47,114],"140":[47,114],"141":[47,114],"149":[47,114],"188":[47,114],"267":[47,114],"334":[47,114],"339":[47,114],"345":[47,114],"357":[47,114],"358":[47,114],"361":[47,114]},"packages/frontend/editor-ui/src/features/core/dataTable/components/DataTableActions.vue":{"54":[47,114],"55":[47,114],"57":[47,114],"92":[114],"154":[114]},"packages/frontend/editor-ui/src/features/core/dataTable/components/DataTableBreadcrumbs.vue":{"16":[47,114],"38":[47,114],"42":[47,114],"46":[47,114],"81":[47],"103":[47,114],"109":[47,114],"119":[47,114],"122":[47,114]},"packages/frontend/editor-ui/src/features/core/dataTable/components/DataTableCard.vue":{"34":[47,114],"44":[47,114],"49":[47,114],"50":[47,114],"55":[47,114],"64":[47,114],"67":[47,114],"74":[47,114],"81":[47,114],"93":[47,114],"105":[47,114],"114":[47,114],"120":[47,114]},"packages/frontend/editor-ui/src/features/core/dataTable/components/DownloadDataTableModal.vue":{"25":[47,114]},"packages/frontend/editor-ui/src/features/core/dataTable/components/ImportCsvModal.vue":{"22":[47,114],"158":[47,114],"171":[47,114],"174":[47,114]},"packages/frontend/editor-ui/src/features/core/dataTable/components/dataGrid/AddColumnButton.vue":{"31":[47,114],"48":[47,114],"74":[47,114],"76":[47],"79":[47],"85":[47],"122":[47],"131":[47],"137":[47],"150":[47,114],"162":[47,114],"168":[47,114],"182":[47],"192":[47],"225":[47],"229":[47],"230":[47],"251":[47]},"packages/frontend/editor-ui/src/features/core/dataTable/components/dataGrid/AddRowButton.vue":{"6":[47,114],"15":[47,114],"16":[47,114]},"packages/frontend/editor-ui/src/features/core/dataTable/components/dataGrid/DataTableLoadingIndicator.vue":{"8":[47,114],"15":[47,114]},"packages/frontend/editor-ui/src/features/core/dataTable/components/dataGrid/DataTableTable.vue":{"54":[47,114],"57":[47,114],"75":[47,114],"96":[47,114],"114":[47],"123":[47,114],"124":[47],"127":[47],"135":[47],"139":[47],"143":[47],"147":[47,114],"170":[47,114],"191":[47],"196":[47,114],"197":[47],"229":[47,114]},"packages/frontend/editor-ui/src/features/core/dataTable/components/dataGrid/registerAgGridModulesOnce.ts":{"27":[47,114]},"packages/frontend/editor-ui/src/features/core/dataTable/composables/useAgGrid.ts":{"23":[47,114],"34":[47,114],"86":[47,114],"98":[47,114],"118":[47],"124":[47],"133":[47],"135":[47],"145":[47],"153":[47],"173":[47],"212":[47,114],"231":[47,114]},"packages/frontend/editor-ui/src/features/core/dataTable/composables/useDataTableColumnFilters.ts":{"19":[47,114]},"packages/frontend/editor-ui/src/features/core/dataTable/composables/useDataTableColumns.ts":{"40":[47,114],"59":[47,114],"66":[47],"77":[47],"97":[47],"123":[47,114],"132":[47,114],"159":[47,114],"161":[47,114],"165":[47,114],"208":[47,114],"214":[47,114],"218":[47],"219":[47],"226":[47],"234":[47],"242":[47],"244":[47],"245":[47]},"packages/frontend/editor-ui/src/features/core/dataTable/composables/useDataTableOperations.ts":{"59":[47,114],"116":[47],"118":[47],"136":[47],"139":[47],"209":[47],"234":[47],"245":[47],"261":[47],"284":[47],"337":[47,114],"363":[47],"399":[47]},"packages/frontend/editor-ui/src/features/core/dataTable/composables/useDataTablePagination.ts":{"11":[47,114],"17":[47,114],"21":[47],"32":[47]},"packages/frontend/editor-ui/src/features/core/dataTable/composables/useDataTableSelection.ts":{"5":[47,114],"13":[47,114],"15":[47,114],"21":[47],"22":[47,114],"27":[47],"31":[47],"40":[47,114]},"packages/frontend/editor-ui/src/features/core/dataTable/composables/useDataTableTypes.ts":{"8":[47,114],"9":[47,114],"18":[47,114],"25":[47,114]},"packages/frontend/editor-ui/src/features/core/dataTable/modals.ts":{"12":[46,47,114]},"packages/frontend/editor-ui/src/features/core/dataTable/module.descriptor.ts":{"15":[46,47,114],"16":[46,47,114],"17":[46,47,114],"34":[46,114],"38":[46,114],"39":[46,114],"45":[46]},"packages/frontend/editor-ui/src/features/core/dataTable/typeGuards.ts":{"11":[47],"21":[47,114]},"packages/frontend/editor-ui/src/features/core/dataTable/utils/columnUtils.ts":{"26":[47],"29":[47],"35":[47,114],"36":[47,114],"51":[47,114],"52":[47,114],"65":[47,114],"66":[47,114],"94":[47,114],"95":[47],"119":[47],"126":[47,114],"135":[47],"141":[47],"149":[47,114],"156":[47,114],"163":[47,114],"170":[47,114],"177":[47],"184":[47,114],"191":[47,114],"198":[47,114],"205":[47,114],"212":[47,114],"219":[47,114],"229":[47,114],"241":[47],"253":[47]},"packages/@n8n/agents/src/runtime/loop/generate-sink.ts":{"27":[49],"30":[49],"32":[49],"46":[49],"67":[49],"74":[49],"81":[49],"89":[49],"93":[49],"104":[49]},"packages/@n8n/ai-utilities/src/llm-output/extract-json.ts":{"4":[49],"10":[49],"30":[49],"42":[49],"64":[49]},"packages/@n8n/instance-ai/src/tools/workflows/credential-utils.ts":{"35":[49],"46":[49],"62":[49],"95":[49],"109":[49],"114":[49],"118":[49],"136":[49]},"packages/@n8n/instance-ai/src/utils/parse-model-headers.ts":{"5":[49]},"packages/@n8n/workflow-sdk/src/mock-data/ai-root-shapes.ts":{"38":[49,50],"51":[49,50],"70":[49,50],"76":[49,50],"93":[49,50]},"packages/@n8n/workflow-sdk/src/mock-data/data-table-read.ts":{"39":[49],"48":[49],"69":[49],"76":[49]},"packages/@n8n/workflow-sdk/src/mock-data/date-anchors.ts":{"15":[49],"25":[49]},"packages/@n8n/workflow-sdk/src/mock-data/parse.ts":{"10":[49],"31":[49],"43":[49],"50":[49],"54":[49],"58":[49],"84":[49],"90":[49],"116":[49]},"packages/@n8n/workflow-sdk/src/mock-data/prompt.ts":{"29":[49],"76":[49],"112":[49]},"packages/nodes-base/nodes/Slack/Slack.node.ts":{"8":[29,31,9,49,126,134,139]},"packages/nodes-base/nodes/Slack/SlackTriggerHelpers.ts":{"8":[29,31,9,49,126,134,139],"22":[29,31,9,49,126,134,139],"39":[29,31,9,49,126,134,139],"50":[29,31,9,49,126,134,139],"104":[29,31,9,49,126,134,139],"119":[29,31,9,49,126,134,139],"139":[29,31,9,49,126,134,139],"143":[29,31,9,49,126,134,139]},"packages/nodes-base/nodes/Slack/V1/GenericFunctions.ts":{"16":[29,31,9,49,126,134,139],"19":[29,31,9,49,126,134,139],"20":[29,31,9,49,126,134,139],"26":[29,31,9,49,126,134,139],"27":[29,31,9,49,126,134,139],"33":[29,31,9,49,126,134,139],"104":[29,31,9,49,126,134,139],"140":[29,31,9,49,126,134,139]},"packages/nodes-base/nodes/Slack/V1/SlackV1.node.ts":{"76":[29,31,9,49,126,134,139],"190":[29,31,9,49,126,134,139],"202":[29,31,9,49,126,134,139],"216":[29,31,9,49,126,134,139],"236":[29,31,9,49,126,134,139],"250":[29,31,9,49,126,134,139],"268":[29,31,9,49,126,134,139],"476":[29,31,9,49,126,134,139],"486":[29,31,9,49,126,134,139]},"packages/nodes-base/nodes/Slack/V2/GenericFunctions.ts":{"41":[29,31,9,49,126,134,139],"48":[29,31,9,49,126,134,139],"51":[29,31,9,49,126,134,139],"52":[29,31,9,49,126,134,139],"58":[29,31,9,49,126,134,139],"59":[29,31,9,49,126,134,139],"70":[29,31,9,49,126,134,139],"136":[29,31,9,49,126,134,139],"140":[29,31,9,49,126,134,139],"200":[29,31,9,49,126,134,139],"213":[29,31,9,49,126,134,139],"249":[29,31,9,49,126,134,139],"314":[29,31,9,49,126,134,139],"354":[29,31,9,49,126,134,139],"398":[29,31,9,49,126,134,139],"473":[29,31,9,49,126,134,139],"483":[29,31,9,49,126,134,139],"510":[29,31,9,49,126,134,139],"526":[29,31,9,49,126,134,139],"570":[29,31,9,49,126,134,139]},"packages/nodes-base/nodes/Slack/V2/SlackHitlWebhook.ts":{"23":[29,31,9,49,126,134,139],"60":[29,31,9,49,126,134,139],"80":[29,31,9,49,126,134,139],"91":[29,31,9,49,126,134,139],"141":[29,31,9,49,126,134,139],"213":[29,31,9,49,126,134,139]},"packages/nodes-base/nodes/Slack/V2/SlackV2.node.ts":{"66":[29,31,9,49,126,134,139],"187":[29,31,9,49,126,134,139],"204":[29,31,9,49,126,134,139],"224":[29,31,9,49,126,134,139],"229":[29,31,9,49,126,134,139],"234":[29,31,9,49,126,134,139],"241":[29,31,9,49,126,134,139],"257":[29,31,9,49,126,134,139],"263":[29,31,9,49,126,134,139],"268":[29,31,9,49,126,134,139],"279":[29,31,9,49,126,134,139],"296":[29,31,9,49,126,134,139],"310":[29,31,9,49,126,134,139],"330":[29,31,9,49,126,134,139],"344":[29,31,9,49,126,134,139],"363":[29,31,9,49,126,134,139],"377":[29,31,9,49,126,134,139],"397":[29,31,9,49,126,134,139],"621":[29,31,9,49,126,134,139],"684":[29,31,9,49,126,134,139],"694":[29,31,9,49,126,134,139],"1644":[29,31,9,49,126,134,139],"1689":[29,31,9,49,126,134,139],"1717":[29,31,9,49,126,134,139]},"packages/nodes-base/utils/webhook-signature-verification.ts":{"64":[29,31,9,49,126,134,139],"106":[29,31,9,49,126,134,139]},"localhost-40937/assets/index-Dv_brJ4-.js":{"3":[49]},"localhost-40937/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[49],"9":[49],"10":[49],"19":[49],"23":[49],"29":[49],"33":[49],"34":[49]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/ConfirmationFooter.vue":{"15":[49]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/InstanceAiWorkflowSetup.vue":{"9":[49]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/components/WorkflowSetupCard.vue":{"14":[49],"23":[49],"25":[49],"26":[49],"28":[49],"32":[49],"36":[49],"55":[49],"67":[49]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/components/WorkflowSetupSectionBody.vue":{"29":[49],"38":[49],"40":[49],"46":[49],"61":[49],"68":[49],"79":[49],"83":[49],"102":[49],"106":[49],"109":[49],"112":[49],"136":[49],"143":[49],"145":[49],"157":[49],"166":[49],"170":[49],"173":[49],"198":[49],"221":[49]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/components/WorkflowSetupWizard.vue":{"6":[49],"15":[49]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/components/WorkflowSetupWizardFooter.vue":{"8":[49],"11":[49],"12":[49],"17":[49],"22":[49],"29":[49],"39":[49],"41":[49],"43":[49],"49":[49],"59":[49],"72":[49],"89":[49],"118":[49]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/composables/useWorkflowSetupActions.ts":{"31":[49],"61":[49],"74":[49]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/composables/useWorkflowSetupApply.ts":{"13":[49]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/composables/useWorkflowSetupBootstrap.ts":{"5":[49],"14":[49]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/composables/useWorkflowSetupContext.ts":{"62":[49],"67":[49],"83":[49],"87":[49],"88":[49],"89":[49],"133":[49],"142":[49],"179":[49]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/composables/useWorkflowSetupInputs.ts":{"15":[49],"77":[49],"89":[49],"96":[49],"102":[49],"128":[49],"141":[49],"145":[49],"149":[49],"220":[49],"245":[49],"254":[49],"257":[49],"268":[49],"271":[49]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/composables/useWorkflowSetupSections.ts":{"11":[49],"16":[49],"21":[49],"75":[49],"98":[49],"123":[49]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/composables/useWorkflowSetupTelemetry.ts":{"46":[49],"62":[49],"75":[49],"79":[49],"85":[49],"91":[49],"190":[49],"204":[49],"211":[49],"229":[49],"234":[49]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/workflowSetup.helpers.ts":{"2":[49]},"packages/frontend/editor-ui/src/features/credentials/composables/useCredentialTestInBackground.ts":{"4":[31,107,46,96,49],"11":[31,46],"20":[31,46],"84":[46,49]},"packages/frontend/editor-ui/src/features/setupPanel/setupPanel.utils.ts":{"8":[31,46,49],"27":[31,46],"65":[31,46],"118":[31,46],"151":[31,46],"242":[31,46],"282":[31,46],"298":[46],"301":[46],"308":[46],"314":[46],"315":[46],"325":[31,46],"328":[46],"333":[31,46]},"localhost-41437/assets/verified-Dido3Ow4.js":{"8":[125]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/edit-image.svg":{"11":[124,125,191]},"packages/frontend/editor-ui/src/app/components/SuggestionFooter.vue":{"11":[11,125],"20":[11,125],"25":[125]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/Panel/NoResults.vue":{"8":[125],"24":[125],"27":[125],"32":[125],"47":[125],"59":[125]},"packages/community-packages.controller.ts":{"11":[129,151],"15":[129,151],"25":[129,151],"31":[129,151],"39":[129,151]},"packages/community-packages.lifecycle.service.ts":{"35":[129,151],"37":[129,151],"49":[129,151],"60":[129,151],"71":[129,151],"94":[129,151],"132":[129,151],"229":[129,151],"245":[129,151],"253":[129,151],"303":[129,151],"313":[129,151],"328":[129,151],"339":[129,151],"358":[129,151],"395":[129,151],"409":[129,151]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/nodeCreator/CommunityNodeDetails.vue":{"20":[129],"40":[129],"103":[129]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/nodeCreator/CommunityNodeDocsLink.vue":{"9":[129],"14":[129],"23":[129]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/nodeCreator/CommunityNodeFooter.vue":{"16":[46,129],"21":[46,129],"25":[46],"29":[46],"35":[46,129],"55":[46,129],"60":[46,129],"67":[46],"75":[46,129],"76":[46,129],"79":[46,129],"82":[46,129],"83":[46,129]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/nodeCreator/CommunityNodeInfo.vue":{"18":[129],"30":[129],"31":[129],"35":[129],"44":[129],"51":[129],"112":[129],"117":[129],"122":[129],"148":[129],"151":[129]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/CommunityNodeItem.vue":{"11":[129]},"packages/@n8n/api-types/src/dto/user/user-update-request.dto.ts":{"6":[154,100],"13":[154,100],"15":[154,100]},"localhost-38195/assets/index-Dv_brJ4-.js":{"3":[70,167,190]},"localhost-38195/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[70,167,190],"9":[70,167,190],"10":[70,167,190],"19":[70,167,190],"23":[70,167,190],"29":[70,167,190],"33":[70,167,190],"34":[70,167,190]},"localhost-38195/assets/verified-Dido3Ow4.js":{"8":[70,167]},"packages/frontend/editor-ui/src/features/credentials/credentials.ee.api.ts":{"6":[46,158,70],"19":[46,59]},"localhost-35655/assets/index-Dv_brJ4-.js":{"3":[80]},"localhost-35655/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[80],"9":[80],"10":[80],"19":[80],"23":[80],"29":[80],"33":[80],"34":[80]},"packages/@n8n/api-types/src/dto/binary-data/binary-data-query.dto.ts":{"8":[34],"12":[34]},"packages/cli/src/binary-data/binary-data-access.service.ts":{"21":[34],"28":[34],"48":[34]},"packages/cli/src/controllers/binary-data.controller.ts":{"18":[34],"24":[34],"44":[34],"58":[34],"89":[34]},"packages/cli/src/webhooks/waiting-forms.ts":{"17":[90,211,54],"20":[90,211,54],"24":[90,211,54],"30":[90,211,54],"41":[90,211,54],"53":[90,211,54],"73":[90,211,54],"152":[90,211,54]},"localhost-37955/assets/index-Dv_brJ4-.js":{"3":"b:AAAAAAAAAAAAAAAEgBAAAAUIEQgQgBEQAAAAAAA="},"localhost-37955/assets/rolldown-runtime-Bq5D3eIA.js":{"8":"b:AAAAAAAAAAAAAAAEgBAAAAUIEQgQgBEQAAAAAAA=","9":"b:AAAAAAAAAAAAAAAEgBAAAAUIEQgQgBEQAAAAAAA=","10":"b:AAAAAAAAAAAAAAAEgBAAAAUIEQgQgBEQAAAAAAA=","19":"b:AAAAAAAAAAAAAAAEgBAAAAUIEQgQgBEQAAAAAAA=","23":"b:AAAAAAAAAAAAAAAEgBAAAAUIEQgQgBEQAAAAAAA=","29":"b:AAAAAAAAAAAAAAAEgBAAAAUIEQgQgBEQAAAAAAA=","33":"b:AAAAAAAAAAAAAAAEgBAAAAUIEQgQgBEQAAAAAAA=","34":"b:AAAAAAAAAAAAAAAEgBAAAAUIEQgQgBEQAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nFormBox/FormBox.vue":{"28":[107,108,46,100],"35":[108,46,100],"36":[108,46,100],"37":[108,46,100],"38":[46],"39":[107,108,46,100],"45":[107,108,46,100],"60":[46],"74":[107,108,46,100]},"packages/frontend/@n8n/design-system/src/components/N8nFormInputs/FormInputs.vue":{"20":[107,108,46,100],"38":[107,108,46,100],"39":[107,108,46,100],"44":[108,46,100],"45":[108,46,100],"56":[107,108,46,100],"57":[107,108,46,100],"60":[107,108,46,100],"64":[107,108,46,100],"65":[46,100],"68":[46,100],"69":[46,100],"70":[46,100],"75":[108,46,100],"81":[107,108,46,100],"88":[46],"92":[46],"96":[46],"108":[46,100],"117":[108,46,100],"124":[108,46,100],"137":[107,108,46,100],"151":[108,46,100],"154":[107,108,46,100],"158":[107,108,46,100],"161":[107,108,46,100],"172":[46],"185":[108,46,100],"186":[107,108,46,100]},"packages/frontend/@n8n/design-system/src/components/ResizeObserver/ResizeObserver.vue":{"6":[107,108,46,100],"21":[107,108,46,100],"23":[107,108,46,100],"25":[107,108,46,100],"30":[107,108,46,100],"36":[107,108,46,100],"37":[107,108,46,100],"38":[107,108,46,100],"47":[108,46,100],"52":[107,108,46,100]},"packages/frontend/editor-ui/src/app/stores/sessionExpiry.store.ts":{"5":[107,108,46,100],"8":[46]},"packages/frontend/editor-ui/src/app/utils/handleSessionExpired.ts":{"12":[107,108,46,100]},"packages/frontend/editor-ui/src/app/utils/rbac/checks/isGuest.ts":{"4":[107,108,46,100]},"packages/frontend/editor-ui/src/app/utils/rbac/middleware/guest.ts":{"6":[107,108,46,100]},"packages/frontend/editor-ui/src/features/core/auth/views/AuthView.vue":{"28":[108,100],"32":[108,100]},"packages/frontend/editor-ui/src/features/core/auth/views/SigninView.vue":{"60":[107,108,100],"75":[107,108,100],"113":[108,100],"118":[107,108,100],"119":[107,108,100],"162":[100],"171":[108,100],"190":[108,100],"207":[108,100],"215":[108,100],"292":[100],"297":[100]},"packages/nodes-base/nodes/Html/Html.node.ts":{"19":[167],"23":[167],"24":[167],"383":[167],"429":[167],"435":[167],"451":[167],"474":[167],"579":[167]},"packages/nodes-base/nodes/Html/utils.ts":{"10":[167],"12":[167],"13":[167],"21":[167],"29":[167],"39":[167]},"packages/cli/src/modules/mcp/mcp-api-key.service.ts":{"24":[208],"30":[208],"52":[208],"67":[208],"104":[208],"113":[208],"126":[208],"142":[208],"143":[208]},"packages/cli/src/modules/mcp/mcp.errors.ts":{"13":[208],"30":[208]},"packages/cli/src/modules/mcp/tools/tool-error.utils.ts":{"8":[208],"12":[208],"26":[208]},"packages/cli/src/modules/mcp/tools/webhook-utils.ts":{"48":[208],"56":[208],"64":[208],"70":[208],"83":[208],"140":[208],"145":[208],"154":[208],"159":[208],"169":[208],"174":[208],"188":[208],"200":[208],"217":[208],"257":[208],"260":[208],"266":[208],"276":[208],"292":[208],"324":[208],"339":[208],"359":[208]},"packages/cli/src/modules/mcp/tools/workflow-inputs.ts":{"55":[208],"60":[208],"77":[208]},"packages/cli/src/modules/mcp/tools/workflow-validation.utils.ts":{"22":[208],"50":[208],"61":[208],"94":[208]},"localhost-37955/assets/verified-Dido3Ow4.js":{"8":[128,176,180]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/n8n-trigger.svg":{"11":[128]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/n8n.svg":{"11":[128,162]},"packages/core/src/execution-engine/node-execution-context/utils/construct-execution-metadata.ts":{"8":[55,172,84],"13":[55,172,84]},"packages/nodes-base/nodes/Kafka/Kafka.node.ts":{"8":[55]},"packages/nodes-base/nodes/Kafka/KafkaTrigger.node.ts":{"8":[55]},"packages/nodes-base/nodes/Kafka/utils.ts":{"42":[55],"59":[55],"133":[55],"149":[55],"162":[55],"197":[55],"204":[55],"237":[55],"288":[55],"294":[55],"330":[55],"360":[55],"384":[55],"389":[55],"392":[55],"395":[55],"400":[55],"404":[55],"407":[55],"410":[55],"413":[55],"416":[55],"445":[55],"448":[55],"463":[55],"496":[55],"500":[55],"544":[55],"595":[55],"622":[55],"645":[55],"655":[55],"683":[55],"686":[55],"695":[55],"697":[55],"706":[55],"707":[55],"730":[55],"746":[55],"768":[55],"773":[55],"774":[55],"793":[55],"804":[55],"805":[55],"815":[55],"816":[55],"817":[55],"844":[55],"852":[55]},"packages/nodes-base/nodes/Kafka/v1/KafkaTriggerV1.node.ts":{"400":[55],"407":[55],"428":[55],"444":[55],"453":[55],"487":[55],"523":[55],"531":[55],"559":[55]},"packages/nodes-base/nodes/Kafka/v1/KafkaV1.node.ts":{"224":[55],"233":[55],"241":[55],"281":[55],"309":[55]},"packages/nodes-base/nodes/Kafka/v2/KafkaTriggerV2.node.ts":{"21":[55],"28":[55],"58":[55],"63":[55],"70":[55],"72":[55],"84":[55],"105":[55],"108":[55],"116":[55],"122":[55]},"packages/nodes-base/nodes/Kafka/v2/KafkaV2.node.ts":{"33":[55],"60":[55],"93":[55],"97":[55],"316":[55],"323":[55],"396":[55],"423":[55]},"packages/nodes-base/nodes/Kafka/v2/TriggerSettings.ts":{"93":[55],"124":[55],"150":[55],"209":[55],"214":[55],"235":[55],"264":[55],"367":[55]},"packages/nodes-base/nodes/Kafka/v2/consumer/ConsumeTopic.ts":{"114":[55],"130":[55],"133":[55],"137":[55],"161":[55],"184":[55],"208":[55],"214":[55],"242":[55],"263":[55],"296":[55],"326":[55]},"packages/nodes-base/nodes/Kafka/v2/consumer/DataEmitter.ts":{"75":[55],"90":[55],"91":[55],"100":[55],"115":[55],"117":[55],"151":[55],"168":[55],"169":[55],"170":[55],"188":[55],"210":[55],"212":[55]},"packages/nodes-base/nodes/Kafka/v2/consumer/MessageParser.ts":{"37":[55],"42":[55],"58":[55],"64":[55],"114":[55]},"packages/nodes-base/nodes/Kafka/v2/consumer/index.ts":{"15":[55]},"packages/nodes-base/nodes/Kafka/v2/transport/LibraryLogger.ts":{"37":[55],"38":[55],"70":[55],"74":[55],"87":[55],"90":[55],"93":[55],"96":[55],"108":[55],"109":[55]},"packages/nodes-base/nodes/Kafka/v2/transport/admin.ts":{"47":[55],"105":[55],"114":[55]},"packages/nodes-base/nodes/Kafka/v2/transport/client.ts":{"17":[55],"30":[55]},"packages/nodes-base/nodes/Kafka/v2/transport/config.ts":{"11":[55],"42":[55],"47":[55]},"packages/nodes-base/nodes/Kafka/v2/transport/consumer.ts":{"70":[55],"72":[55],"84":[55]},"packages/nodes-base/nodes/Kafka/v2/transport/index.ts":{"3":[55]},"packages/nodes-base/nodes/Kafka/v2/transport/producer.ts":{"13":[55]},"localhost-39553/assets/index-Dv_brJ4-.js":{"3":[55]},"localhost-39553/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[55],"9":[55],"10":[55],"19":[55],"23":[55],"29":[55],"33":[55],"34":[55]},"packages/@n8n/codemirror-lang-sql/src/complete.ts":{"192":[46,167],"193":[46,167]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/html.svg":{"11":[167]},"packages/frontend/editor-ui/src/features/shared/editors/components/HtmlEditor/HtmlEditor.vue":{"51":[46,167],"63":[46,167],"68":[46,167],"97":[46,167],"100":[46,167],"105":[46],"120":[46],"137":[46],"143":[46],"149":[46],"156":[46],"161":[46],"170":[46],"237":[46,167],"243":[46,167],"247":[46,167],"251":[46],"260":[46,167],"265":[46,167]},"packages/frontend/editor-ui/src/features/shared/editors/components/HtmlEditor/utils.ts":{"10":[46],"44":[46,167]},"packages/frontend/editor-ui/src/features/shared/editors/components/SqlEditor/SqlEditor.vue":{"42":[46,167],"80":[46,167],"82":[46,167],"88":[46,167],"130":[46,167],"135":[46,167],"140":[46,167],"146":[46,167],"154":[46,167],"158":[46,167],"160":[46,167],"163":[46,167],"172":[46],"180":[46],"199":[46],"208":[46,167],"213":[46,167]},"packages/frontend/editor-ui/src/features/settings/orchestration.ee/components/WorkerList.vue":{"25":[155],"35":[155],"39":[155],"41":[155],"49":[155],"60":[155]},"packages/frontend/editor-ui/src/features/settings/orchestration.ee/orchestration.store.ts":{"26":[155],"56":[155]},"packages/frontend/editor-ui/src/features/settings/orchestration.ee/views/WorkerView.vue":{"30":[155],"33":[155]},"packages/frontend/editor-ui/src/app/utils/stringUtils.ts":{"8":[46,175,84],"16":[46,175,84],"21":[46,175,84],"22":[46,175,84]},"packages/nodes-base/nodes/Airtable/Airtable.node.ts":{"8":[176]},"packages/nodes-base/nodes/Airtable/v1/AirtableV1.node.ts":{"558":[176],"565":[176],"833":[176],"834":[176],"838":[176],"839":[176]},"packages/nodes-base/nodes/Airtable/v1/GenericFunctions.ts":{"29":[176],"72":[176],"100":[176]},"packages/nodes-base/nodes/Airtable/v2/AirtableV2.node.ts":{"15":[176],"29":[176]},"packages/nodes-base/nodes/Airtable/v2/actions/base/getMany.operation.ts":{"88":[176],"112":[176]},"packages/nodes-base/nodes/Airtable/v2/actions/base/getSchema.operation.ts":{"30":[176]},"packages/nodes-base/nodes/Airtable/v2/actions/record/create.operation.ts":{"51":[176]},"packages/nodes-base/nodes/Airtable/v2/actions/record/deleteRecord.operation.ts":{"36":[176]},"packages/nodes-base/nodes/Airtable/v2/actions/record/get.operation.ts":{"60":[176],"85":[176]},"packages/nodes-base/nodes/Airtable/v2/actions/record/search.operation.ts":{"147":[176],"183":[176],"214":[176],"224":[176]},"packages/nodes-base/nodes/Airtable/v2/actions/record/update.operation.ts":{"57":[176]},"packages/nodes-base/nodes/Airtable/v2/actions/record/upsert.operation.ts":{"52":[176],"120":[176],"125":[176],"142":[176]},"packages/nodes-base/nodes/Airtable/v2/actions/router.ts":{"8":[176]},"packages/nodes-base/nodes/Airtable/v2/helpers/utils.ts":{"11":[176],"16":[176],"41":[176],"50":[176],"56":[176],"63":[176],"78":[176],"97":[176],"112":[176],"121":[176],"131":[176]},"packages/nodes-base/nodes/Airtable/v2/methods/listSearch.ts":{"11":[176],"44":[176],"54":[176],"91":[176],"101":[176],"117":[176],"145":[176]},"packages/nodes-base/nodes/Airtable/v2/methods/loadOptions.ts":{"6":[176],"19":[176],"42":[176],"57":[176],"62":[176],"65":[176],"80":[176]},"packages/nodes-base/nodes/Airtable/v2/methods/resourceMapping.ts":{"48":[176],"63":[176],"76":[176],"88":[176],"90":[176],"120":[176]},"packages/nodes-base/nodes/Airtable/v2/transport/index.ts":{"20":[176],"59":[176],"87":[176],"94":[176],"131":[176]},"packages/nodes-base/nodes/Cron/Cron.node.ts":{"53":[176],"59":[176],"66":[176],"71":[176],"74":[176]},"packages/nodes-base/nodes/Typeform/GenericFunctions.ts":{"40":[176],"77":[176],"113":[176]},"packages/nodes-base/nodes/Typeform/TypeformTrigger.node.ts":{"122":[176],"160":[176],"179":[176],"205":[176],"230":[176],"305":[176]},"packages/nodes-base/nodes/Typeform/TypeformTriggerHelpers.ts":{"18":[176],"24":[176],"36":[176]},"packages/workflow/src/workflow-data-proxy-helpers.ts":{"3":[176]},"packages/cli/src/modules/agents/agents-list.controller.ts":{"27":[190],"30":[190],"47":[190],"56":[190],"80":[190]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/empty-output.svg":{"9":[46,176]},"packages/nodes-base/nodes/Google/Gmail/GmailTrigger.node.ts":{"295":[180],"312":[180],"325":[180],"366":[180],"384":[180],"402":[180],"454":[180],"461":[180],"495":[180],"496":[180],"606":[180],"663":[180],"678":[180],"682":[180],"685":[180],"735":[180],"745":[180],"777":[180],"815":[180],"819":[180],"826":[180]},"packages/@n8n/permissions/src/schemas.ee.ts":{"23":[46,88],"50":[46,88],"73":[46,88]},"localhost-46677/assets/index-Dv_brJ4-.js":{"3":[88]},"localhost-46677/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[88],"9":[88],"10":[88],"19":[88],"23":[88],"29":[88],"33":[88],"34":[88]},"packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreZep/VectorStoreZep.node.ts":{"81":[7],"108":[7]},"packages/frontend/editor-ui/src/features/workflows/components/WorkflowShareModal.ee.vue":{"42":[46,156,159,190],"60":[46,156,159,190],"63":[46,156,159,190],"64":[46,156,159,190],"65":[46,159,190],"68":[46,156,159,190],"71":[46,156,159,190],"74":[46,156,159,190],"87":[46,156,159,190],"91":[46,156,159,190],"93":[46,156,159,190],"112":[46,156,159,190],"116":[46,156,159,190],"123":[46],"131":[46,159,190],"134":[46,156],"136":[46,156,159,190],"141":[46,156,159,190],"142":[46,156,159,190],"158":[46,159],"165":[46,159],"172":[46],"179":[46,159],"186":[46,159],"221":[46,159],"243":[46],"247":[46,156,159,190],"262":[46,156,159,190],"268":[46,159],"274":[46,156,159,190],"286":[46,156,159,190],"301":[46],"330":[46,156],"331":[46,156],"334":[46,156],"349":[46],"367":[46,156,159,190],"370":[46],"379":[46,156,159,190],"381":[46,156,159,190],"383":[46],"384":[46,156],"393":[46,159,190]},"packages/frontend/editor-ui/src/features/workflows/workflowHistory/components/WorkflowHistoryVersionUnpublishModal.vue":{"22":[46,190],"44":[46,190],"51":[46],"62":[46,190],"64":[46,190],"67":[46],"68":[46],"69":[46,190],"73":[46,190],"76":[46,190],"77":[46],"81":[46,190],"85":[46],"89":[46],"94":[46,190],"100":[46,190],"103":[46,190],"107":[46,190],"109":[46,190],"116":[46,190],"121":[46,190],"129":[46],"132":[46],"134":[46],"137":[46],"139":[46],"141":[46],"146":[46],"158":[46,190],"161":[46,190],"164":[46,190]},"localhost-35535/assets/index-Dv_brJ4-.js":{"3":[104,107,42,124,147,69,156,159]},"localhost-35535/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[104,107,42,124,147,69,156,159],"9":[104,107,42,124,147,69,156,159],"10":[104,107,42,124,147,69,156,159],"19":[104,107,42,124,147,69,156,159],"23":[104,107,42,124,147,69,156,159],"29":[104,107,42,124,147,69,156,159],"33":[104,107,42,124,147,69,156,159],"34":[104,107,42,124,147,69,156,159]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/WorkflowBuilderUnavailableNotice.vue":{"7":[107],"10":[107],"15":[107],"22":[107]},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useInstanceAiConfiguration.ts":{"11":[107,96],"21":[107,96],"23":[107,96],"24":[96],"25":[107,96],"26":[96],"27":[107,96]},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useInstanceCredentialTest.ts":{"13":[107,96]},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAiConfiguration.ts":{"17":[107,46,96],"23":[46],"26":[46,96]},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAiSetup.telemetry.ts":{"24":[96],"74":[107,96],"75":[107,96]},"packages/frontend/editor-ui/src/features/ai/instanceAi/onboarding/InstanceAiOnboardingIntro.vue":{"31":[107,96],"41":[107,96],"46":[96],"65":[96],"93":[96]},"packages/frontend/editor-ui/src/features/ai/instanceAi/onboarding/InstanceAiOnboardingView.vue":{"23":[107,96],"33":[107,96],"34":[107,96],"35":[96],"43":[107,96],"44":[107,96],"57":[107,96],"64":[107,96],"74":[96],"78":[107,96],"81":[107,96],"82":[96],"99":[96],"136":[107,96],"142":[107,96]},"packages/frontend/editor-ui/src/features/ai/instanceAi/onboarding/InstanceAiOnboardingWizard.vue":{"53":[107,96],"129":[96],"130":[96],"191":[96],"199":[96],"216":[96],"246":[96],"255":[96],"259":[96],"260":[96],"269":[107,96],"272":[96],"278":[96],"281":[96],"396":[96],"415":[96],"428":[107,96],"430":[107,96],"453":[96],"488":[96],"494":[96],"521":[96],"522":[96],"559":[96],"611":[96],"642":[96],"681":[96],"706":[96],"711":[96],"712":[96],"732":[107,96],"1102":[96],"1138":[96],"1150":[96],"1165":[96],"1170":[96],"1199":[96],"1201":[96],"1213":[96],"1236":[96],"1266":[96],"1272":[96],"1286":[96],"1291":[96],"1297":[96],"1302":[96],"1328":[96],"1354":[96]},"packages/frontend/editor-ui/src/features/ai/instanceAi/onboarding/useInstanceAiOnboarding.ts":{"12":[107,96],"17":[107,96],"24":[96],"33":[96],"39":[96],"44":[96]},"packages/cli/src/controllers/password-reset.controller.ts":{"46":[204],"72":[204],"117":[204],"174":[204],"203":[204],"234":[204]},"packages/cli/src/middlewares/jitter.ts":{"15":[204],"19":[204]},"packages/cli/src/user-management/email/node-mailer.ts":{"19":[204],"48":[204],"84":[204]},"packages/@n8n/decorators/src/credential-resolver/errors.ts":{"5":[194],"16":[194],"27":[194]},"packages/cli/src/modules/dynamic-credentials.ee/config-redaction.ts":{"5":[194],"13":[194],"32":[194],"34":[194],"49":[194],"60":[194],"62":[194],"88":[194]},"packages/cli/src/modules/dynamic-credentials.ee/credential-resolvers/identifiers/n8n-identifier.ts":{"50":[194,211,10],"52":[194,211,10],"79":[194,211,10],"100":[194,211,10],"108":[194,211,10],"112":[194,211,10],"196":[194,211,10],"236":[194,211,10],"246":[194,211,10],"261":[194,211,10]},"packages/cli/src/modules/dynamic-credentials.ee/credential-resolvers/identifiers/oauth2-metadata-http-client.ts":{"36":[194],"53":[194],"66":[194]},"packages/cli/src/modules/dynamic-credentials.ee/credential-resolvers/identifiers/oauth2-userinfo-identifier.ts":{"37":[194],"46":[194],"70":[194],"76":[194],"108":[194],"139":[194],"150":[194],"161":[194],"170":[194],"221":[194],"240":[194],"291":[194],"312":[194],"329":[194],"338":[194],"361":[194],"380":[194],"389":[194]},"packages/cli/src/modules/dynamic-credentials.ee/credential-resolvers/identifiers/oauth2-utils.ts":{"20":[194],"25":[194],"39":[194],"46":[194],"66":[194]},"packages/cli/src/modules/dynamic-credentials.ee/credential-resolvers/oauth-credential-resolver.ts":{"40":[194],"135":[194],"164":[194],"185":[194],"195":[194],"199":[194],"212":[194],"217":[194],"228":[194],"236":[194]},"packages/cli/src/modules/dynamic-credentials.ee/credential-resolvers/storage/dynamic-credential-entry-storage.ts":{"10":[194],"14":[194],"31":[194],"53":[194],"66":[194]},"packages/cli/src/modules/dynamic-credentials.ee/credential-resolvers.controller.ts":{"38":[194,205],"47":[194,205],"48":[194,205],"68":[194,205],"78":[194,205],"89":[194,205],"92":[194,205],"103":[194,205],"135":[194,205],"156":[194,205],"176":[194,205],"216":[194,205]},"packages/cli/src/modules/dynamic-credentials.ee/dynamic-credentials.controller.ts":{"35":[194,211],"51":[194,211],"74":[194,211],"115":[194,211],"127":[194,211],"160":[194,211],"172":[194,211],"243":[194,211],"324":[194,211]},"packages/cli/src/modules/dynamic-credentials.ee/services/credential-resolver-registry.service.ts":{"14":[194],"24":[194],"68":[194],"75":[194]},"packages/cli/src/modules/dynamic-credentials.ee/services/credential-resolver.service.ts":{"49":[194,205],"65":[194,205],"90":[194,205],"93":[194,205],"98":[194,205],"101":[194,205],"108":[194,205],"113":[194,205],"114":[194,205],"122":[194,205],"135":[194,205],"194":[194,205],"208":[194,205],"222":[194,205],"264":[194,205],"295":[194,205],"313":[194,205],"320":[194,205],"334":[194,205]},"packages/cli/src/modules/dynamic-credentials.ee/services/dynamic-credential-storage.service.ts":{"27":[194],"36":[194],"132":[194],"138":[194]},"packages/cli/src/modules/dynamic-credentials.ee/services/resolver-config-expression.service.ts":{"16":[194],"23":[194]},"packages/cli/src/modules/dynamic-credentials.ee/services/shared-fields.ts":{"19":[194],"38":[194],"60":[194],"67":[194]},"packages/workflow/src/node-parameters/node-parameter-value-type-guard.ts":{"13":[194],"27":[194],"38":[194],"54":[194],"66":[194],"84":[194],"120":[194]},"packages/@n8n/instance-ai/src/source-map-filter.ts":{"11":[40,215],"28":[40,215],"39":[40,215],"42":[40,215]},"packages/cli/src/modules/dynamic-credentials.ee/context-establishment-hooks/bearer-token-extractor.ts":{"29":[215],"37":[215],"41":[215]},"packages/cli/src/modules/dynamic-credentials.ee/context-establishment-hooks/http-header-extractor.ts":{"24":[215],"32":[215],"53":[215],"75":[215],"101":[215],"105":[215]},"packages/cli/src/credentials/executing-user-identifier-proxy.ts":{"16":[211],"20":[211]},"packages/cli/src/modules/dynamic-credentials.ee/credential-resolvers/n8n-credential-resolver.ts":{"22":[211],"40":[211],"69":[211],"90":[211],"105":[211],"109":[211],"113":[211],"125":[211],"133":[211]},"packages/cli/src/modules/dynamic-credentials.ee/credential-resolvers/storage/dynamic-credential-user-entry-storage.ts":{"14":[211],"26":[211],"52":[211],"81":[211],"100":[211]},"packages/cli/src/modules/dynamic-credentials.ee/services/authorize-intent.service.ts":{"37":[211],"39":[211],"48":[211],"52":[211]},"packages/cli/src/modules/oauth-server/oauth-flow.service.ts":{"25":[211,115],"42":[211,115],"73":[211,115],"145":[211,115]},"packages/cli/src/services/oauth2-flow-proxy.service.ts":{"24":[211,115],"27":[211,115],"31":[211,115],"36":[211,115],"41":[211,115]},"packages/cli/src/utils/handlebars.util.ts":{"6":[211],"10":[211],"11":[211],"22":[211]},"packages/@n8n/ai-utilities/src/utils/redact-secrets.ts":{"7":[10,12],"20":[10,12],"28":[10,12],"50":[10,12],"60":[10,12],"74":[10,12],"82":[10,12],"109":[10,12]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/CredentialGateTool.ts":{"17":[10,12],"19":[10,12],"20":[10,12],"26":[10,12],"32":[10,12]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/McpServer.ts":{"29":[10,12],"46":[10,12],"47":[10,12],"91":[10,12],"103":[10,12],"112":[10,12],"126":[10,12],"136":[10,12],"137":[10,12],"140":[10,12],"155":[10,12],"172":[10,12],"233":[10,12],"240":[10,12],"268":[10,12],"292":[10,12],"296":[10,12],"306":[10,12],"322":[10,12],"326":[10,12],"388":[10,12],"393":[10,12],"398":[10,12],"402":[10,12],"406":[10,12],"410":[10,12],"412":[10,12],"418":[10,12],"425":[10,12],"443":[10,12],"447":[10,12],"450":[10,12],"453":[10,12],"457":[10,12],"461":[10,12],"465":[10,12],"469":[10,12],"476":[10,12],"487":[10,12],"496":[10,12],"512":[10,12],"530":[10,12],"544":[10,12],"557":[10,12],"562":[10,12],"563":[10,12],"603":[10,12],"606":[10,12],"615":[10,12],"634":[10,12],"690":[10,12],"693":[10,12]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/McpTrigger.node.ts":{"34":[10,12],"64":[10,12],"236":[10,12]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/execution/DirectExecutionStrategy.ts":{"6":[10,12]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/execution/ExecutionCoordinator.ts":{"10":[10,12],"14":[10,12],"22":[10,12],"26":[10,12],"30":[10,12]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/execution/PendingCallsManager.ts":{"10":[10,12],"12":[10,12],"15":[10,12],"21":[10,12],"22":[10,12],"38":[10,12],"49":[10,12],"60":[10,12],"64":[10,12],"68":[10,12],"69":[10,12],"72":[10,12],"76":[10,12]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/protocol/MessageFormatter.ts":{"18":[10,12],"52":[10,12],"68":[10,12],"81":[10,12],"82":[10,12],"86":[10,12],"112":[10,12],"113":[10,12],"114":[10,12],"120":[10,12],"126":[10,12]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/protocol/MessageParser.ts":{"11":[10,12],"20":[10,12],"30":[10,12],"40":[10,12],"49":[10,12]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/session/InMemorySessionStore.ts":{"5":[10,12],"11":[10,12],"16":[10,12],"21":[10,12],"26":[10,12],"30":[10,12],"34":[10,12]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/session/SessionManager.ts":{"18":[10,12],"20":[10,12],"35":[10,12],"43":[10,12],"45":[10,12],"46":[10,12],"49":[10,12],"53":[10,12],"56":[10,12],"60":[10,12],"64":[10,12],"68":[10,12],"72":[10,12],"76":[10,12],"80":[10,12],"84":[10,12]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/transport/StreamableHttpTransport.ts":{"17":[10,12],"32":[10,12],"37":[10,12],"49":[10,12],"54":[10,12]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/transport/TransportFactory.ts":{"13":[10,12],"17":[10,12],"23":[10,12],"30":[10,12],"35":[10,12]},"packages/@n8n/nodes-langchain/utils/schemaParsing.ts":{"9":[10,12],"10":[10,12],"41":[10,12],"49":[10,12],"53":[10,12],"68":[10,12],"72":[10,12]},"packages/cli/src/modules/inbound-auth-core/trusted-source.gate.ts":{"18":[10],"27":[10]},"localhost-35945/assets/index-Dv_brJ4-.js":{"3":[96]},"localhost-35945/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[96],"9":[96],"10":[96],"19":[96],"23":[96],"29":[96],"33":[96],"34":[96]},"localhost-44727/assets/index-Dv_brJ4-.js":{"3":[96]},"localhost-44727/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[96],"9":[96],"10":[96],"19":[96],"23":[96],"29":[96],"33":[96],"34":[96]},"packages/frontend/@n8n/design-system/src/components/N8nRadioGroup/RadioGroup.vue":{"11":[46,96],"12":[46,96],"13":[46,96],"37":[46],"43":[46],"45":[46,96],"55":[46]},"packages/frontend/@n8n/design-system/src/components/N8nRadioGroup/RadioGroupItem.vue":{"15":[46,96],"19":[46,96],"22":[46,96],"25":[46],"31":[46,96],"43":[46,96],"51":[46],"53":[46]},"packages/frontend/@n8n/design-system/src/components/N8nSettingsRowConfigure/SettingsRowConfigure.vue":{"22":[46,96,123],"23":[46,96,123]},"localhost-35535/assets/verified-Dido3Ow4.js":{"8":[124,156]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/ftp.svg":{"11":[124]},"packages/nodes-base/nodes/EmailSend/EmailSend.node.ts":{"8":[53]},"packages/nodes-base/nodes/EmailSend/utils.ts":{"1":[53]},"packages/nodes-base/nodes/EmailSend/v1/EmailSendV1.node.ts":{"136":[53],"143":[53]},"packages/nodes-base/nodes/EmailSend/v2/EmailSendV2.node.ts":{"88":[53],"101":[53]},"packages/nodes-base/nodes/EmailSend/v2/send.operation.ts":{"186":[53]},"packages/nodes-base/nodes/EmailSend/v2/sendAndWait.operation.ts":{"28":[53]},"packages/nodes-base/nodes/EmailSend/v2/utils.ts":{"20":[53],"54":[53]},"localhost-38789/assets/index-Dv_brJ4-.js":{"3":[53]},"localhost-38789/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[53],"9":[53],"10":[53],"19":[53],"23":[53],"29":[53],"33":[53],"34":[53]},"packages/nodes-base/nodes/Reddit/GenericFunctions.ts":{"14":[147],"57":[147],"79":[147],"81":[147],"85":[147],"100":[147]},"packages/nodes-base/nodes/Reddit/Reddit.node.ts":{"87":[147],"328":[147],"370":[147]},"localhost-41425/assets/index-Dv_brJ4-.js":{"3":[28,47,115,160,169,182]},"localhost-41425/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[28,47,115,160,169,182],"9":[28,47,115,160,169,182],"10":[28,47,115,160,169,182],"19":[28,47,115,160,169,182],"23":[28,47,115,160,169,182],"29":[28,47,115,160,169,182],"33":[28,47,115,160,169,182],"34":[28,47,115,160,169,182]},"packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/CodeDiffMessage.vue":{"19":[28,46],"20":[28,46],"31":[46],"32":[28,46],"40":[28,46],"41":[28,46]},"packages/frontend/@n8n/design-system/src/components/CodeDiff/CodeDiff.vue":{"10":[28,46],"43":[28,46],"48":[28,46],"49":[46],"85":[28,46],"93":[28,46],"120":[28,46],"121":[28,46],"137":[28,46],"138":[28,46]},"packages/@n8n/backend-services/src/services/ownership-transfer-handler.registry.ts":{"20":[69],"23":[69],"27":[69]},"packages/cli/src/modules/chat-hub/chat-hub-event-relay.service.ts":{"9":[69],"18":[69],"26":[69]},"packages/cli/src/modules/data-table/data-table.module.ts":{"8":[69],"22":[69],"29":[69],"41":[69],"47":[69],"55":[69],"62":[69]},"packages/cli/src/modules/instance-ai/instance-ai-event-relay.service.ts":{"20":[69],"30":[69],"38":[69]},"packages/cli/src/modules/provisioning.ee/provisioning.controller.ee.ts":{"13":[40,69],"21":[40,69],"31":[40,69]},"packages/cli/src/services/ownership-transfer/ownership-transfer.service.ts":{"27":[69],"42":[69],"53":[69],"83":[69],"86":[69],"111":[69]},"packages/frontend/@n8n/rest-api-client/src/api/provisioning.ts":{"22":[46,69],"28":[46]},"packages/frontend/editor-ui/src/app/utils/rbac/checks/isDefaultUser.ts":{"4":[46,69]},"packages/frontend/editor-ui/src/features/roles/instance/instanceRoleScopes.ts":{"153":[69],"163":[69],"168":[69],"186":[69],"240":[69],"249":[69],"264":[69],"270":[69],"282":[69],"297":[69],"301":[69],"307":[69],"311":[69],"322":[69],"326":[69],"347":[69],"359":[69],"360":[69],"364":[69],"365":[69],"448":[69],"488":[69]},"packages/frontend/editor-ui/src/features/settings/sso/provisioning/composables/userRoleProvisioning.store.ts":{"13":[69],"18":[69]},"packages/frontend/editor-ui/src/features/settings/users/components/DeleteUserModal.vue":{"15":[46,69],"32":[46,69],"35":[46,69],"38":[46,69],"40":[46,69],"49":[46,69],"65":[46,69],"71":[46,69],"105":[46,69],"118":[46,69],"122":[46,69],"128":[46,69],"132":[46,69],"134":[46,69],"137":[46,69],"142":[46,69],"154":[46,69],"155":[46,69],"156":[46,69],"165":[46,69],"174":[46,69]},"packages/frontend/editor-ui/src/features/settings/users/components/SettingsUsersActionsCell.vue":{"7":[69],"16":[69],"21":[69]},"packages/frontend/editor-ui/src/features/settings/users/components/SettingsUsersLastActiveCell.vue":{"7":[69],"10":[69],"13":[69]},"packages/frontend/editor-ui/src/features/settings/users/components/SettingsUsersProjectsCell.vue":{"8":[69],"20":[69],"26":[69],"33":[69],"34":[69],"38":[69],"51":[69],"52":[69]},"packages/frontend/editor-ui/src/features/settings/users/components/SettingsUsersProjectsModal.vue":{"17":[69],"52":[69]},"packages/frontend/editor-ui/src/features/settings/users/components/SettingsUsersRoleCell.vue":{"31":[69],"33":[69],"34":[69],"36":[69],"40":[69],"41":[69],"45":[69],"48":[69],"49":[69],"50":[69],"52":[69],"56":[69],"58":[69]},"packages/frontend/editor-ui/src/features/settings/users/components/SettingsUsersTable.vue":{"19":[69],"41":[69],"47":[69],"63":[69],"74":[69],"85":[69],"96":[69],"127":[69],"135":[69],"138":[69],"143":[69],"145":[69],"160":[69],"165":[69],"176":[69],"179":[69],"182":[69],"186":[69]},"packages/frontend/editor-ui/src/features/settings/users/views/SettingsUsersView.vue":{"71":[69],"73":[69],"77":[69],"81":[69],"83":[69],"98":[69],"103":[69],"112":[69],"118":[69],"125":[69],"134":[69],"139":[69],"143":[69],"147":[69],"171":[69],"206":[69],"211":[69],"328":[69],"329":[69],"338":[69],"350":[69],"373":[69],"378":[69],"425":[69],"428":[69],"433":[69],"442":[69],"502":[69],"509":[69]},"packages/frontend/editor-ui/src/app/api/workflows.ee.ts":{"7":[46,159],"20":[46,59],"28":[46]},"packages/cli/src/modules/mcp-registry/mcp-registry-connection.ts":{"22":[11],"28":[11],"41":[11],"58":[11],"63":[11],"64":[11],"69":[11],"105":[11],"111":[11],"181":[11],"190":[11]},"packages/cli/src/modules/mcp-registry/mcp-registry-node-loader.ts":{"41":[11],"71":[11],"76":[11],"80":[11],"91":[11],"108":[11],"112":[11],"144":[11],"150":[11],"158":[11],"162":[11],"168":[11],"174":[11],"183":[11],"188":[11],"192":[11],"196":[11],"215":[11],"217":[11],"219":[11],"220":[11],"222":[11],"226":[11],"231":[11]},"packages/cli/src/modules/mcp-registry/mcp-registry-test.controller.ts":{"17":[11],"23":[11],"29":[11],"38":[11]},"packages/cli/src/modules/mcp-registry/node-description-transform.ts":{"45":[11],"52":[11],"65":[11],"88":[11],"122":[11],"135":[11],"144":[11],"152":[11],"165":[11],"182":[11],"216":[11],"234":[11],"245":[11],"257":[11],"273":[11],"275":[11],"285":[11],"286":[11],"287":[11],"292":[11],"297":[11],"307":[11],"326":[11]},"packages/cli/src/modules/mcp-registry/registry/mcp-registry-capabilities.ts":{"13":[11],"19":[11],"21":[11]},"packages/cli/src/modules/mcp-registry/registry/mcp-registry.service.ts":{"27":[11],"40":[11],"45":[11],"52":[11],"56":[11],"61":[11],"69":[11],"74":[11],"77":[11],"85":[11],"89":[11],"93":[11],"95":[11],"98":[11],"112":[11],"137":[11],"144":[11],"150":[11],"151":[11],"153":[11],"154":[11],"156":[11],"157":[11],"171":[11],"182":[11],"194":[11],"218":[11],"222":[11],"226":[11]},"packages/cli/src/modules/mcp-registry/registry/mcp-registry.types.ts":{"12":[11],"13":[11],"47":[11],"126":[11],"150":[11],"155":[11],"172":[11]},"packages/workflow/src/mcp-helpers.ts":{"57":[11],"105":[11],"116":[11],"134":[11],"168":[11]},"localhost-46229/assets/index-Dv_brJ4-.js":{"3":[11]},"localhost-46229/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[11],"9":[11],"10":[11],"19":[11],"23":[11],"29":[11],"33":[11],"34":[11]},"packages/frontend/editor-ui/src/app/components/McpRegistrySuggestionFooter.vue":{"15":[11]},"packages/@n8n/utils/src/nodes-api-level.ts":{"6":[151],"17":[151]},"packages/cli/src/errors/response-errors/incompatible-nodes-api-version.error.ts":{"8":[151]},"packages/community-packages.service.ts":{"45":[151],"82":[151],"98":[151],"103":[151],"110":[151],"114":[151],"118":[151],"133":[151],"154":[151],"196":[151],"202":[151],"221":[151],"224":[151],"228":[151],"229":[151],"235":[151],"254":[151],"263":[151],"264":[151],"277":[151],"300":[151],"324":[151],"333":[151],"340":[151],"348":[151],"357":[151],"399":[151],"425":[151],"436":[151],"463":[151],"471":[151],"480":[151],"488":[151],"496":[151],"505":[151],"509":[151],"515":[151],"536":[151],"542":[151],"629":[151],"651":[151],"667":[151],"727":[151],"754":[151],"755":[151],"804":[151],"805":[151],"835":[151],"857":[151],"871":[151],"881":[151],"896":[151],"907":[151],"925":[151],"954":[151],"979":[151],"992":[151],"1059":[151],"1066":[151],"1067":[151],"1072":[151],"1073":[151],"1078":[151]},"packages/core/src/nodes-loader/package-directory-loader.ts":{"17":[151],"27":[151],"57":[151],"86":[151],"94":[151],"100":[151]},"packages/installed-packages.repository.ts":{"10":[151],"17":[151],"21":[151],"28":[151],"37":[151]},"packages/npm-utils.ts":{"46":[151],"55":[151],"61":[151],"71":[151],"75":[151],"76":[151],"79":[151],"88":[151],"93":[151],"104":[151],"128":[151],"149":[151],"164":[151],"168":[151],"181":[151],"196":[151],"253":[151],"287":[151],"335":[151]},"packages/workflow/src/nodes-api-version.ts":{"28":[151],"37":[151]},"packages/@n8n/api-types/src/dto/data-table/delete-data-table-rows.dto.ts":{"7":[46,47],"52":[46,47]},"packages/@n8n/api-types/src/dto/data-table/update-data-table-row.dto.ts":{"10":[46,47],"18":[46,47]},"packages/cli/src/modules/data-table/data-table-permissions.ts":{"12":[47]},"localhost-36981/assets/index-Dv_brJ4-.js":{"3":[151]},"localhost-36981/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[151],"9":[151],"10":[151],"19":[151],"23":[151],"29":[151],"33":[151],"34":[151]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/removeNodeType.ts":{"10":[151]},"packages/cli/src/eventbus/event-message-classes/abstract-event-message.ts":{"10":[66,68],"12":[66,68],"16":[66,68],"28":[66,68],"48":[66,68],"59":[66,68],"72":[66,68],"101":[66,68],"107":[66,68],"115":[66,68],"120":[66,68],"131":[66,68],"142":[66,68],"146":[66,68]},"packages/cli/src/eventbus/event-message-classes/event-message-generic.ts":{"22":[66,67,68],"30":[66,67,68]},"packages/cli/src/modules/log-streaming.ee/create-message-event-bus-destination.ts":{"17":[66,67,68]},"packages/cli/src/modules/log-streaming.ee/destinations/destination-credentials-access.ts":{"14":[66,67,68]},"packages/cli/src/modules/log-streaming.ee/destinations/message-event-bus-destination-sentry.ee.ts":{"16":[68],"36":[68],"56":[68],"95":[68],"105":[68],"119":[68],"123":[68]},"packages/cli/src/modules/log-streaming.ee/destinations/message-event-bus-destination-webhook.ee.ts":{"31":[66,68],"81":[66,68],"116":[66,68],"125":[66,68],"130":[66,68],"142":[66,68],"170":[66,68],"171":[66,68],"190":[66,68],"208":[66,68],"267":[66,68],"301":[66,68],"317":[66,68]},"packages/cli/src/modules/log-streaming.ee/destinations/message-event-bus-destination.ee.ts":{"49":[66,67,68],"84":[66,67,68],"88":[66,67,68],"98":[66,67,68],"117":[66,67,68],"125":[66,67,68],"130":[66,67,68],"134":[66,67,68]},"packages/cli/src/modules/log-streaming.ee/log-streaming-destination.service.ts":{"38":[66,67,68],"51":[66,67,68],"75":[66,67,68],"90":[66,67,68],"97":[66,67,68],"122":[66,67,68],"142":[66,67,68],"161":[66,67,68],"188":[66,67,68],"193":[66,67,68],"194":[66,67,68],"201":[66,67,68],"209":[66,67,68],"220":[66,67,68],"221":[66,67,68],"229":[66,67,68],"238":[66,67,68],"263":[66,67,68]},"packages/cli/src/modules/log-streaming.ee/log-streaming.controller.ts":{"24":[66,67,153,68],"32":[66,67,153,68],"41":[66,67,153,68],"48":[66,67,153,68],"59":[66,67,153,68],"82":[66,67,153,68],"103":[66,67,153,68]},"packages/cli/src/utils/circuit-breaker.ts":{"15":[66,67,68],"147":[66,67,68],"172":[66,67,68],"176":[66,67,68],"180":[66,67,68],"184":[66,67,68],"191":[66,67,68],"197":[66,67,68],"206":[66,67,68],"234":[66,67,68],"269":[66,67,68],"270":[66,67,68]},"packages/cli/src/utils/sliding-window.ts":{"31":[66,67,68],"42":[66,67,68],"57":[66,67,68],"60":[66,67,68],"67":[66,67,68]},"localhost-42501/assets/index-Dv_brJ4-.js":{"3":[68,75,84,179,87,191]},"localhost-42501/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[68,75,84,179,87,191],"9":[68,75,84,179,87,191],"10":[68,75,84,179,87,191],"19":[68,75,84,179,87,191],"23":[68,75,84,179,87,191],"29":[68,75,84,179,87,191],"33":[68,75,84,179,87,191],"34":[68,75,84,179,87,191]},"packages/frontend/@n8n/rest-api-client/src/api/eventbus.ee.ts":{"10":[46,66,153,68],"16":[46,66,153],"28":[46,68],"32":[46,66,153,68],"42":[46,66,153,68],"46":[46,66,153,68]},"packages/frontend/editor-ui/src/features/integrations/logStreaming.ee/components/EventDestinationCard.vue":{"44":[66,153,68],"52":[66,153,68],"56":[66,153,68],"72":[66,153,68],"76":[153],"87":[66,68],"100":[66],"106":[66],"110":[68],"135":[66,153,68],"141":[66,153,68],"144":[66,153,68],"148":[66,153,68],"153":[66,153,68],"157":[66,153,68],"160":[66,153,68],"176":[66]},"packages/frontend/editor-ui/src/features/integrations/logStreaming.ee/components/EventDestinationSettingsModal.vue":{"78":[66,153,68],"89":[66,153,68],"109":[153,68],"123":[66,153,68],"127":[66,153,68],"131":[153,68],"135":[153,68],"139":[66,153,68],"141":[66,153,68],"145":[66,153,68],"163":[66,153,68],"167":[153],"187":[66,153,68],"191":[66,153,68],"206":[66,153,68],"210":[153],"219":[153],"225":[66,153,68],"233":[153,68],"237":[153],"263":[153],"302":[66,153,68],"307":[68],"331":[68],"343":[153],"372":[153,68],"380":[66,153,68],"396":[66,153,68],"413":[66,153,68],"455":[66,153,68],"465":[153,68],"473":[153,68],"475":[153,68],"487":[153,68],"496":[66,153,68]},"packages/frontend/editor-ui/src/features/integrations/logStreaming.ee/components/LogStreamingPaywall.vue":{"27":[68]},"packages/frontend/editor-ui/src/features/integrations/logStreaming.ee/logStreaming.store.ts":{"44":[66,153,68],"53":[66,153,68],"81":[66,153,68],"99":[66,153,68],"105":[66,153,68],"128":[66,153,68],"136":[66,153,68],"151":[66,153,68],"155":[66,153,68],"163":[66,153,68],"220":[66,153],"226":[68],"231":[66,153],"248":[66,153],"265":[66,153,68],"276":[66,153,68],"280":[66,153,68],"284":[68]},"packages/frontend/editor-ui/src/features/integrations/logStreaming.ee/logStreaming.utils.ts":{"13":[66,153,68],"33":[153]},"packages/frontend/editor-ui/src/features/integrations/logStreaming.ee/modals.ts":{"8":[46,66,153,68]},"packages/frontend/editor-ui/src/features/integrations/logStreaming.ee/views/SettingsLogStreamingView.vue":{"36":[66,153,68],"44":[66,153,68],"49":[66,153,68],"53":[66,153,68],"57":[66,153,68],"59":[66,153,68],"72":[66,153,68],"74":[68],"87":[66,153,68],"93":[153],"97":[66,153,68],"102":[68],"107":[66,153,68],"128":[66,153,68],"132":[153,68],"147":[68],"156":[66,68],"177":[66,153,68],"199":[66,153,68],"203":[66,153,68],"209":[68],"210":[66,68],"225":[66,153,68]},"packages/@n8n/db/src/repositories/test-run.repository.ee.ts":{"18":[75],"22":[75],"45":[75],"53":[75],"57":[75],"62":[75],"71":[75],"82":[75],"89":[75],"97":[75],"105":[75],"117":[75],"140":[75],"153":[75],"165":[75],"173":[75],"185":[75],"200":[75],"210":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/OpenAi.node.ts":{"12":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/helpers/binary-data.ts":{"11":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/helpers/description.ts":{"3":[75],"20":[75],"38":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/helpers/polling.ts":{"4":[75],"34":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/helpers/utils.ts":{"17":[75],"27":[75],"39":[75],"50":[75],"58":[75],"66":[75],"88":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/methods/listSearch.ts":{"16":[75],"39":[75],"48":[75],"49":[75],"52":[75],"66":[75],"72":[75],"78":[75],"85":[75],"91":[75],"95":[75],"98":[75],"102":[75],"127":[75],"132":[75],"136":[75],"179":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/methods/loadOptions.ts":{"5":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/transport/index.ts":{"15":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/OpenAiV1.node.ts":{"22":[75],"82":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/assistant/create.operation.ts":{"176":[75],"185":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/assistant/deleteAssistant.operation.ts":{"18":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/assistant/list.operation.ts":{"25":[75],"62":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/assistant/message.operation.ts":{"158":[75],"165":[75],"224":[75],"231":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/assistant/update.operation.ts":{"120":[75],"126":[75],"132":[75],"207":[75],"213":[75],"214":[75],"217":[75],"223":[75],"224":[75],"228":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/audio/generate.operation.ts":{"134":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/audio/transcribe.operation.ts":{"58":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/audio/translate.operation.ts":{"50":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/descriptions.ts":{"5":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/file/deleteFile.operation.ts":{"51":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/file/list.operation.ts":{"53":[75],"63":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/file/upload.operation.ts":{"57":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/image/analyze.operation.ts":{"131":[75],"158":[75],"172":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/image/generate.operation.ts":{"255":[75],"291":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/router.ts":{"16":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/text/classify.operation.ts":{"53":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/text/message.operation.ts":{"240":[75],"244":[75],"360":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/OpenAiV2.node.ts":{"23":[75],"92":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/audio/generate.operation.ts":{"134":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/audio/transcribe.operation.ts":{"58":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/audio/translate.operation.ts":{"50":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/conversation/create.operation.ts":{"84":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/conversation/get.operation.ts":{"27":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/conversation/remove.operation.ts":{"27":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/conversation/update.operation.ts":{"36":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/descriptions.ts":{"5":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/file/deleteFile.operation.ts":{"51":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/file/list.operation.ts":{"62":[75],"72":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/file/upload.operation.ts":{"65":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/image/analyze.operation.ts":{"133":[75],"157":[75],"169":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/image/edit.operation.ts":{"584":[75],"618":[75],"695":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/image/generate.operation.ts":{"73":[75],"118":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/router.ts":{"17":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/text/classify.operation.ts":{"58":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/text/helpers/responses.ts":{"16":[75],"18":[75],"21":[75],"24":[75],"27":[75],"33":[75],"108":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/text/response.operation.ts":{"583":[75],"587":[75],"629":[75],"632":[75],"652":[75],"659":[75],"717":[75],"719":[75],"736":[75]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/video/generate.operation.ts":{"92":[75],"132":[75],"135":[75]},"packages/cli/src/evaluation.ee/test-runs.controller.ee.ts":{"24":[75],"33":[75],"56":[75],"80":[75],"86":[75],"87":[75],"98":[75],"111":[75],"124":[75],"139":[75],"148":[75],"162":[75],"181":[75],"203":[75]},"localhost-42501/assets/verified-Dido3Ow4.js":{"8":[75]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/composables/useWorkflowEvaluationState.ts":{"25":[75],"26":[75],"51":[75]},"localhost-35719/assets/index-Dv_brJ4-.js":{"3":[83]},"localhost-35719/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[83],"9":[83],"10":[83],"19":[83],"23":[83],"29":[83],"33":[83],"34":[83]},"packages/@n8n/expression-runtime/src/bridge/quickjs-bridge.ts":{"41":[46,83],"43":[46,83],"67":[46,83],"76":[46,83],"84":[46,83],"97":[46,83],"107":[46,83],"115":[46,83],"132":[46],"137":[46],"154":[46,83],"196":[46],"203":[46],"205":[46],"233":[46,83],"244":[46],"277":[46],"305":[46,83],"328":[46,83],"343":[46],"363":[46,83],"365":[46],"367":[46,83],"368":[46,83],"369":[46,83],"373":[46,83],"375":[46],"377":[46,83],"378":[46],"379":[46],"383":[46],"385":[46],"387":[46],"392":[46],"397":[46],"401":[46],"403":[46],"405":[46],"406":[46],"407":[46],"411":[46],"413":[46],"415":[46],"416":[46],"420":[46],"422":[46],"424":[46],"425":[46],"429":[46],"431":[46],"433":[46],"434":[46],"438":[46],"441":[46],"483":[46,83],"491":[46,83],"517":[46],"535":[46,83],"545":[46,83],"574":[46,83],"602":[46,83],"607":[46,83],"608":[46,83],"804":[46,83],"848":[46,83],"1021":[46,83],"1045":[46,83],"1083":[46,83],"1090":[46,83],"1100":[46],"1111":[46],"1130":[46,83],"1175":[46,83],"1311":[46],"1320":[46,83],"1334":[46],"1357":[46,83]},"packages/nodes-base/nodes/N8nTrainingCustomerDatastore/N8nTrainingCustomerDatastore.node.ts":{"119":[84]},"packages/frontend/editor-ui/src/features/core/dataTable/components/dataGrid/ElDatePickerCellEditor.vue":{"7":[47],"24":[47],"30":[47],"36":[47],"43":[47],"45":[47]},"packages/frontend/editor-ui/src/features/core/dataTable/components/dataGrid/NullEmptyCellRenderer.vue":{"2":[47]},"packages/frontend/editor-ui/src/features/core/dataTable/composables/useDatePickerCommon.ts":{"11":[47],"17":[47],"22":[47],"35":[47],"60":[47],"67":[47],"84":[47]},"packages/frontend/editor-ui/src/features/core/dataTable/utils/typeUtils.ts":{"13":[47],"49":[47]},"packages/frontend/editor-ui/src/features/core/dataTable/utils.ts":{"1":[46,47],"6":[46,47]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ResourceMapper/MappingFields.vue":{"49":[46,179],"74":[46,179],"83":[46,179],"85":[46,179],"86":[46,179],"101":[46,179],"104":[46,179],"117":[46,179],"118":[46,179],"121":[46,179],"122":[46,179],"131":[46,179],"132":[46,179],"134":[46,179],"161":[46,179],"164":[46,179],"178":[46,179],"182":[46,179],"186":[46,179],"196":[46,179],"204":[46,179],"214":[46,179],"238":[46,179],"252":[46,179],"267":[46,179],"280":[46,179],"284":[46,179],"288":[46,179],"292":[46],"296":[46,179],"315":[46,179],"328":[46,179],"331":[46],"334":[46],"346":[46],"362":[46],"366":[46,179],"397":[46,179],"433":[46],"442":[46,179]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ResourceMapper/MatchingColumnsSelect.vue":{"27":[46,179],"39":[46,179],"50":[46,179],"51":[46,179],"62":[46,179],"63":[46,179],"69":[46,179],"84":[46,179],"103":[46,179],"117":[46,179],"130":[46,179],"138":[46],"147":[46],"156":[46,179],"169":[46,179],"182":[46,179],"191":[46,179],"200":[46,179],"202":[46,179],"206":[46,179],"211":[46,179]},"packages/cli/src/services/workflow-loader.service.ts":{"7":[60,182,87],"9":[60,182,87]},"packages/core/src/execution-engine/node-execution-context/local-load-options-context.ts":{"16":[60,182,87],"23":[60,182,87],"42":[60,182,87],"69":[60,182,87]},"packages/core/src/execution-engine/node-execution-context/workflow-node-context.ts":{"16":[60,182,87],"22":[60,182,87]},"packages/workflow/src/node-parameters/path-utils.ts":{"10":[60,182,87]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/WorkflowSelectorParameterInput/WorkflowSelectorParameterInput.vue":{"60":[46,182,87],"111":[46,182,87],"122":[46,182,87],"132":[46,182,87],"146":[46,182,87],"154":[46,182,87],"162":[46,182,87],"170":[46,182,87],"177":[46,182,87],"195":[46,87],"205":[46,87],"210":[46,87],"214":[46],"218":[46,87],"221":[46],"227":[46],"231":[46,182,87],"252":[46,182,87],"259":[46,182,87],"263":[46,182,87],"264":[46,87],"273":[46,182,87],"274":[46,182,87],"286":[46,182,87],"293":[46,87],"298":[46,87],"331":[46,182,87],"358":[46],"363":[46],"366":[46],"370":[46,87],"375":[46],"378":[46,182,87],"396":[46,182,87],"398":[46,182,87],"404":[46,182,87],"421":[46,182,87],"438":[46],"457":[46,182,87],"480":[46],"481":[46,182,87]},"packages/frontend/editor-ui/src/features/ndv/parameters/composables/useResourceLocatorDropdown.ts":{"8":[46,182,87],"15":[46,87],"23":[46,87],"27":[46,87]},"packages/frontend/editor-ui/src/features/ndv/parameters/composables/useResourceLocatorModes.ts":{"15":[46,182,87],"21":[46,182,87],"34":[46,182,87],"35":[46,182,87],"37":[46,87],"51":[46,182,87]},"packages/frontend/editor-ui/src/features/ndv/parameters/composables/useWorkflowResourcesLocator.ts":{"13":[46,182,87],"17":[46,87],"29":[46,182,87],"31":[46,182,87],"40":[46,182,87],"48":[46,87],"56":[46,182,87],"61":[46,182,87],"71":[46,182,87],"107":[46,182,87],"113":[46,87],"118":[46,87]},"packages/core/src/execution-engine/node-execution-context/hook-context.ts":{"21":[191],"34":[191],"38":[191],"42":[191],"54":[191],"61":[191]},"packages/nodes-base/nodes/Hubspot/HubspotTrigger.node.ts":{"17":[191],"320":[191],"323":[191],"326":[191],"329":[191],"337":[191],"384":[191],"418":[191],"447":[191]},"packages/nodes-base/nodes/Hubspot/V1/GenericFunctions.ts":{"15":[191],"78":[191],"123":[191],"144":[191],"155":[191],"1953":[191],"1955":[191],"1960":[191],"1963":[191],"1978":[191],"1987":[191],"1997":[191],"2008":[191],"2024":[191]},"packages/frontend/@n8n/design-system/src/utils/markdown.ts":{"20":[46],"43":[46,191],"44":[46]},"packages/frontend/editor-ui/src/app/components/CollectionWorkflowCard.vue":{"12":[191],"13":[191],"17":[191]},"packages/frontend/editor-ui/src/app/views/WorkflowOnboardingView.vue":{"17":[191],"55":[191]},"packages/frontend/editor-ui/src/features/workflows/templates/components/TemplateFilters.vue":{"15":[191],"34":[191],"38":[191],"43":[191],"44":[191],"52":[191],"60":[191],"68":[191],"69":[191],"80":[191],"81":[191],"91":[191],"108":[191],"118":[191]},"packages/frontend/editor-ui/src/features/workflows/templates/components/TemplatesInfoCard.vue":{"21":[191],"29":[191]},"packages/frontend/editor-ui/src/features/workflows/templates/components/TemplatesInfoCarousel.vue":{"11":[191],"37":[191],"64":[191],"65":[191],"67":[191],"73":[191],"74":[191],"76":[191],"82":[191],"95":[191],"101":[191],"112":[191],"113":[191],"115":[191]},"packages/frontend/editor-ui/src/features/workflows/templates/recommendations/components/RecommendedTemplateCard.vue":{"17":[191],"35":[191],"38":[191],"43":[191],"46":[191],"71":[191],"82":[191],"101":[191],"109":[191],"121":[191],"127":[191],"137":[191],"148":[191],"177":[191],"187":[191]},"packages/frontend/editor-ui/src/features/workflows/templates/recommendations/recommendedTemplates.store.ts":{"5":[191]},"packages/frontend/editor-ui/src/features/workflows/templates/views/TemplatesSearchView.vue":{"51":[191],"54":[191],"61":[191],"65":[191],"69":[191],"73":[191],"87":[191],"105":[191],"106":[191],"110":[191],"115":[191],"125":[191],"129":[191],"137":[191],"149":[191],"156":[191],"166":[191],"173":[191],"178":[191],"192":[191],"196":[191],"220":[191],"258":[191],"277":[191],"285":[191],"297":[191],"310":[191],"319":[191],"330":[191],"379":[191],"386":[191],"410":[191]},"packages/frontend/editor-ui/src/features/workflows/templates/views/TemplatesWorkflowView.vue":{"43":[191],"47":[191],"49":[191],"81":[191],"91":[191],"92":[191],"103":[191],"125":[191],"149":[191],"156":[191],"169":[191],"195":[191],"201":[191]},"localhost-34489/assets/index-Dv_brJ4-.js":{"3":[59]},"localhost-34489/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[59],"9":[59],"10":[59],"19":[59],"23":[59],"29":[59],"33":[59],"34":[59]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectMoveResourceModal.vue":{"42":[46,59],"68":[46,59],"69":[46],"72":[46],"75":[46,59],"76":[46],"92":[46,59],"96":[46,59],"97":[46,59],"101":[46,59],"107":[46,59],"111":[46,59],"116":[46,59],"119":[46,59],"120":[46],"125":[46],"129":[46,59],"132":[46,59],"137":[46,59],"141":[46,59],"151":[46],"190":[46,59],"206":[46,59],"209":[46,59],"211":[46,59],"219":[46,59],"223":[46],"224":[46],"230":[46,59],"231":[46,59],"239":[46,59],"257":[46,59],"262":[46,59],"283":[46],"285":[46],"298":[46],"313":[46],"322":[46],"333":[46],"349":[46],"354":[46,59],"357":[46,59],"365":[46,59]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectMoveSuccessToastMessage.vue":{"9":[46,59],"19":[46,59],"20":[46,59],"21":[46],"24":[46,59],"28":[46]},"packages/cli/src/controllers/change-email.controller.ts":{"30":[100],"49":[100],"118":[100],"134":[100],"165":[100],"173":[100]},"packages/cli/src/controllers/mfa.controller.ts":{"21":[100],"32":[100],"67":[100],"75":[100],"118":[100],"159":[100],"203":[100]},"packages/cli/src/mfa/mfa.service.ts":{"17":[100],"27":[100],"35":[100],"36":[100],"39":[100],"45":[100],"60":[100],"68":[100],"80":[100],"83":[100],"91":[100],"95":[100],"100":[100],"107":[100],"120":[100],"127":[100],"136":[100],"145":[100],"155":[100],"165":[100]},"packages/cli/src/mfa/totp.service.ts":{"6":[100],"10":[100],"26":[100],"38":[100]},"packages/cli/src/services/email-change.service.ts":{"20":[100],"29":[100],"43":[100],"74":[100],"112":[100]},"localhost-33843/assets/index-Dv_brJ4-.js":{"3":[100]},"localhost-33843/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[100],"9":[100],"10":[100],"19":[100],"23":[100],"29":[100],"33":[100],"34":[100]},"packages/frontend/@n8n/rest-api-client/src/api/mfa.ts":{"4":[46],"8":[46],"14":[46],"21":[46],"33":[46,100],"37":[46]},"packages/frontend/editor-ui/src/features/core/auth/components/PromptMfaCodeModal.vue":{"42":[100],"43":[100],"46":[100],"53":[100],"82":[100],"92":[100],"99":[100],"110":[100],"123":[100],"157":[100],"170":[100],"192":[100],"201":[100]},"packages/frontend/editor-ui/src/features/core/auth/modals.ts":{"14":[46],"19":[46],"24":[46],"29":[46,100]},"packages/frontend/editor-ui/src/features/core/auth/views/MfaView.vue":{"63":[100],"86":[100],"107":[100],"116":[100],"117":[100],"129":[100],"155":[100],"164":[100],"189":[100],"194":[100],"204":[100],"225":[100]},"localhost-43711/assets/index-Dv_brJ4-.js":{"3":[77,162]},"localhost-43711/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[77,162],"9":[77,162],"10":[77,162],"19":[77,162],"23":[77,162],"29":[77,162],"33":[77,162],"34":[77,162]},"localhost-43711/assets/verified-Dido3Ow4.js":{"8":[77,162]},"packages/nodes-base/nodes/N8n/GenericFunctions.ts":{"21":[162],"56":[162],"93":[162],"94":[162],"107":[162],"111":[162],"146":[162],"150":[162],"186":[162],"210":[162]},"packages/nodes-base/nodes/N8n/WorkflowLocator.ts":{"18":[162],"32":[162],"37":[162],"42":[162]},"packages/@n8n/nodes-langchain/nodes/chains/ChainLLM/ChainLlm.node.ts":{"27":[2,15],"71":[2,15],"91":[2,15],"97":[2,15],"128":[2,15],"146":[2,15]},"packages/@n8n/nodes-langchain/nodes/chains/ChainLLM/methods/chainExecutor.ts":{"20":[2,15],"35":[2,15],"46":[2,15],"61":[2,15],"70":[2,15],"96":[2,15],"119":[2,15],"127":[2,15],"141":[2,15]},"packages/@n8n/nodes-langchain/nodes/chains/ChainLLM/methods/config.ts":{"21":[2,15]},"packages/@n8n/nodes-langchain/nodes/chains/ChainLLM/methods/imageUtils.ts":{"15":[2,15],"27":[2,15],"82":[2,15]},"packages/@n8n/nodes-langchain/nodes/chains/ChainLLM/methods/index.ts":{"1":[2,15]},"packages/@n8n/nodes-langchain/nodes/chains/ChainLLM/methods/processItem.ts":{"11":[2,15],"33":[2,15]},"packages/@n8n/nodes-langchain/nodes/chains/ChainLLM/methods/promptUtils.ts":{"23":[2,15],"34":[2,15],"44":[2,15],"50":[2,15],"66":[2,15],"75":[2,15],"120":[2,15],"149":[2,15],"153":[2,15],"158":[2,15],"159":[2,15],"168":[2,15]},"packages/@n8n/nodes-langchain/nodes/chains/ChainLLM/methods/responseFormatter.ts":{"6":[2,15]},"packages/@n8n/nodes-langchain/utils/output_parsers/parserInput.ts":{"10":[2,15]},"localhost-34467/assets/index-Dv_brJ4-.js":{"3":[2,110,134,66]},"localhost-34467/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[2,110,134,66],"9":[2,110,134,66],"10":[2,110,134,66],"19":[2,110,134,66],"23":[2,110,134,66],"29":[2,110,134,66],"33":[2,110,134,66],"34":[2,110,134,66]},"localhost-34467/assets/verified-Dido3Ow4.js":{"8":[2]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/chat-memory-manager.svg":{"11":[2]},"localhost-37017/assets/index-Dv_brJ4-.js":{"3":[94,126,127,131,158,172,186]},"localhost-37017/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[94,126,127,131,158,172,186],"9":[94,126,127,131,158,172,186],"10":[94,126,127,131,158,172,186],"19":[94,126,127,131,158,172,186],"23":[94,126,127,131,158,172,186],"29":[94,126,127,131,158,172,186],"33":[94,126,127,131,158,172,186],"34":[94,126,127,131,158,172,186]},"localhost-37017/assets/verified-Dido3Ow4.js":{"8":[94,126,131]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/completer.ts":{"23":[94,46],"27":[94,46],"29":[46],"67":[46],"111":[46],"227":[46],"228":[46],"236":[46],"237":[46],"254":[46],"255":[46],"267":[46],"273":[46],"274":[46],"286":[46],"287":[46],"289":[46]},"localhost-33729/assets/index-Dv_brJ4-.js":{"3":[95]},"localhost-33729/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[95],"9":[95],"10":[95],"19":[95],"23":[95],"29":[95],"33":[95],"34":[95]},"packages/frontend/@n8n/rest-api-client/src/api/cloudPlans.ts":{"90":[95,46],"94":[95,46],"98":[95,46],"102":[46],"108":[46],"112":[46],"121":[46]},"packages/frontend/editor-ui/src/features/settings/apiKeys/apiKeys.store.ts":{"18":[95,46],"24":[95,46],"40":[46],"43":[46],"46":[46],"50":[46],"51":[46],"60":[46],"65":[46],"87":[46],"97":[46],"107":[46],"114":[46],"122":[46],"126":[46],"135":[46],"144":[46],"150":[46],"157":[46]},"packages/frontend/editor-ui/src/features/settings/apiKeys/components/ApiKeyScopesModal.vue":{"7":[95],"18":[95],"27":[95]},"packages/frontend/editor-ui/src/features/settings/apiKeys/components/RevokeApiKeyConfirmModal.vue":{"9":[95,46],"25":[95,46],"33":[95,46],"44":[95,46],"57":[46],"58":[46],"59":[46]},"packages/frontend/editor-ui/src/features/settings/apiKeys/components/RotateApiKeyConfirmModal.vue":{"7":[95],"21":[95],"28":[95]},"packages/frontend/editor-ui/src/features/settings/apiKeys/views/SettingsApiView.vue":{"136":[95],"206":[95],"306":[95],"308":[95],"309":[95],"318":[95],"327":[95]},"packages/frontend/editor-ui/src/features/shared/banners/components/banners/BaseBanner.vue":{"19":[95,46],"36":[95,46],"40":[46],"46":[95,46],"62":[95,46]},"packages/frontend/editor-ui/src/features/shared/banners/components/banners/TrialBanner.vue":{"77":[95,46],"92":[95,46],"93":[95,46],"100":[95,46],"107":[95,46],"108":[95,46],"109":[95,46],"117":[95,46],"120":[95,46],"126":[95,46],"131":[95,46],"133":[95,46],"147":[95,46],"157":[95,46],"162":[95,46],"170":[95,46],"175":[95,46],"182":[46],"193":[95,46],"207":[95,46],"223":[95,46],"227":[95,46],"233":[95,46],"241":[95,46]},"packages/@n8n/api-types/src/agents/agent-skill.schema.ts":{"16":[46],"23":[46],"39":[46]},"packages/@n8n/api-types/src/agents/child-trace.ts":{"4":[46],"10":[46],"23":[46],"32":[46],"37":[46],"47":[46],"60":[46]},"packages/@n8n/api-types/src/agents/inline-agent-config.schema.ts":{"34":[46],"58":[46],"59":[46],"79":[46],"130":[46]},"packages/@n8n/api-types/src/agents/provider-capabilities.ts":{"186":[46],"210":[46],"218":[46],"246":[46]},"packages/@n8n/api-types/src/agents/rich-card.schema.ts":{"74":[46],"137":[46]},"packages/@n8n/api-types/src/agents/slack/manager-credential.ts":{"4":[46]},"packages/@n8n/api-types/src/dto/ai/ai-ask-request.dto.ts":{"15":[46],"30":[46]},"packages/@n8n/api-types/src/dto/data-table/download-data-table-csv-query.dto.ts":{"8":[46]},"packages/@n8n/api-types/src/dto/data-table/upsert-data-table-row.dto.ts":{"10":[46],"18":[46]},"packages/@n8n/api-types/src/dto/evaluations/evaluation-config.dto.ts":{"37":[46]},"packages/@n8n/api-types/src/dto/insights/insights-summary-public.dto.ts":{"28":[46]},"packages/@n8n/api-types/src/dto/promotions/promotable-resource.dto.ts":{"82":[46]},"packages/@n8n/api-types/src/dto/promotions/promotion-binding-preflight.dto.ts":{"45":[46],"49":[46]},"packages/@n8n/api-types/src/dto/type-availability-policies/replace-attachments.dto.ts":{"21":[46],"23":[46],"28":[46],"30":[46]},"packages/@n8n/api-types/src/dto/workflow-reviews/workflow-review-activity.dto.ts":{"33":[46,74]},"packages/@n8n/api-types/src/schemas/ai-preference.schema.ts":{"39":[46],"48":[46]},"packages/@n8n/api-types/src/schemas/data-table.schema.ts":{"63":[46]},"packages/@n8n/api-types/src/schemas/insights.schema.ts":{"75":[46],"93":[46]},"packages/@n8n/api-types/src/schemas/instance-ai-setup-credential-selection.ts":{"16":[46],"21":[46],"25":[46],"44":[46]},"packages/@n8n/api-types/src/schemas/llm-step-display.ts":{"101":[46],"105":[46],"113":[46],"121":[46],"128":[46],"166":[46],"176":[46],"235":[46],"250":[46],"267":[46],"269":[46],"283":[46],"287":[46],"300":[46],"320":[46],"335":[46],"350":[46],"382":[46],"400":[46],"410":[46],"419":[46],"437":[46],"443":[46],"491":[46],"495":[46],"516":[46],"525":[46],"534":[46],"549":[46],"579":[46],"594":[46],"624":[46],"677":[46],"687":[46],"689":[46],"698":[46],"700":[46],"707":[46],"712":[46],"716":[46],"728":[46],"737":[46],"745":[46],"750":[46],"763":[46],"767":[46],"777":[46],"793":[46],"825":[46],"829":[46],"862":[46],"865":[46],"895":[46],"897":[46],"907":[46],"925":[46],"948":[46],"987":[46],"1024":[46],"1058":[46],"1068":[46],"1098":[46],"1107":[46],"1114":[46],"1123":[46],"1127":[46],"1132":[46],"1156":[46],"1157":[46]},"packages/@n8n/api-types/src/schemas/mcp.schema.ts":{"66":[46],"67":[46],"70":[46],"71":[46]},"packages/@n8n/api-types/src/schemas/project.schema.ts":{"25":[46],"29":[46],"31":[46]},"packages/@n8n/api-types/src/schemas/source-controlled-file.schema.ts":{"33":[46]},"packages/@n8n/api-types/src/schemas/thread-title-search.schema.ts":{"12":[46]},"packages/@n8n/api-types/src/workflow-publish-blocked-details.ts":{"19":[46]},"packages/@n8n/errors/src/application.error.ts":{"21":[46]},"packages/@n8n/expression-runtime/src/extensions/array-extensions.ts":{"14":[46],"19":[46],"25":[46],"29":[46],"33":[46],"37":[46],"47":[46],"51":[46],"58":[46],"61":[46],"62":[46],"77":[46],"82":[46],"83":[46],"85":[46],"93":[46],"96":[46],"97":[46],"102":[46],"105":[46],"116":[46],"120":[46],"132":[46],"136":[46],"148":[46],"159":[46],"161":[46],"166":[46],"174":[46],"181":[46],"195":[46],"207":[46],"213":[46],"219":[46],"229":[46],"249":[46],"254":[46],"286":[46],"317":[46],"324":[46],"331":[46],"340":[46],"347":[46],"356":[46],"361":[46],"368":[46],"372":[46],"376":[46],"380":[46],"384":[46],"388":[46]},"packages/@n8n/expression-runtime/src/extensions/boolean-extensions.ts":{"3":[46],"7":[46],"11":[46]},"packages/@n8n/expression-runtime/src/extensions/date-extensions.ts":{"78":[46],"82":[46],"92":[46],"97":[46],"107":[46],"113":[46],"138":[46],"146":[46],"169":[46],"176":[46],"188":[46],"193":[46],"214":[46],"235":[46],"244":[46],"249":[46],"263":[46],"268":[46],"277":[46],"282":[46],"286":[46]},"packages/@n8n/expression-runtime/src/extensions/expression-extension-error.ts":{"4":[46]},"packages/@n8n/expression-runtime/src/extensions/extend.ts":{"13":[46],"17":[46],"36":[46],"79":[46],"138":[46],"146":[46],"154":[46],"174":[46],"190":[46]},"packages/@n8n/expression-runtime/src/extensions/number-extensions.ts":{"10":[46],"23":[46],"30":[46],"37":[46],"41":[46],"45":[46],"49":[46],"53":[46],"58":[46],"62":[46],"66":[46],"71":[46]},"packages/@n8n/expression-runtime/src/extensions/object-extensions.ts":{"5":[46],"9":[46],"13":[46],"17":[46],"21":[46],"26":[46],"37":[46],"52":[46],"69":[46],"89":[46],"92":[46],"95":[46],"97":[46],"101":[46],"105":[46],"109":[46],"113":[46],"117":[46]},"packages/@n8n/expression-runtime/src/extensions/string-extensions.ts":{"48":[46],"87":[46],"118":[46],"122":[46],"126":[46],"130":[46],"134":[46],"176":[46],"180":[46],"193":[46],"215":[46],"223":[46],"231":[46],"242":[46],"256":[46],"266":[46],"273":[46],"279":[46],"283":[46],"287":[46],"298":[46],"302":[46],"306":[46],"329":[46],"336":[46],"344":[46],"362":[46],"370":[46],"374":[46],"383":[46],"423":[46],"434":[46],"440":[46],"444":[46]},"packages/@n8n/expression-runtime/src/extensions/utils.ts":{"7":[46],"24":[46],"37":[46]},"packages/@n8n/expression-runtime/src/observability/noop-provider.ts":{"4":[46],"5":[46],"6":[46],"7":[46],"11":[46],"12":[46],"13":[46],"17":[46],"21":[46],"22":[46],"23":[46],"24":[46]},"packages/@n8n/expression-runtime/src/pool/idle-scaling-pool.ts":{"20":[46],"29":[46],"35":[46],"45":[46],"56":[46],"60":[46],"74":[46],"79":[46],"83":[46],"84":[46],"89":[46],"93":[46],"96":[46],"101":[46],"109":[46],"117":[46],"119":[46],"121":[46],"126":[46],"137":[46],"140":[46]},"packages/@n8n/expression-runtime/src/types/bridge.ts":{"111":[46],"112":[46],"113":[46],"114":[46]},"packages/@n8n/expression-runtime/src/types/evaluator.ts":{"357":[46]},"packages/@n8n/expression-runtime/src/types/runtime.ts":{"16":[46]},"packages/@n8n/utils/src/is-unknown-array.ts":{"3":[46]},"packages/frontend/@n8n/chat/src/components/Button.vue":{"6":[46],"19":[46],"22":[46],"27":[46]},"packages/frontend/@n8n/chat/src/components/MessageWithButtons.vue":{"18":[46],"21":[46],"34":[46],"42":[46],"50":[46],"56":[46],"57":[46]},"packages/frontend/@n8n/chat/src/utils/utils.ts":{"33":[46],"49":[46],"82":[46]},"packages/frontend/@n8n/design-system/src/components/AskAssistantAvatar/AssistantAvatar.vue":{"10":[46]},"packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/BlockMessage.vue":{"19":[46],"23":[46],"30":[46],"31":[46]},"packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/ErrorMessage.vue":{"18":[46],"19":[46],"23":[46],"34":[46],"35":[46]},"packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/MessageRating.vue":{"15":[31,46],"32":[46],"39":[46],"49":[46],"57":[46],"62":[31,46],"78":[46],"86":[46],"97":[46],"106":[46]},"packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/RestoreVersionConfirm.vue":{"13":[46],"29":[46],"49":[46],"58":[46],"62":[46],"64":[46],"83":[46]},"packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/ToolMessage.vue":{"21":[46],"24":[46],"31":[46],"36":[46],"47":[46],"57":[46],"61":[46],"66":[46],"69":[46],"87":[46]},"packages/frontend/@n8n/design-system/src/components/CanvasCollaborationPill/CanvasCollaborationPill.vue":{"13":[46],"25":[46],"29":[46],"35":[46],"37":[46],"42":[46],"44":[46],"48":[46]},"packages/frontend/@n8n/design-system/src/components/DateRangePicker/DateRangePicker.vue":{"27":[46],"42":[46],"45":[46],"49":[46],"50":[46],"56":[46],"57":[46],"65":[46],"66":[46],"70":[46],"75":[46],"78":[46],"81":[46],"82":[46],"85":[46],"92":[46],"95":[46],"97":[46],"101":[46],"117":[46]},"packages/frontend/@n8n/design-system/src/components/DateRangePicker/DateRangePickerField.vue":{"15":[46],"16":[46],"19":[46],"24":[46],"25":[46],"27":[46],"33":[46],"41":[46],"46":[46],"48":[46],"54":[46],"62":[46],"69":[46],"75":[46],"83":[46],"88":[46],"94":[46],"98":[46]},"packages/frontend/@n8n/design-system/src/components/N8nAiActivityStep/AiActivityStep.vue":{"36":[46],"40":[46],"43":[46],"52":[46],"54":[46],"56":[46],"58":[46],"67":[46],"81":[46],"88":[46],"90":[46],"92":[46]},"packages/frontend/@n8n/design-system/src/components/N8nAiActivityStepButton/AiActivityStepButton.vue":{"4":[46,116],"27":[46],"31":[46,116],"45":[46,116]},"packages/frontend/@n8n/design-system/src/components/N8nAiActivityStepGroup/AiActivityStepGroup.vue":{"37":[46],"38":[46],"44":[46],"46":[46],"52":[46],"54":[46],"64":[46]},"packages/frontend/@n8n/design-system/src/components/N8nAiActivityStepResultSection/AiActivityStepResultSection.vue":{"2":[46]},"packages/frontend/@n8n/design-system/src/components/N8nAlert/Alert.vue":{"16":[46],"23":[46],"37":[46],"53":[46],"64":[46],"70":[46]},"packages/frontend/@n8n/design-system/src/components/N8nCodeBlock/CodeBlock.vue":{"15":[46],"33":[46],"44":[46],"50":[46],"53":[46],"60":[46],"66":[46],"71":[46],"89":[46],"111":[46],"114":[46],"132":[46],"146":[46]},"packages/frontend/@n8n/design-system/src/components/N8nCollapsiblePanel/CollapsiblePanel.vue":{"31":[46],"44":[46],"45":[46],"47":[46],"55":[46],"58":[46],"64":[46],"77":[46]},"packages/frontend/@n8n/design-system/src/components/N8nColorPicker/ColorPicker.vue":{"21":[46,99],"34":[46,99],"45":[46],"49":[46],"53":[46],"57":[46],"59":[46,99]},"packages/frontend/@n8n/design-system/src/components/N8nContextMenu/ContextMenu.utils.ts":{"3":[46],"19":[46],"24":[46],"27":[46],"28":[46],"31":[46],"35":[46]},"packages/frontend/@n8n/design-system/src/components/N8nContextMenu/ContextMenu.vue":{"24":[46],"36":[46],"38":[46],"43":[46],"47":[46],"51":[46],"53":[46],"57":[46],"63":[46],"71":[46],"74":[46],"75":[46],"76":[46],"85":[46],"86":[46],"89":[46],"92":[46],"94":[46],"97":[46],"100":[46],"103":[46]},"packages/frontend/@n8n/design-system/src/components/N8nContextMenu/ContextMenuBody.vue":{"23":[46],"27":[46],"35":[46],"51":[46],"54":[46],"57":[46],"60":[46],"64":[46]},"packages/frontend/@n8n/design-system/src/components/N8nContextMenu/ContextMenuItem.vue":{"33":[46],"53":[46],"55":[46],"58":[46],"60":[46],"61":[46],"66":[46],"69":[46],"71":[46],"77":[46],"84":[46],"91":[46],"97":[46],"101":[46],"109":[46],"114":[46],"121":[46],"124":[46],"127":[46],"142":[46],"148":[46],"151":[46],"154":[46],"157":[46],"161":[46],"175":[46],"182":[46],"185":[46],"188":[46],"193":[46],"204":[46],"211":[46],"214":[46],"217":[46],"222":[46],"232":[46],"239":[46],"242":[46],"245":[46]},"packages/frontend/@n8n/design-system/src/components/N8nContextMenu/ContextMenuItemContent.vue":{"13":[46],"24":[46],"25":[46],"26":[46],"28":[46],"35":[46],"40":[46],"52":[46],"53":[46],"57":[46]},"packages/frontend/@n8n/design-system/src/components/N8nContextMenu/ContextMenuNodes.vue":{"18":[46],"27":[46],"29":[46],"33":[46],"37":[46],"38":[46],"41":[46],"46":[46],"52":[46],"55":[46],"58":[46],"61":[46],"64":[46],"68":[46],"78":[46],"82":[46],"83":[46],"84":[46],"86":[46],"87":[46],"90":[46],"93":[46],"103":[46],"105":[46],"108":[46],"111":[46],"114":[46],"118":[46],"125":[46],"126":[46],"129":[46],"132":[46],"136":[46]},"packages/frontend/@n8n/design-system/src/components/N8nCopyInput/CopyInput.vue":{"31":[46],"50":[46],"52":[46],"57":[46],"62":[46],"75":[46],"80":[46],"84":[46],"86":[46],"95":[46],"100":[46]},"packages/frontend/@n8n/design-system/src/components/N8nEmptyState/EmptyStateIconCards.vue":{"21":[46],"23":[46],"29":[46],"32":[46],"36":[46],"41":[46],"51":[46],"53":[46],"58":[46],"60":[46],"66":[46],"75":[46],"77":[46],"84":[46],"91":[46],"93":[46]},"packages/frontend/@n8n/design-system/src/components/N8nFloatingWindow/FloatingWindow.vue":{"14":[46],"59":[46],"68":[46],"79":[46],"94":[46],"99":[46],"111":[46],"124":[46],"133":[46],"151":[46],"208":[46],"218":[46],"236":[46],"244":[46],"262":[46],"266":[46],"270":[46],"274":[46],"278":[46],"282":[46],"286":[46],"290":[46],"298":[46],"306":[46]},"packages/frontend/@n8n/design-system/src/components/N8nHeaderAction/HeaderAction.vue":{"36":[46],"37":[46],"43":[46],"44":[46],"53":[46]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/anthropic.svg":{"13":[46]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/azure.svg":{"9":[46]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/binary.svg":{"8":[46]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/bot-fail.svg":{"12":[46]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/bot-idle.svg":{"12":[46]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/bot-pass.svg":{"12":[46]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/bot-waiting.svg":{"5":[46]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/bot-warning.svg":{"12":[46]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/continue.svg":{"9":[46]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/discord.svg":{"8":[46]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/entra.svg":{"9":[46]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/form.svg":{"9":[46]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/linear.svg":{"8":[46]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/lovable.svg":{"11":[46]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/resolver.svg":{"11":[46]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/retry.svg":{"8":[46]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/run-once.svg":{"9":[46]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/slack.svg":{"14":[46]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/star-filled.svg":{"16":[46]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/status-canceled.svg":{"8":[46]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/status-completed.svg":{"8":[46]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/status-error.svg":{"8":[46]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/status-new.svg":{"8":[46]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/status-unknown.svg":{"8":[46]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/teams.svg":{"9":[46]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/telegram.svg":{"8":[46]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/webhook.svg":{"8":[46,60]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/whatsapp.svg":{"8":[46]},"packages/frontend/@n8n/design-system/src/components/N8nIconPicker/IconColorPicker.vue":{"15":[46,60],"63":[46,60],"65":[46,60],"67":[46],"71":[46],"76":[46],"81":[46,60],"92":[46,60],"100":[46,60],"104":[46],"112":[46],"121":[46]},"packages/frontend/@n8n/design-system/src/components/N8nIconPicker/IconPicker.utils.ts":{"10":[46],"18":[46,60],"22":[46],"29":[46,60],"30":[46,60],"35":[46],"41":[46],"42":[46],"43":[46],"49":[46],"71":[46],"81":[46]},"packages/frontend/@n8n/design-system/src/components/N8nIconPicker/SkinTonePicker.vue":{"12":[46,60],"31":[46,60],"33":[46],"41":[46,60],"51":[46,60],"59":[46,60],"63":[46],"70":[46],"72":[46],"79":[46],"80":[46]},"packages/frontend/@n8n/design-system/src/components/N8nSectionHeader/SectionHeader.vue":{"21":[46,126],"28":[46,126]},"packages/frontend/@n8n/design-system/src/components/N8nSettingsRowButton/SettingsRowButton.vue":{"25":[46]},"packages/frontend/@n8n/design-system/src/components/N8nSettingsSaveBar/SettingsSaveBar.vue":{"42":[46],"68":[46],"86":[46],"91":[46],"98":[46],"108":[46],"117":[46],"121":[46],"136":[46],"147":[46],"155":[46]},"packages/frontend/@n8n/design-system/src/components/N8nSetupConnection/SetupConnection.vue":{"9":[46],"14":[46],"30":[46],"32":[46],"39":[46],"61":[46],"63":[46],"70":[46],"80":[46],"81":[46]},"packages/frontend/@n8n/design-system/src/components/N8nSetupPanel/SetupPanel.vue":{"10":[46],"18":[46],"21":[46],"28":[46],"33":[46],"35":[46],"41":[46],"45":[46],"51":[46],"52":[46],"56":[46],"57":[46],"65":[46],"73":[46],"75":[46],"92":[46],"99":[46],"129":[46],"136":[46],"137":[46],"146":[46],"155":[46],"165":[46],"166":[46],"206":[46],"215":[46],"225":[46],"226":[46]},"packages/frontend/@n8n/design-system/src/components/N8nStepper/Stepper.vue":{"30":[46],"31":[46],"42":[46],"44":[46]},"packages/frontend/@n8n/design-system/src/components/N8nUsersList/UsersList.vue":{"12":[46],"22":[46],"23":[46],"60":[46],"61":[46],"65":[46],"66":[46],"77":[46],"82":[46],"87":[46],"99":[46],"113":[46]},"packages/frontend/@n8n/design-system/src/locale/lang/en.ts":{"45":[46],"49":[46],"55":[46],"116":[46]},"packages/frontend/@n8n/design-system/src/utils/colorUtils.ts":{"16":[46],"23":[46],"37":[46],"40":[46],"51":[46],"62":[46],"74":[46],"84":[46]},"packages/frontend/@n8n/design-system/src/utils/valueByPath.ts":{"10":[46],"11":[46]},"packages/frontend/@n8n/design-system/src/v2/components/Loading/Loading.vue":{"7":[46],"16":[46],"18":[46],"19":[46],"20":[46],"21":[46],"22":[46],"27":[46],"29":[46],"38":[46],"42":[46],"52":[46],"65":[46]},"packages/frontend/@n8n/frontend-module-sdk/src/registries/commandRegistry.ts":{"6":[46],"10":[46],"12":[46],"15":[46]},"packages/frontend/@n8n/rest-api-client/src/api/ai-usage.ts":{"6":[46]},"packages/frontend/@n8n/rest-api-client/src/api/api-keys.ts":{"13":[46],"33":[46],"37":[46],"44":[46],"51":[46],"59":[46]},"packages/frontend/@n8n/rest-api-client/src/api/breaking-changes.ts":{"17":[46],"24":[46],"35":[46],"42":[46],"55":[46],"66":[46],"78":[46]},"packages/frontend/@n8n/rest-api-client/src/api/credentialResolvers.ts":{"10":[46],"18":[46],"24":[46],"31":[46],"38":[46],"51":[46],"58":[46]},"packages/frontend/@n8n/rest-api-client/src/api/dynamic-banners.ts":{"26":[46]},"packages/frontend/@n8n/rest-api-client/src/api/events.ts":{"4":[46]},"packages/frontend/@n8n/rest-api-client/src/api/instance-version-history.ts":{"4":[46]},"packages/frontend/@n8n/rest-api-client/src/api/ldap.ts":{"50":[46],"54":[46],"58":[46],"70":[46],"74":[46]},"packages/frontend/@n8n/rest-api-client/src/api/npsSurvey.ts":{"6":[46]},"packages/frontend/@n8n/rest-api-client/src/api/orchestration.ts":{"8":[46],"12":[46],"19":[46]},"packages/frontend/@n8n/rest-api-client/src/api/roleMappingRule.ts":{"41":[46],"65":[46],"72":[46],"80":[46],"87":[46]},"packages/frontend/@n8n/rest-api-client/src/api/sso.ts":{"16":[46],"21":[46],"25":[46],"31":[46],"45":[46],"52":[46],"56":[46],"63":[46],"82":[46]},"packages/frontend/@n8n/rest-api-client/src/api/third-party-licenses.ts":{"4":[46]},"packages/frontend/@n8n/rest-api-client/src/api/ui.ts":{"6":[46]},"packages/frontend/@n8n/rest-api-client/src/api/webhooks.ts":{"13":[46]},"packages/frontend/@n8n/stores/src/invitation.api.ts":{"26":[46],"33":[46]},"packages/frontend/@n8n/stores/src/onboarding.api.ts":{"7":[46]},"packages/frontend/editor-ui/src/app/components/AiUpdatedCodeMessage.vue":{"3":[46],"4":[46]},"packages/frontend/editor-ui/src/app/components/ChatEmbedModal.vue":{"53":[46],"55":[46],"72":[46],"80":[46],"83":[46],"87":[46],"88":[46],"97":[46],"106":[46],"117":[46],"132":[46],"138":[46],"140":[46],"151":[46],"167":[46],"182":[46],"187":[46],"192":[46]},"packages/frontend/editor-ui/src/app/components/NodeActionsList.vue":{"17":[46],"28":[46],"29":[46],"33":[46],"35":[46],"36":[46],"45":[46],"61":[46],"69":[46],"76":[46],"82":[46],"86":[46],"94":[46],"105":[46],"109":[46]},"packages/frontend/editor-ui/src/app/components/NodeExecutionErrorMessage.vue":{"4":[46],"5":[46]},"packages/frontend/editor-ui/src/app/components/TitledList.vue":{"9":[46],"12":[46]},"packages/frontend/editor-ui/src/app/components/WarningTooltip.vue":{"6":[46],"8":[46],"10":[46]},"packages/frontend/editor-ui/src/app/components/WhatsNewModal.vue":{"24":[46],"41":[46],"43":[46],"47":[46],"55":[46],"56":[46],"68":[46],"82":[46],"92":[46],"98":[46],"104":[46],"107":[46],"113":[46],"131":[46],"142":[46],"148":[46],"151":[46],"166":[46],"173":[46],"184":[46]},"packages/frontend/editor-ui/src/app/components/scopes/ScopesSelector.vue":{"31":[46],"80":[46],"81":[46],"92":[46],"96":[46],"98":[46],"100":[46],"102":[46],"106":[46],"110":[46],"112":[46],"114":[46],"117":[46],"128":[46],"135":[46],"141":[46],"152":[46],"173":[46],"179":[46],"195":[46],"199":[46],"212":[46],"229":[46],"233":[46],"237":[46],"238":[46],"241":[46],"242":[46],"245":[46],"254":[46],"257":[46],"264":[46],"265":[46],"271":[46],"278":[46],"281":[46],"284":[46],"298":[46],"299":[46],"313":[46],"322":[46],"328":[46],"338":[46],"346":[46],"358":[46],"372":[46],"389":[46],"413":[46],"414":[46],"415":[46],"421":[46],"425":[46]},"packages/frontend/editor-ui/src/app/components/scopes/scopes.utils.ts":{"22":[46],"30":[46],"34":[46],"37":[46],"53":[46],"72":[46],"79":[46],"80":[46]},"packages/frontend/editor-ui/src/app/composables/useToolParameters.ts":{"28":[46],"40":[46],"73":[46],"78":[46],"81":[46],"85":[46],"99":[46],"116":[46],"140":[46],"169":[46],"195":[46],"203":[46],"204":[46],"210":[46],"211":[46],"219":[46],"242":[46],"246":[46],"256":[46],"264":[46],"325":[46],"331":[46]},"packages/frontend/editor-ui/src/app/moduleInitializer/placeholderPage.ts":{"5":[46]},"packages/frontend/editor-ui/src/app/stores/webhooks.store.ts":{"16":[46],"21":[46],"24":[46]},"packages/frontend/editor-ui/src/app/utils/rbac/checks/isEnterpriseFeatureEnabled.ts":{"4":[46,169],"15":[46,169],"17":[46]},"packages/frontend/editor-ui/src/app/utils/rbac/middleware/defaultUser.ts":{"6":[46]},"packages/frontend/editor-ui/src/app/utils/rbac/middleware/enterprise.ts":{"6":[46,169]},"packages/frontend/editor-ui/src/app/utils/rbac/middleware/role.ts":{"6":[46]},"packages/frontend/editor-ui/src/app/utils/retryUtils.ts":{"18":[46]},"packages/frontend/editor-ui/src/app/utils/safeRegex.ts":{"25":[46],"33":[46],"37":[46],"41":[46],"42":[46],"46":[46],"52":[46],"58":[46],"69":[46],"75":[46],"81":[46],"93":[46],"94":[46],"99":[46],"113":[46]},"packages/frontend/editor-ui/src/experiments/exposeAllWorkflowsToMcp/modals.ts":{"7":[46]},"packages/frontend/editor-ui/src/experiments/exposeAllWorkflowsToMcp/stores/exposeAllWorkflowsToMcp.store.ts":{"10":[46,123],"15":[46],"18":[46,123],"25":[46],"28":[46],"32":[46],"36":[46]},"packages/frontend/editor-ui/src/experiments/mcpJsonNudge/modals.ts":{"7":[46]},"packages/frontend/editor-ui/src/experiments/personalizedTemplatesV3/components/NodeRecommendationModal.vue":{"13":[46],"23":[46],"27":[46],"35":[46],"42":[46],"47":[46],"51":[46],"58":[46],"69":[46],"72":[46],"76":[46],"85":[46],"88":[46],"91":[46],"94":[46]},"packages/frontend/editor-ui/src/experiments/personalizedTemplatesV3/components/TemplateCard.vue":{"12":[46],"21":[46],"24":[46],"34":[46],"45":[46],"57":[46],"84":[46],"88":[46],"93":[46],"95":[46],"98":[46],"102":[46]},"packages/frontend/editor-ui/src/experiments/surfaceAssistantOnWorkflowError/workflowErrorNudge.telemetry.ts":{"9":[46],"16":[46]},"packages/frontend/editor-ui/src/experiments/surfaceAssistantOnWorkflowError/workflowErrorNudgeOutline.ts":{"21":[46],"26":[46],"38":[46],"57":[46]},"packages/frontend/editor-ui/src/experiments/surfaceAssistantOnWorkflowError/workflowErrorNudgePosition.ts":{"5":[46],"7":[46],"8":[46]},"packages/frontend/editor-ui/src/experiments/surfaceMcpToNewCloudUsers/modals.ts":{"7":[46]},"packages/frontend/editor-ui/src/experiments/templateRecoV2/components/NodeRecommendationModal.vue":{"16":[46],"35":[46],"45":[46],"46":[46],"55":[46],"57":[46],"60":[46],"64":[46],"68":[46],"76":[46],"83":[46],"87":[46],"90":[46],"98":[46],"99":[46],"107":[46],"111":[46],"114":[46],"118":[46],"125":[46],"135":[46],"142":[46],"155":[46],"160":[46],"161":[46],"168":[46],"172":[46],"181":[46],"183":[46],"184":[46],"191":[46],"195":[46],"203":[46],"207":[46]},"packages/frontend/editor-ui/src/experiments/templateRecoV2/components/TemplateCard.vue":{"13":[46],"25":[46],"28":[46],"32":[46],"39":[46],"44":[46],"48":[46],"52":[46],"57":[46],"59":[46],"64":[46]},"packages/frontend/editor-ui/src/experiments/templateRecoV2/components/YoutubeCard.vue":{"5":[46],"13":[46],"16":[46],"21":[46],"28":[46],"29":[46]},"packages/frontend/editor-ui/src/features/agents/components/AgentChipButton.vue":{"7":[46],"38":[46],"46":[46],"68":[46],"81":[46],"94":[46],"95":[46]},"packages/frontend/editor-ui/src/features/agents/components/AgentCredentialSelect.vue":{"18":[46],"42":[46],"44":[46],"48":[46],"56":[46],"58":[46],"73":[46]},"packages/frontend/editor-ui/src/features/agents/components/AgentItemContextMenu.vue":{"9":[46],"18":[46],"50":[46],"57":[46],"62":[46],"66":[46],"67":[46],"69":[46]},"packages/frontend/editor-ui/src/features/agents/components/model-selector/ModelSelectorItemLeadingIcon.vue":{"11":[46]},"packages/frontend/editor-ui/src/features/agents/components/model-selector/ModelSelectorRestrictedMarker.vue":{"11":[46],"15":[46],"16":[46],"27":[46]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentProjectNameResolver.ts":{"8":[46],"11":[46],"15":[46],"18":[46]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentToolRefAdapter.ts":{"21":[46],"23":[46],"32":[46],"50":[46],"67":[46],"82":[46],"106":[46],"127":[46],"146":[46],"151":[46],"152":[46],"163":[46]},"packages/frontend/editor-ui/src/features/agents/composables/useMcpServerAdapter.ts":{"12":[46],"14":[46],"19":[46],"25":[46],"29":[46],"31":[46],"35":[46],"39":[46],"43":[46],"59":[46],"72":[46],"73":[46],"82":[46],"108":[46],"112":[46],"114":[46],"117":[46],"120":[46],"121":[46],"124":[46],"135":[46],"139":[46],"143":[46],"158":[46],"175":[46],"189":[46],"207":[46],"211":[46],"232":[46],"237":[46],"244":[46],"281":[46]},"packages/frontend/editor-ui/src/features/agents/modals.ts":{"19":[46],"25":[46],"31":[46],"37":[46],"43":[46],"49":[46],"55":[46],"62":[46],"68":[46],"73":[46],"79":[46],"86":[46],"92":[46],"96":[46],"102":[46],"108":[46],"114":[46],"119":[46],"127":[46]},"packages/frontend/editor-ui/src/features/agents/utils/agentCapabilityActivity.ts":{"5":[46],"9":[46],"13":[46],"17":[46]},"packages/frontend/editor-ui/src/features/agents/utils/agentSkill.ts":{"3":[46],"10":[46]},"packages/frontend/editor-ui/src/features/agents/utils/agentValidationIssueMessages.ts":{"44":[46],"61":[46]},"packages/frontend/editor-ui/src/features/agents/utils/capabilitySummaryTools.ts":{"11":[46],"15":[46]},"packages/frontend/editor-ui/src/features/agents/utils/inlineAgent.ts":{"16":[46],"20":[46],"36":[46],"51":[46],"66":[46],"79":[46],"89":[46],"90":[46]},"packages/frontend/editor-ui/src/features/agents/utils/promptCaching.ts":{"18":[46]},"packages/frontend/editor-ui/src/features/agents/utils/reasoning.ts":{"7":[46]},"packages/frontend/editor-ui/src/features/agents/utils/toolDisplayName.ts":{"15":[46],"52":[46],"72":[46],"76":[46],"88":[46]},"packages/frontend/editor-ui/src/features/agents/utils/workflowToolTriggers.ts":{"11":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/AIBuilderDiffModal.vue":{"12":[46],"27":[46],"32":[46],"37":[46],"39":[46],"55":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/BuilderNodeGroupCard.vue":{"26":[46],"62":[46],"78":[46],"80":[46],"81":[46],"82":[46],"83":[46],"85":[46],"86":[46],"90":[46],"92":[46],"93":[46],"100":[46],"112":[46],"114":[46],"120":[46],"130":[46],"134":[46],"142":[46],"161":[46],"162":[46],"165":[46],"169":[46],"170":[46],"181":[46],"185":[46],"186":[46],"191":[46],"201":[46],"212":[46],"216":[46],"217":[46],"218":[46],"236":[46],"237":[46],"240":[46],"249":[46],"250":[46],"262":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/BuilderSetupCard.vue":{"30":[31,46],"55":[31,46],"59":[31,46],"61":[31,46],"84":[31,46],"86":[46],"91":[31,46],"97":[31,46],"101":[31,46],"105":[31,46],"106":[31,46],"107":[31,46],"111":[31,46],"112":[31,46],"113":[31,46],"114":[31,46],"116":[31,46],"120":[46],"122":[31,46],"129":[46],"140":[31,46],"153":[31,46],"161":[46],"173":[46],"186":[31,46],"191":[31,46],"192":[46],"193":[31,46],"209":[31,46],"210":[31,46],"213":[31,46],"222":[31,46],"223":[31,46],"236":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/BuilderSetupWizard.vue":{"14":[31,46],"22":[46],"39":[31,46],"43":[31,46],"47":[31,46],"51":[31,46],"55":[31,46],"59":[31,46],"68":[46],"75":[31,46],"86":[31,46],"91":[31,46],"96":[31,46],"102":[31,46],"104":[31,46],"107":[31,46],"115":[31,46],"122":[31,46],"131":[31,46],"140":[31,46],"148":[46],"152":[46],"162":[31,46],"175":[31,46],"187":[31,46],"204":[46],"210":[31,46]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/ChatVersionCard.vue":{"13":[46],"37":[46],"43":[46],"49":[46],"59":[46],"88":[46],"92":[46],"106":[46],"109":[46],"148":[46],"155":[46],"161":[46],"162":[46],"182":[46],"183":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/CollapsedMessagesGroup.vue":{"11":[46],"31":[46],"33":[46],"45":[46],"77":[46],"84":[46],"104":[46],"111":[46],"115":[46],"117":[46],"142":[46],"152":[46],"153":[46],"154":[46],"155":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/CredentialsSetupCard.vue":{"24":[46],"26":[46],"29":[46],"34":[46],"37":[46],"62":[46],"64":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/CreditWarningBanner.vue":{"9":[46],"35":[46],"64":[46],"72":[46],"79":[46],"85":[46],"104":[46],"117":[46],"118":[46],"127":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/CreditsSettingsDropdown.vue":{"11":[31,46],"36":[31,46],"43":[46],"50":[46],"52":[46],"60":[46],"64":[46],"71":[46],"82":[46],"89":[46],"96":[46],"101":[46],"104":[31,46],"120":[31,46],"126":[46],"150":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/ExecuteMessage.vue":{"34":[31,46],"37":[46],"40":[46],"51":[31,46],"58":[31,46],"59":[46],"72":[46],"87":[31,46],"101":[46],"122":[46],"129":[46],"136":[31,46],"138":[46],"142":[46],"146":[31,46],"150":[46],"153":[46],"156":[46],"161":[46],"164":[46],"168":[46],"173":[46],"181":[46],"186":[46],"188":[46],"191":[31,46],"199":[46],"206":[46],"218":[46],"223":[31,46],"234":[46],"235":[46],"258":[46],"260":[46],"265":[46],"283":[46],"285":[46],"297":[46],"326":[46],"328":[46],"344":[46],"346":[46],"370":[46],"406":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/NodeIssueItem.vue":{"26":[46],"31":[46],"35":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/NotificationPermissionBanner.vue":{"7":[46],"11":[46],"21":[46],"24":[46],"38":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/PlanDisplayMessage.vue":{"9":[46],"29":[46],"31":[46],"35":[46],"42":[46],"46":[46],"47":[46],"52":[46],"53":[46],"55":[46],"56":[46],"64":[46],"66":[46],"67":[46],"78":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/PlanQuestionsMessage.vue":{"17":[46],"40":[46],"41":[46],"42":[46],"45":[46],"46":[46],"51":[46],"56":[46],"58":[46],"72":[46],"78":[46],"83":[46],"95":[46],"103":[46],"120":[46],"127":[46],"139":[46],"149":[46],"159":[46],"165":[46],"178":[46],"206":[46],"212":[46],"225":[46],"234":[46],"241":[46],"252":[46],"256":[46],"269":[46],"278":[46],"290":[46],"301":[46],"313":[46],"330":[46],"358":[46],"369":[46],"387":[46],"388":[46],"401":[46],"403":[46],"409":[46],"420":[46],"422":[46],"428":[46],"441":[46],"442":[46],"456":[46],"476":[46],"484":[46],"489":[46],"501":[46],"551":[46],"555":[46],"567":[46],"580":[46],"590":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/ReviewChangesBanner.vue":{"13":[46],"20":[46],"28":[46],"29":[46],"45":[46],"46":[46],"53":[46],"58":[46],"59":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/UserAnswersMessage.vue":{"19":[46],"21":[46],"33":[46],"38":[46],"40":[46],"45":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/WebFetchApprovalMessage.vue":{"17":[46],"44":[46],"55":[46],"57":[46],"63":[46],"67":[46],"79":[46],"89":[46],"104":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/creditFormatting.ts":{"2":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/components/AskModeCoachmark.vue":{"9":[46],"14":[46],"28":[46],"31":[46],"45":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/components/FocusedNodes/FocusedNodeChip.vue":{"13":[46],"23":[46],"24":[46],"26":[46],"28":[46],"35":[46],"40":[46],"43":[46],"52":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/components/FocusedNodes/MessageFocusedNodesChips.vue":{"18":[46],"22":[46],"26":[46],"27":[46],"28":[46],"33":[46],"36":[46],"37":[46],"43":[46],"47":[46],"63":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/components/FocusedNodes/NodeMentionDropdown.vue":{"18":[46],"34":[46],"35":[46],"41":[46],"45":[46],"58":[46],"62":[46],"66":[46],"70":[46],"74":[46],"81":[46],"82":[46],"84":[46],"94":[46],"96":[46],"103":[46],"106":[46],"116":[46],"127":[46],"135":[46],"136":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useBuilderExecution.ts":{"21":[31,46],"25":[46],"34":[46],"35":[46],"39":[46],"41":[46],"45":[46],"46":[46],"53":[31,46],"60":[46],"63":[46],"65":[46],"81":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useBuilderSetupCards.ts":{"10":[31,46],"21":[31,46],"26":[31,46],"30":[31,46],"45":[31,46],"59":[31,46],"60":[31,46],"65":[31,46],"67":[31,46],"71":[31,46],"74":[31,46],"77":[31,46],"80":[46],"89":[31,46],"90":[31,46],"104":[31,46],"110":[31,46],"116":[46],"120":[46],"135":[46],"145":[46],"157":[31,46]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useBuilderStreamingGuard.ts":{"13":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useExecutionWatcher.ts":{"12":[46],"18":[46],"20":[46]},"packages/frontend/editor-ui/src/features/ai/assistant/focusedNodes.utils.ts":{"10":[46],"20":[46],"22":[46]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/components/AddExecutionToDataset/AddExecutionToDatasetModal.vue":{"27":[46],"50":[46],"51":[46],"52":[46],"63":[46],"68":[46],"75":[46],"85":[46],"86":[46],"92":[46],"94":[46],"95":[46],"98":[46],"103":[46],"109":[46],"110":[46],"117":[46],"140":[46],"157":[46],"187":[46],"189":[46],"197":[46],"208":[46],"221":[46],"223":[46],"230":[46],"240":[46],"250":[46],"257":[46],"266":[46],"272":[46],"283":[46],"291":[46]},"packages/frontend/editor-ui/src/features/ai/gateway/assets/service-icons/alibaba.svgcomponent":{"11":[46]},"packages/frontend/editor-ui/src/features/ai/gateway/assets/service-icons/anthropic.svgcomponent":{"11":[46]},"packages/frontend/editor-ui/src/features/ai/gateway/assets/service-icons/brave-search.svgcomponent":{"11":[46]},"packages/frontend/editor-ui/src/features/ai/gateway/assets/service-icons/browserbase.svgcomponent":{"11":[46]},"packages/frontend/editor-ui/src/features/ai/gateway/assets/service-icons/firecrawl.svgcomponent":{"11":[46]},"packages/frontend/editor-ui/src/features/ai/gateway/assets/service-icons/gemini.svgcomponent":{"8":[46]},"packages/frontend/editor-ui/src/features/ai/gateway/assets/service-icons/llamaindex.svgcomponent":{"11":[46]},"packages/frontend/editor-ui/src/features/ai/gateway/assets/service-icons/minimax.svgcomponent":{"11":[46]},"packages/frontend/editor-ui/src/features/ai/gateway/assets/service-icons/moonshot.svgcomponent":{"11":[46]},"packages/frontend/editor-ui/src/features/ai/gateway/assets/service-icons/openai.svgcomponent":{"11":[46]},"packages/frontend/editor-ui/src/features/ai/gateway/assets/service-icons/pdfco.svgcomponent":{"13":[46]},"packages/frontend/editor-ui/src/features/ai/gateway/components/AiGatewayTopUpModal.vue":{"23":[46],"91":[46],"92":[46],"95":[46],"96":[46],"98":[46],"99":[46],"100":[46],"104":[46],"114":[46],"123":[46],"132":[46],"137":[46],"142":[46],"146":[46],"155":[46],"164":[46],"179":[46],"182":[46],"186":[46],"199":[46]},"packages/frontend/editor-ui/src/features/ai/instanceAi/modals.ts":{"12":[46],"17":[46],"22":[46],"23":[46]},"packages/frontend/editor-ui/src/features/ai/instanceAi/planReview.utils.ts":{"4":[46],"6":[46],"20":[46],"21":[46],"31":[46]},"packages/frontend/editor-ui/src/features/ai/instanceAi/prefills.ts":{"60":[46,122],"68":[46,122],"80":[46,122]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectMoveResourceModalCredentialsList.vue":{"10":[46],"21":[46],"24":[46],"27":[46],"45":[46],"50":[46],"55":[46]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialInfo.vue":{"18":[46],"25":[46],"31":[46],"37":[46],"51":[46],"65":[46],"66":[46],"70":[46],"71":[46],"77":[46],"78":[46],"82":[46],"83":[46],"89":[46],"90":[46],"94":[46]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialOptionsInput.vue":{"19":[46],"39":[46],"40":[46],"43":[46],"47":[46],"50":[46],"61":[46],"71":[46],"87":[46],"88":[46],"90":[46],"93":[46],"99":[46],"104":[46],"116":[46]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialTypeSelector.vue":{"15":[9,46],"42":[9,46],"44":[9,46],"59":[46],"63":[9,46],"70":[9,46],"74":[46],"78":[46],"79":[9,46],"87":[46],"89":[9,46],"99":[9,46],"100":[9,46],"101":[9,46],"103":[9,46],"108":[9,46],"112":[9,46],"115":[9,46]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/GoogleAuthButton.vue":{"2":[29,9,46]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/TemplatedAuthSimpleView.vue":{"43":[46],"57":[46],"61":[46],"65":[46],"67":[46],"69":[46],"72":[46],"82":[46],"86":[46],"101":[46],"108":[46],"109":[46],"114":[46],"115":[46],"135":[46],"137":[46],"148":[46],"169":[46],"175":[46],"180":[46],"186":[46],"187":[46],"199":[46],"203":[46],"207":[46],"217":[46],"222":[46],"230":[46],"233":[46],"248":[46],"253":[46],"275":[46],"276":[46],"292":[46],"293":[46],"297":[46],"307":[46],"325":[46],"328":[46],"339":[46],"348":[46],"353":[46],"361":[46],"372":[46],"376":[46],"394":[46],"401":[46],"412":[46],"430":[46],"437":[46]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/TypeToConfirmDialog.vue":{"14":[46],"35":[46],"39":[46],"40":[46],"46":[46],"51":[46],"53":[46],"63":[46],"64":[46],"66":[46],"69":[46]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialPrivateConnectionRow.vue":{"23":[46],"36":[46],"50":[46],"56":[46],"71":[46],"76":[46],"85":[46],"91":[46],"100":[46],"102":[46],"110":[46],"112":[46],"119":[46],"130":[46],"132":[46],"152":[46],"154":[46]},"packages/frontend/editor-ui/src/features/credentials/components/ScopesNotice.vue":{"7":[46],"15":[46],"27":[46],"36":[46],"42":[46],"47":[46]},"packages/frontend/editor-ui/src/features/credentials/composables/useCredentialOptions.ts":{"22":[46],"31":[46],"33":[46],"39":[46],"40":[46],"42":[46],"44":[46],"50":[46],"75":[46],"84":[46],"91":[46],"96":[46],"101":[46],"102":[46],"109":[46]},"packages/frontend/editor-ui/src/features/credentials/gatewayCreditsPromotion/GatewayCreditsPromotion.vue":{"8":[46],"9":[46]},"packages/frontend/editor-ui/src/features/credentials/quickConnect/components/QuickConnectBanner.vue":{"11":[46],"19":[46],"27":[46],"32":[46]},"packages/frontend/editor-ui/src/features/credentials/quickConnect/quickConnect.api.ts":{"9":[46]},"packages/frontend/editor-ui/src/features/credentials/templatedAuth.utils.ts":{"43":[46],"54":[46],"56":[46],"65":[46],"75":[46],"78":[46],"79":[46],"90":[46],"107":[46],"116":[46],"126":[46],"129":[46],"135":[46],"139":[46],"149":[46],"163":[46],"171":[46],"185":[46],"191":[46],"193":[46]},"packages/frontend/editor-ui/src/features/execution/executions/components/DebugPaywallModal.vue":{"6":[46],"12":[46],"16":[46],"23":[46],"27":[46],"30":[46]},"packages/frontend/editor-ui/src/features/execution/executions/components/RevealDataWarning.vue":{"13":[46],"14":[46],"29":[46]},"packages/frontend/editor-ui/src/features/execution/executions/components/StopManyExecutionsModal.vue":{"13":[46],"27":[46],"46":[46],"57":[46],"90":[46],"92":[46],"103":[46],"106":[46],"107":[46],"111":[46],"112":[46],"116":[46],"117":[46],"149":[46]},"packages/frontend/editor-ui/src/features/integrations/externalSecrets.ee/assets/images/azure-key-vault.svg":{"10":[46]},"packages/frontend/editor-ui/src/features/integrations/externalSecrets.ee/assets/images/gcp-secrets-manager.svg":{"10":[46]},"packages/frontend/editor-ui/src/features/integrations/externalSecrets.ee/assets/images/one-password.svg":{"8":[46]},"packages/frontend/editor-ui/src/features/integrations/externalSecrets.ee/components/ExternalSecretsProviderConnectionSwitch.ee.vue":{"11":[46],"35":[46],"39":[46],"45":[46],"65":[46],"78":[46]},"packages/frontend/editor-ui/src/features/integrations/externalSecrets.ee/components/ExternalSecretsProviderImage.ee.vue":{"17":[46],"18":[46]},"packages/frontend/editor-ui/src/features/integrations/externalSecrets.ee/components/ExternalSecretsProviderModal.ee.vue":{"24":[46],"48":[46],"49":[46],"61":[46],"62":[46],"70":[46],"73":[46],"74":[46],"80":[46],"105":[46],"112":[46],"131":[46],"139":[46],"164":[46],"166":[46],"178":[46],"200":[46],"211":[46],"218":[46],"238":[46],"243":[46],"252":[46],"266":[46],"271":[46]},"packages/frontend/editor-ui/src/features/integrations/externalSecrets.ee/composables/useExternalSecretsProvider.ts":{"15":[46],"25":[46],"28":[46],"36":[46],"37":[46],"39":[46],"50":[46],"56":[46],"66":[46],"74":[46]},"packages/frontend/editor-ui/src/features/integrations/promotions.ee/modals.ts":{"7":[46]},"packages/frontend/editor-ui/src/features/integrations/promotions.ee/module.descriptor.ts":{"8":[46],"36":[46],"40":[46]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/components/SecretsProviderConnectionModal.ee.vue":{"43":[46],"76":[46],"77":[46],"78":[46],"79":[46],"93":[46],"94":[46],"104":[46],"121":[46],"131":[46],"147":[46],"151":[46],"152":[46],"158":[46],"167":[46],"172":[46],"176":[46],"180":[46],"184":[46],"189":[46],"202":[46],"210":[46],"230":[46],"237":[46],"250":[46],"266":[46],"272":[46],"291":[46],"305":[46],"310":[46],"315":[46],"346":[46],"412":[46],"420":[46],"441":[46],"443":[46],"453":[46],"457":[46],"462":[46],"479":[46],"483":[46],"492":[46],"497":[46],"504":[46],"507":[46],"512":[46],"517":[46]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/composables/useConnectionModal.ee.ts":{"31":[46],"35":[46],"60":[46],"66":[46],"76":[46],"94":[46],"99":[46],"106":[46],"108":[46],"114":[46],"115":[46],"120":[46],"122":[46],"128":[46],"130":[46],"135":[46],"140":[46],"144":[46],"153":[46],"161":[46],"166":[46],"168":[46],"169":[46],"175":[46],"176":[46],"183":[46],"189":[46],"196":[46],"201":[46],"202":[46],"209":[46],"210":[46],"214":[46],"215":[46],"217":[46],"227":[46],"235":[46],"241":[46],"259":[46],"278":[46],"283":[46],"285":[46],"293":[46],"300":[46],"308":[46],"309":[46],"316":[46],"331":[46],"340":[46],"359":[46],"403":[46],"444":[46],"452":[46],"455":[46],"480":[46],"518":[46]},"packages/frontend/editor-ui/src/features/integrations/sourceControl.ee/components/SourceControlInitializationErrorMessage.vue":{"6":[46],"7":[46],"11":[46],"13":[46]},"packages/frontend/editor-ui/src/features/integrations/sourceControl.ee/components/SourceControlPullModal.vue":{"56":[46],"71":[46],"80":[46],"81":[46],"82":[46],"110":[46],"111":[46],"116":[46],"117":[46],"123":[46],"156":[46],"167":[46],"170":[46],"181":[46],"183":[46],"184":[46],"190":[46],"191":[46],"209":[46],"210":[46],"215":[46],"216":[46],"221":[46],"222":[46],"229":[46],"231":[46],"240":[46],"253":[46],"258":[46],"266":[46],"280":[46],"301":[46],"324":[46],"350":[46],"356":[46],"359":[46],"371":[46],"374":[46],"394":[46],"398":[46],"414":[46],"422":[46],"428":[46],"440":[46],"442":[46],"447":[46],"449":[46],"454":[46],"458":[46],"465":[46],"467":[46],"472":[46],"474":[46],"476":[46],"484":[46],"489":[46],"493":[46],"502":[46],"507":[46],"516":[46],"527":[46],"538":[46],"544":[46],"545":[46],"546":[46],"568":[46],"573":[46],"584":[46],"591":[46],"598":[46],"608":[46],"617":[46],"627":[46],"631":[46],"647":[46],"649":[46],"650":[46],"655":[46],"656":[46],"659":[46],"662":[46],"668":[46],"671":[46]},"packages/frontend/editor-ui/src/features/integrations/sourceControl.ee/components/SourceControlPullResultModal.vue":{"13":[46],"23":[46],"24":[46],"29":[46],"30":[46],"38":[46],"60":[46],"64":[46],"66":[46],"77":[46],"79":[46],"83":[46],"87":[46],"92":[46],"96":[46],"117":[46],"121":[46],"127":[46],"131":[46],"141":[46],"154":[46],"157":[46]},"packages/frontend/editor-ui/src/features/integrations/sourceControl.ee/components/SourceControlPushModal.vue":{"66":[46],"81":[46],"88":[46],"112":[46],"137":[46],"140":[46],"145":[46],"162":[46],"163":[46],"165":[46],"231":[46],"265":[46],"266":[46],"271":[46],"277":[46],"281":[46],"292":[46],"295":[46],"300":[46],"322":[46],"323":[46],"326":[46],"329":[46],"331":[46],"332":[46],"336":[46],"339":[46],"361":[46],"391":[46],"393":[46],"398":[46],"431":[46],"432":[46],"434":[46],"453":[46],"454":[46],"456":[46],"475":[46],"492":[46],"498":[46],"508":[46],"512":[46],"515":[46],"519":[46],"521":[46],"525":[46],"531":[46],"536":[46],"547":[46],"553":[46],"616":[46],"619":[46],"620":[46],"623":[46],"646":[46],"648":[46],"649":[46],"654":[46],"658":[46],"664":[46],"675":[46],"685":[46],"697":[46],"705":[46],"711":[46],"714":[46],"720":[46],"727":[46],"734":[46],"738":[46],"741":[46],"754":[46],"767":[46],"772":[46],"780":[46],"790":[46],"803":[46],"826":[46],"839":[46],"846":[46],"865":[46],"883":[46],"891":[46],"892":[46],"893":[46],"894":[46],"895":[46],"896":[46],"904":[46],"908":[46],"920":[46],"922":[46],"938":[46],"948":[46],"955":[46],"957":[46],"961":[46],"973":[46],"975":[46],"1011":[46],"1013":[46],"1021":[46],"1036":[46],"1042":[46],"1049":[46],"1052":[46],"1057":[46],"1061":[46],"1077":[46],"1078":[46],"1085":[46],"1099":[46],"1106":[46],"1116":[46],"1127":[46],"1141":[46],"1143":[46],"1147":[46],"1153":[46],"1154":[46],"1155":[46],"1156":[46],"1185":[46],"1187":[46],"1195":[46],"1204":[46],"1215":[46],"1245":[46],"1247":[46],"1255":[46],"1260":[46],"1278":[46],"1284":[46],"1286":[46],"1288":[46],"1289":[46],"1290":[46],"1296":[46],"1301":[46],"1320":[46]},"packages/frontend/editor-ui/src/features/integrations/sourceControl.ee/composables/useRevealWorkflowInScroller.ts":{"7":[46],"27":[46],"36":[46],"58":[46]},"packages/frontend/editor-ui/src/features/integrations/sourceControl.ee/composables/useSourceControlFileList.ts":{"20":[46],"26":[46]},"packages/frontend/editor-ui/src/features/integrations/sourceControl.ee/composables/useWorkflowTreeRows.ts":{"6":[46],"9":[46],"13":[46],"36":[46],"40":[46],"49":[46],"55":[46],"69":[46]},"packages/frontend/editor-ui/src/features/integrations/sourceControl.ee/sourceControl.utils.ts":{"17":[46],"20":[46],"38":[46],"48":[46],"51":[46],"61":[46],"74":[46],"84":[46],"97":[46],"178":[46],"214":[46],"230":[46],"237":[46],"243":[46],"254":[46]},"packages/frontend/editor-ui/src/features/ndv/agents/components/AgentNdvInlineControls.vue":{"22":[46],"35":[46],"36":[46],"37":[46],"38":[46],"39":[46],"41":[46],"45":[46],"47":[46],"49":[46],"71":[46]},"packages/frontend/editor-ui/src/features/ndv/agents/components/AgentNdvReferencedSummary.vue":{"30":[46],"39":[46],"40":[46],"41":[46],"42":[46],"43":[46],"44":[46],"45":[46],"46":[46],"47":[46],"49":[46],"54":[46],"63":[46],"69":[46],"71":[46],"77":[46],"87":[46],"90":[46],"91":[46],"100":[46],"103":[46],"108":[46],"110":[46],"127":[46],"138":[46],"156":[46],"163":[46],"172":[46]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/AgentSelectorParameterInput/AgentSelectorParameterInput.vue":{"59":[46],"112":[46],"121":[46],"129":[46],"140":[46],"150":[46],"154":[46],"164":[46],"189":[46],"193":[46],"198":[46],"203":[46],"208":[46],"212":[46],"216":[46],"225":[46],"253":[46],"261":[46],"268":[46],"273":[46],"274":[46],"283":[46],"291":[46],"313":[46],"317":[46],"320":[46],"327":[46],"345":[46],"347":[46],"353":[46],"370":[46],"387":[46],"406":[46],"426":[46]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ButtonParameter/ButtonParameter.vue":{"23":[46],"39":[46],"48":[46],"49":[46],"50":[46],"53":[46],"57":[46],"61":[46],"70":[46],"76":[46],"80":[46],"81":[46],"86":[46],"90":[46],"166":[46],"174":[46],"181":[46],"185":[46],"196":[46],"210":[46],"242":[46],"256":[46],"271":[46],"275":[46]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/Collection/CollectionParameterNew.vue":{"44":[46],"59":[46],"61":[46],"68":[46],"75":[46],"81":[46],"93":[46],"109":[46],"113":[46],"118":[46],"130":[46],"132":[46],"133":[46],"136":[46],"138":[46],"148":[46],"150":[46],"165":[46],"166":[46],"169":[46],"170":[46],"176":[46],"178":[46],"187":[46],"193":[46],"201":[46],"205":[46],"262":[46],"264":[46],"273":[46],"274":[46],"276":[46],"281":[46],"283":[46],"292":[46],"318":[46],"340":[46],"349":[46],"350":[46],"351":[46],"357":[46],"386":[46]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FilterConditions/CombinatorSelect.vue":{"14":[46,131],"20":[46],"22":[46,131],"31":[46,131],"32":[46,131]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FilterConditions/Condition.vue":{"43":[46,131],"63":[46,131],"67":[46,131],"69":[46],"79":[46,131],"97":[46,131],"110":[46,131],"118":[46],"120":[46,131],"131":[46,131],"143":[46,131],"145":[46,131],"150":[46],"155":[46],"166":[46,131],"170":[46,131],"174":[46],"184":[46],"192":[46],"215":[46,131],"216":[46],"221":[46,131],"250":[46,131],"269":[46,131],"278":[46,131],"304":[46],"306":[46,131],"314":[46],"316":[46,131]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FilterConditions/FilterConditions.vue":{"39":[46,131],"62":[46,131],"71":[46,131],"75":[46,131],"78":[46,131],"90":[46,131],"94":[46,131],"96":[46,131],"100":[46,131],"105":[46,131],"134":[46,131],"135":[46,131],"144":[46,131],"145":[46,131],"152":[46,131],"160":[46,131],"164":[46,131],"168":[46],"172":[46,131],"176":[46,131],"178":[46,131],"210":[46,131],"232":[46,131],"233":[46,131]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FilterConditions/OperatorSelect.vue":{"19":[46,131],"30":[46,131],"31":[46,131],"34":[46,131],"36":[46,131],"38":[46,131],"41":[46,131],"42":[46,131],"55":[46,131],"69":[46],"73":[46,131],"86":[46,131],"88":[46,131]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FilterConditions/utils.ts":{"20":[46,131],"23":[46],"29":[46],"46":[46],"78":[46],"82":[46,131],"106":[46],"130":[46,131],"151":[46,131]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FromAiParametersModal.vue":{"24":[46],"44":[46],"48":[46],"57":[46],"61":[46],"69":[46],"115":[46],"120":[46],"136":[46],"137":[46],"141":[46],"143":[46],"144":[46],"154":[46],"167":[46]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ImportCurlModal.vue":{"13":[46],"25":[46],"33":[46],"38":[46],"42":[46],"46":[46],"50":[46],"55":[46],"59":[46],"72":[46],"86":[46],"88":[46],"104":[46],"116":[46],"119":[46],"132":[46]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/MultipleParameter.vue":{"16":[46],"37":[46],"41":[46],"42":[46],"49":[46],"57":[46],"59":[46],"61":[46],"75":[46],"84":[46],"88":[46],"97":[46],"106":[46],"108":[46],"112":[46],"122":[46],"131":[46],"139":[46],"146":[46],"182":[46],"190":[46]},"packages/frontend/editor-ui/src/features/ndv/parameters/composables/useAgentResourcesLocator.ts":{"25":[46],"42":[46],"44":[46],"50":[46],"56":[46],"60":[46],"77":[46],"131":[46],"138":[46],"148":[46],"154":[46]},"packages/frontend/editor-ui/src/features/ndv/parameters/utils/assignmentCollection.utils.ts":{"8":[46,82],"18":[46,82],"30":[46],"33":[46],"35":[46],"43":[46]},"packages/frontend/editor-ui/src/features/ndv/parameters/utils/buttonParameter.utils.ts":{"21":[46],"28":[46],"29":[46],"31":[46],"32":[46],"35":[46],"37":[46],"40":[46],"48":[46],"61":[46],"69":[46],"82":[46],"114":[46],"158":[46],"183":[46],"249":[46],"263":[46],"266":[46],"275":[46],"297":[46],"304":[46],"310":[46],"340":[46],"373":[46],"374":[46],"381":[46],"403":[46]},"packages/frontend/editor-ui/src/features/ndv/runData/components/BinaryDataDisplay.vue":{"10":[46],"24":[46],"28":[46],"56":[46],"61":[46]},"packages/frontend/editor-ui/src/features/ndv/runData/components/BinaryDataDisplayEmbed.vue":{"10":[46],"23":[46],"27":[46],"55":[46]},"packages/frontend/editor-ui/src/features/ndv/runData/components/BinaryDataViewModal.vue":{"12":[46],"28":[46],"60":[46],"67":[46],"118":[46],"119":[46],"121":[46],"126":[46],"129":[46],"139":[46]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataBinary.vue":{"18":[46],"26":[46],"33":[46],"37":[46],"42":[46],"47":[46],"58":[46],"63":[46],"65":[46],"71":[46],"72":[46],"75":[46],"77":[46],"86":[46],"97":[46],"105":[46],"117":[46],"125":[46],"133":[46],"145":[46],"153":[46]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataHtml.vue":{"27":[46],"32":[46]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataMarkdown.vue":{"17":[46]},"packages/frontend/editor-ui/src/features/ndv/settings/components/NodeSettingsInvalidNodeWarning.vue":{"24":[46],"33":[46],"34":[46],"39":[46],"40":[46],"42":[46],"46":[46],"48":[46],"61":[46],"92":[46],"97":[46],"106":[46],"115":[46],"116":[46],"128":[46],"136":[46],"148":[46]},"packages/frontend/editor-ui/src/features/resolvers/components/CredentialResolverEditModal.vue":{"37":[46],"76":[46],"79":[46],"88":[46],"101":[46],"118":[46],"119":[46],"124":[46],"137":[46],"141":[46],"154":[46],"158":[46],"183":[46],"199":[46],"207":[46],"220":[46],"242":[46],"249":[46],"322":[46],"335":[46],"340":[46],"344":[46],"368":[46],"381":[46],"393":[46],"413":[46],"438":[46],"442":[46],"446":[46],"455":[46],"464":[46],"467":[46],"492":[46],"501":[46],"504":[46],"513":[46],"538":[46],"541":[46]},"packages/frontend/editor-ui/src/features/resolvers/components/PrivateCredentialIcon.vue":{"15":[46],"23":[46],"24":[46],"28":[46],"32":[46]},"packages/frontend/editor-ui/src/features/resolvers/components/ResolverDeleteConfirmMessage.vue":{"10":[46],"19":[46],"20":[46],"22":[46],"28":[46],"35":[46],"44":[46],"48":[46],"54":[46]},"packages/frontend/editor-ui/src/features/settings/apiKeys/apiKeys.utils.ts":{"43":[46],"52":[46]},"packages/frontend/editor-ui/src/features/settings/apiKeys/components/ApiKeyCreateOrEditModal.vue":{"70":[46],"78":[46],"114":[46],"127":[46],"131":[46],"139":[46],"146":[46],"153":[46],"157":[46],"164":[46],"174":[46],"176":[46],"185":[46],"193":[46],"199":[46],"203":[46],"207":[46],"212":[46],"228":[46],"232":[46],"267":[46],"271":[46],"277":[46],"284":[46],"307":[46],"323":[46],"340":[46],"347":[46],"363":[46],"366":[46],"383":[46],"401":[46],"408":[46],"411":[46],"437":[46],"445":[46],"447":[46],"463":[46],"464":[46],"468":[46],"476":[46],"485":[46],"507":[46]},"packages/frontend/editor-ui/src/features/settings/apiKeys/components/ApiKeyScopes.vue":{"8":[46],"18":[46],"31":[46]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/ContactAdministratorToInstall.vue":{"11":[46],"17":[46],"18":[46],"21":[46],"26":[46],"30":[46],"36":[46],"40":[46]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/NodesInWorkflowTable.vue":{"19":[46],"46":[46],"51":[46],"59":[46],"65":[46],"77":[46],"79":[46],"82":[46],"94":[46]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/nodeCreator/CommunityNodeUpdateInfo.vue":{"11":[46],"15":[46],"18":[46],"23":[46],"25":[46],"26":[46]},"packages/frontend/editor-ui/src/features/settings/context/module.descriptor.ts":{"21":[46],"28":[46],"34":[46],"41":[46]},"packages/frontend/editor-ui/src/features/settings/environments.ee/completions/variables.completions.ts":{"4":[46],"6":[46],"8":[46],"14":[46],"24":[46]},"packages/frontend/editor-ui/src/features/settings/migrationReport/MigrateWorkflowModal.vue":{"21":[46],"37":[46],"49":[46],"50":[46],"52":[46],"56":[46],"61":[46],"91":[46],"109":[46],"111":[46],"122":[46],"124":[46],"131":[46],"137":[46],"140":[46],"141":[46],"142":[46],"150":[46],"162":[46],"168":[46],"174":[46],"178":[46],"182":[46],"184":[46],"192":[46],"199":[46],"203":[46],"210":[46]},"packages/frontend/editor-ui/src/features/settings/usage/components/CommunityPlusEnrollmentModal.vue":{"15":[46],"35":[46],"54":[46],"60":[46],"83":[46],"96":[46],"99":[46],"101":[46],"138":[46],"143":[46],"146":[46],"154":[46],"157":[46]},"packages/frontend/editor-ui/src/features/settings/users/components/InviteUsersModal.vue":{"31":[46],"58":[46],"59":[46],"62":[46],"75":[46],"79":[46],"83":[46],"87":[46],"94":[46],"96":[46],"99":[46],"120":[46],"122":[46],"125":[46],"134":[46],"140":[46],"141":[46],"148":[46],"149":[46],"152":[46],"166":[46],"194":[46],"202":[46],"207":[46],"226":[46],"240":[46],"247":[46],"251":[46],"264":[46],"268":[46],"279":[46],"323":[46],"334":[46],"349":[46],"352":[46],"354":[46],"361":[46],"363":[46],"365":[46],"371":[46],"387":[46]},"packages/frontend/editor-ui/src/features/settings/users/components/PersonalizationModal.vue":{"103":[46],"118":[46],"121":[46],"228":[46],"238":[46],"295":[46],"305":[46],"352":[46],"366":[46],"415":[46],"426":[46],"459":[46],"497":[46],"553":[46],"561":[46],"565":[46],"574":[46],"590":[46],"611":[46],"629":[46],"642":[46]},"packages/frontend/editor-ui/src/features/settings/users/invite-link.utils.ts":{"14":[46],"20":[46]},"packages/frontend/editor-ui/src/features/setupPanel/components/TriggerExecuteButton.vue":{"6":[31,46],"18":[31,46],"20":[46],"22":[31,46],"27":[46],"28":[46],"30":[31,46]},"packages/frontend/editor-ui/src/features/setupPanel/components/WebhookUrlPreview.vue":{"15":[46],"21":[46],"27":[46],"34":[46],"44":[46],"48":[46],"52":[46]},"packages/frontend/editor-ui/src/features/setupPanel/components/cards/SetupCardBody.vue":{"22":[31,46],"57":[31,46],"61":[31,46],"63":[31,46],"70":[31,46],"77":[31,46],"94":[31,46],"97":[31,46],"106":[31,46],"110":[31,46],"111":[31,46],"113":[31,46],"114":[46],"116":[46],"124":[31,46],"135":[31,46],"136":[31,46],"139":[46],"143":[31,46],"164":[46],"183":[31,46],"197":[31,46],"198":[46],"200":[31,46],"206":[31,46],"247":[46]},"packages/frontend/editor-ui/src/features/setupPanel/components/cards/SetupCardSection.vue":{"9":[31,46],"13":[31,46],"16":[31,46]},"packages/frontend/editor-ui/src/features/setupPanel/composables/groupSetupCards.ts":{"20":[31,46],"51":[46],"81":[31,46],"111":[46],"116":[46],"178":[46]},"packages/frontend/editor-ui/src/features/setupPanel/composables/useNodeGroupSections.ts":{"11":[46],"19":[46],"24":[46],"31":[46],"34":[46],"45":[46],"52":[46],"60":[46],"66":[46],"73":[46],"81":[46],"87":[46],"107":[46],"111":[46],"117":[46]},"packages/frontend/editor-ui/src/features/setupPanel/composables/useTriggerExecution.ts":{"18":[31,46],"38":[31,46],"40":[31,46],"46":[31,46],"57":[46],"70":[31,46],"77":[31,46],"81":[31,46],"87":[31,46],"91":[31,46]},"packages/frontend/editor-ui/src/features/setupPanel/composables/useWebhookUrls.ts":{"21":[31,46],"25":[31,46],"27":[31,46],"33":[31,46],"35":[31,46],"38":[46],"54":[46],"83":[31,46]},"packages/frontend/editor-ui/src/features/setupPanel/composables/useWorkflowSetupState.ts":{"50":[31,46],"67":[31,46],"74":[31,46],"92":[46],"121":[31,46],"124":[31,46],"160":[31,46],"168":[46],"173":[46],"198":[31,46],"226":[31,46],"231":[31,46],"235":[46],"254":[46],"297":[31,46],"299":[31,46],"300":[31,46],"306":[31,46],"330":[31,46],"353":[31,46],"354":[31,46],"361":[31,46],"362":[31,46],"365":[31,46],"366":[31,46],"376":[31,46],"390":[31,46],"404":[31,46],"417":[31,46],"420":[46],"434":[31,46],"435":[31,46],"437":[31,46],"441":[31,46],"449":[31,46],"468":[31,46],"471":[31,46],"477":[31,46],"478":[31,46],"486":[46],"513":[31,46],"554":[46],"622":[31,46],"638":[31,46],"641":[31,46],"656":[46],"664":[31,46],"665":[31,46],"667":[31,46],"669":[31,46],"682":[46],"683":[46],"686":[46],"690":[46],"691":[46],"700":[31,46],"703":[31,46],"705":[46],"707":[46],"709":[46],"714":[31,46],"718":[31,46],"730":[31,46],"775":[46],"800":[31,46],"803":[46],"811":[31,46],"837":[31,46],"868":[46],"882":[46]},"packages/frontend/editor-ui/src/features/shared/banners/components/banners/DataTableStorageLimitErrorBanner.vue":{"6":[46],"8":[46],"12":[46]},"packages/frontend/editor-ui/src/features/shared/banners/components/banners/DataTableStorageLimitWarningBanner.vue":{"6":[46],"8":[46],"12":[46]},"packages/frontend/editor-ui/src/features/shared/banners/components/banners/DynamicBanner.vue":{"13":[46],"14":[46],"23":[46]},"packages/frontend/editor-ui/src/features/shared/banners/components/banners/EmailConfirmationBanner.vue":{"10":[46],"13":[46],"17":[46],"31":[46],"37":[46],"40":[46],"44":[46],"52":[46]},"packages/frontend/editor-ui/src/features/shared/banners/components/banners/NonProductionLicenseBanner.vue":{"7":[46],"8":[46]},"packages/frontend/editor-ui/src/features/shared/banners/components/banners/TrialOverBanner.vue":{"8":[46],"10":[46],"12":[46],"17":[46],"20":[46],"27":[46]},"packages/frontend/editor-ui/src/features/shared/banners/components/banners/V1Banner.vue":{"8":[46],"10":[46],"14":[46],"15":[46],"19":[46]},"packages/frontend/editor-ui/src/features/shared/banners/components/banners/WorkflowAutoDeactivatedBanner.vue":{"7":[46],"8":[46]},"packages/frontend/editor-ui/src/features/shared/commandBar/commandBar.utils.ts":{"9":[46],"12":[46],"15":[46]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/completions/base.completions.ts":{"11":[46],"13":[46],"14":[46],"17":[46],"24":[46],"53":[46],"105":[46],"140":[46],"147":[46]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/completions/execution.completions.ts":{"7":[46],"13":[46]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/completions/itemField.completions.ts":{"6":[46],"15":[46],"53":[46],"111":[46]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/completions/itemIndex.completions.ts":{"8":[46],"14":[46],"69":[46]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/completions/jsonField.completions.ts":{"12":[46],"16":[46],"29":[46],"78":[46],"131":[46],"176":[46],"196":[46],"206":[46],"207":[46],"224":[46],"225":[46],"245":[46]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/completions/luxon.completions.ts":{"8":[46],"12":[46],"30":[46],"48":[46],"58":[46],"59":[46],"73":[46],"75":[46],"76":[46],"84":[46],"85":[46]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/completions/prevNode.completions.ts":{"8":[46],"10":[46],"16":[46]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/completions/require.completions.ts":{"6":[46],"10":[46],"17":[46]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/completions/utils.ts":{"3":[46]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/completions/workflow.completions.ts":{"6":[46],"8":[46],"14":[46]},"packages/frontend/editor-ui/src/features/shared/editors/components/CssEditor/CssEditor.vue":{"36":[46],"50":[46],"55":[46],"85":[46],"90":[46],"99":[46],"104":[46]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/typescript/client/hoverTooltip.ts":{"5":[46],"16":[46],"43":[46]},"packages/frontend/editor-ui/src/features/shared/tags/components/TagsManager/AnnotationTagsManager.ee.vue":{"11":[46],"16":[46],"17":[46],"19":[46],"29":[46],"44":[46],"64":[46],"85":[46]},"packages/frontend/editor-ui/src/features/workflow-reviews/module.descriptor.ts":{"8":[46],"9":[46],"21":[46]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/CanvasNodeAgent.vue":{"30":[46],"58":[46],"60":[46],"65":[46],"73":[46],"77":[46],"88":[46],"95":[46],"96":[46],"106":[46],"110":[46],"118":[46],"125":[46],"129":[46],"136":[46],"141":[46],"145":[46],"158":[46],"162":[46],"165":[46],"180":[46],"184":[46],"190":[46],"194":[46],"209":[46],"212":[46],"216":[46],"230":[46],"236":[46],"256":[46],"261":[46],"273":[46]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/parts/CanvasNodeAgentChips.vue":{"12":[46],"31":[46],"32":[46],"39":[46],"40":[46],"41":[46],"42":[46],"43":[46],"44":[46],"46":[46],"51":[46],"64":[46],"66":[46],"71":[46],"81":[46],"96":[46],"100":[46]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/parts/canvasNodeAgentChips.utils.ts":{"49":[46],"75":[46],"83":[46],"110":[46],"123":[46],"133":[46]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/nodeGroupTelemetry.utils.ts":{"4":[46],"11":[46]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/components/ExperimentalEmbeddedNdvActions.vue":{"6":[46],"7":[46],"17":[46],"25":[46]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/components/ExperimentalEmbeddedNdvHeader.vue":{"22":[46],"23":[46],"33":[46],"40":[46],"44":[46],"58":[46]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/components/ExperimentalEmbeddedNodeDetails.vue":{"25":[46],"28":[46],"34":[46],"35":[46],"43":[46],"56":[46],"62":[46],"66":[46],"70":[46],"78":[46],"81":[46],"107":[46],"119":[46],"122":[46]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/experimentalNdv.utils.ts":{"5":[46],"25":[46],"26":[46]},"packages/frontend/editor-ui/src/features/workflows/canvas/nodeGroups.utils.ts":{"7":[46,78],"12":[46],"17":[46],"18":[46],"24":[46],"32":[46,78]},"packages/frontend/editor-ui/src/features/workflows/components/DuplicateWorkflowDialog.vue":{"21":[46],"56":[46],"60":[46],"66":[46],"70":[46],"74":[46],"78":[46],"153":[46],"154":[46],"162":[46],"167":[46],"178":[46],"198":[46]},"packages/frontend/editor-ui/src/features/workflows/components/WorkflowActivationConflictingWebhookModal.vue":{"12":[46],"28":[46],"32":[46],"61":[46],"65":[46],"67":[46],"78":[46],"80":[46],"85":[46],"86":[46],"89":[46],"94":[46],"96":[46],"100":[46]},"packages/frontend/editor-ui/src/features/workflows/components/WorkflowActivationErrorMessage.vue":{"3":[46],"4":[46]},"packages/frontend/editor-ui/src/features/workflows/components/WorkflowExtractionNameModal.vue":{"21":[46,182],"31":[46,182],"37":[46,182],"57":[46,182],"59":[46,182],"64":[46,182],"79":[46,182],"90":[46,182]},"packages/frontend/editor-ui/src/features/workflows/components/WorkflowSettings/WorkflowCustomTelemetryTags.vue":{"22":[46],"42":[46],"44":[46],"45":[46],"47":[46],"49":[46],"51":[46],"53":[46],"54":[46],"56":[46],"58":[46],"69":[46],"70":[46],"72":[46],"73":[46],"77":[46],"78":[46],"82":[46],"83":[46],"84":[46],"85":[46],"86":[46],"87":[46],"93":[46],"104":[46],"111":[46],"115":[46],"116":[46],"121":[46],"125":[46],"126":[46],"129":[46],"134":[46],"139":[46],"156":[46],"165":[46],"173":[46],"175":[46],"178":[46],"180":[46],"186":[46],"195":[46],"213":[46],"219":[46],"235":[46],"254":[46],"268":[46],"281":[46],"293":[46],"306":[46],"317":[46],"329":[46],"339":[46],"349":[46],"356":[46]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/DiffBadge.vue":{"4":[46],"8":[46],"21":[46],"33":[46]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/HighlightedEdge.vue":{"6":[46,160],"7":[46,160],"11":[46,160],"13":[46,160]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/NodeDiff.vue":{"5":[46],"8":[46]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/SyncedWorkflowCanvas.vue":{"16":[46,160],"39":[46,160],"49":[46,160],"68":[46,160],"71":[46,160],"76":[46],"90":[46,160],"98":[46,160],"102":[46,160],"105":[46],"107":[46],"108":[46],"119":[46],"131":[46,160],"146":[46,160],"149":[46,160],"152":[46,160]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/WorkflowDiffAside.vue":{"8":[46],"14":[46],"19":[46],"26":[46],"38":[46],"42":[46],"48":[46]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/WorkflowDiffContent.vue":{"15":[46,160],"41":[46,160],"46":[46,160],"48":[46,160],"59":[46,160],"70":[46,160],"75":[46,160],"87":[46,160],"102":[46,160],"113":[46,160],"118":[46,160],"130":[46,160],"138":[46],"139":[46]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/WorkflowDiffEmptyState.vue":{"10":[46],"11":[46]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/WorkflowDiffModal.vue":{"21":[46],"48":[46],"62":[46],"71":[46],"91":[46],"106":[46],"107":[46],"108":[46],"109":[46],"110":[46],"112":[46],"120":[46],"123":[46],"127":[46],"139":[46],"142":[46],"157":[46],"167":[46],"173":[46],"178":[46],"180":[46],"185":[46],"190":[46],"196":[46],"201":[46],"203":[46],"206":[46]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/WorkflowDiffNodeItem.vue":{"18":[46],"19":[46],"30":[46],"31":[46]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/WorkflowDiffView.vue":{"32":[46,160],"62":[46],"66":[46],"80":[46,160],"81":[46,160],"100":[46,160],"101":[46,160],"107":[46],"118":[46,160],"126":[46],"137":[46],"147":[46,160],"165":[46],"168":[46,160],"189":[46,160],"194":[46,160],"196":[46,160],"203":[46,160],"214":[46],"220":[46],"230":[46],"241":[46],"249":[46],"262":[46],"264":[46],"335":[46],"338":[46],"341":[46],"344":[46],"347":[46]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/useViewportSync.ts":{"30":[46,160],"47":[46,160],"53":[46,160],"72":[46,160]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/useWorkflowDiff.ts":{"37":[46,160],"38":[46,160],"48":[46,160],"49":[46,160],"53":[46,160],"58":[46,160],"77":[46,160],"89":[46,160],"100":[46,160],"106":[46,160],"123":[46,160],"136":[46,160],"152":[46,160],"168":[46,160],"173":[46,160],"183":[46,160],"217":[46],"226":[46,160],"248":[46,160],"276":[46,160]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/useWorkflowDiffUI.ts":{"25":[46,160],"40":[46,160],"45":[46],"50":[46],"75":[46],"78":[46],"94":[46,160],"97":[46,160],"98":[46,160],"105":[46],"106":[46],"116":[46],"117":[46],"130":[46,160],"157":[46],"167":[46,160],"175":[46],"176":[46],"182":[46,160],"189":[46],"192":[46],"196":[46],"211":[46],"221":[46,160],"225":[46,160],"248":[46]},"packages/frontend/editor-ui/src/features/workflows/workflowHistory/components/WorkflowVersionFormModal.vue":{"27":[46],"41":[46],"43":[46],"47":[46],"61":[46],"65":[46],"69":[46],"74":[46],"84":[46],"96":[46],"97":[46],"99":[46]},"packages/import-package-request.dto.ts":{"42":[46],"80":[46]},"packages/modules/insights/frontend/src/insights.module.ts":{"5":[46],"18":[46],"19":[46],"35":[46]},"packages/modules/mcp/frontend/src/assets/client-icons/claude.svgcomponent":{"9":[46,123]},"packages/modules/mcp/frontend/src/assets/client-icons/cursor.svgcomponent":{"8":[46]},"packages/modules/mcp/frontend/src/assets/client-icons/mistral.svgcomponent":{"8":[46]},"packages/modules/mcp/frontend/src/assets/client-icons/openai.svgcomponent":{"11":[46]},"packages/modules/mcp/frontend/src/assets/client-icons/vscode.svgcomponent":{"8":[46]},"packages/modules/mcp/frontend/src/clients.utils.ts":{"38":[46],"41":[46],"54":[46],"62":[46],"79":[46],"81":[46],"91":[46],"102":[46]},"packages/modules/mcp/frontend/src/components/McpAccessToggle.vue":{"15":[46],"27":[46],"33":[46],"35":[46],"42":[46],"51":[46]},"packages/modules/mcp/frontend/src/components/McpClientLogoCards.vue":{"11":[46],"21":[46],"23":[46],"29":[46],"31":[46],"37":[46],"38":[46],"40":[46],"46":[46],"51":[46]},"packages/modules/mcp/frontend/src/mcp.api.ts":{"45":[46],"52":[46],"56":[46],"60":[46,123],"66":[46],"78":[46],"99":[46,123],"104":[46,123],"114":[46,123],"120":[46],"133":[46],"156":[46,123],"173":[46],"184":[46,123]},"packages/modules/type-availability-policies/frontend/src/components/RestrictedNodePanel.vue":{"20":[46,73],"26":[46,73],"29":[46,73],"35":[46,73],"37":[46,73],"44":[46],"45":[46,73],"54":[46],"55":[46,73]},"packages/modules/type-availability-policies/frontend/src/components/RestrictedNodePopover.vue":{"47":[46,73],"51":[46,73],"55":[46],"60":[46,73],"63":[46,73],"66":[46,73],"77":[46],"78":[46],"82":[46],"85":[46,73],"102":[46,73],"112":[46],"118":[46],"120":[46],"121":[46],"123":[46],"131":[46]},"packages/modules/type-availability-policies/frontend/src/components/RestrictedToolCallout.vue":{"15":[46],"19":[46],"20":[46],"26":[46],"31":[46],"32":[46]},"packages/modules/type-availability-policies/frontend/src/composables/useExclusiveOpen.ts":{"5":[46,73],"8":[46,73],"13":[46,73],"22":[46,73]},"packages/modules/type-availability-policies/frontend/src/policy-violations/PolicyViolationList.vue":{"9":[46],"32":[46],"40":[46],"46":[46],"53":[46],"66":[46],"70":[46],"72":[46],"77":[46],"88":[46],"93":[46],"104":[46],"106":[46],"108":[46]},"packages/modules/type-availability-policies/frontend/src/type-availability-policies.api.ts":{"5":[46,73],"12":[46,73]},"packages/modules/type-availability-policies/frontend/src/type-availability-policies.constants.ts":{"14":[46]},"packages/vite/expression-runtime-stub.ts":{"37":[46]},"packages/vite/node-fs-shim.ts":{"14":[46]},"packages/nodes-base/nodes/N8nTrigger/N8nTrigger.node.ts":{"63":[195],"86":[195]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/OpenTemplateItem.vue":{"14":[127],"23":[127]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/transport/SSETransport.ts":{"10":[12],"17":[12],"22":[12]},"packages/core/src/utils/hitl-callback-reference.ts":{"31":[134],"40":[134],"52":[134],"61":[134],"73":[134],"77":[134],"91":[134],"110":[134],"124":[134]},"packages/core/src/utils/signature-helpers.ts":{"9":[134],"21":[134],"28":[134],"43":[134]},"packages/workflow/src/safe-regex.ts":{"49":[134],"56":[134],"60":[134],"70":[134],"83":[134],"91":[134],"98":[134],"99":[134],"100":[134],"102":[134],"104":[134],"109":[134],"126":[134],"137":[134],"144":[134],"151":[134],"159":[134],"166":[134],"176":[134],"181":[134],"185":[134],"192":[134],"193":[134],"194":[134],"196":[134],"197":[134]},"packages/cli/src/modules/promotions.ee/promotions-git.utils.ts":{"20":[99],"25":[99],"33":[99],"54":[99],"55":[99],"61":[99],"91":[99],"96":[99],"106":[99]},"packages/cli/src/modules/source-control.ee/source-control-export.service.ee.ts":{"73":[99],"98":[99],"102":[99],"106":[99],"110":[99],"118":[99],"120":[99],"127":[99],"129":[99],"130":[99],"134":[99],"146":[99],"151":[99],"173":[99],"176":[99],"198":[99],"216":[99],"229":[99],"254":[99],"270":[99],"299":[99],"314":[99],"315":[99],"348":[99],"382":[99],"387":[99],"423":[99],"451":[99],"457":[99],"465":[99],"483":[99],"489":[99],"525":[99],"528":[99],"556":[99],"578":[99],"582":[99],"589":[99],"603":[99],"619":[99]},"packages/cli/src/modules/source-control.ee/source-control-git.service.ee.ts":{"48":[99],"58":[99],"81":[99],"118":[99],"168":[99],"172":[99],"187":[99],"194":[99],"209":[99],"265":[99],"280":[99],"291":[99],"322":[99],"330":[99],"339":[99],"340":[99],"354":[99],"365":[99],"376":[99],"388":[99],"400":[99],"414":[99],"468":[99],"471":[99],"472":[99],"490":[99],"504":[99],"514":[99],"535":[99],"545":[99],"562":[99],"576":[99],"600":[99],"607":[99],"615":[99]},"packages/cli/src/modules/source-control.ee/source-control-helper.ee.ts":{"42":[99],"66":[99],"74":[99],"97":[99],"124":[99],"158":[99],"162":[99],"166":[99],"173":[99],"177":[99],"181":[99],"185":[99],"189":[99],"207":[99],"213":[99],"226":[99],"246":[99],"258":[99],"264":[99],"281":[99],"287":[99],"291":[99],"300":[99],"304":[99],"305":[99],"309":[99],"317":[99],"321":[99],"323":[99],"327":[99],"334":[99],"336":[99],"338":[99],"340":[99],"342":[99],"346":[99],"353":[99],"354":[99],"356":[99],"358":[99],"368":[99],"385":[99],"422":[99],"426":[99],"448":[99],"456":[99],"457":[99],"459":[99],"476":[99],"496":[99],"505":[99],"509":[99],"524":[99]},"packages/cli/src/modules/source-control.ee/source-control-preferences.service.ee.ts":{"35":[99],"48":[99],"56":[99],"66":[99],"74":[99],"84":[99],"92":[99],"100":[99],"112":[99],"121":[99],"136":[99],"144":[99],"170":[99],"184":[99],"198":[99],"211":[99],"239":[99],"243":[99],"247":[99],"251":[99],"255":[99],"259":[99],"278":[99],"330":[99],"338":[99]},"packages/cli/src/modules/source-control.ee/source-control.controller.ee.ts":{"31":[99],"40":[99],"67":[99],"132":[99],"177":[99],"187":[99],"196":[99],"227":[99],"243":[99],"252":[99],"269":[99],"286":[99],"300":[99]},"packages/cli/src/modules/source-control.ee/source-control.service.ee.ts":{"72":[99],"89":[99],"104":[99],"113":[99],"126":[99],"149":[99],"158":[99],"188":[99],"219":[99],"268":[99],"277":[99],"290":[99],"291":[99],"294":[99],"310":[99],"320":[99],"331":[99],"348":[99],"362":[99],"370":[99],"376":[99],"398":[99],"417":[99],"418":[99],"437":[99],"440":[99],"507":[99],"532":[99],"537":[99],"541":[99],"555":[99],"570":[99],"594":[99],"623":[99],"728":[99],"729":[99],"735":[99]},"localhost-44887/assets/index-Dv_brJ4-.js":{"3":[99]},"localhost-44887/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[99],"9":[99],"10":[99],"19":[99],"23":[99],"29":[99],"33":[99],"34":[99]},"packages/frontend/editor-ui/src/app/components/layouts/EmptyStateLayout.vue":{"19":[40,60,99],"46":[40,60,99],"50":[40,60],"57":[40,60,99],"77":[40,60,99],"85":[40,60,99],"111":[40,60,99],"165":[40,60,99],"174":[40,60,99],"185":[40,60,99],"194":[40,60,99]},"packages/frontend/editor-ui/src/experiments/surfaceMcpToNewCloudUsers/composables/useSurfaceMcpEmptyState.ts":{"15":[40,60,99],"25":[40,60,99],"43":[40,60,99],"48":[40,60,99],"65":[40,60,99]},"packages/frontend/editor-ui/src/experiments/surfaceMcpToNewCloudUsers/composables/useSurfaceMcpToNewCloudUsersEligibility.ts":{"7":[40,60,99],"13":[40,60,99]},"packages/frontend/editor-ui/src/experiments/surfaceMcpToNewCloudUsers/stores/surfaceMcpToNewCloudUsers.store.ts":{"22":[40,60,99]},"packages/frontend/editor-ui/src/features/integrations/sourceControl.ee/views/SettingsSourceControl.vue":{"47":[99],"48":[99],"119":[99],"137":[99],"148":[99],"157":[99],"178":[99],"182":[99],"287":[99],"288":[99],"338":[99],"348":[99],"352":[99],"429":[99],"447":[99],"452":[99],"453":[99],"470":[99],"492":[99],"499":[99],"518":[99],"520":[99],"539":[99]},"packages/@n8n/db/src/utils/escape-like.ts":{"5":[60,182]},"packages/nodes-base/nodes/Notion/NotionTrigger.node.ts":{"31":[172],"39":[172],"50":[172],"281":[172],"354":[172],"363":[172],"366":[172]},"localhost-38277/assets/index-Dv_brJ4-.js":{"3":[60]},"localhost-38277/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[60],"9":[60],"10":[60],"19":[60],"23":[60],"29":[60],"33":[60],"34":[60]},"packages/frontend/editor-ui/src/app/views/DemoDiffView.vue":{"20":[160],"27":[160],"36":[160],"64":[160]},"packages/frontend/editor-ui/src/features/execution/executions/composables/useExecutionDebugging.ts":{"41":[169],"45":[169],"86":[169],"87":[169],"94":[169],"104":[169],"121":[169],"140":[169],"146":[169],"156":[169],"160":[169],"204":[169]},"packages/cli/src/modules/provisioning.ee/claims-context.builder.ts":{"3":[40],"17":[40],"29":[40]},"packages/cli/src/modules/provisioning.ee/role-mapping-rule.service.ee.ts":{"47":[40],"54":[40],"81":[40],"85":[40],"124":[40],"162":[40],"180":[40],"214":[40],"273":[40],"309":[40],"315":[40],"348":[40],"354":[40],"373":[40],"376":[40],"393":[40],"403":[40],"405":[40],"408":[40],"424":[40],"431":[40]},"packages/cli/src/modules/sso-oidc/oidc.controller.ee.ts":{"32":[40],"45":[40],"56":[40],"74":[40],"96":[40],"119":[40],"232":[40]},"packages/cli/src/modules/sso-oidc/oidc.service.ee.ts":{"73":[40],"92":[40],"106":[40],"115":[40],"121":[40],"125":[40],"137":[40],"152":[40],"193":[40],"201":[40],"234":[40],"240":[40],"286":[40],"384":[40],"417":[40],"426":[40],"444":[40],"470":[40],"479":[40],"519":[40],"585":[40],"586":[40],"598":[40],"623":[40],"634":[40],"644":[40],"675":[40],"708":[40],"718":[40],"774":[40],"798":[40],"832":[40]},"localhost-39029/assets/index-Dv_brJ4-.js":{"3":[40]},"localhost-39029/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[40],"9":[40],"10":[40],"19":[40],"23":[40],"29":[40],"33":[40],"34":[40]},"packages/frontend/editor-ui/src/app/utils/formatters/textFormatter.ts":{"8":[58]},"localhost-36089/assets/index-Dv_brJ4-.js":{"3":[43,54,135]},"localhost-36089/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[43,54,135],"9":[43,54,135],"10":[43,54,135],"19":[43,54,135],"23":[43,54,135],"29":[43,54,135],"33":[43,54,135],"34":[43,54,135]},"localhost-36089/assets/verified-Dido3Ow4.js":{"8":[43]},"localhost-39045/assets/index-Dv_brJ4-.js":{"3":[22]},"localhost-39045/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[22],"9":[22],"10":[22],"19":[22],"23":[22],"29":[22],"33":[22],"34":[22]},"packages/cli/src/modules/type-availability-policies/available-types.controller.ts":{"18":[73],"40":[73],"48":[73]},"packages/cli/src/modules/type-availability-policies/type-availability-policy-project.controller.ts":{"22":[73],"27":[73],"41":[73]},"packages/workflow/src/credential-only-nodes.ts":{"14":[73],"18":[73],"23":[73]},"localhost-35619/assets/index-Dv_brJ4-.js":{"3":[73]},"localhost-35619/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[73],"9":[73],"10":[73],"19":[73],"23":[73],"29":[73],"33":[73],"34":[73]},"localhost-35619/assets/verified-Dido3Ow4.js":{"8":[73]},"packages/@n8n/ai-utilities/src/utils/embeddings-input-validation.ts":{"13":[0,3],"32":[0,3],"40":[0,3]},"packages/@n8n/ai-utilities/src/utils/loaders/n8n-pdf-loader.ts":{"21":[0],"26":[0],"43":[0],"57":[0],"73":[0],"82":[0]},"packages/@n8n/ai-utilities/src/utils/n8n-binary-loader.ts":{"33":[0],"40":[0],"54":[0],"60":[0],"86":[0],"104":[0],"151":[0],"158":[0],"166":[0],"174":[0],"198":[0],"227":[0]},"packages/@n8n/ai-utilities/src/utils/vector-store/MemoryManager/MemoryCalculator.ts":{"21":[0,3],"61":[0,3]},"packages/@n8n/ai-utilities/src/utils/vector-store/MemoryManager/MemoryVectorStoreManager.ts":{"40":[0,3],"69":[0,3],"80":[0,3],"91":[0,3],"106":[0,3],"114":[0,3],"131":[0,3],"138":[0,3],"163":[0,3],"175":[0,3],"182":[0,3],"190":[0,3],"211":[0,3],"268":[0,3]},"packages/@n8n/ai-utilities/src/utils/vector-store/MemoryManager/StoreCleanupService.ts":{"16":[0,3],"31":[0,3],"45":[0,3],"79":[0,3],"117":[0,3],"120":[0,3],"153":[0,3]},"packages/@n8n/ai-utilities/src/utils/vector-store/MemoryManager/config.ts":{"10":[0,3],"38":[0,3],"47":[0,3]},"packages/@n8n/ai-utilities/src/utils/vector-store/createVectorStoreNode/operations/insertOperation.ts":{"17":[0,3]},"packages/@n8n/ai-utilities/src/utils/vector-store/processDocuments.ts":{"7":[0,3],"19":[0,3],"28":[0,3],"41":[0,3]},"packages/@n8n/nodes-langchain/nodes/code/Code.node.ts":{"72":[0,3,8],"127":[0,3,8],"131":[0,3,8],"141":[0,3,8],"151":[0,3,8],"155":[0,3,8],"156":[0,3,8],"157":[0,3,8],"163":[0,3,8],"168":[0,3,8]},"packages/@n8n/nodes-langchain/nodes/document_loaders/DocumentDefaultDataLoader/DocumentDefaultDataLoader.node.ts":{"21":[0,3],"38":[0,3],"329":[0,3]},"packages/@n8n/nodes-langchain/nodes/text_splitters/TextSplitterCharacterTextSplitter/TextSplitterCharacterTextSplitter.node.ts":{"13":[0,3],"68":[0,3]},"packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreInMemory/VectorStoreInMemory.node.ts":{"37":[0,3,8],"132":[0,3,8],"143":[0,3,8],"152":[0,3,8],"161":[0,3,8],"186":[0,3,8],"192":[0,3,8]},"packages/nodes-base/nodes/Code/ExecutionError.ts":{"14":[0,3,8],"30":[0,3,8],"38":[0,3,8],"39":[0,3,8],"59":[0,3,8],"75":[0,3,8]},"packages/nodes-base/nodes/Code/JavaScriptSandbox.ts":{"30":[0,3,8],"52":[0,3,8],"55":[0,3,8],"65":[0,3,8],"85":[0,3,8],"93":[0,3,8],"103":[0,3,8]},"packages/nodes-base/nodes/Code/Sandbox.ts":{"24":[0,3,8],"46":[0,3,8],"59":[0,3,8],"71":[0,3,8]},"packages/@n8n/scheduler/src/core/lifecycle/loop.ts":{"59":[64],"61":[64],"62":[64],"65":[64],"105":[64],"121":[64],"129":[64],"137":[64],"146":[64],"150":[64],"156":[64],"162":[64],"167":[64],"172":[64],"188":[64]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/character-text-splitter.svg":{"11":[0,3]},"packages/nodes-base/nodes/Microsoft/GenericFunctions.ts":{"10":[29],"65":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/MicrosoftOutlook.node.ts":{"8":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v1/GenericFunctions.ts":{"12":[29],"57":[29],"90":[29],"123":[29],"131":[29],"155":[29],"157":[29],"161":[29],"165":[29],"176":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v1/MicrosoftOutlookV1.node.ts":{"108":[29],"119":[29],"138":[29],"264":[29],"312":[29],"315":[29],"372":[29],"589":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/MicrosoftOutlookV2.node.ts":{"16":[29],"27":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/calendar/create.operation.ts":{"94":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/calendar/delete.operation.ts":{"19":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/calendar/get.operation.ts":{"19":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/calendar/getAll.operation.ts":{"38":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/calendar/update.operation.ts":{"89":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/contact/create.operation.ts":{"42":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/contact/delete.operation.ts":{"19":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/contact/get.operation.ts":{"55":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/contact/getAll.operation.ts":{"81":[29],"106":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/contact/update.operation.ts":{"30":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/draft/create.operation.ts":{"206":[29],"223":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/draft/delete.operation.ts":{"19":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/draft/get.operation.ts":{"85":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/draft/send.operation.ts":{"29":[29],"36":[29],"37":[29],"41":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/draft/update.operation.ts":{"184":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/event/create.operation.ts":{"180":[29],"222":[29],"225":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/event/delete.operation.ts":{"20":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/event/get.operation.ts":{"56":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/event/getAll.operation.ts":{"125":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/event/update.operation.ts":{"217":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/folder/create.operation.ts":{"38":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/folder/delete.operation.ts":{"20":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/folder/get.operation.ts":{"39":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/folder/getAll.operation.ts":{"68":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/folder/update.operation.ts":{"30":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/folderMessage/getAll.operation.ts":{"228":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/message/delete.operation.ts":{"19":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/message/get.operation.ts":{"115":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/message/getAll.operation.ts":{"244":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/message/move.operation.ts":{"22":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/message/reply.operation.ts":{"222":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/message/send.operation.ts":{"209":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/message/sendAndWait.operation.ts":{"31":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/message/update.operation.ts":{"173":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/messageAttachment/add.operation.ts":{"54":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/messageAttachment/download.operation.ts":{"30":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/messageAttachment/get.operation.ts":{"62":[29],"79":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/messageAttachment/getAll.operation.ts":{"62":[29],"77":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/router.ts":{"16":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/helpers/utils.ts":{"65":[29],"107":[29],"147":[29],"149":[29],"157":[29],"183":[29],"185":[29],"207":[29],"208":[29],"216":[29],"224":[29],"242":[29],"258":[29],"267":[29],"279":[29],"285":[29],"286":[29],"345":[29],"370":[29],"374":[29],"378":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/methods/listSearch.ts":{"11":[29],"45":[29],"55":[29],"63":[29],"71":[29],"104":[29],"115":[29],"147":[29],"158":[29],"201":[29],"212":[29],"241":[29],"247":[29],"258":[29],"295":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/methods/loadOptions.ts":{"8":[29],"28":[29],"48":[29]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/transport/index.ts":{"27":[29],"48":[29],"72":[29],"150":[29],"184":[29],"237":[29],"273":[29],"291":[29]},"localhost-35731/assets/index-Dv_brJ4-.js":{"3":[29,102,15]},"localhost-35731/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[29,102,15],"9":[29,102,15],"10":[29,102,15],"19":[29,102,15],"23":[29,102,15],"29":[29,102,15],"33":[29,102,15],"34":[29,102,15]},"localhost-35731/assets/verified-Dido3Ow4.js":{"8":[29,15]},"localhost-39021/assets/index-Dv_brJ4-.js":{"3":[19,116,118,50,122]},"localhost-39021/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[19,116,118,50,122],"9":[19,116,118,50,122],"10":[19,116,118,50,122],"19":[19,116,118,50,122],"23":[19,116,118,50,122],"29":[19,116,118,50,122],"33":[19,116,118,50,122],"34":[19,116,118,50,122]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/AgentSection.vue":{"17":[116],"24":[116],"27":[116],"35":[116],"60":[116],"68":[116],"74":[116],"75":[116],"76":[116],"78":[116]},"packages/@n8n/syslog-client/src/client.ts":{"78":[67],"129":[67],"147":[67],"148":[67],"162":[67],"185":[67],"197":[67],"205":[67],"214":[67],"233":[67],"253":[67],"279":[67],"293":[67],"310":[67],"322":[67],"337":[67],"342":[67],"350":[67],"365":[67],"377":[67],"391":[67],"420":[67],"438":[67],"453":[67],"468":[67],"475":[67],"483":[67],"501":[67]},"packages/@n8n/syslog-client/src/factory.ts":{"25":[67]},"packages/@n8n/syslog-client/src/index.ts":{"13":[67]},"packages/@n8n/syslog-client/src/schemas.ts":{"9":[67],"10":[67],"11":[67]},"packages/@n8n/syslog-client/src/utils.ts":{"7":[67],"15":[67],"37":[67],"69":[67]},"packages/cli/src/modules/log-streaming.ee/destinations/message-event-bus-destination-syslog.ee.ts":{"20":[67],"48":[67],"80":[67],"85":[67],"102":[67],"122":[67],"136":[67],"150":[67],"154":[67]},"localhost-42705/assets/index-Dv_brJ4-.js":{"3":[153]},"localhost-42705/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[153],"9":[153],"10":[153],"19":[153],"23":[153],"29":[153],"33":[153],"34":[153]},"packages/@n8n/nodes-langchain/nodes/output_parser/OutputParserAutofixing/OutputParserAutofixing.node.ts":{"19":[8],"102":[8]},"packages/@n8n/nodes-langchain/nodes/tools/ToolVectorStore/ToolVectorStore.node.ts":{"17":[8],"51":[8],"140":[8],"148":[8]},"localhost-38249/assets/index-Dv_brJ4-.js":{"3":[5]},"localhost-38249/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[5],"9":[5],"10":[5],"19":[5],"23":[5],"29":[5],"33":[5],"34":[5]},"packages/frontend/editor-ui/src/features/ai/components/CredentialSelectorModal.vue":{"36":[5],"37":[5],"46":[5],"108":[5],"116":[5],"120":[5],"123":[5],"147":[5],"150":[5]},"packages/nodes-base/nodes/Pipedrive/PipedriveTrigger.node.ts":{"16":[9],"280":[9],"314":[9],"362":[9],"386":[9]},"packages/nodes-base/nodes/Pipedrive/v1/GenericFunctions.ts":{"31":[9,177],"103":[9,177],"142":[9,177],"187":[9,177],"195":[9,177],"210":[9,177],"230":[9,177],"278":[9,177],"292":[9,177],"293":[9,177],"302":[9,177],"305":[9,177]},"localhost-46791/assets/index-Dv_brJ4-.js":{"3":[9,78]},"localhost-46791/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[9,78],"9":[9,78],"10":[9,78],"19":[9,78],"23":[9,78],"29":[9,78],"33":[9,78],"34":[9,78]},"localhost-46791/assets/verified-Dido3Ow4.js":{"8":[9]},"packages/cli/src/push/origin-validator.ts":{"16":[61],"26":[61],"43":[61],"111":[61],"145":[61],"166":[61],"177":[61],"187":[61],"199":[61],"239":[61]},"packages/cli/src/push/sse.push.ts":{"11":[61],"32":[61],"42":[61],"46":[61],"52":[61]},"packages/cli/src/services/rate-limit.service.ts":{"31":[61],"45":[61],"56":[61],"58":[61],"65":[61],"69":[61],"70":[61],"77":[61],"95":[61]},"localhost-43851/assets/index-Dv_brJ4-.js":{"3":[61]},"localhost-43851/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[61],"9":[61],"10":[61],"19":[61],"23":[61],"29":[61],"33":[61],"34":[61]},"packages/@n8n/db/src/repositories/workflow-review-activity-comment.repository.ts":{"10":[74],"14":[74]},"packages/@n8n/db/src/repositories/workflow-review-activity.repository.ts":{"46":[74],"50":[74],"65":[74],"87":[74],"99":[74],"114":[74]},"packages/@n8n/db/src/repositories/workflow-review-inbox.repository.ts":{"54":[74],"69":[74],"81":[74],"99":[74],"150":[74],"181":[74],"185":[74],"207":[74],"220":[74],"221":[74]},"packages/@n8n/db/src/repositories/workflow-review-request-author.repository.ts":{"10":[74],"14":[74],"30":[74],"42":[74],"55":[74],"67":[74],"77":[74]},"packages/@n8n/db/src/repositories/workflow-review-request-reviewer.repository.ts":{"10":[74],"15":[74],"27":[74],"37":[74],"50":[74],"62":[74],"72":[74]},"packages/cli/src/modules/workflow-reviews.ee/workflow-review-activity.service.ts":{"29":[74],"41":[74],"64":[74],"84":[74],"123":[74],"127":[74],"129":[74],"133":[74],"138":[74],"141":[74],"147":[74],"150":[74],"158":[74]},"packages/cli/src/modules/workflow-reviews.ee/workflow-review-authorization.service.ts":{"50":[74],"68":[74],"76":[74],"80":[74],"95":[74],"122":[74],"145":[74],"175":[74],"199":[74],"209":[74],"216":[74],"217":[74],"220":[74],"239":[74],"244":[74],"253":[74],"269":[74]},"packages/cli/src/modules/workflow-reviews.ee/workflow-review-decision-policy.ts":{"32":[74]},"packages/cli/src/modules/workflow-reviews.ee/workflow-review-inbox.service.ts":{"40":[74],"49":[74],"72":[74],"78":[74],"90":[74],"97":[74],"110":[74],"138":[74],"173":[74],"185":[74],"201":[74],"205":[74],"222":[74],"240":[74]},"packages/cli/src/modules/workflow-reviews.ee/workflow-review-participant.resolver.ts":{"31":[74],"42":[74],"43":[74],"53":[74],"54":[74],"55":[74],"65":[74],"66":[74],"69":[74],"80":[74],"87":[74]},"packages/cli/src/modules/workflow-reviews.ee/workflow-review-request-decision.service.ts":{"42":[74],"61":[74],"89":[74],"95":[74],"141":[74],"173":[74],"216":[74],"281":[74],"317":[74],"347":[74],"358":[74]},"packages/cli/src/modules/workflow-reviews.ee/workflow-review-request-mutation-guard.service.ts":{"19":[74],"27":[74],"33":[74]},"packages/cli/src/modules/workflow-reviews.ee/workflow-review-request-status.service.ts":{"24":[74],"32":[74],"53":[74],"62":[74],"72":[74],"86":[74],"91":[74],"103":[74],"106":[74]},"packages/cli/src/modules/workflow-reviews.ee/workflow-review-request-submission.service.ts":{"39":[74],"46":[74],"65":[74],"78":[74],"79":[74],"82":[74],"110":[74],"129":[74],"144":[74],"190":[74],"193":[74],"202":[74],"285":[74],"304":[74],"337":[74],"362":[74],"378":[74]},"packages/cli/src/modules/workflow-reviews.ee/workflow-review-requests.controller.ts":{"28":[74],"38":[74],"49":[74],"59":[74],"71":[74],"86":[74],"102":[74],"112":[74],"121":[74],"136":[74],"157":[74]},"packages/cli/src/modules/workflow-reviews.ee/workflow-review.mapper.ts":{"26":[74],"40":[74],"58":[74],"79":[74],"99":[74]},"packages/cli/src/services/workflow-review-policy.service.ts":{"12":[74],"14":[74],"30":[74]},"packages/nodes-base/nodes/Pipedrive/Pipedrive.node.ts":{"8":[177]},"packages/nodes-base/nodes/Pipedrive/v1/PipedriveV1.node.ts":{"37":[177],"2256":[177],"2393":[177],"3809":[177],"3820":[177],"3834":[177],"3862":[177],"3876":[177],"3900":[177],"3904":[177],"3908":[177],"3912":[177],"3916":[177],"3926":[177],"3930":[177],"3944":[177],"3962":[177],"3978":[177],"3994":[177],"4023":[177],"4053":[177],"4058":[177],"4063":[177],"4068":[177],"4073":[177],"4103":[177],"4949":[177]},"packages/nodes-base/nodes/Pipedrive/v2/PipedriveV2.node.ts":{"16":[177],"28":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/activity/create.operation.ts":{"119":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/activity/delete.operation.ts":{"31":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/activity/get.operation.ts":{"34":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/activity/getAll.operation.ts":{"126":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/activity/update.operation.ts":{"140":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/deal/create.operation.ts":{"222":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/deal/delete.operation.ts":{"31":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/deal/duplicate.operation.ts":{"31":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/deal/get.operation.ts":{"34":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/deal/getAll.operation.ts":{"124":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/deal/search.operation.ts":{"138":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/deal/update.operation.ts":{"179":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/dealProduct/add.operation.ts":{"117":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/dealProduct/getAll.operation.ts":{"54":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/dealProduct/remove.operation.ts":{"40":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/dealProduct/update.operation.ts":{"116":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/file/create.operation.ts":{"87":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/file/delete.operation.ts":{"31":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/file/download.operation.ts":{"34":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/file/get.operation.ts":{"31":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/file/update.operation.ts":{"54":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/lead/create.operation.ts":{"148":[177],"175":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/lead/delete.operation.ts":{"31":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/lead/get.operation.ts":{"31":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/lead/getAll.operation.ts":{"100":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/lead/update.operation.ts":{"105":[177],"132":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/note/create.operation.ts":{"96":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/note/delete.operation.ts":{"31":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/note/get.operation.ts":{"31":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/note/getAll.operation.ts":{"143":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/note/update.operation.ts":{"103":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/organization/create.operation.ts":{"71":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/organization/delete.operation.ts":{"31":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/organization/get.operation.ts":{"34":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/organization/getAll.operation.ts":{"81":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/organization/search.operation.ts":{"98":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/organization/update.operation.ts":{"78":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/person/create.operation.ts":{"164":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/person/delete.operation.ts":{"31":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/person/get.operation.ts":{"34":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/person/getAll.operation.ts":{"80":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/person/search.operation.ts":{"117":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/person/update.operation.ts":{"171":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/product/create.operation.ts":{"126":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/product/delete.operation.ts":{"31":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/product/get.operation.ts":{"34":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/product/getAll.operation.ts":{"53":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/product/search.operation.ts":{"101":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/product/update.operation.ts":{"133":[177]},"packages/nodes-base/nodes/Pipedrive/v2/actions/router.ts":{"15":[177]},"packages/nodes-base/nodes/Pipedrive/v2/helpers/customFields.ts":{"24":[177],"36":[177],"58":[177],"59":[177],"61":[177],"69":[177],"97":[177],"130":[177],"142":[177],"143":[177]},"packages/nodes-base/nodes/Pipedrive/v2/helpers/fields.ts":{"10":[177]},"packages/nodes-base/nodes/Pipedrive/v2/helpers/index.ts":{"3":[177],"7":[177]},"packages/nodes-base/nodes/Pipedrive/v2/helpers/searchResponse.ts":{"9":[177],"14":[177],"25":[177]},"packages/nodes-base/nodes/Pipedrive/v2/helpers/typeCoercion.ts":{"4":[177],"18":[177],"32":[177],"55":[177]},"packages/nodes-base/nodes/Pipedrive/v2/methods/loadOptions.ts":{"9":[177],"34":[177],"65":[177],"83":[177],"117":[177],"120":[177],"127":[177],"130":[177],"137":[177],"143":[177],"150":[177],"162":[177],"187":[177],"193":[177],"203":[177],"206":[177],"213":[177],"223":[177],"226":[177]},"packages/nodes-base/nodes/Pipedrive/v2/transport/pipedrive.api.ts":{"30":[177],"96":[177],"126":[177],"170":[177],"229":[177],"232":[177]},"packages/@n8n/ai-utilities/src/utils/n8n-json-loader.ts":{"15":[3],"21":[3],"35":[3],"45":[3],"81":[3]},"packages/@n8n/nodes-langchain/nodes/chains/ChainRetrievalQA/ChainRetrievalQa.node.ts":{"21":[3],"186":[3],"202":[3],"208":[3]},"packages/@n8n/nodes-langchain/nodes/chains/ChainRetrievalQA/processItem.ts":{"19":[3]},"packages/@n8n/nodes-langchain/nodes/retrievers/RetrieverVectorStore/RetrieverVectorStore.node.ts":{"14":[3],"73":[3]},"localhost-39033/assets/index-Dv_brJ4-.js":{"3":[3]},"localhost-39033/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[3],"9":[3],"10":[3],"19":[3],"23":[3],"29":[3],"33":[3],"34":[3]},"packages/@n8n/backend-services/src/services/project-scope.service.ts":{"13":[123],"18":[123],"24":[123]},"packages/@n8n/db/src/utils/apply-workflow-boolean-setting-filter.ts":{"12":[123]},"packages/cli/src/modules/agents/agent-mcp-access.controller.ts":{"19":[123],"22":[123],"27":[123]},"packages/cli/src/modules/agents/agent-mcp-access.service.ts":{"29":[123],"39":[123],"54":[123],"60":[123],"76":[123],"78":[123],"80":[123],"110":[123],"111":[123],"117":[123]},"packages/cli/src/modules/oauth-server/database/repositories/oauth-user-consent.repository.ts":{"42":[123],"53":[123],"96":[123],"114":[123]},"packages/cli/src/modules/oauth-server/oauth-clients.controller.ts":{"21":[123],"32":[123],"49":[123],"78":[123],"90":[123]},"packages/modules/mcp/frontend/src/SettingsMCPView.vue":{"56":[123],"58":[123],"64":[123],"65":[123],"88":[123],"100":[123],"111":[123],"120":[123],"129":[123],"138":[123],"185":[123],"195":[123],"198":[123],"205":[123],"210":[123],"242":[123],"266":[123],"318":[123],"324":[123],"337":[123],"352":[123],"360":[123],"388":[123],"401":[123],"409":[123],"434":[123]},"packages/modules/mcp/frontend/src/components/ConnectionParameter.vue":{"16":[123],"33":[123],"72":[123]},"packages/modules/mcp/frontend/src/components/McpAllowedCallbackUrlsDialog.vue":{"24":[123],"44":[123],"60":[123],"111":[123]},"packages/modules/mcp/frontend/src/components/McpConnectClientDialog.vue":{"24":[123],"31":[123],"32":[123],"33":[123],"36":[123],"42":[123],"49":[123],"55":[123],"123":[123],"132":[123],"137":[123],"142":[123],"168":[123],"177":[123],"278":[123],"285":[123],"301":[123]},"packages/modules/mcp/frontend/src/components/McpStatusControl.vue":{"6":[123],"20":[123],"28":[123],"37":[123],"49":[123]},"packages/modules/mcp/frontend/src/components/OAuthClientDetailsModal.vue":{"22":[123],"61":[123]},"packages/modules/mcp/frontend/src/components/RevokeOAuthClientConfirmModal.vue":{"7":[123],"23":[123],"31":[123],"43":[123]},"packages/modules/mcp/frontend/src/mcp.clients.catalog.ts":{"42":[123]}}} \ No newline at end of file +{"specs":["tests/e2e/a11y/a11y-landmark-structure.spec.ts","tests/e2e/agents/agent-builder-write-lock.spec.ts","tests/e2e/agents/agent-preview-layout.spec.ts","tests/e2e/agents/agent-sessions.spec.ts","tests/e2e/ai/ai-2505-pdf-embed.spec.ts","tests/e2e/ai/assistant-basic.spec.ts","tests/e2e/ai/assistant-code-help.spec.ts","tests/e2e/ai/assistant-credential-help.spec.ts","tests/e2e/ai/assistant-support-chat.spec.ts","tests/e2e/ai/chat-session.spec.ts","tests/e2e/ai/langchain-vectorstores.spec.ts","tests/e2e/ai/workflow-builder.spec.ts","tests/e2e/api/form-endpoint-isolation.spec.ts","tests/e2e/api/publish-unreachable-node.spec.ts","tests/e2e/api/wait-form-resume.spec.ts","tests/e2e/api/webhook-isolate-skip.spec.ts","tests/e2e/auth/authenticated.spec.ts","tests/e2e/building-blocks/credentials.spec.ts","tests/e2e/chat-hub/chat-hub-attachment.spec.ts","tests/e2e/chat-hub/chat-hub-chat-user.spec.ts","tests/e2e/chat-hub/chat-hub-tools.spec.ts","tests/e2e/chat-hub/chat-hub-workflow-agent.spec.ts","tests/e2e/cloud/cloud.spec.ts","tests/e2e/credentials/crud.spec.ts","tests/e2e/data-tables/details.spec.ts","tests/e2e/data-tables/tables.spec.ts","tests/e2e/dynamic-credentials/external-user-trigger.spec.ts","tests/e2e/dynamic-credentials/form-trigger-end-user-credential-shell.spec.ts","tests/e2e/instance-ai/instance-ai-artifacts.spec.ts","tests/e2e/instance-ai/instance-ai-attachments.spec.ts","tests/e2e/instance-ai/instance-ai-background-lifecycle.spec.ts","tests/e2e/instance-ai/instance-ai-mentions.spec.ts","tests/e2e/instance-ai/instance-ai-multimain.spec.ts","tests/e2e/instance-ai/instance-ai-onboarding.spec.ts","tests/e2e/instance-ai/instance-ai-remediation-guard.spec.ts","tests/e2e/instance-ai/instance-ai-workflow-execution.spec.ts","tests/e2e/instance-ai/thread-launcher.spec.ts","tests/e2e/mcp-registry/mcp-registry.spec.ts","tests/e2e/mcp/mcp-service.spec.ts","tests/e2e/nodes/community-nodes.spec.ts","tests/e2e/nodes/email-send-node.spec.ts","tests/e2e/nodes/http-request-node.spec.ts","tests/e2e/nodes/n8n-trigger.spec.ts","tests/e2e/projects/folders-basic.spec.ts","tests/e2e/projects/projects-move-resources.spec.ts","tests/e2e/projects/projects.spec.ts","tests/e2e/push/sse-push-backend.spec.ts","tests/e2e/redaction-enforcement/redaction-enforcement.spec.ts","tests/e2e/regression/ADO-4462-template-setup-experiment.spec.ts","tests/e2e/scheduling/poll-trigger-backoff.spec.ts","tests/e2e/scheduling/poll-trigger-cursor-unmigrated.spec.ts","tests/e2e/scheduling/poll-trigger-durable.spec.ts","tests/e2e/scheduling/poll-trigger-misfire-skip.spec.ts","tests/e2e/scheduling/schedule-trigger-durable.spec.ts","tests/e2e/scheduling/schedule-trigger-legacy.spec.ts","tests/e2e/scheduling/schedule-trigger-misfire-coalesce.spec.ts","tests/e2e/scheduling/schedule-trigger-timezone.spec.ts","tests/e2e/sentry/sentry-baseline.spec.ts","tests/e2e/settings/community-nodes/node-api-version-guard.spec.ts","tests/e2e/settings/environments/source-control.spec.ts","tests/e2e/settings/external-secrets/secret-providers-connections-ui.spec.ts","tests/e2e/settings/log-streaming/log-streaming-observability.spec.ts","tests/e2e/settings/log-streaming/log-streaming.spec.ts","tests/e2e/settings/personal/two-factor-authentication.spec.ts","tests/e2e/type-availability-policies/credential-type-policy-worker.spec.ts","tests/e2e/type-availability-policies/credential-type-policy.spec.ts","tests/e2e/type-availability-policies/node-type-policy.spec.ts","tests/e2e/webhooks/webhook-trigger-oauth2.spec.ts","tests/e2e/workflow-reviews/review-round-trip.spec.ts","tests/e2e/workflows/checklist/production-checklist.spec.ts","tests/e2e/workflows/editor/canvas/actions.spec.ts","tests/e2e/workflows/editor/canvas/node-groups.spec.ts","tests/e2e/workflows/editor/execution/debug.spec.ts","tests/e2e/workflows/editor/execution/executions-list-infinite-scroll.spec.ts","tests/e2e/workflows/editor/expressions/env-access.spec.ts","tests/e2e/workflows/editor/expressions/modal.spec.ts","tests/e2e/workflows/editor/expressions/quickjs-engine.spec.ts","tests/e2e/workflows/editor/ndv/ndv-parameters.spec.ts","tests/e2e/workflows/editor/ndv/resource-locator.spec.ts","tests/e2e/workflows/editor/workflow-actions/archive.spec.ts","tests/e2e/workflows/editor/workflow-actions/publish.spec.ts","tests/e2e/workflows/list/workflows.spec.ts","tests/e2e/workflows/templates/credentials-setup.spec.ts","tests/e2e/agents/background-workflow-stop.spec.ts","tests/e2e/ai/langchain-agents.spec.ts","tests/e2e/ai/langchain-chains.spec.ts","tests/e2e/ai/rag-callout.spec.ts","tests/e2e/api/discovery.spec.ts","tests/e2e/app-config/versions.spec.ts","tests/e2e/auth/oidc.spec.ts","tests/e2e/auth/token-exchange.spec.ts","tests/e2e/credentials/global.spec.ts","tests/e2e/instance-ai/instance-ai-chat-basics.spec.ts","tests/e2e/projects/folders-advanced.spec.ts","tests/e2e/scheduling/poll-trigger-legacy.spec.ts","tests/e2e/settings/external-secrets/vault.spec.ts","tests/e2e/workflows/editor/canvas/canvas-nodes.spec.ts","tests/e2e/workflows/editor/ndv/pinning.spec.ts","tests/e2e/workflows/editor/routing.spec.ts","tests/e2e/workflows/editor/viewer-permissions.spec.ts","tests/e2e/workflows/templates/templates.spec.ts","tests/e2e/api/binary-data-xss.spec.ts","tests/e2e/api/wait-webhook-deadline.spec.ts","tests/e2e/api/webhook-isolation.spec.ts","tests/e2e/api/workflow-publication-service.spec.ts","tests/e2e/app-config/env-feature-flags.spec.ts","tests/e2e/auth/password-reset.spec.ts","tests/e2e/capabilities/process-internals.spec.ts","tests/e2e/capabilities/task-runner.spec.ts","tests/e2e/dynamic-credentials/execution-status.spec.ts","tests/e2e/mcp/mcp-oauth.spec.ts","tests/e2e/nodes/kafka-nodes.spec.ts","tests/e2e/scheduling/poll-trigger-cursor-migrated.spec.ts","tests/e2e/settings/external-secrets/aws-secrets-manager.spec.ts","tests/e2e/settings/log-streaming/log-streaming-ui-e2e.spec.ts","tests/e2e/settings/workers/workers.spec.ts","tests/e2e/workflows/editor/expressions/mapping.spec.ts","tests/e2e/settings/log-streaming/log-streaming-delivery.spec.ts","tests/e2e/sharing/credential-picker-scope.spec.ts","tests/e2e/workflows/editor/subworkflows/output.spec.ts","tests/e2e/api/manual-run-outcome.spec.ts","tests/e2e/app-config/security-notifications.spec.ts","tests/e2e/building-blocks/credential-mismatch.spec.ts","tests/e2e/building-blocks/workflow-entry-points.spec.ts","tests/e2e/credentials/oauth.spec.ts","tests/e2e/dynamic-credentials/mcp-trigger-credential-gate.spec.ts","tests/e2e/instance-ai/instance-ai-confirmations.spec.ts","tests/e2e/instance-ai/instance-ai-workflow-preview.spec.ts","tests/e2e/journeys/admin-views-executions-list.spec.ts","tests/e2e/nodes/code-node-api.spec.ts","tests/e2e/nodes/form-trigger-node.spec.ts","tests/e2e/regression/ADO-5630-execute-button-layout.spec.ts","tests/e2e/sharing/credential-sharing.spec.ts","tests/e2e/sharing/credential-visibility.spec.ts","tests/e2e/workflows/editor/canvas/canvas-zoom.spec.ts","tests/e2e/workflows/editor/code/code-node.spec.ts","tests/e2e/workflows/editor/execution/execution.spec.ts","tests/e2e/workflows/editor/execution/logs.spec.ts","tests/e2e/workflows/editor/ndv/binary-data-download.spec.ts","tests/e2e/workflows/editor/ndv/ndv-floating-nodes.spec.ts","tests/e2e/workflows/editor/ndv/paired-item.spec.ts","tests/e2e/workflows/editor/ndv/resource-mapper.spec.ts","tests/e2e/workflows/editor/subworkflows/workflow-selector.spec.ts","tests/e2e/building-blocks/user-service.spec.ts","tests/e2e/ai/builder-setup-wizard.spec.ts","tests/e2e/ai/eval-collections-compare.spec.ts","tests/e2e/ai/workflow-builder-smoke.spec.ts","tests/e2e/api/waiting-endpoint-security.spec.ts","tests/e2e/app-config/demo-reimport.spec.ts","tests/e2e/app-config/demo.spec.ts","tests/e2e/auth/admin-smoke.spec.ts","tests/e2e/auth/signin.spec.ts","tests/e2e/building-blocks/canvas-actions.spec.ts","tests/e2e/building-blocks/node-details-configuration.spec.ts","tests/e2e/capabilities/proxy-server.spec.ts","tests/e2e/chat-hub/chat-hub-basic.spec.ts","tests/e2e/chat-hub/chat-hub-personal-agent.spec.ts","tests/e2e/chat-hub/chat-hub-settings.spec.ts","tests/e2e/dynamic-credentials/form-trigger-submit-gate-client.spec.ts","tests/e2e/instance-ai/instance-ai-out-of-credits.spec.ts","tests/e2e/instance-ai/instance-ai-oversized-attachments.spec.ts","tests/e2e/instance-ai/instance-ai-sidebar.spec.ts","tests/e2e/instance-ai/open-by-default.spec.ts","tests/e2e/mcp/mcp-copy-button-hover.spec.ts","tests/e2e/node-creator/actions.spec.ts","tests/e2e/node-creator/navigation.spec.ts","tests/e2e/node-creator/special-nodes.spec.ts","tests/e2e/node-creator/vector-stores.spec.ts","tests/e2e/node-creator/workflows.spec.ts","tests/e2e/nodes/if-node.spec.ts","tests/e2e/nodes/pdf-node.spec.ts","tests/e2e/nodes/schedule-trigger-node.spec.ts","tests/e2e/nodes/send-and-wait.spec.ts","tests/e2e/nodes/webhook.spec.ts","tests/e2e/projects/folders-operations.spec.ts","tests/e2e/projects/project-settings.spec.ts","tests/e2e/regression/ADO-1338-ndv-missing-input-panel.spec.ts","tests/e2e/regression/ADO-2230-ndv-reset-data-pagination.spec.ts","tests/e2e/regression/ADO-2372-prevent-clipping-params.spec.ts","tests/e2e/regression/ADO-2929-can-load-old-switch-node-workflows.spec.ts","tests/e2e/regression/ADO-5808-stale-node-execution-data.spec.ts","tests/e2e/regression/AI-1401-sub-nodes-input-panel.spec.ts","tests/e2e/regression/AI-2795-chat-panel-header-height.spec.ts","tests/e2e/regression/AI-716-correctly-set-up-agent-model-shows-error.spec.ts","tests/e2e/regression/AI-812-partial-execs-broken-when-using-chat-trigger.spec.ts","tests/e2e/regression/CAT-2395-node-spacing.spec.ts","tests/e2e/regression/CAT-726-canvas-node-connectors-not-rendered-when-nodes-inserted.spec.ts","tests/e2e/regression/PAY-4367-node-shifting-cyclic.spec.ts","tests/e2e/regression/SUG-121-fields-reset-after-closing-ndv.spec.ts","tests/e2e/regression/SUG-38-inline-expression-preview.spec.ts","tests/e2e/regression/ado-5599-from-ai-button-alignment.spec.ts","tests/e2e/settings/community-nodes/community-nodes.spec.ts","tests/e2e/settings/environments/variables.spec.ts","tests/e2e/settings/personal/personal.spec.ts","tests/e2e/settings/users/users.spec.ts","tests/e2e/sharing/access-control.spec.ts","tests/e2e/sharing/workflow-sharing.spec.ts","tests/e2e/workflows/demo-diff.spec.ts","tests/e2e/workflows/demo-executable-chat-trigger.spec.ts","tests/e2e/workflows/editor/canvas/focus-panel.spec.ts","tests/e2e/workflows/editor/canvas/stickies.spec.ts","tests/e2e/workflows/editor/canvas/undo-redo.spec.ts","tests/e2e/workflows/editor/code/editors.spec.ts","tests/e2e/workflows/editor/editor-after-route-changes.spec.ts","tests/e2e/workflows/editor/execution/inject-previous.spec.ts","tests/e2e/workflows/editor/execution/partial.spec.ts","tests/e2e/workflows/editor/expressions/inline.spec.ts","tests/e2e/workflows/editor/expressions/transformation.spec.ts","tests/e2e/workflows/editor/ndv/io-filter.spec.ts","tests/e2e/workflows/editor/ndv/ndv-core.spec.ts","tests/e2e/workflows/editor/ndv/ndv-data-display.spec.ts","tests/e2e/workflows/editor/ndv/schema-preview.spec.ts","tests/e2e/workflows/editor/subworkflows/debugging.spec.ts","tests/e2e/workflows/editor/subworkflows/extraction.spec.ts","tests/e2e/workflows/editor/tags.spec.ts","tests/e2e/workflows/executions/filter.spec.ts","tests/e2e/workflows/executions/list.spec.ts","tests/e2e/workflows/executions/preview-isolation.spec.ts","tests/e2e/workflows/list/import.spec.ts","tests/e2e/dynamic-credentials/resolver-deletion.spec.ts","tests/e2e/dynamic-credentials/webhook-trigger-private-credential.spec.ts","tests/e2e/nodes/mcp-trigger.spec.ts","tests/e2e/credentials/api-operations.spec.ts","tests/e2e/api/engine-v2-binary-data.spec.ts","tests/e2e/api/webhook-external.spec.ts","tests/e2e/workflows/editor/execution/subworkflow-stop.spec.ts","tests/e2e/workflows/editor/subworkflows/wait.spec.ts","tests/e2e/workflows/editor/subworkflows/subworkflow-version-resolution.spec.ts","tests/e2e/instance-ai/instance-ai-workflow-setup.spec.ts"],"files":{"packages/@n8n/db/src/repositories/scheduled-job.repository.ts":{"73":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","81":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","98":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","132":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","137":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","143":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","155":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","165":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","172":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","183":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","188":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","194":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","199":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","205":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","210":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","240":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","265":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","281":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","290":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","307":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","317":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","327":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","338":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","361":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","371":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","381":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","387":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","402":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","419":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","434":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","444":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","468":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","494":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","518":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","541":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","559":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","575":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","586":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","587":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","589":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","595":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","596":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","605":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","606":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","623":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","624":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","625":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","648":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA=","656":"b://///////////wcAAAAAAAAAAAAAAAAAAAAAAAA="},"packages/@n8n/db/src/utils/dialect-time.ts":{"13":"b:/8/e+y/5K//HPgQAAAAAAAAAAAAAAAAAAAAAAAA=","22":"b:/8/e+y/5K//HPgQAAAAAAAAAAAAAAAAAAAAAAAA=","38":"b:/8/e+y/5K//HPgQAAAAAAAAAAAAAAAAAAAAAAAA=","54":"b:/8/e+y/5K//HPgQAAAAAAAAAAAAAAAAAAAAAAAA=","76":"b:/8/e+y/5K//HPgQAAAAAAAAAAAAAAAAAAAAAAAA=","94":"b:/8/e+y/5K//HPgQAAAAAAAAAAAAAAAAAAAAAAAA="},"packages/@n8n/scheduler/src/core/factory.ts":{"148":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","233":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","243":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","276":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","291":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","298":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","305":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","311":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","317":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","323":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","329":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","330":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","337":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","338":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","349":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","350":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","355":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","356":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","357":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","364":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","365":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","405":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","411":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","417":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","428":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","455":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","471":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","472":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","478":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","483":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","493":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","498":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","504":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","509":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","519":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","524":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","534":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","543":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","546":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","553":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","578":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","587":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","594":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","601":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","607":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","614":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","619":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","643":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","648":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","658":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","674":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","680":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","686":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","733":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","758":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","774":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","787":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","790":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA=","793":"b:/9/f+7//7//H//7/HwAAAAAAAAAAAAAAAAAAAAA="},"packages/@n8n/scheduler/src/core/materializer/materialize.ts":{"98":"b:/+/e+y/5///3vgUAAAAAAAAAAAAAAAAAAAAAAAA=","105":"b:/+/e+y/5///3vgUAAAAAAAAAAAAAAAAAAAAAAAA=","150":"b:/+/e+y/5///3vgUAAAAAAAAAAAAAAAAAAAAAAAA=","151":"b:/+/e+y/5///3vgUAAAAAAAAAAAAAAAAAAAAAAAA=","155":"b:/+/e+y/5///3vgUAAAAAAAAAAAAAAAAAAAAAAAA=","156":"b:/+/e+y/5///3vgUAAAAAAAAAAAAAAAAAAAAAAAA=","157":"b:/+/e+y/5///3vgUAAAAAAAAAAAAAAAAAAAAAAAA=","180":"b:/+/e+y/5///3vgUAAAAAAAAAAAAAAAAAAAAAAAA=","181":"b:/+/e+y/5///3vgUAAAAAAAAAAAAAAAAAAAAAAAA=","186":"b:/+/e+y/5///3vgUAAAAAAAAAAAAAAAAAAAAAAAA=","194":"b:/+/e+y/5///3vgUAAAAAAAAAAAAAAAAAAAAAAAA=","196":"b:/+/e+y/5///3vgUAAAAAAAAAAAAAAAAAAAAAAAA=","197":"b:/+/e+y/5///3vgUAAAAAAAAAAAAAAAAAAAAAAAA=","201":"b:/+/e+y/5///3vgUAAAAAAAAAAAAAAAAAAAAAAAA="},"packages/@n8n/scheduler/src/observability/materializer-tracing.ts":{"17":"b:/8/e+y/5Kf7HPgQAAAAAAAAAAAAAAAAAAAAAAAA=","28":"b:/8/e+y/5Kf7HPgQAAAAAAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/controllers/e2e.controller.ts":{"197":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","216":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","219":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","230":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","234":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","245":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","251":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","257":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","263":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","274":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","287":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","303":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","310":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","324":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","336":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","341":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","380":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","389":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","398":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","419":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","432":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","436":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","437":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","440":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","451":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","458":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","469":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","479":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","490":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","500":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","580":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","586":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","587":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","595":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","606":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","611":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","620":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","641":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","648":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA=","717":"b:/3/e+y/9v//XPvzv6f8PAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/metrics/prometheus/scheduler-metrics.service.ts":{"46":"b:/8/f+7/77//H/36/HwAAAAAAAAAAAAAAAAAAAAA=","52":"b:/8/f+7/77//H/36/HwAAAAAAAAAAAAAAAAAAAAA=","56":"b:/8/f+7/77//H/36/HwAAAAAAAAAAAAAAAAAAAAA=","62":"b:/8/f+7/77//H/36/HwAAAAAAAAAAAAAAAAAAAAA=","178":"b:/8/f+7/77//H/36/HwAAAAAAAAAAAAAAAAAAAAA=","190":"b:/8/f+7/77//H/36/HwAAAAAAAAAAAAAAAAAAAAA=","191":"b:/8/f+7/77//H/36/HwAAAAAAAAAAAAAAAAAAAAA=","198":"b:/8/f+7/77//H/36/HwAAAAAAAAAAAAAAAAAAAAA=","199":"b:/8/f+7/77//H/36/HwAAAAAAAAAAAAAAAAAAAAA=","206":"b:/8/f+7/77//H/36/HwAAAAAAAAAAAAAAAAAAAAA=","207":"b:/8/f+7/77//H/36/HwAAAAAAAAAAAAAAAAAAAAA=","214":"b:/8/f+7/77//H/36/HwAAAAAAAAAAAAAAAAAAAAA=","216":"b:/8/f+7/77//H/36/HwAAAAAAAAAAAAAAAAAAAAA=","230":"b:/8/f+7/77//H/36/HwAAAAAAAAAAAAAAAAAAAAA=","236":"b:/8/f+7/77//H/36/HwAAAAAAAAAAAAAAAAAAAAA=","242":"b:/8/f+7/77//H/36/HwAAAAAAAAAAAAAAAAAAAAA=","248":"b:/8/f+7/77//H/36/HwAAAAAAAAAAAAAAAAAAAAA=","254":"b:/8/f+7/77//H/36/HwAAAAAAAAAAAAAAAAAAAAA=","260":"b:/8/f+7/77//H/36/HwAAAAAAAAAAAAAAAAAAAAA=","266":"b:/8/f+7/77//H/36/HwAAAAAAAAAAAAAAAAAAAAA=","272":"b:/8/f+7/77//H/36/HwAAAAAAAAAAAAAAAAAAAAA=","279":"b:/8/f+7/77//H/36/HwAAAAAAAAAAAAAAAAAAAAA=","290":"b:/8/f+7/77//H/36/HwAAAAAAAAAAAAAAAAAAAAA=","296":"b:/8/f+7/77//H/36/HwAAAAAAAAAAAAAAAAAAAAA=","306":"b:/8/f+7/77//H/36/HwAAAAAAAAAAAAAAAAAAAAA=","312":"b:/8/f+7/77//H/36/HwAAAAAAAAAAAAAAAAAAAAA=","318":"b:/8/f+7/77//H/36/HwAAAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/scheduling/durable-scheduler.ts":{"37":"b:/8/e+y/5v/7HPgQAAAAQAAAAAAAAAAAAAAAAAAA=","111":"b:/8/e+y/5v/7HPgQAAAAQAAAAAAAAAAAAAAAAAAA=","112":"b:/8/e+y/5v/7HPgQAAAAQAAAAAAAAAAAAAAAAAAA=","114":"b:/8/e+y/5v/7HPgQAAAAQAAAAAAAAAAAAAAAAAAA=","126":"b:/8/e+y/5v/7HPgQAAAAQAAAAAAAAAAAAAAAAAAA=","130":"b:/8/e+y/5v/7HPgQAAAAQAAAAAAAAAAAAAAAAAAA=","143":"b:/8/e+y/5v/7HPgQAAAAQAAAAAAAAAAAAAAAAAAA=","148":"b:/8/e+y/5v/7HPgQAAAAQAAAAAAAAAAAAAAAAAAA=","154":"b:/8/e+y/5v/7HPgQAAAAQAAAAAAAAAAAAAAAAAAA=","181":"b:/8/e+y/5v/7HPgQAAAAQAAAAAAAAAAAAAAAAAAA=","195":"b:/8/e+y/5v/7HPgQAAAAQAAAAAAAAAAAAAAAAAAA=","200":"b:/8/e+y/5v/7HPgQAAAAQAAAAAAAAAAAAAAAAAAA=","202":"b:/8/e+y/5v/7HPgQAAAAQAAAAAAAAAAAAAAAAAAA=","204":"b:/8/e+y/5v/7HPgQAAAAQAAAAAAAAAAAAAAAAAAA=","208":"b:/8/e+y/5v/7HPgQAAAAQAAAAAAAAAAAAAAAAAAA=","210":"b:/8/e+y/5v/7HPgQAAAAQAAAAAAAAAAAAAAAAAAA=","211":"b:/8/e+y/5v/7HPgQAAAAQAAAAAAAAAAAAAAAAAAA=","214":"b:/8/e+y/5v/7HPgQAAAAQAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/workflows/publication/workflow-publication-reconciler.service.ts":{"67":"b:/8/e+275uf72Pn2qCUDhAAAAAAAAAAAAAAAAAAA=","86":"b:/8/e+275uf72Pn2qCUDhAAAAAAAAAAAAAAAAAAA=","99":"b:/8/e+275uf72Pn2qCUDhAAAAAAAAAAAAAAAAAAA=","105":"b:/8/e+275uf72Pn2qCUDhAAAAAAAAAAAAAAAAAAA=","113":"b:/8/e+275uf72Pn2qCUDhAAAAAAAAAAAAAAAAAAA=","119":"b:/8/e+275uf72Pn2qCUDhAAAAAAAAAAAAAAAAAAA=","135":"b:/8/e+275uf72Pn2qCUDhAAAAAAAAAAAAAAAAAAA=","145":"b:/8/e+275uf72Pn2qCUDhAAAAAAAAAAAAAAAAAAA=","216":"b:/8/e+275uf72Pn2qCUDhAAAAAAAAAAAAAAAAAAA=","222":"b:/8/e+275uf72Pn2qCUDhAAAAAAAAAAAAAAAAAAA=","228":"b:/8/e+275uf72Pn2qCUDhAAAAAAAAAAAAAAAAAAA=","233":"b:/8/e+275uf72Pn2qCUDhAAAAAAAAAAAAAAAAAAA=","250":"b:/8/e+275uf72Pn2qCUDhAAAAAAAAAAAAAAAAAAA=","277":"b:/8/e+275uf72Pn2qCUDhAAAAAAAAAAAAAAAAAAA=","285":"b:/8/e+275uf72Pn2qCUDhAAAAAAAAAAAAAAAAAAA=","292":"b:/8/e+275uf72Pn2qCUDhAAAAAAAAAAAAAAAAAAA=","309":"b:/8/e+275uf72Pn2qCUDhAAAAAAAAAAAAAAAAAAA="},"packages/@n8n/api-types/src/dto/index.ts":{"1":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","3":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","4":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","12":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","16":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","42":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","43":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","46":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","58":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","69":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","76":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","78":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","80":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","84":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","86":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","89":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","91":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","97":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","98":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","145":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","147":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","148":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","149":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","151":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","152":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","156":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","162":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","164":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","166":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","167":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","169":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","172":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","173":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","185":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","186":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","201":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","205":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","210":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","216":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","218":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","226":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","227":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","235":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","236":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","237":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","238":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","240":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","242":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","243":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","281":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","312":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","336":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","343":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","344":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","418":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","420":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","437":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","462":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","496":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","506":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","509":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","510":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","512":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","562":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","584":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","585":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","587":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","588":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","629":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","630":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","648":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","796":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA=","797":"b:/o+ikyz5AHH3vn4qawEg//9/AAAAAAAAAAAAAAA="},"packages/@n8n/api-types/src/dto/pagination/pagination.dto.ts":{"11":"b:/k/i8y75AZj0PnQvCRAAEACCAAAAAAAAAAAAAAA=","12":"b:/k/i8y75AZj0PnQvCRAAEACCAAAAAAAAAAAAAAA=","15":"b:/k/i8y75AZj0PnQvCRAAEACCAAAAAAAAAAAAAAA=","20":"b:/k//8777Ad70/3c/H5B83vz/////////////BwA=","28":"b:/k/i8y75AZj0PnQvCRAAEACCAAAAAAAAAAAAAAA=","29":"b:/k/i8y75AZj0PnQvCRAAEACCAAAAAAAAAAAAAAA=","32":[86,124],"33":"b:/k/i8y75AZj0PnQvCRAAAACCAAAAAAAAAAAAAAA=","41":"b:/k/i8y75AZj0PnQvCRAAEACCAAAAAAAAAAAAAAA=","53":"b:/k/i8y75AZj0PnQvCRAAEACCAAAAAAAAAAAAAAA=","54":"b:/k/i8y75AZj0PnQvCRAAEACCAAAAAAAAAAAAAAA=","57":"b:/k/i8y75AZj0PnQvCRAAEACCAAAAAAAAAAAAAAA=","61":"b:/k//8777Ad70/3c/H5B83vz/////////////BwA=","65":"b:/k/i8y75AZj0PnQvCRAAEACCAAAAAAAAAAAAAAA=","66":"b:/k/i8y75AZj0PnQvCRAAEACCAAAAAAAAAAAAAAA=","69":"b:/k/i8y75AZj0PnQvCRAAEACCAAAAAAAAAAAAAAA=","72":"b:/k/i8y75AZj0PnQvCRAAEACCAAAAAAAAAAAAAAA="},"packages/@n8n/api-types/src/dto/user/users-list-filter.dto.ts":{"51":"b:/k/i8y75AZj0PnQrCRAAEAACAAAAAAAAAAAAAAA="},"packages/@n8n/api-types/src/dto/workflows/base-workflow.dto.ts":{"26":"b:+L+igCj9viH3P3xobTkAeUAKAAEAAAAAAACAAQA=","30":[86,124],"31":"b:+L+igCj9viH3P3xobTkAaUAKAAEAAAAAAACAAQA=","42":"b:+L+igCj9viH3P3xobTkAeUAKAAEAAAAAAACAAQA=","53":[86,124],"54":"b:+L+igCj9viH3P3xobTkAaUAKAAEAAAAAAACAAQA=","55":"b:+L+igCj9viH3P3xobTkAeUAKAAEAAAAAAACAAQA=","69":[86,124],"70":"b:+L+igCj9viH3P3xobTkAaUAKAAEAAAAAAACAAQA=","124":"b:+L+igCj9viH3P3xobTkAeUAKAAEAAAAAAACAAQA=","127":"b:+L+igCj9viH3P3xobTkAeUAKAAEAAAAAAACAAQA="},"packages/@n8n/api-types/src/dto/workflows/manual-run.dto.ts":{"5":"b:eAcAAAjBAABGGnAIYwAAkMU3AAAAAAAAAAAAAAA=","64":"b:eAcAAAjBAABGGnAIYwAAkMU3AAAAAAAAAAAAAAA=","69":"b:eAcAAAjBAABGGjAIYwAAgMU3AAAAAAAAAAAAAAA=","86":"b:eAcAAAjBAABGGjAIYwAAgMU3AAAAAAAAAAAAAAA="},"packages/@n8n/api-types/src/index.ts":{"104":"b:/n//82/9v//3Pvz/aX0CQHEKAIEBgAAABAAACAA=","125":"b:/n//82/9v//3Pvz/aX0CQHEKAIEBgAAABAAACAA=","155":"b:/n//82/9v//3Pvz/aX0CQHEKAIEBgAAABAAACAA=","185":"b:/n//82/9v//3Pvz/aX0CQHEKAIEBgAAABAAACAA=","206":"b:/n//82/9v//3Pvz/aX0CQHEKAIEBgAAABAAACAA=","236":"b:/n//82/9v//3Pvz/aX0CQHEKAIEBgAAABAAACAA=","936":"b:/n//82/9v//3Pvz/aX0CQHEKAIEBgAAABAAACAA=","966":"b:/n//82/9v//3Pvz/aX0CQHEKAIEBgAAABAAACAA=","977":"b:/n//82/9v//3Pvz/aX0CQHEKAIEBgAAABAAACAA="},"packages/@n8n/api-types/src/schemas/boolean-from-string.ts":{"3":"b:/k/e+y75Ad/WPnQvCVAEEAAAAAAAAAAAAAAAAAA="},"packages/@n8n/api-types/src/zod-class.ts":{"41":"b:/k//8777Ad72//c/H5B83vz/////////////FwA=","49":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","51":"b:jgCiAwC4ABAWgMIuCAAAGjDAAAAAgAAACAAAEAA=","56":"b:jgCiAwC4ABAWgMIuCAAAGjDAAAAAgAAACAAAEAA=","60":"b:jgCiAwC4ABAWgMIuCAAAGjDAAAAAgAAACAAAEAA=","64":"b:jgCiAwC4ABAWgMIuCAAAGjDAAAAAgAAACAAAEAA=","80":"b:jgCiAwC4ABAWgMIuCAAAGjDAAAAAgAAACAAAEAA=","87":[86,124],"89":"b:jgCiAwC4ABAWgMIuCAAAGjDAAAAAgAAACAAAEAA=","93":"b:jgCiAwC4ABAWgMIuCAAAGjDAAAAAgAAACAAAEAA=","97":"b:jgCiAwC4ABAWgMIuCAAAGjDAAAAAgAAACAAAEAA="},"packages/@n8n/backend-common/src/index.ts":{"5":"b:+Cefmw75AJlnuj4r6yEAQuY1AAAABAAAAAgAIAA=","6":"b:+Cefmw75AJlnuj4r6yEAQuY1AAAABAAAAAgAIAA=","7":"b:+Cefmw75AJlnuj4r6yEAQuY1AAAABAAAAAgAIAA=","10":"b:+Cefmw75AJlnuj4r6yEAQuY1AAAABAAAAAgAIAA=","21":"b:+Cefmw75AJlnuj4r6yEAQuY1AAAABAAAAAgAIAA="},"packages/@n8n/backend-common/src/license-state.ts":{"9":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","15":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","18":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","22":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","33":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","47":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","57":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","61":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","65":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","69":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","73":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","77":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","81":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","85":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","89":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","93":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","97":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","101":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","105":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","109":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","113":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","117":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","121":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","125":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","129":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","133":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","137":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","141":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","145":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","149":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","153":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","157":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","161":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","165":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","169":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","173":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","177":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","181":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","185":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","189":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","193":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","197":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","201":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","205":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","209":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","213":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","217":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","221":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","225":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","233":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","237":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","241":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","245":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","249":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","253":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","257":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","261":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","265":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","269":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","274":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA=","287":"b:/v/f+279v//3/n5vaXkEWkTKgaAIIAAABQgAaAA="},"packages/@n8n/backend-common/src/logging/logger.ts":{"20":"b:bPAQAhiAALwHYDyEEAiAAAABMCABAAAAAAAAoAA=","30":"b:bPAQAhiAALwHYDyEEAiAAAABMCABAAAAAAAAoAA=","41":"b:bPAQAhiAALwHYDyEEAiAAAABMCABAAAAAAAAoAA=","71":"b:bPAQAhiAALwHYDyEEAiAAAABMCABAAAAAAAAoAA=","76":"b:bPAQAhiAALwHYDyEEAiAAAABMCABAAAAAAAAoAA=","88":"b:bPAQAhiAALwHYDyEEAiAAAABMCABAAAAAAAAoAA=","109":"b:bPAQAhiAALwHYDyEEAiAAAABMCABAAAAAAAAoAA=","130":"b:bPAQAhiAALwHYDyEEAiAAAABMCABAAAAAAAAoAA=","142":"b:bPAQAhiAALwHYDyEEAiAAAABMCABAAAAAAAAoAA=","151":"b:bPAQAhiAALwHYDyEEAiAAAABMCABAAAAAAAAoAA=","159":"b:bPAQAhiAALwHYDyEEAiAAAABMCABAAAAAAAAoAA=","163":"b:bPAQAhiAALwHYDyEEAiAAAABMCABAAAAAAAAoAA=","169":"b:bPAQAhiAALwHYDyEEAiAAAABMCABAAAAAAAAoAA=","170":"b:bPAQAhiAALwHYDyEEAiAAAABMCABAAAAAAAAoAA=","176":"b:bPAQAhiAALwHYDyEEAiAAAABMCABAAAAAAAAoAA=","182":"b:bPAQAhiAALwHYDyEEAiAAAABMCABAAAAAAAAoAA=","192":"b:bPAQAhiAALwHYDyEEAiAAAABMCABAAAAAAAAoAA=","195":"b:bPAQAhiAALwHYDyEEAiAAAABMCABAAAAAAAAoAA=","198":"b:bPAQAhiAALwHYDyEEAiAAAABMCABAAAAAAAAoAA=","208":"b:bPAQAhiAALwHYDyEEAiAAAABMCABAAAAAAAAoAA=","214":"b:bPAQAhiAALwHYDyEEAiAAAABMCABAAAAAAAAoAA=","221":"b:bPAQAhiAALwHYDyEEAiAAAABMCABAAAAAAAAoAA=","223":"b:bPAQAhiAALwHYDyEEAiAAAABMCABAAAAAAAAoAA=","231":"b:bPAQAhiAALwHYDyEEAiAAAABMCABAAAAAAAAoAA=","245":"b:bPAQAhiAALwHYDyEEAiAAAABMCABAAAAAAAAoAA=","264":"b:bPAQAhiAALwHYDyEEAiAAAABMCABAAAAAAAAoAA=","268":"b:bPAQAhiAALwHYDyEEAiAAAABMCABAAAAAAAAoAA=","272":"b:bPAQAhiAALwHYDyEEAiAAAABMCABAAAAAAAAoAA=","276":"b:bPAQAhiAALwHYDyEEAiAAAABMCABAAAAAAAAoAA=","284":"b:bPAQAhiAALwHYDyEEAiAAAABMCABAAAAAAAAoAA="},"packages/@n8n/backend-common/src/utils/parse-flatted.ts":{"15":"b:eAccGAjBAAFHGjgIYwEAQMY1AAAAAAAAAAAAAAA="},"packages/@n8n/backend-network/src/http/index.ts":{"9":"b:eLc8FBjFviFxWjjI4QkAQMQVAAEBEBAAAACCgAE=","10":"b:eLc8FBjFviFxWjjI4QkAQMQVAAEBEBAAAACCgAE=","11":"b:eLc8FBjFviFxWjjI4QkAQMQVAAEBEBAAAACCgAE=","12":"b:eLc8FBjFviFxWjjI4QkAQMQVAAEBEBAAAACCgAE="},"packages/@n8n/backend-services/src/errors/rest-error-classifier.ts":{"5":"b:DPAAAgCAAKQHYBwEEAiIAAAAMCEAEAAAAAAAoAA=","40":"b:DPAAAgCAAKQHYBwEEAiIAAAAMCEAEAAAAAAAoAA=","62":"b:DPAAAgCAAKQHYBwEEAiIAAAAMCEAEAAAAAAAoAA=","120":"b:DPAAAgCAAKQHYBwEEAiIAAAAMCEAEAAAAAAAoAA=","132":"b:DPAAAgCAAKQHYBwEEAiIAAAAMCEAEAAAAAAAoAA="},"packages/@n8n/backend-services/src/errors/rest-error-response.ts":{"18":"b:DPAAAgCAAKQHYBwEEAiAAAAAMCAAEAAAAAAAoAA=","85":"b:DPAAAgCAAKQHYBwEEAiAAAAAMCAAEAAAAAAAoAA="},"packages/@n8n/backend-services/src/executions/is-billable-execution.ts":{"30":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA="},"packages/@n8n/backend-services/src/services/cache/cache.service.ts":{"24":"b:/v++lCz9viH3vn1o/6mATOwfCEAAUAAAQIgAoAA=","31":"b:/v++lCz9viH3vn1o/6mATOwfCEAAUAAAQIgAoAA=","68":"b:/v++lCz9viH3vn1o/6mATOwfCEAAUAAAQIgAoAA=","78":"b:/v++lCz9viH3vn1o/6mATOwfCEAAUAAAQIgAoAA=","82":"b:/v++lCz9viH3vn1o/6mATOwfCEAAUAAAQIgAoAA=","86":"b:/v++lCz9viH3vn1o/6mATOwfCEAAUAAAQIgAoAA=","90":"b:/v++lCz9viH3vn1o/6mATOwfCEAAUAAAQIgAoAA=","102":"b:/v++lCz9viH3vn1o/6mATOwfCEAAUAAAQIgAoAA=","114":"b:/v++lCz9viH3vn1o/6mATOwfCEAAUAAAQIgAoAA=","120":"b:/v++lCz9viH3vn1o/6mATOwfCEAAUAAAQIgAoAA=","138":"b:/v++lCz9viH3vn1o/6mATOwfCEAAUAAAQIgAoAA=","159":"b:/v++lCz9viH3vn1o/6mATOwfCEAAUAAAQIgAoAA=","179":"b:/v++lCz9viH3vn1o/6mATOwfCEAAUAAAQIgAoAA=","222":"b:/v++lCz9viH3vn1o/6mATOwfCEAAUAAAQIgAoAA=","233":"b:/v++lCz9viH3vn1o/6mATOwfCEAAUAAAQIgAoAA=","257":"b:/v++lCz9viH3vn1o/6mATOwfCEAAUAAAQIgAoAA=","295":"b:/v++lCz9viH3vn1o/6mATOwfCEAAUAAAQIgAoAA=","339":"b:/v++lCz9viH3vn1o/6mATOwfCEAAUAAAQIgAoAA=","347":"b:/v++lCz9viH3vn1o/6mATOwfCEAAUAAAQIgAoAA=","359":"b:/v++lCz9viH3vn1o/6mATOwfCEAAUAAAQIgAoAA=","378":"b:/v++lCz9viH3vn1o/6mATOwfCEAAUAAAQIgAoAA=","394":"b:/v++lCz9viH3vn1o/6mATOwfCEAAUAAAQIgAoAA="},"packages/@n8n/backend-services/src/services/instance-write-access.service.ts":{"10":"b:eAcAswzBAABGGjAIYwAAAIUnAIAAAAAAAAAAAAA=","13":"b:eAcAswzBAABGGjAIYwAAAIUnAIAAAAAAAAAAAAA=","17":"b:eAcAswzBAABGGjAIYwAAAIUnAIAAAAAAAAAAAAA="},"packages/@n8n/backend-services/src/services/role.service.ts":{"52":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","62":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","65":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","72":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","80":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","84":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","92":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","99":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","117":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","130":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","143":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","192":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","208":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","230":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","234":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","236":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","238":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","248":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","298":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","327":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","332":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","341":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","368":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","424":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","434":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","438":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","448":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","457":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","471":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","495":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","506":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","507":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","517":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","519":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","524":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","530":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","534":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA=","544":"b:/v///y79v//3/v5v6fmETnDKgQgEkAAADAgAsAA="},"packages/@n8n/backend-services/src/services/workflow-project.service.ts":{"7":"b:+Lc+Fgz1viH3ujpoaQkARswNAQAAAAAABAAAAAA=","12":"b:+Lc+Fgz1viH3ujpoaQkARswNAQAAAAAABAAAAAA=","17":"b:+Lc+Fgz1viH3ujpoaQkARswNAQAAAAAABAAAAAA=","40":"b:+Lc+Fgz1viH3ujpoaQkARswNAQAAAAAABAAAAAA=","48":"b:+Lc+Fgz1viH3ujpoaQkARswNAQAAAAAABAAAAAA=","53":"b:+Lc+Fgz1viH3ujpoaQkARswNAQAAAAAABAAAAAA=","56":"b:+Lc+Fgz1viH3ujpoaQkARswNAQAAAAAABAAAAAA=","59":"b:+Lc+Fgz1viH3ujpoaQkARswNAQAAAAAABAAAAAA="},"packages/@n8n/backend-services/src/services/workflow-sharing.service.ts":{"21":"b:+PcjFwj1vrt3mztr/4mASvc3gAAEEAAACQCgoAA=","38":"b:+PcjFwj1vrt3mztr/4mASvc3gAAEEAAACQCgoAA=","67":"b:+PcjFwj1vrt3mztr/4mASvc3gAAEEAAACQCgoAA=","91":"b:+PcjFwj1vrt3mztr/4mASvc3gAAEEAAACQCgoAA=","107":"b:+PcjFwj1vrt3mztr/4mASvc3gAAEEAAACQCgoAA=","123":"b:+PcjFwj1vrt3mztr/4mASvc3gAAEEAAACQCgoAA=","127":"b:+PcjFwj1vrt3mztr/4mASvc3gAAEEAAACQCgoAA=","135":"b:+PcjFwj1vrt3mztr/4mASvc3gAAEEAAACQCgoAA=","138":"b:+PcjFwj1vrt3mztr/4mASvc3gAAEEAAACQCgoAA=","144":"b:+PcjFwj1vrt3mztr/4mASvc3gAAEEAAACQCgoAA=","151":"b:+PcjFwj1vrt3mztr/4mASvc3gAAEEAAACQCgoAA=","159":"b:+PcjFwj1vrt3mztr/4mASvc3gAAEEAAACQCgoAA="},"packages/@n8n/db/src/entities/types-db.ts":{"330":"b:/j/e8y/9v+/XPvzqaWkCAAAAAAAAAAAAAAAAAAA=","342":"b:/j/e8y/9v+/XPvzqaWkCAAAAAAAAAAAAAAAAAAA=","481":"b:/j/e8y/9v+/XPvzqaWkCAAAAAAAAAAAAAAAAAAA="},"packages/@n8n/db/src/index.ts":{"14":"b:/Leflxz9vv/3+j5//zkIZvy/sC0MEgAADSgAyAA=","15":"b:/Leflxz9vv/3+j5//zkIZvy/sC0MEgAADSgAyAA=","18":"b:/Leflxz9vv/3+j5//zkIZvy/sC0MEgAADSgAyAA=","19":"b:/Leflxz9vv/3+j5//zkIZvy/sC0MEgAADSgAyAA=","20":"b:/Leflxz9vv/3+j5//zkIZvy/sC0MEgAADSgAyAA=","24":"b:/Leflxz9vv/3+j5//zkIZvy/sC0MEgAADSgAyAA=","26":"b:/Leflxz9vv/3+j5//zkIZvy/sC0MEgAADSgAyAA=","27":"b:/Leflxz9vv/3+j5//zkIZvy/sC0MEgAADSgAyAA=","28":"b:/Leflxz9vv/3+j5//zkIZvy/sC0MEgAADSgAyAA=","43":"b:/Leflxz9vv/3+j5//zkIZvy/sC0MEgAADSgAyAA=","53":"b:/Leflxz9vv/3+j5//zkIZvy/sC0MEgAADSgAyAA=","63":"b:/Leflxz9vv/3+j5//zkIZvy/sC0MEgAADSgAyAA="},"packages/@n8n/db/src/repositories/base-repository.ts":{"17":"b:+L+e8Cz9vjH3PnxsaSkAAEAIAAAAAAAAAAAAAAA=","30":"b:+L+e8Cz9vjH3PnxsaSkAAEAIAAAAAAAAAAAAAAA=","49":"b:+L+e8Cz9vjH3PnxsaSkAAEAIAAAAAAAAAAAAAAA=","53":"b:+L+e8Cz9vjH3PnxsaSkAAEAIAAAAAAAAAAAAAAA="},"packages/@n8n/db/src/repositories/credentials.repository.ts":{"33":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","67":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","76":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","87":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","111":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","121":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","129":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","139":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","147":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","151":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","159":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","163":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","190":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","203":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","209":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","217":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","233":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","241":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","258":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","277":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","299":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","307":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","327":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","339":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","378":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","407":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","422":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","429":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","434":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","509":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","547":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","566":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","581":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","595":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","608":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","616":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","625":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","633":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","669":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","756":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","758":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA=","762":"b:/v//l679v/n3fn5r7zlkXv5/gSsEYIBADAAA4AA="},"packages/@n8n/db/src/repositories/execution.repository.ts":{"74":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","123":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","154":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","188":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","221":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","241":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","246":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","253":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","260":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","266":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","272":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","278":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","285":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","290":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","330":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","393":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","403":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","427":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","434":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","445":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","453":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","486":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","512":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","517":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","520":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","537":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","540":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","569":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","593":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","620":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","660":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","671":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","672":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","679":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","685":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","688":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","700":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","704":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","724":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","737":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","745":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","758":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","765":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","769":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","794":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","807":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","810":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","844":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","934":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","946":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","956":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","970":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","995":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","1006":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","1012":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","1025":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","1032":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","1072":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","1113":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","1129":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","1133":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","1160":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","1196":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","1200":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","1220":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","1239":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","1360":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","1362":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","1370":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","1407":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","1415":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","1418":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","1426":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","1430":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","1435":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","1438":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","1447":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","1450":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","1456":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","1464":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","1471":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","1479":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA=","1496":"b:eJc8FEjFviFHGzhI4YmAQMU3AAAAEAAAAACAgQA="},"packages/@n8n/db/src/repositories/index.ts":{"11":"b:+r+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","12":"b:+r+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","17":"b:+r+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","20":"b:+r+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","21":"b:+r+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","22":"b:+r+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","44":"b:+r+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","47":"b:+r+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","56":"b:+r+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","59":"b:+r+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","60":"b:+r+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","69":"b:+r+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","95":"b:+r+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","97":"b:+r+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","100":"b:+r+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","101":"b:+r+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","103":"b:+r+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","109":"b:+r+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","110":"b:+r+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","138":"b:+r+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","139":"b:+r+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","144":"b:+r+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","151":"b:+r+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","152":"b:+r+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/@n8n/db/src/repositories/project-relation.repository.ts":{"14":"b:/v/f9y79v//XPnxq6WmAADWBAEgAgAAABAAAoAA=","18":"b:/v/f9y79v//XPnxq6WmAADWBAEgAgAAABAAAoAA=","33":"b:/v/f9y79v//XPnxq6WmAADWBAEgAgAAABAAAoAA=","48":"b:/v/f9y79v//XPnxq6WmAADWBAEgAgAAABAAAoAA=","67":"b:/v/f9y79v//XPnxq6WmAADWBAEgAgAAABAAAoAA=","75":"b:/v/f9y79v//XPnxq6WmAADWBAEgAgAAABAAAoAA=","78":"b:/v/f9y79v//XPnxq6WmAADWBAEgAgAAABAAAoAA=","83":"b:/v/f9y79v//XPnxq6WmAADWBAEgAgAAABAAAoAA=","89":"b:/v/f9y79v//XPnxq6WmAADWBAEgAgAAABAAAoAA=","96":"b:/v/f9y79v//XPnxq6WmAADWBAEgAgAAABAAAoAA=","102":"b:/v/f9y79v//XPnxq6WmAADWBAEgAgAAABAAAoAA=","110":"b:/v/f9y79v//XPnxq6WmAADWBAEgAgAAABAAAoAA=","116":"b:/v/f9y79v//XPnxq6WmAADWBAEgAgAAABAAAoAA=","130":"b:/v/f9y79v//XPnxq6WmAADWBAEgAgAAABAAAoAA=","143":"b:/v/f9y79v//XPnxq6WmAADWBAEgAgAAABAAAoAA=","144":"b:/v/f9y79v//XPnxq6WmAADWBAEgAgAAABAAAoAA=","151":"b:/v/f9y79v//XPnxq6WmAADWBAEgAgAAABAAAoAA=","162":"b:/v/f9y79v//XPnxq6WmAADWBAEgAgAAABAAAoAA="},"packages/@n8n/db/src/repositories/project.repository.ts":{"14":"b:/v/e+y79v//3fn5vaXlEWvBJASAAAABADAAASAA=","21":"b:/v/e+y79v//3fn5vaXlEWvBJASAAAABADAAASAA=","29":"b:/v/e+y79v//3fn5vaXlEWvBJASAAAABADAAASAA=","38":"b:/v/e+y79v//3fn5vaXlEWvBJASAAAABADAAASAA=","68":"b:/v/e+y79v//3fn5vaXlEWvBJASAAAABADAAASAA=","80":"b:/v/e+y79v//3fn5vaXlEWvBJASAAAABADAAASAA=","92":"b:/v/e+y79v//3fn5vaXlEWvBJASAAAABADAAASAA=","98":"b:/v/e+y79v//3fn5vaXlEWvBJASAAAABADAAASAA=","102":"b:/v/e+y79v//3fn5vaXlEWvBJASAAAABADAAASAA=","114":"b:/v/e+y79v//3fn5vaXlEWvBJASAAAABADAAASAA=","131":"b:/v/e+y79v//3fn5vaXlEWvBJASAAAABADAAASAA=","141":"b:/v/e+y79v//3fn5vaXlEWvBJASAAAABADAAASAA=","145":"b:/v/e+y79v//3fn5vaXlEWvBJASAAAABADAAASAA=","149":"b:/v/e+y79v//3fn5vaXlEWvBJASAAAABADAAASAA=","173":"b:/v/e+y79v//3fn5vaXlEWvBJASAAAABADAAASAA=","188":"b:/v/e+y79v//3fn5vaXlEWvBJASAAAABADAAASAA=","205":"b:/v/e+y79v//3fn5vaXlEWvBJASAAAABADAAASAA=","215":"b:/v/e+y79v//3fn5vaXlEWvBJASAAAABADAAASAA=","227":"b:/v/e+y79v//3fn5vaXlEWvBJASAAAABADAAASAA=","243":"b:/v/e+y79v//3fn5vaXlEWvBJASAAAABADAAASAA=","252":"b:/v/e+y79v//3fn5vaXlEWvBJASAAAABADAAASAA=","268":"b:/v/e+y79v//3fn5vaXlEWvBJASAAAABADAAASAA=","281":"b:/v/e+y79v//3fn5vaXlEWvBJASAAAABADAAASAA=","295":"b:/v/e+y79v//3fn5vaXlEWvBJASAAAABADAAASAA=","305":"b:/v/e+y79v//3fn5vaXlEWvBJASAAAABADAAASAA=","312":"b:/v/e+y79v//3fn5vaXlEWvBJASAAAABADAAASAA=","318":"b:/v/e+y79v//3fn5vaXlEWvBJASAAAABADAAASAA=","329":"b:/v/e+y79v//3fn5vaXlEWvBJASAAAABADAAASAA="},"packages/@n8n/db/src/repositories/role.repository.ts":{"11":"b:/k/++y75Ad7UPvQvCVAEADCAAAAAgAAADAAAEAA=","15":"b:/k/++y75Ad7UPvQvCVAEADCAAAAAgAAADAAAEAA=","20":"b:/k/++y75Ad7UPvQvCVAEADCAAAAAgAAADAAAEAA=","38":"b:/k/++y75Ad7UPvQvCVAEADCAAAAAgAAADAAAEAA=","54":"b:/k/++y75Ad7UPvQvCVAEADCAAAAAgAAADAAAEAA=","65":"b:/k/++y75Ad7UPvQvCVAEADCAAAAAgAAADAAAEAA=","74":"b:/k/++y75Ad7UPvQvCVAEADCAAAAAgAAADAAAEAA=","82":"b:/k/++y75Ad7UPvQvCVAEADCAAAAAgAAADAAAEAA=","108":"b:/k/++y75Ad7UPvQvCVAEADCAAAAAgAAADAAAEAA=","111":"b:/k/++y75Ad7UPvQvCVAEADCAAAAAgAAADAAAEAA=","114":"b:/k/++y75Ad7UPvQvCVAEADCAAAAAgAAADAAAEAA=","128":"b:/k/++y75Ad7UPvQvCVAEADCAAAAAgAAADAAAEAA=","131":"b:/k/++y75Ad7UPvQvCVAEADCAAAAAgAAADAAAEAA=","151":"b:/k/++y75Ad7UPvQvCVAEADCAAAAAgAAADAAAEAA=","180":"b:/k/++y75Ad7UPvQvCVAEADCAAAAAgAAADAAAEAA=","187":"b:/k/++y75Ad7UPvQvCVAEADCAAAAAgAAADAAAEAA=","194":"b:/k/++y75Ad7UPvQvCVAEADCAAAAAgAAADAAAEAA=","205":"b:/k/++y75Ad7UPvQvCVAEADCAAAAAgAAADAAAEAA=","206":"b:/k/++y75Ad7UPvQvCVAEADCAAAAAgAAADAAAEAA=","230":"b:/k/++y75Ad7UPvQvCVAEADCAAAAAgAAADAAAEAA=","263":"b:/k/++y75Ad7UPvQvCVAEADCAAAAAgAAADAAAEAA=","267":"b:/k/++y75Ad7UPvQvCVAEADCAAAAAgAAADAAAEAA="},"packages/@n8n/db/src/repositories/scheduled-task.repository.ts":{"155":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","176":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","188":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","231":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","248":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","258":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","261":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","262":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","275":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","298":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","308":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","329":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","334":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","341":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","345":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","350":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","386":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","391":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","436":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","448":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","459":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","466":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","468":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","493":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","505":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","506":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","521":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","523":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","536":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","538":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","543":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","546":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","555":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","558":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","559":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","570":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","577":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","578":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","598":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","614":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","639":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","685":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","702":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","707":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","708":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","709":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","731":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","736":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","737":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","752":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","757":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","770":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","803":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","839":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","840":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","861":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","876":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","906":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","931":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","944":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","956":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","985":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","1027":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","1031":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA=","1032":"b:/j/e+278///0vP3/HwAAAAAAAAAAAAAAAAAAAAA="},"packages/@n8n/db/src/repositories/shared-workflow.repository.ts":{"28":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","36":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","41":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","44":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","68":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","71":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","84":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","87":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","100":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","103":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","140":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","165":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","173":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","177":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","189":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","192":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","213":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","223":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","229":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","241":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","253":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","265":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","268":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","277":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","284":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","291":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","297":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","310":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","319":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","328":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","337":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","342":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","355":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA=","408":"b:+P+rnyz9vqn3v39v66mgSvc/SAkIUAAAFAiioAA="},"packages/@n8n/db/src/repositories/user.repository.ts":{"21":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","25":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","42":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","56":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","60":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","67":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","74":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","80":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","104":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","114":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","119":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","146":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","156":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","160":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","164":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","171":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","175":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","186":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","193":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","204":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","211":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","215":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","262":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","295":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","317":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","325":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","346":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","359":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","367":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","372":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","431":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","457":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","476":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","498":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA=","509":"b:/v/+9y79v7n3/v9viZ2AfvHLAQEAkAEADAAisAA="},"packages/@n8n/db/src/repositories/workflow-content-write-context.ts":{"7":"b:+L+ekCz9viH3PnxsaSkAQEAIAAAAAAAAAAAAAAA=","10":"b:+L+ekCz9viH3PnxsaSkAQEAIAAAAAAAAAAAAAAA="},"packages/@n8n/db/src/repositories/workflow-dependency.repository.ts":{"37":"b:+L+ikCz9viH3vn5saSkAQEAKAAAAAAAAAAAAAAA=","43":"b:+L+ikCz9viH3vn5saSkAQEAKAAAAAAAAAAAAAAA=","62":"b:+L+ikCz9viH3vn5saSkAQEAKAAAAAAAAAAAAAAA=","77":"b:+L+ikCz9viH3vn5saSkAQEAKAAAAAAAAAAAAAAA=","109":"b:+L+ikCz9viH3vn5saSkAQEAKAAAAAAAAAAAAAAA=","122":"b:+L+ikCz9viH3vn5saSkAQEAKAAAAAAAAAAAAAAA=","137":"b:+L+ikCz9viH3vn5saSkAQEAKAAAAAAAAAAAAAAA=","156":"b:+L+ikCz9viH3vn5saSkAQEAKAAAAAAAAAAAAAAA=","171":"b:+L+ikCz9viH3vn5saSkAQEAKAAAAAAAAAAAAAAA=","198":"b:+L+ikCz9viH3vn5saSkAQEAKAAAAAAAAAAAAAAA=","202":"b:+L+ikCz9viH3vn5saSkAQEAKAAAAAAAAAAAAAAA=","207":"b:+L+ikCz9viH3vn5saSkAQEAKAAAAAAAAAAAAAAA=","254":"b:+L+ikCz9viH3vn5saSkAQEAKAAAAAAAAAAAAAAA=","279":"b:+L+ikCz9viH3vn5saSkAQEAKAAAAAAAAAAAAAAA=","280":"b:+L+ikCz9viH3vn5saSkAQEAKAAAAAAAAAAAAAAA=","291":"b:+L+ikCz9viH3vn5saSkAQEAKAAAAAAAAAAAAAAA=","317":"b:+L+ikCz9viH3vn5saSkAQEAKAAAAAAAAAAAAAAA="},"packages/@n8n/db/src/repositories/workflow-statistics.repository.ts":{"44":"b:eNcgHAjFviFHGjhI4QmAQMQ3AEAAAAAAAAAAoAA=","52":"b:eNcgHAjFviFHGjhI4QmAQMQ3AEAAAAAAAAAAoAA=","62":"b:eNcgHAjFviFHGjhI4QmAQMQ3AEAAAAAAAAAAoAA=","95":"b:eNcgHAjFviFHGjhI4QmAQMQ3AEAAAAAAAAAAoAA=","138":"b:eNcgHAjFviFHGjhI4QmAQMQ3AEAAAAAAAAAAoAA=","143":"b:eNcgHAjFviFHGjhI4QmAQMQ3AEAAAAAAAAAAoAA=","156":"b:eNcgHAjFviFHGjhI4QmAQMQ3AEAAAAAAAAAAoAA=","209":"b:eNcgHAjFviFHGjhI4QmAQMQ3AEAAAAAAAAAAoAA=","214":"b:eNcgHAjFviFHGjhI4QmAQMQ3AEAAAAAAAAAAoAA=","224":"b:eNcgHAjFviFHGjhI4QmAQMQ3AEAAAAAAAAAAoAA="},"packages/@n8n/db/src/repositories/workflow.repository.ts":{"90":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","107":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","126":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","139":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","180":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","199":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","218":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","236":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","246":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","252":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","255":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","262":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","265":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","271":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","280":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","286":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","296":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","311":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","318":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","330":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","336":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","337":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","361":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","363":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","374":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","385":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","396":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","407":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","413":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","416":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","432":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","441":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","448":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","457":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","464":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","470":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","480":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","501":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","520":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","540":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","548":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","552":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","560":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","563":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","585":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","592":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","598":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","604":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","614":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","703":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","727":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","749":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","775":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","786":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","787":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","790":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","812":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","856":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","914":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","948":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","978":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1058":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1069":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1074":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1075":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1078":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1080":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1081":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1084":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1099":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1106":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1107":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1109":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1118":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1130":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1147":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1174":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1245":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1268":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1307":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1317":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1333":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1347":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1357":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1372":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1385":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1402":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1414":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1422":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1445":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1453":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1459":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1470":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1476":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1481":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1492":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1508":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1529":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1542":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1551":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1572":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1583":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1596":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1606":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1619":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1624":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1649":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1676":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1680":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1690":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1725":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1741":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1747":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1757":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1773":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1782":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1789":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1796":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1803":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1813":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1828":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1862":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1869":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1873":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1888":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1895":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1929":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1946":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","1987":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","2003":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI=","2042":"b:+v//n+z9v633vn9v/7mhzv1/oAEMcAKAFAggqAI="},"packages/@n8n/db/src/services/typeorm-transaction.ts":{"16":"b:/r+e8iz9vjH3PnxsaWkAAAAIAAAAAAAAAAAAAAA=","21":"b:/r+e8iz9vjH3PnxsaWkAAAAIAAAAAAAAAAAAAAA=","29":"b:/r+e8iz9vjH3PnxsaWkAAAAIAAAAAAAAAAAAAAA=","36":"b:/r+e8iz9vjH3PnxsaWkAAAAIAAAAAAAAAAAAAAA=","59":"b:/r+e8iz9vjH3PnxsaWkAAAAIAAAAAAAAAAAAAAA="},"packages/@n8n/db/src/subscribers/workflow-entity-subscriber.ts":{"10":"b:+P++lCz9viH3PnxsabkATOgIAAAAEAAAAAAAAAA=","12":"b:+P++lCz9viH3PnxsabkATOgIAAAAEAAAAAAAAAA=","16":"b:+P++lCz9viH3PnxsabkATOgIAAAAEAAAAAAAAAA=","20":"b:+P++lCz9viH3PnxsabkATOgIAAAAEAAAAAAAAAA=","24":"b:+P++lCz9viH3PnxsabkATOgIAAAAEAAAAAAAAAA=","32":"b:+P++lCz9viH3PnxsabkATOgIAAAAEAAAAAAAAAA="},"packages/@n8n/db/src/utils/is-query-failed-error-of-kind.ts":{"10":"b:DDAAAgCAAIQGYBQEEAgIAAAAMCEAAAAAACAAAAA="},"packages/@n8n/db/src/utils/is-unique-constraint-error.ts":{"6":"b:DDAAAgCAAIQGYBQEEAgIAAAAMCEAAAAAACAAAAA="},"packages/@n8n/db/src/utils/transformers.ts":{"7":"b:+L+elCz9viH3Pnxs6SkAQMQ9AAAAAAAAAAAAgAA=","8":"b:+L+elCz9viH3Pnxs6SkAQMQ9AAAAAAAAAAAAgAA=","15":"b:+L+elCz9viH3Pnxs6SkAQMQ9AAAAAAAAAAAAgAA=","16":"b:+L+elCz9viH3Pnxs6SkAQMQ9AAAAAAAAAAAAgAA=","23":"b:+L+elCz9viH3Pnxs6SkAQMQ9AAAAAAAAAAAAgAA=","24":"b:+L+elCz9viH3Pnxs6SkAQMQ9AAAAAAAAAAAAgAA=","32":"b:+L+elCz9viH3Pnxs6SkAQMQ9AAAAAAAAAAAAgAA=","34":"b:+L+elCz9viH3Pnxs6SkAQMQ9AAAAAAAAAAAAgAA=","44":"b:+L+elCz9viH3Pnxs6SkAQMQ9AAAAAAAAAAAAgAA=","45":"b:+L+elCz9viH3Pnxs6SkAQMQ9AAAAAAAAAAAAgAA="},"packages/@n8n/decorators/src/execution-lifecycle/lifecycle-metadata.ts":{"97":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","100":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","104":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA="},"packages/@n8n/decorators/src/policy-check/policy-check-metadata.ts":{"30":"b:/r+ekC79vjH3PnxsaSkAQEAIAAAAAAAAAAAAAAA=","55":"b:/r+ekC79vjH3PnxsaSkAQEAIAAAAAAAAAAAAAAA=","65":"b:/r+ekC79vjH3PnxsaSkAQEAIAAAAAAAAAAAAAAA=","70":"b:/r+ekC79vjH3PnxsaSkAQEAIAAAAAAAAAAAAAAA=","71":"b:/r+ekC79vjH3PnxsaSkAQEAIAAAAAAAAAAAAAAA=","92":"b:/r+ekC79vjH3PnxsaSkAQEAIAAAAAAAAAAAAAAA=","94":"b:/r+ekC79vjH3PnxsaSkAQEAIAAAAAAAAAAAAAAA=","125":"b:/r+ekC79vjH3PnxsaSkAQEAIAAAAAAAAAAAAAAA=","126":"b:/r+ekC79vjH3PnxsaSkAQEAIAAAAAAAAAAAAAAA="},"packages/@n8n/decorators/src/policy-check/policy-cleared.ts":{"28":"b:/r++kK79vjH3fnxsaTkARPgIASAAIAIAAAAAYAA=","39":"b:/r++kK79vjH3fnxsaTkARPgIASAAIAIAAAAAYAA=","55":"b:/r++kK79vjH3fnxsaTkARPgIASAAIAIAAAAAYAA=","69":"b:/r++kK79vjH3fnxsaTkARPgIASAAIAIAAAAAYAA=","78":"b:/r++kK79vjH3fnxsaTkARPgIASAAIAIAAAAAYAA=","113":"b:/r++kK79vjH3fnxsaTkARPgIASAAIAIAAAAAYAA="},"packages/@n8n/decorators/src/policy-check/policy-mint.ts":{"15":"b:/r+ekC79vjH3PnxsaSkAQEAIAAAAAAAAAAAAAAA="},"packages/@n8n/decorators/src/redactable.ts":{"14":"b:/j/e8y/8v+/XPvzmYW0CAAAAAAAAAAAAAAAAAAA=","21":"b:/j/e8y/8v+/XPvzmYW0CAAAAAAAAAAAAAAAAAAA=","46":"b:/j/e8y/8v+/XPvzmYW0CAAAAAAAAAAAAAAAAAAA=","47":"b:/j/e8y/8v+/XPvzmYW0CAAAAAAAAAAAAAAAAAAA=","53":"b:/j/e8y/8v+/XPvzmYW0CAAAAAAAAAAAAAAAAAAA=","54":"b:/j/e8y/8v+/XPvzmYW0CAAAAAAAAAAAAAAAAAAA="},"packages/@n8n/errors/src/base.error.ts":{"32":"b:fLSQsCzAAqxHXngEsViAMMQ7MaAAAoFBAMQGgAA="},"packages/@n8n/errors/src/isolate.error.ts":{"2":"b:eLccEAjFviF3gnxIYSkAUMQVAAAAAAAAAAAAgAA="},"packages/@n8n/errors/src/response-errors/not-found.error.ts":{"4":"b:DNAgAACwACADAAAAAAiAAAAAMCAAEAAAAAAA4AA=","14":"b:DNAgAACwACADAAAAAAiAAAAAMCAAEAAAAAAA4AA="},"packages/@n8n/errors/src/response-errors/response.error.ts":{"19":"b:DPAAsAyAAKQBAAkEAEiAAAAAMKAAEAAAAAAAoAA="},"packages/@n8n/expression-runtime/src/bridge/isolated-vm-bridge.ts":{"25":"b:eLccGAzFviF3OjxI4SmQUcQVAEAAAgAAAIAkgAQ=","46":"b:eLccGAzFviF3OjxI4SmQUcQVAEAAAgAAAIAkgAQ=","64":"b:eLccGAzFviF3OjxI4SmQUcQVAEAAAgAAAIAkgAQ=","99":"b:eLccGAzFviF3OjxI4SmQUcQVAEAAAgAAAIAkgAQ=","133":"b:eLccGAzFviF3OjxI4SmQUcQVAEAAAgAAAIAkgAQ=","156":"b:eLccGAzFviF3OjxI4SmQUcQVAEAAAgAAAIAkgAQ=","195":"b:eLccGAzFviF3OjxI4SmQUcQVAEAAAgAAAIAkgAQ=","248":"b:eLccGAzFviF3OjxI4SmQUcQVAEAAAgAAAIAkgAQ=","265":"b:eLccGAzFviF3OjxI4SmQUcQVAEAAAgAAAIAkgAQ=","309":"b:eLccGAzFviF3OjxI4SmQUcQVAEAAAgAAAIAkgAQ=","310":"b:eLccGAzFviF3OjxI4SmQUcQVAEAAAgAAAIAkgAQ=","329":"b:eLccGAzFviF3OjxI4SmQUcQVAEAAAgAAAIAkgAQ=","330":"b:eLccGAzFviF3OjxI4SmQUcQVAEAAAgAAAIAkgAQ=","356":"b:eLccGAzFviF3OjxI4SmQUcQVAEAAAgAAAIAkgAQ=","357":"b:eLccGAzFviF3OjxI4SmQUcQVAEAAAgAAAIAkgAQ=","386":"b:eLccGAzFviF3OjxI4SmQUcQVAEAAAgAAAIAkgAQ=","502":"b:eLccGAzFviF3OjxI4SmQUcQVAEAAAgAAAIAkgAQ=","516":"b:eLccGAzFviF3OjxI4SmQUcQVAEAAAgAAAIAkgAQ=","537":"b:eLccGAzFviF3OjxI4SmQUcQVAEAAAgAAAIAkgAQ="},"packages/@n8n/expression-runtime/src/evaluator/expression-evaluator.ts":{"19":"b:eLccGAzFviF3OnxIYSmAUcQVAEAAAAAAAIAEgAA=","74":"b:eLccGAzFviF3OnxIYSmAUcQVAEAAAAAAAIAEgAA=","76":"b:eLccGAzFviF3OnxIYSmAUcQVAEAAAAAAAIAEgAA=","80":"b:eLccGAzFviF3OnxIYSmAUcQVAEAAAAAAAIAEgAA=","86":"b:eLccGAzFviF3OnxIYSmAUcQVAEAAAAAAAIAEgAA=","104":"b:eLccGAzFviF3OnxIYSmAUcQVAEAAAAAAAIAEgAA=","119":"b:eLccGAzFviF3OnxIYSmAUcQVAEAAAAAAAIAEgAA=","147":"b:eLccGAzFviF3OnxIYSmAUcQVAEAAAAAAAIAEgAA=","184":"b:eLccGAzFviF3OnxIYSmAUcQVAEAAAAAAAIAEgAA=","225":"b:eLccGAzFviF3OnxIYSmAUcQVAEAAAAAAAIAEgAA=","245":"b:eLccGAzFviF3OnxIYSmAUcQVAEAAAAAAAIAEgAA=","253":"b:eLccGAzFviF3OnxIYSmAUcQVAEAAAAAAAIAEgAA=","266":"b:eLccGAzFviF3OnxIYSmAUcQVAEAAAAAAAIAEgAA=","280":"b:eLccGAzFviF3OnxIYSmAUcQVAEAAAAAAAIAEgAA=","296":"b:eLccGAzFviF3OnxIYSmAUcQVAEAAAAAAAIAEgAA=","303":"b:eLccGAzFviF3OnxIYSmAUcQVAEAAAAAAAIAEgAA="},"packages/@n8n/expression-runtime/src/pool/isolate-pool.ts":{"6":"b:eLccEAzFviF3unxIYSkAUMQVAAAAAAAAAAAAgAA=","13":"b:eLccEAzFviF3unxIYSkAUMQVAAAAAAAAAAAAgAA=","36":"b:eLccEAzFviF3unxIYSkAUMQVAAAAAAAAAAAAgAA=","43":"b:eLccEAzFviF3unxIYSkAUMQVAAAAAAAAAAAAgAA=","45":"b:eLccEAzFviF3unxIYSkAUMQVAAAAAAAAAAAAgAA=","67":"b:eLccEAzFviF3unxIYSkAUMQVAAAAAAAAAAAAgAA=","75":"b:eLccEAzFviF3unxIYSkAUMQVAAAAAAAAAAAAgAA=","80":"b:eLccEAzFviF3unxIYSkAUMQVAAAAAAAAAAAAgAA=","83":"b:eLccEAzFviF3unxIYSkAUMQVAAAAAAAAAAAAgAA=","90":"b:eLccEAzFviF3unxIYSkAUMQVAAAAAAAAAAAAgAA=","96":"b:eLccEAzFviF3unxIYSkAUMQVAAAAAAAAAAAAgAA=","103":"b:eLccEAzFviF3unxIYSkAUMQVAAAAAAAAAAAAgAA=","112":"b:eLccEAzFviF3unxIYSkAUMQVAAAAAAAAAAAAgAA=","119":"b:eLccEAzFviF3unxIYSkAUMQVAAAAAAAAAAAAgAA="},"packages/@n8n/permissions/src/index.ts":{"21":"b:/r/e8y/9v//3PvzuaW0CQEAIAAAAAAAAAAAAAAA=","22":"b:/r/e8y/9v//3PvzuaW0CQEAIAAAAAAAAAAAAAAA=","26":"b:/r/e8y/9v//3PvzuaW0CQEAIAAAAAAAAAAAAAAA=","28":"b:/r/e8y/9v//3PvzuaW0CQEAIAAAAAAAAAAAAAAA="},"packages/@n8n/permissions/src/roles/all-roles.ts":{"57":"b:/k//+777Ad70/3c/H9B83vz/////////////BwA=","61":"b:/k//+777Ad70/3c/H9B83vz/////////////BwA=","83":"b:/k/e+y75Ad7UPnQvAVAEAAAAAAAAAAAAAAAAAAA="},"packages/@n8n/permissions/src/utilities/combine-scopes.ee.ts":{"16":"b:/v//87//v//3////f/l+3vz/////////////BwA=","18":"b:/v//87//v//3////f/l+3vz/////////////BwA=","23":"b:/r/e8y/9v//3PvzuaWkCUEAIAAAAAAAAAAAAAAA=","26":"b:/r/e8y/9v//3PvzuaWkCUEAIAAAAAAAAAAAAAAA="},"packages/@n8n/permissions/src/utilities/get-global-scopes.ee.ts":{"8":"b:/j/e8y/8v+/XPvzmYW0CAAAAAAAAAAAAAAAAAAA=","9":"b:/j/e8y/8v+/XPvzmYW0CAAAAAAAAAAAAAAAAAAA="},"packages/@n8n/permissions/src/utilities/get-role-scopes.ee.ts":{"5":"b:/v//87//v//3////f/l+3vz/////////////BwA=","16":"b:/v//87//v//3////f/l+3vz/////////////BwA=","19":"b:/r/e8y/9v//3PvzuaWkCUEAIAAAAAAAAAAAAAAA=","30":"b:/r/e8y/9v//3PvzuaWkCQEAIAAAAAAAAAAAAAAA=","36":"b:/r/e8y/9v//3PvzuaWkCQEAIAAAAAAAAAAAAAAA=","38":"b:/r/e8y/9v//3PvzuaWkCQEAIAAAAAAAAAAAAAAA="},"packages/@n8n/permissions/src/utilities/has-global-scope.ee.ts":{"10":"b:/j/e8y/9v+/XPvzuaWkCAAAAAAAAAAAAAAAAAAA="},"packages/@n8n/permissions/src/utilities/has-scope.ee.ts":{"11":"b:/n//87//v//3////f/l+3vz/////////////BwA=","20":"b:/n//87//v//3////f/l+3vz/j///////n///BwA=","21":"b:/n//87//v//3////f/l+3vz/////////////BwA="},"packages/@n8n/scheduler/src/core/executor/executor.ts":{"147":"b:agrO4C707nsALPDKCAAAAAAAAAAAAAAAAAAAAAA=","186":"b:agrO4C707nsALPDKCAAAAAAAAAAAAAAAAAAAAAA=","223":"b:agrO4C707nsALPDKCAAAAAAAAAAAAAAAAAAAAAA=","226":"b:agrO4C707nsALPDKCAAAAAAAAAAAAAAAAAAAAAA=","237":"b:agrO4C707nsALPDKCAAAAAAAAAAAAAAAAAAAAAA=","240":"b:agrO4C707nsALPDKCAAAAAAAAAAAAAAAAAAAAAA=","245":"b:agrO4C707nsALPDKCAAAAAAAAAAAAAAAAAAAAAA=","258":"b:agrO4C707nsALPDKCAAAAAAAAAAAAAAAAAAAAAA=","259":"b:agrO4C707nsALPDKCAAAAAAAAAAAAAAAAAAAAAA=","263":"b:agrO4C707nsALPDKCAAAAAAAAAAAAAAAAAAAAAA=","309":"b:agrO4C707nsALPDKCAAAAAAAAAAAAAAAAAAAAAA=","311":"b:agrO4C707nsALPDKCAAAAAAAAAAAAAAAAAAAAAA=","314":"b:agrO4C707nsALPDKCAAAAAAAAAAAAAAAAAAAAAA=","327":"b:agrO4C707nsALPDKCAAAAAAAAAAAAAAAAAAAAAA=","348":"b:agrO4C707nsALPDKCAAAAAAAAAAAAAAAAAAAAAA=","400":"b:agrO4C707nsALPDKCAAAAAAAAAAAAAAAAAAAAAA=","408":"b:agrO4C707nsALPDKCAAAAAAAAAAAAAAAAAAAAAA=","411":"b:agrO4C707nsALPDKCAAAAAAAAAAAAAAAAAAAAAA=","421":"b:agrO4C707nsALPDKCAAAAAAAAAAAAAAAAAAAAAA=","426":"b:agrO4C707nsALPDKCAAAAAAAAAAAAAAAAAAAAAA=","427":"b:agrO4C707nsALPDKCAAAAAAAAAAAAAAAAAAAAAA=","439":"b:agrO4C707nsALPDKCAAAAAAAAAAAAAAAAAAAAAA=","448":"b:agrO4C707nsALPDKCAAAAAAAAAAAAAAAAAAAAAA=","464":"b:agrO4C707nsALPDKCAAAAAAAAAAAAAAAAAAAAAA=","471":"b:agrO4C707nsALPDKCAAAAAAAAAAAAAAAAAAAAAA=","480":"b:agrO4C707nsALPDKCAAAAAAAAAAAAAAAAAAAAAA="},"packages/@n8n/scheduler/src/core/executor/task-handler.ts":{"50":"b:agrO4C707nsALPDKCAABAAAAAAAAAAAAAAAAAAA=","52":"b:agrO4C707nsALPDKCAABAAAAAAAAAAAAAAAAAAA=","56":"b:agrO4C707nsALPDKCAABAAAAAAAAAAAAAAAAAAA=","109":"b:agrO4C707nsALPDKCAABAAAAAAAAAAAAAAAAAAA=","113":"b:agrO4C707nsALPDKCAABAAAAAAAAAAAAAAAAAAA=","120":"b:agrO4C707nsALPDKCAABAAAAAAAAAAAAAAAAAAA=","125":"b:agrO4C707nsALPDKCAABAAAAAAAAAAAAAAAAAAA="},"packages/@n8n/scheduler/src/core/lifecycle/alarm.ts":{"15":"b:agqO4C+0AHoBLIBAAAAAAAAAAAAAAAAAAAAAAAA=","18":"b:agqO4C+0AHoBLIBAAAAAAAAAAAAAAAAAAAAAAAA=","21":"b:agqO4C+0AHoBLIBAAAAAAAAAAAAAAAAAAAAAAAA=","33":"b:agqO4C+0AHoBLIBAAAAAAAAAAAAAAAAAAAAAAAA="},"packages/@n8n/scheduler/src/core/lifecycle/loop.ts":{"59":"b:/s/e9y/9Af7XPvzqiQAAAAAAAAAAAAAAAAAAAAA=","61":"b:/s/e9y/9Af7XPvzqiQAAAAAAAAAAAAAAAAAAAAA=","62":"b:/s/e9y/9Af7XPvzqiQAAAAAAAAAAAAAAAAAAAAA=","65":"b:/s/e9y/9Af7XPvzqiQAAAAAAAAAAAAAAAAAAAAA=","105":"b:/s/e9y/9Af7XPvzqiQAAAAAAAAAAAAAAAAAAAAA=","121":"b:/s/e9y/9Af7XPvzqiQAAAAAAAAAAAAAAAAAAAAA=","129":"b:/s/e9y/9Af7XPvzqiQAAAAAAAAAAAAAAAAAAAAA=","137":"b:/s/e9y/9Af7XPvzqiQAAAAAAAAAAAAAAAAAAAAA=","146":"b:/s/e9y/9Af7XPvzqiQAAAAAAAAAAAAAAAAAAAAA=","150":"b:/s/e9y/9Af7XPvzqiQAAAAAAAAAAAAAAAAAAAAA=","156":"b:/s/e9y/9Af7XPvzqiQAAAAAAAAAAAAAAAAAAAAA=","162":"b:/s/e9y/9Af7XPvzqiQAAAAAAAAAAAAAAAAAAAAA=","167":"b:/s/e9y/9Af7XPvzqiQAAAAAAAAAAAAAAAAAAAAA=","172":"b:/s/e9y/9Af7XPvzqiQAAAAAAAAAAAAAAAAAAAAA=","188":"b:/s/e9y/9Af7XPvzqiQAAAAAAAAAAAAAAAAAAAAA="},"packages/@n8n/scheduler/src/core/lifecycle/timeline.ts":{"16":"b:agqO4C+0AHoBLIBAAAAAAAAAAAAAAAAAAAAAAAA=","26":"b:agqO4C+0AHoBLIBAAAAAAAAAAAAAAAAAAAAAAAA=","34":"b:agqO4C+0AHoBLIBAAAAAAAAAAAAAAAAAAAAAAAA="},"packages/@n8n/scheduler/src/core/reaper/reap.ts":{"108":"b:/g+W2y64If7EPHy/CQAAAAAAAAAAAAAAAAAAAAA=","165":"b:/g+W2y64If7EPHy/CQAAAAAAAAAAAAAAAAAAAAA="},"packages/@n8n/scheduler/src/observability/pass-tracing.ts":{"17":"b:agqO4C+0AHoBLIBAAAAAAAAAAAAAAAAAAAAAAAA=","23":"b:agqO4C+0AHoBLIBAAAAAAAAAAAAAAAAAAAAAAAA=","24":"b:agqO4C+0AHoBLIBAAAAAAAAAAAAAAAAAAAAAAAA=","42":"b:agqO4C+0AHoBLIBAAAAAAAAAAAAAAAAAAAAAAAA="},"packages/@n8n/utils/src/errors/ensure-error.ts":{"2":"b:DPAAAgCAAqQHYFwEEEiAEAAAMCAAEAAAAAAAoAA="},"packages/@n8n/utils/src/promise/deferred-promise.ts":{"10":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","12":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA="},"packages/cli/src/active-executions.ts":{"56":"b:eNccHAjFviFHGjhI4QmAQMQ3CAAAMAAAAAAAgA4=","66":"b:eNccHAjFviFHGjhI4QmAQMQ3CAAAMAAAAAAAgA4=","73":"b:eNccHAjFviFHGjhI4QmAQMQ3CAAAMAAAAAAAgA4=","176":"b:eNccHAjFviFHGjhI4QmAQMQ3CAAAMAAAAAAAgA4=","180":"b:eNccHAjFviFHGjhI4QmAQMQ3CAAAMAAAAAAAgA4=","201":"b:eNccHAjFviFHGjhI4QmAQMQ3CAAAMAAAAAAAgA4=","211":"b:eNccHAjFviFHGjhI4QmAQMQ3CAAAMAAAAAAAgA4=","218":"b:eNccHAjFviFHGjhI4QmAQMQ3CAAAMAAAAAAAgA4=","224":"b:eNccHAjFviFHGjhI4QmAQMQ3CAAAMAAAAAAAgA4=","233":"b:eNccHAjFviFHGjhI4QmAQMQ3CAAAMAAAAAAAgA4=","263":"b:eNccHAjFviFHGjhI4QmAQMQ3CAAAMAAAAAAAgA4=","285":"b:eNccHAjFviFHGjhI4QmAQMQ3CAAAMAAAAAAAgA4=","303":"b:eNccHAjFviFHGjhI4QmAQMQ3CAAAMAAAAAAAgA4=","310":"b:eNccHAjFviFHGjhI4QmAQMQ3CAAAMAAAAAAAgA4=","330":"b:eNccHAjFviFHGjhI4QmAQMQ3CAAAMAAAAAAAgA4=","333":"b:eNccHAjFviFHGjhI4QmAQMQ3CAAAMAAAAAAAgA4=","340":"b:eNccHAjFviFHGjhI4QmAQMQ3CAAAMAAAAAAAgA4=","351":"b:eNccHAjFviFHGjhI4QmAQMQ3CAAAMAAAAAAAgA4=","357":"b:eNccHAjFviFHGjhI4QmAQMQ3CAAAMAAAAAAAgA4=","374":"b:eNccHAjFviFHGjhI4QmAQMQ3CAAAMAAAAAAAgA4=","380":"b:eNccHAjFviFHGjhI4QmAQMQ3CAAAMAAAAAAAgA4=","382":"b:eNccHAjFviFHGjhI4QmAQMQ3CAAAMAAAAAAAgA4=","397":"b:eNccHAjFviFHGjhI4QmAQMQ3CAAAMAAAAAAAgA4=","401":"b:eNccHAjFviFHGjhI4QmAQMQ3CAAAMAAAAAAAgA4=","405":"b:eNccHAjFviFHGjhI4QmAQMQ3CAAAMAAAAAAAgA4=","409":"b:eNccHAjFviFHGjhI4QmAQMQ3CAAAMAAAAAAAgA4=","414":"b:eNccHAjFviFHGjhI4QmAQMQ3CAAAMAAAAAAAgA4=","455":"b:eNccHAjFviFHGjhI4QmAQMQ3CAAAMAAAAAAAgA4="},"packages/cli/src/auth/auth-handler.registry.ts":{"7":"b:/j/e8y/8v+/XPvzmYW0CAAAAAAAAAAAAAAAAAAA=","20":"b:/j/e8y/8v+/XPvzmYW0CAAAAAAAAAAAAAAAAAAA=","30":"b:/j/e8y/8v+/XPvzmYW0CAAAAAAAAAAAAAAAAAAA=","82":"b:/j/e8y/8v+/XPvzmYW0CAAAAAAAAAAAAAAAAAAA=","94":"b:/j/e8y/8v+/XPvzmYW0CAAAAAAAAAAAAAAAAAAA=","112":"b:/j/e8y/8v+/XPvzmYW0CAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/auth/auth.service.ts":{"47":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA=","99":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA=","149":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA=","154":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA=","216":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA=","217":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA=","245":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA=","249":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA=","258":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA=","266":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA=","270":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA=","274":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA=","283":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA=","299":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA=","325":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA=","346":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA=","353":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA=","379":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA=","389":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA=","405":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA=","406":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA=","411":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA=","428":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA=","461":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA=","491":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA=","503":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA=","521":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA=","526":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA=","536":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA=","570":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA=","578":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA=","583":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA=","593":"b:/n/e+6/9v+//PvzvaX0CgMAJAEEgAAAAAAAAAAA="},"packages/cli/src/auth/handlers/email.auth-handler.ts":{"16":"b:/j/e8y/8v+/XPvzmYW0CAAAAAAAAAAAAAAAAAAA=","23":"b:/j/e8y/8v+/XPvzmYW0CAAAAAAAAAAAAAAAAAAA=","35":"b:/j/e8y/8v+/XPvzmYW0CAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/chat/chat-server.ts":{"21":"b:/k/e8C6pAQT0PnQoCRAAAEAIAAEAAAAAAAAAAAA=","23":"b:/k/e8C6pAQT0PnQoCRAAAEAIAAEAAAAAAAAAAAA=","24":"b:/k/e8C6pAQT0PnQoCRAAAEAIAAEAAAAAAAAAAAA=","29":"b:/k/e8C6pAQT0PnQoCRAAAEAIAAEAAAAAAAAAAAA=","35":"b:/k/e8C6pAQT0PnQoCRAAAEAIAAEAAAAAAAAAAAA=","40":"b:/k/e8C6pAQT0PnQoCRAAAEAIAAEAAAAAAAAAAAA=","43":"b:/k/e8C6pAQT0PnQoCRAAAEAIAAEAAAAAAAAAAAA=","52":"b:/k/e8C6pAQT0PnQoCRAAAEAIAAEAAAAAAAAAAAA="},"packages/cli/src/chat/chat-service.ts":{"44":"b:6gXW2wy4If7UOny6SUAAAAAASgAAAAAAAAAAAAA=","47":"b:6gXW2wy4If7UOny6SUAAAAAASgAAAAAAAAAAAAA=","51":"b:6gXW2wy4If7UOny6SUAAAAAASgAAAAAAAAAAAAA=","63":"b:6gXW2wy4If7UOny6SUAAAAAASgAAAAAAAAAAAAA=","69":"b:6gXW2wy4If7UOny6SUAAAAAASgAAAAAAAAAAAAA=","74":"b:6gXW2wy4If7UOny6SUAAAAAASgAAAAAAAAAAAAA=","121":"b:6gXW2wy4If7UOny6SUAAAAAASgAAAAAAAAAAAAA=","123":"b:6gXW2wy4If7UOny6SUAAAAAASgAAAAAAAAAAAAA=","146":"b:6gXW2wy4If7UOny6SUAAAAAASgAAAAAAAAAAAAA=","176":"b:6gXW2wy4If7UOny6SUAAAAAASgAAAAAAAAAAAAA=","181":"b:6gXW2wy4If7UOny6SUAAAAAASgAAAAAAAAAAAAA=","190":"b:6gXW2wy4If7UOny6SUAAAAAASgAAAAAAAAAAAAA=","191":"b:6gXW2wy4If7UOny6SUAAAAAASgAAAAAAAAAAAAA=","237":"b:6gXW2wy4If7UOny6SUAAAAAASgAAAAAAAAAAAAA=","238":"b:6gXW2wy4If7UOny6SUAAAAAASgAAAAAAAAAAAAA=","268":"b:6gXW2wy4If7UOny6SUAAAAAASgAAAAAAAAAAAAA=","294":"b:6gXW2wy4If7UOny6SUAAAAAASgAAAAAAAAAAAAA=","320":"b:6gXW2wy4If7UOny6SUAAAAAASgAAAAAAAAAAAAA=","322":"b:6gXW2wy4If7UOny6SUAAAAAASgAAAAAAAAAAAAA=","329":"b:6gXW2wy4If7UOny6SUAAAAAASgAAAAAAAAAAAAA=","335":"b:6gXW2wy4If7UOny6SUAAAAAASgAAAAAAAAAAAAA=","340":"b:6gXW2wy4If7UOny6SUAAAAAASgAAAAAAAAAAAAA=","350":"b:6gXW2wy4If7UOny6SUAAAAAASgAAAAAAAAAAAAA=","357":"b:6gXW2wy4If7UOny6SUAAAAAASgAAAAAAAAAAAAA=","386":"b:6gXW2wy4If7UOny6SUAAAAAASgAAAAAAAAAAAAA="},"packages/cli/src/concurrency/concurrency-capacity-reservation.ts":{"21":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","23":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","30":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA="},"packages/cli/src/concurrency/concurrency-control.service.ts":{"35":"b:eJccFAjFviFHGjhI4QkAQMQ3AAAAAAAAAAAAgAI=","45":"b:eJccFAjFviFHGjhI4QkAQMQ3AAAAAAAAAAAAgAI=","90":"b:eJccFAjFviFHGjhI4QkAQMQ3AAAAAAAAAAAAgAI=","100":"b:eJccFAjFviFHGjhI4QkAQMQ3AAAAAAAAAAAAgAI=","113":"b:eJccFAjFviFHGjhI4QkAQMQ3AAAAAAAAAAAAgAI=","135":"b:eJccFAjFviFHGjhI4QkAQMQ3AAAAAAAAAAAAgAI=","136":"b:eJccFAjFviFHGjhI4QkAQMQ3AAAAAAAAAAAAgAI=","145":"b:eJccFAjFviFHGjhI4QkAQMQ3AAAAAAAAAAAAgAI=","150":"b:eJccFAjFviFHGjhI4QkAQMQ3AAAAAAAAAAAAgAI=","158":"b:eJccFAjFviFHGjhI4QkAQMQ3AAAAAAAAAAAAgAI=","173":"b:eJccFAjFviFHGjhI4QkAQMQ3AAAAAAAAAAAAgAI=","183":"b:eJccFAjFviFHGjhI4QkAQMQ3AAAAAAAAAAAAgAI=","193":"b:eJccFAjFviFHGjhI4QkAQMQ3AAAAAAAAAAAAgAI=","205":"b:eJccFAjFviFHGjhI4QkAQMQ3AAAAAAAAAAAAgAI=","208":"b:eJccFAjFviFHGjhI4QkAQMQ3AAAAAAAAAAAAgAI=","225":"b:eJccFAjFviFHGjhI4QkAQMQ3AAAAAAAAAAAAgAI=","233":"b:eJccFAjFviFHGjhI4QkAQMQ3AAAAAAAAAAAAgAI=","237":"b:eJccFAjFviFHGjhI4QkAQMQ3AAAAAAAAAAAAgAI=","244":"b:eJccFAjFviFHGjhI4QkAQMQ3AAAAAAAAAAAAgAI="},"packages/cli/src/controller.registry.ts":{"36":"b:/j/e82/9v//ffv7qaWkiGjAAAUAAAAAAAQAAQAA=","45":"b:/j/e82/9v//ffv7qaWkiGjAAAUAAAAAAAQAAQAA=","53":"b:/j/e82/9v//ffv7qaWkiGjAAAUAAAAAAAQAAQAA=","65":"b:/j/e82/9v//ffv7qaWkiGjAAAUAAAAAAAQAAQAA=","88":"b:/j/e82/9v//ffv7qaWkiGjAAAUAAAAAAAQAAQAA=","107":"b:/j/e82/9v//ffv7qaWkiGjAAAUAAAAAAAQAAQAA=","133":"b:/j/e82/9v//ffv7qaWkiGjAAAUAAAAAAAQAAQAA=","138":"b:/j/e82/9v//ffv7qaWkiGjAAAUAAAAAAAQAAQAA=","172":"b:/j/e82/9v//ffv7qaWkiGjAAAUAAAAAAAQAAQAA=","252":"b:/j/e82/9v//ffv7qaWkiGjAAAUAAAAAAAQAAQAA=","253":"b:/j/e82/9v//ffv7qaWkiGjAAAUAAAAAAAQAAQAA=","262":"b:/j/e82/9v//ffv7qaWkiGjAAAUAAAAAAAQAAQAA=","263":"b:/j/e82/9v//ffv7qaWkiGjAAAUAAAAAAAQAAQAA="},"packages/cli/src/controllers/auth.controller.ts":{"41":"b:/n/e+y/9v//XPvzvaX0GAAAAAAAAAAAAAAAAAAA=","68":"b:/n/e+y/9v//XPvzvaX0GAAAAAAAAAAAAAAAAAAA=","110":"b:/n/e+y/9v//XPvzvaX0GAAAAAAAAAAAAAAAAAAA=","116":"b:/n/e+y/9v//XPvzvaX0GAAAAAAAAAAAAAAAAAAA=","132":"b:/n/e+y/9v//XPvzvaX0GAAAAAAAAAAAAAAAAAAA=","165":"b:/n/e+y/9v//XPvzvaX0GAAAAAAAAAAAAAAAAAAA=","193":"b:/n/e+y/9v//XPvzvaX0GAAAAAAAAAAAAAAAAAAA=","206":"b:/n/e+y/9v//XPvzvaX0GAAAAAAAAAAAAAAAAAAA=","252":"b:/n/e+y/9v//XPvzvaX0GAAAAAAAAAAAAAAAAAAA=","261":"b:/n/e+y/9v//XPvzvaX0GAAAAAAAAAAAAAAAAAAA=","280":"b:/n/e+y/9v//XPvzvaX0GAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/controllers/module-settings.controller.ts":{"7":"b:/k/e+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","13":"b:/k/e+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/controllers/project.controller.ts":{"37":"b:/k/++y75Ad7X/n4rCXBEGjFAASAAgAAADAAAQAA=","43":"b:/k/++y75Ad7X/n4rCXBEGjFAASAAgAAADAAAQAA=","64":"b:/k/++y75Ad7X/n4rCXBEGjFAASAAgAAADAAAQAA=","75":"b:/k/++y75Ad7X/n4rCXBEGjFAASAAgAAADAAAQAA=","92":"b:/k/++y75Ad7X/n4rCXBEGjFAASAAgAAADAAAQAA=","110":"b:/k/++y75Ad7X/n4rCXBEGjFAASAAgAAADAAAQAA=","118":"b:/k/++y75Ad7X/n4rCXBEGjFAASAAgAAADAAAQAA=","135":"b:/k/++y75Ad7X/n4rCXBEGjFAASAAgAAADAAAQAA=","147":"b:/k/++y75Ad7X/n4rCXBEGjFAASAAgAAADAAAQAA=","157":"b:/k/++y75Ad7X/n4rCXBEGjFAASAAgAAADAAAQAA=","164":"b:/k/++y75Ad7X/n4rCXBEGjFAASAAgAAADAAAQAA=","174":"b:/k/++y75Ad7X/n4rCXBEGjFAASAAgAAADAAAQAA=","183":"b:/k/++y75Ad7X/n4rCXBEGjFAASAAgAAADAAAQAA=","193":"b:/k/++y75Ad7X/n4rCXBEGjFAASAAgAAADAAAQAA=","203":"b:/k/++y75Ad7X/n4rCXBEGjFAASAAgAAADAAAQAA=","235":"b:/k/++y75Ad7X/n4rCXBEGjFAASAAgAAADAAAQAA=","257":"b:/k/++y75Ad7X/n4rCXBEGjFAASAAgAAADAAAQAA=","270":"b:/k/++y75Ad7X/n4rCXBEGjFAASAAgAAADAAAQAA="},"packages/cli/src/controllers/role.controller.ts":{"39":"b:/k/e+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","46":"b:/k/e+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","53":"b:/k/e+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","54":"b:/k/e+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","55":"b:/k/e+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","56":"b:/k/e+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","61":"b:/k/e+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","88":"b:/k/e+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","112":"b:/k/e+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","118":"b:/k/e+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","124":"b:/k/e+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","134":"b:/k/e+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","145":"b:/k/e+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","165":"b:/k/e+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","188":"b:/k/e+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/controllers/users.controller.ts":{"41":"b:/k/i8y75AZj0PnQrCRAAAAACAAAAAAAABAAAAAA=","49":"b:/k/i8y75AZj0PnQrCRAAAAACAAAAAAAABAAAAAA=","73":"b:/k/i8y75AZj0PnQrCRAAAAACAAAAAAAABAAAAAA=","82":"b:/k/i8y75AZj0PnQrCRAAAAACAAAAAAAABAAAAAA=","95":"b:/k/i8y75AZj0PnQrCRAAAAACAAAAAAAABAAAAAA=","102":"b:/k/i8y75AZj0PnQrCRAAAAACAAAAAAAABAAAAAA=","120":"b:/k/i8y75AZj0PnQrCRAAAAACAAAAAAAABAAAAAA=","142":"b:/k/i8y75AZj0PnQrCRAAAAACAAAAAAAABAAAAAA=","171":"b:/k/i8y75AZj0PnQrCRAAAAACAAAAAAAABAAAAAA=","192":"b:/k/i8y75AZj0PnQrCRAAAAACAAAAAAAABAAAAAA=","199":"b:/k/i8y75AZj0PnQrCRAAAAACAAAAAAAABAAAAAA="},"packages/cli/src/environments.ee/variables/variables.service.ee.ts":{"30":"b:eLccEAjlviF3OjxIYSkAUMQVAAAAAAAAAQAAgAA=","38":"b:eLccEAjlviF3OjxIYSkAUMQVAAAAAAAAAQAAgAA=","45":"b:eLccEAjlviF3OjxIYSkAUMQVAAAAAAAAAQAAgAA=","68":"b:eLccEAjlviF3OjxIYSkAUMQVAAAAAAAAAQAAgAA=","73":"b:eLccEAjlviF3OjxIYSkAUMQVAAAAAAAAAQAAgAA=","77":"b:eLccEAjlviF3OjxIYSkAUMQVAAAAAAAAAQAAgAA=","83":"b:eLccEAjlviF3OjxIYSkAUMQVAAAAAAAAAQAAgAA=","85":"b:eLccEAjlviF3OjxIYSkAUMQVAAAAAAAAAQAAgAA=","92":"b:eLccEAjlviF3OjxIYSkAUMQVAAAAAAAAAQAAgAA=","98":"b:eLccEAjlviF3OjxIYSkAUMQVAAAAAAAAAQAAgAA=","108":"b:eLccEAjlviF3OjxIYSkAUMQVAAAAAAAAAQAAgAA=","115":"b:eLccEAjlviF3OjxIYSkAUMQVAAAAAAAAAQAAgAA=","123":"b:eLccEAjlviF3OjxIYSkAUMQVAAAAAAAAAQAAgAA=","127":"b:eLccEAjlviF3OjxIYSkAUMQVAAAAAAAAAQAAgAA=","145":"b:eLccEAjlviF3OjxIYSkAUMQVAAAAAAAAAQAAgAA=","173":"b:eLccEAjlviF3OjxIYSkAUMQVAAAAAAAAAQAAgAA=","178":"b:eLccEAjlviF3OjxIYSkAUMQVAAAAAAAAAQAAgAA=","183":"b:eLccEAjlviF3OjxIYSkAUMQVAAAAAAAAAQAAgAA=","191":"b:eLccEAjlviF3OjxIYSkAUMQVAAAAAAAAAQAAgAA=","202":"b:eLccEAjlviF3OjxIYSkAUMQVAAAAAAAAAQAAgAA=","204":"b:eLccEAjlviF3OjxIYSkAUMQVAAAAAAAAAQAAgAA=","207":"b:eLccEAjlviF3OjxIYSkAUMQVAAAAAAAAAQAAgAA=","214":"b:eLccEAjlviF3OjxIYSkAUMQVAAAAAAAAAQAAgAA=","221":"b:eLccEAjlviF3OjxIYSkAUMQVAAAAAAAAAQAAgAA=","263":"b:eLccEAjlviF3OjxIYSkAUMQVAAAAAAAAAQAAgAA="},"packages/cli/src/eventbus/event-message-classes/event-message-node.ts":{"34":"b:eJccFAjFviFAGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","42":"b:eJccFAjFviFAGjhI4QkAQMQ1AAAAAAAAAAAAgAA="},"packages/cli/src/eventbus/event-message-classes/event-message-workflow.ts":{"36":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","44":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA="},"packages/cli/src/eventbus/message-event-bus/message-event-bus.ts":{"58":"b:eJccHEjFviFPGjhI4VkAYMU3AAAIAAAAAAAEoAA=","78":"b:eJccHEjFviFPGjhI4VkAYMU3AAAIAAAAAAAEoAA=","117":"b:eJccHEjFviFPGjhI4VkAYMU3AAAIAAAAAAAEoAA=","128":"b:eJccHEjFviFPGjhI4VkAYMU3AAAIAAAAAAAEoAA=","131":"b:eJccHEjFviFPGjhI4VkAYMU3AAAIAAAAAAAEoAA=","142":"b:eJccHEjFviFPGjhI4VkAYMU3AAAIAAAAAAAEoAA=","153":"b:eJccHEjFviFPGjhI4VkAYMU3AAAIAAAAAAAEoAA=","160":"b:eJccHEjFviFPGjhI4VkAYMU3AAAIAAAAAAAEoAA=","183":"b:eJccHEjFviFPGjhI4VkAYMU3AAAIAAAAAAAEoAA=","187":"b:eJccHEjFviFPGjhI4VkAYMU3AAAIAAAAAAAEoAA=","188":"b:eJccHEjFviFPGjhI4VkAYMU3AAAIAAAAAAAEoAA=","193":"b:eJccHEjFviFPGjhI4VkAYMU3AAAIAAAAAAAEoAA=","199":"b:eJccHEjFviFPGjhI4VkAYMU3AAAIAAAAAAAEoAA=","205":"b:eJccHEjFviFPGjhI4VkAYMU3AAAIAAAAAAAEoAA=","211":"b:eJccHEjFviFPGjhI4VkAYMU3AAAIAAAAAAAEoAA=","216":"b:eJccHEjFviFPGjhI4VkAYMU3AAAIAAAAAAAEoAA=","230":"b:eJccHEjFviFPGjhI4VkAYMU3AAAIAAAAAAAEoAA=","241":"b:eJccHEjFviFPGjhI4VkAYMU3AAAIAAAAAAAEoAA=","245":"b:eJccHEjFviFPGjhI4VkAYMU3AAAIAAAAAAAEoAA=","249":"b:eJccHEjFviFPGjhI4VkAYMU3AAAIAAAAAAAEoAA=","253":"b:eJccHEjFviFPGjhI4VkAYMU3AAAIAAAAAAAEoAA=","257":"b:eJccHEjFviFPGjhI4VkAYMU3AAAIAAAAAAAEoAA=","261":"b:eJccHEjFviFPGjhI4VkAYMU3AAAIAAAAAAAEoAA=","265":"b:eJccHEjFviFPGjhI4VkAYMU3AAAIAAAAAAAEoAA=","269":"b:eJccHEjFviFPGjhI4VkAYMU3AAAIAAAAAAAEoAA=","280":"b:eJccHEjFviFPGjhI4VkAYMU3AAAIAAAAAAAEoAA=","346":"b:eJccHEjFviFPGjhI4VkAYMU3AAAIAAAAAAAEoAA=","362":"b:eJccHEjFviFPGjhI4VkAYMU3AAAIAAAAAAAEoAA="},"packages/cli/src/events/relays/event-relay.ts":{"8":"b:/j/e8y/8v+/XPvzmYW0CAAAAAAAAAAAAAAAAAAA=","10":"b:/j/e8y/8v+/XPvzmYW0CAAAAAAAAAAAAAAAAAAA=","18":"b:/j/e8y/8v+/XPvzmYW0CAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/events/relays/log-streaming.event-relay.ts":{"21":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","25":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","39":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","40":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","47":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","51":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","56":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","68":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","77":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","79":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","80":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","81":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","82":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","83":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","84":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","85":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","86":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","87":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","88":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","89":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","90":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","91":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","92":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","93":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","94":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","95":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","96":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","97":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","98":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","99":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","100":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","101":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","102":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","103":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","104":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","105":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","106":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","107":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","108":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","109":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","110":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","111":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","112":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","113":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","114":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","115":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","116":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","117":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","118":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","120":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","121":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","122":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","123":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","124":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","125":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","126":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","127":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","129":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","130":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","132":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","133":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","135":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","137":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","139":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","140":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","142":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","143":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","144":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","145":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","146":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","147":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","148":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","149":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","150":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","151":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","152":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","153":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","154":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","155":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","156":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","157":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","158":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","159":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","160":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","161":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","162":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","163":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","164":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","165":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","166":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","167":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","168":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","169":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","170":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","171":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","172":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","173":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","174":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","175":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","176":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","177":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","178":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","179":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","180":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","181":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","182":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","183":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","184":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","185":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","186":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","187":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","188":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","189":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","190":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","191":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","192":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","193":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","194":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","195":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","196":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","197":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","198":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","205":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","213":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","227":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","234":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","240":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","245":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","253":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","265":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","273":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","281":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","289":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","302":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","320":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","333":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","354":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","390":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","455":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","478":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","499":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","511":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","531":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","556":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","564":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","572":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","580":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","588":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","596":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","608":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","616":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","623":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","638":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","646":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","654":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","668":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","676":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","684":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","696":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","712":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","744":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","756":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","767":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","775":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","800":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","809":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","823":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","831":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","839":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","850":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","864":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","876":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","889":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","901":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","922":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","931":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","937":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","946":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","956":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","965":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","974":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","983":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","992":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1001":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1010":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1019":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1033":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1044":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1052":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1063":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1070":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1079":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1097":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1112":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1122":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1140":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1155":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1182":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1191":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1198":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1205":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1212":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1219":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1226":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1233":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1240":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1247":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1254":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1261":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1268":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1275":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1286":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1293":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1304":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1311":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1318":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1330":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1378":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1394":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1414":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1427":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1450":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1471":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1478":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1485":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1492":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1499":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1506":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1513":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1520":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1531":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1549":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1564":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1578":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1591":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1609":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1617":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1625":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1636":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1648":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY=","1656":"b:/v/+/+/9v//////u6/2i7P2/CSQIsAIADwAk8AY="},"packages/cli/src/execution-lifecycle/execution-lifecycle-hooks.ts":{"58":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","70":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","88":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","103":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","119":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","134":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","161":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","170":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","180":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","222":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","224":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","226":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","236":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","238":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","254":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","277":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","291":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","308":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","326":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","404":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","464":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","485":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","495":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","500":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","504":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","514":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","519":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","531":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","532":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","537":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","542":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","553":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","576":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","594":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","724":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","733":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","829":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","858":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","865":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","905":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","937":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY=","994":"b:eNccHAjHviFHGzhI4xmAQMQ3AAQAGAAAACAwgAY="},"packages/cli/src/execution-lifecycle/restore-binary-data-id.ts":{"30":"b:eNc8FAjFviFHGjhI4QmAQMQ1AAAAEAAAAAAAgAA=","64":"b:eNc8FAjFviFHGjhI4QmAQMQ1AAAAEAAAAAAAgAA=","78":"b:eNc8FAjFviFHGjhI4QmAQMQ1AAAAEAAAAAAAgAA="},"packages/cli/src/execution-lifecycle/shared/shared-hook-functions.ts":{"13":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","29":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","79":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","95":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA="},"packages/cli/src/execution-lifecycle/to-save-settings.ts":{"20":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA="},"packages/cli/src/executions/execution-data/db-store.ts":{"14":"b:eNccHAjFviFHGjhI4wmAQMY3AAAAEAABABAAgAQ=","16":"b:eNccHAjFviFHGjhI4wmAQMY3AAAAEAABABAAgAQ=","32":"b:eNccHAjFviFHGjhI4wmAQMY3AAAAEAABABAAgAQ=","50":"b:eNccHAjFviFHGjhI4wmAQMY3AAAAEAABABAAgAQ=","58":"b:eNccHAjFviFHGjhI4wmAQMY3AAAAEAABABAAgAQ=","76":"b:eNccHAjFviFHGjhI4wmAQMY3AAAAEAABABAAgAQ=","91":"b:eNccHAjFviFHGjhI4wmAQMY3AAAAEAABABAAgAQ=","105":"b:eNccHAjFviFHGjhI4wmAQMY3AAAAEAABABAAgAQ=","109":"b:eNccHAjFviFHGjhI4wmAQMY3AAAAEAABABAAgAQ="},"packages/cli/src/executions/execution-data/types.ts":{"13":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","27":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","39":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","47":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA="},"packages/cli/src/executions/execution-id.ts":{"8":"b:eAcAEAjBAAFHGjgIYwEAQMY3AAAAAAAAAAAAAAA=","14":"b:eAcAEAjBAAFHGjgIYwEAQMY3AAAAAAAAAAAAAAA=","23":"b:eAcAEAjBAAFHGjgIYwEAQMY3AAAAAAAAAAAAAAA="},"packages/cli/src/executions/execution-persistence.ts":{"79":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","99":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","109":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","115":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","170":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","207":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","227":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","299":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","397":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","418":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","434":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","487":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","488":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","496":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","497":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","502":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","511":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","557":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","570":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","591":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","596":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","639":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","649":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","655":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","659":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","662":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","678":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","692":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","722":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","736":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","755":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","756":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","759":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","772":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","789":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","811":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","831":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","838":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","888":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","907":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","926":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","952":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","976":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","988":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","998":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","1019":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","1032":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","1037":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","1046":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","1062":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","1082":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","1095":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","1109":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","1121":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","1137":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","1153":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","1159":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY=","1169":"b:ePc8HEjlviHXmj5o7wmARO5/AEAAEgYBQBgAgAY="},"packages/cli/src/executions/execution-redaction-proxy.service.ts":{"13":"b:eAcAEAjBAAFHGjgIYwEAQMY3AAAAAAAAAAAAAAA=","17":"b:eAcAEAjBAAFHGjgIYwEAQMY3AAAAAAAAAAAAAAA=","27":"b:eAcAEAjBAAFHGjgIYwEAQMY3AAAAAAAAAAAAAAA="},"packages/cli/src/executions/execution.service.ee.ts":{"13":"b:eAcAEAjBAABHGjAIIxAAQMY3AAAAAAAAAAAAAAA=","19":"b:eAcAEAjBAABHGjAIIxAAQMY3AAAAAAAAAAAAAAA="},"packages/cli/src/executions/execution.service.ts":{"109":"b:eAcAFAjlviHXmzxob4GARO9/AEAAEgYAAAiAAAI=","139":"b:eAcAFAjlviHXmzxob4GARO9/AEAAEgYAAAiAAAI=","202":"b:eAcAFAjlviHXmzxob4GARO9/AEAAEgYAAAiAAAI=","234":"b:eAcAFAjlviHXmzxob4GARO9/AEAAEgYAAAiAAAI=","407":"b:eAcAFAjlviHXmzxob4GARO9/AEAAEgYAAAiAAAI=","413":"b:eAcAFAjlviHXmzxob4GARO9/AEAAEgYAAAiAAAI=","448":"b:eAcAFAjlviHXmzxob4GARO9/AEAAEgYAAAiAAAI=","487":"b:eAcAFAjlviHXmzxob4GARO9/AEAAEgYAAAiAAAI=","495":"b:eAcAFAjlviHXmzxob4GARO9/AEAAEgYAAAiAAAI=","510":"b:eAcAFAjlviHXmzxob4GARO9/AEAAEgYAAAiAAAI=","518":"b:eAcAFAjlviHXmzxob4GARO9/AEAAEgYAAAiAAAI=","556":"b:eAcAFAjlviHXmzxob4GARO9/AEAAEgYAAAiAAAI=","577":"b:eAcAFAjlviHXmzxob4GARO9/AEAAEgYAAAiAAAI=","585":"b:eAcAFAjlviHXmzxob4GARO9/AEAAEgYAAAiAAAI=","595":"b:eAcAFAjlviHXmzxob4GARO9/AEAAEgYAAAiAAAI=","624":"b:eAcAFAjlviHXmzxob4GARO9/AEAAEgYAAAiAAAI=","644":"b:eAcAFAjlviHXmzxob4GARO9/AEAAEgYAAAiAAAI=","666":"b:eAcAFAjlviHXmzxob4GARO9/AEAAEgYAAAiAAAI=","700":"b:eAcAFAjlviHXmzxob4GARO9/AEAAEgYAAAiAAAI=","745":"b:eAcAFAjlviHXmzxob4GARO9/AEAAEgYAAAiAAAI=","757":"b:eAcAFAjlviHXmzxob4GARO9/AEAAEgYAAAiAAAI=","773":"b:eAcAFAjlviHXmzxob4GARO9/AEAAEgYAAAiAAAI=","774":"b:eAcAFAjlviHXmzxob4GARO9/AEAAEgYAAAiAAAI=","802":"b:eAcAFAjlviHXmzxob4GARO9/AEAAEgYAAAiAAAI=","832":"b:eAcAFAjlviHXmzxob4GARO9/AEAAEgYAAAiAAAI=","847":"b:eAcAFAjlviHXmzxob4GARO9/AEAAEgYAAAiAAAI=","855":"b:eAcAFAjlviHXmzxob4GARO9/AEAAEgYAAAiAAAI=","887":"b:eAcAFAjlviHXmzxob4GARO9/AEAAEgYAAAiAAAI=","895":"b:eAcAFAjlviHXmzxob4GARO9/AEAAEgYAAAiAAAI=","906":"b:eAcAFAjlviHXmzxob4GARO9/AEAAEgYAAAiAAAI="},"packages/cli/src/executions/executions.controller.ts":{"22":"b:eAcAFAjFviFHGzhIY4GAQMc3AAAAEAAAAACAAAI=","30":"b:eAcAFAjFviFHGzhIY4GAQMc3AAAAEAAAAACAAAI=","35":"b:eAcAFAjFviFHGzhIY4GAQMc3AAAAEAAAAACAAAI=","62":"b:eAcAFAjFviFHGzhIY4GAQMc3AAAAEAAAAACAAAI=","73":"b:eAcAFAjFviFHGzhIY4GAQMc3AAAAEAAAAACAAAI=","87":"b:eAcAFAjFviFHGzhIY4GAQMc3AAAAEAAAAACAAAI=","103":"b:eAcAFAjFviFHGzhIY4GAQMc3AAAAEAAAAACAAAI=","114":"b:eAcAFAjFviFHGzhIY4GAQMc3AAAAEAAAAACAAAI=","133":"b:eAcAFAjFviFHGzhIY4GAQMc3AAAAEAAAAACAAAI=","144":"b:eAcAFAjFviFHGzhIY4GAQMc3AAAAEAAAAACAAAI=","165":"b:eAcAFAjFviFHGzhIY4GAQMc3AAAAEAAAAACAAAI="},"packages/cli/src/executions/pre-execution-checks/credentials-permission-checker.ts":{"18":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA=","27":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA=","35":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA=","53":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA=","75":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA=","93":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA=","125":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA=","139":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA=","149":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA=","172":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA=","201":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA=","206":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA=","215":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA=","217":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA=","218":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA=","227":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA=","235":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA=","243":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA=","251":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA=","255":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA=","268":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA=","283":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA=","302":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA=","352":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA=","399":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA=","400":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA=","416":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA=","430":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA=","451":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA=","480":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA=","496":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA=","497":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA=","524":"b:ePc8FAjFviF3mjtI4YmASMQ1AAgAMAAAAAAwoAA="},"packages/cli/src/executions/pre-execution-checks/workflow-pre-execute.ts":{"30":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","37":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","78":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","95":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA="},"packages/cli/src/executions/sum-binary-data-bytes.ts":{"13":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","37":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","64":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA="},"packages/cli/src/expression-observability/expression-observability.provider.ts":{"45":"b:eLccGAzFviF3OjxIYSmAUcQVAEAAAAAAAIAEgAA=","48":"b:eLccGAzFviF3OjxIYSmAUcQVAEAAAAAAAIAEgAA=","73":"b:eLccGAzFviF3OjxIYSmAUcQVAEAAAAAAAIAEgAA=","74":"b:eLccGAzFviF3OjxIYSmAUcQVAEAAAAAAAIAEgAA=","75":"b:eLccGAzFviF3OjxIYSmAUcQVAEAAAAAAAIAEgAA=","79":"b:eLccGAzFviF3OjxIYSmAUcQVAEAAAAAAAIAEgAA=","83":"b:eLccGAzFviF3OjxIYSmAUcQVAEAAAAAAAIAEgAA=","84":"b:eLccGAzFviF3OjxIYSmAUcQVAEAAAAAAAIAEgAA=","85":"b:eLccGAzFviF3OjxIYSmAUcQVAEAAAAAAAIAEgAA=","86":"b:eLccGAzFviF3OjxIYSmAUcQVAEAAAAAAAIAEgAA=","90":"b:eLccGAzFviF3OjxIYSmAUcQVAEAAAAAAAIAEgAA=","122":"b:eLccGAzFviF3OjxIYSmAUcQVAEAAAAAAAIAEgAA=","129":"b:eLccGAzFviF3OjxIYSmAUcQVAEAAAAAAAIAEgAA=","137":"b:eLccGAzFviF3OjxIYSmAUcQVAEAAAAAAAIAEgAA=","145":"b:eLccGAzFviF3OjxIYSmAUcQVAEAAAAAAAIAEgAA=","155":"b:eLccGAzFviF3OjxIYSmAUcQVAEAAAAAAAIAEgAA=","186":"b:eLccGAzFviF3OjxIYSmAUcQVAEAAAAAAAIAEgAA=","194":"b:eLccGAzFviF3OjxIYSmAUcQVAEAAAAAAAIAEgAA=","203":"b:eLccGAzFviF3OjxIYSmAUcQVAEAAAAAAAIAEgAA=","207":"b:eLccGAzFviF3OjxIYSmAUcQVAEAAAAAAAIAEgAA=","211":"b:eLccGAzFviF3OjxIYSmAUcQVAEAAAAAAAIAEgAA=","212":"b:eLccGAzFviF3OjxIYSmAUcQVAEAAAAAAAIAEgAA="},"packages/cli/src/external-hooks.ts":{"57":"b:+L++lCz9viH3Pnxs6SkAQMQ/AAAAAAAAAAAAgAA=","184":"b:+L++lCz9viH3Pnxs6SkAQMQ/AAAAAAAAAAAAgAA=","201":"b:+L++lCz9viH3Pnxs6SkAQMQ/AAAAAAAAAAAAgAA=","221":"b:+L++lCz9viH3Pnxs6SkAQMQ/AAAAAAAAAAAAgAA=","232":"b:+L++lCz9viH3Pnxs6SkAQMQ/AAAAAAAAAAAAgAA=","236":"b:+L++lCz9viH3Pnxs6SkAQMQ/AAAAAAAAAAAAgAA="},"packages/cli/src/generic-helpers.ts":{"13":"b:+L+CkCz9viH3PnxsaSkAQEAKACAAAAAAAAAAAAA=","25":"b:+L+CkCz9viH3PnxsaSkAQEAKACAAAAAAAAAAAAA="},"packages/cli/src/license.ts":{"49":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","59":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","78":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","79":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","81":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","82":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","84":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","85":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","87":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","88":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","90":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","91":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","92":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","118":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","120":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","146":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","160":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","175":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","185":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","190":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","197":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","214":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","216":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","224":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","237":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","248":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","265":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","269":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","278":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","288":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","301":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","305":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","309":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","314":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","319":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","324":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","329":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","334":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","339":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","344":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","349":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","354":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","359":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","364":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","369":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","374":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","379":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","384":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","389":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","394":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","399":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","404":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","409":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","414":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","419":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","424":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","428":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","432":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","436":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","446":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","456":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","459":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","463":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","470":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","475":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","480":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","485":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","490":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","498":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","502":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","506":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","514":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","522":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","537":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","552":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","561":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","566":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","572":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA=","575":"b:/n/e8y/9v+/3PvzvaX0CQAACAAAAAAAAAAAAAAA="},"packages/cli/src/load-nodes-and-credentials.ts":{"69":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","78":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","139":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","143":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","144":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","147":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","163":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","166":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","176":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","180":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","186":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","188":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","192":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","196":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","200":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","204":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","208":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","212":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","253":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","260":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","264":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","282":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","312":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","313":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","328":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","339":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","345":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","354":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","365":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","368":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","369":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","388":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","391":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","396":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","405":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","406":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","413":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","429":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","433":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","442":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","453":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","464":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","474":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","551":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","564":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","581":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","582":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","585":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","597":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","603":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","608":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","640":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","657":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","659":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","662":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","667":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","682":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","689":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","710":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","716":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","744":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","745":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","760":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","769":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","771":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","778":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","781":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","809":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","824":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","828":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","829":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","835":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","845":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","846":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA=","847":"b:+PeesK71vzX3fnxMezkAZOAZAYEgMCUIADQEIAA="},"packages/cli/src/manual-execution.service.ts":{"29":"b:eAUAAAjDAABGGhAIYwAAiME3AAQACAAAACAEAAA=","34":"b:eAUAAAjDAABGGhAIYwAAiME3AAQACAAAACAEAAA=","54":"b:eAUAAAjDAABGGhAIYwAAiME3AAQACAAAACAEAAA=","67":"b:eAUAAAjDAABGGhAIYwAAiME3AAQACAAAACAEAAA="},"packages/cli/src/metrics/prometheus/workflow-execution-duration-metrics.service.ts":{"18":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","23":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","27":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","40":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA="},"packages/cli/src/modules/agents/agent-config.service.ts":{"61":[1,2,3],"76":[1,2,3],"90":[1,2,3],"103":[1,2,3],"179":[1,2,3],"204":[1,2,3],"209":[1,2,3],"210":[1,2,3],"216":[1,2,3],"238":[1,2,3],"261":[1,2,3],"272":[1,2,3],"274":[1,2,3],"279":[1,2,3],"283":[1,2,3],"286":[1,2,3],"288":[1,2,3],"295":[1,2,3],"329":[1,2,3],"362":[1,2,3],"369":[1,2,3],"380":[1,2,3],"386":[1,2,3],"394":[1,2,3],"395":[1,2,3],"402":[1,2,3],"411":[1,2,3],"451":[1,2,3],"459":[1,2,3]},"packages/cli/src/modules/agents/agent-message-queue-consumer.service.ts":{"31":"b:/j/e8y75v//SPvyuCWAAAAAAAAAAAAAAAAAAAAA=","45":"b:/j/e8y75v//SPvyuCWAAAAAAAAAAAAAAAAAAAAA=","47":"b:/j/e8y75v//SPvyuCWAAAAAAAAAAAAAAAAAAAAA=","48":"b:/j/e8y75v//SPvyuCWAAAAAAAAAAAAAAAAAAAAA=","56":"b:/j/e8y75v//SPvyuCWAAAAAAAAAAAAAAAAAAAAA=","63":"b:/j/e8y75v//SPvyuCWAAAAAAAAAAAAAAAAAAAAA=","77":"b:/j/e8y75v//SPvyuCWAAAAAAAAAAAAAAAAAAAAA=","81":"b:/j/e8y75v//SPvyuCWAAAAAAAAAAAAAAAAAAAAA=","84":"b:/j/e8y75v//SPvyuCWAAAAAAAAAAAAAAAAAAAAA=","88":"b:/j/e8y75v//SPvyuCWAAAAAAAAAAAAAAAAAAAAA=","95":"b:/j/e8y75v//SPvyuCWAAAAAAAAAAAAAAAAAAAAA=","98":"b:/j/e8y75v//SPvyuCWAAAAAAAAAAAAAAAAAAAAA=","129":"b:/j/e8y75v//SPvyuCWAAAAAAAAAAAAAAAAAAAAA=","159":"b:/j/e8y75v//SPvyuCWAAAAAAAAAAAAAAAAAAAAA=","181":"b:/j/e8y75v//SPvyuCWAAAAAAAAAAAAAAAAAAAAA=","194":"b:/j/e8y75v//SPvyuCWAAAAAAAAAAAAAAAAAAAAA=","245":"b:/j/e8y75v//SPvyuCWAAAAAAAAAAAAAAAAAAAAA=","246":"b:/j/e8y75v//SPvyuCWAAAAAAAAAAAAAAAAAAAAA=","252":"b:/j/e8y75v//SPvyuCWAAAAAAAAAAAAAAAAAAAAA=","278":"b:/j/e8y75v//SPvyuCWAAAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/modules/agents/agent-workflow-tool-resume.service.ts":{"37":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","55":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","87":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","105":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","137":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","150":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","207":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","234":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","255":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","301":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","338":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA="},"packages/cli/src/modules/agents/agents-config.controller.ts":{"24":[1,2,3],"36":[1,2,3],"50":[1,2,3],"65":[1,2,3],"88":[1,2,3],"113":[1,2,3]},"packages/cli/src/modules/agents/agents.controller.ts":{"24":[1,2,3,83],"33":[1,2,3,83],"72":[1,2,3,83],"87":[1,2,3,83],"108":[1,2,3,83],"117":[1,2,3,83],"133":[1,2,3,83]},"packages/cli/src/modules/agents/agents.service.ts":{"96":[1,2,3,83,81],"136":[1,2,3,83,81],"145":[1,2,3,83,81],"185":[1,2,3,83,81],"225":[1,2,3,83,81],"235":[1,2,3,83,81],"247":[1,2,3,83,81],"253":[1,2,3,83,81],"257":[1,2,3,83,81],"264":[1,2,3,83,81],"268":[1,2,3,83,81],"278":[1,2,3,83,81],"291":[1,2,3,83,81],"297":[1,2,3,83,81],"300":[1,2,3,83,81],"319":[1,2,3,83,81],"321":[1,2,3,83,81],"335":[1,2,3,83,81],"349":[1,2,3,83,81],"355":[1,2,3,83,81],"373":[1,2,3,83,81],"398":[1,2,3,83,81],"410":[1,2,3,83,81],"414":[1,2,3,83,81],"420":[1,2,3,83,81],"434":[1,2,3,83,81],"453":[1,2,3,83,81],"464":[1,2,3,83,81],"474":[1,2,3,83,81],"479":[1,2,3,83,81],"487":[1,2,3,83,81],"489":[1,2,3,83,81],"499":[1,2,3,83,81],"502":[1,2,3,83,81],"539":[1,2,3,83,81],"564":[1,2,3,83,81],"582":[1,2,3,83,81],"583":[1,2,3,83,81],"607":[1,2,3,83,81],"612":[1,2,3,83,81],"614":[1,2,3,83,81],"621":[1,2,3,83,81],"632":[1,2,3,83,81],"643":[1,2,3,83,81],"655":[1,2,3,83,81],"668":[1,2,3,83,81]},"packages/cli/src/modules/agents/repositories/agent.repository.ts":{"33":[1,2,3,83,18,20,163,81],"42":[1,2,3,83,18,20,163,81],"48":[1,2,3,83,18,20,163,81],"52":[1,2,3,83,18,20,163,81],"60":[1,2,3,83,18,20,163,81],"78":[1,2,3,83,18,20,163,81],"81":[1,2,3,83,18,20,163,81],"85":[1,2,3,83,18,20,163,81],"90":[1,2,3,83,18,20,163,81],"104":[1,2,3,83,18,20,163,81],"140":[1,2,3,83,18,20,163,81],"181":[1,2,3,83,18,20,163,81],"193":[1,2,3,83,18,20,163,81],"203":[1,2,3,83,18,20,163,81],"211":[1,2,3,83,18,20,163,81],"222":[1,2,3,83,18,20,163,81],"266":[1,2,3,83,18,20,163,81],"294":[1,2,3,83,18,20,163,81],"304":[1,2,3,83,18,20,163,81],"305":[1,2,3,83,18,20,163,81],"325":[1,2,3,83,18,20,163,81],"332":[1,2,3,83,18,20,163,81],"336":[1,2,3,83,18,20,163,81],"346":[1,2,3,83,18,20,163,81],"353":[1,2,3,83,18,20,163,81],"369":[1,2,3,83,18,20,163,81],"380":[1,2,3,83,18,20,163,81],"389":[1,2,3,83,18,20,163,81],"394":[1,2,3,83,18,20,163,81],"403":[1,2,3,83,18,20,163,81],"412":[1,2,3,83,18,20,163,81],"423":[1,2,3,83,18,20,163,81],"442":[1,2,3,83,18,20,163,81],"452":[1,2,3,83,18,20,163,81],"462":[1,2,3,83,18,20,163,81],"474":[1,2,3,83,18,20,163,81],"487":[1,2,3,83,18,20,163,81],"493":[1,2,3,83,18,20,163,81],"500":[1,2,3,83,18,20,163,81],"505":[1,2,3,83,18,20,163,81],"513":[1,2,3,83,18,20,163,81],"522":[1,2,3,83,18,20,163,81],"529":[1,2,3,83,18,20,163,81],"544":[1,2,3,83,18,20,163,81],"551":[1,2,3,83,18,20,163,81],"553":[1,2,3,83,18,20,163,81],"569":[1,2,3,83,18,20,163,81],"577":[1,2,3,83,18,20,163,81],"579":[1,2,3,83,18,20,163,81],"592":[1,2,3,83,18,20,163,81],"604":[1,2,3,83,18,20,163,81],"620":[1,2,3,83,18,20,163,81],"636":[1,2,3,83,18,20,163,81],"656":[1,2,3,83,18,20,163,81],"675":[1,2,3,83,18,20,163,81],"698":[1,2,3,83,18,20,163,81],"712":[1,2,3,83,18,20,163,81]},"packages/cli/src/modules/agents/utils/get-agent-or-throw.ts":{"6":[1,2,3,83]},"packages/cli/src/modules/breaking-changes/breaking-changes.rule-registry.service.ts":{"10":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","14":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","22":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","23":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","26":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","30":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","35":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/breaking-changes.service.ts":{"84":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","95":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","99":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","103":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","129":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","136":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","154":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","203":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","213":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","233":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","305":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","326":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","341":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","351":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","363":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","377":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","381":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","384":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","395":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","406":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","409":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","420":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","428":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","429":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","439":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","448":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","451":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","454":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","482":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/database/repositories/migration-finding.repository.ts":{"36":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","48":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","57":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","63":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","71":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","88":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","100":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","112":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","135":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","145":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","153":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","181":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","190":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","221":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","228":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","230":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","246":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","254":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","264":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","279":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","302":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","306":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","319":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","330":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","334":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA="},"packages/cli/src/modules/breaking-changes/database/repositories/migration-workflow-owner.repository.ts":{"15":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","19":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","34":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","51":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","56":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","74":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","83":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","94":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","95":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA="},"packages/cli/src/modules/breaking-changes/detection-report.ts":{"14":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","21":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/group-nodes-by-type.ts":{"4":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v2/binary-data-storage.rule.ts":{"14":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","21":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","34":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v2/cli-replace-update-workflow-command.rule.ts":{"11":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","14":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","27":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v2/disabled-nodes.rule.ts":{"14":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","22":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","35":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","52":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","60":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","65":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v2/dotenv-upgrade.rule.ts":{"14":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","16":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","28":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","37":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","54":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","60":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v2/file-access.rule.ts":{"14":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","19":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","31":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","43":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","47":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","52":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v2/oauth-callback-auth.rule.ts":{"12":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","15":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","28":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v2/process-env-access.rule.ts":{"14":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","16":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","28":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","48":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","58":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","67":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","77":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v2/pyodide-removed.rule.ts":{"15":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","18":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","31":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","53":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","66":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","72":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v2/queue-worker-max-stalled-count.rule.ts":{"11":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","14":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","27":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v2/removed-nodes.rule.ts":{"14":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","23":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","35":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","46":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","50":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","55":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v2/settings-file-permissions.rule.ts":{"13":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","17":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","30":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v2/start-node-removed.rule.ts":{"14":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","19":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","30":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","51":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","61":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v2/task-runner-docker-image.rule.ts":{"13":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","17":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","30":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v2/tunnel-option.rule.ts":{"11":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","14":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","25":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v2/wait-node-subworkflow.rule.ts":{"25":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","65":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","78":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","95":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","100":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","136":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","182":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","192":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","202":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","237":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v2/workflow-hooks-deprecated.rule.ts":{"11":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","14":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","27":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/agent-node-mode.ts":{"19":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAACAAAAAAAAA=","25":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAACAAAAAAAAA=","29":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAACAAAAAAAAA=","34":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAACAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/agent-node-version.rule.ts":{"20":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","23":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","35":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","48":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","53":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","56":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/agent-removed-modes.rule.ts":{"20":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","23":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","35":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","48":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","53":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","60":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/ai-transform-deprecated.rule.ts":{"17":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","20":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","32":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","45":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","51":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/always-output-data-multi-output.rule.ts":{"21":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","23":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","34":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","46":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","59":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","72":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","89":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/chat-hub-deprecated.rule.ts":{"16":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","20":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","32":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/chat-trigger-embedded-json.rule.ts":{"24":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAEABAAAAAAA=","27":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAEABAAAAAAA=","40":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAEABAAAAAAA=","53":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAEABAAAAAAA=","58":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAEABAAAAAAA=","59":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAEABAAAAAAA=","61":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAEABAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/compression-node-limits.rule.ts":{"12":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","15":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","26":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/docker-only-deployment.rule.ts":{"14":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","18":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","30":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/execute-workflow-source-modes.rule.ts":{"23":"b:+L+ikCz9viH3PnxsaSmAQEBKAAAAAAAAAAAwAAI=","26":"b:+L+ikCz9viH3PnxsaSmAQEBKAAAAAAAAAAAwAAI=","38":"b:+L+ikCz9viH3PnxsaSmAQEBKAAAAAAAAAAAwAAI=","56":"b:+L+ikCz9viH3PnxsaSmAQEBKAAAAAAAAAAAwAAI=","61":"b:+L+ikCz9viH3PnxsaSmAQEBKAAAAAAAAAAAwAAI=","64":"b:+L+ikCz9viH3PnxsaSmAQEBKAAAAAAAAAAAwAAI="},"packages/cli/src/modules/breaking-changes/rules/v3/external-secrets-project-roles-default.rule.ts":{"16":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","23":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","35":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","66":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","71":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/get-paired-item.rule.ts":{"17":"b:+L+ikCz9viH3PnxsaSkAQMALAAAAAAAAAAAAAAA=","20":"b:+L+ikCz9viH3PnxsaSkAQMALAAAAAAAAAAAAAAA=","32":"b:+L+ikCz9viH3PnxsaSkAQMALAAAAAAAAAAAAAAA=","45":"b:+L+ikCz9viH3PnxsaSkAQMALAAAAAAAAAAAAAAA=","49":"b:+L+ikCz9viH3PnxsaSkAQMALAAAAAAAAAAAAAAA=","53":"b:+L+ikCz9viH3PnxsaSkAQMALAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/gmail-trigger-version.rule.ts":{"18":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAIAAA=","21":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAIAAA=","33":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAIAAA=","46":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAIAAA=","51":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAIAAA=","54":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAIAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/in-memory-binary-data.rule.ts":{"14":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","18":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","29":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/offload-manual-executions.rule.ts":{"14":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","18":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","29":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/pre-execute-error-creates-execution.rule.ts":{"14":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","18":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","29":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/removed-nodes-with-replacements.rule.ts":{"20":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","27":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","30":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","34":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","40":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","47":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","57":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","60":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/removed-nodes.rule.ts":{"14":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","27":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","37":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","48":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","52":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","57":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/ssrf-default-blocked-ranges.rule.ts":{"14":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","18":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","32":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","40":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/storage-path-rename.rule.ts":{"15":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","19":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","30":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/task-runner-task-timeout.rule.ts":{"12":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","15":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","26":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/unverified-packages.rule.ts":{"18":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","25":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","34":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","38":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","49":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/rules/v3/workflow-import-url-removed.rule.ts":{"11":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","14":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","26":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/breaking-changes/sync/migration-finding-diff.ts":{"38":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","52":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA=","56":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAACAAA="},"packages/cli/src/modules/breaking-changes/sync/migration-finding-sync.listener.ts":{"16":"b:+P+ilKz9viH3vn9sabmATOgKAAAAMAIAAAAgoAA=","25":"b:+P+ilKz9viH3vn9sabmATOgKAAAAMAIAAAAgoAA=","26":"b:+P+ilKz9viH3vn9sabmATOgKAAAAMAIAAAAgoAA=","29":"b:+P+ilKz9viH3vn9sabmATOgKAAAAMAIAAAAgoAA=","32":"b:+P+ilKz9viH3vn9sabmATOgKAAAAMAIAAAAgoAA=","35":"b:+P+ilKz9viH3vn9sabmATOgKAAAAMAIAAAAgoAA=","42":"b:+P+ilKz9viH3vn9sabmATOgKAAAAMAIAAAAgoAA="},"packages/cli/src/modules/breaking-changes/sync/migration-finding-sync.service.ts":{"21":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","42":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","61":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","70":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","80":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","96":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","153":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","173":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","177":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","188":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","201":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","202":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","224":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","247":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","255":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","261":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","262":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","283":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","287":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","288":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","296":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/modules/chat-hub/chat-hub-execution-store.service.ts":{"58":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","79":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","93":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","103":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","127":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","140":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","154":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","158":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","171":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","189":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","199":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","202":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","211":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA="},"packages/cli/src/modules/chat-hub/chat-hub-execution-watcher.service.ts":{"32":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","54":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","117":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","163":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","206":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","238":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","260":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","283":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ="},"packages/cli/src/modules/data-table/data-table-aggregate.controller.ts":{"10":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","16":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","25":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA="},"packages/cli/src/modules/data-table/data-table-size-validator.service.ts":{"16":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","21":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","33":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","56":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","73":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","86":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","91":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/modules/data-table/data-table.repository.ts":{"29":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","45":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","47":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","49":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","54":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","63":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","64":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","70":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","89":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","119":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","121":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","128":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","136":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","171":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","173":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","186":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","188":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","202":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","213":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","219":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","224":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","235":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","239":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","244":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","259":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","267":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","277":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","300":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","308":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","319":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","330":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","334":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","337":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","341":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","369":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA=","407":"b:/k/X+y75Ad7UPnYrHVAEAgAAgAAEAAAABAAAAAA="},"packages/cli/src/modules/data-table/data-table.service.ts":{"54":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","70":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","71":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","73":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","86":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","99":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","123":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","177":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","187":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","194":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","206":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","233":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","242":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","254":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","269":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","279":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","290":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","300":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","314":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","328":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","339":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","351":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","355":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","362":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","368":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","389":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","395":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","415":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","424":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","472":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","482":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","529":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","580":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","590":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","651":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","660":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","690":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","693":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","703":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","712":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","719":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","720":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","722":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","740":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","786":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","801":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","814":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","825":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","831":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","843":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","846":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","895":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","897":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","901":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","903":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","919":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","937":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","941":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","944":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","947":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","975":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","1000":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","1005":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","1007":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","1012":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","1037":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","1065":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA=","1074":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAgAAABAAAAAA="},"packages/cli/src/modules/data-table/utils/sql-utils.ts":{"25":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","26":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","44":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","72":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","79":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","83":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","87":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","102":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","111":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","128":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","137":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","146":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","149":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","153":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","157":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","170":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","174":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","184":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","192":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","205":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","212":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","230":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","251":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","256":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","260":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","289":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","322":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","340":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","363":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","380":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","386":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","391":"b:/k/W+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/modules/favorites/database/repositories/user-favorite.repository.ts":{"9":"b:/m/e+y75Ad7Uvn4rCVAEAAAAAAAAQAAAAAAAAAA=","13":"b:/m/e+y75Ad7Uvn4rCVAEAAAAAAAAQAAAAAAAAAA=","20":"b:/m/e+y75Ad7Uvn4rCVAEAAAAAAAAQAAAAAAAAAA=","24":"b:/m/e+y75Ad7Uvn4rCVAEAAAAAAAAQAAAAAAAAAA="},"packages/cli/src/modules/favorites/favorites.controller.ts":{"10":"b:/k/e+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","16":"b:/k/e+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","19":"b:/k/e+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","24":"b:/k/e+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","29":"b:/k/e+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/modules/favorites/favorites.service.ts":{"24":"b:/m/e+y75Ad7Uvn4rCVAEAAAAAAAAQAAAAAAAAAA=","25":"b:/m/e+y75Ad7Uvn4rCVAEAAAAAAAAQAAAAAAAAAA=","27":"b:/m/e+y75Ad7Uvn4rCVAEAAAAAAAAQAAAAAAAAAA=","33":"b:/m/e+y75Ad7Uvn4rCVAEAAAAAAAAQAAAAAAAAAA=","44":"b:/m/e+y75Ad7Uvn4rCVAEAAAAAAAAQAAAAAAAAAA=","53":"b:/m/e+y75Ad7Uvn4rCVAEAAAAAAAAQAAAAAAAAAA=","66":"b:/m/e+y75Ad7Uvn4rCVAEAAAAAAAAQAAAAAAAAAA=","76":"b:/m/e+y75Ad7Uvn4rCVAEAAAAAAAAQAAAAAAAAAA=","94":"b:/m/e+y75Ad7Uvn4rCVAEAAAAAAAAQAAAAAAAAAA=","116":"b:/m/e+y75Ad7Uvn4rCVAEAAAAAAAAQAAAAAAAAAA=","117":"b:/m/e+y75Ad7Uvn4rCVAEAAAAAAAAQAAAAAAAAAA=","125":"b:/m/e+y75Ad7Uvn4rCVAEAAAAAAAAQAAAAAAAAAA=","130":"b:/m/e+y75Ad7Uvn4rCVAEAAAAAAAAQAAAAAAAAAA=","135":"b:/m/e+y75Ad7Uvn4rCVAEAAAAAAAAQAAAAAAAAAA=","149":"b:/m/e+y75Ad7Uvn4rCVAEAAAAAAAAQAAAAAAAAAA=","173":"b:/m/e+y75Ad7Uvn4rCVAEAAAAAAAAQAAAAAAAAAA=","196":"b:/m/e+y75Ad7Uvn4rCVAEAAAAAAAAQAAAAAAAAAA=","214":"b:/m/e+y75Ad7Uvn4rCVAEAAAAAAAAQAAAAAAAAAA=","241":"b:/m/e+y75Ad7Uvn4rCVAEAAAAAAAAQAAAAAAAAAA=","253":"b:/m/e+y75Ad7Uvn4rCVAEAAAAAAAAQAAAAAAAAAA=","257":"b:/m/e+y75Ad7Uvn4rCVAEAAAAAAAAQAAAAAAAAAA="},"packages/cli/src/modules/instance-ai/browser/browser-use-server.ts":{"22":"b:/k/e8C6pAQT0PnQoCRAAAEAIAAEAAAAAAAAAAAA=","24":"b:/k/e8C6pAQT0PnQoCRAAAEAIAAEAAAAAAAAAAAA=","25":"b:/k/e8C6pAQT0PnQoCRAAAEAIAAEAAAAAAAAAAAA=","28":"b:/k/e8C6pAQT0PnQoCRAAAEAIAAEAAAAAAAAAAAA=","31":"b:/k/e8C6pAQT0PnQoCRAAAEAIAAEAAAAAAAAAAAA=","43":"b:/k/e8C6pAQT0PnQoCRAAAEAIAAEAAAAAAAAAAAA=","47":"b:/k/e8C6pAQT0PnQoCRAAAEAIAAEAAAAAAAAAAAA=","52":"b:/k/e8C6pAQT0PnQoCRAAAEAIAAEAAAAAAAAAAAA=","53":"b:/k/e8C6pAQT0PnQoCRAAAEAIAAEAAAAAAAAAAAA=","64":"b:/k/e8C6pAQT0PnQoCRAAAEAIAAEAAAAAAAAAAAA="},"packages/cli/src/modules/instance-ai/instance-ai-memory.service.ts":{"51":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","61":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","74":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","110":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","126":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","150":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","163":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","182":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","257":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","277":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","289":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","295":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","317":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","331":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","343":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","351":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","397":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","433":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","454":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","458":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","470":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","474":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","535":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","583":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","593":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","613":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","629":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","639":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","648":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","661":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","665":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","669":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","675":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","699":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","706":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","721":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","736":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","788":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA=","806":"b:Hkbj8y75AZjkPnQ7CxAAAiACAIAjAAAABAAAAAA="},"packages/cli/src/modules/instance-ai/instance-ai-settings.service.ts":{"106":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","120":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","131":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","150":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","171":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","178":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","190":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","213":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","304":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","324":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","329":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","334":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","362":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","404":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","487":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","606":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","639":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","795":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","817":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","875":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","921":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","939":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","953":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1027":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1036":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1062":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1084":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1095":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1102":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1113":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1123":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1128":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1135":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1145":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1147":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1154":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1171":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1186":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1213":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1222":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1231":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1237":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1247":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1251":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1261":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1266":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1275":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1280":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1284":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1289":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1294":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1299":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1315":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1320":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1330":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1336":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1357":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1362":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1371":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1404":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1421":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1438":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1446":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1469":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1477":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1538":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1561":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1567":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1573":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1581":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1617":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1633":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1642":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1655":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1659":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1667":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1671":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1675":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1706":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1715":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1725":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1739":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1745":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1750":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1786":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1790":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1809":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1822":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1827":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1830":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1836":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1837":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1846":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA=","1863":"b:Hkbj8y/5AZjkPnQrCxAAAiACAIAgAAAAAAAAAAA="},"packages/cli/src/modules/instance-ai/instance-ai.controller.ts":{"107":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","138":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","150":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","158":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","168":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","178":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","196":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","214":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","265":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","297":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","313":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","324":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","330":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","340":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","409":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","446":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","465":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","502":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","506":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","579":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","587":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","626":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","635":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","649":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","655":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","669":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","692":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","708":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","724":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","733":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","739":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","745":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","768":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","778":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","788":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","797":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","806":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","813":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","816":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","821":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","825":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","843":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","858":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","864":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","878":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","884":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","890":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","897":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","908":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","916":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","964":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","978":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","995":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1007":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1029":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1042":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1113":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1126":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1139":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1158":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1166":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1174":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1181":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1196":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1220":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1240":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1263":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1280":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1334":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1390":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1407":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1426":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1439":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1462":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1466":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1472":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1478":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1484":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1504":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1535":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1552":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1573":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1586":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1599":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1616":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1624":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1632":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1640":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1650":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1665":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1676":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1688":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1713":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA=","1726":"b:Hkbj8y/5AZjkPnQ7CxAAQiACAIAiAAAAAAAAAAA="},"packages/cli/src/modules/otel/execution-level-tracer.ts":{"41":"b:eJccFAjHviFHGzhI4QkAQMQ1AAQAAAAAACAAgAA=","56":"b:eJccFAjHviFHGzhI4QkAQMQ1AAQAAAAAACAAgAA=","62":"b:eJccFAjHviFHGzhI4QkAQMQ1AAQAAAAAACAAgAA=","66":"b:eJccFAjHviFHGzhI4QkAQMQ1AAQAAAAAACAAgAA=","117":"b:eJccFAjHviFHGzhI4QkAQMQ1AAQAAAAAACAAgAA=","153":"b:eJccFAjHviFHGzhI4QkAQMQ1AAQAAAAAACAAgAA=","180":"b:eJccFAjHviFHGzhI4QkAQMQ1AAQAAAAAACAAgAA=","201":"b:eJccFAjHviFHGzhI4QkAQMQ1AAQAAAAAACAAgAA=","252":"b:eJccFAjHviFHGzhI4QkAQMQ1AAQAAAAAACAAgAA=","291":"b:eJccFAjHviFHGzhI4QkAQMQ1AAQAAAAAACAAgAA=","296":"b:eJccFAjHviFHGzhI4QkAQMQ1AAQAAAAAACAAgAA=","317":"b:eJccFAjHviFHGzhI4QkAQMQ1AAQAAAAAACAAgAA=","335":"b:eJccFAjHviFHGzhI4QkAQMQ1AAQAAAAAACAAgAA=","340":"b:eJccFAjHviFHGzhI4QkAQMQ1AAQAAAAAACAAgAA=","353":"b:eJccFAjHviFHGzhI4QkAQMQ1AAQAAAAAACAAgAA=","361":"b:eJccFAjHviFHGzhI4QkAQMQ1AAQAAAAAACAAgAA=","373":"b:eJccFAjHviFHGzhI4QkAQMQ1AAQAAAAAACAAgAA=","385":"b:eJccFAjHviFHGzhI4QkAQMQ1AAQAAAAAACAAgAA=","396":"b:eJccFAjHviFHGzhI4QkAQMQ1AAQAAAAAACAAgAA=","408":"b:eJccFAjHviFHGzhI4QkAQMQ1AAQAAAAAACAAgAA=","417":"b:eJccFAjHviFHGzhI4QkAQMQ1AAQAAAAAACAAgAA=","424":"b:eJccFAjHviFHGzhI4QkAQMQ1AAQAAAAAACAAgAA=","429":"b:eJccFAjHviFHGzhI4QkAQMQ1AAQAAAAAACAAgAA=","435":"b:eJccFAjHviFHGzhI4QkAQMQ1AAQAAAAAACAAgAA=","454":"b:eJccFAjHviFHGzhI4QkAQMQ1AAQAAAAAACAAgAA=","467":"b:eJccFAjHviFHGzhI4QkAQMQ1AAQAAAAAACAAgAA=","474":"b:eJccFAjHviFHGzhI4QkAQMQ1AAQAAAAAACAAgAA=","482":"b:eJccFAjHviFHGzhI4QkAQMQ1AAQAAAAAACAAgAA="},"packages/cli/src/modules/otel/otel-lifecycle-handler.ts":{"25":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","34":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","46":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","58":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","61":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","66":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","70":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","81":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","93":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","132":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","139":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","173":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","184":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","210":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","213":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","224":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","227":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","240":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","244":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","266":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","285":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","296":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","309":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","314":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","319":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","321":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ=","324":"b:eNccHAjFviFHGjhI4QmAQMQ3AAAAEAAAAAAAgAQ="},"packages/cli/src/modules/policy-infrastructure/policy-decision.service.ts":{"54":"b:/r+elC79vjH3PnxsaSkAQMQdAAAAAAAAAAAAgAA=","63":"b:/r+elC79vjH3PnxsaSkAQMQdAAAAAAAAAAAAgAA=","68":"b:/r+elC79vjH3PnxsaSkAQMQdAAAAAAAAAAAAgAA=","69":"b:/r+elC79vjH3PnxsaSkAQMQdAAAAAAAAAAAAgAA=","81":"b:/r+elC79vjH3PnxsaSkAQMQdAAAAAAAAAAAAgAA=","92":"b:/r+elC79vjH3PnxsaSkAQMQdAAAAAAAAAAAAgAA=","93":"b:/r+elC79vjH3PnxsaSkAQMQdAAAAAAAAAAAAgAA=","121":"b:/r+elC79vjH3PnxsaSkAQMQdAAAAAAAAAAAAgAA=","129":"b:/r+elC79vjH3PnxsaSkAQMQdAAAAAAAAAAAAgAA=","145":"b:/r+elC79vjH3PnxsaSkAQMQdAAAAAAAAAAAAgAA=","157":"b:/r+elC79vjH3PnxsaSkAQMQdAAAAAAAAAAAAgAA=","168":"b:/r+elC79vjH3PnxsaSkAQMQdAAAAAAAAAAAAgAA=","180":"b:/r+elC79vjH3PnxsaSkAQMQdAAAAAAAAAAAAgAA=","191":"b:/r+elC79vjH3PnxsaSkAQMQdAAAAAAAAAAAAgAA=","197":"b:/r+elC79vjH3PnxsaSkAQMQdAAAAAAAAAAAAgAA=","200":"b:/r+elC79vjH3PnxsaSkAQMQdAAAAAAAAAAAAgAA=","226":"b:/r+elC79vjH3PnxsaSkAQMQdAAAAAAAAAAAAgAA=","234":"b:/r+elC79vjH3PnxsaSkAQMQdAAAAAAAAAAAAgAA=","235":"b:/r+elC79vjH3PnxsaSkAQMQdAAAAAAAAAAAAgAA="},"packages/cli/src/modules/policy-infrastructure/policy-lifecycle-handler.ts":{"17":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","23":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA="},"packages/cli/src/modules/provisioning.ee/provisioning.service.ee.ts":{"43":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","60":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","64":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","72":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","126":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","177":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","243":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","256":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","286":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","288":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","291":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","308":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","369":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","402":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","418":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","422":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","441":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","456":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","464":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","472":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","480":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","485":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","490":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","499":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","503":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","511":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","518":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","557":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","578":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","585":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","593":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","652":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","679":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","689":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","701":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","703":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","708":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","730":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","781":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","790":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","814":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","825":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA=","831":"b:jgCiAwC4ABAUgAIqCAAAGjFAAAAAAAAABAAAAAA="},"packages/cli/src/modules/redaction/dynamic-credentials-context-hook.ts":{"21":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","31":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","52":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA="},"packages/cli/src/modules/redaction/executions/execution-redaction.service.ts":{"44":"b:eAcAEAjBAAFHGjgIYwEAQMY3AAAAAAAAAAAAAAA=","53":"b:eAcAEAjBAAFHGjgIYwEAQMY3AAAAAAAAAAAAAAA=","65":"b:eAcAEAjBAAFHGjgIYwEAQMY3AAAAAAAAAAAAAAA=","82":"b:eAcAEAjBAAFHGjgIYwEAQMY3AAAAAAAAAAAAAAA=","97":"b:eAcAEAjBAAFHGjgIYwEAQMY3AAAAAAAAAAAAAAA=","105":"b:eAcAEAjBAAFHGjgIYwEAQMY3AAAAAAAAAAAAAAA=","106":"b:eAcAEAjBAAFHGjgIYwEAQMY3AAAAAAAAAAAAAAA=","222":"b:eAcAEAjBAAFHGjgIYwEAQMY3AAAAAAAAAAAAAAA=","271":"b:eAcAEAjBAAFHGjgIYwEAQMY3AAAAAAAAAAAAAAA=","310":"b:eAcAEAjBAAFHGjgIYwEAQMY3AAAAAAAAAAAAAAA=","339":"b:eAcAEAjBAAFHGjgIYwEAQMY3AAAAAAAAAAAAAAA=","361":"b:eAcAEAjBAAFHGjgIYwEAQMY3AAAAAAAAAAAAAAA=","381":"b:eAcAEAjBAAFHGjgIYwEAQMY3AAAAAAAAAAAAAAA=","396":"b:eAcAEAjBAAFHGjgIYwEAQMY3AAAAAAAAAAAAAAA=","415":"b:eAcAEAjBAAFHGjgIYwEAQMY3AAAAAAAAAAAAAAA="},"packages/cli/src/modules/redaction/redaction-context-hook.ts":{"20":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","29":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","47":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA="},"packages/cli/src/modules/workflow-index/workflow-index.service.ts":{"33":"b:+P+ilKz9viH3vn9sabmATOhLAAAAMAIAAAAwoAI=","45":"b:+P+ilKz9viH3vn9sabmATOhLAAAAMAIAAAAwoAI=","46":"b:+P+ilKz9viH3vn9sabmATOhLAAAAMAIAAAAwoAI=","48":"b:+P+ilKz9viH3vn9sabmATOhLAAAAMAIAAAAwoAI=","50":"b:+P+ilKz9viH3vn9sabmATOhLAAAAMAIAAAAwoAI=","53":"b:+P+ilKz9viH3vn9sabmATOhLAAAAMAIAAAAwoAI=","56":"b:+P+ilKz9viH3vn9sabmATOhLAAAAMAIAAAAwoAI=","59":"b:+P+ilKz9viH3vn9sabmATOhLAAAAMAIAAAAwoAI=","71":"b:+P+ilKz9viH3vn9sabmATOhLAAAAMAIAAAAwoAI=","74":"b:+P+ilKz9viH3vn9sabmATOhLAAAAMAIAAAAwoAI=","76":"b:+P+ilKz9viH3vn9sabmATOhLAAAAMAIAAAAwoAI=","82":"b:+P+ilKz9viH3vn9sabmATOhLAAAAMAIAAAAwoAI=","95":"b:+P+ilKz9viH3vn9sabmATOhLAAAAMAIAAAAwoAI=","143":"b:+P+ilKz9viH3vn9sabmATOhLAAAAMAIAAAAwoAI=","157":"b:+P+ilKz9viH3vn9sabmATOhLAAAAMAIAAAAwoAI=","175":"b:+P+ilKz9viH3vn9sabmATOhLAAAAMAIAAAAwoAI=","182":"b:+P+ilKz9viH3vn9sabmATOhLAAAAMAIAAAAwoAI=","204":"b:+P+ilKz9viH3vn9sabmATOhLAAAAMAIAAAAwoAI=","222":"b:+P+ilKz9viH3vn9sabmATOhLAAAAMAIAAAAwoAI=","223":"b:+P+ilKz9viH3vn9sabmATOhLAAAAMAIAAAAwoAI=","265":"b:+P+ilKz9viH3vn9sabmATOhLAAAAMAIAAAAwoAI=","275":"b:+P+ilKz9viH3vn9sabmATOhLAAAAMAIAAAAwoAI=","292":"b:+P+ilKz9viH3vn9sabmATOhLAAAAMAIAAAAwoAI=","314":"b:+P+ilKz9viH3vn9sabmATOhLAAAAMAIAAAAwoAI=","334":"b:+P+ilKz9viH3vn9sabmATOhLAAAAMAIAAAAwoAI=","348":"b:+P+ilKz9viH3vn9sabmATOhLAAAAMAIAAAAwoAI=","363":"b:+P+ilKz9viH3vn9sabmATOhLAAAAMAIAAAAwoAI="},"packages/cli/src/node-types.ts":{"19":"b:+LeekCzlviH3PnxMaSkAQMAJAAAAAAAAAAAAAAA=","35":"b:+LeekCzlviH3PnxMaSkAQMAJAAAAAAAAAAAAAAA=","49":"b:+LeekCzlviH3PnxMaSkAQMAJAAAAAAAAAAAAAAA=","68":"b:+LeekCzlviH3PnxMaSkAQMAJAAAAAAAAAAAAAAA=","96":"b:+LeekCzlviH3PnxMaSkAQMAJAAAAAAAAAAAAAAA=","100":"b:+LeekCzlviH3PnxMaSkAQMAJAAAAAAAAAAAAAAA=","120":"b:+LeekCzlviH3PnxMaSkAQMAJAAAAAAAAAAAAAAA=","161":"b:+LeekCzlviH3PnxMaSkAQMAJAAAAAAAAAAAAAAA=","175":"b:+LeekCzlviH3PnxMaSkAQMAJAAAAAAAAAAAAAAA=","188":"b:+LeekCzlviH3PnxMaSkAQMAJAAAAAAAAAAAAAAA=","190":"b:+LeekCzlviH3PnxMaSkAQMAJAAAAAAAAAAAAAAA=","208":"b:+LeekCzlviH3PnxMaSkAQMAJAAAAAAAAAAAAAAA=","226":"b:+LeekCzlviH3PnxMaSkAQMAJAAAAAAAAAAAAAAA=","229":"b:+LeekCzlviH3PnxMaSkAQMAJAAAAAAAAAAAAAAA=","236":"b:+LeekCzlviH3PnxMaSkAQMAJAAAAAAAAAAAAAAA=","239":"b:+LeekCzlviH3PnxMaSkAQMAJAAAAAAAAAAAAAAA=","250":"b:+LeekCzlviH3PnxMaSkAQMAJAAAAAAAAAAAAAAA=","251":"b:+LeekCzlviH3PnxMaSkAQMAJAAAAAAAAAAAAAAA=","275":"b:+LeekCzlviH3PnxMaSkAQMAJAAAAAAAAAAAAAAA="},"packages/cli/src/permissions.ee/check-access.ts":{"32":"b:/j/e8y/9v+/XPvzqaWkCACEAACAAgAAACAIAAAA=","55":"b:/j/e8y/9v+/XPvzqaWkCACEAACAAgAAACAIAAAA=","77":"b:/j/e8y/9v+/XPvzqaWkCACEAACAAgAAACAIAAAA=","111":"b:/j/e8y/9v+/XPvzqaWkCACEAACAAgAAACAIAAAA=","118":"b:/j/e8y/9v+/XPvzqaWkCACEAACAAgAAACAIAAAA=","120":"b:/j/e8y/9v+/XPvzqaWkCACEAACAAgAAACAIAAAA=","138":"b:/j/e8y/9v+/XPvzqaWkCACEAACAAgAAACAIAAAA=","163":"b:/j/e8y/9v+/XPvzqaWkCACEAACAAgAAACAIAAAA="},"packages/cli/src/policy/policed-agent-nodes.ts":{"26":"b:/r+ekCz9viH3PnxsaSkAQMAJAAAAAAAAAAAAAAA=","40":"b:/r+ekCz9viH3PnxsaSkAQMAJAAAAAAAAAAAAAAA=","67":"b:/r+ekCz9viH3PnxsaSkAQMAJAAAAAAAAAAAAAAA=","82":"b:/r+ekCz9viH3PnxsaSkAQMAJAAAAAAAAAAAAAAA=","85":"b:/r+ekCz9viH3PnxsaSkAQMAJAAAAAAAAAAAAAAA=","110":"b:/r+ekCz9viH3PnxsaSkAQMAJAAAAAAAAAAAAAAA=","118":"b:/r+ekCz9viH3PnxsaSkAQMAJAAAAAAAAAAAAAAA=","119":"b:/r+ekCz9viH3PnxsaSkAQMAJAAAAAAAAAAAAAAA="},"packages/cli/src/policy/policy-enforcement.service.ts":{"35":"b:/r++lC79vjH3fnxsaSkAVOQdAQAAIAAAAAAA4AA=","38":"b:/r++lC79vjH3fnxsaSkAVOQdAQAAIAAAAAAA4AA=","43":"b:/r++lC79vjH3fnxsaSkAVOQdAQAAIAAAAAAA4AA=","52":"b:/r++lC79vjH3fnxsaSkAVOQdAQAAIAAAAAAA4AA=","56":"b:/r++lC79vjH3fnxsaSkAVOQdAQAAIAAAAAAA4AA=","74":"b:/r++lC79vjH3fnxsaSkAVOQdAQAAIAAAAAAA4AA=","86":"b:/r++lC79vjH3fnxsaSkAVOQdAQAAIAAAAAAA4AA=","90":"b:/r++lC79vjH3fnxsaSkAVOQdAQAAIAAAAAAA4AA=","103":"b:/r++lC79vjH3fnxsaSkAVOQdAQAAIAAAAAAA4AA=","107":"b:/r++lC79vjH3fnxsaSkAVOQdAQAAIAAAAAAA4AA=","119":"b:/r++lC79vjH3fnxsaSkAVOQdAQAAIAAAAAAA4AA=","123":"b:/r++lC79vjH3fnxsaSkAVOQdAQAAIAAAAAAA4AA=","135":"b:/r++lC79vjH3fnxsaSkAVOQdAQAAIAAAAAAA4AA=","139":"b:/r++lC79vjH3fnxsaSkAVOQdAQAAIAAAAAAA4AA=","151":"b:/r++lC79vjH3fnxsaSkAVOQdAQAAIAAAAAAA4AA=","155":"b:/r++lC79vjH3fnxsaSkAVOQdAQAAIAAAAAAA4AA=","167":"b:/r++lC79vjH3fnxsaSkAVOQdAQAAIAAAAAAA4AA=","171":"b:/r++lC79vjH3fnxsaSkAVOQdAQAAIAAAAAAA4AA=","183":"b:/r++lC79vjH3fnxsaSkAVOQdAQAAIAAAAAAA4AA=","187":"b:/r++lC79vjH3fnxsaSkAVOQdAQAAIAAAAAAA4AA=","197":"b:/r++lC79vjH3fnxsaSkAVOQdAQAAIAAAAAAA4AA=","201":"b:/r++lC79vjH3fnxsaSkAVOQdAQAAIAAAAAAA4AA=","212":"b:/r++lC79vjH3fnxsaSkAVOQdAQAAIAAAAAAA4AA=","216":"b:/r++lC79vjH3fnxsaSkAVOQdAQAAIAAAAAAA4AA=","233":"b:/r++lC79vjH3fnxsaSkAVOQdAQAAIAAAAAAA4AA="},"packages/cli/src/policy/policy-violation.error.ts":{"8":"b:/r++kC79vjH3PnxsaSkAQEAIAAAAAAAAAAAAAAI=","11":"b:/r++kC79vjH3PnxsaSkAQEAIAAAAAAAAAAAAAAI=","14":"b:/r++kC79vjH3PnxsaSkAQEAIAAAAAAAAAAAAAAI=","46":"b:/r++kC79vjH3PnxsaSkAQEAIAAAAAAAAAAAAAAI=","63":"b:/r++kC79vjH3PnxsaSkAQEAIAAAAAAAAAAAAAAI=","71":"b:/r++kC79vjH3PnxsaSkAQEAIAAAAAAAAAAAAAAI="},"packages/cli/src/posthog/index.ts":{"34":"b:/j/e82/8v+/XPvzmYW0CAAAAAIAAAAAAAAAAAAA=","54":"b:/j/e82/8v+/XPvzmYW0CAAAAAIAAAAAAAAAAAAA=","59":"b:/j/e82/8v+/XPvzmYW0CAAAAAIAAAAAAAAAAAAA=","72":"b:/j/e82/8v+/XPvzmYW0CAAAAAIAAAAAAAAAAAAA=","76":"b:/j/e82/8v+/XPvzmYW0CAAAAAIAAAAAAAAAAAAA=","84":"b:/j/e82/8v+/XPvzmYW0CAAAAAIAAAAAAAAAAAAA=","90":"b:/j/e82/8v+/XPvzmYW0CAAAAAIAAAAAAAAAAAAA=","110":"b:/j/e82/8v+/XPvzmYW0CAAAAAIAAAAAAAAAAAAA=","136":"b:/j/e82/8v+/XPvzmYW0CAAAAAIAAAAAAAAAAAAA=","148":"b:/j/e82/8v+/XPvzmYW0CAAAAAIAAAAAAAAAAAAA=","152":"b:/j/e82/8v+/XPvzmYW0CAAAAAIAAAAAAAAAAAAA=","172":"b:/j/e82/8v+/XPvzmYW0CAAAAAIAAAAAAAAAAAAA=","208":"b:/j/e82/8v+/XPvzmYW0CAAAAAIAAAAAAAAAAAAA=","237":"b:/j/e82/8v+/XPvzmYW0CAAAAAIAAAAAAAAAAAAA=","259":"b:/j/e82/8v+/XPvzmYW0CAAAAAIAAAAAAAAAAAAA="},"packages/cli/src/push/abstract.push.ts":{"34":"b:/v/e9z7tv/31Pnx4yxkAQsS/sAkACAAAAAAAAAA=","40":"b:/v/e9z7tv/31Pnx4yxkAQsS/sAkACAAAAAAAAAA=","43":"b:/v/e9z7tv/31Pnx4yxkAQsS/sAkACAAAAAAAAAA=","58":"b:/v/e9z7tv/31Pnx4yxkAQsS/sAkACAAAAAAAAAA=","66":"b:/v/e9z7tv/31Pnx4yxkAQsS/sAkACAAAAAAAAAA=","70":"b:/v/e9z7tv/31Pnx4yxkAQsS/sAkACAAAAAAAAAA=","79":"b:/v/e9z7tv/31Pnx4yxkAQsS/sAkACAAAAAAAAAA=","96":"b:/v/e9z7tv/31Pnx4yxkAQsS/sAkACAAAAAAAAAA=","102":"b:/v/e9z7tv/31Pnx4yxkAQsS/sAkACAAAAAAAAAA=","106":"b:/v/e9z7tv/31Pnx4yxkAQsS/sAkACAAAAAAAAAA=","115":"b:/v/e9z7tv/31Pnx4yxkAQsS/sAkACAAAAAAAAAA=","123":"b:/v/e9z7tv/31Pnx4yxkAQsS/sAkACAAAAAAAAAA=","131":"b:/v/e9z7tv/31Pnx4yxkAQsS/sAkACAAAAAAAAAA=","135":"b:/v/e9z7tv/31Pnx4yxkAQsS/sAkACAAAAAAAAAA=","145":"b:/v/e9z7tv/31Pnx4yxkAQsS/sAkACAAAAAAAAAA="},"packages/cli/src/push/index.ts":{"52":"b:/v/e9C7tvyX1PnxoixkAQMQ/AAEACAAAAAAAAAA=","62":"b:/v/e9C7tvyX1PnxoixkAQMQ/AAEACAAAAAAAAAA=","65":"b:/v/e9C7tvyX1PnxoixkAQMQ/AAEACAAAAAAAAAA=","70":"b:/v/e9C7tvyX1PnxoixkAQMQ/AAEACAAAAAAAAAA=","73":"b:/v/e9C7tvyX1PnxoixkAQMQ/AAEACAAAAAAAAAA=","75":"b:/v/e9C7tvyX1PnxoixkAQMQ/AAEACAAAAAAAAAA=","79":"b:/v/e9C7tvyX1PnxoixkAQMQ/AAEACAAAAAAAAAA=","94":"b:/v/e9C7tvyX1PnxoixkAQMQ/AAEACAAAAAAAAAA=","99":"b:/v/e9C7tvyX1PnxoixkAQMQ/AAEACAAAAAAAAAA=","111":"b:/v/e9C7tvyX1PnxoixkAQMQ/AAEACAAAAAAAAAA=","166":"b:/v/e9C7tvyX1PnxoixkAQMQ/AAEACAAAAAAAAAA=","171":"b:/v/e9C7tvyX1PnxoixkAQMQ/AAEACAAAAAAAAAA=","180":"b:/v/e9C7tvyX1PnxoixkAQMQ/AAEACAAAAAAAAAA=","189":"b:/v/e9C7tvyX1PnxoixkAQMQ/AAEACAAAAAAAAAA=","198":"b:/v/e9C7tvyX1PnxoixkAQMQ/AAEACAAAAAAAAAA=","219":"b:/v/e9C7tvyX1PnxoixkAQMQ/AAEACAAAAAAAAAA=","226":"b:/v/e9C7tvyX1PnxoixkAQMQ/AAEACAAAAAAAAAA=","241":"b:/v/e9C7tvyX1PnxoixkAQMQ/AAEACAAAAAAAAAA="},"packages/cli/src/push/push-helpers.ts":{"5":"b:/k/e8C7pAQT0PnQoCRAAAEAIAAEAAAAAAAAAAAA=","9":"b:/k/e8C7pAQT0PnQoCRAAAEAIAAEAAAAAAAAAAAA=","14":"b:/k/e8C7pAQT0PnQoCRAAAEAIAAEAAAAAAAAAAAA=","18":"b:/k/e8C7pAQT0PnQoCRAAAEAIAAEAAAAAAAAAAAA="},"packages/cli/src/push/websocket.push.ts":{"9":"b:/k/+8C6pAQT0P3QoCRAAQEAZARFwKAAAAIAAAAA=","15":"b:/k/+8C6pAQT0P3QoCRAAQEAZARFwKAAAAIAAAAA=","21":"b:/k/+8C6pAQT0P3QoCRAAQEAZARFwKAAAAIAAAAA=","60":"b:/k/+8C6pAQT0P3QoCRAAQEAZARFwKAAAAIAAAAA=","71":"b:/k/+8C6pAQT0P3QoCRAAQEAZARFwKAAAAIAAAAA=","75":"b:/k/+8C6pAQT0P3QoCRAAQEAZARFwKAAAAIAAAAA=","79":"b:/k/+8C6pAQT0P3QoCRAAQEAZARFwKAAAAIAAAAA=","88":"b:/k/+8C6pAQT0P3QoCRAAQEAZARFwKAAAAIAAAAA="},"packages/cli/src/response-helper.ts":{"19":"b:DPAAAgCAAKQHYBwEEAiIAAAAMCEAEAAAACAAoAA=","52":"b:DPAAAgCAAKQHYBwEEAiIAAAAMCEAEAAAACAAoAA=","104":"b:DPAAAgCAAKQHYBwEEAiIAAAAMCEAEAAAACAAoAA=","118":"b:DPAAAgCAAKQHYBwEEAiIAAAAMCEAEAAAACAAoAA=","122":"b:DPAAAgCAAKQHYBwEEAiIAAAAMCEAEAAAACAAoAA="},"packages/cli/src/scheduling/scheduler-tracer.ts":{"13":"b:aiqO4C+0AHoBLIBAAAAAAAAAAAAAAAAAAAAAAAA=","15":"b:aiqO4C+0AHoBLIBAAAAAAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/server.ts":{"94":"b:/k/e+675Ad73PnQvC1AEAMAZAAEgEAUIADQEAAA=","106":"b:/k/e+675Ad73PnQvC1AEAMAZAAEgEAUIADQEAAA=","130":"b:/k/e+675Ad73PnQvC1AEAMAZAAEgEAUIADQEAAA=","172":"b:/k/e+675Ad73PnQvC1AEAMAZAAEgEAUIADQEAAA=","209":"b:/k/e+675Ad73PnQvC1AEAMAZAAEgEAUIADQEAAA=","278":"b:/k/e+675Ad73PnQvC1AEAMAZAAEgEAUIADQEAAA=","308":"b:/k/e+675Ad73PnQvC1AEAMAZAAEgEAUIADQEAAA=","360":"b:/k/e+675Ad73PnQvC1AEAMAZAAEgEAUIADQEAAA=","366":"b:/k/e+675Ad73PnQvC1AEAMAZAAEgEAUIADQEAAA=","378":"b:/k/e+675Ad73PnQvC1AEAMAZAAEgEAUIADQEAAA=","393":"b:/k/e+675Ad73PnQvC1AEAMAZAAEgEAUIADQEAAA=","457":"b:/k/e+675Ad73PnQvC1AEAMAZAAEgEAUIADQEAAA=","465":"b:/k/e+675Ad73PnQvC1AEAMAZAAEgEAUIADQEAAA=","472":"b:/k/e+675Ad73PnQvC1AEAMAZAAEgEAUIADQEAAA=","499":"b:/k/e+675Ad73PnQvC1AEAMAZAAEgEAUIADQEAAA=","518":"b:/k/e+675Ad73PnQvC1AEAMAZAAEgEAUIADQEAAA=","527":"b:/k/e+675Ad73PnQvC1AEAMAZAAEgEAUIADQEAAA=","528":"b:/k/e+675Ad73PnQvC1AEAMAZAAEgEAUIADQEAAA=","537":"b:/k/e+675Ad73PnQvC1AEAMAZAAEgEAUIADQEAAA=","546":"b:/k/e+675Ad73PnQvC1AEAMAZAAEgEAUIADQEAAA=","555":"b:/k/e+675Ad73PnQvC1AEAMAZAAEgEAUIADQEAAA=","564":"b:/k/e+675Ad73PnQvC1AEAMAZAAEgEAUIADQEAAA=","571":"b:/k/e+675Ad73PnQvC1AEAMAZAAEgEAUIADQEAAA="},"packages/cli/src/services/database-independent-routes.service.ts":{"5":"b:/j/e8y/9v8/XPvzu6WkCAAAAAAAAAAAAAAAAAAA=","8":"b:/j/e8y/9v8/XPvzu6WkCAAAAAAAAAAAAAAAAAAA=","13":"b:/j/e8y/9v8/XPvzu6WkCAAAAAAAAAAAAAAAAAAA=","18":"b:/j/e8y/9v8/XPvzu6WkCAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/services/engine-v2-dispatcher.service.ts":{"51":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","52":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","69":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","80":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","95":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","110":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","135":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","188":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","214":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","261":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","270":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","271":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","274":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","275":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","285":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","303":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","315":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA="},"packages/cli/src/services/frontend.service.ts":{"124":"b:/k/f+275Ad7UPnQrCVAEgAAAhAAAAAAAAAAAAAA=","145":"b:/k/f+275Ad7UPnQrCVAEgAAAhAAAAAAAAAAAAAA=","146":"b:/k/f+275Ad7UPnQrCVAEgAAAhAAAAAAAAAAAAAA=","150":"b:/k/f+275Ad7UPnQrCVAEgAAAhAAAAAAAAAAAAAA=","162":"b:/k/f+275Ad7UPnQrCVAEgAAAhAAAAAAAAAAAAAA=","169":"b:/k/f+275Ad7UPnQrCVAEgAAAhAAAAAAAAAAAAAA=","415":"b:/k/f+275Ad7UPnQrCVAEgAAAhAAAAAAAAAAAAAA=","416":"b:/k/f+275Ad7UPnQrCVAEgAAAhAAAAAAAAAAAAAA=","421":"b:/k/f+275Ad7UPnQrCVAEgAAAhAAAAAAAAAAAAAA=","457":"b:/k/f+275Ad7UPnQrCVAEgAAAhAAAAAAAAAAAAAA=","464":"b:/k/f+275Ad7UPnQrCVAEgAAAhAAAAAAAAAAAAAA=","465":"b:/k/f+275Ad7UPnQrCVAEgAAAhAAAAAAAAAAAAAA=","466":"b:/k/f+275Ad7UPnQrCVAEgAAAhAAAAAAAAAAAAAA=","470":"b:/k/f+275Ad7UPnQrCVAEgAAAhAAAAAAAAAAAAAA=","480":"b:/k/f+275Ad7UPnQrCVAEgAAAhAAAAAAAAAAAAAA=","689":"b:/k/f+275Ad7UPnQrCVAEgAAAhAAAAAAAAAAAAAA=","700":"b:/k/f+275Ad7UPnQrCVAEgAAAhAAAAAAAAAAAAAA=","721":"b:/k/f+275Ad7UPnQrCVAEgAAAhAAAAAAAAAAAAAA=","763":"b:/k/f+275Ad7UPnQrCVAEgAAAhAAAAAAAAAAAAAA=","767":"b:/k/f+275Ad7UPnQrCVAEgAAAhAAAAAAAAAAAAAA=","783":"b:/k/f+275Ad7UPnQrCVAEgAAAhAAAAAAAAAAAAAA=","791":"b:/k/f+275Ad7UPnQrCVAEgAAAhAAAAAAAAAAAAAA=","796":"b:/k/f+275Ad7UPnQrCVAEgAAAhAAAAAAAAAAAAAA=","806":"b:/k/f+275Ad7UPnQrCVAEgAAAhAAAAAAAAAAAAAA=","820":"b:/k/f+275Ad7UPnQrCVAEgAAAhAAAAAAAAAAAAAA=","821":"b:/k/f+275Ad7UPnQrCVAEgAAAhAAAAAAAAAAAAAA=","855":"b:/k/f+275Ad7UPnQrCVAEgAAAhAAAAAAAAAAAAAA="},"packages/cli/src/services/jwt.service.ts":{"27":"b:/j/e+2/9v+/fPvzuYW0CADCAAEAAgAAACAAAEAA=","52":"b:/j/e+2/9v+/fPvzuYW0CADCAAEAAgAAACAAAEAA=","71":"b:/j/e+2/9v+/fPvzuYW0CADCAAEAAgAAACAAAEAA=","84":"b:/j/e+2/9v+/fPvzuYW0CADCAAEAAgAAACAAAEAA=","97":"b:/j/e+2/9v+/fPvzuYW0CADCAAEAAgAAACAAAEAA=","105":"b:/j/e+2/9v+/fPvzuYW0CADCAAEAAgAAACAAAEAA=","110":"b:/j/e+2/9v+/fPvzuYW0CADCAAEAAgAAACAAAEAA=","130":"b:/j/e+2/9v+/fPvzuYW0CADCAAEAAgAAACAAAEAA=","146":"b:/j/e+2/9v+/fPvzuYW0CADCAAEAAgAAACAAAEAA=","164":"b:/j/e+2/9v+/fPvzuYW0CADCAAEAAgAAACAAAEAA="},"packages/cli/src/services/last-active-at.service.ts":{"11":"b:/j/e8y/9v+/XPvzuYWkCAAAAAAAAAAAAAAAAAAA=","16":"b:/j/e8y/9v+/XPvzuYWkCAAAAAAAAAAAAAAAAAAA=","18":"b:/j/e8y/9v+/XPvzuYWkCAAAAAAAAAAAAAAAAAAA=","25":"b:/j/e8y/9v+/XPvzuYWkCAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/services/ownership.service.ts":{"25":"b:+P++liz9vjH3vn5o6amBTswJAEQAAAAABAAQoAA=","37":"b:+P++liz9vjH3vn5o6amBTswJAEQAAAAABAAQoAA=","44":"b:+P++liz9vjH3vn5o6amBTswJAEQAAAAABAAQoAA=","54":"b:+P++liz9vjH3vn5o6amBTswJAEQAAAAABAAQoAA=","71":"b:+P++liz9vjH3vn5o6amBTswJAEQAAAAABAAQoAA=","75":"b:+P++liz9vjH3vn5o6amBTswJAEQAAAAABAAQoAA=","83":"b:+P++liz9vjH3vn5o6amBTswJAEQAAAAABAAQoAA=","88":"b:+P++liz9vjH3vn5o6amBTswJAEQAAAAABAAQoAA=","91":"b:+P++liz9vjH3vn5o6amBTswJAEQAAAAABAAQoAA=","106":"b:+P++liz9vjH3vn5o6amBTswJAEQAAAAABAAQoAA=","107":"b:+P++liz9vjH3vn5o6amBTswJAEQAAAAABAAQoAA=","123":"b:+P++liz9vjH3vn5o6amBTswJAEQAAAAABAAQoAA=","130":"b:+P++liz9vjH3vn5o6amBTswJAEQAAAAABAAQoAA=","139":"b:+P++liz9vjH3vn5o6amBTswJAEQAAAAABAAQoAA=","149":"b:+P++liz9vjH3vn5o6amBTswJAEQAAAAABAAQoAA=","191":"b:+P++liz9vjH3vn5o6amBTswJAEQAAAAABAAQoAA=","200":"b:+P++liz9vjH3vn5o6amBTswJAEQAAAAABAAQoAA=","204":"b:+P++liz9vjH3vn5o6amBTswJAEQAAAAABAAQoAA="},"packages/cli/src/services/password.utility.ts":{"8":"b:/j/e8y/8v+/XPvzmYW0CAAAAAAAAAAAAAAAAAAA=","12":"b:/j/e8y/8v+/XPvzmYW0CAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/services/project.service.ee.ts":{"48":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","56":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","62":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","66":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","89":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","106":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","107":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","112":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","113":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","118":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","120":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","124":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","125":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","130":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","132":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","136":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","137":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","142":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","143":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","148":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","149":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","154":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","156":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","160":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","162":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","166":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","214":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","216":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","238":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","250":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","328":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","355":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","359":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","368":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","377":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","381":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","384":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","386":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","401":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","409":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","423":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","433":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","448":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","452":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","456":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","472":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","509":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","543":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","552":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","553":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","576":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","585":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","589":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","601":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","605":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","608":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","609":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","614":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","618":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","624":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","634":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","640":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","653":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","658":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","669":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","679":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","687":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","693":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","694":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","697":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","714":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","732":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","738":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","756":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","760":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","775":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","785":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","790":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","803":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","809":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","813":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","821":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","822":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","823":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","826":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","831":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","833":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","837":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","849":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","857":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","878":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","884":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","892":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","900":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","904":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","911":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","921":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","936":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","953":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","975":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","978":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","984":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","987":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","1020":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","1033":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","1042":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","1046":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","1058":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","1068":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","1072":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","1082":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","1096":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","1101":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","1106":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA=","1117":"b:/v/+/y79v//3/n5vaXlEGnFIAagAwAAADQAAQAA="},"packages/cli/src/services/user.service.ts":{"58":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","77":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","87":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","91":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","103":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","115":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","126":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","132":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","137":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","180":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","183":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","184":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","189":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","200":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","210":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","283":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","284":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","288":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","290":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","292":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","304":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","310":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","312":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","332":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","340":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","343":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","359":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","362":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","452":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","481":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","496":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","502":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","516":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","543":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","560":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","630":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","650":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","670":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","713":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","721":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","726":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA=","731":"b:/v/++y/9v//3Pvzvaf0GADCKCAAAgABADgAwkAA="},"packages/cli/src/services/workflow-statistics.service.ts":{"33":"b:eNc8HAjFviFHGjhI4YmAQMQ3CEAAMAAAAAAwoAI=","69":"b:eNc8HAjFviFHGjhI4YmAQMQ3CEAAMAAAAAAwoAI=","84":"b:eNc8HAjFviFHGjhI4YmAQMQ3CEAAMAAAAAAwoAI=","88":"b:eNc8HAjFviFHGjhI4YmAQMQ3CEAAMAAAAAAwoAI=","91":"b:eNc8HAjFviFHGjhI4YmAQMQ3CEAAMAAAAAAwoAI=","99":"b:eNc8HAjFviFHGjhI4YmAQMQ3CEAAMAAAAAAwoAI=","122":"b:eNc8HAjFviFHGjhI4YmAQMQ3CEAAMAAAAAAwoAI=","151":"b:eNc8HAjFviFHGjhI4YmAQMQ3CEAAMAAAAAAwoAI=","204":"b:eNc8HAjFviFHGjhI4YmAQMQ3CEAAMAAAAAAwoAI=","224":"b:eNc8HAjFviFHGjhI4YmAQMQ3CEAAMAAAAAAwoAI=","261":"b:eNc8HAjFviFHGjhI4YmAQMQ3CEAAMAAAAAAwoAI=","273":"b:eNc8HAjFviFHGjhI4YmAQMQ3CEAAMAAAAAAwoAI=","319":"b:eNc8HAjFviFHGjhI4YmAQMQ3CEAAMAAAAAAwoAI=","350":"b:eNc8HAjFviFHGjhI4YmAQMQ3CEAAMAAAAAAwoAI="},"packages/cli/src/sso.ee/sso-helpers.ts":{"15":"b:/j/e8y/8v+/XPvzmYW0CADCAAAAAgAAADAAAEAA=","29":"b:/j/e8y/8v+/XPvzmYW0CADCAAAAAgAAADAAAEAA=","48":"b:/j/e8y/8v+/XPvzmYW0CADCAAAAAgAAADAAAEAA=","52":"b:/j/e8y/8v+/XPvzmYW0CADCAAAAAgAAADAAAEAA=","59":"b:/j/e8y/8v+/XPvzmYW0CADCAAAAAgAAADAAAEAA=","63":"b:/j/e8y/8v+/XPvzmYW0CADCAAAAAgAAADAAAEAA=","67":"b:/j/e8y/8v+/XPvzmYW0CADCAAAAAgAAADAAAEAA=","71":"b:/j/e8y/8v+/XPvzmYW0CADCAAAAAgAAADAAAEAA=","75":"b:/j/e8y/8v+/XPvzmYW0CADCAAAAAgAAADAAAEAA=","79":"b:/j/e8y/8v+/XPvzmYW0CADCAAAAAgAAADAAAEAA=","83":"b:/j/e8y/8v+/XPvzmYW0CADCAAAAAgAAADAAAEAA=","91":"b:/j/e8y/8v+/XPvzmYW0CADCAAAAAgAAADAAAEAA=","96":"b:/j/e8y/8v+/XPvzmYW0CADCAAAAAgAAADAAAEAA=","107":"b:/j/e8y/8v+/XPvzmYW0CADCAAAAAgAAADAAAEAA=","111":"b:/j/e8y/8v+/XPvzmYW0CADCAAAAAgAAADAAAEAA="},"packages/cli/src/task-runners/task-broker/task-broker-ws-server.ts":{"27":"b:+gXW2wz4If7EOjy66VAAIMETWAAAAAAAAAAEAAA=","60":"b:+gXW2wz4If7EOjy66VAAIMETWAAAAAAAAAAEAAA=","70":"b:+gXW2wz4If7EOjy66VAAIMETWAAAAAAAAAAEAAA=","75":"b:+gXW2wz4If7EOjy66VAAIMETWAAAAAAAAAAEAAA=","84":"b:+gXW2wz4If7EOjy66VAAIMETWAAAAAAAAAAEAAA=","92":"b:+gXW2wz4If7EOjy66VAAIMETWAAAAAAAAAAEAAA=","97":"b:+gXW2wz4If7EOjy66VAAIMETWAAAAAAAAAAEAAA=","120":"b:+gXW2wz4If7EOjy66VAAIMETWAAAAAAAAAAEAAA=","130":"b:+gXW2wz4If7EOjy66VAAIMETWAAAAAAAAAAEAAA=","141":"b:+gXW2wz4If7EOjy66VAAIMETWAAAAAAAAAAEAAA=","145":"b:+gXW2wz4If7EOjy66VAAIMETWAAAAAAAAAAEAAA=","149":"b:+gXW2wz4If7EOjy66VAAIMETWAAAAAAAAAAEAAA=","153":"b:+gXW2wz4If7EOjy66VAAIMETWAAAAAAAAAAEAAA=","159":"b:+gXW2wz4If7EOjy66VAAIMETWAAAAAAAAAAEAAA=","192":"b:+gXW2wz4If7EOjy66VAAIMETWAAAAAAAAAAEAAA=","210":"b:+gXW2wz4If7EOjy66VAAIMETWAAAAAAAAAAEAAA=","220":"b:+gXW2wz4If7EOjy66VAAIMETWAAAAAAAAAAEAAA=","263":"b:+gXW2wz4If7EOjy66VAAIMETWAAAAAAAAAAEAAA=","273":"b:+gXW2wz4If7EOjy66VAAIMETWAAAAAAAAAAEAAA=","281":"b:+gXW2wz4If7EOjy66VAAIMETWAAAAAAAAAAEAAA=","292":"b:+gXW2wz4If7EOjy66VAAIMETWAAAAAAAAAAEAAA=","300":"b:+gXW2wz4If7EOjy66VAAIMETWAAAAAAAAAAEAAA=","305":"b:+gXW2wz4If7EOjy66VAAIMETWAAAAAAAAAAEAAA=","315":"b:+gXW2wz4If7EOjy66VAAIMETWAAAAAAAAAAEAAA="},"packages/cli/src/utils/request-path.ts":{"9":"b:/k/e+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","17":"b:/k/e+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","22":"b:/k/e+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","29":"b:/k/e+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","30":"b:/k/e+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","39":"b:/k/e+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA=","50":"b:/k/e+y75Ad7UPnQrCVAEAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/utils.ts":{"10":"b:+Pefly79vrn3/n7v+6mCbvZ/iUAMMCAATAgw4AI=","19":"b:+Pefly79vrn3/n7v+6mCbvZ/iUAMMCAATAgw4AI=","28":"b:+Pefly79vrn3/n7v+6mCbvZ/iUAMMCAATAgw4AI=","32":"b:+Pefly79vrn3/n7v+6mCbvZ/iUAMMCAATAgw4AI=","33":"b:+Pefly79vrn3/n7v+6mCbvZ/iUAMMCAATAgw4AI=","35":"b:+Pefly79vrn3/n7v+6mCbvZ/iUAMMCAATAgw4AI=","37":"b:+Pefly79vrn3/n7v+6mCbvZ/iUAMMCAATAgw4AI=","42":"b:+Pefly79vrn3/n7v+6mCbvZ/iUAMMCAATAgw4AI=","62":"b:+Pefly79vrn3/n7v+6mCbvZ/iUAMMCAATAgw4AI=","66":"b:+Pefly79vrn3/n7v+6mCbvZ/iUAMMCAATAgw4AI=","68":"b:+Pefly79vrn3/n7v+6mCbvZ/iUAMMCAATAgw4AI=","73":"b:+Pefly79vrn3/n7v+6mCbvZ/iUAMMCAATAgw4AI=","78":"b:+Pefly79vrn3/n7v+6mCbvZ/iUAMMCAATAgw4AI=","84":"b:+Pefly79vrn3/n7v+6mCbvZ/iUAMMCAATAgw4AI=","97":"b:+Pefly79vrn3/n7v+6mCbvZ/iUAMMCAATAgw4AI=","99":"b:+Pefly79vrn3/n7v+6mCbvZ/iUAMMCAATAgw4AI=","104":"b:+Pefly79vrn3/n7v+6mCbvZ/iUAMMCAATAgw4AI=","124":"b:+Pefly79vrn3/n7v+6mCbvZ/iUAMMCAATAgw4AI=","131":"b:+Pefly79vrn3/n7v+6mCbvZ/iUAMMCAATAgw4AI=","151":"b:+Pefly79vrn3/n7v+6mCbvZ/iUAMMCAATAgw4AI=","163":"b:+Pefly79vrn3/n7v+6mCbvZ/iUAMMCAATAgw4AI=","170":"b:+Pefly79vrn3/n7v+6mCbvZ/iUAMMCAATAgw4AI=","178":"b:+Pefly79vrn3/n7v+6mCbvZ/iUAMMCAATAgw4AI="},"packages/cli/src/webhooks/test-webhooks.ts":{"65":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA=","82":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA=","112":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA=","167":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA=","182":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA=","246":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA=","269":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA=","283":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA=","307":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA=","309":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA=","312":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA=","316":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA=","323":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA=","326":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA=","339":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA=","358":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA=","377":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA=","384":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA=","396":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA=","447":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA=","450":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA=","463":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA=","474":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA=","571":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA=","599":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA=","606":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA=","620":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA=","628":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA=","629":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA=","638":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA=","650":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA=","657":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA=","693":"b:eAcAAAjBAABGAjAIcwAAiMU3CEAAQACAQAAAAAA="},"packages/cli/src/webhooks/webhook-helpers.ts":{"146":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","152":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","156":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","176":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","193":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","206":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","262":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","272":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","282":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","323":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","342":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","349":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","354":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","357":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","369":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","392":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","428":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","435":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","453":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","486":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","498":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","507":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","524":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","545":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","553":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","624":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","663":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","706":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","725":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","790":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","802":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","811":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","848":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","853":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","869":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","886":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","923":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","957":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","958":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","972":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","1036":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","1236":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","1239":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","1374":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","1399":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","1466":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","1557":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","1614":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","1667":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","1678":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","1694":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","1739":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","1764":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk=","1780":"b:ePcgDAjFviF/gjhI4QmAgMQXCEAAIAAAAAAAoAk="},"packages/cli/src/webhooks/webhook.service.ts":{"35":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","42":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","47":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","50":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","54":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","66":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","88":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","101":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","111":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","125":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","129":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","146":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","156":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","163":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","165":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","177":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","179":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","180":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","201":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","215":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","219":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","256":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","268":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","275":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","280":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","284":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","291":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","295":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","300":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","301":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","306":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","310":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","321":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","332":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","334":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","343":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","344":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","348":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","369":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","370":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","377":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","470":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","497":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","518":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","532":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","581":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","583":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","587":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","592":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","611":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","620":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","652":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA=","683":"b:ePcgDAjFviF/gjtI84mAiMQXCEAAUAAAAAAgsAA="},"packages/cli/src/workflow-execute-additional-data.ts":{"83":"b:ePccGAjnviF3OzxI4TmAcMUXAAQAEAAAAAA0oA4=","128":"b:ePccGAjnviF3OzxI4TmAcMUXAAQAEAAAAAA0oA4=","179":"b:ePccGAjnviF3OzxI4TmAcMUXAAQAEAAAAAA0oA4=","197":"b:ePccGAjnviF3OzxI4TmAcMUXAAQAEAAAAAA0oA4=","257":"b:ePccGAjnviF3OzxI4TmAcMUXAAQAEAAAAAA0oA4=","290":"b:ePccGAjnviF3OzxI4TmAcMUXAAQAEAAAAAA0oA4=","307":"b:ePccGAjnviF3OzxI4TmAcMUXAAQAEAAAAAA0oA4=","392":"b:ePccGAjnviF3OzxI4TmAcMUXAAQAEAAAAAA0oA4=","404":"b:ePccGAjnviF3OzxI4TmAcMUXAAQAEAAAAAA0oA4=","515":"b:ePccGAjnviF3OzxI4TmAcMUXAAQAEAAAAAA0oA4=","527":"b:ePccGAjnviF3OzxI4TmAcMUXAAQAEAAAAAA0oA4=","541":"b:ePccGAjnviF3OzxI4TmAcMUXAAQAEAAAAAA0oA4=","542":"b:ePccGAjnviF3OzxI4TmAcMUXAAQAEAAAAAA0oA4=","556":"b:ePccGAjnviF3OzxI4TmAcMUXAAQAEAAAAAA0oA4=","575":"b:ePccGAjnviF3OzxI4TmAcMUXAAQAEAAAAAA0oA4=","801":"b:ePccGAjnviF3OzxI4TmAcMUXAAQAEAAAAAA0oA4=","811":"b:ePccGAjnviF3OzxI4TmAcMUXAAQAEAAAAAA0oA4=","850":"b:ePccGAjnviF3OzxI4TmAcMUXAAQAEAAAAAA0oA4=","857":"b:ePccGAjnviF3OzxI4TmAcMUXAAQAEAAAAAA0oA4=","919":"b:ePccGAjnviF3OzxI4TmAcMUXAAQAEAAAAAA0oA4=","925":"b:ePccGAjnviF3OzxI4TmAcMUXAAQAEAAAAAA0oA4=","935":"b:ePccGAjnviF3OzxI4TmAcMUXAAQAEAAAAAA0oA4=","972":"b:ePccGAjnviF3OzxI4TmAcMUXAAQAEAAAAAA0oA4=","975":"b:ePccGAjnviF3OzxI4TmAcMUXAAQAEAAAAAA0oA4=","978":"b:ePccGAjnviF3OzxI4TmAcMUXAAQAEAAAAAA0oA4="},"packages/cli/src/workflow-helpers.ts":{"11":"b:+P++nKz9viH3fnxs6TnAdewfAAAAMAIAAAAwoAw=","51":"b:+P++nKz9viH3fnxs6TnAdewfAAAAMAIAAAAwoAw=","78":"b:+P++nKz9viH3fnxs6TnAdewfAAAAMAIAAAAwoAw=","82":"b:+P++nKz9viH3fnxs6TnAdewfAAAAMAIAAAAwoAw=","94":"b:+P++nKz9viH3fnxs6TnAdewfAAAAMAIAAAAwoAw=","121":"b:+P++nKz9viH3fnxs6TnAdewfAAAAMAIAAAAwoAw=","150":"b:+P++nKz9viH3fnxs6TnAdewfAAAAMAIAAAAwoAw=","188":"b:+P++nKz9viH3fnxs6TnAdewfAAAAMAIAAAAwoAw=","196":"b:+P++nKz9viH3fnxs6TnAdewfAAAAMAIAAAAwoAw=","202":"b:+P++nKz9viH3fnxs6TnAdewfAAAAMAIAAAAwoAw=","225":"b:+P++nKz9viH3fnxs6TnAdewfAAAAMAIAAAAwoAw=","262":"b:+P++nKz9viH3fnxs6TnAdewfAAAAMAIAAAAwoAw=","267":"b:+P++nKz9viH3fnxs6TnAdewfAAAAMAIAAAAwoAw=","398":"b:+P++nKz9viH3fnxs6TnAdewfAAAAMAIAAAAwoAw=","419":"b:+P++nKz9viH3fnxs6TnAdewfAAAAMAIAAAAwoAw=","448":"b:+P++nKz9viH3fnxs6TnAdewfAAAAMAIAAAAwoAw=","577":"b:+P++nKz9viH3fnxs6TnAdewfAAAAMAIAAAAwoAw=","599":"b:+P++nKz9viH3fnxs6TnAdewfAAAAMAIAAAAwoAw="},"packages/cli/src/workflow-runner.ts":{"98":"b:eJccHAjFviFHGjhI4QkAQMQ1CAAAAAAAACAAgAg=","110":"b:eJccHAjFviFHGjhI4QkAQMQ1CAAAAAAAACAAgAg=","132":"b:eJccHAjFviFHGjhI4QkAQMQ1CAAAAAAAACAAgAg=","329":"b:eJccHAjFviFHGjhI4QkAQMQ1CAAAAAAAACAAgAg=","351":"b:eJccHAjFviFHGjhI4QkAQMQ1CAAAAAAAACAAgAg=","404":"b:eJccHAjFviFHGjhI4QkAQMQ1CAAAAAAAACAAgAg=","502":"b:eJccHAjFviFHGjhI4QkAQMQ1CAAAAAAAACAAgAg=","521":"b:eJccHAjFviFHGjhI4QkAQMQ1CAAAAAAAACAAgAg=","529":"b:eJccHAjFviFHGjhI4QkAQMQ1CAAAAAAAACAAgAg=","536":"b:eJccHAjFviFHGjhI4QkAQMQ1CAAAAAAAACAAgAg=","543":"b:eJccHAjFviFHGjhI4QkAQMQ1CAAAAAAAACAAgAg=","563":"b:eJccHAjFviFHGjhI4QkAQMQ1CAAAAAAAACAAgAg=","629":"b:eJccHAjFviFHGjhI4QkAQMQ1CAAAAAAAACAAgAg=","634":"b:eJccHAjFviFHGjhI4QkAQMQ1CAAAAAAAACAAgAg=","690":"b:eJccHAjFviFHGjhI4QkAQMQ1CAAAAAAAACAAgAg=","700":"b:eJccHAjFviFHGjhI4QkAQMQ1CAAAAAAAACAAgAg=","711":"b:eJccHAjFviFHGjhI4QkAQMQ1CAAAAAAAACAAgAg=","735":"b:eJccHAjFviFHGjhI4QkAQMQ1CAAAAAAAACAAgAg=","801":"b:eJccHAjFviFHGjhI4QkAQMQ1CAAAAAAAACAAgAg=","803":"b:eJccHAjFviFHGjhI4QkAQMQ1CAAAAAAAACAAgAg=","945":"b:eJccHAjFviFHGjhI4QkAQMQ1CAAAAAAAACAAgAg=","967":"b:eJccHAjFviFHGjhI4QkAQMQ1CAAAAAAAACAAgAg="},"packages/cli/src/workflows/deprecated-nodes-validation.service.ts":{"21":"b:+L+ekKz9viH3PnxsaTkAROgJAAAAIAIAAAAAAAA=","28":"b:+L+ekKz9viH3PnxsaTkAROgJAAAAIAIAAAAAAAA=","45":"b:+L+ekKz9viH3PnxsaTkAROgJAAAAIAIAAAAAAAA=","48":"b:+L+ekKz9viH3PnxsaTkAROgJAAAAIAIAAAAAAAA=","73":"b:+L+ekKz9viH3PnxsaTkAROgJAAAAIAIAAAAAAAA=","104":"b:+L+ekKz9viH3PnxsaTkAROgJAAAAIAIAAAAAAAA=","109":"b:+L+ekKz9viH3PnxsaTkAROgJAAAAIAIAAAAAAAA=","115":"b:+L+ekKz9viH3PnxsaTkAROgJAAAAIAIAAAAAAAA=","125":"b:+L+ekKz9viH3PnxsaTkAROgJAAAAIAIAAAAAAAA=","126":"b:+L+ekKz9viH3PnxsaTkAROgJAAAAIAIAAAAAAAA="},"packages/cli/src/workflows/publication/workflow-publication-outbox-consumer.ts":{"69":"b:/vf+/y79v//1vh/rycmBCAAAAAAAEAAAAAAgoAA=","83":"b:/vf+/y79v//1vh/rycmBCAAAAAAAEAAAAAAgoAA=","84":"b:/vf+/y79v//1vh/rycmBCAAAAAAAEAAAAAAgoAA=","86":"b:/vf+/y79v//1vh/rycmBCAAAAAAAEAAAAAAgoAA=","90":"b:/vf+/y79v//1vh/rycmBCAAAAAAAEAAAAAAgoAA=","98":"b:/vf+/y79v//1vh/rycmBCAAAAAAAEAAAAAAgoAA=","107":"b:/vf+/y79v//1vh/rycmBCAAAAAAAEAAAAAAgoAA=","118":"b:/vf+/y79v//1vh/rycmBCAAAAAAAEAAAAAAgoAA=","134":"b:/vf+/y79v//1vh/rycmBCAAAAAAAEAAAAAAgoAA=","158":"b:/vf+/y79v//1vh/rycmBCAAAAAAAEAAAAAAgoAA=","162":"b:/vf+/y79v//1vh/rycmBCAAAAAAAEAAAAAAgoAA=","183":"b:/vf+/y79v//1vh/rycmBCAAAAAAAEAAAAAAgoAA=","203":"b:/vf+/y79v//1vh/rycmBCAAAAAAAEAAAAAAgoAA=","218":"b:/vf+/y79v//1vh/rycmBCAAAAAAAEAAAAAAgoAA=","242":"b:/vf+/y79v//1vh/rycmBCAAAAAAAEAAAAAAgoAA=","252":"b:/vf+/y79v//1vh/rycmBCAAAAAAAEAAAAAAgoAA=","267":"b:/vf+/y79v//1vh/rycmBCAAAAAAAEAAAAAAgoAA=","281":"b:/vf+/y79v//1vh/rycmBCAAAAAAAEAAAAAAgoAA=","289":"b:/vf+/y79v//1vh/rycmBCAAAAAAAEAAAAAAgoAA=","290":"b:/vf+/y79v//1vh/rycmBCAAAAAAAEAAAAAAgoAA=","311":"b:/vf+/y79v//1vh/rycmBCAAAAAAAEAAAAAAgoAA=","322":"b:/vf+/y79v//1vh/rycmBCAAAAAAAEAAAAAAgoAA=","326":"b:/vf+/y79v//1vh/rycmBCAAAAAAAEAAAAAAgoAA=","371":"b:/vf+/y79v//1vh/rycmBCAAAAAAAEAAAAAAgoAA=","454":"b:/vf+/y79v//1vh/rycmBCAAAAAAAEAAAAAAgoAA=","482":"b:/vf+/y79v//1vh/rycmBCAAAAAAAEAAAAAAgoAA=","492":"b:/vf+/y79v//1vh/rycmBCAAAAAAAEAAAAAAgoAA="},"packages/cli/src/workflows/utils.ts":{"19":"b:+L++gCj9viH3PnxsaykAyME/AAQAAAAAAAAAAAA=","26":"b:+L++gCj9viH3PnxsaykAyME/AAQAAAAAAAAAAAA=","27":"b:+L++gCj9viH3PnxsaykAyME/AAQAAAAAAAAAAAA=","35":"b:+L++gCj9viH3PnxsaykAyME/AAQAAAAAAAAAAAA=","41":"b:+L++gCj9viH3PnxsaykAyME/AAQAAAAAAAAAAAA=","46":"b:+L++gCj9viH3PnxsaykAyME/AAQAAAAAAAAAAAA=","56":"b:+L++gCj9viH3PnxsaykAyME/AAQAAAAAAAAAAAA="},"packages/cli/src/workflows/workflow-creation.service.ts":{"54":"b:+L+igCj9viH3PnxsaSkAQEAKAAAAQAAAAAAAAAA=","81":"b:+L+igCj9viH3PnxsaSkAQEAKAAAAQAAAAAAAAAA=","100":"b:+L+igCj9viH3PnxsaSkAQEAKAAAAQAAAAAAAAAA=","104":"b:+L+igCj9viH3PnxsaSkAQEAKAAAAQAAAAAAAAAA=","105":"b:+L+igCj9viH3PnxsaSkAQEAKAAAAQAAAAAAAAAA=","107":"b:+L+igCj9viH3PnxsaSkAQEAKAAAAQAAAAAAAAAA=","119":"b:+L+igCj9viH3PnxsaSkAQEAKAAAAQAAAAAAAAAA=","141":"b:+L+igCj9viH3PnxsaSkAQEAKAAAAQAAAAAAAAAA=","246":"b:+L+igCj9viH3PnxsaSkAQEAKAAAAQAAAAAAAAAA=","315":"b:+L+igCj9viH3PnxsaSkAQEAKAAAAQAAAAAAAAAA=","418":"b:+L+igCj9viH3PnxsaSkAQEAKAAAAQAAAAAAAAAA=","430":"b:+L+igCj9viH3PnxsaSkAQEAKAAAAQAAAAAAAAAA=","435":"b:+L+igCj9viH3PnxsaSkAQEAKAAAAQAAAAAAAAAA=","446":"b:+L+igCj9viH3PnxsaSkAQEAKAAAAQAAAAAAAAAA=","489":"b:+L+igCj9viH3PnxsaSkAQEAKAAAAQAAAAAAAAAA="},"packages/cli/src/workflows/workflow-entity-mapper.ts":{"24":"b:+L+igCj9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","31":"b:+L+igCj9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","32":"b:+L+igCj9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/cli/src/workflows/workflow-execution.service.ts":{"63":"b:eAccAAjH/gFGGjBIc4AQiMU3AEQAKAIAAGAGAAA=","84":"b:eAccAAjH/gFGGjBIc4AQiMU3AEQAKAIAAGAGAAA=","134":"b:eAccAAjH/gFGGjBIc4AQiMU3AEQAKAIAAGAGAAA=","277":"b:eAccAAjH/gFGGjBIc4AQiMU3AEQAKAIAAGAGAAA=","319":"b:eAccAAjH/gFGGjBIc4AQiMU3AEQAKAIAAGAGAAA=","335":"b:eAccAAjH/gFGGjBIc4AQiMU3AEQAKAIAAGAGAAA=","336":"b:eAccAAjH/gFGGjBIc4AQiMU3AEQAKAIAAGAGAAA=","347":"b:eAccAAjH/gFGGjBIc4AQiMU3AEQAKAIAAGAGAAA=","526":"b:eAccAAjH/gFGGjBIc4AQiMU3AEQAKAIAAGAGAAA=","574":"b:eAccAAjH/gFGGjBIc4AQiMU3AEQAKAIAAGAGAAA=","619":"b:eAccAAjH/gFGGjBIc4AQiMU3AEQAKAIAAGAGAAA=","782":"b:eAccAAjH/gFGGjBIc4AQiMU3AEQAKAIAAGAGAAA=","800":"b:eAccAAjH/gFGGjBIc4AQiMU3AEQAKAIAAGAGAAA=","805":"b:eAccAAjH/gFGGjBIc4AQiMU3AEQAKAIAAGAGAAA=","808":"b:eAccAAjH/gFGGjBIc4AQiMU3AEQAKAIAAGAGAAA=","811":"b:eAccAAjH/gFGGjBIc4AQiMU3AEQAKAIAAGAGAAA=","814":"b:eAccAAjH/gFGGjBIc4AQiMU3AEQAKAIAAGAGAAA=","822":"b:eAccAAjH/gFGGjBIc4AQiMU3AEQAKAIAAGAGAAA=","841":"b:eAccAAjH/gFGGjBIc4AQiMU3AEQAKAIAAGAGAAA=","856":"b:eAccAAjH/gFGGjBIc4AQiMU3AEQAKAIAAGAGAAA=","870":"b:eAccAAjH/gFGGjBIc4AQiMU3AEQAKAIAAGAGAAA=","883":"b:eAccAAjH/gFGGjBIc4AQiMU3AEQAKAIAAGAGAAA=","895":"b:eAccAAjH/gFGGjBIc4AQiMU3AEQAKAIAAGAGAAA=","902":"b:eAccAAjH/gFGGjBIc4AQiMU3AEQAKAIAAGAGAAA="},"packages/cli/src/workflows/workflow-finder.service.ts":{"42":"b:+L+ikCz9viH3vnxtaSkAZmwKgAAAUgAAEAoAAAA=","50":"b:+L+ikCz9viH3vnxtaSkAZmwKgAAAUgAAEAoAAAA=","84":"b:+L+ikCz9viH3vnxtaSkAZmwKgAAAUgAAEAoAAAA=","107":"b:+L+ikCz9viH3vnxtaSkAZmwKgAAAUgAAEAoAAAA=","113":"b:+L+ikCz9viH3vnxtaSkAZmwKgAAAUgAAEAoAAAA=","114":"b:+L+ikCz9viH3vnxtaSkAZmwKgAAAUgAAEAoAAAA=","135":"b:+L+ikCz9viH3vnxtaSkAZmwKgAAAUgAAEAoAAAA=","186":"b:+L+ikCz9viH3vnxtaSkAZmwKgAAAUgAAEAoAAAA=","205":"b:+L+ikCz9viH3vnxtaSkAZmwKgAAAUgAAEAoAAAA=","209":"b:+L+ikCz9viH3vnxtaSkAZmwKgAAAUgAAEAoAAAA=","212":"b:+L+ikCz9viH3vnxtaSkAZmwKgAAAUgAAEAoAAAA=","253":"b:+L+ikCz9viH3vnxtaSkAZmwKgAAAUgAAEAoAAAA=","288":"b:+L+ikCz9viH3vnxtaSkAZmwKgAAAUgAAEAoAAAA=","309":"b:+L+ikCz9viH3vnxtaSkAZmwKgAAAUgAAEAoAAAA=","328":"b:+L+ikCz9viH3vnxtaSkAZmwKgAAAUgAAEAoAAAA=","339":"b:+L+ikCz9viH3vnxtaSkAZmwKgAAAUgAAEAoAAAA=","356":"b:+L+ikCz9viH3vnxtaSkAZmwKgAAAUgAAEAoAAAA=","365":"b:+L+ikCz9viH3vnxtaSkAZmwKgAAAUgAAEAoAAAA=","414":"b:+L+ikCz9viH3vnxtaSkAZmwKgAAAUgAAEAoAAAA=","418":"b:+L+ikCz9viH3vnxtaSkAZmwKgAAAUgAAEAoAAAA=","427":"b:+L+ikCz9viH3vnxtaSkAZmwKgAAAUgAAEAoAAAA=","439":"b:+L+ikCz9viH3vnxtaSkAZmwKgAAAUgAAEAoAAAA=","446":"b:+L+ikCz9viH3vnxtaSkAZmwKgAAAUgAAEAoAAAA="},"packages/cli/src/workflows/workflow-history/workflow-history.service.ts":{"40":"b:+P+ilCz9viH3vn9sbSkAQGwKEUAAEgAAAAgAAAA=","49":"b:+P+ilCz9viH3vn9sbSkAQGwKEUAAEgAAAAgAAAA=","85":"b:+P+ilCz9viH3vn9sbSkAQGwKEUAAEgAAAAgAAAA=","88":"b:+P+ilCz9viH3vn9sbSkAQGwKEUAAEgAAAAgAAAA=","98":"b:+P+ilCz9viH3vn9sbSkAQGwKEUAAEgAAAAgAAAA=","136":"b:+P+ilCz9viH3vn9sbSkAQGwKEUAAEgAAAAgAAAA=","158":"b:+P+ilCz9viH3vn9sbSkAQGwKEUAAEgAAAAgAAAA=","201":"b:+P+ilCz9viH3vn9sbSkAQGwKEUAAEgAAAAgAAAA=","237":"b:+P+ilCz9viH3vn9sbSkAQGwKEUAAEgAAAAgAAAA=","272":"b:+P+ilCz9viH3vn9sbSkAQGwKEUAAEgAAAAgAAAA=","320":"b:+P+ilCz9viH3vn9sbSkAQGwKEUAAEgAAAAgAAAA=","337":"b:+P+ilCz9viH3vn9sbSkAQGwKEUAAEgAAAAgAAAA=","362":"b:+P+ilCz9viH3vn9sbSkAQGwKEUAAEgAAAAgAAAA=","365":"b:+P+ilCz9viH3vn9sbSkAQGwKEUAAEgAAAAgAAAA=","380":"b:+P+ilCz9viH3vn9sbSkAQGwKEUAAEgAAAAgAAAA="},"packages/cli/src/workflows/workflow-validation.service.ts":{"57":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","58":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","63":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","79":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","88":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","99":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","160":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","161":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","184":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","216":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","276":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","297":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","324":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","345":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","380":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","389":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","400":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","408":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","418":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","481":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","515":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","527":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","528":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","554":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","589":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","594":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","622":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","666":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","671":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","705":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","724":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","749":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","757":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI=","778":"b:+P+ilCz9viH3/n9seanATGAKAAAAMAAAAAAgoAI="},"packages/cli/src/workflows/workflow.service.ee.ts":{"53":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","72":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","85":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","87":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","94":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","105":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","117":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","123":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","127":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","144":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","158":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","174":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","175":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","182":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","185":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","193":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","204":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","238":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","253":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","269":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","290":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","343":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","348":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","350":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","354":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","391":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","436":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","448":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","449":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","452":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","469":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","480":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","487":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","542":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","564":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","639":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","665":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","697":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","722":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","746":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","772":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","783":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","822":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","831":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","832":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","835":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","837":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","863":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","868":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","881":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","895":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","901":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI=","922":"b:+L+imKz9viH3fnxoaznARO5LAQEAYAIAEAIwIAI="},"packages/cli/src/workflows/workflow.service.ts":{"152":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","212":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","251":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","324":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","355":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","371":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","383":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","404":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","421":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","434":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","441":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","445":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","451":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","463":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","466":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","467":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","470":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","471":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","475":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","481":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","486":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","492":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","500":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","507":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","511":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","513":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","527":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","540":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","859":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","904":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","968":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","997":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1072":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1096":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1106":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1124":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1401":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1483":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1550":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1576":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1625":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1660":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1736":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1766":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1839":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1877":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1881":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1885":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1890":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1894":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1906":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1914":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1923":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1924":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1935":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1936":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1941":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1947":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1959":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1966":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1977":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1979":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1986":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1996":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","1997":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","2017":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","2031":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","2053":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","2077":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","2116":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","2138":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","2145":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","2169":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","2234":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","2240":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA=","2284":"b:+P+/l+z9vq3/vn9rebmATulKgAAMcAKAFAhgqAA="},"packages/cli/src/workflows/workflows.controller.ts":{"71":"b:+P/jl6z9v63/vn9rb7mAzu1/oEEIMgaAFAggqAA=","96":"b:+P/jl6z9v63/vn9rb7mAzu1/oEEIMgaAFAggqAA=","129":"b:+P/jl6z9v63/vn9rb7mAzu1/oEEIMgaAFAggqAA=","158":"b:+P/jl6z9v63/vn9rb7mAzu1/oEEIMgaAFAggqAA=","174":"b:+P/jl6z9v63/vn9rb7mAzu1/oEEIMgaAFAggqAA=","208":"b:+P/jl6z9v63/vn9rb7mAzu1/oEEIMgaAFAggqAA=","294":"b:+P/jl6z9v63/vn9rb7mAzu1/oEEIMgaAFAggqAA=","301":"b:+P/jl6z9v63/vn9rb7mAzu1/oEEIMgaAFAggqAA=","355":"b:+P/jl6z9v63/vn9rb7mAzu1/oEEIMgaAFAggqAA=","366":"b:+P/jl6z9v63/vn9rb7mAzu1/oEEIMgaAFAggqAA=","387":"b:+P/jl6z9v63/vn9rb7mAzu1/oEEIMgaAFAggqAA=","421":"b:+P/jl6z9v63/vn9rb7mAzu1/oEEIMgaAFAggqAA=","455":"b:+P/jl6z9v63/vn9rb7mAzu1/oEEIMgaAFAggqAA=","490":"b:+P/jl6z9v63/vn9rb7mAzu1/oEEIMgaAFAggqAA=","521":"b:+P/jl6z9v63/vn9rb7mAzu1/oEEIMgaAFAggqAA=","578":"b:+P/jl6z9v63/vn9rb7mAzu1/oEEIMgaAFAggqAA=","584":"b:+P/jl6z9v63/vn9rb7mAzu1/oEEIMgaAFAggqAA=","598":"b:+P/jl6z9v63/vn9rb7mAzu1/oEEIMgaAFAggqAA=","599":"b:+P/jl6z9v63/vn9rb7mAzu1/oEEIMgaAFAggqAA=","603":"b:+P/jl6z9v63/vn9rb7mAzu1/oEEIMgaAFAggqAA=","604":"b:+P/jl6z9v63/vn9rb7mAzu1/oEEIMgaAFAggqAA=","608":"b:+P/jl6z9v63/vn9rb7mAzu1/oEEIMgaAFAggqAA=","609":"b:+P/jl6z9v63/vn9rb7mAzu1/oEEIMgaAFAggqAA=","630":"b:+P/jl6z9v63/vn9rb7mAzu1/oEEIMgaAFAggqAA=","654":"b:+P/jl6z9v63/vn9rb7mAzu1/oEEIMgaAFAggqAA=","661":"b:+P/jl6z9v63/vn9rb7mAzu1/oEEIMgaAFAggqAA=","678":"b:+P/jl6z9v63/vn9rb7mAzu1/oEEIMgaAFAggqAA=","699":"b:+P/jl6z9v63/vn9rb7mAzu1/oEEIMgaAFAggqAA=","721":"b:+P/jl6z9v63/vn9rb7mAzu1/oEEIMgaAFAggqAA=","747":"b:+P/jl6z9v63/vn9rb7mAzu1/oEEIMgaAFAggqAA=","764":"b:+P/jl6z9v63/vn9rb7mAzu1/oEEIMgaAFAggqAA="},"packages/core/src/execution-engine/execution-context-hook-registry.service.ts":{"18":"b:eJccFAjFviFHGjhI4QmAQMQ1AAAAAAAAAAAwgAI=","34":"b:eJccFAjFviFHGjhI4QmAQMQ1AAAAAAAAAAAwgAI=","89":"b:eJccFAjFviFHGjhI4QmAQMQ1AAAAAAAAAAAwgAI=","98":"b:eJccFAjFviFHGjhI4QmAQMQ1AAAAAAAAAAAwgAI=","111":"b:eJccFAjFviFHGjhI4QmAQMQ1AAAAAAAAAAAwgAI=","112":"b:eJccFAjFviFHGjhI4QmAQMQ1AAAAAAAAAAAwgAI=","117":"b:eJccFAjFviFHGjhI4QmAQMQ1AAAAAAAAAAAwgAI=","127":"b:eJccFAjFviFHGjhI4QmAQMQ1AAAAAAAAAAAwgAI="},"packages/core/src/execution-engine/execution-context.service.ts":{"25":"b:eJc8HAjFviFPejhI4wmAyMU3AEUAAAAAAAAygAI=","31":"b:eJc8HAjFviFPejhI4wmAyMU3AEUAAAAAAAAygAI=","36":"b:eJc8HAjFviFPejhI4wmAyMU3AEUAAAAAAAAygAI=","55":"b:eJc8HAjFviFPejhI4wmAyMU3AEUAAAAAAAAygAI=","77":"b:eJc8HAjFviFPejhI4wmAyMU3AEUAAAAAAAAygAI=","95":"b:eJc8HAjFviFPejhI4wmAyMU3AEUAAAAAAAAygAI=","104":"b:eJc8HAjFviFPejhI4wmAyMU3AEUAAAAAAAAygAI=","148":"b:eJc8HAjFviFPejhI4wmAyMU3AEUAAAAAAAAygAI=","173":"b:eJc8HAjFviFPejhI4wmAyMU3AEUAAAAAAAAygAI=","185":"b:eJc8HAjFviFPejhI4wmAyMU3AEUAAAAAAAAygAI=","207":"b:eJc8HAjFviFPejhI4wmAyMU3AEUAAAAAAAAygAI=","235":"b:eJc8HAjFviFPejhI4wmAyMU3AEUAAAAAAAAygAI="},"packages/core/src/execution-engine/execution-context.ts":{"134":"b:eNccFAjFviFHGjhI4YmAQMQ1AAAAAAAAAAAwgAA=","141":"b:eNccFAjFviFHGjhI4YmAQMQ1AAAAAAAAAAAwgAA="},"packages/core/src/execution-engine/execution-lifecycle-hooks.ts":{"103":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","110":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","118":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA="},"packages/core/src/execution-engine/node-execution-context/base-execute-context.ts":{"56":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4=","71":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4=","75":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4=","79":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4=","80":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4=","87":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4=","88":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4=","100":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4=","104":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4=","108":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4=","113":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4=","123":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4=","135":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4=","139":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4=","149":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4=","158":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4=","223":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4=","253":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4=","267":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4=","275":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4=","298":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4=","307":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4=","331":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4=","335":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4=","353":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4=","361":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4=","381":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4=","398":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4=","403":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4=","412":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4=","437":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4=","448":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4=","473":"b:eMc8HAjHviEAGzhI4RmA4MU3AAQAMAAAAAA0oA4="},"packages/core/src/execution-engine/node-execution-context/execute-context.ts":{"51":"b:eIccHAjFviEAGjhI4QkAQMQ1CAAABAAAAIAAgAg=","98":"b:eIccHAjFviEAGjhI4QkAQMQ1CAAABAAAAIAAgAg=","100":"b:eIccHAjFviEAGjhI4QkAQMQ1CAAABAAAAIAAgAg=","108":"b:eIccHAjFviEAGjhI4QkAQMQ1CAAABAAAAIAAgAg=","113":"b:eIccHAjFviEAGjhI4QkAQMQ1CAAABAAAAIAAgAg=","128":"b:eIccHAjFviEAGjhI4QkAQMQ1CAAABAAAAIAAgAg=","149":"b:eIccHAjFviEAGjhI4QkAQMQ1CAAABAAAAIAAgAg=","157":"b:eIccHAjFviEAGjhI4QkAQMQ1CAAABAAAAIAAgAg=","159":"b:eIccHAjFviEAGjhI4QkAQMQ1CAAABAAAAIAAgAg=","174":"b:eIccHAjFviEAGjhI4QkAQMQ1CAAABAAAAIAAgAg=","179":"b:eIccHAjFviEAGjhI4QkAQMQ1CAAABAAAAIAAgAg=","184":"b:eIccHAjFviEAGjhI4QkAQMQ1CAAABAAAAIAAgAg=","188":"b:eIccHAjFviEAGjhI4QkAQMQ1CAAABAAAAIAAgAg=","192":"b:eIccHAjFviEAGjhI4QkAQMQ1CAAABAAAAIAAgAg=","197":"b:eIccHAjFviEAGjhI4QkAQMQ1CAAABAAAAIAAgAg="},"packages/core/src/execution-engine/node-execution-context/node-execution-context.ts":{"57":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","69":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","74":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","86":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","90":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","94":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","98":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","103":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","107":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","111":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","133":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","171":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","182":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","186":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","191":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","202":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","212":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","217":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","219":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","223":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","228":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","230":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","234":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","237":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","238":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","239":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","242":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","246":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","250":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","254":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","258":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","262":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","270":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","274":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","305":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","309":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","318":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","329":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","384":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","495":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","509":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","514":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","524":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","623":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo=","638":"b:ePc8HEjlviF3+jlI85mAYMQXCEEAOAABQKAwoAo="},"packages/core/src/execution-engine/node-execution-context/utils/binary-helper-functions.ts":{"33":"b:eLccFAjFviFxGjhI4QkAQMQ1AAAABAAAAAAAgAA=","40":"b:eLccFAjFviFxGjhI4QkAQMQ1AAAABAAAAAAAgAA=","47":"b:eLccFAjFviFxGjhI4QkAQMQ1AAAABAAAAAAAgAA=","56":"b:eLccFAjFviFxGjhI4QkAQMQ1AAAABAAAAAAAgAA=","128":"b:eLccFAjFviFxGjhI4QkAQMQ1AAAABAAAAAAAgAA=","155":"b:eLccFAjFviFxGjhI4QkAQMQ1AAAABAAAAAAAgAA=","167":"b:eLccFAjFviFxGjhI4QkAQMQ1AAAABAAAAAAAgAA=","180":"b:eLccFAjFviFxGjhI4QkAQMQ1AAAABAAAAAAAgAA=","239":"b:eLccFAjFviFxGjhI4QkAQMQ1AAAABAAAAAAAgAA=","243":"b:eLccFAjFviFxGjhI4QkAQMQ1AAAABAAAAAAAgAA=","252":"b:eLccFAjFviFxGjhI4QkAQMQ1AAAABAAAAAAAgAA=","350":"b:eLccFAjFviFxGjhI4QkAQMQ1AAAABAAAAAAAgAA=","359":"b:eLccFAjFviFxGjhI4QkAQMQ1AAAABAAAAAAAgAA=","363":"b:eLccFAjFviFxGjhI4QkAQMQ1AAAABAAAAAAAgAA=","365":"b:eLccFAjFviFxGjhI4QkAQMQ1AAAABAAAAAAAgAA=","367":"b:eLccFAjFviFxGjhI4QkAQMQ1AAAABAAAAAAAgAA="},"packages/core/src/execution-engine/node-execution-context/utils/cleanup-parameter-data.ts":{"8":"b:eLccHAjlviExEjhI4YkAQcQXAEQAAgAAAIAAgAA=","14":"b:eLccHAjlviExEjhI4YkAQcQXAEQAAgAAAIAAgAA=","19":"b:eLccHAjlviExEjhI4YkAQcQXAEQAAgAAAIAAgAA="},"packages/core/src/execution-engine/node-execution-context/utils/credential-check-helper-functions.ts":{"3":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","9":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAAAAAAAAAAgAA="},"packages/core/src/execution-engine/node-execution-context/utils/custom-data.ts":{"15":"b:eIccFAjBACAAEjgI4QEAQMQ3AAAAAAABQIAAgAA=","23":"b:eIccFAjBACAAEjgI4QEAQMQ3AAAAAAABQIAAgAA=","34":"b:eIccFAjBACAAEjgI4QEAQMQ3AAAAAAABQIAAgAA=","45":"b:eIccFAjBACAAEjgI4QEAQMQ3AAAAAAABQIAAgAA=","48":"b:eIccFAjBACAAEjgI4QEAQMQ3AAAAAAABQIAAgAA="},"packages/core/src/execution-engine/node-execution-context/utils/data-table-helper-functions.ts":{"8":"b:eIccFAjFviEGOjhI4QkAQMQ1AAAAAAAAAAAAgAA=","16":"b:eIccFAjFviEGOjhI4QkAQMQ1AAAAAAAAAAAAgAA=","22":"b:eIccFAjFviEGOjhI4QkAQMQ1AAAAAAAAAAAAgAA="},"packages/core/src/execution-engine/node-execution-context/utils/deduplication-helper-functions.ts":{"16":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","30":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","46":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","60":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","72":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","84":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","88":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","95":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","109":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","116":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","122":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAAAAAAAAAAgAA="},"packages/core/src/execution-engine/node-execution-context/utils/file-system-helper-functions.ts":{"41":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA=","47":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA=","48":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA=","49":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA=","54":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA=","60":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA=","77":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA=","85":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA=","86":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA=","87":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA=","97":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA=","106":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA=","127":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA=","133":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA=","143":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA=","149":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA=","150":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA=","158":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA=","170":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA=","178":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA=","190":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA=","243":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA=","246":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA=","252":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA=","279":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA=","280":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA=","330":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA=","334":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA=","424":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA=","436":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA=","439":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA=","443":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA=","451":"b:eIccFAjFviEAGjhI4QkAQMQ1AAAABAAAAAAAgAA="},"packages/core/src/execution-engine/node-execution-context/utils/get-additional-keys.ts":{"13":"b:eLccFAjlviExEjxI4SkAUMQ1AAAAAAAAAIAAgAA=","20":"b:eLccFAjlviExEjxI4SkAUMQ1AAAAAAAAAIAAgAA=","62":"b:eLccFAjlviExEjxI4SkAUMQ1AAAAAAAAAIAAgAA="},"packages/core/src/execution-engine/node-execution-context/utils/request-helpers/factory.ts":{"28":"b:eLccFAjHviF3ezhI4QkAQMQVAAUAEAAAACACgAA=","35":"b:eLccFAjHviF3ezhI4QkAQMQVAAUAEAAAACACgAA=","70":"b:eLccFAjHviF3ezhI4QkAQMQVAAUAEAAAACACgAA=","90":"b:eLccFAjHviF3ezhI4QkAQMQVAAUAEAAAACACgAA=","92":"b:eLccFAjHviF3ezhI4QkAQMQVAAUAEAAAACACgAA=","114":"b:eLccFAjHviF3ezhI4QkAQMQVAAUAEAAAACACgAA=","131":"b:eLccFAjHviF3ezhI4QkAQMQVAAUAEAAAACACgAA=","145":"b:eLccFAjHviF3ezhI4QkAQMQVAAUAEAAAACACgAA=","170":"b:eLccFAjHviF3ezhI4QkAQMQVAAUAEAAAACACgAA=","191":"b:eLccFAjHviF3ezhI4QkAQMQVAAUAEAAAACACgAA=","212":"b:eLccFAjHviF3ezhI4QkAQMQVAAUAEAAAACACgAA="},"packages/core/src/execution-engine/node-execution-context/utils/resolve-source-overwrite.ts":{"7":"b:eJccFAjFviFAGjhI4QkAQMQ1AAAAAAAAAAAAgAA="},"packages/core/src/execution-engine/node-execution-context/utils/ssh-tunnel-helper-functions.ts":{"7":"b:eKccFAjFviF2OjhI4QkAQMQVAAAAAAAAAAAAgAA=","10":"b:eKccFAjFviF2OjhI4QkAQMQVAAAAAAAAAAAAgAA=","12":"b:eKccFAjFviF2OjhI4QkAQMQVAAAAAAAAAAAAgAA="},"packages/core/src/execution-engine/node-execution-context/utils/validate-value-against-schema.ts":{"25":"b:ePccHAjlviExkjhI4wmAQcQ1AEAACgAAAKAggAY=","46":"b:ePccHAjlviExkjhI4wmAQcQ1AEAACgAAAKAggAY=","113":"b:ePccHAjlviExkjhI4wmAQcQ1AEAACgAAAKAggAY=","125":"b:ePccHAjlviExkjhI4wmAQcQ1AEAACgAAAKAggAY=","187":"b:ePccHAjlviExkjhI4wmAQcQ1AEAACgAAAKAggAY=","198":"b:ePccHAjlviExkjhI4wmAQcQ1AEAACgAAAKAggAY="},"packages/core/src/execution-engine/requests-response.ts":{"31":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","55":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","89":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","187":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","203":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","238":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","290":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","296":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA="},"packages/core/src/execution-engine/ssh-clients-manager.ts":{"10":"b:eKccFAjFviF2OjhI5xkAwsSVoAkBEAAAAIAAgAA=","16":"b:eKccFAjFviF2OjhI5xkAwsSVoAkBEAAAAIAAgAA=","17":"b:eKccFAjFviF2OjhI5xkAwsSVoAkBEAAAAIAAgAA=","67":"b:eKccFAjFviF2OjhI5xkAwsSVoAkBEAAAAIAAgAA=","69":"b:eKccFAjFviF2OjhI5xkAwsSVoAkBEAAAAIAAgAA=","85":"b:eKccFAjFviF2OjhI5xkAwsSVoAkBEAAAAIAAgAA=","88":"b:eKccFAjFviF2OjhI5xkAwsSVoAkBEAAAAIAAgAA=","108":"b:eKccFAjFviF2OjhI5xkAwsSVoAkBEAAAAIAAgAA=","133":"b:eKccFAjFviF2OjhI5xkAwsSVoAkBEAAAAIAAgAA=","135":"b:eKccFAjFviF2OjhI5xkAwsSVoAkBEAAAAIAAgAA=","157":"b:eKccFAjFviF2OjhI5xkAwsSVoAkBEAAAAIAAgAA=","158":"b:eKccFAjFviF2OjhI5xkAwsSVoAkBEAAAAIAAgAA=","162":"b:eKccFAjFviF2OjhI5xkAwsSVoAkBEAAAAIAAgAA=","166":"b:eKccFAjFviF2OjhI5xkAwsSVoAkBEAAAAIAAgAA=","170":"b:eKccFAjFviF2OjhI5xkAwsSVoAkBEAAAAIAAgAA=","180":"b:eKccFAjFviF2OjhI5xkAwsSVoAkBEAAAAIAAgAA=","191":"b:eKccFAjFviF2OjhI5xkAwsSVoAkBEAAAAIAAgAA=","203":"b:eKccFAjFviF2OjhI5xkAwsSVoAkBEAAAAIAAgAA="},"packages/core/src/execution-engine/workflow-execute.ts":{"110":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","133":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","143":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","149":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","167":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","191":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","238":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","246":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","349":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","381":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","422":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","450":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","469":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","672":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","889":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","956":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","974":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","996":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1060":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1073":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1084":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1099":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1104":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1113":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1164":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1171":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1173":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1198":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1266":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1286":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1339":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1374":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1394":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1525":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1560":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1586":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1612":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1654":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1663":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1678":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1749":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1761":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1774":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1778":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1783":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1821":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1838":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1852":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1865":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1889":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1927":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1953":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","1962":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2000":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2009":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2013":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2024":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2044":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2062":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2155":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2168":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2189":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2206":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2211":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2216":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2221":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2232":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2247":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2260":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2281":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2285":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2349":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2350":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2363":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2364":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2597":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2693":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2710":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2713":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2740":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2745":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2782":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2798":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2816":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2837":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2856":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2877":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","2933":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","3016":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","3027":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","3039":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","3077":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","3146":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","3206":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","3207":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","3209":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc=","3217":"b:eNc8HAjHviFHGzhI4wmAyMU3AAQAGhMAACCEgAc="},"packages/core/src/nodes-loader/directory-loader.ts":{"37":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","88":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","108":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","117":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","123":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","135":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","139":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","143":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","145":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","146":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","147":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","150":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","165":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","229":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","242":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","260":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","289":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","310":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","313":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","325":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","327":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","332":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","344":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","369":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","400":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","406":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","412":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","424":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","443":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","460":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","479":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","499":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","513":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","533":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","539":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","540":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","542":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","548":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","582":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA=","604":"b:+PeelCzlviX3Pl9MbSmATcAJAARAEAAAAKAAgAA="},"packages/core/src/observability/tracing/tracing.ts":{"38":"b:+P+ilCz9viH3vn9s6amASEAKAAAAEAAAAAAgoAA=","62":"b:+P+ilCz9viH3vn9s6amASEAKAAAAEAAAAAAgoAA=","69":"b:+P+ilCz9viH3vn9s6amASEAKAAAAEAAAAAAgoAA=","77":"b:+P+ilCz9viH3vn9s6amASEAKAAAAEAAAAAAgoAA=","86":"b:+P+ilCz9viH3vn9s6amASEAKAAAAEAAAAAAgoAA=","94":"b:+P+ilCz9viH3vn9s6amASEAKAAAAEAAAAAAgoAA=","102":"b:+P+ilCz9viH3vn9s6amASEAKAAAAEAAAAAAgoAA="},"packages/core/src/storage.config.ts":{"22":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","34":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","40":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","68":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","103":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA="},"packages/core/src/utils/assertions.ts":{"14":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","31":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA="},"packages/core/src/utils/convert-binary-data.ts":{"13":"b:eJccFAjFviFAGjhI4QkAQMQ1AAAAAAAAAAAAgAA="},"packages/core/src/utils/deep-merge.ts":{"4":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA=","17":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA="},"packages/nodes-base/nodes/ExecuteWorkflow/ExecuteWorkflowTrigger/ExecuteWorkflowTrigger.node.ts":{"223":[3,83,45,225,212,213,119,142],"229":[3,83,45,225,212,213,119,142],"248":[3,83,45,225,212,213,119,142],"249":[3,83,45,225,212,213,119,142],"251":[3,83,45,225,212,213,119,142],"254":[3,83,45,225,212,213,119,142]},"packages/nodes-base/nodes/Set/Set.node.ts":{"8":"b:aIYAkAigACDUEBgADQEAQQgLAAIAEAAIAKgAgAA="},"packages/nodes-base/nodes/Set/v1/SetV1.node.ts":{"139":"b:aIYAkAigACDUEBgADQEAQQgbAAIAEAAIAKgGgAA=","146":"b:aIYAkAigACDUEBgADQEAQQgbAAIAEAAIAKgGgAA=","182":"b:aIYAkAigACDUEBgADQEAQQgbAAIAEAAIAKgGgAA=","193":"b:aIYAkAigACDUEBgADQEAQQgbAAIAEAAIAKgGgAA=","211":"b:aIYAkAigACDUEBgADQEAQQgbAAIAEAAIAKgGgAA="},"packages/nodes-base/nodes/Set/v2/SetV2.node.ts":{"302":"b:aIYAkAigACDUEBgAjQEAQQgfAAIAEAAIAKgkgAA=","309":"b:aIYAkAigACDUEBgAjQEAQQgfAAIAEAAIAKgkgAA="},"packages/nodes-base/nodes/Set/v2/helpers/utils.ts":{"28":"b:aIYAkAigACDUEBgAjQGAQQgfAAIAEAAIAKgkgAA=","31":"b:aIYAkAigACDUEBgAjQGAQQgfAAIAEAAIAKgkgAA=","34":"b:aIYAkAigACDUEBgAjQGAQQgfAAIAEAAIAKgkgAA=","37":"b:aIYAkAigACDUEBgAjQGAQQgfAAIAEAAIAKgkgAA=","43":"b:aIYAkAigACDUEBgAjQGAQQgfAAIAEAAIAKgkgAA=","46":"b:aIYAkAigACDUEBgAjQGAQQgfAAIAEAAIAKgkgAA=","49":"b:aIYAkAigACDUEBgAjQGAQQgfAAIAEAAIAKgkgAA=","56":"b:aIYAkAigACDUEBgAjQGAQQgfAAIAEAAIAKgkgAA=","89":"b:aIYAkAigACDUEBgAjQGAQQgfAAIAEAAIAKgkgAA=","90":"b:aIYAkAigACDUEBgAjQGAQQgfAAIAEAAIAKgkgAA=","104":"b:aIYAkAigACDUEBgAjQGAQQgfAAIAEAAIAKgkgAA=","105":"b:aIYAkAigACDUEBgAjQGAQQgfAAIAEAAIAKgkgAA=","130":"b:aIYAkAigACDUEBgAjQGAQQgfAAIAEAAIAKgkgAA=","161":"b:aIYAkAigACDUEBgAjQGAQQgfAAIAEAAIAKgkgAA=","222":"b:aIYAkAigACDUEBgAjQGAQQgfAAIAEAAIAKgkgAA=","236":"b:aIYAkAigACDUEBgAjQGAQQgfAAIAEAAIAKgkgAA=","238":"b:aIYAkAigACDUEBgAjQGAQQgfAAIAEAAIAKgkgAA=","245":"b:aIYAkAigACDUEBgAjQGAQQgfAAIAEAAIAKgkgAA=","265":"b:aIYAkAigACDUEBgAjQGAQQgfAAIAEAAIAKgkgAA="},"packages/nodes-base/nodes/Set/v2/manual.mode.ts":{"189":"b:aIYAkAigACDUEBgAjQEAQQgfAAIAEAAIAKgkgAA="},"packages/nodes-base/nodes/Set/v2/raw.mode.ts":{"36":"b:aIYAkAigACDUEBgADQGAQQgLAAIAEAAIAKgAgAA="},"packages/nodes-base/utils/utilities.ts":{"34":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","53":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","65":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","70":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","86":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","89":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","113":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","136":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","140":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","148":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","167":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","174":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","183":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","186":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","189":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","267":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","271":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","276":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","278":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","287":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","309":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","336":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","345":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","346":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","356":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","365":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","387":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","389":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","413":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","414":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","417":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","441":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","447":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI=","454":"b:6JecmAyhACDXFBwITSGARQxJCAYAEAAIAIgwAAI="},"packages/nodes-base/utils/workflowInputsResourceMapping/GenericFunctions.ts":{"27":[3,83,45,225,212,213,119,142],"29":[3,83,45,225,212,213,119,142],"74":[3,83,45,225,212,213,119,142],"81":[3,83,45,225,212,213,119,142],"121":[3,83,45,225,212,213,119,142],"126":[3,83,45,225,212,213,119,142],"147":[3,83,45,225,212,213,119,142],"155":[3,83,45,225,212,213,119,142],"157":[3,83,45,225,212,213,119,142],"160":[3,83,45,225,212,213,119,142],"168":[3,83,45,225,212,213,119,142],"183":[3,83,45,225,212,213,119,142]},"packages/workflow/src/common/get-child-nodes.ts":{"5":"b:CLccFAzFviE3ghhIYQkAQEQVAEQAAAAAAAAAgAA="},"packages/workflow/src/common/get-connected-nodes.ts":{"13":"b:ePccFAzFviF3GjhIYYmAQMQVAAQAAAAAAAAEoAA=","29":"b:ePccFAzFviF3GjhIYYmAQMQVAAQAAAAAAAAEoAA=","63":"b:ePccFAzFviF3GjhIYYmAQMQVAAQAAAAAAAAEoAA=","77":"b:ePccFAzFviF3GjhIYYmAQMQVAAQAAAAAAAAEoAA=","83":"b:ePccFAzFviF3GjhIYYmAQMQVAAQAAAAAAAAEoAA=","84":"b:ePccFAzFviF3GjhIYYmAQMQVAAQAAAAAAAAEoAA="},"packages/workflow/src/common/map-connections-by-destination.ts":{"5":"b:eLccEAzlviF3OjxIYSkAUMQVAAAAAAAAAAAAgAA="},"packages/workflow/src/common/resolve-variables.ts":{"23":"b:eLccEAjlviF3OjxIYSkAUMQVAAAAAAAAAAAAgAA=","51":"b:eLccEAjlviF3OjxIYSkAUMQVAAAAAAAAAAAAgAA="},"packages/workflow/src/dynamic-credentials-helpers.ts":{"9":"b:eJccFAjFviFHGjhI4QmAYMQ1AAAAAAAAAAAwgAo=","10":"b:eJccFAjFviFHGjhI4QmAYMQ1AAAAAAAAAAAwgAo=","13":"b:eJccFAjFviFHGjhI4QmAYMQ1AAAAAAAAAAAwgAo=","22":"b:eJccFAjFviFHGjhI4QmAYMQ1AAAAAAAAAAAwgAo=","23":"b:eJccFAjFviFHGjhI4QmAYMQ1AAAAAAAAAAAwgAo=","24":"b:eJccFAjFviFHGjhI4QmAYMQ1AAAAAAAAAAAwgAo=","33":"b:eJccFAjFviFHGjhI4QmAYMQ1AAAAAAAAAAAwgAo=","66":"b:eJccFAjFviFHGjhI4QmAYMQ1AAAAAAAAAAAwgAo=","87":"b:eJccFAjFviFHGjhI4QmAYMQ1AAAAAAAAAAAwgAo=","99":"b:eJccFAjFviFHGjhI4QmAYMQ1AAAAAAAAAAAwgAo="},"packages/workflow/src/errors/index.ts":{"21":"b:bPAwAhiAAqQHYDwEEAiAAAADMCEBAAAAACACoAM=","31":"b:bPAwAhiAAqQHYDwEEAiAAAADMCEBAAAAACACoAM=","37":"b:bPAwAhiAAqQHYDwEEAiAAAADMCEBAAAAACACoAM=","41":"b:bPAwAhiAAqQHYDwEEAiAAAADMCEBAAAAACACoAM=","43":"b:bPAwAhiAAqQHYDwEEAiAAAADMCEBAAAAACACoAM=","44":"b:bPAwAhiAAqQHYDwEEAiAAAADMCEBAAAAACACoAM=","47":"b:bPAwAhiAAqQHYDwEEAiAAAADMCEBAAAAACACoAM=","49":"b:bPAwAhiAAqQHYDwEEAiAAAADMCEBAAAAACACoAM=","50":"b:bPAwAhiAAqQHYDwEEAiAAAADMCEBAAAAACACoAM="},"packages/workflow/src/execution-context-establishment-hooks.ts":{"41":"b:eJccFAjFviFHGjhI4QkAQMQ1AAAAAAAAAAAAgAA="},"packages/workflow/src/execution-context.ts":{"12":"b:eAU8BAjBAABGGhAIYwAAiME1AAQAAAAAAAAAAAI=","290":"b:eAU8BAjBAABGGhAIYwAAiME1AAQAAAAAAAAAAAI=","425":"b:eAU8BAjBAABGGhAIYwAAiME1AAQAAAAAAAAAAAI=","447":"b:eAU8BAjBAABGGhAIYwAAiME1AAQAAAAAAAAAAAI=","460":"b:eAU8BAjBAABGGhAIYwAAiME1AAQAAAAAAAAAAAI=","465":"b:eAU8BAjBAABGGhAIYwAAiME1AAQAAAAAAAAAAAI="},"packages/workflow/src/execution-status.ts":{"16":"b:eJcgFAjFviFHGjhI4QkAQMQ3AAAAAAAAAAAAgAA=","29":"b:eJcgFAjFviFHGjhI4QkAQMQ3AAAAAAAAAAAAgAA="},"packages/workflow/src/expression.ts":{"24":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","27":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","30":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","34":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","48":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","101":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","102":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","126":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","140":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","172":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","174":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","182":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","186":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","197":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","199":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","206":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","209":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","226":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","232":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","242":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","252":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","284":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","291":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","334":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","342":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","347":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","351":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","370":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","385":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","399":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","404":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","408":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","565":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","574":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","615":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","707":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA=","725":"b:eLccGAzlviF3OjxIYSmAUcQVAEAAAAAAAIAGgAA="},"packages/workflow/src/global-state.ts":{"9":"b:eLccEAzlviF3OjxIYSkAUMQVAAAAAAAAAAAAgAA=","13":"b:eLccEAzlviF3OjxIYSkAUMQVAAAAAAAAAAAAgAA="},"packages/workflow/src/interfaces.ts":{"150":"b:eLeeFAr1vjEHejxI4SkAROQ1AQAAIAAAAAAA4AA=","2730":"b:eLeeFAr1vjEHejxI4SkAROQ1AQAAIAAAAAAA4AA=","2747":"b:eLeeFAr1vjEHejxI4SkAROQ1AQAAIAAAAAAA4AA="},"packages/workflow/src/node-grouping-validation.ts":{"38":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","65":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","73":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","74":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","78":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","93":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","99":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","102":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","110":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","119":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","124":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","223":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","241":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","260":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","264":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","279":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","291":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","346":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","347":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","380":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","397":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","414":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","422":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","425":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","431":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","482":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","487":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","501":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","518":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","521":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","543":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","544":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","554":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","581":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","595":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","601":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","611":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","619":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","624":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","645":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","649":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","650":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","653":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","680":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","686":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","731":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","741":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/workflow/src/node-helpers.ts":{"258":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","266":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","276":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","286":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","301":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","323":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","324":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","341":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","345":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","360":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","419":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","446":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","485":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","529":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","560":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","593":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","630":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","669":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","674":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","752":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1020":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1059":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1091":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1092":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1140":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1170":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1200":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1221":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1230":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1234":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1240":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1243":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1280":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1342":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1378":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1404":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1433":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1447":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1472":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1500":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1537":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1552":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1563":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1568":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1594":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1606":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1651":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1654":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1819":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1860":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1868":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1880":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1890":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1894":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1911":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1924":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1930":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1932":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1940":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1944":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","1968":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","2003":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","2010":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","2026":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","2031":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","2065":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","2098":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","2113":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","2145":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","2172":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","2188":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","2202":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","2216":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","2227":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","2242":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","2267":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","2276":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY=","2277":"b:+Pf+nGz/vzH3/39s+/mgefQ/AWUAOiEAAKAk4AY="},"packages/workflow/src/observable-object.ts":{"9":"b:eLccFEzlviF3uj1I4zkAcMUXAAAACAAAACAEgAA=","38":"b:eLccFEzlviF3uj1I4zkAcMUXAAAACAAAACAEgAA=","48":"b:eLccFEzlviF3uj1I4zkAcMUXAAAACAAAACAEgAA=","51":"b:eLccFEzlviF3uj1I4zkAcMUXAAAACAAAACAEgAA=","54":"b:eLccFEzlviF3uj1I4zkAcMUXAAAACAAAACAEgAA="},"packages/workflow/src/run-execution-data/run-execution-data.ts":{"29":"b:eAccGAjBAAFHGjgIYwEAQMY1AAAAAAAAAAAAAAA="},"packages/workflow/src/run-execution-data-factory.ts":{"57":"b:ePccFAjFviFHWjxI8amAUMQ1AEAAAAAAAAAAoAA=","70":"b:ePccFAjFviFHWjxI8amAUMQ1AEAAAAAAAAAAoAA=","89":"b:ePccFAjFviFHWjxI8amAUMQ1AEAAAAAAAAAAoAA=","113":"b:ePccFAjFviFHWjxI8amAUMQ1AEAAAAAAAAAAoAA=","130":"b:ePccFAjFviFHWjxI8amAUMQ1AEAAAAAAAAAAoAA="},"packages/workflow/src/type-validation.ts":{"15":"b:OKYcGQyBACAAEBgAwQGQ4QQnAAAAMgAAAIAkoAA=","24":"b:OKYcGQyBACAAEBgAwQGQ4QQnAAAAMgAAAIAkoAA=","38":"b:OKYcGQyBACAAEBgAwQGQ4QQnAAAAMgAAAIAkoAA=","48":"b:OKYcGQyBACAAEBgAwQGQ4QQnAAAAMgAAAIAkoAA=","72":"b:OKYcGQyBACAAEBgAwQGQ4QQnAAAAMgAAAIAkoAA=","114":"b:OKYcGQyBACAAEBgAwQGQ4QQnAAAAMgAAAIAkoAA=","124":"b:OKYcGQyBACAAEBgAwQGQ4QQnAAAAMgAAAIAkoAA=","146":"b:OKYcGQyBACAAEBgAwQGQ4QQnAAAAMgAAAIAkoAA=","162":"b:OKYcGQyBACAAEBgAwQGQ4QQnAAAAMgAAAIAkoAA=","206":"b:OKYcGQyBACAAEBgAwQGQ4QQnAAAAMgAAAIAkoAA=","233":"b:OKYcGQyBACAAEBgAwQGQ4QQnAAAAMgAAAIAkoAA=","286":"b:OKYcGQyBACAAEBgAwQGQ4QQnAAAAMgAAAIAkoAA=","298":"b:OKYcGQyBACAAEBgAwQGQ4QQnAAAAMgAAAIAkoAA=","319":"b:OKYcGQyBACAAEBgAwQGQ4QQnAAAAMgAAAIAkoAA=","347":"b:OKYcGQyBACAAEBgAwQGQ4QQnAAAAMgAAAIAkoAA=","451":"b:OKYcGQyBACAAEBgAwQGQ4QQnAAAAMgAAAIAkoAA=","452":"b:OKYcGQyBACAAEBgAwQGQ4QQnAAAAMgAAAIAkoAA="},"packages/workflow/src/utils.ts":{"17":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","28":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","36":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","57":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","96":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","101":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","102":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","109":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","127":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","129":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","156":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","199":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","205":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","215":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","240":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","247":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","249":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","260":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","278":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","282":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","284":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","291":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","304":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","308":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","325":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","342":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","345":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","352":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","390":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","408":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","415":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","419":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","428":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","440":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","448":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","456":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","475":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","494":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA=","497":"b:/v++nCz9viX3fnzo6TkgReQ/CEFAEAAAAIAGgAA="},"packages/workflow/src/versioned-node-type.ts":{"11":"b:6LeekCyhACD3NBwIDSEARQAJAARAAAAAAIAAAAA=","20":"b:6LeekCyhACD3NBwIDSEARQAJAARAAAAAAIAAAAA=","24":"b:6LeekCyhACD3NBwIDSEARQAJAARAAAAAAIAAAAA="},"packages/workflow/src/workflow-checksum.ts":{"46":"b:+L+ikCz9viH3PnxoaSkAQMALAAAAAAAAAAAAAAA=","50":"b:+L+ikCz9viH3PnxoaSkAQMALAAAAAAAAAAAAAAA=","74":"b:+L+ikCz9viH3PnxoaSkAQMALAAAAAAAAAAAAAAA=","99":"b:+L+ikCz9viH3PnxoaSkAQMALAAAAAAAAAAAAAAA="},"packages/workflow/src/workflow-expression.ts":{"22":"b:ePccHAzlviF3ej1I8amAUcQXAEQAAgAAAIAAoAA=","30":"b:ePccHAzlviF3ej1I8amAUcQXAEQAAgAAAIAAoAA=","74":"b:ePccHAzlviF3ej1I8amAUcQXAEQAAgAAAIAAoAA=","89":"b:ePccHAzlviF3ej1I8amAUcQXAEQAAgAAAIAAoAA=","94":"b:ePccHAzlviF3ej1I8amAUcQXAEQAAgAAAIAAoAA=","154":"b:ePccHAzlviF3ej1I8amAUcQXAEQAAgAAAIAAoAA=","189":"b:ePccHAzlviF3ej1I8amAUcQXAEQAAgAAAIAAoAA=","222":"b:ePccHAzlviF3ej1I8amAUcQXAEQAAgAAAIAAoAA=","269":"b:ePccHAzlviF3ej1I8amAUcQXAEQAAgAAAIAAoAA=","274":"b:ePccHAzlviF3ej1I8amAUcQXAEQAAgAAAIAAoAA=","278":"b:ePccHAzlviF3ej1I8amAUcQXAEQAAgAAAIAAoAA=","282":"b:ePccHAzlviF3ej1I8amAUcQXAEQAAgAAAIAAoAA="},"packages/workflow/src/workflow-structure-validation.ts":{"97":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","100":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","106":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","108":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","116":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","122":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA=","206":"b:+L+ikCz9viH3PnxsaSkAQEAKAAAAAAAAAAAAAAA="},"packages/workflow/src/workflow.ts":{"87":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","137":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","144":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","149":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","153":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","157":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","164":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","217":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","245":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","253":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","254":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","261":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","262":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","271":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","300":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","309":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","330":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","334":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","384":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","403":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","441":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","485":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","538":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","557":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","575":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","589":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","604":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","618":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","629":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","652":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","670":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","671":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","685":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","744":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","815":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","845":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","846":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","865":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ=","890":"b:ePc8HEznviF3uj9I46mAWcQ3CEQAGAAAQCAmoAQ="},"localhost-46669/assets/index-BoK1c_f3.js":{"3":[108,166,167,169,132,201,205,208,215,217]},"localhost-46669/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[108,166,167,169,132,201,205,208,215,217],"9":[108,166,167,169,132,201,205,208,215,217],"10":[108,166,167,169,132,201,205,208,215,217],"19":[108,166,167,169,132,201,205,208,215,217],"23":[108,166,167,169,132,201,205,208,215,217],"29":[108,166,167,169,132,201,205,208,215,217],"33":[108,166,167,169,132,201,205,208,215,217],"34":[108,166,167,169,132,201,205,208,215,217]},"localhost-46669/assets/verified-Pt0guxqN.js":{"8":[108,166,169,201]},"packages/@n8n/api-types/src/agent-builder-tool-node-types.ts":{"20":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/@n8n/api-types/src/agents/agent-integration.schema.ts":{"24":"b:/k//8/77Ad7k/3c7H9B83vz/////////////BwA=","38":"b:/k//8/77Ad7k/3c7H9B83vz/////////////BwA=","71":[86,124,110,38],"75":[86,124,110,38],"139":[86,124,110,38],"150":[86,124,110,38],"249":[110,38]},"packages/@n8n/api-types/src/agents/dto.ts":{"82":[1,2,83,86,124,163,81],"216":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","218":[1,2,83,86,124,163,81],"222":[1,2,83,86,124,163,81],"226":[1,2,83,86,124,163,81],"232":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","234":[1,2,83,86,124,163,81],"238":[1,2,83,86,124,163,81],"242":[1,2,83,86,124,163,81],"248":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","250":[1,2,83,86,124,163,81],"254":[1,2,83,86,124,163,81],"258":[1,2,83,86,124,163,81],"299":[1,2,83,86,124,163,81],"303":[1,2,83,86,124,163,81],"315":[1,2,83,163,81],"319":[1,2,83,163,81],"323":[1,2,83,163,81],"372":[86,124],"373":[1,2,83,163,81],"381":[1,2,83,163,81],"385":[1,2,83,163,81],"389":[1,2,83,163,81]},"packages/@n8n/api-types/src/dto/audit/audit-public.dto.ts":{"114":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","116":[86,124],"120":[86,124]},"packages/@n8n/api-types/src/dto/data-table/data-table-public.dto.ts":{"104":[86,124],"112":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","118":[86,124],"122":[86,124],"126":[86,124],"170":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","172":[86,124],"176":[86,124],"231":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","233":[86,124],"237":[86,124],"263":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","265":[86,124],"269":[86,124],"274":[86,124],"332":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","334":[86,124],"338":[86,124]},"packages/@n8n/api-types/src/dto/data-table/list-data-table-query.dto.ts":{"35":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","39":"b:AAABAwAwAIgAAEIjHAAAEgAAgAAEAAAABAAAAAA="},"packages/@n8n/api-types/src/dto/evaluations/llm-judge-providers.ts":{"120":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/@n8n/api-types/src/dto/folders/folder-public.dto.ts":{"119":[86,124],"127":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","133":[86,124],"137":[86,124],"141":[86,124]},"packages/@n8n/api-types/src/dto/ldap/ldap-configuration-public.dto.ts":{"45":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","84":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/@n8n/api-types/src/dto/ldap/ldap-sync-public.dto.ts":{"32":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","41":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","55":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/@n8n/api-types/src/dto/log-streaming/log-streaming-public.dto.ts":{"40":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","181":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","206":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","208":[86,124],"212":[86,124],"219":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","221":[86,124],"225":[86,124],"232":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","234":[86,124],"238":[86,124],"254":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/@n8n/api-types/src/dto/oidc/oidc-configuration-public.dto.ts":{"31":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","59":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/@n8n/api-types/src/dto/openapi-nullable.ts":{"6":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/@n8n/api-types/src/dto/otel/otel-settings-public.dto.ts":{"30":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","57":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/@n8n/api-types/src/dto/otel/otel-test-trace-public.dto.ts":{"39":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","49":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/@n8n/api-types/src/dto/promotions/promotion-connection.dto.ts":{"75":[86,124],"85":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","93":[86,124],"97":[86,124],"101":[86,124]},"packages/@n8n/api-types/src/dto/promotions/promotion-operations.dto.ts":{"31":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","127":[86,124]},"packages/@n8n/api-types/src/dto/promotions/promotion-provider.dto.ts":{"63":[86,124],"201":[86,124],"212":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","220":[86,124],"224":[86,124],"228":[86,124]},"packages/@n8n/api-types/src/dto/saml/saml-configuration-public.dto.ts":{"132":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","269":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/@n8n/api-types/src/dto/security-settings/security-policy.dto.ts":{"43":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","78":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/@n8n/api-types/src/dto/type-availability-policies/node-type-policy-public.dto.ts":{"24":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/@n8n/api-types/src/dto/type-availability-policies/policy-rule.schema.ts":{"33":[86,124,64,65,66],"54":"b:/k//8777Ad7n/3c7H5B83vz/////////////BwA="},"packages/@n8n/api-types/src/dto/workflows/workflow-public.openapi.ts":{"303":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/@n8n/api-types/src/schemas/instance-ai.schema.ts":{"58":"b:AAAA8B8AAAAAAEAAAAAAUAAAAIAEAAAAAAAAAAA=","78":"b:AAAA8B8AAAAAAEAAAAAAUAAAAIAEAAAAAAAAAAA=","108":"b:AAAA8B8AAAAAAEAAAAAAUAAAAIAEAAAAAAAAAAA=","120":"b:AAAA8B8AAAAAAEAAAAAAUAAAAIAEAAAAAAAAAAA=","125":[28,29,30,126,31,32,33,159,34,35,162,36],"134":"b:AAAA8B8AAAAAAEAAAAAAUAAAAIAEAAAAAAAAAAA=","152":[28,29,30,126,31,32,33,159,34,35,162,36],"157":[28,29,30,126,31,32,33,159,34,35,162,36],"173":[28,29,30,126,31,32,33,159,34,35,162,36],"194":[28,29,30,126,31,32,33,159,34,35,162,36],"338":"b:AAAA8B8AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","551":"b:AAAA8B8AAAAAAEAAAAAAUAAAAIAEAAAAAAAAAAA=","577":"b:AAAA8B8AAAAAAEAAAAAAUAAAAIAEAAAAAAAAAAA=","975":[28,29,30,126,31,32,33,159,34,35,162,36],"979":[28,29,30,126,31,32,33,159,34,35,162,36],"983":[28,29,30,126,31,32,33,159,34,35,162,36],"987":[28,29,30,126,31,32,33,159,34,35,162,36],"990":[28,29,30,126,31,32,33,159,34,35,162,36],"998":[28,29,30,126,31,32,33,159,34,35,162,36],"1037":"b:AAAA8B8AAAAAAEAAAAAAUAAAAIAFAAAAAAAAAAA=","1038":"b:AAAA8B8AAAAAAEAAAAAAUAAAAIAEAAAAAAAAAAA=","1226":"b:AAAA8B8AAAAAAEAAAAAAUAAAAIAEAAAAAAAAAAA=","1472":"b:/k//87/7Ad7k/3c7H5B83vz/////////////BwA=","1477":"b:/k//87/7Ad7k/3c7H5B83vz/////////////BwA=","1482":"b:AAAA8B8AAAAAAEAAAAAAUAAAAIAFAAAAAAAAAAA=","1490":"b:AAAA8B8AAAAAAEAAAAAAUAAAAIAFAAAAAAAAAAA=","1502":"b:AAAA8B8AAAAAAEAAAAAAUAAAAIAFAAAAAAAAAAA=","1913":"b:AAAA8B8AAAAAAEAAAAAAUAAAAIAEAAAAAAAAAAA=","2404":[28,29,30,126,31,32,33,159,34,35,162,36],"2416":[28,29,30,126,31,32,33,159,34,35,162,36],"2434":[28,29,30,126,31,32,33,159,34,35,162,36],"2541":"b:AAAA8B8AAAAAAEAAAAAAUAAAAIAEAAAAAAAAAAA=","2592":[28,29,30,126,31,32,33,159,34,35,162,36],"2729":"b:AAAA8B8AAAAAAEAAAAAA0AAAAIAEAAAAAAAAAAA=","3080":"b:AAAA8B8AAAAAAEAAAAAAUAAAAIAEAAAAAAAAAAA=","3083":"b:AAAA8B8AAAAAAEAAAAAAUAAAAIAEAAAAAAAAAAA=","3102":[28,29,30,126,31,32,33,159,34,35,162,36],"3199":"b:AAAA8B8AAAAAAEAAAAAAUAAAAIAEAAAAAAAAAAA=","3245":[28,29,30,126,31,32,33,159,34,35,162,36],"3262":[28,29,30,126,31,32,33,159,34,35,162,36],"3312":[28,29,30,126,31,32,33,159,34,35,162,36],"3318":[28,29,30,126,31,32,33,159,34,35,162,36],"3319":[28,29,30,126,31,32,33,159,34,35,162,36]},"packages/@n8n/api-types/src/schemas/object-guard.schema.ts":{"8":[86,90,124,47],"11":"b:/k//8777Ad7k/3c/H5B83vz/////////////BwA=","14":"b:/k//8777Ad7k/3c/H5B83vz/////////////BwA=","15":[86,90,124,47]},"packages/@n8n/api-types/src/schemas/password.schema.ts":{"13":"b:/k//8777Ad70//c7H5B83vz/////////////FwA=","18":"b:AAAAAACAAAAQAMAAAAAAEDCAAAAAgAAADAAAEAA=","21":"b:AAAAAACAAAAQAMAAAAAAEDCAAAAAgAAADAAAEAA="},"packages/@n8n/api-types/src/schemas/public-api-path-params.schema.ts":{"11":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","17":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","32":[86,124],"38":[86,124]},"packages/@n8n/api-types/src/schemas/read-only-public.schema.ts":{"7":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/@n8n/chat-hub/src/constants.ts":{"50":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/@n8n/codemirror-lang-sql/src/sql.ts":{"19":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","26":[86,124,202],"29":[86,124],"61":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","76":[86,124,202],"80":[86,124,202],"140":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","152":[86,124],"157":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","195":[86,124,202]},"packages/@n8n/codemirror-lang-sql/src/tokens.ts":{"33":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","80":[86,124,202],"84":[86,124],"88":[86,124,202],"100":[86,124],"113":[86,124,202],"122":[86,124,202],"136":[86,124],"141":[86,124,202],"160":[86,124],"164":[86,124,202],"171":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","221":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","240":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","241":[86,124,202]},"packages/@n8n/constants/src/browser.ts":{"11":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/@n8n/constants/src/nodes.ts":{"22":"b:8E/SkKzjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","26":"b:8E/SkKzjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA="},"packages/@n8n/errors/src/user.error.ts":{"18":"b:cAQAAADAAAAHWlAAoRAAMMUTMQAAAgAAAIQEAAA="},"packages/@n8n/inbound-auth/src/trusted-source-config.ts":{"44":[86,124],"113":[86,124],"155":[86,124],"172":[86,124],"211":[86,124],"222":[86,124],"238":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","239":[86,124]},"packages/@n8n/permissions/src/roles/custom-role-scopes.ee.ts":{"260":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","285":[86,124],"286":[86,124],"296":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","305":[86,124],"319":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","320":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","332":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","333":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/@n8n/permissions/src/scope-information.ts":{"4":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","5":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","6":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","12":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","13":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","14":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/@n8n/permissions/src/utilities/get-resource-permissions.ee.ts":{"14":"b:/k//8777Ad7k/3c7H5B83vz/j///////3///BwA=","15":"b:/k//8777Ad7k/3c7H5B83vz/j///////3///BwA=","18":"b:/k//8777Ad7k/3c7H5B83vz/j///////3///BwA="},"packages/@n8n/telemetry/src/define.ts":{"19":"b:/k//87/7Ad7k/3c7H5B83vz/////////////BwA=","26":"b:IAEA8B8AAADAAEQQDgAA0EACAIQLBAEoAAIkAAA="},"packages/@n8n/tournament/src/ExpressionBuilder.ts":{"25":"b:+PeemCyiATDkfX8I34HQ/Wx/KUdQM+9vyP4/pAk=","29":"b:+PeemCyiATDEfX0I34HQ/Wx/KUdQM+9vyP4/oAk=","33":"b:OPacCCCAACBgcHsA0wGQOQx7KUMQMOlBQOI2pAk=","37":"b:MPYcCAAAACAAGHkAwQGAOQQRCEAAEAEAQMAUoAk=","50":"b:+PeemCyiATDkfX8I34HQ/Wx/KUdQM+9vyP4/pAk=","54":"b:MPYcCAAAACAAEHkAwQGAOQQRCEAAEAkAQIAUoAk=","58":"b:MPYcCAAAACAAEHkAwQGAOQQRCEAAEAEAQIAUoAk=","62":"b:MPacCCCAACBgMHsA0wGQOQwbKEMAMOlBQOIWpAk=","71":"b:+PeemCyiATDkfX8I34HQ/Wx/KUdQM+9vyP4/pAk=","75":"b:MPYcCAAAACAgEHkAwQGAOQQbCEAAECEAQIAUoAk=","88":"b:+PeemCyiATDkfX8I34HQ/Wx/KUdQM+9vyP4/pAk=","103":"b:+PeemCyiATDkfX8I34HQ/Wx/KUdQM+9vyP4/pAk=","110":"b:MPYcCAAAACAAEHkAwQGQOQQRCUAAEA0BQIAWoAk=","136":"b:+PeemCyiATDkfX8I34HQ/Wx/KUdQM+9vyP4/pAk=","137":"b:MPYcCAAAACAgEHkAwQGAOQQbCEAAECEAQIAUoAk=","141":"b:MPYcCAAAACAgEHkAwQGAOQQbCEAAECEAQIAUoAk=","157":"b:+PeemCyiATDkfX8I34HQ/Wx/KUdQM+9vyP4/pAk=","158":"b:+PeemCyiATDkfX8I34HQ/Wx/KUdQM+9vyP4/pAk=","171":"b:+PeemCyiATDkfX8I34HQ/Wx/KUdQM+9vyP4/pAk=","191":"b:+PeemCyiATDkfX8I34HQ/Wx/KUdQM+9vyP4/pAk=","193":"b:+PeemCyiATDkfX8I34HQ/Wx/KUdQM+9vyP4/pAk=","194":"b:+PeemCyiATDkfX8I34HQ/Wx/KUdQM+9vyP4/pAk=","259":"b:MPYcCAAAACAAEHkAwQGQOQQRCUAAEA0BQIAWoAk="},"packages/@n8n/tournament/src/ExpressionSplitter.ts":{"19":"b:+LeemCyiATDkfX8IX4HQ3Wx/KUdQM+9vyP4/hAA=","23":"b:+LeemCyiATDkfX8IX4HQ3Wx/KUdQM+9vyP4/hAA=","27":"b:+LeemCyiATDkfX8IX4HQ3Wx/KUdQM+9vyP4/hAA=","101":"b:MLYcCAAAACAAEDgAQQGAAQQRAEAAAAAAAIAEgAA=","105":"b:MLYcCAAAACAAEDgAQQGAAQQRAEAAAAAAAIAEgAA=","107":"b:MLYcCAAAACAAEDgAQQGAAQQRAEAAAAAAAIAEgAA="},"packages/@n8n/tournament/src/FunctionEvaluator.ts":{"8":"b:+AeCkCyiARDkbXcIH4BQ3Gx/KQdQM+9vyP4/BAA=","18":"b:+AeCkCyiARDkbXcIH4BQ3Gx/KQdQM+9vyP4/BAA="},"packages/@n8n/tournament/src/Parser.ts":{"5":"b:+LeemCyiATDkfX8IX4HQ3Wx/KUdQM+9vyP4/hAA="},"packages/@n8n/tournament/src/VariablePolyfill.ts":{"12":"b:ELYcCAAAACAAEHkAQQGAEQQRAEAAAAAAAIAEgAk=","21":"b:+LeemCyiATDkfX8IX4HQ3Wx/KUdQM+9vyP4/hAk=","41":"b:+LeemCyiATDkfX8IX4HQ3Wx/KUdQM+9vyP4/hAk=","70":"b:ELacCCCAACBgMHsAUwGQGQQbIEMAMKhAAOIGhAk=","80":"b:ELacCCCAACBgMHsAUwGQGQQbIEMAMKhAAOIGhAk=","107":"b:ELacCCCAACBgMHsAUwGQGQQbIEMAMKhAAOIGhAk=","119":"b:+LeemCyiATDkfX8IX4HQ3Wx/KUdQM+9vyP4/hAk=","144":"b:+LeemCyiATDkfX8IX4HQ3Wx/KUdQM+9vyP4/hAk=","171":"b:+LeemCyiATDkfX8IX4HQ3Wx/KUdQM+9vyP4/hAk=","176":"b:ELYcCAAAACAAEHkAQQGAEQQRAEAAAAAAAIAEgAk=","181":"b:ELacCCCAACBgOHsAUwGQGQwbIEMAMOhBQOIGhAk=","204":"b:ELYcCAAAACAAEHkAQQGAEQQRAEAAAAAAAIAEgAk=","209":"b:ELacCCCAACBgMHsAUwGQGQQbIEMAMKhAAOIGhAk=","214":"b:ELacCCCAACBgMHsAUwGQGQQbIEMAMKhAAKIGhAk=","223":"b:ELacCCAAACBAEHkAQQGAEQQZAEAAAKBAAIAEgAk=","228":"b:ELYcCAAAACAAEHkAQQGAEQQRAEAAAAAAAIAEgAk=","233":"b:ELYcCAAAACAAEHkAQQGAEQQRAEAAAAAAAIAEgAk=","238":"b:ELYcCAAAACAAEHkAQQGAEQQRAEAAAAAAAIAEgAk=","243":"b:ELYcCAAAACAAEHkAQQGAEQQRAEAAAAAAAIAEgAk=","248":"b:ELYcCAAAACAAEHkAQQGAEQQRAEAAAAAAAIAEgAk=","255":"b:+LeemCyiATDkfX8IX4HQ3Wx/KUdQM+9vyP4/hAk=","260":"b:ELYcCAAAACAAEHkAQQGAEQQRAEAAAAAAAIAEgAk=","263":"b:+LeemCyiATDkfX8IX4HQ3Wx/KUdQM+9vyP4/hAk="},"packages/@n8n/tournament/src/index.ts":{"20":"b:/v//+777Af7k/387X5H83/z/////////////hwA=","21":"b:MLYcCAAAACAAEHgAQQGAEQQRAEAAAAAAAIAEgAA=","29":"b:/v//+777Af7k/387X5H83/z/////////////hwA=","33":"b:+LeemCyiATDkfX8IX4HQ3Wx/KUdQM+9vyP4/hAA=","37":"b:+LeemCyiATDkfX8IX4HQ3Wx/KUdQM+9vyP4/hAA="},"packages/@n8n/utils/src/create-event-queue.ts":{"7":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","17":"b:9ke+kIzjAATk+3UIH5BQ3Ox/C10APndl2P7/AwA=","44":"b:9ke+kIzjAATk+3UIH5BQ3Ox/C10APndl2P7/AwA="},"packages/@n8n/utils/src/event-bus.ts":{"43":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","50":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","60":[86,124,118,81],"61":[86,124,81],"68":"b:+E/ak6zzAdTk/3cIH5B03Px/vW/0v///3f//BwA=","75":"b:8E/KkKzzAdTk/3cIH5B03Px/v2/wP////f//BwA=","78":"b:8E/CkKzzAdTk/3cIH5BU3Px/vWfwP////P//BwA="},"packages/@n8n/utils/src/is-record.ts":{"1":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/@n8n/utils/src/lru-cache.ts":{"4":"b:/v//+777Af7k/387X5H83/z/////////////hwA=","13":"b:MLYcCAAAACAAEHgAQQGAEQQRAEAAAAAAAIAEgAA=","21":"b:MLYcCAAAACAAEHgAQQGAEQQRAEAAAAAAAIAEgAA=","31":"b:MLYcCAAAACAAEHgAQQGAEQQRAEAAAAAAAIAEgAA=","35":"b:MLYcCAAAACAAEHgAQQGAEQQRAEAAAAAAAIAEgAA="},"packages/@n8n/utils/src/placeholder.ts":{"13":[28,29,126,31,159,34,35],"22":[28,29,126,31,159,34,35],"32":"b:4EWSsKyiAFBkfXUIBxB0VPR/Ka9QO7d/iPY/AgA=","43":[144,86,124,28,29,126,31,159,34,35],"63":"b:4EWSsKyiAFBkfXUIBxB0VPR/Ka9QO7d/iPY/AgA=","84":[144,86,124,28,29,126,31,159,34,35],"87":[144,86,124,28,29,126,31,159,34,35],"91":[144,86,124,28,29,126,31,159,34,35],"95":[144,86,124,28,29,126,31,159,34,35],"107":[144,86,124,28,29,126,31,159,34,35],"111":[144,86,124,28,29,126,31,159,34,35]},"packages/@n8n/utils/src/redaction/pii-patterns.ts":{"44":"b:/k//8777Ad7k/387H5B8/vz/////////////JwA=","52":"b:/k//8777Ad7k/387H5B8/vz/////////////JwA=","58":[83,86,124,125,28,29,31,159,34,35,221],"81":[83,86,124,125,28,29,31,159,34,35,221],"89":[83,86,124,125,28,29,31,159,34,35,221],"105":[83,86,124,125,28,29,31,159,34,35,221],"128":[83,86,124,125,28,29,31,159,34,35,221],"141":[83,86,124,125,28,29,31,159,34,35,221],"146":[83,86,124,125,28,29,31,159,34,35,221],"159":"b:/k//8777Ad7k/387H5B8/vz/////////////JwA=","234":[83,86,124,125,28,29,31,159,34,35,221],"237":[83,86,124,125,28,29,31,159,34,35,221],"250":"b:/k//8777Ad7k/387H5B8/vz/////////////JwA=","253":[83,86,124,125,28,29,126,31,159,34,35,221]},"packages/@n8n/utils/src/result.ts":{"7":"b:QAAAAAAAABAAfEAAAgAQEAAzAAAAEBQoAOCIAAA=","12":"b:YECAACiCAABAWXAAAwAAEIA/AAQAErdtAHSeAgA=","23":[6,180,137,215]},"packages/@n8n/utils/src/search/re-rank-search-results.ts":{"1":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAAA=","6":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAAA=","9":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAAA=","23":"b:oECCAKAiAABkeXEAAxAQEOhpAAPwK5BACMYKAAA="},"packages/@n8n/utils/src/search/sublime-search.ts":{"25":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAAA=","41":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAAA=","182":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAAA=","205":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAAA=","222":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAAA=","231":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAAA=","285":"b:oECCAKAiAABkeXEAAxAQEOhpAAPwK5BACMYKAAA="},"packages/@n8n/utils/src/sort/sort-by-property.ts":{"1":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","6":"b:AACCAgC4AAAEQUMgHgBQEMxFBQIQyNtqmABgAQA="},"packages/__vite-browser-external":{"1":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/@n8n/chat/src/composables/useChat.ts":{"6":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/@n8n/chat/src/utils/event-bus.ts":{"11":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","14":[86,124],"22":[9,84,85,10,86,124,182,184,198,137],"33":[86,124],"36":[9,84,85,10,86,124,182,184,198,137],"40":[9,84,85,10,86,124,182,184,198,137]},"packages/frontend/@n8n/composables/src/registries/telemetryRegistry.ts":{"68":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","73":"b:/k//8777Ad7k/3c7H5B83vz/j///////3///BwA="},"packages/frontend/@n8n/composables/src/structuralComputed.ts":{"21":"b:+EeSkKzjAUDk/3cIH5B03Ox/OUfwP/9/+P+/BwA=","27":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA="},"packages/frontend/@n8n/composables/src/useClipboard.ts":{"8":"b:/k/+87zjAQjk/3cYH5BQ3Ox/Pd//P/9/3f//BwA=","9":[86,124],"25":[86,124,136],"48":[86,124,134,201,202,99,79],"59":[86,124,134,201,202,99],"77":"b:/k/+87zjAQjk/3cYH5BQ3Ox/Pd//P/9/3f//BwA=","90":"b:4EWAEiAgAABk+3cIHxBQkMQ7CBFWK7Rfif6vAwA="},"packages/frontend/@n8n/composables/src/useDebounce.ts":{"8":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","23":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","27":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","39":"b:4EWCA6iqABBkf3cIBxBUFPx/KQ/0u7d/CPY/AwA=","53":"b:oECCA6AqAABkf3MIBxAQEOxpCAP0q5BOCfYOAQA="},"packages/frontend/@n8n/composables/src/useDeviceSupport.ts":{"3":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","26":"b:AAYAAAAAAACAAFAAAwAAEEACAAAAAAARgCMgAwA=","28":"b:YAGCgQAIAJDguVcAHwBAEHAKAQUQxYk8Q9fnBwA="},"packages/frontend/@n8n/composables/src/useDocumentTitle.ts":{"28":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","37":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","42":[86,124,79],"47":"b:8E/CAKDjAQDk/3cIH5BQHOx/P0fwP/9/+P//BwA=","62":[86,124]},"packages/frontend/@n8n/composables/src/useExternalHooks.ts":{"37":[86,124],"48":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","57":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/@n8n/composables/src/useShortKeyPress.ts":{"6":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","22":[86,124],"33":"b:IAEAAAAAAAAAdEAAAgAAEEAgAQAAAAAAAMQAAAA="},"packages/frontend/@n8n/composables/src/useStorage.ts":{"4":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/@n8n/composables/src/useStyles.ts":{"3":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","4":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","11":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/@n8n/composables/src/useTelemetry.ts":{"32":[86,124],"33":[86,124],"34":[86,124],"35":[86,124],"36":[86,124],"37":[86,124],"38":[86,124],"39":[86,124],"40":[86,124],"50":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/@n8n/composables/src/useThrottleWithReactiveDelay.ts":{"7":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","12":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA="},"packages/frontend/@n8n/composables/src/useToast.ts":{"50":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","54":[86,124],"55":[86,124],"59":"b:cEeyAgD7AJzA+3YoD5AQGvQ3ADwD/rOlV+D3AwA=","75":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","78":"b:YACwAgAAAAQAAXQACgAAAEADAAABABAAAiCCAQA=","86":"b:YACwAgAAAAQAAXQACgAAAEADAAABABAAAiCCAQA=","92":"b:cEeyAgD7AJzA+3YoD5AQGvQ3ADwD/rOlV+D3AwA=","167":[86,121,93,43,174,44,47,63,194,71,72,98,81],"181":[86,121],"205":[86],"223":[86,20,21,23,25,160,58,193,205,97,82],"260":"b:cEcAEAjjAIBgm3YIH5AQiIQ3iEQAPjMlSOy3AwA=","261":[5,6,86,72,215,216]},"packages/frontend/@n8n/design-system/src/components/AskAssistantChat/AskAssistantChat.vue":{"25":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","62":[5,86,124],"77":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","78":[5,6,7,8,144,86,11,124],"86":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","87":[5,6,7,8,144,86,11,124],"99":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","133":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","188":[86,124],"189":[86,124],"198":[86,124],"205":[86,124],"224":[86,124],"231":[86,124],"239":[86,124],"272":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","275":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","287":[5,6,7,8,144,86,11,124],"303":"b:8E+CAKDjAUDk/3cIH5B0HOx/OUfwP/9/mP+/BwA=","307":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","311":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","315":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","321":[5,6,7,8,144,86,11,124],"327":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","332":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","345":[144,86,124],"360":"b:8E+CAKDjAUDk/3cIH5B0HOx/OUfwP/9/mP+/BwA=","364":[86,11,124],"378":[5,86,124],"382":[5,8,144,86,11,124],"387":[86,124],"391":[144,86,11,124],"395":[144,86,11,124],"399":[5,8,144,86,11,124],"403":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","405":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","422":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","439":[5,6,7,8,86,124,131],"443":[5,6,7,8,144,86,11,124],"456":[5,6,7,8,144,86,11,124],"464":[5,6,7,8,144,86,11,124,131],"469":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","500":[5,6,7,8,144,86,11,124],"507":[5,6,7,8,144,86,11,124],"534":[6,86,124],"535":[6,86,124],"538":[144,86,124],"541":[86,124],"554":[5,6,8,86,124],"562":[5,86,124],"563":[5,6,8,86,124],"597":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","602":[144,86,11,124],"612":[86,124],"613":[86,124],"614":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","630":[86,124],"632":[86,124],"635":[86,124],"699":[86,124],"701":[86,124],"704":[86,124]},"packages/frontend/@n8n/design-system/src/components/AskAssistantIcon/AssistantIcon.vue":{"4":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","22":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","30":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA="},"packages/frontend/@n8n/design-system/src/components/AskAssistantText/AssistantText.vue":{"9":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA="},"packages/frontend/@n8n/design-system/src/components/ConditionalRouterLink/CondtionalRouterLink.vue":{"56":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","61":"b:/k/j87z7AZjk33c7H5BQ3vx/j8f3//9/nf//BwA=","66":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA="},"packages/frontend/@n8n/design-system/src/components/N8nActionDropdown/ActionDropdown.vue":{"14":"b:/k/+k6zjAQDk/3cIH5BQ3Ox/D1/yP/9/2P//BwA=","34":"b:/k/+k6zjAQDk/3cIH5BQ3Ox/D1/yP/9/2P//BwA=","39":"b:/k/+k6zjAQDk/3cIH5BQ3Ox/D1/yP/9/2P//BwA=","44":"b:/k/+k6zjAQDk/3cIH5BQ3Ox/D1/yP/9/2P//BwA=","52":"b:/k/+k6zjAQDk/3cIH5BQ3Ox/D1/yP/9/2P//BwA=","66":"b:/k/+k6zjAQDk/3cIH5BQ3Ox/D1/yP/9/2P//BwA=","76":[86,156,124,24,161],"77":[86,156,124,24,161,137],"78":[86,124],"83":[86,124],"84":[86,124],"87":"b:/k/+k6zjAQDk/3cIH5BQ3Ox/D1/yP/9/2P//BwA=","95":"b:/k/+k6zjAQDk/3cIH5BQ3Ox/D1/yP/9/2P//BwA=","121":"b:/k/+k6zjAQDk/3cIH5BQ3Ox/D1/yP/9/2P//BwA=","135":[86,156,124,24,161,137],"143":[86,156,124,24,161,137],"145":[86,156,124,24,161,137],"150":[86,156,124,24,161,137],"161":[86,124],"164":[86,124],"175":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nActionToggle/ActionToggle.vue":{"14":"b:4EWyA6w6AFRk/XcpHxB0FvR/CS9U+7f/jf4/AAA=","35":"b:4EWyA6w6AFRk/XcpHxB0FvR/CS9U+7f/jf4/AAA=","36":"b:4EWyA6w6AFRk/XcpHxB0FvR/CS9U+7f/jf4/AAA=","44":[86,157,25,43,174,44,191,60,62,194,141,81],"45":[86,157,25,43,174,44,191,60,62,194,141,81],"49":[86],"51":[86],"59":[86],"74":"b:4EWyA6w6AFRk/XcpHxB0FvR/CS9U+7f/jf4/AAA=","81":[86,157,25,43,174,44,191,60,62,194,141,81],"99":"b:4EWyA6w6AFRk/XcpHxB0FvR/CS9U+7f/jf4/AAA=","112":[86,157,25,43,174,44,191,60,62,194,141,81],"117":[86]},"packages/frontend/@n8n/design-system/src/components/N8nBlockUi/BlockUi.vue":{"12":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","13":"b:6EeCAKiiAABkXXEIBxBQFOR/KAdQO7d/iPY/AgA="},"packages/frontend/@n8n/design-system/src/components/N8nButton/Button.vue":{"9":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","25":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","31":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","38":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","44":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","49":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","54":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","56":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","82":"b:9E/+M677ANzk/3c5F5B0yPx/if/7/r//3f//BwA=","85":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","104":"b:/k//87z7Adzk33c7H5B83vz/v///////////BwA=","106":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA="},"packages/frontend/@n8n/design-system/src/components/N8nButtonList/ButtonList.vue":{"11":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA="},"packages/frontend/@n8n/design-system/src/components/N8nChatInput/ChatInput.vue":{"65":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","104":[86,124],"116":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","132":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","137":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","151":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","152":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","164":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","168":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","177":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","179":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","188":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","190":"b:IAk8sAwAAAAAAEAQAAAA0AAAAZgDAAAAAAAAAAA=","201":"b:IAk8sAwAAAAAAEAQAAAA0AAAAZgDAAAAAAAAAAA=","208":"b:IAk8sAwAAAAAAEAQAAAA0AAAAZgDAAAAAAAAAAA=","212":[5,8,144,86,11,124],"218":"b:IAk8MAwAAAAAAEAQAAAA0AAAAZgDAAAAAAAAAAA=","225":[86,11,124],"232":[5,8,144,86,11,124,31],"277":"b:5Ak88B4AAAAAAEAQAAAA0AgAAZgHAAAAAAAAAAA=","282":"b:ZAk8MAwAAAAAAEAQAAAA0AAAAZgDAAAAAAAAAAA=","287":[144,86,124],"292":[144,86,124],"297":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","302":"b:AAAAsAwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","309":"b:7kn/87y6AYjk/3c6H5AQ0Px/v5/3779/S//+BwA=","317":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","319":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","330":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","334":"b:/k//87z7Adzk33c7H5B83vz/v///////////BwA=","351":[86,124],"356":"b:IAE8sAwAAAAAAEAQAAAA0AAAAZgDAAAAAAAAAAA=","374":"b:IAE8sAwAAAAAAEAQAAAA0AAAAZgDAAAAAAAAAAA=","390":[86,20,124],"399":[86,124],"402":"b:IAk8MAwAAAAAAEAQAAAA0AAAAZgDAAAAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nCommandBar/CommandBar.vue":{"56":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","65":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","86":[86,124,216],"87":[86,124,216],"89":[86,124],"91":[86,124,216],"94":[86,124,216],"97":[86,124,216],"99":[86,124,216],"100":[86,124],"101":[86,124],"102":[86,124,216],"103":[86,124],"109":[86,124],"110":[86,124],"123":[86,124],"131":[86,124],"137":[86,124],"142":[86,124],"150":[86,124],"205":[86,124],"212":[86,124,216],"217":[86,124,216],"225":"b:YAmCgQAYAJDg/VcAHwBUEHAqAQUyxYs8A9fnBwA=","232":[86,124,216],"239":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","244":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","246":[86,124,216],"252":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","256":[86,124],"259":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","270":[86,124,216],"280":[86,124],"281":[86,124],"288":[86,124],"309":[86,124,216],"323":[86,124,216],"331":[86,124],"332":[86,124],"346":[86,124,216],"357":[86,124],"379":[86,124],"380":[86,124],"381":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nDialog/Dialog.vue":{"104":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","106":"b:AACCAAAgABAAQEQIAAAAEDAAACgAAAAAAAAAAAA=","108":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","117":"b:/k//87z7Ad7k33c7H5B83vz/j///////n///BwA=","130":[86,124],"131":[7,86,155,23,124,78,82],"132":[86,124,33,63,216],"133":"b:AACCAAIgAJAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","134":"b:gACCAIIgAJAAYHQIAAAAEDAAACgIAIAAAAAAAQA=","136":[86,163,63],"137":[86,163,63]},"packages/frontend/@n8n/design-system/src/components/N8nDialog/DialogContent.vue":{"63":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","85":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","88":"b:gACCAIKgAJAAYHQIAAAAEDAAACgIAIAAAAAAAQA=","89":"b:gACCAIKgAJAAYHQIAAAAEDAAACgIAIAAAAAAAQA=","99":[7,86,155,23,124,78,82],"105":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","114":[86,124],"116":[86,124,33,47,63,216],"117":"b:AACCAAKgAJAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","118":"b:gACCAIKgAJAAYHQIAAAAEDAAACgIAIAAAAAAAQA=","121":[86,33,216],"126":[86]},"packages/frontend/@n8n/design-system/src/components/N8nDialog/DialogOverlay.vue":{"19":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA="},"packages/frontend/@n8n/design-system/src/components/N8nDropdownMenu/DropdownMenu.typeguards.ts":{"6":"b:/k//8777AVTk/3c5H5B03vx/D///////3f//BwA=","8":"b:/k//8777AVTk/3c5H5B03vx/D///////3f//BwA="},"packages/frontend/@n8n/design-system/src/components/N8nDropdownMenu/DropdownMenu.vue":{"30":"b:/k//8777AVTk/3c5H5B03vx/D///////3f//BwA=","61":"b:YAEIgACIAAAgoEAgBgBAAAACABwARAk4GApGBAA=","66":"b:YAEIgACIAAAgoEAgBgBAAAACABwARAk4GApGBAA=","77":"b:YAEIgACIAAAgoEAgBgBAAAACABwARAk4GApGBAA=","87":"b:/k//8777AVTk/3c5H5B03vx/D///////3f//BwA=","92":"b:/k//8777AVTk/3c5H5B03vx/D///////3f//BwA=","93":"b:/k//8777AVTk/3c5H5B03vx/D///////3f//BwA=","99":"b:/k//8777AVTk/3c5H5B03vx/D///////3f//BwA=","107":"b:/k//8777AVTk/3c5H5B03vx/D///////3f//BwA=","128":[86,31],"134":[86,161],"144":[86,31],"156":[86,31],"162":[86],"169":[86,155,19,156,161],"181":[86,31],"185":[86,31],"191":"b:4AGIAwCYAFAgoEIgBgBAAAAiAD4CZAm4HApGBAA=","198":"b:/k//8777AVTk/3c5H5B03vx/D///////3f//BwA=","203":[86,43,69],"212":"b:5AGIAwCYAFAgoEIgBgBAAAAiAD4CZAm4HApGBAA=","217":"b:5AGIAwCYAFAgoEIgBgBAAAAiAD4CZAm4HApGBAA=","226":"b:YAEAAAAAAAAAIEAABgAAAAACAAQABAk4AAIGBAA=","236":[86],"245":"b:5AGIAwCYAFAgoEIgBgBAAAAiAD4CZAm4HApGBAA=","257":"b:5AGIAwCYAFAgoEIgBgBAAAAiAD4CZAm4HApGBAA=","267":[86],"271":[86],"276":"b:5EeaMyy4AFBk+Xc5HxBQwvR7CL9X/73/nP7vBwA=","283":"b:5EGIAyC4AFBkuXMoBxBQBMQ7CD9Cbj3+HO5vBgA=","290":"b:5EGIAyC4AFBkuXMoBxBQBMQ7CD4CZj3+HO5PBgA=","293":[86],"299":[86],"304":"b:4AGIAwCYAFAgoEIgBgBAAAAiAD4CZAm4HApGBAA=","310":[86],"314":"b:4AGIAwCYAFAgoEIgBgBAAAAiAD4CZAm4HApGBAA=","318":[86,31],"326":[86,31],"351":"b:/k//8777AVTk/3c5H5B03vx/D///////3f//BwA=","352":"b:/k//8777AVTk/3c5H5B03vx/D///////3f//BwA=","366":"b:/k//8777AVTk/3c5H5B03vx/D///////3f//BwA=","377":[86,31],"380":[86],"400":"b:oEeSMyw4AFBk+Xc5HxBQwvR7CLtX+7T/jP6vAwA=","409":"b:5AGIgwCYAFAgoEIgBgBAAAAiAD4CZAm4HApGBAA=","417":[86],"418":[86],"425":[86],"432":[86],"439":"b:/k//8777AVTk/3c5H5B03vx/D///////3f//BwA=","443":"b:/k//87z7AVTk33c5H5B03vx/D///////3f//BwA=","451":"b:/k//8777AVTk/3c5H5B03vx/D///////3f//BwA=","462":[86],"470":"b:/k//8777AVTk/3c5H5B03vx/D///////3f//BwA=","489":"b:5AGIgwCYAFAggEIgBgBAAAAiAD4CZAm4HApGBAA=","501":[86],"503":[86,155,19,156],"506":[86],"509":[86],"511":[86,155,19,156,31,161],"529":[86],"532":[86,161],"534":[86],"537":[86,155,19,156,31],"540":[86,155,19,156,31,161],"543":[86,155,19,156,31,161],"563":[86],"566":[86],"568":[86],"571":[86,156,24,161,137],"574":[86,156,24,161,93,43,174,137],"577":"b:BAAAAwAYAFAAAEIAAAAAAAAiADACQACABAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nFormInput/validators.ts":{"7":[86,16,151,21,124,175,45,59,192,63],"23":[86,124],"36":[86,124,192],"49":[86,124],"67":[86,151,124,63],"79":[86,124],"97":[86,124,59,192],"109":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","139":[86,16,151,21,124,175,45,59,192,63]},"packages/frontend/@n8n/design-system/src/components/N8nHeading/Heading.vue":{"27":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","34":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","50":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","52":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","56":"b:/k//87z7Ad7k33c7H5B83vz/////////////BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/Icon.vue":{"25":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","32":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","42":"b:/k//8777Adzk/3c7H5B8zvz/v///////////BwA=","54":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","66":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","83":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","91":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","93":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","95":"b:+EeSkKzjABDk/3cIH5BQ3Px/OUfwP/9/+P6/BwA=","107":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","109":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","129":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/arrow-from-bracket-up--outline-16.svg":{"9":"b:/k/j8777ARjk/3c7H5BQ3vx/j8f3//9/nf//BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/arrow-left--outline-16.svg":{"9":"b:4EXSAKiiANxkfXUIBxB8FOT/Cif4M7f/DvY/AgA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/arrow-right--outline-16.svg":{"9":"b:4EWCML6iAABkfXEYBxBQ1Ox/Cof3O7d/CPY/AwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/arrow-right-from-line--outline-16.svg":{"9":"b:4EWCAKAiAABkfXEIBxBQFOR+CAdQI7dfCPYeAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/arrow-right-to-line--outline-16.svg":{"9":"b:4EWCAKAiAABkbXEIBxBQFOR+CAdQI4ZfCGYeAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/arrow-square-out--outline-16.svg":{"9":"b:9E/SkKzjAdTk/3cJH5B03Oz/LW/wP///2v//BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/arrow-up--outline-16.svg":{"9":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/arrows-cw--outline-16.svg":{"9":"b:4EW+ACiiAEhgfXEIBwA0FGR/Kj9QO6RviPY/AAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/broom--outline-16.svg":{"9":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/chart-bars--outline-16.svg":{"9":"b:/k/j8777Adzk/3c5F5B83vz/j+f/////n///BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/check--outline-16.svg":{"9":"b:/k7/8777Adzk/3c7H5B83vT/v///////////BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/check--solid-16.svg":{"9":"b:cEcAEAjDAABAG3AIA5AQ2IQ3CAQAPjMlQOC3AwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/check-circle--outline-16.svg":{"9":"b:gESCAIqiABAAcXQIAgAQELQ3CiwAOoIgAKA3AgA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/checks--outline-16.svg":{"9":"b:oECCAKgiAABgfXEIAxAQUORpCAPwK4BOCMYKAQA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/chevron-down--outline-16.svg":{"9":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/chevron-right--outline-16.svg":{"9":"b:5EWC8646ABBgfXM5HxBQ1uR/Kydee7d/KP4/AAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/chevron-up--outline-16.svg":{"9":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/DWfwP/9/2P//BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/chevrons-down-up--outline-16.svg":{"9":"b:AEYAAAiCAAAAGVAAAgAQEIQzKAQAOgIhAOQ3AgA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/corners--outline-16.svg":{"9":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/cube--outline-16.svg":{"9":"b:/k7/8777Adzk/3c7H5B83vT/v///////////BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/dots-grip--outline-16.svg":{"9":"b:IEAAAAggAAAgMEAAAgAQEAQTCAIAMgQhgKAHAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/dots-horizontal--outline-16.svg":{"9":"b:/k/Ck6zjAQDk/3cIH5BQ3Ox/D0fwP/9/2P//BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/dots-horizontal--solid-16.svg":{"9":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/2P+/BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/dots-vertical--outline-12.svg":{"9":"b:4EWSAKwiAFBkfXUIBxB0FPR/CS9QO7d/iPY/AAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/flask--outline-16.svg":{"9":"b:/kWDkKrjAQDk/3cIH5BQ3Ox/CUfwP79/uP6/BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/folder-open--outline-16.svg":{"9":"b:oECCAKAiAABgfXEIAxAQEORpCAPwK4BOCMYKAQA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/grid--outline-16.svg":{"9":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/home--outline-16.svg":{"9":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/info-circle--outline-16.svg":{"9":"b:4ETmg4i6AFiAeXYpHgA0ErR3CDxE+oYkCf4/AwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/lightbulb--outline-16.svg":{"9":"b:4EWCAKiiAABkfXEIBxBQFOx/KAdQO7d/iPY/AgA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/lightning--solid-16.svg":{"9":"b:/EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/lines-horizontal-3--outline-16.svg":{"9":"b:4EWCAKiiAABkfXEIBxBQFOR/CAdQM7d/CPY/AgA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/list-bullets--outline-16.svg":{"9":"b:BgAA8DwAAAAAIHAQAAAQ0AAaAIIHIgBAgIABAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/lock-locked--outline-16.svg":{"9":"b:YEBhAAiiANwEOUAKCwA8EIC3ACQIkiOsBvQqAwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/magic-wand--outline-16.svg":{"9":"b:EEaCAKDjAUDk/3cIH5B0HOR/OkfwP/9/mP+/BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/magnifying-glass--outline-16.svg":{"9":"b:/k//8777AZjk/3c7H5BQ3vx/r9/3//9/nf//BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/magnifying-glass-minus--outline-16.svg":{"9":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/magnifying-glass-plus--outline-16.svg":{"9":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/n8n-assistant--outline-16.svg":{"9":"b:Hkbj8777Adzk/3c5F5B83vT/iuf/////n///BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/pencil--outline-16.svg":{"9":"b:4EW+AaiiAABk/XUIBxBQFOx/CT/yP59/GP5/BAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/person--outline-16.svg":{"9":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/play--solid-16.svg":{"9":"b:8EeCkKjjAQDk/3cIH5BQ3Ox/CUfwP/9/2P6/BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/plus--outline-16.svg":{"9":"b:/k//8777AZjk/3c7H5BQ3vx/j//3//9/nf//BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/power--solid-16.svg":{"9":"b:8EeCkKjjAQDk/3cIH5BQ3Ox/CUfwP/9/mP6/BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/question-circle--outline-16.svg":{"9":"b:/k/z8777Adzk/3c7H5B03vx/r//3////nf//BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/satellite-dish--outline-16.svg":{"9":"b:oECCAKAiAABgfXEIAxAQEORpCAPwK4BOCMYKAQA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/sidebar-left--outline-16.svg":{"9":"b:/k//8777AZjk/3c7H5BQ3vx/j9/3//9/nf//BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/sidebar-right--outline-16.svg":{"9":"b:8E/C8LzjAUDk/3cYH5B03Ox/Dcf3P/9/mP//BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/square--outline-16.svg":{"9":"b:cEcAEAjjAABAG3AIE5AQmIQ3CEQAPjMlQOC3AwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/sticky-note--outline-16.svg":{"9":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/thumbtack--outline-16.svg":{"9":"b:AEAAAAiiAAAAGUAAAgAQEIQ3KAQAOgIgAOQ3AgA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/trash--outline-16.svg":{"9":"b:9EeaEQjjAFjg+3UIA5A03PQ3CD4SPrd9kOL/AwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/trash--solid-16.svg":{"9":"b:8EeCkKjjAQDk/3cIH5BQ3Ox/CUfwP/9/mP+/BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/wrench--outline-16.svg":{"9":"b:/k/j8777AZjk/3c7H5BY3vx/j8f3//9/nf//BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/x--outline-16.svg":{"9":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/x-circle--outline-16.svg":{"9":"b:oECCAKIiAABkfXEIBxAQEOxpCAPwK5BOCNYOAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/iconColor.ts":{"25":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/icons.ts":{"868":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","872":"b:+EeSkKzjABDk/3cIH5BQ3Px/OUfwP/9/+P6/BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/chat-trigger.svg":{"11":"b:oEaCAKAiAABgfTEIAxAQAOxrCAPwK8BPSMYKAQA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/code.svg":{"11":"b:cAQAAADAAABEAwQABRAAAMATAAEABhAYIAqGAwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/edit-fields.svg":{"11":"b:aAYAkAigAADAMBAAD4AQyAgfMAIAMmwv4Lo/BAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/form-trigger.svg":{"11":"b:oECCAKAiAABgfTEIAxAQAORpCEPwK4BOCMYKAQA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/if.svg":{"11":"b:AAAAgAAAAACAAAAAEAAAAAATAQAAAgAAAAgHBAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/information-extractor.svg":{"11":[17,23,169,195,133,77,80]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/manual-trigger.svg":{"11":"b:8EWCkKzjAADgfzEID5BQzOx/OAfwP7t+ON6/AwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/no-operation.svg":{"11":"b:AACCAAgAAAAEKAEAEgAQACBRAABAIiEMCEIABAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/read-write-files-from-disk.svg":{"11":[169,170]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/schedule-trigger.svg":{"11":"b:oECCAKAiAABk/TEIBxAQAORrCQPwK4ROiOYKBQA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/sub-workflow-trigger.svg":{"11":"b:qECCAKAiAABgfTEIAxAQAORpCAPwK4BOCMYKAQA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/switch.svg":{"11":[169,179,96,201,116,210,140,218]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/text-classifier.svg":{"11":[169,77]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/webhook.svg":{"11":"b:oECCAKCiAABgfTEIExAQCORpKAPwO4BOCOYKAQA="},"packages/frontend/@n8n/design-system/src/components/N8nIconButton/IconButton.vue":{"6":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","7":"b:/k//87z7Adzk33c7H5B83vz/v///////////BwA="},"packages/frontend/@n8n/design-system/src/components/N8nIconPicker/iconCategories.ts":{"118":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","129":[86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nInfoTip/InfoTip.vue":{"14":"b:4ESCAIi6AFAAeXYpHgA0ErQ3CCwEeoIgCfw3AgA=","57":"b:4ESCAIi6AFAAeXYpHgA0ErQ3CCwEeoIgCfw3AgA=","63":"b:4ESCAIi6AFAAeXYpHgA0ErQ3CCwEeoIgCfw3AgA=","87":[86]},"packages/frontend/@n8n/design-system/src/components/N8nInlineTextEdit/InlineTextEdit.vue":{"16":"b:9k/Sk6zrAVDk/3coH5B03Px/L2/wf/9/mP//BwA=","35":"b:9k/Sk6zrAVDk/3coH5B03Px/L2/wf/9/mP//BwA=","38":"b:9k/Sk6zrAVDk/3coH5B03Px/L2/wf/9/mP//BwA=","44":"b:9k/Sk6zrAVDk/3coH5B03Px/L2/wf/9/mP//BwA=","47":"b:9k/Sk6zrAVDk/3coH5B03Px/L2/wf/9/mP//BwA=","57":"b:9k/Sk6zrAVDk/3coH5B03Px/L2/wf/9/mP//BwA=","68":"b:YAGCAQAAABCAIEYIBgAEEDACAAQARAk4AABGBAA=","74":"b:YAEAAAAgAAAAoEIIBgAAEAACAAQABAk4AABGBAA=","81":"b:YAGCAQAAABCAIEYIBgAEEDACAAQARAk4AABGBAA=","92":"b:YAGCAQAAABCAIEYIBgAEEDACAAQARAk4AABGBAA=","96":"b:YAGCAQAgABCAoEYIBgAEEDACAAQARAk4AABGBAA=","103":"b:9k/Sk6zrAVDk/3coH5B03Px/L2/wf/9/mP//BwA=","122":"b:9k/Sk6zrAVDk33coH5B03Px/L2/wf/9/mP//BwA=","127":"b:9k/Sk6zrAVDk33coH5B03Px/L2/wf/9/mP//BwA=","145":"b:YAGCAQAAABCAIEYIBgAEADACAAQARAk4AABGBAA=","146":[86]},"packages/frontend/@n8n/design-system/src/components/N8nInput/Input.vue":{"10":"b:6EezA666ANzk/XcpHxB0FvT/qT9c+7f/j///BgA=","41":"b:6EezA666ANzk/XcpHxB0FvT/qT9U+7f/j///BgA=","50":"b:6EezA666ANzk/XcpHxB0FvT/qT9c+7f/j///BgA=","60":"b:6EezA666ANzk/XcpHxB0FvT/qT9c+7f/j///BgA=","79":"b:6EezA666ANzk/XcpHxB0FvT/qT9c+7f/j///BgA=","82":"b:6EezA666ANzk/XcpHxB0FvT/qT9c+7f/j///BgA=","84":"b:6EezA666ANzk/XcpHxB0FvT/qT9c+7f/j///BgA=","98":"b:6EezA666ANzk/XcpHxB0FvT/qT9c+7f/j///BgA=","112":"b:AEGCAwIqAJQAYXYIAAAUADRgiB4AooDABwBHBAA=","119":"b:AEGCAwIiAJQg5XUIAAAUADRgiB4AsoDAhwJnBAA=","125":"b:AEGDAwIqAJQg5XcIAAAUADRgiB4AsoDAhwJnBAA=","131":"b:AAGAAQAIAIAAIEIAAAAUAAAAAAAAgAAAAwJDAAA=","136":"b:AEAAAAAKAAAAZEIAAAAQAARgCAYAAABABAIAAAA=","141":[86],"147":"b:6EezA666ANzk/XcpHxB0FvT/qT9c+7f/j///BgA=","151":"b:6EezA666ANzk/XcpHxB0FvT/qT9c+7f/j///BgA=","157":"b:qEeyAyIwANDk/XcIHxBQAPR7iDtU+7bfhf5vBgA=","158":"b:6EezA666ANzk/XcpHxB0FvT/qT9c+7f/j///BgA=","163":"b:6EezA666ANzk/XcpHxB0FvT/qT9c+7f/j///BgA=","164":"b:IEGCA4qqANQAYXYIEgA0BHT/qD8QsobhhzBnBAA=","173":"b:6EezA666ANzk/XcpHxB0FvT/qT9c+7f/j///BgA=","183":"b:AEGDAwAqAJAAZXYIAAAUADRgiB4AooBAhQJnBAA=","184":[86,209,78],"185":[86,24,25,172,175,45,69,208,210,213,79,80],"188":"b:6EezA666ANzk/XcpHxB0FvT/qT9c+7f/j///BgA="},"packages/frontend/@n8n/design-system/src/components/N8nInputLabel/InputLabel.vue":{"25":"b:4EWzA66iANxk/XcIBxB0FPR/qT9Qu7f/jfY/AgA=","31":[86,124],"34":[86,124],"38":"b:4EWzA66iANxk/XcIBxB0FPR/qT9Qu7f/jfY/AgA=","72":"b:4EWTA66iANRk/TcIBxB0FPR/qT9QO7f/jfY/AgA=","76":"b:gACCA4AgAAAgwDUAAAAAEDAAADgAEIAAAQAAAAA=","85":[124]},"packages/frontend/@n8n/design-system/src/components/N8nLink/Link.vue":{"31":"b:/k/Dk677Adzk/3cpH5B83vz/r2/8f///n///BwA=","32":"b:/k/Dk6z7Adzk33cpH5B83vz/r2/8f///n///BwA=","34":"b:/k/Dk6z7Adzk33cpH5B83vz/r2/8f///n///BwA="},"packages/frontend/@n8n/design-system/src/components/N8nLoading/Loading.vue":{"38":"b:oECD87w6AJxk/3c7HxBQ0vxpiKP365DODd4OAQA=","44":[86,124],"47":"b:oECD87w6AJxk/3c7HxBQ0vxpiKP365DODd4OAQA=","49":[86,157,124,24,25,82],"60":"b:oECDg6A6AJxk/3crHxBQEvxpiCP065DODd4OAQA="},"packages/frontend/@n8n/design-system/src/components/N8nMenuItem/MenuItem.vue":{"16":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA=","38":"b:gAD+AoCwANwAYHQLCAAsEDCAADgIAICABgIAAAA=","45":"b:gAD+AoCwANwAYHQLCAAsEDCAADgIAICABgIAAAA=","49":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA=","65":"b:AAAAAwAQAAAAAEAJDAAAEDAAADACAAAAAAoAAAA=","72":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA=","84":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA=","93":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA=","97":[86,124],"109":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA=","112":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA=","117":[86,124],"119":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA=","138":"b:/k//87z7Adzk33c7H5B83vz/j///////n///BwA=","147":[86,88,124,45,201],"178":"b:gAD+AoCwANwAYHQLCAAsEDCAADgIAICABgIAAAA=","188":"b:AABAAACAANwAAEAAAAAsEACAACAIAACABgAAAAA=","192":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nNavigationDropdown/NavigationDropdown.vue":{"41":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","47":[86,124],"55":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","57":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","58":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","59":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","67":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","79":[86,124],"83":"b:/E/iM677ABDk/3c5H5BQ3vx/D8f3//9/mf//BwA=","88":[86,124,175,45,98],"93":[86,124,175,45],"102":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","112":[86,124,175,45,98],"116":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","125":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","127":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","129":"b:/k/j87z7AZjk33c7H5BQ3vx/j8f3//9/nf//BwA=","140":"b:AACiAoC4ABAEQUMgHgBQGsxFBUIQyNtqmRh0BQA=","142":"b:AACiAoC4ABAEQUMgHgBQGsxFBUIQyNtqmRh0BQA=","154":[86,124],"160":"b:AACiAoC4ABAEQUMgHgBQGsxFBUIQyNtqmRh0BQA=","162":"b:AACiAoC4ABAEQUMgHgBQGsxFBUIQyNtqmRh0BQA=","165":"b:AACiAoC4ABAEQUMgHgBQGsxFBUIQyNtqmRh0BQA=","169":[86,124,45,98],"170":"b:AACiAoC4ABAEQUMgHgBQGsxFBUIQyNtqmRh0BQA=","171":"b:AACiAoC4ABAEQUMgHgBQGsxFBUIQyNtqmRh0BQA=","183":[86,124,45],"195":[86,124],"207":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","211":"b:/k/j87z7AZjk33c7H5BQ3vx/j8f3//9/nf//BwA="},"packages/frontend/@n8n/design-system/src/components/N8nNodeCreatorNode/NodeCreatorNode.vue":{"32":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","33":"b:oECCAKAiAABkXXEIBxAQEOxpCAPwK5BOCNYOAQA=","60":[86,124],"70":"b:AACCAAAAAAAEIFEAAAAAECAAAACAAgAACAQCAAA=","73":[84,86,124,37,190,139]},"packages/frontend/@n8n/design-system/src/components/N8nNodeIcon/IconContent.vue":{"20":"b:+EeekKzzARDk/3cIH5BQ3Px/OX/wP/9/+P6/BwA=","22":[86],"34":"b:+EeSkKzjABDk/3cIH5BQ3Px/OUfwP/9/+P6/BwA=","44":[86],"53":"b:+EeSkKzjABDk/3cIH5BQ3Px/OUfwP/9/+P6/BwA=","56":"b:+EeekKzzARDk/3cIH5BQ3Px/OX/wP/9/+P6/BwA=","75":[86],"76":[86]},"packages/frontend/@n8n/design-system/src/components/N8nNodeIcon/NodeIcon.vue":{"24":"b:+EeekKzzARDk/3cIH5BQ3Px/OX/wP/9/+P6/BwA=","28":"b:+EeekKzzARDk/3cIH5BQ3Px/OX/wP/9/+P6/BwA=","43":"b:+EeekKzzARDk/3cIH5BQ3Px/OX/wP/9/+P6/BwA=","57":[86],"59":"b:4EWCAKiiAABkfXUIFxBQBOR/KAdQO7d/CPY/AgA="},"packages/frontend/@n8n/design-system/src/components/N8nOption/Option.vue":{"12":"b:4EW6A6y6AFhkfXcpHxB0FvR/KS9U+7d/nf7/AgA=","13":"b:4EW6A6y6AFhkXXcpHxB0FvR/KS9U+7d/nf7/AgA=","16":"b:4EW6A6y6AFhkXXcpHxB0FvR/KS9U+7d/nf7/AgA="},"packages/frontend/@n8n/design-system/src/components/N8nPopover/Popover.vue":{"89":"b:/k//8777AZjk/3c7H5BQ3vx/j9/3//9/nf//BwA=","110":"b:AAAAAQCgABAgfEIBAgAQCABwAAAAAABAgMeCAAA=","116":"b:AAAAAQCgABAgeEIAAAAQCABgAAAAAAAAgMYCAAA=","130":"b:AAAAAQCAABAAfEIAAgAQCABgAAAAAAAAgMaAAAA=","138":"b:/k//8777AZjk/3c7H5BQ3vx/j9/3//9/nf//BwA=","139":"b:AAAAAQCgABAgfEAAAgAQCABwAAAAAABAgMUCAAA=","148":"b:/k//8777AZjk/3c7H5BQ3vx/j9/3//9/nf//BwA=","151":"b:AAAAAQCAABAgfEIBAgAQCABgAAAAAAAAgMaAAAA=","152":"b:/k//8777AZjk/3c7H5BQ3vx/j9/3//9/nf//BwA=","153":"b:/k//8777AZjk/3c7H5BQ3vx/j9/3//9/nf//BwA=","156":"b:/k//8777AZjk/3c7H5BQ3vx/j9/3//9/nf//BwA=","172":"b:AAAAAQCgABAgXEIBAgAQCABwAAAAAABAgMeCAAA=","179":[86,88,123,24,47,69,199,201,215,81],"180":[86],"183":[86]},"packages/frontend/@n8n/design-system/src/components/N8nPromptInputSuggestions/N8nPromptInputSuggestions.vue":{"10":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","20":[86,11,124],"23":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","41":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","46":[86,11,124]},"packages/frontend/@n8n/design-system/src/components/N8nResizeWrapper/ResizeWrapper.vue":{"11":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","74":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","92":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","104":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","107":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","115":[86,124],"118":[86,124],"128":"b:oEWAECAgAABku3cIHxBQkMQ7CBFWK7RfCP6vAwA=","132":[86,124],"138":[86,124],"141":[86,124],"144":[86,124],"150":[86,124],"171":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","183":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","190":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","196":[86,124],"200":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","213":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nRoute/Route.vue":{"13":"b:/k//8777Adzk/3c7H5B83vz/r///////n///BwA=","15":"b:/k//8777Adzk/3c7H5B83vz/r///////n///BwA=","28":"b:/k//8777Adzk/3c7H5B83vz/r///////n///BwA=","29":"b:/k//8777Adzk/3c7H5B83vz/r///////n///BwA=","38":"b:/k//8777Adzk/3c7H5B8zvz/j///////n///BwA="},"packages/frontend/@n8n/design-system/src/components/N8nScrollArea/N8nScrollArea.vue":{"50":"b:/k//8777AZjk/3c7H5BQ3vx/j9/3//9/nf//BwA=","68":"b:/k//8777AZjk/3c7H5BQ3vx/j9/3//9/nf//BwA=","82":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","104":[144,86,11,124],"125":[86,124],"144":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","163":"b:/k//8777AZjk/3c7H5BQ3vx/j9/3//9/nf//BwA=","172":"b:/k//87z7AZjk33c7H5BQ3vx/j9/3//9/nf//BwA=","174":"b:/k//8777AZjk/3c7H5BQ3vx/j9/3//9/nf//BwA=","181":[86,18,124,92,160,81],"189":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nSegmentControl/SegmentControl.vue":{"11":"b:8E/CEKjjARDk/3cIH5B03Px/L2/wP/9/+P//BwA=","25":"b:8E/CEKjjARDk/3cIH5B03Px/L2/wP/9/+P//BwA=","26":"b:8E/CEKjjARDk/3cIH5B03Px/L2/wP/9/+P//BwA=","44":"b:8E/CEKjjARDk/3cIH5B03Px/L2/wP/9/+P//BwA=","48":"b:8E/CEKjjARDk/3cIH5B03Px/L2/wP/9/+P//BwA=","49":"b:8E/CEKjjARDk/3cIH5B03Px/L2/wP/9/2P//BwA=","55":"b:AAAAAAAAABAAf1AAAgAQEAB3AAAAACAAAMCHAwA=","59":"b:AAAAAAAAABAAf1AAAgAQEAB3AAAAACAAAMCHAwA=","62":[86,124,216],"73":[86,124],"88":"b:AAAAAAAAABAAf1AAAgAQEAB3AAAAACAAAMCHAwA=","96":"b:AAAAAAAAABAAf1AAAgAQEAB3AAAAACAAAMCHAwA=","105":"b:8E/CEKjjARDk/3cIH5B03Px/L2/wP/9/+P//BwA=","132":"b:8E/CEKjjARDk33cIH5B03Px/L2/wP/9/+P//BwA=","134":"b:8E/CEKjjARDk33cIH5B03Px/L2/wP/9/+P//BwA=","141":"b:8E/CEKjjARDk33cIH5B03Px/L2/wP/9/+P//BwA=","142":"b:8E/CEKjjARDk33cIH5B03Px/L2/wP/9/2P//BwA="},"packages/frontend/@n8n/design-system/src/components/N8nSegmentControl/SegmentControlItem.vue":{"18":"b:8E/CEKjjARDk/3cIH5B03Px/L2/wP/9/+P//BwA=","23":"b:8E/CEKjjARDk33cIH5B03Px/L2/wP/9/+P//BwA="},"packages/frontend/@n8n/design-system/src/components/N8nSelect/Select.vue":{"25":"b:4EW6A6y6AFhkfXcpHxB0FvR/KS9U+7d/nf7/AgA=","83":"b:4EW6A6y6AFhkfXcpHxB0FvR/KS9U+7d/nf7/AgA=","87":"b:4EW6A6y6AFhkfXcpHxB0FvR/KS9U+7d/nf7/AgA=","107":"b:4EW6A6y6AFhkfXcpHxB0FvR/KS9U+7d/nf7/AgA=","108":"b:4EW6A6y6AFhkfXcpHxB0FvR/KS9U+7d/nf7/AgA=","116":"b:4EW6A6y6AFhkfXcpHxB0FvR/KS9U+7d/nf7/AgA=","129":"b:4EW6A6y6AFhkfXcpHxB0FvR/KS9U+7d/nf7/AgA=","133":[7,86,17,23,91,45,60,132,133],"137":[84,86,157],"141":"b:AECQAIAAAAAAIEAIAAAAAIQAAAJAIAAAAABAAAA=","170":[86,157,214,81],"174":"b:4EW6A6y6AFhkfXcpHxB0FvR/KS9U+7d/nf7/AgA=","195":"b:4EW6A6y6AFhkfXcpHxB0FvR/KS9U+7d/nf7/AgA=","197":"b:gAC6AAAwABAAYHYIAABQBDQSASAAoKAAHQCHAAA=","200":[86],"203":"b:AACaAAAAAAAAYHQIAABABCQCASAAIIAACAAAAAA=","206":"b:AACaAAAAAAAAYHQIAABABCQCASAAIIAACAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nSendStopButton/N8nSendStopButton.vue":{"5":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","30":"b:IAE8MAwAAAAAAEAQAAAA0AAAAZgDAAAAAAAAAAA=","34":[86,11,124],"36":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","62":"b:/k//87z7Adzk33c7H5B83vz/v///////////BwA="},"packages/frontend/@n8n/design-system/src/components/N8nSpinner/Spinner.vue":{"6":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","21":"b:/k//87z7Ad7k33c7H5B83vz/////////////BwA=","61":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/@n8n/design-system/src/components/N8nSuggestedActions/SuggestedActions.vue":{"39":"b:8E+CkIzjAADk+3UAF5BQ3Ox/C0UAPndlmP7/AwA=","48":[86,124],"50":[86,124,69],"53":"b:8E+CkIzjAADk+3UAF5BQ3Ox/C0UAPndlmP7/AwA=","64":[86,123,124,47,69],"66":"b:8E+CkIzjAADk+3UAF5BQ3Ox/C0UAPndlmP7/AwA=","70":[86,124],"74":[86,123,124,47,69],"77":[86,123,124,47,69],"82":[86,124,69],"83":[86,123,124,47,69],"87":[86,124],"89":[86,123,124,47,69],"99":[86,124,69],"107":[86,123,124,47,69],"111":[86,123,124,47,69],"119":[86,124],"120":[86,123,124,47,69]},"packages/frontend/@n8n/design-system/src/components/N8nTabs/Tabs.vue":{"12":"b:5kWyA6i6ABBk/XMpHxBQFvR/Kgdc+7d/if4/AgA=","25":"b:5kWyA6i6ABBk/XMpHxBQFvR/Kgdc+7d/if4/AgA=","33":"b:5kWyA6i6ABBk/XMpHxBQFvR/Kgdc+7d/if4/AgA=","43":"b:oEWQAyAgAABkuXMIDxBQEMQ7CAFUq7RfiP4vAgA=","53":"b:5kWyA6i6ABBk/XMpHxBQFvR/Kgdc+7d/if4/AgA=","55":"b:gAACAwAwABAAAEAICAAAEDAQAAAAwAAAAAAAAAA=","67":[86,124],"68":[86,124,45,209,140],"73":[86,124],"79":[86,124],"80":[86,124],"81":"b:5kWyA6i6ABBk/XMpHxBQFvR/Kgdc+7d/if4/AgA=","101":"b:5kWyA6i6ABBk3XMpHxBQFvR/Kgdc+7d/if4/AgA=","108":[86,124],"109":[86,124],"110":"b:5kWyA6i6ABBk/XMpHxBQFvR/Kgdc+7d/if4/AgA=","119":[86,124],"129":[86,124],"136":"b:gACiAwA4ABAAgEIpHAAAEjAAAAAEwAAACQgAAAA=","143":[86,124],"158":[86,124,45,209,140],"159":[86,124],"179":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nText/Text.vue":{"21":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","29":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","49":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","51":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","55":"b:/k//87z7Adzk33c7H5B83vz/v///////////BwA="},"packages/frontend/@n8n/design-system/src/components/N8nTooltip/Tooltip.vue":{"21":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","37":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","45":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","46":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","48":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","57":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","62":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","63":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","73":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","75":"b:tEfyA6jzAATkf3MJB5BQiOx/CEfyP73/zO+/BwA=","77":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","88":"b:/k//87z7Adzk33c7H5B83vz/v///////////BwA=","94":"b:/k//8777Adzk/3c7H5B8zvz/v///////////BwA=","98":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","101":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","109":"b:AAYAAACAAAAAAHAAEgBACIQDCEACKAARAAACAAA=","119":[86]},"packages/frontend/@n8n/design-system/src/components/N8nTree/Tree.vue":{"14":"b:AAQAAAAAAAAAAUAAAAAQEAASIAAAIgAAAIAFAAA=","22":"b:AAQAAAAAAAAAAUAAAAAQEAASIAAAIgAAAIAFAAA=","26":"b:AAQAAAAAAAAAAUAAAAAQEAASIAAAIgAAAIAFAAA=","30":"b:AAQAAAAAAAAAAUAAAAAQEAASIAAAIgAAAIAFAAA=","46":"b:AAQAAAAAAAAAAUAAAAAQEAASIAAAIgAAAIAFAAA=","55":"b:AAQAAAAAAAAAAUAAAAAQEAASIAAAIgAAAIAFAAA=","62":"b:AAQAAAAAAAAAAUAAAAAQEAASIAAAIgAAAIAFAAA=","81":[86,124,137,116,208,140],"85":[86,124],"89":[86,124,137,116,208,140]},"packages/frontend/@n8n/design-system/src/composables/useAutosizeTextarea.ts":{"41":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","57":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","70":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","116":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","127":[86,34],"141":"b:/k//8777Adzk/3c7H5B8zvz/v///////////BwA=","152":"b:+E+yM67zAdDk/3cYH5B0zPx/uf/3f///nf//BwA=","162":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","168":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","169":[86]},"packages/frontend/@n8n/design-system/src/composables/useCharacterLimit.ts":{"15":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","19":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","21":[86,124],"23":[5,8,144,86,11,124],"25":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA="},"packages/frontend/@n8n/design-system/src/composables/useI18n.ts":{"4":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","6":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/@n8n/design-system/src/composables/useIconBodyLoader.ts":{"9":[86,124],"20":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA="},"packages/frontend/@n8n/design-system/src/composables/useMessage.ts":{"14":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","15":[86,62,72,78,98,82],"21":[86],"27":[86],"49":"b:AACAAwAAAEAAwUYABAAAAAABABAAAAAAAQAAAAA=","64":[86,156,23,24,25,192,62,72,136,78,98,79,81],"88":[86],"94":[86],"111":[86,43,174,134]},"packages/frontend/@n8n/design-system/src/composables/useResizablePanel.ts":{"75":[86,124],"79":[86,124],"83":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","88":[86,124],"93":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","109":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","113":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","116":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","119":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","140":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","150":[86,124],"159":[86,124],"164":[86,124],"170":[86,124],"180":"b:oEeAECAgAABku3cIHxBQkMQ7CBFWK7RfCP6vAwA=","184":[86,124],"190":[86,124],"195":"b:8E/+kKzjAQDk/3cIH5BQ3Ox/DV/wP/9/2P//BwA=","199":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","202":"b:5EWC8LyiAABkfXEYBxBQ1OR/KIdXO7d/CPY/AgA=","211":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","215":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","218":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","225":"b:8E/+kKzjAQDk/3cIH5BQ3Ox/DV/wP/9/2P//BwA=","232":"b:AAYAEAAAAAAgg1AABAAAkAADABAAAAABAAiAAwA=","241":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","264":[86,124],"288":[86,124],"293":[86,124],"300":[86,124],"305":"b:oEeAECAgAABku3cIHxBQkMQ7CBFWK7RfCP6vAwA=","317":"b:oEeAECAgAABku3cIHxBQkMQ7CBFWK7RfCP6vAwA=","328":[86,124],"341":[86,124],"347":[86,124],"353":[86,124],"379":[86,124],"386":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","389":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","392":"b:8E/+kKzjAQDk/3cIH5BQ3Ox/DV/wP/9/2P//BwA=","395":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA="},"packages/frontend/@n8n/design-system/src/composables/useTooltipAppendTo.ts":{"7":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/DUfwP/9/2P//BwA=","11":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","14":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA="},"packages/frontend/@n8n/design-system/src/directives/n8n-html.ts":{"19":"b:6E/SA6i6AVRkfXcIFxB0FvR/KS9S+7f/ifY/AgA=","31":"b:6E/SA6i6AVRkfXcIFxB0FvR/KS9S+7f/ifY/AgA="},"packages/frontend/@n8n/design-system/src/icons/lucide/bucket.ts":{"16":"b:+EeSkKzjABDk/3cIH5BQ3Px/OUfwP/9/+P7/BwA="},"packages/frontend/@n8n/design-system/src/icons/lucide/index.ts":{"16":"b:+EeSkKzjABDk/3cIH5BQ3Px/OUfwP/9/+P7/BwA=","22":"b:+EeSkKzjABDk/3UIH5BQzPx/OUfwP/9/+P7/BwA=","27":[86]},"packages/frontend/@n8n/design-system/src/locale/format.ts":{"8":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","9":"b:AAAAAwA4AAAAAEIhHAAAEgAAAAAEQAAAAAgAAAA=","12":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","30":"b:AAAAAwA4AAAAAEIhHAAAEgAAAAAEQAAAAAgAAAA="},"packages/frontend/@n8n/design-system/src/locale/index.ts":{"15":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","35":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","37":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/@n8n/design-system/src/plugin.ts":{"8":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/@n8n/design-system/src/types/binary.ts":{"24":"b:aEQAAAiCAAAAOUAAAwAQEIA3IQQAMiMsgPQ/AgA="},"packages/frontend/@n8n/design-system/src/utils/cn.ts":{"4":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA="},"packages/frontend/@n8n/design-system/src/utils/typeguards.ts":{"1":"b:4EW6A6y6AFhkfXcpHxB0FvR/KS9U+7d/nf7/AgA="},"packages/frontend/@n8n/design-system/src/utils/uid.ts":{"6":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/@n8n/design-system/src/v2/components/Select/Select.vue":{"40":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","42":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","46":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","69":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","75":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","97":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","105":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","109":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","113":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","117":[86,124],"129":[86,124],"138":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","171":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","179":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","229":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","230":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","233":"b:Pk7/8777Adzk/3c7H5B83vT/v///////////BwA=","234":"b:Pk7/8777Adzk/3c7H5B83vT/v///////////BwA=","237":[86,124],"245":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","249":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","253":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","257":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","261":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","272":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","275":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","283":[86,21,124,25,47,194],"291":[86,124],"304":[86,21,124,25,47,194],"312":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","319":"b:AAAgAwC4AAAAAEIhHAAAEgAAABAEQAAAAAgAAAA=","328":[86,124],"329":[86,124],"332":[86,124],"337":"b:AAAgAwC4AAAAAEIhHAAAEgAAABAEQAAAAAgAAAA=","343":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","352":[86,21,124,25,47,194],"353":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","362":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","364":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","372":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","385":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","386":"b:AAAgAwC4AAAAAEIhHAAAEgAAABAEQAAAAAgAAAA=","395":[86,124],"396":[86,124],"417":"b:Pk7/8777Adzk/3c7H5B83vT/v///////////BwA=","425":[86,124],"430":"b:Pk7/8777Adzk/3c7H5B83vT/v///////////BwA=","437":"b:Pk7/87z7Adzk33c7H5B83vT/v///////////BwA=","448":[86,21,124,175,194],"454":"b:Pk7/8777Adzk/3c7H5B83vT/v///////////BwA=","458":"b:Pk7/87z7Adzk33c7H5B83vT/v///////////BwA=","463":"b:Pk7/8777Adzk/3c7H5B83vT/v///////////BwA=","466":"b:Pk7/8777Adzk/3c7H5B83vT/v///////////BwA=","469":"b:Pk7/8777Adzk/3c7H5B83vT/v///////////BwA=","484":[86,124]},"packages/frontend/@n8n/design-system/src/v2/components/Select/SelectItem.vue":{"19":"b:Pk7/8777Adzk/3c7H5B83vT/v///////////BwA=","23":"b:Pk7/8777Adzk/3c7H5B83vT/v///////////BwA=","28":"b:Pk7/8777Adzk/3c7H5B83vT/v///////////BwA=","33":"b:Pk7/8777Adzk/3c7H5B83vT/v///////////BwA=","34":"b:Pk7/8777Adzk/3c7H5B83vT/v///////////BwA=","43":[86,21,124,25,47,194],"44":"b:Pk7/8777Adzk/3c7H5B83vT/v///////////BwA=","46":"b:Pk7/8777Adzk/3c7H5B83vT/v///////////BwA=","50":"b:Pk7/8777Adzk/3c7H5B83vT/v///////////BwA=","57":"b:Pk7/8777Adzk/3c7H5B83vT/v///////////BwA="},"packages/frontend/@n8n/frontend-constants/src/views.ts":{"20":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/@n8n/frontend-module-sdk/src/declareCapability.ts":{"19":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/@n8n/frontend-module-sdk/src/defineFrontendModule.ts":{"27":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/@n8n/frontend-module-sdk/src/registries/capabilityRegistry.ts":{"16":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","29":[86,124,163],"39":[86,124],"55":[86,124]},"packages/frontend/@n8n/frontend-module-sdk/src/registries/componentRegistry.ts":{"17":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","27":[86,124]},"packages/frontend/@n8n/frontend-module-sdk/src/registries/modalRegistry.ts":{"16":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","20":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","21":[86,124],"24":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","63":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA="},"packages/frontend/@n8n/frontend-module-sdk/src/registries/parameterInputRegistry.ts":{"13":[86,124],"17":[86,124],"18":[86,124],"25":[86,124],"49":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA="},"packages/frontend/@n8n/frontend-module-sdk/src/registries/pushHandlerRegistry.ts":{"9":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","27":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","36":"b:9ke+kIzjAATk+3UIH5BQ3Ox/C10APndl2P7/AwA=","40":"b:8EeCkIzjAATk+3UIH5BQ3Ox/C0UAPndl2P7/AwA="},"packages/frontend/@n8n/frontend-module-sdk/src/registries/resourceRegistry.ts":{"25":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA="},"packages/frontend/@n8n/frontend-module-sdk/src/routeNames.ts":{"7":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","32":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/@n8n/frontend-utils/src/htmlUtils.ts":{"24":"b:8EeyAwD7ANzg+3coD5AQGvQ/ADwT/relV+b3AwA=","26":[86,121,93,43,174,44,178,116,76,209,213,81],"47":"b:AACwAgAYAAQAEEIgAgAQAgAAAAABQAQABqAiAAA=","64":[86,124],"81":"b:AACAAwAIAEAAwUYABAAAEEABABAAQAAAAQAAAAA=","88":[86,124],"92":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","93":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","94":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","100":[86,124,70,99,82],"117":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/DUfwP/9/2P//BwA=","138":"b:YACAACAAABBEeHAAARAQEMA7AAEAAJRRgMYCAAA="},"packages/frontend/@n8n/i18n/src/index.ts":{"41":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","49":[86,124],"53":"b:8EeSEKzjAEBkf3EIB5B03Ox/KUfwP7d/yPa/AwA=","57":[86,124],"68":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","98":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","106":"b:8EeSEKzjAFBkf3UIB5B03Px/KW/wP7d/yPa/AwA=","110":"b:AAYAEAiAAAAAA3AAAAAA0AADAAAAAAABQACAAwA=","143":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","150":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","158":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","175":"b:gACCAIAgABAAYHQIAAAAADAAACgAAIAAAAAAAAA=","185":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","195":"b:gACCAIAgABAAYHQIAAAAADAAACgAAIAAAAAAAAA=","208":"b:gACCAIAgABAAYHQIAAAAADAAACgAAIAAAAAAAAA=","221":"b:gACCAIAgABAAYHQIAAAAADAAACgAAIAAAAAAAAA=","234":"b:8EeSEKzjAFBkf3UIB5B03PR/KW9QP7d/yPa/AwA=","243":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","255":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","267":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","282":"b:4EWSAKiiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","300":"b:4EWSAKiiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","322":"b:4EWSAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","345":[86,124,205,116,209,210,140],"367":[86,124],"378":[86,147,124,130],"385":"b:cEcAEAjDAABAA3AIA5AQ2IQ3CEQAPjMlQCCWAwA=","394":"b:4EGCAKAiAQBkfXUIHxAQEOxrCQfwL5l+CNcuBQA=","412":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","443":[86,124],"473":[86,124],"489":[86,124],"495":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/@n8n/i18n/src/utils.ts":{"9":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","29":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","31":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","34":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","41":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","49":"b:oEEAAAiAAAAgOFEAAwAQFAQ3CAYQOgRhgOIeAAA=","57":"b:oEEAAAiAAAAgOFEAAwAQFAQ3CAYQOgRhgOIeAAA=","58":"b:oEEAAAiAAAAgOFEAAwAQFAQ3CAYQOgRhgOIeAAA="},"packages/frontend/@n8n/rest-api-client/src/api/module-settings.ts":{"6":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA="},"packages/frontend/@n8n/rest-api-client/src/api/nodeTypes.ts":{"24":"b:/k//8777Ad7k/3c7H5B83vz/v///////////BwA=","38":"b:/k//8777Ad7k/3c7H5B83vz/v///////////BwA=","62":"b:8E/CkKzjAQDk/3cIH5BQ3Ox9P0fwP///+P//BwA=","68":[86,124,39,191,58],"79":[86,124],"85":[86,124],"92":[86,152,124,209,77],"99":[84,86,124,78],"111":[86,124,78,141],"123":[86,124,213,142],"135":[86,124]},"packages/frontend/@n8n/rest-api-client/src/api/roles.ts":{"13":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","17":[86,124],"21":[86,124],"28":[86,124],"36":[86,124],"45":[86,124],"52":[86,124],"64":[86,124]},"packages/frontend/@n8n/rest-api-client/src/api/settings.ts":{"6":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/@n8n/rest-api-client/src/api/usage.ts":{"6":"b:8E/Dk6z7AYjk/3crH5BQ3ux/v0f0//9/3P//BwA=","10":[86,124],"20":[86,124],"24":[86,124],"30":[86,124]},"packages/frontend/@n8n/rest-api-client/src/api/users.ts":{"92":"b:/k//8777Ad7k/3c7H5B83vz/z///////n///BwA=","98":[86,151,124,63],"105":[86,124],"109":[86,124],"121":[86,124],"128":[86,124],"135":[86,124],"142":[86,124],"149":[86,124,193,63],"156":[86,124,63],"163":[86,124],"170":[86,124],"177":[86,124,184,190,69,137,139,77],"184":[86,124],"192":[86,124],"199":[86,124,194],"206":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","220":[86,124],"227":[86,124],"234":[86,124],"247":[86,124,194]},"packages/frontend/@n8n/rest-api-client/src/api/versions.ts":{"50":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","59":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA="},"packages/frontend/@n8n/rest-api-client/src/api/workflowHistory.ts":{"52":[86,124,203],"65":"b:EAYAkAzhAACEo1YAHYBQ3GwfM0AAEnYB2Dj3AwA=","77":[144,86,11,124],"92":[86,124],"105":[86,124]},"packages/frontend/@n8n/rest-api-client/src/utils.ts":{"14":[86,124],"45":"b:DACBAgAAAIQAIFQAAAAAEgAAsAkAAAAABiAAAAA=","81":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","86":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","88":"b:/k//8777Adjk/3c7H5B03vx/j///////nf//BwA=","89":"b:/k//8777Adjk/3c7H5B03vx/j///////nf//BwA=","91":[86,117,114,62,194,100],"100":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","179":"b:BgABkwy4AIwggEIrHABA0jBAgCAMwACAHAggAQA=","196":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","214":"b:/k//8777Ad7k/3c7H5B83vz/v///////3///BwA=","223":[144,86,11,124,191,58],"232":[86,124],"241":[5,6,7,8,144,86,11,124],"251":[86,11,124],"276":[5,6,7,8,144,86,124]},"packages/frontend/@n8n/stores/src/cloudPlan.store.ts":{"31":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","43":[86,124],"45":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","49":[86,124],"55":[86,22,124],"57":[86,22,124],"60":[86,22,124],"63":[86,22,124],"72":[86,22,124],"79":[86,22,124],"85":[86,22,124],"87":[86,22,124],"97":[86,22,124],"99":[86,22,124],"101":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","103":[86,22,124],"105":"b:AAABAwA4AIgAgEIjHAAAEgAAgAAEwAAADAgAAAA=","106":[86,124],"125":[86,22,124],"130":[86,124],"135":[86,143,22,124,193,63],"141":[86,22,124],"152":[86,124],"156":[86,22,124],"172":[86,22,124],"178":[86,124],"187":[86,124],"197":[86,22,124],"218":[86,22,124],"219":[86,124],"233":[86,22,124],"244":[86,22,124],"252":[86,22,124],"272":[86,124]},"packages/frontend/@n8n/stores/src/composables/useAssistantTopUpEligibility.ts":{"20":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","26":[86,124,159]},"packages/frontend/@n8n/stores/src/composables/useBasePageRedirectionHelper.ts":{"36":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","44":[86,124],"50":[86,124],"91":[86,124],"100":[86,124],"110":[86,124],"140":[86,124]},"packages/frontend/@n8n/stores/src/composables/useCloudUbbActive.ts":{"21":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","27":[86,124]},"packages/frontend/@n8n/stores/src/metaTagConfig.ts":{"1":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","8":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","34":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/@n8n/stores/src/notifications.store.ts":{"22":"b:8E/zAqD7AZzk/3coH5BQHvx/v3/z////////BwA=","26":[86,148,149,151,63,198]},"packages/frontend/@n8n/stores/src/rbac.store.ts":{"9":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","73":[86,124],"79":[86,124],"83":[86,124],"89":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","93":[86,124],"108":[86,124],"125":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/@n8n/stores/src/registries/upgradeRedirectGuard.ts":{"16":[86,124],"18":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","22":[86,124]},"packages/frontend/@n8n/stores/src/roles.store.ts":{"23":[86,21,124,175,45,194],"24":[86,21,124,175,45,194],"35":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","51":[86,21,124,175,45],"52":[86,21,124,175,45],"56":[86,124,194],"57":[86,124,194],"60":[86,124,194],"62":[86,124,194],"70":[86,124,194],"71":[86,124,194],"74":[86,21,124,175,45],"76":[86,21,124,175,45],"84":[86,157,91,124,132,133],"85":[86,157,91,124,132,133],"88":[86,124,195,196,81],"89":[86,124,195,196,81],"92":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","96":[86,124],"100":[86,124],"104":[86,124],"108":[86,124],"112":[86,124],"116":[86,124],"123":[86,124]},"packages/frontend/@n8n/stores/src/settings.store.ts":{"29":[86,124],"44":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","73":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","75":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","77":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","79":[86,124],"81":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","83":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","85":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","90":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","92":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","94":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","96":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","98":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","100":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA=","102":[86,22,124],"104":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","106":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","108":"b:/k//8777Ad7k/3c7H5B83vz/v///////3///BwA=","110":[86,124],"114":[86,22,124],"116":[86,22,124],"118":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","122":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","124":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","128":[5,6,7,8,144,86,146,11,124,131],"132":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","134":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","136":"b:/k//8777Ad7k/3c7H5B83vz/v///////////BwA=","138":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","140":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","144":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","156":[86,124],"160":"b:5kW/A6y6AJhk/XcpHxBQFvR/KD9U+7d/jf4/AgA=","164":[86,18,155,19,156,20,21,124],"166":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","170":"b:/k//8777Adzk/3c7H5B83vz/r///////3///BwA=","172":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA=","176":[86,124],"180":[86,124],"182":[86,124],"184":"b:8E/D8777AYjk/3c7H5BQ3ux/vcf3//9/3P//BwA=","188":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","190":[86,124],"192":"b:AAABAACCAAAgYHEBEgB8FBh+iAUYPf+/mCO7BwA=","194":[86,124],"198":[86,143,124,193,63],"200":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","202":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","204":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","208":"b:4EWyAKiiAABkfXEIBxBQFOR/KAdQu7d/iPY/AgA=","217":[86,21,124,175,45],"220":[1,2,86,124],"224":[85,86,124],"228":[86,21,124,175,194],"232":"b:YAEAAAA4AAAAIEIhHgAAEgACAAQERAk4AAhGBAA=","236":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/2P//BwA=","242":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","244":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","246":[86,124,100],"248":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","250":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","252":"b:/k/38777Adzk/3c5H5B83vz/v///////////BwA=","254":[86,124,191,58],"258":[86,124],"260":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA=","261":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","263":[86,124,115],"265":[86,124,47,69],"269":[86,22,124],"271":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","273":[86,124],"275":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","277":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/D0fwP/9/mP//BwA=","281":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","313":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","317":[86,124],"321":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","325":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","329":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","333":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","337":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","391":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","401":[86,124],"405":[86,124],"415":[86,124,100],"416":[86,124,100],"417":[86,124,100],"423":[86,124,47,69],"428":[86,124],"432":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","437":[86,124]},"packages/frontend/@n8n/stores/src/useAgentRequestStore.ts":{"18":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","23":[86,124],"34":[86,124],"38":[86,124],"51":[86,124],"64":[4,10,86,124,35,181,184,70,136,205,206,75],"70":[86,124],"78":"b:cAQAAAgCAABAGGAAAgAQEIAzAAQAKCIBAOAGAAA="},"packages/frontend/@n8n/stores/src/useRootStore.ts":{"41":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","74":"b:/k//8777Ad7k/3c7H5B83vz/v///////////BwA=","76":"b:AACAAAAAAAAAQEAAAgAAEAQBKAMQIAAAACACAAA=","78":"b:AACAAAAAAAAAQEAAAgAAEAQBKEMQIAAAACACAAA=","82":[86,124,137],"86":"b:AACAAAAAAAAAQEAAAgAAEAQBKAMQIAAAACACAAA=","88":"b:AAaAAAAAAAAAQHAAAgAAEAQDKAMQIEABQCACAAA=","92":[86,124],"96":"b:AACAAAAAAAAAQEAAAgAAEAQBKAMQIAAAACACAAA=","98":"b:AACAAAAAAAAAQEAAAgAAEAQBKAMQIAAAACACAAA=","102":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","104":"b:cEcAAAjDAABAG3AIE5AQmIQ3CEQAPjMlQOC3AwA=","106":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","108":[5,6,84,85,86,124,137,209,78],"110":[86,124],"112":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","114":"b:/k//8777Ad7k/3c7H5B83vz/v///////////BwA=","116":[7,86,23,124],"118":[86,124],"120":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","122":[86,124,47,69],"124":[86,124,47,69],"126":[86,124,47,69],"128":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","133":[86,124],"143":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","148":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","153":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","158":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","162":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","166":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","170":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","174":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","178":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","182":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","186":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","190":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","195":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","199":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","203":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","207":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","211":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","215":[86,124],"219":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","223":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","227":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","231":[86,124],"235":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/@n8n/stores/src/users.store.ts":{"40":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","41":"b:/k//8777Ad7k/3c7H5B83vz/v///////////BwA=","42":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","44":[86,91,124,45,99],"47":[86,124],"53":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","66":[86,124],"74":[86,124],"75":[86,124],"78":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","87":[86,124],"88":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","99":"b:/k/j8777ARjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","101":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","105":"b:gACCAAAAAABkaEEAAxAAEORgCAGQIRAACEYOAAA=","107":[86,124],"109":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","111":[86,91,124,45,99],"113":"b:oECSAKAiAARkfXEIBxAQEOxpCAPwK5DOCNYOAQA=","115":[86,143,124,193,63],"117":[86,143,124,193,63],"119":[86,124],"121":[84,85,86,124,184,190,69,137,139,77],"125":[86,88,124],"129":[86,124,184,190,69,137,139,77],"135":"b:YAEAAAAAAABAIEQADAAAEEADAAQEAAkoAAIEBAA=","138":[86,124],"146":[86,124,194],"152":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","153":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","175":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","188":"b:/k//8777Ad7k/3c7H5B83vz/z///////n///BwA=","197":"b:/k//8777Ad7k/3c7H5B83vz/z///////n///BwA=","211":[86,124],"215":[86,124,194],"220":[86,124],"234":[86,151,124,63],"243":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","247":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","251":[86,124],"259":[86,124],"290":[86,124],"303":[86,124],"307":[86,124],"319":[86,124],"323":[86,124],"327":[86,124],"331":[86,124,193,63],"337":[86,124,193,63],"345":[86,124,63],"356":[86,124],"360":[86,124],"364":[86,124],"375":[86,124],"379":[86,124],"383":[86,124,194],"388":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","405":[86,124],"408":[86,124],"416":[86,124],"425":[86,124],"429":[86,124],"433":[86,124],"440":"b:8E/D8777AYjk/3c7H5BQ3ux/vcf3//9/3P//BwA=","447":[86,124],"451":[86,124],"455":[86,124],"459":[86,124],"466":[86,124,63],"474":[86,124],"479":[86,124],"483":[86,124,194],"488":[86,124],"501":[86,124,194],"510":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA="},"packages/frontend/@n8n/stores/src/versions.store.ts":{"32":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","59":[86,124],"67":[86,124],"68":[86,124],"71":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","81":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","85":[86,124],"108":[86,124],"112":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","116":[86,121,124],"120":"b:/k/j8777AZjk/3c7H5BQ3Px/j8f3//9/nf//BwA=","126":"b:/k//8777Ad7k/3c7H5B83Pz/j///////n///BwA=","132":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","142":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","157":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","158":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","159":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","162":"b:/k//8777Ad7k/3c7H5B83Pz/j///////n///BwA=","166":[86,124],"175":"b:/k/j8777AZjk/3c7H5BQ3Px/j8f3//9/nf//BwA=","179":[86,124],"184":[86,124],"186":[86,124],"190":"b:/k//8777Ad7k/3c7H5B83Pz/j///////n///BwA=","195":"b:/k//8777Ad7k/3c7H5B83Pz/j///////n///BwA=","202":"b:/k//8777Ad7k/3c7H5B83Pz/j///////n///BwA=","209":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","228":[86,124],"251":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","255":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","278":[86,121,124]},"packages/frontend/editor-ui/src/app/App.vue":{"42":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","57":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","81":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","82":[86,124],"86":"b:4ASCAAAAAABAfVEIAgAQEIRYCAIAIIBAAMYVAAA=","93":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","99":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","105":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","106":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","113":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","126":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","133":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","138":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","142":[86,124],"146":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","153":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/api/favorites.ts":{"16":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","20":[86,124],"31":[86,124]},"packages/frontend/editor-ui/src/app/api/workflow-dependencies.ts":{"10":"b:EAaAkwz5AACEo1YpHYBQ3nwfAkAEUnYBmDi3AwA=","23":[86,124,44,47,195,118,196,69,203,214,79,81],"36":[86,124]},"packages/frontend/editor-ui/src/app/api/workflows.ts":{"26":"b:4EnCAKAiAQBg/XcIFxAQGORrPQfwL4l+aMdOBQA=","39":"b:4EnCAKAiAQBg/XcIFxAQGORrPQfwL4l+aMdOBQA=","65":"b:EAYAkAzxAACko1YAHYBQ3GxfAkAEEnYBmDj3AwA=","69":"b:4EnCAKAiAABg/XMIBxAQGORrDQfwL4l+CMdOBQA=","80":[86,124,28,126,31,34,35,127,162,47,69,216],"96":[86,124,191,58],"107":"b:AAABAwA4AIgAgEIjHAAAEgBAgAAEwAAADAggAAA=","123":"b:8E/Dk6z7AYjk/3crH5BQ3ux/j0f0//9/nP//BwA=","145":"b:cEcAEAjDAABAG3AIA5AQ2IQ3AAQAPjMlQOC3AwA=","158":"b:EAYAAADhAACEo1YAHYBQHGwfAEAAEnYBmDi3AwA=","169":"b:8E+CkIzjAADk+3cIH5BQ3Ox/C0UAPndlmP7/AwA="},"packages/frontend/editor-ui/src/app/capabilities.manifest.ts":{"21":[86,124],"22":[86,124],"26":[86,124],"48":[86,124,163],"49":[86,124],"50":[86,124],"57":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/componentSlots.manifest.ts":{"12":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","16":[86,124]},"packages/frontend/editor-ui/src/app/components/BottomMenu.vue":{"23":"b:/k//8777AZjk/zc7H5BQzvx/j9/3//9/nf//BwA=","33":[88,201],"36":[88,201],"78":[88,201],"84":"b:/k//8777AZjk/zc7H5BQzvx/j9/3//9/nf//BwA=","104":[88,201],"106":[88,201],"118":[88,201],"129":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","134":[88,201],"168":"b:/k//8777AZjk/zc7H5BQzvx/j9/3//9/nf//BwA="},"packages/frontend/editor-ui/src/app/components/ConnectionTracker.vue":{"26":"b:8E/CkKzjAQDk/zcIH5BYzOx/D0fwP/9/mP//BwA="},"packages/frontend/editor-ui/src/app/components/Draggable.vue":{"18":"b:6EeCAKi6AABkfXMpHxBQFuR/KAdUe7d/iP4/AgA=","40":"b:6EeCAKi6AABkfXMpHxBQFuR/KAdUe7d/iP4/AgA=","44":"b:AAAAAAA4AAAAAEIgCAAQEAAQAAAEQAAAAAgFAAA=","78":[86,124,93,116],"105":[86,124,93,116],"115":[86,124,162,93,43,174,44,45,203,116,81],"127":[86,124,162,93,43,174,44,45,203,116,81],"135":"b:KEeAACA6AABkOXMpHxBQEsQ7CAVUa7ZfgP4vAgA=","140":"b:6EeCAKi6AABkfXMpHxBQFuR/KAdUe7d/iP4/AgA=","149":"b:6EeCAKi6AABkXXMpHxBQFuR/KAdUe7d/iP4/AgA="},"packages/frontend/editor-ui/src/app/components/DraggableTarget.vue":{"15":"b:4EWSAKyiAFBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","31":"b:4EWSAKwiABBkfXEIBxB0FOR/CQdQO7d/iPY/AAA=","32":[86,124,116],"33":[86,124],"34":"b:4EWSAKyiAFBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","37":"b:4EWSAKyiAFBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","39":[86,124,116],"49":"b:IECQAIACAFAAfFAIAgBQFIRzCQZAIARBAOQSAAA=","53":"b:IECQAIACAFAAfFAIAgBQEIRzCAZAIAQBAOQSAAA=","57":"b:AECQAIACABAAfFAIAgAQFIRwCAZAIABAAOQCAAA=","64":[86,124,116],"79":"b:4EWSAKyiAFBkfXEIBxB0FOR/KQdQO7d/iPY/AgA="},"packages/frontend/editor-ui/src/app/components/DynamicModalLoader.vue":{"8":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","19":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","20":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","27":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","31":"b:/k//87z7Ad7k33c7H5B83vz/////////////BwA=","33":[86,19,156,157,20,124,24,25,117,114,62,63]},"packages/frontend/editor-ui/src/app/components/FocusSidebar.vue":{"32":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","51":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","52":[188,199],"53":"b:8E/CEKzjAQDk/zcIH5BQjOx/KUfwP/9/2P//BwA=","55":[188,199],"60":[188,199],"65":[188,199],"72":[188,199],"83":[188,199],"87":"b:8E/CEKzjAQDk/zcIH5BQjOx/KUfwP/9/2P//BwA=","95":[188,199],"111":[188,199],"115":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","119":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","120":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","131":"b:8E/CEKzjAQDk/zcIH5BQjOx/KUfwP/9/2P//BwA=","159":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","163":"b:AAAAEAAgAAAggxAAFAAAgAADAAAAAAAAAAiAAwA=","166":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","188":[188,199]},"packages/frontend/editor-ui/src/app/components/FreeAiCreditsCallout.vue":{"21":"b:4EWCAKyiABBkfXUIBxBQFPR/KC9QO7d/iPY/AgA=","41":[86,124],"45":[86,124],"51":[86,124],"55":"b:4EWCAKyiABBkfXUIBxBQFPR/KC9QO7d/iPY/AgA=","57":"b:4EWCAKyiABBkfXUIBxBQFPR/KC9QO7d/iPY/AgA=","59":[86,124],"63":"b:4EWCAKyiABBkfXUIBxBQFPR/KC9QO7d/iPY/AgA=","78":[86,124],"89":[86,124],"90":[86,124]},"packages/frontend/editor-ui/src/app/components/KeyboardShortcutTooltip.vue":{"16":"b:/k//8777AZjk/3c7H5BQ3vx/v9/3//9//f//BwA=","17":[86,124],"21":"b:/k//8777AZjk/3c7H5BQ3vx/v9/3//9//f//BwA="},"packages/frontend/editor-ui/src/app/components/MainHeader/ActionsDropdownMenu.vue":{"61":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","99":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","100":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","108":[122,40,130,111,172,43,45,118,66,82],"133":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","141":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","143":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","147":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","156":"b:YAEAAAAIAAAAIAAABgAAAAACAAQABAk4AAAGBAA=","160":"b:YAEAAAAIAAAAIAAABgAAAAACAAQABAk4AAAGBAA=","178":"b:YAEAAAAIAAAAIAAABgAAAAACAAQABAk4AAAGBAA=","186":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","364":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","370":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","371":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","376":[43,214],"397":"b:YAEAAACIAAAgoAAABgBAAAACAAQABAk4GApGBAA=","402":"b:YAEAAACIAAAgoAAABgBAAAACAAQABAk4GApGBAA=","439":[43,69],"461":[43],"479":[43],"559":[43],"560":[43],"592":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","596":[28,127,43,45,203,98,79],"603":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA="},"packages/frontend/editor-ui/src/app/components/MainHeader/MainHeader.vue":{"52":"b:8E/CAKDrAQDk/zcIH5BQDOx/D0fwP/9/mP//BwA=","60":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","61":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","66":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","67":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","68":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","69":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","70":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","72":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","82":"b:4E2CAKAqAQBk/zcIFxBQBOR/CQdQP7d/CP7/AwA=","86":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","90":[28,127,43,203,98,79],"94":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","99":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","106":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","116":"b:8E/CAKDrAQDk/zcIH5BQDOx/DUfwP/9/mP//BwA=","136":[84,43,72,136,73,137,215,216,217],"157":[84,43,216,217],"188":[84,43,72,136,73,137,215,216,217],"214":[43],"232":[43]},"packages/frontend/editor-ui/src/app/components/MainHeader/TabBar.vue":{"22":[84,43,72,136,73,137,215,216,217],"24":"b:8E/CAKDrAQDk/zcIH5BQDOx/D0fwP/9/mP//BwA="},"packages/frontend/editor-ui/src/app/components/MainHeader/WorkflowDetails.vue":{"39":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","71":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","75":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","79":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","83":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","88":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","100":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","101":[43,45,98,79],"108":[43],"114":"b:YAEAAAAIAAAAIAIIBgAAAAACAAQABAk4AABGBAA=","140":[43],"184":[43],"205":[43],"249":[43,79],"259":[43,79],"310":[43],"312":[43],"318":"b:YAEAAAAIAAAAIAAABgAAAAACAAQABAk4AAAGBAA=","324":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","332":[28,127,43,45,203,98,79],"339":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","349":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","388":[43,79],"395":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA="},"packages/frontend/editor-ui/src/app/components/MainHeader/WorkflowHeaderDraftPublishActions.vue":{"79":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","85":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","87":[43],"88":[43],"91":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","110":[43],"114":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","118":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","122":[43],"124":[43],"127":[43],"130":[43],"136":[43],"148":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","149":[43,45,98,79],"160":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","162":[43],"171":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","175":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","181":"b:gACAACAIAQAgQDUAEAAAAAQKCQMQIIRAAAAKBAA=","183":"b:oAaAACCIAQAk+DcAFwAQCAwLCUMQOMRBgOIKBAA=","185":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","188":"b:8E/CkKzrAQDk/zcIF5BQzOx/D0fwP/9/mP//BwA=","214":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","215":[43],"216":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","218":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","248":"b:8E+CkIzrAADk+zcIH5BQzOx/C0UAPndlmP7/AwA=","249":"b:8E+CkIzrAADk+zcIH5BQzOx/C0UAPndlmP7/AwA=","250":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","251":[123,172,43,47,69,79,80],"253":"b:4EnCAKAqAQBg/TcIHxAQCORrDQfwL4l+CMdOBQA=","260":[43],"271":[43],"277":[43,69],"302":[172,43,69,79,80],"307":[172,43,69,79,80],"314":[43],"320":[43],"331":[43],"341":[43],"350":[43],"355":[43],"364":[43],"370":[43],"385":[172,43,69,79,80],"420":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","561":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","566":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","581":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","592":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","601":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","602":[172,43,45,69,98,79,80],"612":[43],"619":[43],"624":"b:8E/C8LzrAQDk/zcYH5BQzOx/D8f3P/9/mP//BwA=","629":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","631":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","667":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","672":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","675":[43],"694":[43],"729":[43],"739":[43],"760":[43],"785":[43],"786":[43],"791":[43],"795":[43],"800":[43],"806":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","811":[28,127,43,45,203,98,79],"815":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","826":[43],"845":[43],"860":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","907":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","918":[43],"927":[43]},"packages/frontend/editor-ui/src/app/components/MainSidebar.vue":{"36":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","83":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","86":"b:/k/j8777AZjk/zc6H5BQzPx/j8f3//9/nf//BwA=","91":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","93":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","226":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","228":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","229":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","231":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","235":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","247":[88,22,25,44,45],"248":[88,22,25,44,45],"253":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","257":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","262":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","273":[162,45,195,203,98,99,79,81,82,100],"282":[201],"304":[88,201],"360":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","393":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA="},"packages/frontend/editor-ui/src/app/components/MainSidebarHeader.vue":{"37":"b:/E/iM677ABDk/zc5H5BQzvx/D8f3//9/mf//BwA=","41":[88,22,25,44,45],"69":"b:AAB8AgAwAIAAAAADCAAAAAAAABgAAAAAAAAAAAA=","114":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","123":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","132":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","144":[16,89,91,45,63,194,99],"157":[63],"169":"b:/k//8777AZjk/zc7H5BQzvx/j9/3//9/nf//BwA="},"packages/frontend/editor-ui/src/app/components/MainSidebarSourceControl.vue":{"27":[59],"37":[59],"41":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","47":[59],"53":[59],"62":[59],"84":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","111":[59],"144":[59],"170":[59]},"packages/frontend/editor-ui/src/app/components/ModalDrawer.vue":{"7":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","34":[86,124],"40":"b:YAGCgQAIAJDgqEYAHwAAEHAKAAUAxAk4QwNnBQA=","50":[86,124],"61":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","71":[86,124],"75":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","89":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","91":[86,121,124],"92":[86,124]},"packages/frontend/editor-ui/src/app/components/ModalRoot.vue":{"5":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","25":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","26":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/components/Modals.vue":{"131":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","132":[86,124],"134":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","139":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","146":[86,124],"168":[86,124,201],"172":[86,124],"176":[7,86,17,23,91,124,45,60,132,133],"180":[86,124],"186":[86,124,201,218],"190":[86,124],"194":[86,124,214],"198":[86,124],"202":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","206":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","212":[86,124,47,69],"216":[86,124],"222":[86,124,194],"228":[86,124,172,69,79,80],"232":[86,124,195,196,81],"238":[86,124,191,58],"242":[86,124],"246":[86,124,191,58],"256":[86,124],"262":[86,124],"268":[86,124],"274":[86,124],"280":[86,124],"286":[86,124],"292":[86,124],"298":[86,124,60],"304":[86,124],"314":[86,124,81],"324":[86,124],"334":[86,124,48,82],"343":[86,124,44],"352":[5,86,124],"358":[86,124],"364":[86,124,174],"370":[86,124,44,118],"376":[86,124],"382":[86,124],"388":[86,124],"394":[86,124],"400":[86,124,213],"406":[86,124],"412":[86,124],"418":[86,124],"424":[86,124,192],"430":[86,124],"436":[86,124,214],"442":[86,124,172,69,79,80],"448":[86,124],"454":[86,124],"463":[86,124],"469":[86,124],"475":[86,124]},"packages/frontend/editor-ui/src/app/components/NodeExecuteButton.vue":{"15":"b:4EWCAKgiAABkfXEIBxBQFOR/CAdQO7d/iPY/AAA=","60":"b:4EWCAKgiAABkfXEIBxBQFOR/CAdQO7d/iPY/AAA=","75":"b:YAQAAAACAAAAEGAAAgAQEIAwAAQAKAIBAKAGAAA=","77":[86,124],"82":"b:4EWCAKgiAABkfXEIBxBQFOR/CAdQO7d/iPY/AAA=","94":"b:4EWCAKgiAABkfXEIBxBQFOR/CAdQO7d/iPY/AAA=","100":"b:4EWCAKgiAABkfXEIBxBQFOR/CAdQO7d/iPY/AAA=","106":"b:4EWCAKgiAABkfXEIBxBQFOR/CAdQO7d/iPY/AAA=","121":"b:4EWCAKAiAABkfXEIBxBQFOR6CAdQK4ZfiOYOAAA=","125":"b:YAQAAAACAAAAUGAAAgAQEIAwAAQAKAIBAKAGAAA=","137":"b:YAQAAAACAAAAEGAAAgAQEIAwAAQAKAIBAKAGAAA=","141":"b:4EWCAKgiAABkfXEIBxBQFOR/CAdQO7d/iPY/AAA=","150":[86,124],"153":"b:4EWCAKgiAABkfXEIBxBQFOR/CAdQO7d/iPY/AAA="},"packages/frontend/editor-ui/src/app/components/NodeIcon.vue":{"25":"b:+EeSkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","43":"b:+EeSkKzjAQDk/3cIH5BQ3Ox/KUfwP79/2P6/BwA=","44":"b:+EeSkKzjAQDk/3cIH5BQ3Ox/KUfwP79/2P6/BwA=","48":"b:+EeSkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","50":"b:+EeSkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","51":"b:+EeSkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","56":"b:+EeSkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","61":"b:+EeSkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","66":"b:+EeSkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","68":"b:+EeSkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","71":"b:+EeSkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","86":"b:YEUAAAigAADEuUUACwBQFMQ/KAQAMjcxgHa3AwA="},"packages/frontend/editor-ui/src/app/components/NpsSurvey.vue":{"14":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","40":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","54":[86,124],"75":[86,124],"88":[86,124],"92":[86,124],"107":[86,124],"117":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","118":[86,124],"127":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","144":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","146":"b:/k//87z7Ad7k33c7H5B83vz/////////////BwA=","149":[86,124],"153":[86,124],"159":[86,124],"164":[86,124],"165":[86,124]},"packages/frontend/editor-ui/src/app/components/UpdatesPanel.vue":{"11":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","15":"b:/k//87z7Ad7k33c7H5B83vz/////////////BwA=","24":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","29":[86,121,124],"60":[86,124],"61":[86,121,124],"70":[86,121,124]},"packages/frontend/editor-ui/src/app/components/WorkflowProductionChecklist.vue":{"34":"b:8E+CkIzrAADk+zcIH5BQzOx/C0UAPndlmP7/AwA=","50":[123,172,43,47,69,79,80],"51":[123,172,43,47,69,79,80],"52":[123,172,43,47,69,79,80],"58":[43,69],"62":[123,172,43,47,69,79,80],"67":[123,172,43,47,69,79,80],"68":[123,172,43,47,69,79,80],"73":[123,172,43,47,69,79,80],"74":[123,172,43,47,69,79,80],"77":[123,172,43,47,69,79,80],"82":[123,43,47,69],"86":[123,172,43,47,69,80],"88":"b:8E+CkIzrAADk+zUAF5BQzOx/C0UAPndlmP7/AwA=","92":"b:8E+CkIzpAADk+zUIHZBAzOx/C0UAGlNgGP71AgA=","93":[91,43,45,99],"95":"b:8E+CkIzrAADk+zUIH5BQzOx/C0UAPndlmP7/AwA=","99":"b:8E+CkIzrAADk+zUIH5BQzOx/C0UAPndlmP7/AwA=","103":"b:8E+CkIzpAADk+zUIHZBAzOx/C0UAGlNgGP71AgA=","105":"b:8E+CkIzrAADk+zcIH5BQzOx/C0UAPndlmP7/AwA=","198":"b:8E+CkIzrAADk+zcIH5BQzOx/C0UAPndlmP7/AwA=","206":[43,69],"231":[123,43,47,69],"235":[43],"239":[123,43,47,69],"254":"b:8E+CkIzrAADk+zcIH5BQzOx/C0UAPndlmP7/AwA=","267":[123,172,43,47,69,79,80],"274":[43,69],"281":[123,43,47],"292":"b:8E+CkIzrAADk+zcIH5BQzOx/C0UAPndlmP7/AwA=","298":"b:8E+CkIzrAADk+zcIH5BQzOx/C0UAPndlmP7/AwA=","301":"b:8E+CkIzrAADk+zcIH5BQzOx/C0UAPndlmP7/AwA="},"packages/frontend/editor-ui/src/app/components/app/AppBanners.vue":{"7":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","9":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","10":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/components/app/AppChatPanel.vue":{"9":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","24":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","26":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","34":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","39":[86,124],"45":[86,124],"49":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA="},"packages/frontend/editor-ui/src/app/components/app/AppCommandBar.vue":{"11":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","29":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","31":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","35":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","41":[86,124,216],"46":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/components/app/AppHeader.vue":{"6":"b:8E/CAKDjAQDk/zcIH5BQDOx/D0fwP/9/mP//BwA="},"packages/frontend/editor-ui/src/app/components/app/AppLayout.vue":{"5":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","6":"b:jgCjAwA4AJgAgEYrHAAAEjAAgAAEwAAADQgAAAA=","9":"b:AABAAACAANwAAEAAAAAsEACAACAIAACABgAAAAA=","12":"b:8E/CAKDjAQDk/3cIH5BQHOx/D0fwP/9/mP//BwA=","14":[86,16,151,124,63],"15":[86,148,149,124,197,198],"16":[86,18,155,19,156,20,21,124],"18":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","30":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","35":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","37":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/components/app/AppModals.vue":{"7":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/components/app/E2ETestModeMarker.vue":{"5":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","7":"b:/k//87z7Ad7k33c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/components/transitions/SlideTransition.vue":{"3":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA="},"packages/frontend/editor-ui/src/app/composables/useActivationError.ts":{"9":"b:8E/CkKz7AQDk/3cpH5BQ3ux/D0f0f/9/mP//BwA=","13":[86,124]},"packages/frontend/editor-ui/src/app/composables/useActivityDetection.ts":{"12":"b:wAGAAAAAAADkaREADxAQAOx4AQAAIBJBAHaiAwA=","18":"b:wAGCAAAAAADk6READxAQAOx6AQAAMBJFAHaqAwA=","19":"b:wAGCAAAAAADk6READxAQAOx6AQAAMBJFAHaqAwA=","24":"b:AAAAEAAgAAAggxYAHAAAgAADAAAAAAAACAiAAwA=","25":"b:AAAAEAAgAAAggxYAHAAAgAADAAAAAAAACAiAAwA=","31":"b:9k/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","32":"b:wAGCAAAAAADk6READxAQAOx6AQAAMBJFAHaqAwA=","42":"b:9k/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","49":"b:AAAAEAAgAAAggxYAHAAAgAADAAAAAAAACAiAAwA="},"packages/frontend/editor-ui/src/app/composables/useAiGateway.ts":{"8":"b:/k//8777Adzk/3c7H5B83vz/r///////n///BwA=","14":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA=","15":[86,124],"16":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","17":[86,124],"19":"b:/k/z8777Adzk/3c7H5B83vz/j+//////n///BwA=","21":"b:4EWSAKyiABBkfXUIBxBQFPR/CS9QO7d/iPY/AgA=","26":[86,124],"29":[86,124],"32":[86,124],"38":[86,124],"41":"b:gACSAIAgAAAgaEEAAgBAEGQ0CAFQISUACEQOAAA=","47":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","50":"b:9k/SkKzjARDk/3cIH5BQ3Px/DW/wP/9/mP//BwA=","55":[86,124]},"packages/frontend/editor-ui/src/app/composables/useAiGatewayTopUp.ts":{"14":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA=","23":[86,124],"29":[86,124]},"packages/frontend/editor-ui/src/app/composables/useAiSimulatedDataGuard.ts":{"13":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","18":"b:YEQAAAiCAAAAEUAAAgAQAIQ3CAQAOgIgAKA3AgA=","25":[86]},"packages/frontend/editor-ui/src/app/composables/useBackendStatus.ts":{"10":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","19":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","25":[86,124],"52":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","70":"b:AACwEwwwAABAC1EoAxAA0PRKAHoAoAAAEkxkAQA=","75":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","85":[86,124]},"packages/frontend/editor-ui/src/app/composables/useBeforeUnload.ts":{"15":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","22":[86,124],"27":[86,124],"32":[86,124],"43":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","47":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/2P//BwA=","51":"b:AAAAEAAgAAAgg1YAHAAAkAADAAAAAAAACAiAAwA="},"packages/frontend/editor-ui/src/app/composables/useBrowserNotifications.ts":{"57":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","66":[144,86,11,124],"67":[86,124],"68":[86,124],"70":[86,124],"76":[86,124],"80":[144,86,11,124],"89":[86,124],"101":[86,124],"126":[86,124],"133":[86,124],"137":[86,124],"162":[86,124]},"packages/frontend/editor-ui/src/app/composables/useBugReporting.ts":{"27":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","30":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA="},"packages/frontend/editor-ui/src/app/composables/useCalloutHelpers.ts":{"17":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","28":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","42":[86,124],"75":[86,124,136,77],"79":[86,124]},"packages/frontend/editor-ui/src/app/composables/useCanvasOnlyExternalLinks.ts":{"15":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","41":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA="},"packages/frontend/editor-ui/src/app/composables/useCanvasOperations.ts":{"226":"b:4EGCAKAiAQBkfXUIHxAQEOxrCQfwL5l+CNcuBQA=","236":"b:4EGCAIAiAQBEfVUIHxAQEORiCQdQJxk+CNYuBAA=","245":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","269":"b:4EWCAKiiAABkfXEIBxBQBOR/KAdQO7d/CPY/AgA=","300":[86],"306":"b:oECCAKAiAABgfXEIAxAQAOxpCAPwK4BGCMYKAQA=","310":"b:4EGCAKAiAQBkfXUIHxAQAOxrCQfwL5l+CNcuBQA=","317":[86],"325":[86,71],"333":[86,71],"346":[144,86,185],"365":[86,185],"373":[86,184,70,96,71,201,99],"377":[86,184,70,96,71,201,99],"390":[86,184,70,96,71,201,99],"399":[144,86,185],"416":[144,86,185],"420":[144,86,185],"461":[144,86,184,186,187,70,96,71,201,99],"486":[86,201],"495":[86,187,213],"523":[86,213],"535":[86,134,77,142],"592":[86],"596":[86,179,180,70,96,71,201,137,213],"679":[86,179,180,70,96,71,201,137,213],"809":[86,70,96,71,201,213],"823":[86,70,96,71,201,213],"837":[86,201,213],"842":[86,179,180,70,96,71,201,137,213],"861":[86,213],"882":[86,213],"983":[86],"1014":[86],"1015":[86],"1066":"b:4EWCAKiiAABkfXEIBxBQBOR/KAdQO7d/CPY/AgA=","1076":"b:4EWCAKiiAABkfXEIBxBQBOR/KAdQO7d/CPY/AgA=","1080":[86],"1084":[86],"1099":"b:8EeCAKiiAADk/XUIDxBQBOx/KAfwP79/iPe/BwA=","1115":"b:AAAAAAAAAABgAVEAAAAAAEACAAAAAAAAACKAAwA=","1128":[86,201],"1135":[86],"1144":[86],"1145":[86],"1147":[86],"1158":[86],"1188":"b:4EGCAKAiAQBkfXUIHxAQAOxrCQfwL5l+CNcuBQA=","1196":"b:4EGCAKAiAQBkfXUIHxAQAOxrCQfwL5l+CNcuBQA=","1281":"b:4EGCAKAiAQBkfXUIHxAQAOxrCQfwL5l+CNcuBQA=","1285":[86],"1300":"b:4EGCAKAiAQBkfXUIHxAQAOxrCQfwL5l+CNcuBQA=","1314":[86,134,99],"1325":"b:4EGCAKAiAQBkfXUIHxAQAOxrCQfwL5l+CNcuBQA=","1355":"b:4EGCAKAiAQBkfXUIHxAQAOxrCQfwL5l+CNcuBQA=","1410":"b:YAEAAAAAAAAAIEAADgAAAEACAAQABAk4AAIGBAA=","1411":"b:YAEAAAAAAAAAIEAADgAAAEACAAQABAk4AAIGBAA=","1439":[86,201,213],"1448":[86,186,187,70],"1459":"b:4EGCAKAiAQBkfXUIHxAQAOxrCQfwL5l+CNcuBQA=","1532":"b:oECCAKAiAABkfXEIBxAQAOxpCAPwK5BOCNcKAQA=","1542":[86,200],"1548":"b:oECCAKAiAABkfXEIBxAQAOxpCAPwK5BOCNYKAQA=","1579":[86],"1600":"b:4EGCAKAiAQBkfXUIHxAQAOxrCQfwL5l+CNcuBQA=","1644":"b:4EGCAKAiAQBkfXUIHxAQAOxrCQfwL5l+CNcuBQA=","1650":"b:4EGCAKAiAQBkfXUIHxAQAOxrCQfwL5l+CNcuBQA=","1655":"b:4EGCAKAiAQBkfXUIHxAQAOxrCQfwL5l+CNcuBQA=","1675":"b:oECCAKAiAABkfXEIBxAQAOxpCAPwK5BOCNcKAQA=","1687":"b:4EGCAKAiAQBkfXUIHxAQAOxrCQfwL5l+CNcuBQA=","1813":"b:AACAACAAAABECHAABwAAAMAoAAAAIIBKAFYIAAA=","1826":"b:gECCAKAiAABkfXEIBxAQAORoCAFAIIBOCNYKAAA=","1847":[86,186,187,70],"1903":"b:gECCAKAiAABkfXEIBxAQAORoCAFAIIBOCNYKAAA=","1908":[84,85,86,23,37,183,190,139],"1935":"b:AAAAAAAAAABECFAABwAAAMAgAAAAIAAKAFYIAAA=","1986":"b:4EGCAKAiAQBkfXUIHxAQAOxrCQfwL5l+CNcuBQA=","1995":[86,186,187,70],"2017":[86,186,187,70],"2054":[86,186,187,70],"2069":[86,187],"2074":[86,186,187,70],"2076":[86,186,187,70],"2082":[86,187],"2096":[86,187],"2108":[86,187],"2122":[86,187],"2129":[86,187],"2136":[86,186,187,70],"2143":[86,186,187,70],"2151":[86,187,70],"2160":[86,187,70],"2164":[86,186,187,70],"2176":[86,186,187,70],"2179":[86,186,187,70],"2182":[86,186,187,70],"2283":[86,187],"2330":[86,186,187,70],"2354":[86,186,187,70],"2401":"b:4EGCAKAiAADkfXEIBxAQAORqCQdQJ4l+CNYuBAA=","2439":"b:4EGCAKAiAADkfXEIBxAQAORqCQdQJ4l+CNcuBAA=","2528":"b:4EGCAKAiAADkfXEIBxAQAORqCQdQJ4l+CNYuBAA=","2538":[86,201,213],"2553":[86,179,180,70,96,71,201,137,213],"2619":"b:AAAAAAAAAADAAEAAAQAAAAACAQAAABgMAAIgAAA=","2654":"b:AAAAAAAAAADAAEAAAQAAAAACAQAAABgMAAIgAAA=","2668":[86,201,213],"2684":[84,86,153,173,213],"2701":[84,86,213],"2722":[86],"2728":[84,86,213],"2732":[86,153,173,213],"2736":"b:4EGCAKAiAADkfXEIBxAQAORqCQdQJ4l+CNcuBAA=","2744":"b:4EGCAKAiAADkfXEIBxAQAORqCQdQJ4l+CNcuBAA=","2750":"b:4EGCAKAiAADkfXEIBxAQAORqCQdQJ4l+CNYuBAA=","2757":"b:4EGCAKAiAADkfXEIBxAQAORqCQdQJ4l+CNYuBAA=","2761":"b:4EGCAKAiAADkfXEIBxAQAORqCQdQJ4l+CNYuBAA=","2766":"b:4EGCAKAiAADkfXEIBxAQAORqCQdQJ4l+CNYuBAA=","2845":"b:4EGCAKAiAADkfXEIBxAQAORqCQdQJ4l+CNYuBAA=","2876":"b:4EGCAKAiAABkfXEIDxAQAOxrCQfwL5l+CNcOBQA=","2903":"b:8E/CkKzjAQDk/3cIH5BQzOx/P0fwP/9/+P//BwA=","2954":"b:EAYAkAzhAACEo1YAHYBQzGwfMkAAEnYB2Dj3AwA=","2967":[86],"2968":[86],"2992":"b:YAEAAAAAAAAAIEAADgAAAEACAAQABAk4AAIGBAA=","3009":"b:YAEAAAAAAAAAIEAADgAAAEACAAQABAk4AAIGBAA=","3027":"b:YAEAAAAAAAAAIEAADgAAAEACAAQABAk4AAIGBAA=","3044":"b:YAEAAAAAAAAAIEAADgAAAEACAAQABAk4AAIGBAA=","3047":"b:YAEAAAAAAAAAIEAADgAAAEACAAQABAk4AAIGBAA=","3090":"b:YAEAAAAAAAAAIEAADgAAAEACAAQABAk4AAIGBAA=","3145":[86],"3212":"b:YAEAAAAAAAAAIEAADgAAAEACAAQABAk4AAIGBAA=","3250":"b:YAEAAAAAAAAAIEAADgAAAEACAAQABAk4AAIGBAA=","3260":[86],"3265":"b:YAEAAAAAAAAAIEAADgAAAEACAAQABAk4AAIGBAA=","3272":"b:YAEAAAAAAAAAIEAADgAAAEACAAQABAk4AAIGBAA=","3282":"b:YAEAAAAAAAAAIEAADgAAAEACAAQABAk4AAIGBAA=","3283":"b:YAEAAAAAAAAAIEAADgAAAEACAAQABAk4AAIGBAA=","3327":[86],"3330":[86],"3332":[86],"3413":"b:YAEAAAAAAAAAIEAADgAAAEACAAQABAk4AAIGBAA=","3443":[86,170,187,188,210,77,97,98,218],"3445":[86,218],"3448":[86,188,98,218],"3454":[86,188,98,218],"3463":[86,188,98,218],"3471":[86,188,98,218],"3472":[86,188,98,218],"3483":[86,218],"3506":[86,70,134,201,97,99,82],"3511":[86],"3512":[86],"3514":[86],"3520":"b:YAEAAAAAAAAAIEAADgAAAEACAAQABAk4AAIGBAA=","3534":[86],"3557":[86,70,134,201,97,99,82],"3569":[86,70,134,201,97,99],"3617":[86,82],"3622":[86],"3630":[86,70,134,201,97,99,82],"3651":[86,70,134,99,82],"3658":[86,70,134,99],"3659":[86,70,134,99],"3670":[86,134,201,97],"3677":[86,134,201,97],"3679":[86,70,99,82],"3681":[86,70,99],"3697":[86,70,99],"3704":[86],"3710":[86],"3760":[84,85,10,86,184,198],"3775":[84,85,10,86,184,198],"3780":[86,48,82,100],"3806":[86],"3830":[86],"3848":[86],"3885":"b:oECCAKAiAABkfXEIBxAQAOxpCAPwK5BOCNcKAQA=","3899":"b:oECCAKAiAABkfXEIBxAQAOxpCAPwK5BOCNcKAQA=","3903":[86],"3937":"b:AACAAKAAAAAAYHAAAAAAAAAoAAJQA4BGAAACAAA=","3978":[86],"3990":[86],"4006":[86],"4029":[86],"4050":"b:8E/CkKzjAQDk/3cIH5BQzOx/P0fwP/9/+P//BwA=","4051":"b:8E/CkKzjAQDk/3cIH5BQzOx/P0fwP/9/+P//BwA=","4054":[86,48,82,100],"4062":[86,48,82,100],"4069":[86,48,82,100],"4126":[86]},"packages/frontend/editor-ui/src/app/composables/useCollectionOverhaul.ts":{"5":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","8":"b:4EWSAKiiAEBkfXUIBxB0FOR/KC9QO7d/iPY/AgA="},"packages/frontend/editor-ui/src/app/composables/useDataSchema.ts":{"31":"b:+E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","35":"b:aEQAAAiCAAAAOUAAAwAQEIA3AQQAEiMsgPQ/AgA=","58":[86,124],"65":[86,124,169,176,199,137,116,207,208,77,140],"75":"b:aEQAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","100":"b:aEQAAAiCAAAAOUAAAwAQEIA3AQQAEiMsgPQ/AgA=","110":[86,124,187,205,211],"130":[86,124,187,205,211],"151":[86,124,187,205,211],"163":"b:YEQAAAiCAAAAGUAAAwAQEIQ3CAQAOiIkAOA3AgA=","179":"b:4EWCAKiiAADkfXEIBxBQFOR/KQdQO7d/iPY/AgA=","207":"b:4EWCAKiiAADkfXEIBxBQFOR/KQdQO7d/iPY/AgA=","216":"b:AAAAAAAAAAAAOUAAAgAQEAAQIAAAAAAAgOQlAAA=","221":"b:AAAAAAAAAAAAOUAAAgAQEAAQIAAAAAAAgOQlAAA=","228":[86,124,210],"236":"b:aEQAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","241":[86,124,210],"365":"b:aEQAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","367":"b:aEAAAAiCAAAACUAAAwAAEIA3AAQAEiMkADAeAgA=","378":[86,124,205,211],"385":"b:aEQAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","394":"b:aEQAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","396":"b:aEQAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","399":[86,124,116,210],"407":"b:aEQAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","468":"b:aEQAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","509":"b:YEAAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","514":"b:YEAAAAiCAAAAOUAAAwAQEIA3AAQAEiMkgPQ/AgA="},"packages/frontend/editor-ui/src/app/composables/useDebugInfo.ts":{"70":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","76":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","113":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","124":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","134":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","145":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","152":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","156":[86,124,201],"164":[86,124,201],"167":[86,124,201],"170":[86,124],"172":[86,124,201],"182":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","199":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","217":[86,124,201],"231":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","235":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA="},"packages/frontend/editor-ui/src/app/composables/useDependencies.ts":{"17":"b:EAaAkwz4AACEo1IpHQAQ2mgfAkAEQnYBmDi3AwA=","31":"b:kAaCkwz5ABCko1YpHYBQ3nwfAkAEUnYBmDj3AwA=","41":"b:8E+Ck4z7ABDk+3cpH5BQ3vx/C0UEfn99mP7/BwA=","50":"b:EAaAkwz5AACko1YpHYBQ3nwfAkAEUnYBmDj3AwA=","56":"b:8E/Dk6z7AZjk/3crH5BQ3vx/j2f0//9/nP//BwA=","60":"b:kAaCkwz5ABCEo1YpHYBQznwfAkAEUnYBmDi3AwA=","65":"b:EAaAkwz5AACEo1YpHYBQznwfAkAEUnYBmDi3AwA=","66":"b:EAaAkwz5AACEo1YpHYBQznwfAkAEUnYBmDi3AwA=","89":[86,44,47,195,118,196,69,203,214,79,81],"94":[86,44,47,195,118,196,69,203,214,79,81],"95":[86,44,47,195,118,196,69,203,214,79,81],"121":[86],"137":"b:YAEAAACxAAAkoEYIFoBABDQCAAQAFAk4GApGBAA=","144":[86,81],"151":"b:8E+Ck4z7ABDk+3cpH5BQ3vx/C0UEfndlmP7/AwA=","154":"b:EAaAkwz5AACEo1YpHYBQznwfAkAEUnYBmDi3AwA=","157":"b:8E+Ck4z7ABDk+3cpH5BQ3vx/C0UEfndlmP7/AwA=","164":[86]},"packages/frontend/editor-ui/src/app/composables/useDocumentTitle.ts":{"18":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","20":[86,124,162],"23":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","30":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA="},"packages/frontend/editor-ui/src/app/composables/useDocumentVisibility.ts":{"12":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","17":"b:AAAkwhC4ANiEoEIwHwAgFkSAAAAGwgAAAFAgAAA=","22":[86,124],"24":[86,124],"28":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","32":[86,124],"36":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","40":"b:4AEAEAAgAAAAgEYAHAAAkAhgAAAEAAAACAggAAA="},"packages/frontend/editor-ui/src/app/composables/useEditorContext.ts":{"21":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","27":"b:8E/CAKjjAQDk/3cAF5BQHOx/DUfwP/9/mP//BwA=","30":"b:8E/CAKjjAQDk/3cIH5BQHOx/DUfwP/9/mP//BwA=","53":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","54":"b:8E/CAKjjAQDk/3cIH5BQHOx/DUfwP/9/mP//BwA=","61":"b:8E/SkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","62":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","63":"b:8EWCkIjjAQDk/1cIH5BQ3Ox/CUfwPz8+mP6/BwA=","64":"b:8EeCkIzjAATk+3UIH5BQ3Ox/C0UAPndl2P7/AwA=","67":"b:8EeCkIzjAATk+3UIH5BQ3Ox/C0UAPndl2P7/AwA="},"packages/frontend/editor-ui/src/app/composables/useErrorHandler.ts":{"26":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","33":[86,124]},"packages/frontend/editor-ui/src/app/composables/useExecutingNode.ts":{"19":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","25":"b:cEcAEAjDAABAG3AIA5AQ2IQ3CAQAPjMlQOC3AwA=","37":"b:cEcAEAjDAABAG3AIA5AQ2IQ3CAQAPjMlQOC3AwA=","45":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","51":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/CUfwP/9/+P+/BwA="},"packages/frontend/editor-ui/src/app/composables/useExposeCssVar.ts":{"7":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","11":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","12":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","19":[86,124]},"packages/frontend/editor-ui/src/app/composables/useExternalHooks.ts":{"16":"b:/k//8777Ad7k/3c7H5B83vz/v///////////BwA=","38":"b:/k//8777Ad7k/3c7H5B83vz/v///////////BwA=","50":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/composables/useFloatingUiOffsets.ts":{"17":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","22":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","27":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","28":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","37":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/composables/useFreeAiCredits.ts":{"24":"b:5kW+AKyiABBkfXUIBxBQFPR/KD9QO7d/iPY/AgA=","35":"b:5kW+AKyiABBkfXUIBxBQFPR/KD9QO7d/iPY/AgA=","37":[86,18,155,19,156,20,21,124],"39":[86,124],"44":[86,124],"49":[86,124],"53":"b:5kW+AKyiABBkfXUIBxBQFPR/KD9QO7d/iPY/AgA=","61":[86,124],"92":[86,124]},"packages/frontend/editor-ui/src/app/composables/useGlobalEntityCreation.ts":{"34":"b:AACiAoC4ABAEQUMgHgBQGsxFBUIQyNtqmBBgAQA=","37":"b:AACiAoC4ABAEQUMgHgBQGsxFBUIQyNtqmBBgAQA=","58":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","87":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","91":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","94":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","98":"b:/k/j8777ARjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","102":"b:/k/j8777ARjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","106":"b:/k/j8777ARjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","109":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","113":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","123":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","127":[86,124,192,203,210,212,218],"147":[86,124],"156":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","167":"b:AACiAoC4ABAEQUMgHgBQGsxFBUIQyNtqmBBgAQA=","179":"b:AACiAoC4ABAEQUMgHgBQGsxFBUIQyNtqmBBgAQA=","191":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","213":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","235":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","360":"b:AACiAoC4ABAEQUMgHgBQGsxFBUIQyNtqmBBgAQA=","394":"b:AACiAoC4ABAEQUMgHgBQGsxFBUIQyNtqmBBgAQA=","429":"b:AACiAoC4ABAEQUMgHgBQGsxFBUIQyNtqmBBgAQA=","449":[86,124,175,45],"472":[86,124],"514":[86,124,175,45,98],"567":[86,16,89,91,124,45,63,194,99],"592":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","593":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","594":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","597":[86,124,63]},"packages/frontend/editor-ui/src/app/composables/useGlobalLinkActions.ts":{"14":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","15":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","18":"b:AAAAEACgAAAgg1YAHAAAkAADAAAAAAAACAiAAwA=","22":[86,124,77],"34":"b:8E/CAKjjAADk/3cID5BQnOx/KUfwP/9/2P//BwA=","47":[86,124],"55":[86,124,77],"60":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","69":"b:AAAAEACgAAAgg1YAHAAAkAADAAAAAAAACAiAAwA="},"packages/frontend/editor-ui/src/app/composables/useHistoryHelper.ts":{"18":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","24":"b:YAGCgQAIAJDgqVcAHwBAEHAKAQUQxYk8QxPnBwA=","32":[86,124,201,213],"60":[86,124,201],"88":[86,124,201,213],"94":[86,124,201,213],"99":[86,124,201],"110":"b:YAGAgQAIAIDgqVcAHwAAEEAKAQUQxYk8QxPnBwA=","117":"b:YAGCgQAIAJDgqVcAHwBAEHAKAQUQxYk8QxPnBwA=","147":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","151":[86,124]},"packages/frontend/editor-ui/src/app/composables/useInjectWorkflowId.ts":{"4":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA="},"packages/frontend/editor-ui/src/app/composables/useInstanceAiEditorCapability.ts":{"79":"b:8E/SkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA="},"packages/frontend/editor-ui/src/app/composables/useInvalidNodeGroupCleanup.ts":{"24":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","32":[86,124,71],"51":[86,124,71],"52":[86,124,71],"58":[86,124],"64":[86,124],"80":"b:4EmCAIAiAADkeXcIExAQEOR7CQUALANlAObuAwA=","84":[86,124,71]},"packages/frontend/editor-ui/src/app/composables/useKeybindings.ts":{"53":"b:/k//8777AZjk/3c7H5BQ3vx/v9/3//9//f//BwA=","65":"b:/k//8777AZjk/3c7H5BQ3vx/v9/3//9//f//BwA=","76":[86,124],"80":[86,124],"86":"b:YAGCgQAIABDgqVcAHwBAEHAKAQUQxYk8QRPnBwA=","88":"b:YAGCgQAIABDgqVcAHwBAEHAKAQUQxYk8QRPnBwA=","90":"b:YAGCgQAIABDgqVMAHwBAEHAKAQUQxYk8QRPnBwA=","92":"b:YAGCgQAIABDgqVMAHwBAEHAKAQUQxYk8QRPnBwA=","97":"b:YAGCgQAIABDgqVcAHwBAEHAKAQUQxYk8QRPnBwA=","99":"b:YAGCgQAIABDgqVMAHwBAEHAKAQUQxYk8QRPnBwA=","100":"b:YAGCgQAIABDgqVMAHwBAEHAKAQUQxYk8QRPnBwA=","104":"b:YAGCgQAIABDgqVcAHwBAEHAKAQUQxYk8QRPnBwA=","110":"b:YAGCgQAIABDgqVMAHwBAEHAKAQUQxYk8QRPnBwA=","128":"b:YAGCgQAIABDgqVcAHwBAEHAKAQUQxYk8QRPnBwA=","146":"b:YAGCgQAIABDgqVcAHwBAEHAKAQUQxYk8QRPnBwA=","200":"b:YAGCgQAIABDgqVcAHwBAEHAKAQUQxYk8QRPnBwA="},"packages/frontend/editor-ui/src/app/composables/useLayoutProps.ts":{"4":"b:8E/CAKDjAQDk/zcIH5BQDOx/D0fwP/9/mP//BwA=","7":"b:8E/CAKDjAQDk/zcIH5BQDOx/D0fwP/9/mP//BwA="},"packages/frontend/editor-ui/src/app/composables/useLoadingService.ts":{"10":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","14":[86,124,48,59,218,82,100],"26":[86,124,48,82,100],"32":[86,124,48,59,218,82,100],"39":"b:4EmCAIAiAADkeXcIExAQEOR7CQUALANlAObuAwA="},"packages/frontend/editor-ui/src/app/composables/useModulePushDispatcher.ts":{"16":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","23":"b:9ke+kIzjAATk+3UIH5BQ3Ox/C10APndl2P7/AwA=","32":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","33":"b:9ke+kIzjAATk+3UIH5BQ3Ox/C10APndl2P7/AwA=","38":[86,124]},"packages/frontend/editor-ui/src/app/composables/useNodeConnections.ts":{"12":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","25":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","26":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","29":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","30":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","33":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","34":"b:EASAACAAAABgIHAAAAAAEAAKAAAAAKBAAAAAAAA=","37":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","45":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","46":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","49":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","50":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","53":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","61":[86,124,71,213]},"packages/frontend/editor-ui/src/app/composables/useNodeDirtiness.ts":{"27":"b:AAAAAAAAAAAAAUAAAQAAEAACAAAAABAEACCgAwA=","35":"b:AAAAAAAAAAAAAUAAAQAAEAACAAAAABAEACCgAwA=","58":[86,124,180,137,213],"66":[86,124,186,96,72,137,205,213,215,216,217],"67":[86,124,186,96,72,137,205,213,215,216,217],"77":[86,124,215,216,217],"89":"b:QAAAAAAAAAAAAEAAAgAAEIAiAAAAIAIEACAgAAA=","138":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","141":"b:cEcAEAjDAABAG3AIA5AQ2IQ3CAQAPjMlQOC3AwA=","144":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","148":"b:cEcAEAjDAABAG3AIA5AQ2IQ3CAQAPjMlQOC3AwA=","152":[86,124,186,215,216,217],"156":"b:cEcAEAjDAABAG3AIA5AQ2IQ3CAQAPjMlQOC3AwA=","158":"b:cEcAEAjDAAAAG3AIA5AQ0IQ3CAQANjMlQOC3AwA=","159":[4,84,85,10,86,124,137],"162":"b:cEcAEAjDAABAG3AIA5AQ2IQ3CAQAPjMlQOC3AwA=","179":"b:cEcAEAjDAABAG3AIA5AQ2IQ3CAQAPjMlQOC3AwA=","215":[86,124,186],"218":[86,124,186],"258":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","262":"b:QAAAAAAAAAAAAEAAAgAAEIAiAAAAIAIEACAgAAA=","271":[86,124,186],"308":"b:cEcAEAjDAAAAG3AIA5AQ0IQ3CAQANjMlQOC3AwA=","309":"b:cEcAEAjDAAAAG3AIA5AQ0IQ3CAQANjMlQOC3AwA="},"packages/frontend/editor-ui/src/app/composables/useNodeDocsUrl.ts":{"5":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","8":[86,124,39],"10":[86,23,124,39,210,139],"18":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA="},"packages/frontend/editor-ui/src/app/composables/useNodeExecution.ts":{"82":"b:4EWCAKiiAABkfXEIBxBQFOR/KQdQO7d/iPY/AgA=","105":[86,124],"106":[86,124],"109":"b:YAQAAAACAAAAEGAAAgAQEIAwAAQAKAIBAKAGAAA=","117":"b:4EWCAKgiAABkfXEIBxBQFOR/CQdQO7d/iPY/AAA=","121":"b:4EWCAKgiAABkfXEIBxBQFOR/CQdQO7d/CPY/AAA=","127":"b:4EWCAKgiAABkfXEIBxBQFOR/CQdQO7d/iPY/AAA=","131":[86,147,124,130,173],"133":"b:4EWCAKgiAABkfXEIBxBQFOR/CQdQO7d/CPY/AAA=","135":"b:YAQAAAACAAAAEGAAAgAQEIAwAAQAKAIBAKAGAAA=","141":"b:4EWCAKgiAABkfXEIBxBQFOR/CQdQO7d/CPY/AAA=","143":"b:4EWCAKgiAABkfXEIBxBQFOR/CQdQO7d/CPY/AAA=","145":[86,147,124,130,171,173,97],"147":"b:4EWCAKgiAABkfXEIBxBQFOR/CQdQO7d/CPY/AAA=","149":"b:4EWCAKgiAABkfXEIBxBQFOR/CQdQO7d/iPY/AAA=","159":"b:4EWCAKgiAABkfXEIBxBQFOR/CQdQO7d/iPY/AAA=","172":"b:4EWCAKgiAABkfXEIBxBQFOR/CQdQO7d/CPY/AAA=","180":"b:4EWCAKgiAABkfXEIBxBQFOR/CQdQO7d/iPY/AAA=","186":"b:oACAAAAAAAAgWHEAAwAQEARJCQMQKAQAAOYLAAA=","193":"b:4EWCAKgiAABkfXEIBxBQFOR/CAdQO7d/iPY/AAA=","222":"b:4EWCAKgiAABkfXEIBxBQFOR/CQdQO7d/CPY/AAA=","250":"b:4EWCAKgiAABkfXEIBxBQFOR/CQdQO7d/CPY/AAA=","256":"b:4EWCAKgiAABkfXEIBxBQFOR/CQdQO7d/iPY/AAA=","276":[86,124],"284":[86,124],"356":[85,10,86,124,184],"365":"b:YAQAAAACAAAAEGAAAgAQEIAwAAQAKAIBAKAGAAA=","451":[86,124]},"packages/frontend/editor-ui/src/app/composables/useNodeGroupRules.ts":{"13":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","17":"b:YAEAgCAAAADAIHQADwAAAEAKAAQABAl4AAImBAA=","23":"b:YAEAACAAAADAIHQADwAAAEAKAAQABAl4AAImBAA="},"packages/frontend/editor-ui/src/app/composables/useNodeHelpers.ts":{"67":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","83":"b:4EWSAKyiAEBkfTEIBxB0BOR/KQdQO7d/iPY/AgA=","113":"b:4EWCAKiiAABkfTEIBxBQBOR/KQdQO7d/iPY/AgA=","146":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/iPY/AgA=","159":"b:AACCAAAgAAAAIDAIAABABCQCAAAAIIAACAAAAAA=","160":"b:AACCAAAgAAAAIDAIAABABCQCAAAAIIAACAAAAAA=","161":"b:AACCAAAgAAAAIDAIAABABCQCAAAAIIAACAAAAAA=","165":"b:4EeSAKyjAVBkfTcIF5B0nPx/OW9QO/d/yPY/BgA=","185":[85,20,139],"251":"b:cEcQEAjDAABAGzAIE5AQyIQ/CEQAPjMlQOC3AwA=","267":[122,23,91,41],"281":"b:8EeCkKzjAQDk/zcIH5BQzOx/CUfwP/9/mP+/BwA=","301":"b:QEGCAIACAABEfRAIAxAQAORoCAcAIhJQCOYiAAA=","309":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","317":"b:8E/CEKjjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","329":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","337":"b:QEGCAIACAABEfRQIAxAQAORoCAcAIhJQCOYiAAA=","345":"b:4EGCAKAiAQBkfTUIHxAQAOxrCQfwL5t+CPeuBwA=","360":"b:QEGCAIACAABEfRAIAxAQAORoCQcAIhJQCOYiAAA=","368":"b:8EeCkKzjAQDk/zcIH5BQzOx/KUfwP/9/mP+/BwA=","395":"b:8EeCkKzjAQDk/zcIH5BQzOx/CUfwP/9/mP+/BwA=","409":[84,85,23,37,183,190,70,137,139,77],"454":"b:gEeSAKSjAQBkZTcIEoBAjGwbOUdQMedLSDYaBAA=","458":"b:gEeCAKSjAQBkZTcIEoBAjGwbOUdQMedLSDYaBAA=","466":"b:gEeCAKSjAQBkZTcIEoBAjGwbOUdQMedLSDYaBAA=","509":"b:gEeSAKSjAQBkZTcIEoBAjGwbOUdQMedLSDYaBAA=","541":"b:8EeSkKzjAQDk/zcIH5BQzOx/OUfwP/9/2P+/BwA=","649":"b:AACSAAABAAAEIDQAAIBAACQCAQAAMIAACAAAAAA=","704":[122,23,91,41],"712":[122,23],"723":[122,23],"726":"b:8E/CkKzjAQDk/zcIH5BQ3Px/PWfwP/9/2P//BwA=","741":"b:6EeCAKiiAABkfTEIBxBQBOR/KAdQO7d/iPY/AgA=","745":"b:6EeCAKiiAABkfTEIBxBQBOR/KAdQO7d/iPY/AgA=","752":"b:4EWCAKiiAABkfTEIBxBQBOR/CAdQM6d/CPY/AgA=","754":"b:YEAAAAiCAAAAGQAAAwAQAIA3AAQAEiMkAOA3AgA=","760":"b:YEAAAAiCAAAAOQAAAwAQAIA3AAQAEiMsgPQ/AgA=","768":"b:YEAAAAiCAAAAGQAAAwAQAIA3AAQAEiMkAPA3AgA=","774":"b:6EeCAKiiAABkfTEIBxBQBOR/KAdQO7d/iPY/AgA=","800":"b:aEYAAAiCAAAAGTAAAwAQAIQ3CAQAOiMlAPA3AgA=","808":"b:6EeCAKiiAABkfTEIBxBQBOR/KAdQO7d/iPY/AgA=","830":[84,69,70,134,201,72,137,205,80,215,216,217],"837":[84,69,70,134,201,72,137,205,80,215,216,217],"879":"b:+EeCkKzjAQDk/zcIH5BQzOx/OUfwP/9/2P+/BwA=","883":[122,40,130,111,172,45,118,66,137,82],"899":[122,40,130,111,172,118,66,137,82],"934":"b:YAEAAAAAAAAAIAAADgAAAEACAAQABAk4AAIGBAA=","938":"b:YAEAAAAAAAAAIAAADgAAAEACAAQABAk4AAIGBAA=","941":"b:YAEAAAAAAAAAIAAADgAAAEACAAQABAk4AAIGBAA=","959":[201],"993":[10,169,116,209,140,97],"1009":"b:6EeCAKiiAABkfTEIBxBQBOR/KAdQO7d/iPY/AgA=","1078":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNcKAQA="},"packages/frontend/editor-ui/src/app/composables/useNodeIconSource.ts":{"6":"b:+E/SkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","12":"b:+EeSkKzjAQDk/3cIH5BQ3Ox/KUfwP79/2P6/BwA="},"packages/frontend/editor-ui/src/app/composables/useNodeType.ts":{"8":"b:+E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","16":"b:4EWCAKiiAABkfXEIBxBQFOx/KAfwO7d/iPY/AwA=","29":"b:4EWCAKiiAABkfXEIBxBQFOx/KAfwO7d/iPY/AwA=","31":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO5d/CPY/AgA="},"packages/frontend/editor-ui/src/app/composables/usePageRedirectionHelper.ts":{"15":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/composables/usePinnedData.ts":{"50":"b:+E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","70":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/BgA=","78":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","83":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/CPY/AgA=","93":"b:4EWCAKiiAADkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","104":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","109":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","126":[86,124],"171":"b:AAAAAAAAAAAAOUAAAgAQEAAQAAAAAAEAAMYGBAA=","175":"b:AAAAAAAAAAAAOUAAAgAQEAAQAAAAAAEAAMYGBAA=","225":"b:AAAAAAAAAAAAOUAAAgAQEAAQAAAAAAEAAMYGBAA=","244":[86,124,97],"266":"b:AAAAAAAAAAAAOUAAAgAQEAAQAAAAAAEAAMYGBAA=","303":[86,124],"316":[86,124]},"packages/frontend/editor-ui/src/app/composables/usePolicyViolationToast.ts":{"28":[86,124],"29":[86,124],"32":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","40":[86,124],"51":[86,124],"57":[86,124],"66":[86,124],"69":[86,124],"84":[86,124],"86":[86,124],"96":[86,124],"107":"b:4EmCAIAiAADk+XcIExAQEOR7CQUAPANlAObuAwA="},"packages/frontend/editor-ui/src/app/composables/usePostMessageHandler.ts":{"40":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","44":"b:8E/CAKDjAQDk/zcIH5BQDOx/P0fwP/9/+P//BwA=","66":"b:8E/CAKDjAQDk/zcIH5BQDOx/P0fwP/9/+P//BwA=","85":[148,149,198],"233":"b:8E/CAKDjAQDk/zcIH5BQDOx/P0fwP/9/+P//BwA=","296":"b:8E/CAKDjAQDk/zcIH5BQDOx/P0fwP/9/+P//BwA=","302":[203,98,79]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/executionFinished.ts":{"70":"b:cEcAEAjDAABAGzAIA5AQyIQ3AAQAPjMlQOC3AwA=","216":"b:cEcAEAjDAABAGzAIA5AQyIQ3AAQAPjMlQOC3AwA=","237":"b:cEcAEAjDAABAGzAIA5AQyIQ3AAQAPjMlAOC3AwA=","243":"b:AEcAEAjBAAAAAxAIA5AAyAQXAAQAFgElACC3AwA=","278":"b:cEcAEAjDAABAGzAIA5AQyIQ3AAQAPjMlQOC3AwA=","308":"b:cEcAEAjDAABAGzAIA5AQyIQ3AAQAPjMlAOC3AwA=","321":"b:cEcAEAjDAABAGzAIA5AQyIQ3AAQAPjMlAOC3AwA=","382":[5,6,84,85,180,72,136,137,205,209,215,216],"465":[5,6,72,215,216],"488":"b:EEcAEAjDAABAGxAIA5AQyIQ3AAQAPiMlQOC3AwA=","509":"b:EEcAEAjDAABAGxAIA5AQyIQ3AAQAPiMlQOC3AwA=","579":"b:cEcAEAjDAABAGzAIA5AQyIQ3AAQAPjMlAOC3AwA="},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/executionStarted.ts":{"13":"b:cEcAEAjDAABAGzAIA5AQyIQ3CAQAPjMlQOC3AwA="},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/nodeExecuteAfter.ts":{"16":"b:cEcAEAjDAABAGzAIA5AQyIQ3CAQAPjMlQOC3AwA=","49":"b:cEcAEAjDAABAGzAIA5AQyIQ3CAQAPjMlQOC3AwA=","50":"b:cEcAEAjDAABAGzAIA5AQyIQ3CAQAPjMlQOC3AwA="},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/nodeExecuteAfterData.ts":{"11":"b:cEcAEAjDAABAGzAIA5AQyIQ3CAQAPjMlQOC3AwA="},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/nodeExecuteBefore.ts":{"9":"b:cEcAEAjDAABAGzAIA5AQyIQ3CAQAPjMlQOC3AwA="},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/trackNodeExecution.ts":{"11":"b:cEcAEAjDAABAGzAIA5AQyIQ3CAQAPjMlQOC3AwA="},"packages/frontend/editor-ui/src/app/composables/usePushConnection/usePushConnection.ts":{"47":"b:8E/CkKzjAQTk/zcIH5BYzOx/P0fwP///+P//BwA=","48":"b:8EeCkIzjAATk+zUIH5BQzOx/C0UAPndl2P7/AwA=","53":[28,127,203,98,79],"62":"b:8EeCkIzjAATk+zUIH5BQzOx/C0UAPndl2P7/AwA="},"packages/frontend/editor-ui/src/app/composables/useResolvedExpression.ts":{"30":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","45":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","52":"b:4EWCAKiiAFBkfXUIBxB0FPR/KC9QO7d/iPY/AgA=","59":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","60":"b:IAAAAAAAAAAACEAAAgAQEAATAAAAEAEgAEAAAAA=","61":"b:IACAACAAABBAfHAAAgAQEAA7AAAAEIVhAMACAAA=","66":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","68":"b:IACAACAAABBAfHAAAgAQEAA7AAAAEIVhAMACAAA=","107":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","160":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","161":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","162":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA="},"packages/frontend/editor-ui/src/app/composables/useRunWorkflow.ts":{"72":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","97":"b:cEcAAAjDAABAG3AIE5AQmIQ3CEQAPjMlQOC3AwA=","100":[86,124],"101":[86,124],"115":[5,6,86,124,173,177,136,137,205,210,140,141],"119":"b:cEcAAAjDAABAG3AIE5AQmIQ3CEQAPjMlQOC3AwA=","120":[86,124],"134":"b:cEcAAAjDAABAG3AIE5AQmIQ3CEQAPjMlQOC3AwA=","138":"b:cEcAAAjDAABAG3AIE5AQmIQ3CEQAPjMlQOC3AwA=","289":"b:cEcAAAjDAABAG3AIE5AQmIQ3CEQAPjMlQOC3AwA=","292":"b:cEcAAAjDAABAG3AIE5AQmIQ3CEQAHjMlQOC3AwA=","298":[86,124],"324":[9,84,10,86,124,184,198,137],"335":[86,124,171,173,70,136,97],"359":[86,124,171,173,70,136,97],"402":[86,124,173,177,205,141],"455":[86,147,124,158,130],"495":"b:cEcAAAjDAABAG3AIE5AQmIQ3CEQAPjMlQOC3AwA=","546":[86,124,136,137],"553":[86,124],"602":[86,124,136,137],"621":[86,124],"630":"b:AEEAAAjBAAAAA1AIE5AAmAQXCEQANhEkACC3AwA=","651":[86,124]},"packages/frontend/editor-ui/src/app/composables/useRunWorkflowApi.ts":{"9":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","14":"b:cEcAAAjDAABAG3AIE5AQmIQ3CEQAPjMlQOC3AwA="},"packages/frontend/editor-ui/src/app/composables/useSelectionValidation.ts":{"32":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","38":"b:8E/CkKjjAQDk/3cIH5BQzOx/DUfwP/9/mP//BwA=","53":"b:4EeCAKgiAADkfXUIDxBQBOx/CAfwP79/iPe/BwA=","70":"b:8E/CkKjjAQDk/3cIH5BQzOx/DUfwP/9/mP//BwA=","77":"b:YAEAACAAAADAIHQADwAAAEAKAAQABAl4AAImBAA=","84":[86,71],"109":"b:8E/CkKjjAQDk/3cIH5BQzOx/DUfwP/9/mP//BwA=","111":"b:4EeCAKgiAADkfXEIDxBQBOx/CAfwP79/iPe/BwA=","115":"b:4EeCAKgiAADkfXEIDxBQBOx/CAfwP79/iPe/BwA=","124":"b:8E/CkKjjAQDk/3cIH5BQzOx/DUfwP/9/mP//BwA=","130":"b:4EeCgKgiAADkfXEIDxBQBOx/CAfwP79/iPe/BwA=","132":"b:4EeCgKgiAADkfXEIDxBQBOx/CAfwP79/iPe/BwA=","139":"b:4EWCgKgiAADkfXEIDxBQBOR/CAdQM4d/iPa/AwA=","141":"b:AAQAgAgAAADEKVAAAwAQAMA4AABAIAUPgGa9AwA="},"packages/frontend/editor-ui/src/app/composables/useSettingsItems.ts":{"29":"b:/k//8777Adzk/zc7H5B8zvz/j///////n///BwA=","228":"b:/k//8777Adzk/zc7H5B8zvz/j///////n///BwA=","229":"b:/k//8777Adzk/zc7H5B8zvz/j///////n///BwA=","232":"b:/k//8777Adzk/zc7H5B8zvz/j///////n///BwA=","237":"b:/k//8777Adzk/zc7H5B8zvz/j///////n///BwA="},"packages/frontend/editor-ui/src/app/composables/useSidebarLayout.ts":{"11":"b:/k//8777AZjk/zc7H5BQzvx/j9/3//9/nf//BwA=","17":"b:/k//8777AZjk/zc7H5BQzvx/j9/3//9/nf//BwA=","27":[88,22,25,44,45]},"packages/frontend/editor-ui/src/app/composables/useTelemetryContext.ts":{"11":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/composables/useTelemetryInitializer.ts":{"13":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","23":[86,124],"27":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","32":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","36":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","40":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","59":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","63":[86,124],"69":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/composables/useUniqueNodeName.ts":{"4":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","11":[84,86,96,134,200,201,135,202,97,141,211,99],"12":[84,86,96,134,200,201,135,202,97,141,211,99],"27":"b:4EGCAKAiAQBkfXUIHxAQAOxrCQfwL5l+CNcuBQA=","34":[84,86,96,134,200,201,135,202,97,141,211,99]},"packages/frontend/editor-ui/src/app/composables/useUserHelpers.ts":{"5":"b:/k//8777Adzk/zc7H5B8zvz/j///////n///BwA=","6":"b:/k//8777Adzk/zc7H5B8zvz/j///////n///BwA=","12":"b:/k//8777Adzk/zc7H5B8zvz/j///////n///BwA="},"packages/frontend/editor-ui/src/app/composables/useWorkflowActivate.ts":{"35":"b:8E/CkKz7AQDk/3cpH5BQ3ux/D0f0f/9/mP//BwA=","44":"b:AAAAEAAwAAAggEMhHAAAkgAAAAAEEAAAAAgAAAA=","57":[86,124],"79":[86,124],"99":[86,124],"111":[86,124,172,69,79,80],"118":[86,124,172,69,79,80],"119":[86,124,172,69,79,80],"134":[86,124,172,69,79,80],"150":[86,124,172,69,79,80],"155":[86,124],"163":[86,124,172,69,79,80],"197":[86,124,172,69,79,80],"314":[86,124,81]},"packages/frontend/editor-ui/src/app/composables/useWorkflowDiffRouting.ts":{"18":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","27":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","33":[86,124],"50":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","73":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","111":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","133":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/composables/useWorkflowExtraction.ts":{"45":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","60":[86,124],"69":[86,124],"81":[86,124],"85":[86,124],"95":[86,124,213],"113":[86,124,213],"115":[86,124,213],"146":[86,124,213],"147":[86,124,213],"151":[86,124],"173":[86,124,213],"184":[86,124,213],"192":[86,124,213],"193":[86,124,213],"199":[86,124,213],"200":[86,124,213],"254":[86,124,213],"279":[86,124,213],"307":[86,124,213],"312":[86,124,213],"313":[86,124,213],"320":[86,124,213],"338":[86,124,213],"342":[86,124,213],"344":[86,124,213],"351":[86,124,213],"352":[86,124],"356":[86,124],"357":[86,124],"370":[86,124],"380":[86,124,213],"383":[86,124,213],"417":[86,124,213],"436":[86,124,213],"455":[86,124,213],"460":[86,124,213],"476":[86,124,213],"479":[86,124,213],"480":[86,124,213],"489":[86,124],"514":[86,124,213],"524":[86,124],"535":[86,124],"568":[86,124,213],"575":[86,124,213],"578":[86,124,213],"583":[86,124,213],"592":[86,124,213],"593":[86,124,213],"599":[86,124,213],"600":[86,124,213],"615":[86,124,213],"644":[86,124,213],"645":[86,124,213],"653":[86,124,213],"660":[86,124,213],"672":[86,124,213],"692":[86,124,213]},"packages/frontend/editor-ui/src/app/composables/useWorkflowHelpers.ts":{"77":"b:IACQACAAABBAfHAAAgAQEAR7KAMQMqVhAOQiAAA=","178":"b:IAAAAAAAAAAACEAAAgAQEAAzAAAAECEgAEAgAAA=","281":[86,124,78,141],"288":[86,124],"295":[86,124],"312":[84,86,152,124,209,77,78,141,213,142],"322":[84,86,152,124,209,77,78,141,213,142],"348":"b:aEEAAAjBAAAAI3AIH5AAmEQXCEQANhk8ACK3BwA=","354":"b:IACAACAAAABAfHAAAgAQEAR7KAMQMqVhAOQiAAA=","385":"b:IAAAAAAAAAAAOEAAAgAQEAAzAAAAECAgAMQgAAA=","401":[86,124,171,173,70,136,97],"427":"b:IACAACAAAABAfHAAAgAQEAR7KAMQOqVhAOQiAAA=","516":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","530":"b:YAEAAAAAAAAAIEAADgAAAEACAAQABAk4AAIGBAA=","556":"b:4EGCAKAiAABAZXEIBxAQAOhrAAfwB4l+CAYGAQA=","570":"b:AACAAAAAAAAAQGAAAgAAAAQBKAMQIAAAACACAAA=","591":"b:AACAAAAAAAAAQEAAAgAAAAQBKAMQIAAAACACAAA=","632":[5,6,86],"635":[5,6,86],"666":"b:IACQACAAABBAfHAAAgAQAAQ7KAMQMKVhAOQCAAA=","696":[86],"742":"b:YAEAAAAAAAAAIEAADgAAAEACAAQABAk4AAIGBAA=","764":[86,70,134,201,97,99,82],"768":[86,70,134,201,97,99],"773":[86],"780":[86],"794":[86],"802":[86],"812":"b:EAYAkAzhAACEo1YAHYBQzGwfMkAAEnYB2Dj3AwA=","850":"b:EAYAkAzhAACEo1YAHYBQzGwfMkAAEnYB2Dj3AwA=","881":[86],"891":[86],"904":[86],"915":[86]},"packages/frontend/editor-ui/src/app/composables/useWorkflowId.ts":{"17":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","20":"b:/k//8777Ad7k/3c7H5B8zvz/////////////BwA=","40":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/composables/useWorkflowImport.ts":{"11":"b:8E/CAKDjAQDk/zcIH5BQDOx/P0fwP/9/+P//BwA=","17":[148,149,198],"19":[148,149,198]},"packages/frontend/editor-ui/src/app/composables/useWorkflowInitialization.ts":{"82":"b:8E/CkKzjAQDk/zcIH5BQzOx/P0fwP/9/+P//BwA=","93":"b:8E/CkKzjAADk/zcIH5BQzOx/D0fwP/9/mP//BwA=","94":"b:8E/CkKzjAADk/zcIH5BQzOx/P0fwP/9/+P//BwA=","95":"b:8E/CkKzjAQDk/zcIH5BQzOx/P0fwP/9/+P//BwA=","96":[48,82,100],"97":"b:8E/CkKzjAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","99":"b:8E/CkKzjAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","124":"b:8E/CkKzjAQDk/zcIH5BQzOx/P0fwP/9/+P//BwA=","209":"b:EAYAkAzhAACEoxYAHYBQzGwfAkAAEnYBmDi3AwA=","226":"b:8E/CkKzjAQDk/zcIH5BQzOx/P0fwP/9/+P//BwA=","228":"b:8E/CkKzjAQDk/zcIH5BQzOx/P0fwP/9/+P//BwA=","264":"b:EAYAkAzhAACEoxYAHYBQzGwfAkAAEnYBmDi3AwA=","319":"b:4EnCAKAiAABg/TMIBxAQCORrPQfwL4l+aMdOBQA=","334":"b:4EnCAKAiAABg/TMIBxAQCORrPQfwL4l+aMdOBQA=","367":"b:EAYAkAzhAACEoxYAHYBQzGwfAkAAEnYBmDi3AwA=","422":"b:8E/CkKzjAQDk/zcIH5BQzOx/P0fwP/9/+P//BwA=","492":[28,127,203,98,79]},"packages/frontend/editor-ui/src/app/composables/useWorkflowNormalization.ts":{"22":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","26":"b:+EeCkKzjAQDk/3cIH5BQzOx/OUfwP/9/2P+/BwA=","46":"b:+EeCkKzjAQDk/3cIH5BQzOx/OUfwP/9/2P+/BwA=","58":"b:+EeCkKzjAQDk/3cIH5BQzOx/OUfwP/9/2P+/BwA=","76":"b:GAYAkAzhAACEo1YAHYBQzGwfMkAAEnYB2Dj3AwA=","81":"b:GAYAkAzhAACEo1YAHYBQzGwfMEAAEnYB0Di3AwA=","82":"b:GAYAkAzhAACEo1YAHYBQzGwfMEAAEnYB0Di3AwA=","83":"b:GAYAkAzhAACEo1YAHYBQzGwfMEAAEnYB0Di3AwA=","85":"b:GAYAkAzhAACEo1YAHYBQzGwfMEAAEnYB0Di3AwA="},"packages/frontend/editor-ui/src/app/composables/useWorkflowPublicationStatusSync.ts":{"26":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","35":[172,43,69,79,80],"38":[43],"49":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","54":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","76":[123,43,47],"77":[43],"84":[43],"98":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","104":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","105":[123,172,43,47,69,79,80],"111":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","114":[43],"117":[28,127,43,45,203,98,79]},"packages/frontend/editor-ui/src/app/composables/useWorkflowSaving.ts":{"51":[86,124],"66":[86,124],"99":[86,124],"109":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","148":[86,124],"182":[86,124],"185":[86,124],"194":[86,124],"219":[86,124],"286":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","287":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","291":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","316":"b:4EGCAKAiAADkfXMIDxAQEOx7CQfwL5t/CPfuBwA=","335":[86,124,45,203,72,98,79,216,217,100],"338":[86,124],"339":[86,124,98],"402":[86,124],"412":"b:4EmCAIAiAADkeXcIExAQEOR7CQUALANlAObuAwA=","419":"b:4EmCAIAiAADkeXcIExAQEOR7CQUALANlAObuAwA=","449":"b:4EmCAIAiAADkeXcIExAQEOR7CQUALANlAObuAwA=","569":"b:4EmCAIAiAABgeXcIExAAEORrCQUALAFkAMZOAQA=","629":[86,124],"637":[86,124],"639":[86,124],"645":[86,124],"746":[86,124],"804":"b:4AGCAIAgAADkaXcIAxAQEOR7AQUAIAFkAEbuAwA=","818":"b:gAGCAIAgAADkaVcAAxAAEORoAQEAIABAAEZqAwA=","838":"b:4EGCAKAiAADkfXcIDxAQEOx7CQfwL5t/CPfuBwA=","847":"b:YEkAAAACAABgGXAIFxAQEIQzCQQALAMlAOCmAQA=","866":[86,148,149,124,28,126,35,127,45,198]},"packages/frontend/editor-ui/src/app/composables/useWorkflowUpdate.ts":{"39":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","58":[144,86,124],"60":[144,86,124],"63":[144,86,124],"70":[144,86,124],"93":[144,86,124],"106":[144,86,124],"183":[144,86,124],"192":[144,86,124],"196":[144,86,124],"211":[144,86,124],"236":[144,86,124],"248":[144,86,124],"249":[144,86,124],"253":[144,86,124],"255":[144,86,124],"279":[144,86,124],"313":[144,86,124],"325":[144,86,124],"340":[144,86,124],"348":[144,86,124],"367":[144,86,124]},"packages/frontend/editor-ui/src/app/composables/useWorkflowsCache.ts":{"24":"b:8E+CkIzrAADk+zcIH5BQzOx/C0UAPndlmP7/AwA=","27":"b:8E+CkIzrAADk+zUIH5BQzOx/C0UAPndlmP7/AwA=","32":"b:8E+CkIzrAADk+zcIH5BQzOx/C0UAPndlmP7/AwA=","36":"b:8E+CkIzrAADk+zcIH5BQzOx/C0UAPndlmP7/AwA=","43":[123,172,43,47,69,80],"58":[123,172,43,47,69,79,80],"69":[43],"78":[43]},"packages/frontend/editor-ui/src/app/constants/actions.ts":{"1":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/constants/experiments.ts":{"16":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/constants/localStorage.ts":{"18":[86,18,155,19,156,20,21,124],"20":[86,18,155,19,156,20,21,124],"22":[1,2,86,124],"26":[86,18,155,19,156,20,21,124],"28":[86,124],"33":[86,124],"38":[86,124],"48":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/D0fwP/9/mP//BwA=","50":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/D0fwP/9/mP//BwA=","52":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/D0fwP/9/mP//BwA=","54":[86,124]},"packages/frontend/editor-ui/src/app/constants/navigation.ts":{"9":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/constants/nodeCreator.ts":{"27":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNcOAQA="},"packages/frontend/editor-ui/src/app/constants/workflows.ts":{"16":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/dev/render-tracker.ts":{"38":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","47":[86,124],"67":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","78":[86,124],"83":[86,124],"86":[86,124],"94":[86,124]},"packages/frontend/editor-ui/src/app/init/expressionEngine.ts":{"19":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/init/index.ts":{"52":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","116":"b:/k//8777Ad7k/3c7H5B83vz/v///////////BwA=","136":[86,143,22,124,193,63],"157":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","197":[86,22,124],"208":[86,124],"219":"b:/k/38777Ad7k/3c7H5B83vz/j///////n///BwA=","226":[86,124],"260":[86,124],"270":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","283":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","329":[86,124]},"packages/frontend/editor-ui/src/app/init/toastNotifier.ts":{"19":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","20":"b:cEeyAgD7AJzA+3YoD5AQGvQ3ADwD/rOlV+D3AwA="},"packages/frontend/editor-ui/src/app/layouts/BaseLayout.vue":{"4":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","10":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","13":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/layouts/WorkflowLayout.vue":{"34":"b:8E/CAKDjAQDk/zcIH5BQDOx/D0fwP/9/mP//BwA=","35":"b:8E/CAKDjAQDk/zcIH5BQDOx/D0fwP/9/mP//BwA=","36":[9,84,85,10,182,184,137,217],"63":"b:8E/CAKDjAQDk/zcIH5BQDOx/D0fwP/9/mP//BwA=","72":[45,48,98,79,82,100],"85":[72],"93":[203,98,79],"102":"b:8E/CAKDjAQDk/zcIH5BQDOx/D0fwP/9/mP//BwA=","104":"b:8E/CAKDjAQDk/zcIH5BQDOx/D0fwP/9/mP//BwA=","106":"b:8E/CAKDjAQDk/zcIH5BQDOx/D0fwP/9/mP//BwA=","116":"b:8E/CAKDjAQDk/zcIH5BQDOx/DUfwP/9/mP//BwA=","119":"b:8E/CAKDjAQDk/zcIH5BQDOx/D0fwP/9/mP//BwA="},"packages/frontend/editor-ui/src/app/modals.manifest.ts":{"20":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","21":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","39":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","40":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA="},"packages/frontend/editor-ui/src/app/models/history.ts":{"8":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","38":"b:4EGCAKAiAADkfXEIDxAQEOxrCQfwL5l/CPeuBwA=","47":[86,124],"55":"b:4EmCAKAiAADkfXEIDxAQEOxrCQfwL5l/CPeuBwA=","60":"b:YEEAAAACAABAGXAIAxAAEIQjCAQALBElAOCmAwA=","61":"b:YEEAAAACAABAGXAIAxAAEIQjCAQALBElAOCmAwA=","72":[144,86,124,184,186,187,70,96,71,201,99],"84":[86,124,201],"88":[86,124,186,187,70,71],"99":[86,124,201],"100":[86,124,201],"113":"b:4EGCAKAiAABkfXEIDxAQEOxrCQfwL5l+CNcuBQA=","118":[86,124,201,213],"122":"b:4EGCAKAiAABkfXEIBxAQEORqCQdQJ4l+CNYuBAA=","126":[86,124,201,213],"127":[86,124,201,213],"137":[86,124,179,180,70,96,71,201,137,213],"142":[86,124,201,213],"146":[86,124,96,201,213],"150":[86,124,201,213],"151":[86,124,201,213],"161":"b:4EGCAKAiAADkfXEIBxAQEORqCQdQJ4l+CNYuBAA=","166":[86,124,201,213],"170":"b:YAAAAAAAAADAIGAAAwAAEAACAQBABAksAAImBAA=","180":[86,124,201,213],"181":[86,124,201,213],"191":"b:AAAAAAAAAADAAEAAAQAAEAACAQAAABgMAAIgAAA=","196":[86,124,201,213],"200":"b:AAAAAAAAAADAAEAAAQAAEAACAQAAABgMAAIgAAA=","210":[86,124,201,213],"211":[86,124,201,213],"212":[86,124,201,213],"227":"b:AAAAAAAAAABgAVEAAAAAEEACAAAAAAAAACKAAwA=","234":[86,124,201],"238":[86,124,134,201],"244":[86,124,201],"245":[86,124,201],"260":[86,124,134],"266":[86,124],"270":[86,124],"278":[86,124],"279":[86,124],"290":[86,124,187,213],"299":[86,124,213],"308":[86,124,187],"317":[86,124,213],"318":[86,124,213],"329":[86,124,71],"333":[86,124],"339":[86,124],"346":[86,124,71],"351":[86,124],"355":[86,124],"361":[86,124],"362":[86,124],"372":[86,124,71],"377":[86,124],"381":[86,124,71],"387":[86,124],"388":[86,124],"400":[86,124,71],"406":[86,124],"410":[86,124,71],"418":[86,124],"419":[86,124]},"packages/frontend/editor-ui/src/app/moduleInitializer/moduleInitializer.ts":{"25":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","26":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","27":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","36":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","38":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","56":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","58":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","73":"b:DgAB8x4AAEAAAEAQAAAk0AAAAIAPAAAAAAAAAAA=","80":[86,124],"105":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","106":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","107":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","110":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","123":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","125":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","135":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","136":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","137":[86,124],"152":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","153":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","154":[86,124],"161":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","170":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","187":[86,124,117,114,62],"197":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","200":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","201":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/plugins/cache.ts":{"3":"b:8E+CkIzrAADk+zcIH5BQzOx/C0UAPndlmP7/AwA=","8":"b:8E+CkIzrAADk+zcIH5BQzOx/C0UAPndlmP7/AwA=","9":"b:8E+CkIzrAADk+zcIH5BQzOx/C0UAPndlmP7/AwA=","10":"b:8E+CkIzrAADk+zcIH5BQzOx/C0UAPndlmP7/AwA=","13":"b:8E+CkIzrAADk+zcIH5BQzOx/C0UAPndlmP7/AwA=","25":[43],"33":"b:8E+CkIzrAADk+zcIH5BQzOx/C0UAPndlmP7/AwA=","34":"b:8E+CkIzrAADk+zcIH5BQzOx/C0UAPndlmP7/AwA=","36":"b:8E+CEIzrAADk+zcIF5BQzOx/C0UAPndlmO7/AwA=","39":"b:8E+CkIzrAADk+zcIH5BQzOx/C0UAPndlmP7/AwA=","40":[43],"44":[123,172,43,47,69,80],"49":"b:8E+CkIzrAADk+zUIH5BQzOx/C0UAPndlmP7/AwA=","53":[43],"58":[43],"63":[43],"67":[43],"68":[43],"71":[43],"82":[43],"89":"b:8E+CkIzrAADk+zcIH5BQzOx/C0UAPndlmP7/AwA=","99":"b:8E+CkIzrAADk+zcIH5BQzOx/C0UAPndlmP7/AwA=","100":"b:8E+CkIzrAADk+zUIH5BQzOx/C0UAPndlmP7/AwA=","104":[43],"111":[123,172,43,47,69,80],"112":[123,172,43,47,69,80],"117":[43],"118":[43],"123":[43],"124":[43]},"packages/frontend/editor-ui/src/app/plugins/chartjs.ts":{"15":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/plugins/components.ts":{"10":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/plugins/directives.ts":{"5":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/plugins/sentry.ts":{"33":[86,124,57],"36":[86,124,57],"60":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/plugins/telemetry/index.ts":{"31":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","46":"b:/k//8777Ad7k/3c7H5B83vz/v///////////BwA=","50":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","55":[86,124],"85":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","119":"b:8E//8777AZTk/3c5H5Bc3Px/j///////2///BwA=","149":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","179":[86,124],"183":[86,124],"186":[86,124],"191":[86,124],"205":[86,124],"221":"b:QEGCAIACAABEfVAIAxAQEORoCAcAIhJQCOYiAAA=","247":[86,124],"266":[86,124],"267":[86,124],"283":[86,124],"309":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/plugins/vitePreloadError.ts":{"4":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","5":[86,124],"14":[86,124]},"packages/frontend/editor-ui/src/app/push-connection/useEventSourceClient.ts":{"13":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","17":[86,124,46],"22":[86,124],"32":[86,124,46],"36":[86,124,46],"46":[86,124,46],"59":[86,124],"64":[86,124,46]},"packages/frontend/editor-ui/src/app/push-connection/useHeartbeat.ts":{"12":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","17":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","21":[86,156,124,203]},"packages/frontend/editor-ui/src/app/push-connection/useReconnectTimer.ts":{"14":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","21":[86,124],"27":[86,124],"33":[86,156,124,203],"40":"b:/k//8L7jAQTk/3cYH5BY3Ox/D9/3P///2P//BwA="},"packages/frontend/editor-ui/src/app/push-connection/useWebSocketClient.ts":{"24":"b:/k//8767Ad7k/3c7H5B83vz/////////////BwA=","35":[86,20,124],"40":"b:/k//8L6jAQTk/3cYH5BY3Ox/D9/3P///2P//BwA=","47":[86,124],"53":"b:9ke+kIyjAATk+3UIH5BQ3Ox/C10APndl2P7/AwA=","57":[86,124],"61":"b:/k//8L6jAQTk/3cYH5BY3Ox/D9/3P///2P//BwA=","75":"b:/k//8L6jAQTk/3cYH5BY3Ox/D9/3P///2P//BwA=","89":[86,124],"94":"b:9k+CkIyjAADk+3UIH5BQ3Ox/C0UAPndlmP7/AwA="},"packages/frontend/editor-ui/src/app/router.ts":{"35":[86,124],"36":[86,124],"37":[86,124],"38":[86,124],"39":[86,124],"40":[86,124],"41":[86,124],"42":[86,124],"43":[86,124],"44":[86,124],"46":"b:8E/CAKDjAQDk/3cIH5BQHOx/PUfwP/9/2P//BwA=","47":[84,86,124,47,72,136,73,137,215,216,217],"48":[84,86,124,47,72,136,73,137,215,216,217],"49":[84,86,124,72,136,73,137,215,216,217],"50":[84,86,124,72,136,73,137,215,216,217],"53":[86,124,47,72,136,73,137,215,216,217],"54":[86,124,47,72,136,73,137,215,216,217],"55":[86,124],"56":[86,124],"57":[86,143,124,193,63],"58":[86,143,124,193,63],"59":[86,124,194],"60":[86,124,194],"61":[86,124],"62":[86,124,191,58],"63":[86,124,191,58],"64":[86,22,124],"65":[86,22,124],"66":[86,124],"67":[86,16,151,124,63],"68":[86,124],"69":[86,124,82],"70":[86,124,82],"71":[86,124,100],"72":[86,124,100],"73":[86,124,82],"74":[86,124,82],"75":[86,124,100],"76":[86,124,100],"77":[86,124],"78":[86,124],"79":[86,124],"80":[86,124],"81":[86,124],"82":[86,124],"83":[86,124],"84":[86,124,59],"85":[86,124,59],"86":[86,124,60],"91":[86,124,60],"96":[86,124],"100":[86,124,115],"101":[86,124,115],"102":[86,124,203],"103":[86,124,203],"104":[86,124,100],"105":[86,124,69],"106":[86,124,69],"107":[86,124],"108":[86,124],"109":[145,86,124],"110":[145,86,124],"111":[145,86,124,69],"112":[145,86,124,69],"113":[86,124],"114":[86,124],"115":[86,124],"116":[86,124],"117":[86,124],"119":[86,124,47],"120":[86,124,47],"124":[86,124],"125":[86,124],"127":[86,124],"128":[86,124],"130":[86,124],"142":[86,124],"164":[86,124],"165":"b:AAAJMAwAAAAAAEASAAAA0AAAAIADAAAAAAAAAAA=","189":[86,124],"212":[86,124],"234":[86,124],"246":[86,124,48,82],"268":[86,124],"275":[86,124,100],"280":[86,124,100],"296":[86,124],"312":[86,124],"430":[86,124],"445":"b:4EnCAKAiAQBg/XcIFxAQGORrDQfwL4l+CMdOBQA=","465":[86,148,149,124,198],"476":[86,124,197],"482":[86,124,197],"605":[86,150,124],"624":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA=","631":[86,124],"642":[86,124],"670":[86,124],"686":[86,124],"707":[86,124],"728":[86,124],"746":[5,6,7,8,144,86,146,11,124,131],"753":[86,124],"765":[86,124],"774":[86,124],"781":[86,124],"806":"b:/k/38777Adzk/3c5F5B83vz/j///////n///BwA=","813":[86,124],"824":[86,124],"835":[86,124],"846":[86,124],"856":[86,124],"872":[86,124],"877":[86,124],"882":[86,124],"888":[86,124],"904":[86,124],"921":[86,124],"926":[86,124],"931":[86,124],"944":[86,124],"960":[86,124],"981":[86,124],"1002":[86,124],"1023":[86,124],"1041":[86,124],"1050":[86,124],"1081":"b:/k/38777Adzk/3c5F5B83vz/j///////n///BwA=","1114":[86,124],"1157":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","1172":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","1182":[86,16,151,124,63],"1186":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","1226":[86,16,124,194],"1265":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA="},"packages/frontend/editor-ui/src/app/stores/aiGateway.store.ts":{"17":[86,124],"18":[86,124],"22":[86,124],"38":"b:/k//8777Adzk/3c7H5B83vz/r///////n///BwA=","42":[86,124],"44":[86,124],"46":[86,124],"64":[86,124],"70":[86,124],"74":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","81":"b:/k//8777Adzk/3c7H5B83vz/r///////n///BwA=","88":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","101":[86,124],"105":[86,124],"107":[86,124],"120":[86,124],"132":[86,124],"143":[86,124],"154":[86,124],"162":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","173":[86,124],"191":[86,124],"206":[86,124],"215":[86,124],"226":[86,124],"243":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","245":"b:AACSAAAgAAAAIHAIAABAFCQCAQAAIIAACAAAAAA=","248":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","265":"b:gACSAIAgAAAgaEEAAgBAEGQ0CAFQISUACEQOAAA=","279":[86,124]},"packages/frontend/editor-ui/src/app/stores/aiSimulatedExecutions.store.ts":{"21":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","24":[86,124],"36":"b:YEQAAAiCAAAAEUAAAgAQEIQ3CAQAOgIgAKA3AgA="},"packages/frontend/editor-ui/src/app/stores/backendConnection.store.ts":{"7":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","10":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/stores/canvas.store.ts":{"6":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","13":"b:EAYAEAAgAADAAEAAAAAAkEACAAEAIAABgAEmAAA=","20":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","27":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/DUfwP/9/2P//BwA=","28":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/DUfwP/9/2P//BwA="},"packages/frontend/editor-ui/src/app/stores/executionData.store.ts":{"59":"b:+E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","66":"b:+E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","75":[86,124,137,216,217],"85":"b:+E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","86":"b:+E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","95":"b:+E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","99":"b:YEAAAAgCAAAAGUAAAwAQEIQ3CAQAOjMkAOA3AAA=","101":"b:cEcAEAjDAABAG3AIA5AQ2IQ3AAQAPjMlQOC3AwA=","116":"b:cEcAEAjDAABAG3AIE5AQ2IQ3CEQAPjMlQOC3AwA=","133":"b:eEcAEAjDAABAG3AIA5AQ2MQ3CAQAPjMlQPC3AwA=","136":"b:eEcAEAjDAABAG3AIA5AQ2MQ3CAQAPjMlQPC3AwA=","139":[86,124],"142":[5,6,86,124,173,177,137,205,210,140,141,216],"145":[5,6,86,124,173,177,137,205,210,140,141,216],"151":"b:+E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","159":"b:+E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","190":"b:+E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","192":"b:eEcAEAjDAABAG3AIE5AQ2MQ3CEQAPjMlQPC3AwA=","196":"b:cEcAEAjDAABAG3AIE5AQ2IQ3CEQAPjMlQOC3AwA=","200":"b:+E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","219":"b:cEcAEAjDAABAG3AIE5AQ2IQ3CEQAPjMlQOC3AwA=","236":"b:cEcAEAjDAABAG3AIE5AQ2IQ3CEQAPjMlQOC3AwA=","246":"b:cEcAEAjDAABAG3AIE5AQ2IQ3CEQAPjMlQOC3AwA=","255":"b:cEcAEAjDAABAG3AIA5AQ2IQ3AAQAPjMlQOC3AwA=","264":"b:cEcAEAjDAABAG3AIE5AQ2IQ3CEQAPjMlQOC3AwA=","302":"b:eEcAEAjDAABAG3AIE5AQ2MQ3CEQAPjMlQPC3AwA=","308":"b:eEcAEAjDAABAG3AIE5AQ2MQ3CEQAPjMlQPC3AwA=","311":"b:cEcAEAjDAABAG3AIE5AQ2IQ3CEQAPjMlQOC3AwA=","321":"b:cEcAEAjDAABAG3AIE5AQ2IQ3CEQAPjMlQOC3AwA=","326":"b:cEcAEAjDAABAG3AIE5AQ2IQ3CEQAPjMlQOC3AwA=","331":"b:cEcAEAjDAABAG3AIE5AQ2IQ3CEQAPjMlQOC3AwA=","340":"b:cEcAEAjDAABAG3AIA5AQ2IQ3AAQAPjMlQOC3AwA=","344":[86,124,213],"347":[86,124,213],"357":"b:+E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","365":"b:+E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","381":"b:+E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","391":"b:cEYAEAjDAAAAC3AIA5AQ2IQ3CEQANjMlAHC3AwA=","482":"b:eEcAEAjDAABAG3AIE5AQ2MQ3CEQAPjMlQPC3AwA=","502":"b:cEcAEAjDAABAG3AIA5AQ2IQ3CAQAPjMlQOC3AwA=","510":[86,124],"524":"b:cEcAEAjDAABAG3AIA5AQ2IQ3AAQAPjMlAOC3AwA=","528":"b:eEcAEAjDAABAG3AIE5AQ2MQ3CEQAPjMlQPC3AwA=","542":"b:cEcAEAjDAABAG3AIA5AQ2IQ3CAQAPjMlQOC3AwA=","550":"b:cEcAEAjDAABAG3AIA5AQ2IQ3CAQAPjMlQOC3AwA=","565":[86,124,136,137],"570":"b:cEcAEAjDAABAG3AIA5AQ2IQ3CAQAPjMlQOC3AwA=","589":[10,86,14,124,130,172,137,210,140,212,213],"594":[10,86,14,124,130,172,137,210,140,212,213],"613":"b:cEcAEAjDAABAG3AIA5AQ2IQ3CAQAPjMlQOC3AwA=","617":[86,124],"632":"b:cEcAEAjDAABAG3AIA5AQ2IQ3CAQAPjMlQOC3AwA=","635":"b:cEcAEAjDAABAG3AIA5AQ2IQ3CAQAPjMlQOC3AwA=","643":[86,124,216],"650":[86,124],"670":[86,124],"671":[86,124],"675":[86,124],"687":[86,124],"688":[86,124],"696":[86,124],"740":[86,124,136,137],"748":[86,124,136,137],"760":[86,124],"811":"b:+E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA="},"packages/frontend/editor-ui/src/app/stores/favorites.store.ts":{"9":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","16":[86,124],"17":[86,124],"20":[86,124],"21":[86,124],"24":[86,124],"25":[86,124],"28":[86,124],"29":[86,124],"32":[86,124],"33":[86,124],"36":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","46":"b:9k/ik6z7ARDk/3cpH5BQ3ux/D0f0//9/mP//BwA=","47":[86,124],"52":[1,2,86,124,24,174,175,45],"53":[86,124],"61":[86,124],"68":[86,124],"86":[86,124,79,81],"87":[86,124],"92":[86,124]},"packages/frontend/editor-ui/src/app/stores/focusPanel.store.ts":{"47":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","49":[86,124],"54":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","64":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","71":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","72":[86,124,188,199],"73":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","76":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","78":[86,124],"98":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","104":[86,124,188,199],"139":"b:4EmCAIAiAABgeXcIExAAEORrCQUALAFkAMZOAQA=","155":[86,124],"163":[86,124],"167":[86,124],"171":[86,124],"175":[86,124,188,199],"179":[86,124],"183":[86,124],"189":[86,124],"193":[86,124,188,199],"196":[86,124],"204":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","205":[86,124,188,199],"217":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","221":[86,124],"229":[86,124]},"packages/frontend/editor-ui/src/app/stores/history.store.ts":{"10":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","17":[86,124,201,213],"24":"b:4EGCAKAiAADkfXEIDxAQEOxrCQfwL5l/CPeuBwA=","28":"b:4EGCAKAiAADkfXEIBxAQEORqCQdQJ5l+CNYuBAA=","41":[86,124,201],"48":"b:4EGCAKAiAADkfXEIDxAQEOxrCQfwL5l/CPeuBwA=","53":[86,124,201,213],"58":"b:8E/CkKzjAADk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","61":"b:8E/CkKzjAADk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","64":"b:8E/CkKzjAADk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","68":[86,124,201],"74":[86,124,201,213],"78":"b:4EmCAKAiAADkfXEIDxAQEOxrCQfwL5l/CPeuBwA=","81":"b:4EmCAKAiAADkfXEIDxAQEOxrCQfwL5l/CPeuBwA="},"packages/frontend/editor-ui/src/app/stores/logs.store.ts":{"18":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","24":"b:8E/D8L7jAQDk/3cYH5BQ3Ox/D8f3P/9/2P//BwA=","52":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/DUfwP/9/2P//BwA=","56":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","60":[9,84,10,86,124,45,198,137],"64":[9,84,10,86,124,45,198,137],"68":"b:8E/D8L7jAQDk/3cYH5BQ3Ox/D8f3P/9/2P//BwA=","72":[86,124],"76":[9,84,85,10,86,124,184,137,217],"80":[86,124,137],"101":[86,124],"122":[86,124],"126":[9,84,85,10,86,124,184,198,137],"132":"b:8E/D8L7jAQDk/3cYH5BQ3Ox/D8f3P/9/2P//BwA=","133":[9,84,85,10,86,124,184,137,217],"136":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","137":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/DUfwP/9/2P//BwA=","138":"b:AAaAACAAAAAAAHAAAAAAEAgKAAAAAMBBQAAAAAA=","139":[9,84,85,10,86,124,182,184,198,137]},"packages/frontend/editor-ui/src/app/stores/nodeTypes.store.ts":{"41":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","58":"b:4EWCAKiiAABkfXEIBxBQFOx/KAfwO7d/iPY/AwA=","59":"b:4EWCAKiiAABkXXEIBxBQFOx/KAfwO7d/iPY/AwA=","77":"b:8E/SkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","79":"b:8EXCAICiAQDk/3cIHxBQHOx9DUfwP/9/mP//BwA=","80":"b:8EXCAICiAQDk/3cIHxBQHOx9DUfwP/9/mP//BwA=","83":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","85":"b:oACCAIAiAABkeXEABxAQEOxpCAPwK5BOCNYOAQA=","86":"b:oACCAIAiAABkeXEABxAQEOxpCAPwK5BOCNYOAQA=","89":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","93":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","94":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/D0fwP/9/mP//BwA=","95":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/D0fwP/9/mP//BwA=","99":"b:8E/SkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","101":"b:8E/SkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","109":"b:8E/SkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","116":"b:+E/SkKzjAVDk/3cIH5B03Px/PUfwP/9/+P//BwA=","117":"b:+E/SkKzjAVDk33cIH5B03Px/PUfwP/9/+P//BwA=","132":"b:4EWCAKiiAABkfXUIBxBQFOR/KAdQO7d/iPY/AgA=","133":"b:4EWCAKiiAABkXXUIBxBQFOR/KAdQO7d/iPY/AgA=","138":[84,85,86,124,37,41,190,139,77],"139":[84,85,86,124,37,41,190,139],"150":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","151":"b:8EeCkKzjAQDk33cIH5BQ3Ox/OUfwP/9/+P6/BwA=","163":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","168":"b:+EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","169":"b:+EeCkKzjAQDk33cIH5BQ3Ox/OUfwP/9/+P+/BwA=","175":"b:8EWCAKiiAABkfXEIBxBQFOR/KQdQO7d/iPY/AgA=","176":"b:8EWCAKiiAABkXXEIBxBQFOR/KQdQO7d/iPY/AgA=","179":"b:8EWCAKiiAABkfXEIBxBQFOR/CQdQO7d/iPY/AgA=","191":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO5d/iPY/AgA=","192":"b:4EWCAKiiAABkXXEIBxBQFOR/KAdQO5d/iPY/AgA=","195":"b:4EWCAKiiAABkfXEIBxBQFOR/CAdQO5d/iPY/AgA=","207":[86,124],"208":[86,124],"213":"b:8E/SkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","216":"b:8E/SkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","219":[86,124],"220":[86,124],"226":[84,85,86,20,124,37,190,139,77],"227":[84,85,86,20,124,37,190,139,77],"231":[84,85,86,20,124,37,190,139,77],"252":[84,85,86,20,124,37,190,139,77],"268":[86,124],"269":[86,124],"273":[86,124],"292":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","293":"b:8EeCkKzjAQDk33cIH5BQ3Ox/OUfwP/9/+P6/BwA=","307":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","318":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","326":[86,124],"327":[86,124],"335":[86,124],"339":[86,124],"362":[86,124],"373":[86,124],"385":[86,124],"399":[86,124],"401":[86,124],"409":"b:/k//8777Ad7k/3c7H5B83vz/v///////////BwA=","420":"b:/k//8777Ad7k/3c7H5B83vz/j///////v///BwA=","426":[86,124],"434":[86,152,124,209,77],"438":[84,86,124,78],"442":[86,124,78,141],"450":[86,124,213,142],"458":[86,124],"462":"b:8E/SkKzjAQDk/3cIH5BQ3Ox/P0fwP///+P//BwA=","472":"b:8EXCAICiAQDk/3cIHxBQHOx9P0fwP///+P//BwA=","479":[86,124,39,191,58],"497":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","504":"b:+EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/2P+/BwA=","505":"b:+EeCkKzjAQDk33cIH5BQ3Ox/OUfwP/9/2P+/BwA=","514":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","517":[86,124],"518":"b:eEeAECjDAABAf3AIH5AQ2MR/KUcQPr99YO63BwA="},"packages/frontend/editor-ui/src/app/stores/npsSurvey.store.ts":{"18":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","27":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","35":"b:AAABAACCAAAgYHEBEgB8FBh+iAUYPf+/mCO7BwA=","75":[86,124],"79":"b:gAGCAIAgAADkaVcAAxAAEORoAQEAIABAAEZqAgA=","99":[86,124],"110":[86,124]},"packages/frontend/editor-ui/src/app/stores/posthog.store.ts":{"30":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","47":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","52":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","62":[86,124],"72":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","76":[86,124,37],"81":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA=","88":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","92":[86,124],"94":[145,86,124],"100":[86,124],"118":[144,145,86,124,31,162,48,188,199,82],"131":[86,124],"142":[86,124],"146":[86,124],"150":[86,124],"168":[86,124],"192":[86,124],"193":[86,124],"199":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","261":[86,124],"284":[86,124],"301":[86,124],"312":[86,124],"324":"b:YAEAAAAAAABAIEQADAAAEEACAAQAAAkoAAIEBAA=","359":[86,124],"366":[86,124]},"packages/frontend/editor-ui/src/app/stores/pushConnection.store.ts":{"18":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","36":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","39":"b:AAAAEAggAAAggEEABAAA0AAAABAGEAAAAAgAAAA=","47":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","49":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","67":"b:9ke+kIzjAATk+3UIH5BQ3Ox/C10APndl2P7/AwA=","81":"b:9ke+kIzjAATk+3UIH5BQ3Ox/C10APndl2P7/AwA=","86":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","88":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","94":"b:9k+CkIzjAADk+3UIH5BQ3Ox/C0UAPndlmP7/AwA=","106":"b:/k//8L7jAQTk/3cYH5BY3Ox/D9/3P///2P//BwA=","129":"b:/k//8L7jAQTk/3cYH5BY3Ox/D9/3P///2P//BwA=","136":"b:/k/+sK7jAQTk/3cYH5BQ3Ox/D9/zP///2P//BwA=","157":[86,156,124,203,98,79],"183":[86,156,124,203],"196":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","197":"b:/k//8L7jAQTk/3cYH5BY3Ox/D9/3P///2P//BwA=","218":[86,124,28,127,45,203,98,79],"222":"b:/E//8L7jAQDk/3cYH5BY3Ox/D9/zP/9/2P//BwA="},"packages/frontend/editor-ui/src/app/stores/recentWorkflows.store.ts":{"26":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","34":"b:8E+CkIDrAADk+3cIH5BQHOx/CUUAPndlmP7/AwA=","44":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","61":[86,124,66,213,81],"64":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","89":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","99":"b:8E+CEIDjAADk+3cIH5BQHOx/CUUAPndlmP7/AwA=","106":[86,124],"110":"b:8E+CEIDjAADk+3cIH5BQHOx/CUUAPndlmP7/AwA=","114":"b:oEWCAAAgAADkqVMADxBQFOR/CAUAOjdlAH4/AwA=","143":[86,124,31],"156":[86,124],"164":[86,124],"174":[86,124],"175":[86,124],"176":[86,124],"177":[86,124],"193":[86,124],"194":[86,124],"195":[86,124]},"packages/frontend/editor-ui/src/app/stores/ui.store.ts":{"65":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","67":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","84":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","100":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","104":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","111":[86,124],"131":"b:AgAAwhC4AJiEoEIyHwAAFkQAAAAGwgAAAFAgAAA=","132":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","195":"b:+EeekKzzARDk/3cIH5BQ3Px/OX/wP/9/+P6/BwA=","199":"b:+EeekKzzARDk/3cIH5BQ3Px/OX/wP/9/+P6/BwA=","203":[86,124,192,196,81],"270":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","280":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","282":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","290":"b:8E/KkKzzARDk/3cIH5BQ3Px/PWfwP/9/2P//BwA=","292":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA=","294":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA=","299":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA=","305":"b:EAYAkAzhAACEo1YAH4BQ3GwfAkAAEnYR2Du3AwA=","313":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","314":[86,124],"320":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","325":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","333":[86,124],"337":[86,124],"347":"b:oAiaE4CwAdQg43cIHABkkjADATgAUICAHQrgBwA=","355":[86,124],"358":[86,124],"371":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","372":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","381":"b:gACCAIAgABQAYHQIAAAAEDAAACgAAICAAAAAAAA=","385":"b:gACCAIAgABQAYHQIAAAAEDAAACgAQICAAAAAAAA=","389":"b:gACCAIAgABAAYHQIAAAAEDAAAAgAAIAAAAAAAAA=","393":"b:oACaAAAwANAggEMIAABkEDAAADAAUAAAHQBgAAA=","404":"b:oACaA4CwAdQg4HcIAABkEjAAADgAUICAHQJgBAA=","418":"b:oACaA4CwAdQg4HcIAABkEjAAADgAUICAHQJgBAA=","424":"b:oACaAAAwANAggEMIAABkEDAAADAAUAAAHQBgAAA=","429":"b:oAiaEwCwANQg43cIHABAkDADATgAEICAHQrgBwA=","431":"b:oACaAwCwANQgoHcIAABAEDAAADgAEICAFQJgBAA=","434":[86,124],"444":[86,124],"449":[86,157,23,91,124],"480":"b:gACCAIAgABAAYHQIAAAAEDAAAAgAAIAAAAAAAAA=","532":[86,124,191],"538":[86,124,191,58],"548":[86,124,174],"557":[86,124,44,118],"574":[86,124],"580":[86,124],"587":[86,88,22,124,25,44,45],"594":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","601":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","612":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","625":"b:cEcAEAjDAABAG3AIA5AQ2IQ3AAQAPjMlQOC3AwA=","629":"b:4EGCAKAiAUDkfXcIHxA0EOx7CQfwL5t/CPfuBwA=","637":"b:8E/CkKzjAUDk/3cIH5BU3Ox/P0fwP/9/+P//BwA=","652":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","653":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","654":[86,123,124,172,47,69,79,80],"668":[86,143,124,193,63],"712":"b:gACKAAAwARAAAEQIAAAAEDAAACAAAAAAAAAAAAA=","719":"b:gACKAAAwARAAAEQIAAAAEDAAACAAAAAAAAAAAAA=","720":"b:gACKAAAwABAAAEQIAAAAEDAAACAAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/app/stores/ui.utils.ts":{"4":[86,149,124,197],"12":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","17":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","23":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentActive.ts":{"14":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","17":"b:8E+CEIjjAADke3cIE5AQ2OR/CUcAPjNtwPb/BwA=","21":"b:+E+CkIzjAADk+3cIH5BQ3Ox/O0UAPndl+P7/AwA=","30":"b:+E+CkIzjAADk+3cIH5BQ3Ox/O0UAPndl+P7/AwA=","34":"b:EAYAkAzhAACEo1YAHYBQ3GwfAkAAEnYB2Dj3AwA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentChecksum.ts":{"12":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","17":"b:+E+CkIzjAADk+3cIH5BQ3Ox/O0UAPndl+P7/AwA=","22":"b:+E+CkIzjAADk+3cIH5BQ3Ox/O0UAPndl+P7/AwA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentConnections.ts":{"35":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","46":"b:GAYAkAzhAQCEo1YAHYBQ3GxfM0AAEnYB+Dj3AwA=","52":"b:4EGCAKAiAADkfXEIBxAQEORqCQdQJ4l+CNYuBAA=","74":"b:4EGCAKAiAADkfXEIBxAQEORqCQdQJ4l+CNYuBAA=","117":"b:AAAAAAAAAADAAEAAAQAAEAACAQAAABgMAAIgAAA=","147":[86,124,179,180,70,96,71,201,137,213],"189":[86,124,62],"198":"b:+E/SkKzjARDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","200":"b:+EeSkKzjARDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","204":"b:4EWCAKiiAADkfXUIDxBQFOR/KQdQO79/iPa/AwA=","211":"b:cEcAEAjDAADAG3AIA5AQ2IQ3CQQAPjslQOK3AwA=","222":"b:GAYAkAzhAQCEo1YAHYBQ3GxfM0AAEnYB+Dj3AwA=","226":"b:4EGCAKAiAADkfXEIBxAQEORqCQdQJ4l+CNYuBAA=","230":"b:AAAAAAAAAADAAEAAAQAAEAACAQAAABgMAAIgAAA=","234":[86,124,179,180,70,96,71,201,137,213],"241":[86,124],"247":[86,124,62]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentDescription.ts":{"12":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","17":"b:GAYAkAzhAACEo1YAHYBQ3GwfMkAAEnYB+Dj3AwA=","25":"b:GAYAkAzhAACEo1YAHYBQ3GwfMkAAEnYB+Dj3AwA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentExpression.ts":{"6":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","11":"b:+E/SkKzjARDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentGraph.ts":{"16":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","21":"b:8EeSAKyiAEDkfXUIDxB0FOx/KQfwP79/iPe/BwA=","29":"b:+EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","37":"b:6EWCAKiiAQBkfXUIHxBQFOx/KQfwP79/iPc/BwA=","41":[86,124,213],"48":[86,124,186,187,70],"74":[86,124],"78":[85,10,86,124,184],"82":"b:IACAACAAAABAfHAAAgAQEAR7KAMQMqVhAOQiAAA=","86":"b:IACAACAAAABAfHAAAgAQEAR7KAMQMqVhAOQiAAA=","94":"b:4EWCAKAiAABkfXEIBxBQFOR+CAdQI6dfiPYeAAA=","109":"b:cAQAAAgCAABAGGAAAgAQEIAzAAQAKCIBAOAGAAA=","112":"b:cAQAAAgCAAAAGGAAAgAQEIAzAAQAACIBAOAGAAA=","120":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","123":"b:4EWCAKiiAABkfXEIBxBQFOR/CQdQM4d/iPY/AgA=","132":"b:cAQAAAgCAABAGEAAAgAQEIAzAAQAKCIAAOAGAAA=","134":[86,124]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentHomeProject.ts":{"9":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","14":"b:+E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","22":"b:+E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentIsArchived.ts":{"12":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","17":"b:GAYAkAzhAACEo1YAHYBQ3GwfMkAAEnYB+Dj3AwA=","22":"b:GAYAkAzhAACEo1YAHYBQ3GwfMkAAEnYB+Dj3AwA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentMeta.ts":{"13":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","18":"b:GAaCkAzhAQCk43cAHYBQ3GwfMkAAMvYB+Dj3AwA=","26":"b:GAYAkAzhAACEo1YAHYBQ3GwfMkAAEnYB+Dj3AwA=","30":"b:AACCAAAAAQAgYHUAEAAAECAAAAAAIIAACAAAAAA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentName.ts":{"16":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","21":"b:+E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","27":"b:+E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentNodeGroups.ts":{"41":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","48":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","50":"b:4EeCAKiiAADk/XUIDxBQFOx/KQfwP79/iPe/BwA=","60":"b:GAYAkAzhAACEo1YAHYBQ3GwfMkAAEnYB+Dj3AwA=","61":[86,124,31,71],"68":[86,124,71],"84":[86,124,71],"93":"b:GAYAkAzhAACEo1YAHYBQ3GwfMkAAEnYB+Dj3AwA=","97":[86,124,71],"113":[86,124,71],"114":[86,124],"132":[86,124,71],"136":[86,124,71],"142":[86,124],"150":[86,124,71],"156":[86,124],"161":[86,124,71],"166":[86,124,71],"172":[86,124],"181":[86,124],"188":[86,124,31,71],"192":"b:4EeCAKiiAADk/XUIDxBQFOx/KQfwP79/iPe/BwA=","197":[86,124,179,180,114,62,70,96,71,201,137,213],"200":[86,124,71],"209":[86,148,149,124,28,127,45,62,198,203,98,79]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentNodeMetadata.ts":{"20":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","29":"b:GAYQkAzhAECEo1YAHYBQ3GxfM0AAEnYB+Dj3AwA=","34":"b:+EeSkKzjAUDk/3cIH5B03Ox/OUfwP/9/+P+/BwA=","42":"b:4EWCAKiiAQBkfXUIHxBQFOx/KQfwP79/iPc/BwA=","52":[86,124,72],"65":"b:AAAAAAAAAEDAAEAAAQAkEAACAAAAABgAAAIgAAA=","75":[86,124,134,77,142],"89":"b:GAYQkAzhAECEo1YAHYBQ3GxfM0AAEnYB+Dj3AwA=","94":"b:4EGCAKAiAUBkfXUIHxA0EOxrCQfwL5l+CNcuBQA=","100":"b:GAYQkAzhAACEo1YAHYBQ3GxfMUAAEnYB8Di3AwA=","105":"b:AAAAAAAAAEDAAEAAAQAkEAACAAAAABgAAAIgAAA=","109":[86,124,134,77,142],"113":"b:4EWCAKiiAQBkfXUIHxBQFOx/KQfwP79/iPc/BwA=","117":"b:QEGAAIACAABEfVAIAxAQEMRgCQdQIhJYAOYiAAA=","124":[86,124],"131":[86,124],"138":[86,124,72],"142":"b:cEcAEAjDAABAG3AIA5AQ2IQ3CAQAPjMlQOC3AwA=","146":"b:cEcAEAjDAAAAG3AIA5AQ0IQ3CAQANjMlQOC3AwA=","150":"b:cEcAEAjDAABAG3AIA5AQ2IQ3CAQAPjMlQOC3AwA=","154":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentNodes.ts":{"75":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","91":"b:4EGCAKQiAQDkfXUIGxBUFOR7CQdQI7dfCOaqBwA=","115":"b:GAYQkAzhAACEo1YAHYBQ3GxfM0AAEnYB+Dj3AwA=","139":"b:GAYQkAzhAACEo1YAHYBQ3GxfMUAAEnYB8Di3AwA=","143":"b:4EGCAKAiAUBkfXUIHxA0EOxrCQfwL5l+CNcuBQA=","163":[86,124,117,114,62],"164":[86,124,114,62],"178":[86,124,179,180,70,96,71,201,137,213],"179":[86,124,179,180,70,96,71,201,137,213],"180":[86,124,179,180,70,96,71,201,137,213],"199":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","223":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","238":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","252":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","266":"b:+EeSkKzjAUDk/3cIH5B03Ox/OUfwP/9/+P+/BwA=","269":"b:+EeSkKzjAUDk/3cIH5B03Ox/OUfwP/9/+P+/BwA=","272":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","276":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","279":"b:AAAAAAAAAEDAAEAAAQAEEAACEAAAABgAAAIgAAA=","282":"b:AAAAAAAAAEDAAEAAAQAEEAACEAAAABgAAAIgAAA=","289":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","297":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","298":"b:GAYQkAzhAACEo1YAHYBQ3GxfMUAAEnYB8Di3AwA=","299":"b:GAYQkAzhAACEo1YAHYBQ3GxfMUAAEnYB8Di3AwA=","305":"b:+EeSkKzjAUDk/3cIH5B03Ox/O0fwP/9/+P//BwA=","339":"b:+EeSkKzjAUDk/3cIH5B03Ox/O0fwP/9/+P//BwA=","365":[86,124],"367":"b:4EGCAKAiAQBkfXUIHxAQEOxrCQfwL5l+CNcuBQA=","369":"b:8E/SkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","370":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/2P+/BwA=","376":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNcOAQA=","377":"b:oECCAKAiAABkfXEIBxAQEOxoCAHgIJBOCNYOAAA=","384":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","388":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","392":"b:4EWCAKAiAABkfXEIBxBQFOR/CAdQO7d/CPY/AAA=","393":"b:4EWCAKAiAABkfXEIBxBQFOR/CAdQO7d/CPY/AAA=","396":"b:AAAAAAAAAABgAVUACgAAEEACAAAAAAAAACKAAwA=","404":"b:GAYQkAzhAACEo1YAHYBQ3GxfM0AAEnYB+Dj3AwA=","408":"b:4EGCAKAiAUBkfXUIHxA0EOxrCQfwL5l+CNcuBQA=","412":[86,124,117,114,62],"416":[86,124,179,180,70,96,71,201,137,213],"420":"b:wEGCAIACAABkfXEIAxAQEORoCAdQIxJYCOYqAAA=","421":"b:wEGCAIACAABkfXEIAxAQEORoCAdQIxJYCOYqAAA=","446":"b:gACCAAAAAABkaGEAAxAAEORgCAFQIRAACEYKAAA=","447":"b:gACCAAAAAABkaGEAAxAAEORgCAFQIRAACEYKAAA=","465":[144,86,124,184,186,187,70,96,71,201,99],"466":[144,86,124,184,186,187,70,96,71,201,99],"489":[144,86,124,184,186,187,70,96,71,201,99],"490":[144,86,124,184,186,187,70,96,71,201,99],"496":[86,124],"497":[86,124],"506":"b:AACCAAAAAABgYXUIAAAEEGACAQAAIIAACCKAAwA=","510":"b:AACCAAAAAABgIXEIAAAEEGACAQAAIIAACCKAAwA=","526":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/2P+/BwA=","527":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/2P+/BwA=","554":[86,124,62],"564":[86,124,72],"565":[86,124,72],"572":[86,124],"577":[86,124],"607":[84,85,86,17,20,23,91,124,173,183,77,78],"614":[84,85,86,17,20,23,91,124,173,183,77],"633":[84,85,86,23,124,183]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentNodesIssues.ts":{"37":[144,86,124],"38":[144,86,124],"39":[144,86,124],"43":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","54":"b:oAaAACCAAQAk+HcAFwAQGAwLCUMQOMRBgOIKBAA=","63":"b:oAaAACCAAQAk+HcAFwAQGAwLCUMQOMRBgOIKBAA=","77":"b:gACAACAAAQAgQHUAEAAAEAQKCQMQIIRAAAAKBAA=","93":"b:oAaAACCAAQAk+HcAFwAQGAwLCUMQOMRBgOIKBAA=","95":[144,86,11,124],"98":[86,124],"101":[144,86,124],"110":[144,86,124],"114":[144,86,124],"136":[86,124],"149":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","155":"b:+EeSkKzjAUDk/3cIH5B03Ox/OUfwP/9/+P+/BwA=","158":"b:+EeSkKzjAUDk/3cIH5B03Ox/OUfwP/9/+P+/BwA=","161":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","164":"b:AAAAAAAAAEDAAEAAAQAEEAACEAAAABgAAAIgAAA=","167":"b:AAAAAAAAAEDAAEAAAQAEEAACEAAAABgAAAIgAAA=","173":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","181":"b:+EeSkKzjAUDk/3cIH5B03Ox/O0fwP/9/+P//BwA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentParentFolder.ts":{"9":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","14":"b:+E/CkKzjAADk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","22":"b:+E/CkKzjAADk/3cIH5BQ3Ox/P0fwP/9/+P//BwA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentPinData.ts":{"38":"b:AAAAAAAAAAAAOUAAAgAQEAAQAAAAAAEAAMYGBAA=","43":"b:AAAAAAAAAAAAOUAAAgAQEAAQAAAAAAEAAMYGBAA=","56":"b:GAYAkAzhAECEo1YAHYBQ3GwfMkAAEnYB+Dj3AwA=","57":"b:AAAAAAAAAAAAIEAAEAAQEAARIAAAAAAAgCAnAAA=","58":"b:AAAAAAAAAAAAIEAAEAAQEAARIAAAAAAAgCAnAAA=","68":"b:6EeCAKiiAABkfXUIDxBQFOR/KAdQO7d/iPY/BgA=","72":"b:AAAAAAAAAAAAOUAAAgAQEAAQIAAAAAEAgOYnBAA=","76":"b:AAAAAAAAAAAAOUAAAgAQEAAQAAAAAAEAAMYGBAA=","79":"b:AAAAAAAAAAAAOUAAAgAQEAAQAAAAAAEAAMYGBAA=","89":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","94":"b:GAYAkAzhAECEo1YAHYBQ3GwfMkAAEnYB+Dj3AwA=","99":"b:AAAAAAAAAAAAOUAAAgAQEAAQAAAAAAEAAMYGBAA=","107":[86,124,201,72],"116":[86,124,134,77,142],"122":[86,124],"123":[86,124],"129":[86,124],"140":"b:GAYAkAzhAECEo1YAHYBQ3GwfMkAAEnYB+Dj3AwA=","144":"b:AAAAAAAAAAAAOUAAAgAQEAAQAAAAAAEAAMYGBAA=","148":[86,124,72],"152":[86,124,134,77,142],"156":"b:+E+SkKzjARDk/3cIH5BQ3Ox/OUfwP/9/+P//BwA=","160":"b:4EWCAKiiAADkfXEIBxBQFOR/KQdQO7d/iPY/AgA=","179":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","185":"b:+EeSkKzjAUDk/3cIH5B03Ox/OUfwP/9/+P+/BwA=","188":"b:+EeSkKzjAUDk/3cIH5B03Ox/OUfwP/9/+P+/BwA=","191":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","194":"b:AAAAAAAAAEDAAEAAAQAEEAACEAAAABgAAAIgAAA=","197":"b:AAAAAAAAAEDAAEAAAQAEEAACEAAAABgAAAIgAAA=","203":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","211":"b:+EeSkKzjAUDk/3cIH5B03Ox/O0fwP/9/+P//BwA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentPublicationStatus.ts":{"6":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","10":"b:8E+CkIzjAADk+3UIH5BQ3Ox/O0UAPndl2P7/AwA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentRenderData.ts":{"81":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","110":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","116":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","126":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","132":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","153":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","174":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","225":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","247":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","263":[86,124,176,187,71,200,136,212,218,100],"275":[86,124],"291":[86,124],"295":[86,124],"299":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","334":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","355":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","358":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","361":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","365":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","369":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","373":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","377":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","381":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","392":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","399":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","402":"b:AAAAEAAgAADgg1AAFQAAkAADEAAAABgAAAqgAwA=","405":[86,148,124,179,180,70,96,71,201,137,213],"418":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","428":"b:4EGCAKSiAADk/XUIHxBQFOx7OQfwL79/SPfuBwA=","461":"b:AAAAEAAgAAAgg1AAFAAAkAADAAAAAAAAQAiAAwA=","473":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","494":[86,124,187,71,200,212],"495":[86,124,176,187,71,200,136,212,218,100],"529":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","532":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","535":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","538":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","541":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","560":[86,124],"563":[86,124],"566":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","569":"b:cEcAEAjDAABAG3AIA5AQ2IQ3AAQAPjMlQOC3AwA=","572":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","575":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","578":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","581":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","584":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","587":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","590":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentScopes.ts":{"13":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","18":"b:+E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","23":"b:+E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentSettings.ts":{"19":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","24":"b:+E+CkIzjAADk+3cIH5BQ3Ox/O0UAPndl+P7/AwA=","33":"b:+E+CkIzjAADk+3cIH5BQ3Ox/O0UAPndl+P7/AwA=","37":[86,124],"41":"b:8E+CEIjjAADke3cIE5AQ2OR/CUUAPjNlwPb/BwA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentSharedWithProjects.ts":{"13":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","18":"b:GAYAkAzhAACEo1YAHYBQ3GwfMkAAEnYB+Dj3AwA=","29":"b:GAYAkAzhAACEo1YAHYBQ3GwfMkAAEnYB+Dj3AwA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentTags.ts":{"15":"b:GAYAkAzhAACEo1YAH4BQ3GwfMkAAFnYZ+Dj3BwA=","16":[86,124,188,98,214,218],"19":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","24":"b:GAYAkAzhAACEo1YAH4BQ3GwfMkAAFnYZ+Dj3BwA=","29":[86,124,214],"30":[86,124],"37":"b:GAYAkAzhAACEo1YAHYBQ3GwfMkAAEnYB+Dj3AwA=","41":[86,124,170,187,188,210,77,97,98,218],"46":[86,124,214]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentTimestamps.ts":{"19":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","26":"b:GAYAkAzhAACEo1YAHYBQ3GwfMkAAEnYB+Dj3AwA=","31":"b:+E+CkIzjAADk+3cIH5BQ3Ox/O0UAPndl+P7/AwA=","36":"b:GAYAkAzhAACEo1YAHYBQ3GwfMkAAEnYB+Dj3AwA=","40":"b:+E+CkIzjAADk+3cIH5BQ3Ox/O0UAPndl+P7/AwA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentUsedCredentials.ts":{"13":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","18":"b:GAYAkAzhAACEo1YAHYBQ3GwfMkAAEnYB+Dj3AwA=","26":"b:GAYAkAzhAACEo1YAHYBQ3GwfMkAAEnYB+Dj3AwA=","27":[86,122,124,40,130,111,172,45,118,66,137,82]},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentVersionData.ts":{"14":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","20":"b:+E+CkIzjAADk+3cIH5BQ3Ox/O0UAPndl+P7/AwA=","32":"b:+E+CkIzjAADk+3cIH5BQ3Ox/O0UAPndl+P7/AwA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentViewport.ts":{"13":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","18":"b:AAAAEAAgAAAgg1YAHAAAkAADMAAAAAAASAiAAwA=","26":"b:AAAAEAAgAAAgg1YAHAAAkAADMAAAAAAASAiAAwA="},"packages/frontend/editor-ui/src/app/stores/workflowDocument/useWorkflowDocumentWorkflowObject.ts":{"12":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","26":"b:CAAAEACgAAAAg0AAFAAAkAADMAAAAAAAYAiAAwA=","46":"b:+EeSkKzjAUDk/3cIH5B03Ox/O0fwP/9/+P//BwA=","50":"b:+EeCkKzjAUDk/3cIH5BQ3Ox/O0dQN/9/+P7/BwA=","54":"b:+E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","58":"b:+E+CkIzjAADk+3cIH5BQ3Ox/O0UAPndl+P7/AwA=","62":"b:YAEAAAAAAAAAIEAADgAAEEBCAQQABAk4AAIGBAA=","81":[144,86,124,134,77,142],"87":[144,86,124,134,77,142]},"packages/frontend/editor-ui/src/app/stores/workflowDocument.store.ts":{"121":"b:+E+CkIzjAADk+3cIH5BQ3Ox/O0UAPndl+P7/AwA=","126":[86,124],"131":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","156":[86,124,47,72,136,73,137,215,216,217],"165":[86,124,47,72,136,73,137,215,216,217],"178":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","192":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","193":"b:/k//8777Ad7k/3c7H5B8zvz/////////////BwA=","203":"b:+E/CkKzjAQDk/3cIH5BQzOx/P0fwP/9/+P//BwA=","217":"b:+E+CkIzjAADk+3cIH5BQzOx/O0UAPndl+P7/AwA=","226":"b:gACCAAAAAABkaGEAAxAAAORgCAFQIRAACEYKAAA=","229":"b:+EeSkKzjAUDk/3cIH5B0zOx/O0fwP/9/+P//BwA=","240":[86],"241":"b:+EeCkKzjAUDk/3cIH5BQzOx/O0dQN/9/+P7/BwA=","258":"b:oAaAACCAAQAk+HcAFwAQCAwLCUMQOMRBgOIKBAA=","259":[84,85,86,23,37,183,190,137,139],"272":[84,85,86,23,37,183,190,137,139],"293":"b:4EGCAKAiAUDkfXUIHxA0AOxrCQfwL5t/CPeuBwA=","294":"b:4EGCAKAiAADkfXEIBxAQAORqCQdQJ5l+CNYuBAA=","295":[86,71],"297":"b:+EeSkKzjAUDk/3cIH5B0zOx/O0fwP/9/+P//BwA=","303":[86,62],"310":"b:8E+CAIjjAADke3cIE5AQiOR/CUUAPjNlQOb/AwA=","311":"b:8EeCAIjjAADke3UIE5AQiOR/CUUAPjNlQOa/AwA=","331":[86,71],"344":"b:+E/CkKzjAQDk/3cIH5BQzOx/P0fwP/9/+P//BwA=","348":"b:CAAAAACAAAAAA0AAEAAAAAADAAAAAAAAIAiAAwA=","401":[86,148,149,28,127,45,198,203,98,79],"443":"b:+EeSkKzjARDk/3cIH5BQzOx/OUfwP/9/+P+/BwA=","460":"b:cE8AEAjDAABAO3AIA5AQyIQ3AQQAPjMlAOa3BwA=","542":"b:CAAQEAAgAAAAgUAAFAAAkAABAAAAAAAAAAgAAwA=","557":[86,124,31],"572":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","574":"b:/k//8777Adzk/zc7H5B83vz/v///////////BwA=","583":"b:/k//8777Adzk/zc7H5B83vz/v///////////BwA=","600":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","604":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA="},"packages/frontend/editor-ui/src/app/stores/workflowExecutionState.store.ts":{"98":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","114":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","115":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","189":[86,124],"199":[86,124],"203":[86,124],"210":"b:cEcAEAjDAABAG3AIA5AQ2IQ3CAQAPjMlQOC3AwA=","219":"b:+E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","226":[86,124],"263":[86,124],"269":"b:+E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","282":"b:eEcAEAjDAABAG3AIE5AQ2MQ3OEQAPjMlYPC3AwA=","306":"b:8E/SkKzjAVDk/3cIH5B03Px/PW/wP/9/+P//BwA=","333":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","340":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","349":"b:eEcAEAjDAABAG3AIE5AQ2IQ3CEQAPjMlQOC3AwA=","357":"b:eEcAEAjDAABAG3AIE5AQ2IQ3CEQAPjMlQOC3AwA=","359":"b:eEcAEAjDAABAG3AIA5AQ2IQ3CAQAPjMlQOC3AwA=","371":"b:+EeSkKzjAVDk/3cIH5B03Px/OW/wP/9/+P6/BwA=","388":"b:4EWCAKgiAABkfXEIBxBQFOR/CQdQO7d/iPY/AAA=","394":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/DUfwP/9/2P//BwA=","404":[86,124,116,208,210,140],"411":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","418":[86,124],"432":[86,124],"444":[86,124],"457":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","463":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","469":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","476":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","482":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","488":"b:cEcAEAjDAABAG3AIA5AQ2IQ3AAQAPjMlQOC3AwA=","494":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","503":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","533":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/CUfwP/9/+P+/BwA=","541":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/CUfwP/9/+P+/BwA=","551":"b:+EeSkKzjAUDk/3cIH5B03Ox/OUfwP/9/+P+/BwA=","554":"b:+EeSkKzjAUDk/3cIH5B03Ox/OUfwP/9/+P+/BwA=","557":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/CUfwP/9/+P+/BwA=","561":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/CUfwP/9/+P+/BwA=","564":"b:CAAAEAAgAEDAgUAAFQAEkAADEAAAABgAAAogAwA=","567":[86,124,179,180,114,62,70,96,71,201,137,213],"574":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","588":"b:+EeSkKzjAUDk/3cIH5B03Ox/O0fwP/9/2P//BwA=","624":"b:+E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","636":[86,124],"639":[86,124],"644":[86,124],"645":[86,124],"650":[86,124],"654":"b:cEcAEAjDAABAG3AIE5AQ2IQ3OEQAPjMlYOC3AwA=","683":"b:eEcAEAjDAABAG3AIA5AQ2IQ3AAQAPjMlAOC3AwA=","692":"b:8E/CAKjjAQDk/3cIH5BQ3Ox/DUfwP/9/2P//BwA=","698":[86,124],"709":[86,124],"728":"b:cEcAEAjDAABAG3AIA5AQ2IQ3CAQAPjMlQOC3AwA=","745":"b:8E/CAKjjAQDk/3cIH5BQ3Ox/DUfwP/9/2P//BwA=","768":"b:AAAAAAAAAADgAVEAAQAAEEACAAAAABgAACKgAwA=","775":"b:AAYAAAAAAAAAAHAAAgAAGAQDCEAAIAABQAAAAAA=","780":[86,124,72],"785":"b:8E/CAKDjAQDk/3cIH5BQHOx/DUfwP/9/2P//BwA=","798":"b:EAYAAADhAACEo1YAHYBQHGwfAEAAEnYBmDi3AwA=","820":[86,124],"829":"b:8E/CAKDjAQDk/3cIH5BQHOx/DUfwP/9/2P//BwA=","838":[86,124],"842":[86,124],"847":[86,124,48,82,100],"852":[86,124,48,82,100],"856":[86,124],"858":[86,124],"864":[86,124],"866":[86,124],"867":[86,124],"876":[86,124],"881":[86,124],"886":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","899":[86,124,134,77,142],"912":[86,124],"918":[86,124],"924":[86,124],"937":[86,124,134,77,142],"962":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","997":[86,124,136,137],"1126":"b:+E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","1149":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","1153":"b:+E/SkKzjAVDk/zcIH5B0zPx/PW/wP/9/+P//BwA="},"packages/frontend/editor-ui/src/app/stores/workflowSave.store.ts":{"15":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","26":"b:4EmCAKAiAADkfXcIHxAQEOx7CQfwL5t/CPfuBwA=","30":"b:4EmCAIAiAADkeXcIExAQEOR7CQUALANlAObuAwA=","34":[86,124],"39":[86,124],"43":[86,124],"47":[86,124],"51":[86,124],"55":"b:AAEAEAAAAACkCVEAAxAQkMA4AQAAIAIBAGSgAwA=","63":[86,124,28,127]},"packages/frontend/editor-ui/src/app/stores/workflows.store.ts":{"42":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","59":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/D0fwP/9/2P//BwA=","69":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/D0fwP/9/2P//BwA=","70":"b:8E+CkIzjAADk+3cIH5BQ3Ox/C0UAPndl2P7/AwA=","79":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","84":"b:4EWCAKAiAABkfXEIBxBQFOR/CAdQO7d/CPY/AAA=","88":"b:4EWCAKAiAABkfXEIBxBQFOR/CAdQO7d/CPY/AAA=","98":[86,124,48,82,100],"99":[86,124],"119":[86,124,218],"126":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/D0fwP/9/2P//BwA=","156":[86,124],"164":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","168":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","179":"b:EAYAkAzhAACEo1YAHYBQ3GwfAkAAEnYB2Dj3AwA=","186":[86,124,81],"202":[86,124,79,81],"217":[86,124,172,69,79,80],"229":[86,124,81],"233":[86,124],"251":[86,124,47,72,136,73,137,215,216,217],"265":"b:4EmCAICiAADkeXcoExAQEOR7CQUALANlAObuAwA=","266":"b:4EGCAICiAADkeXUIExAQEOR7CQUALANlAOauAwA=","274":"b:4EmCAIAiAABgeXcIExAAEORrCQUALAFkAMZuAQA=","302":"b:AAEAAACAAACkCVEgAxAQEMA4AQAAIAIBAGTgAwA=","345":[86,124,172,69,213,79,80],"359":"b:8E+CkIzjAADk+3cIH5BQ3Ox/C0UAPndlmP7/AwA=","367":[86,124,81],"394":[86,124],"446":"b:cEcAAAjDAABAG3AIE5AQmIQ3CEQAPjMlQOC3AwA=","465":[86,124],"473":"b:cEcAEAjDAABAG3AIA5AQ2IQ3AAQAPjMlQOC3AwA=","485":[86,124,138]},"packages/frontend/editor-ui/src/app/stores/workflowsList.store.ts":{"27":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","39":[86,124,213,142],"40":[86,124,213,142],"45":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/D0f0P/9/2P//BwA=","50":[86,124],"51":[86,124],"59":"b:8E+CkIz7AADk+3cpH5BQ3ux/O0UEfndl2P7/AwA=","69":[86,124,79,81],"74":"b:8E/CkKzjAADk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","83":[86,124],"87":[86,124],"94":[86,124],"99":[86,124,172,69,79,80],"112":[86,124,81],"126":"b:AAABAwA4AIgAgEIjHAAAEgBAgAAEwAAADAggAAA=","154":"b:AAAAAAA4AAAAAEIhHAAAEgBAAAAEQAAAAAggAAA=","155":"b:AAAAAAA4AAAAAEIhHAAAEgBAAAAEQAAAAAggAAA=","166":"b:AAABAwA4AIgAgEIjHAAAEgBAgAAEwAAADAggAAA=","187":[86,124,28,126,31,34,35,127,162,47,69,216],"221":[86,124,28,126,31,34,35,127,162,47,69,216],"234":[86,124],"242":"b:EAYAkAzxAACko1YAHYBQ3GxfAkAEEnYBmDj3AwA=","248":[86,124,191,58],"252":"b:8E/Dk6z7AYjk/3crH5BQ3ux/j0f0//9/nP//BwA=","258":"b:4EnCAKAiAABg/XMIBxAQGORrDQfwL4l+CMdOBQA=","264":[86,124,79,81],"270":[86,124,81],"291":[86,124,79,81]},"packages/frontend/editor-ui/src/app/upgradeRedirectGuard.manifest.ts":{"11":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","12":[86,124],"13":[86,124]},"packages/frontend/editor-ui/src/app/utils/aiUtils.ts":{"23":[86,124],"29":[86,124],"42":[86,124],"57":[84,86,124,137],"82":[86,124,137],"87":[86,124,137],"110":[86,124],"118":[86,124],"132":[86,124],"182":[86,124],"193":[86,124],"204":[86,124],"215":[86,124],"236":[3,84,86,124,137],"245":[3,86,124],"248":[84,86,124,137],"257":[86,124],"263":[84,86,124,137],"264":[84,86,124,137],"274":"b:CAYAEAgAAAAAAHAAAAAA0AACAAAAAAABQAAAAgA=","286":[86,124,137],"300":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/2P+/BwA="},"packages/frontend/editor-ui/src/app/utils/credentialOnlyNodes.ts":{"16":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","51":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA="},"packages/frontend/editor-ui/src/app/utils/expressions.ts":{"19":[86,124],"28":[86,124],"30":[86,124],"31":[86,124],"46":[86,124],"65":[86,124],"86":[86,124],"110":[86,124],"128":[86,124],"132":[86,124,116,75],"136":[86,124,60],"137":[86,124,60],"145":"b:IACAACAAAABAXHAAAAAAEAA6AAAAAIFBAEACAAA=","149":"b:IACAACAAAABAVHAAAAAAEAAoAAAAAIBBAEAAAAA=","153":"b:IACAACAAAABAXHAAAAAAEAAoAAAAAIBBAMQAAAA=","159":[5,86,124,74,76,78,141],"163":"b:IAAAAAAAABAAdEAAAgAQEAAwAAAAAAAAAMQAAAA=","167":[5,86,124,74,76,78,141],"171":[5,86,124,74,76,78,141],"175":[5,86,124,74,76,78,141],"179":[5,86,124,74,76,78,141],"183":"b:IACAACAAABBAfHAAAgAQEAA7AAAAEIVBAMQCAAA=","198":[5,84,85,86,124,74,206,75,76,139,140,78,141],"247":"b:IACAACAAABBAfHAAAgAQEAA7AAAAEIVhAMACAAA=","271":"b:AEGSAIAiABBEfXQIAxAUEPRgCA8AIpJQAMYiAAA=","281":"b:AEGSAAAiABBEdXQIAxAUEPRgCAsAIpAQAIYCAAA="},"packages/frontend/editor-ui/src/app/utils/formatters/dateFormatter.ts":{"4":"b:YEQAAAiCAAAAEUAAAgAQEIQ3CAQAOgIgAKA3AgA=","15":[3,86,124,47,72,136,73,137,215,216,217],"27":"b:AAYAEAgAAAAAAHAAAAAA0AACAAAAAAABQAAAAAA=","29":"b:AAYAEAgAAAAAAHAAAAAA0AACAAAAAAABQAAAAAA=","32":[86,124,194],"35":[86,124,194]},"packages/frontend/editor-ui/src/app/utils/injectStrict.ts":{"4":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA="},"packages/frontend/editor-ui/src/app/utils/mappingUtils.ts":{"11":"b:aEYAAAiCAAAAOVAAAwAQEIQ3KAQAOiMtgPQ/AgA=","15":"b:aEYAAAiCAAAAOVAAAwAQEIQ3KAQAOiMtgPQ/AgA=","16":"b:aEYAAAiCAAAAOVAAAwAQEIQ3KAQAOiMtgPQ/AgA=","29":"b:AEYAAAiCAAAAPVAAAwAQEIQzKAQAOiMhgOQ3AgA=","33":"b:AEYAAAiCAAAAGVAAAgAQEIQzKAQAOiIhAOQ3AgA=","53":"b:AEYAAAiCAAAAOVAAAwAQEIQ3KAQAOiMhgPQ/AgA=","70":[86,124],"82":[86,124,116],"96":[86,124,116]},"packages/frontend/editor-ui/src/app/utils/nodeIcon.ts":{"39":[86,124],"81":"b:+EeSkKzjABDk/3cIH5BQ3Px/OUfwP/9/+P6/BwA=","95":"b:+EeSkKzjARDk/3cIH5BQ3Px/OUfwP/9/+P6/BwA=","99":[86,124],"105":"b:+EeSkKzjABDk/3cIH5BQ3Px/OUfwP/9/+P6/BwA=","113":"b:oECSACQiAQBkeHUAE5BQEOAbAQHwG7dICPYeBAA=","118":"b:+EeSkKzjARDk/3cIH5BQ3Px/OUfwP/9/+P6/BwA=","125":"b:oECSACQiAQBkeHUAE5BQEOAbAQHwG7dICPYeBAA=","131":"b:+EeSkKzjABDk/3cIH5BQ3Px/OUfwP/9/+P6/BwA=","138":[86,124],"152":"b:+EeSkKzjARDk/3cIH5BQ3Px/OUfwP/9/+P6/BwA=","214":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA="},"packages/frontend/editor-ui/src/app/utils/nodeTypes/nodeTypeTransforms.ts":{"8":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","29":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","32":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA="},"packages/frontend/editor-ui/src/app/utils/nodeTypesUtils.ts":{"44":"b:gACCAKQiABAgYHUIAgAAEHAYAStQAYVAAAQKAAA=","47":"b:gACCAKQiABAgYHUIAgAAEHAYAStQAYVAAAQKAAA=","55":"b:gEeSAKSjAQBkZXcIEoBAnGwbOUdQMedLSDYaBAA=","59":[86,124,48,77,78,82],"62":[86,124,48,77,78,82],"66":[86,152,153,124,173,205,209,97,100],"78":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","112":"b:AAAAAAABAAAAAEAAEAAAEAQECEAQJAAAAAACAAA=","123":"b:AAAAAAABAAAAAEAAEAAAEAQECEAQJAAAAAACAAA=","135":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/D0fwP/9/mP//BwA=","136":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/CUfwP/9/mP6/BwA=","141":[86,124,82,100],"142":[86,124,82,100],"143":[86,124,82,100],"147":[86,124,82,100],"150":"b:AAAAAAAAABAAfEAAAgAQEABgAAAAAABAAMAAAAA=","151":"b:AAAAAAAAABAAfEAAAgAQEAAgAAAAAABAAMAAAAA=","154":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","174":"b:6EeCAKiiAABkfXEIBxBQFOR/KQdQO7d/iPY/AgA=","175":"b:aEYAAAiCAAAAOVAAAwAQEIQ3KAQAOiMlgPQ3AgA=","183":"b:gACCAAQgAAAgYHEAAABAECBKAABQAIAACAAiAAA=","195":"b:gACSAKAiAAAgYHEAAgBAEGQaAANQIYVACAQKBAA=","215":"b:4ASSAKyiAEBkeHEABxB0EOR/CQNQO7d3iPY/BgA=","222":"b:gACCAAQgAAAAYAEAAgBAECQQAQNQIAQACAAKAAA=","225":"b:gACCAAQgAAAAYAEAAgBAECQQAQNAIAQACAAKAAA=","242":"b:4ASQAKiiAEBkeHEABxA0EMR/CQNQO7d3gPY/BgA=","247":"b:AACQAKACAAAgIHAAAAAAEEQKAQMQIYFAAAQABAA=","251":[152,153,23,124,164,130,173],"256":[152,153,23,124,164,130,173],"266":[152,153,124,164,130,173],"283":"b:4ACCAIAgABAAYHQIAAAAEDAAACgAAIAACAAAAAA=","297":[7,86,17,23,124,195,133,77,78],"301":[7,86,17,23,124,195,133,77,78],"304":[7,86,17,23,124,195,133,77,78],"331":[7,86,17,23,124,195,133,77,78],"332":[7,86,17,23,124,195,133,77,78],"336":"b:gACCAAAgAAAAYEEAAgBAECAQAAFQAAQACAAKAAA=","342":"b:gACCAAAgAAAAYEEAAgBAECAQAAFQAAQACAAKAAA=","351":[7,86,17,23,124,195,133,77,78],"358":[7,86,17,23,124,195,133,77,78],"364":[7,84,85,86,17,23,124,39,183,195,133,77,78],"373":[7,86,17,23,124,195,133,77,78],"381":"b:gACCAAQgAAAAYEEAAgBAECAQAQFQAAQACAAKAAA=","386":"b:gACCAAQgAAAAYEEAAgBAECAQAQFQAAQACAAKAAA=","398":"b:4ASSAKyiAEBkeHEABxB0EOR/CQNQO7d3iPY/BgA=","404":"b:gACSAKQiAAAgYHEAAgBAEGQaAQNQIYVACAQKBAA=","406":"b:gACCAAQgAAAAYAEAAgBAECQQAQNQIAQACAAKAAA=","407":"b:gACCAAQgAAAAYAEAAgBAECQQAQNQIAQACAAKAAA=","409":"b:gACCAAQgAAAAYAEAAgBAECQQAQNQIAQACAAKAAA=","425":"b:gACCAAQgAAAAYEEAAgBAECQQAQNQIAQACAAKAAA=","448":[86,17,23,124,195,133,77,78],"474":"b:gACCAAQgAAAAYEEAAgBAECAQAQFQAAQACAAKAAA=","483":[86,124],"484":[86,124],"496":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","503":[86,124,141],"516":[86,124,141],"525":[86,124,141],"559":[86,124],"560":[86,124],"563":[86,124,141],"579":"b:AACSAAABAAAAYHQIEIAAECQCAQAAMIAACAAAAAA=","592":[86,23,91,124],"597":[86,23,91,124],"620":"b:AACSAAAAAAAAYHAIAAAAECAAAQAAIIAACAAAAAA=","641":"b:AACSAAAAAAAAIHAIAAAAECAAAQAAIIAACAAAAAA=","646":"b:+EeekKzzARDk/3cIH5BQ3Px/OX/wP/9/+P6/BwA="},"packages/frontend/editor-ui/src/app/utils/nodeViewUtils.ts":{"67":[86,148,149,124,48,198,82,100],"68":[86,148,149,124,48,198,82,100],"77":"b:YAEAAAAAAAAAIEAADgAAEEACAAQABAk4AAIGBAA=","78":"b:YAEAAAAAAAAAIEAADgAAEEACAAQABAk4AAIGBAA=","87":"b:YAEAAAAAAAAAIEAADgAAEEACAAQABAk4AAIGBAA=","88":"b:YAEAAAAAAAAAIEAADgAAEEACAAQABAk4AAIGBAA=","97":"b:YAEAAAAAAAAAIEAADgAAEEACAAQABAk4AAIGBAA=","98":"b:YAEAAAAAAAAAIEAADgAAEEACAAQABAk4AAIGBAA=","107":"b:YAEAAAAAAAAAIEAADgAAEEACAAQABAk4AAIGBAA=","108":"b:YAEAAAAAAAAAIEAADgAAEEACAAQABAk4AAIGBAA=","117":"b:YAEAAAAAAAAAIEAADgAAEEACAAQABAk4AAIGBAA=","134":"b:gECCAKAiAABkfXEIDxAQEOxoCAFAIJBOCNYKAAA=","151":[86,124,186,187,70],"166":"b:+EeSkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","185":"b:+EeSkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","192":[144,86,124,185,197],"199":"b:4EGCAKAiAQBkfXUIHxAQEOxrCQfwL5l+CNcuBQA=","264":"b:cEcAACigAADEuXUACwBQFMQ/KAXgMjdzgHe3AwA=","274":[86,124,200],"286":[86,124,200],"305":[86,124,200],"314":[86,148,149,124,48,198,82,100],"325":[86,148,149,124,48,198,82,100],"395":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","537":[86,124],"563":"b:YAGCgQAoAJDgq1cAHwBAEHALAQUQxYk8QxvnBwA=","580":"b:4EOCAKAiAABkfXEIDxAQEOxrCAfwL5l+CNcOBQA=","592":[9,86,124,137],"601":[9,86,124,137],"607":[9,86,124,137],"643":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA="},"packages/frontend/editor-ui/src/app/utils/nodes/nodeTransforms.ts":{"40":"b:4EGCAKAiAQBkfXUIHxAQEOxrCAfwL5l+CNcuBQA=","49":"b:8EGCkKjjAQDk/3UIH5BQ3OR/CUfwP71+mO+/BwA=","74":"b:gEGCAKCjAQBkZXUIEoBAnGQbCUdQMaVKCCYKBAA=","84":[86,124,82,100],"98":"b:gACCAKAjAQAkYHUAEoBAEGQaAQNQMaVICAQKBAA=","112":"b:8EGCkKjjAQDk/3UIH5BQ3OR/CUfwP71+mO+/BwA=","118":"b:gACCAKAjAQAkYHUAEoBAEGQaAQNQMaVICAQKBAA=","129":"b:cAQAAAgCAABAGEAAAgAQEIAxAAQAKCIBAOAGAAA=","143":"b:4EWSAKiiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","165":"b:4EWCAKiiAEBkfXEIBxB0FOR/KAdQO7d/CPY/AgA=","189":"b:8EeCAIjjAADke3UIG5AQmOR/CUUAPjNlQOa/AwA=","266":[84,85,86,124,40,130,111,172,173,137,82],"269":[84,85,86,124,40,130,111,172,173,137,82]},"packages/frontend/editor-ui/src/app/utils/objectUtils.ts":{"3":"b:+E/SkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/2P//BwA=","7":"b:+E/SkKzjAUDk/3cIH5B03Ox/P0fwP/9/2P//BwA=","11":"b:+E/SkKzjAUDk/3cIH5B03Ox/P0fwP/9/2P//BwA=","15":[86,124,31,71],"16":[86,124,71],"19":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","23":[86,124,208,210],"24":[86,124,208,210],"36":[5,6,7,8,86,124],"62":[86,124],"66":[86,124]},"packages/frontend/editor-ui/src/app/utils/pairedItemUtils.ts":{"19":"b:eEcAEAjDAABAG3AIA5AQ2MQ3KAQAPjMlAPS3AwA=","23":[86,124,116,140],"48":[86,124,116,140],"58":[86,124,116,140],"61":"b:eEcAEAjDAABAG3AIA5AQ2MQ3AAQAPjMlAPC3AwA=","89":"b:GAcAEAjDAAAAG1AIA5AQ0MA3AAQABiMlAPC3AwA=","95":"b:eEcAEAjDAABAG3AIA5AQ2MQ3AAQAPjMlAPC3AwA=","124":"b:GEcAEAjDAAAAG1AIA5AQ0MQ3AAQAFiMlAPC3AwA=","138":"b:eEcAEAjDAABAG3AIA5AQ2MQ3AAQAPjMlAPC3AwA=","143":"b:eEcAEAjDAABAG3AIA5AQ2MQ3AAQAPjMlAPC3AwA=","152":[86,124,111],"168":"b:eEcAEAjDAABAG3AIE5AQ2MQ3CEQAPjMlQPC3AwA=","171":"b:eEcAEAjDAABAG3AIA5AQ2MQ3AAQAPjMlAPC3AwA=","172":"b:eEcAEAjDAABAG3AIA5AQ2MQ3AAQAPjMlAPC3AwA=","173":"b:eEcAEAjDAABAG3AIA5AQ2MQ3AAQAPjMlAPC3AwA=","188":"b:eEcAEAjDAABAG3AIE5AQ2MQ3CEQAPjMlQPC3AwA=","197":"b:eEcAEAjDAABAG3AIA5AQ2MQ3AAQAPjMlAPC3AwA=","209":"b:eEcAEAjDAABAG3AIE5AQ2MQ3CEQAPjMlQPC3AwA=","229":"b:eEcAEAjDAABAG3AIA5AQ2MQ3AAQAPjMlAPC3AwA=","230":"b:eEcAEAjDAABAG3AIA5AQ2MQ3AAQAPjMlAPC3AwA="},"packages/frontend/editor-ui/src/app/utils/parameterUtils.ts":{"13":"b:QEGSAIAiABBEfXQIAxAQEPRoCA8AIpJQCOYiAAA=","31":[86,124]},"packages/frontend/editor-ui/src/app/utils/rbac/checks/hasScope.ts":{"4":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/utils/rbac/checks/isAuthenticated.ts":{"5":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","14":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA="},"packages/frontend/editor-ui/src/app/utils/rbac/checks/isValid.ts":{"3":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA="},"packages/frontend/editor-ui/src/app/utils/rbac/middleware/authenticated.ts":{"7":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA="},"packages/frontend/editor-ui/src/app/utils/rbac/permissions.ts":{"28":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/utils/timeAgoLocale.ts":{"5":"b:AACCAwA4ABAAAEYpHAAAEjAAACAEQAAAAAgAAAA=","25":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/utils/typeGuards.ts":{"31":[86,124],"35":[86,124,116,140],"39":[86,124,78,82],"43":"b:aEQAAAiCAAAAOUAAAwAQEIA3AQQAEiMsgPQ/AgA=","46":[86,124],"49":"b:gACSAIQgAAAgaEEAAgBQEGR3CQFQISUACEQ+AAA=","57":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","61":[86,124,141],"65":[86,124,60],"71":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","77":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUfwP/9/6P+/BwA=","81":"b:AAAAACAAAABAIHAAAAAAEAAoAAHgAABOABAAAAA=","90":[86,147,152,153,124,130,173,136,205,209,97],"96":[86,124,72,141],"102":[86,124],"109":[86,124,47,72,136,73,137,215,216,217],"113":[86,23,124,44,192,132,133],"117":[86,23,124,44,192,132,133],"121":[86,124,192],"125":[86,17,23,91,124,44,45,192,60,132,133],"129":[86,124],"135":[86,23,124,44,192,132,133],"142":"b:AACCAwA4ABAAAEIpHAAAEjAAAAAEQAAAAQgAAAA=","155":[86,21,124,175,45],"167":"b:YEkAAAACAABgGXAIFxAQEIQzCQQALAMlAOCmAQA="},"packages/frontend/editor-ui/src/app/utils/typesUtils.ts":{"12":[86,124],"14":"b:aEYAAAiCAAAAOVAAEwAQEIQ3KAQAOiMlgPY3BgA=","23":"b:6E/TAayyAdhk/3cLHxB0nvR/vS/0v79/7Pf/BwA=","40":[86,124,82,100],"59":[86,124],"63":"b:AAAAAAAAAAAAOUAAAgAQEAAQAAAAAAEAAMYGBAA=","69":[86,124,97],"74":"b:aEYAAAiCAAAAOVAAAwAQEIQ3KAQAOiMtgPQ/AgA=","85":[86,124],"91":[86,124],"92":[86,124],"102":[86,124],"122":[86,124,202,206,116,75,76,207,140,97],"127":[86,124,202,206,116,75,76,207,140,97],"169":[86,124,48,82,100],"173":"b:4EeSkKy6AFDkfXcoDxB01Px/KS/0f79/iP+/BwA=","177":"b:AEGCAQAiABAAfXQIAgAUEDQwCA4AIoJAgMACAAA=","186":[86,124],"195":[86,124],"204":"b:AEGSAIAiABAAfXQIAgAUELQwCA5AIoJAgMACAAA="},"packages/frontend/editor-ui/src/app/utils/urlUtils.ts":{"2":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA="},"packages/frontend/editor-ui/src/app/utils/workflowUtils.ts":{"11":"b:EAYAkAzhAACEo1YAHYBQ3GwfMkAAEnYB2Dj3AwA=","15":[86,124,214],"26":[86,124,197],"36":[86,124,197],"49":"b:eAcAkAzhAACEo1YAH4BQ3GwfMEQAFn850Dq3BwA=","60":"b:eAcAkAzhAACEI1QAH4BQ3EwfMEQAFn85wDq3BwA=","80":"b:eAcAkAzhAACEo1YAH4BQ3GwfMkQAFn852Dr3BwA=","100":"b:eAcAkAzhAACEI1QAH4BQ3EwfMEQAFn85wDq3BwA=","103":"b:eAcAkAzhAACEI1QAH4BQ3EwfMEQAFn85wDq3BwA=","138":[144,86,124],"145":[144,86,124],"146":[144,86,124],"158":[144,86,124],"167":[144,86,124]},"packages/frontend/editor-ui/src/app/views/LoadingView.vue":{"6":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/app/views/NodeView.vue":{"169":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","173":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","177":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","178":"b:8E/CkKjjAQDk3zcIH5BQzOx/DUfwP/9/mP//BwA=","196":"b:gAGCAIAgAADkaRcAAxAAAORoAQEAIABAAEZqAwA=","208":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","301":"b:8E/CkKzjAQDk/zcIH5BQzOx/LUfwP/9/2P//BwA=","312":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","316":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","318":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","319":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","320":"b:oECCAKAiAABkfTEIDxAQAOxrCAPwK5BOCPeKAwA=","321":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","332":"b:8EWCkIjjAQDk/xcIH5BQzOx/CUfwPz8+mP6/BwA=","336":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","348":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","352":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","368":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","370":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","374":"b:AAaAACAAAAAAADAAAAAAAAgKAAAAAMBBQAAAAAA=","380":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","425":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","430":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","440":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","444":"b:8EeCkKzjAQDk/zcIH5BQzOx/OUfwP/9/2P6/BwA=","445":"b:8EeCkKzjAQDk/zcIH5BQzOx/OUfwP/9/2P6/BwA=","448":"b:4EGCAKAiAABgfTEIBxAQAOxrOQfwL4l+SOYOBQA=","486":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","488":"b:8EeCkKzjAQDk/zcIH5BQzOx/OUfwP/9/2P+/BwA=","494":"b:8EWCkIjjAQDk/xcIH5BQzOx/CUfwPz8+mP6/BwA=","496":"b:8EWCkIjjAQDk/xcIH5BQzOx/CUfwPz8+mP6/BwA=","497":"b:8EWCkIjjAQDk/xcIH5BQzOx/CUfwPz8+mP6/BwA=","501":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","502":"b:8EeCkKzjAQDk/zcIH5BQzOx/OUfwP/9/2P6/BwA=","505":[144,185],"516":[213],"520":[184,70,96,71,201,99],"528":[201],"532":[179,180,70,137],"541":[70,96,71,201],"545":[201,213],"561":[69,70,137],"569":[201],"573":[84,134,201,72,205,80,215,216,217],"581":"b:YEUAAAigAADEuSUACwBQBMQfKAQAMjcxgHa3AwA=","586":"b:YEUAAAigAAAEOSAAAgBQBMQfKAQAEjcxAHQ3AgA=","608":"b:8EeCAKiiAADk/TUIDxBQBOx/KAfwP79/iPe/BwA=","617":[70,134,201,99,218,82],"621":[70,99,82],"623":[70,99,82],"636":[134,201,99,79],"681":[134,201,99],"690":[134,201,99],"706":[134,201,97],"730":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","734":"b:AAAAEAAgAAAggxYAHAAAgAADAAAAAAAACAiAAwA=","753":[134],"775":[134],"794":[134],"821":[213],"837":[84],"841":[153,173],"845":"b:AAAAACAAAABAADAAAAAAAAAgAAHgAABCABAAAAA=","885":[71,213],"889":[201,213],"893":"b:AAAAACAAAABAADAAAAAAAAAgAAHgAABCABAAAAA=","921":[70,71,201],"925":[201,213],"933":"b:YAEAAAAAAAAAIAAABgAAAAACAAQABAk4AAAGBAA=","948":"b:YAEAAAAAAAAAIAAABgAAAAACAAQABAk4AAAGBAA=","964":[218],"971":[218],"980":[218],"986":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","992":"b:AAAAEAAgAAAggxYAHAAAgAADAAAAAAAACAiAAwA=","1004":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","1008":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNcKAQA=","1025":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNcKAQA=","1127":[201,213],"1131":[135,202,139,141],"1139":[139],"1152":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","1165":[216],"1178":"b:8EeCAKiiAADk/TUIDxBQBOx/KAfwP79/iPe/BwA=","1184":[200],"1188":[186,187,70],"1253":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","1259":"b:4EnCAKAiAQBg/TcIHxAQCORrDQfwL4l+CMdOBQA=","1261":[144,17,123,23,45,195,78,98,142,81],"1272":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","1273":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","1282":[100],"1291":"b:8EWCkIjjAQDk/xcIH5BQzOx/CUfwPz8+mP6/BwA=","1309":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","1312":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","1315":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","1319":[4,10,35,181,184,70,136,205,206,75],"1389":[4,10,35,181,184,70,136,205,206,75],"1445":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","1450":"b:AAAAEAAgAAAggxYAHAAAgAADAAAAAAAACAiAAwA=","1455":[136,137],"1465":"b:AEEAAAjBAAAAAxAIA5AAiAQXCEQANhEkACC3AwA=","1469":"b:AEEAAAjBAAAAAwAIA5AAiAQXCEQANhEkACC3AwA=","1477":"b:4E/CgKAiAABg/TMIBxAQCOxrDQfwL8l/SOdOBQA=","1478":"b:AAaAgCAAAABAADAAAAAAAEgKAAAAAMBJQCMCAAA=","1483":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","1486":"b:8EeCkKjjAQDk/zcIH5BQzOx/CUfwP/9/2P+/BwA=","1494":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","1495":"b:8EeCkKjjAQDk/zcIH5BQzOx/CUfwP/9/2P6/BwA=","1498":"b:4E/CgKAiAABg/TMIBxAQCOxrDQfwL8l/SOdOBQA=","1504":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","1520":[84,198],"1528":[84],"1607":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","1621":"b:AAAAEAAgAAAggxYAHAAAgAADAAAAAAAACAiAAwA=","1659":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","1663":"b:AAAAEAAgAAAggxYAHAAAgAADAAAAAAAACAiAAwA=","1670":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","1674":"b:AAAAEAAgAAAggxYAHAAAgAADAAAAAAAACAiAAwA=","1682":"b:oECCAKAiAABkfTEIDxAQAOxrCAPwK5BOCPeKAwA=","1725":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","1743":[72],"1759":"b:4EGCAKAiAABkfTEIDxAQAOxrCAfwL5l+CNcOBQA=","1763":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","1769":"b:4EGCAKAiAABkfTEIBxAQAOxrCAfwL5l+CNcOBQA=","1770":"b:4EGCAKAiAABkfTEIBxAQAOxrCAfwL5l+CNcOBQA=","1777":"b:EAYAAAAgAADAAAAAAAAAAEACAAEAIAABgAEmAAA=","1782":"b:EAYAAAAgAADAAAAAAAAAAEACAAEAIAABgAEmAAA=","1790":[70],"1812":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","1822":[77],"1852":"b:AAAAEAAgAAAggxYAHAAAgAADAAAAAAAACAiAAwA=","1858":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","1872":"b:4EWCAKAiAABkfTEIBxBQBOR/CAdQO7d/CPY/AAA=","1890":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","1895":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","1900":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","1912":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","1918":"b:4EnCAKAiAABg/TMIBxAQCORrDQfwL4l+CMdOBQA=","1950":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","1952":"b:4EWCAKAiAABkfTEIBxBQBOR/CAdQO7d/CPY/AQA=","1961":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","1963":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","1981":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","1982":"b:4EGCAKAiAADkfTcIDxAQAOx7CQfwL5t/CPfuBwA=","2000":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","2001":[144,11],"2013":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","2025":"b:cAQAEAgCAABAGAAAAgAQwIAzAAQAKCIAAOAGAAA=","2026":"b:cAQAEAgCAABAGAAAAgAQwIAzAAQAKCIAAOAGAAA=","2031":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","2040":"b:8EWCEIjjAADk/xEID5AQyOR3CQVAPjsuCPa/AwA=","2050":"b:8EWCEIjjAADk/xEID5AQyOR3CQVAPjsuCPa/AwA=","2051":"b:8EWCEIjjAADk/xEID5AQyOR3CQVAPjsuCPa/AwA=","2062":"b:AAAAAAAgAAAggxAAFAAAAAADAAAAAAAAAAiAAwA=","2111":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","2113":[47,214,79],"2130":"b:8E/CkKzjAQDk/zcIH5BQzOx/LUfwP/9/2P//BwA=","2151":"b:AAAAEAAgAAAggxYAHAAAgAADAAAAAAAACAiAAwA=","2233":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","2269":"b:AEEAAAjBAAAAAxAIA5AAiAQXCEQANhEkACC3AwA=","2284":"b:AAaAACAAAAAAADAAAAAAAAgKAAAAAMBBQAAAAAA="},"packages/frontend/editor-ui/src/app/workers/isDataWorkerEnabled.ts":{"10":"b:/k//8777Ad7k/3c7H5B83vz/v///////////BwA="},"packages/frontend/editor-ui/src/experiments/aiTemplatesStarterCollection/stores/aiTemplatesStarterCollection.store.ts":{"20":"b:8E/Dk6z7AYjk/zcrH5BQzux/v0f0//9//P//BwA=","33":"b:AAAAAwA4AAAAAAIhHAAAAgAAAAAEwAAACAgAAAA="},"packages/frontend/editor-ui/src/experiments/credentialDescriptions/useCredentialDescriptionsExperiment.ts":{"6":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","8":"b:gACCAIAwABAAYHQIAAAAEDAAACgAAIAAAAAAAAA="},"packages/frontend/editor-ui/src/experiments/evaluationsWizardSidepanel/useEvaluationsWizardSidepanelExperiment.ts":{"7":"b:8E/CkKzjAQDk/zcIH5BQzOx/P0fwP/9/2P//BwA=","13":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA="},"packages/frontend/editor-ui/src/experiments/inlineAgents/useInlineAgentsExperiment.ts":{"7":[86,124],"10":[86,124],"24":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNcOAQA="},"packages/frontend/editor-ui/src/experiments/instanceAiComputerUse/useInstanceAiComputerUseExperiment.ts":{"6":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","9":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/experiments/instanceAiSetupPanel/useInstanceAiSetupPanelExperiment.ts":{"6":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","8":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","13":[86,124,34]},"packages/frontend/editor-ui/src/experiments/readyToRunWorkflows/stores/readyToRunWorkflows.store.ts":{"21":"b:8E/Dk6z7AYjk/zcrH5BQzux/v0f0//9//P//BwA=","30":"b:AAAAAwA4AAAAgAIhHAAAAgAAAAAEwAAACAgAAAA=","38":"b:AAAAAwA4AAAAgAIhHAAAAgAAAAAEwAAACAgAAAA=","44":"b:AAAAAwA4AAAAgAIhHAAAAgAAAAAEwAAACAgAAAA="},"packages/frontend/editor-ui/src/experiments/readyToRunWorkflowsV2/stores/readyToRunWorkflowsV2.store.ts":{"12":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/3f//BwA="},"packages/frontend/editor-ui/src/experiments/resourceCenter/stores/resourceCenter.store.ts":{"19":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","32":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","114":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA="},"packages/frontend/editor-ui/src/experiments/sidebarExpanded/useSidebarExpandedExperiment.ts":{"6":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","10":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA="},"packages/frontend/editor-ui/src/experiments/surfaceAssistantOnWorkflowError/components/WorkflowErrorNudge.vue":{"27":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","32":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","47":[86,124],"60":[86,124],"65":[86,124],"89":[86,124],"95":[86,124],"99":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","105":[86,124],"109":[86,124],"115":[86,124],"116":[86,124],"117":[86,124],"127":[86,124],"132":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","137":[86,124],"148":[86,124],"152":[86,124],"155":[86,124],"161":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","168":[86,124],"172":[86,124],"177":[86,124],"194":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","206":[86,124],"212":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","248":[86,124]},"packages/frontend/editor-ui/src/experiments/surfaceAssistantOnWorkflowError/composables/useSurfaceAssistantOnWorkflowError.ts":{"31":"b:cEcAEAjDAABAG3AIA5AQ2IQ3AAQAPjMlQOC3AwA=","37":"b:cEcAEAjDAABAG3AIA5AQ2IQ3AAQAPjMlQOC3AwA=","42":[5,6,86,124,72,215,216],"56":"b:YAAAAACAAAAAA3AAAAAAEAADAAAAABAAACCCAwA=","61":[86,124],"71":"b:YAAAAAAAAAAAAXAAAAAAEAADAAAAABAAACCCAQA=","103":[86,124]},"packages/frontend/editor-ui/src/experiments/trialIntroModal/stores/trialIntroModal.store.ts":{"22":[86,124],"36":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","45":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","47":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","51":[86,124],"60":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","63":"b:AAABAwA4AIgAgEIjHAAAEgAAgAAEwAAADAgAAAA=","72":[86,124],"74":[86,124],"76":[86,124],"89":[86,124],"101":[86,124],"112":[86,124],"116":[86,124],"128":[86,124],"142":[86,124],"158":[86,124]},"packages/frontend/editor-ui/src/experiments/trialIntroModal/useTrialIntroModalAutoOpen.ts":{"6":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","12":[86,124],"17":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","24":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/experiments/utils.ts":{"26":[86,124],"46":"b:4EnCAKAiAABg/XMIBxAQGORrDQfwL4l+CMdOBQA=","53":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","60":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","91":[86,124]},"packages/frontend/editor-ui/src/features/agents/agentNodeCanvasGeometry.store.ts":{"10":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","17":[86,124],"26":[86,124],"30":[86,124],"41":[86,124],"50":[86,124],"54":[86,124],"63":[86,124],"71":"b:AAAAEAAgAAAgg1AAFAAAkAADAAAAAAAAAAiAAwA="},"packages/frontend/editor-ui/src/features/agents/agentReturnContext.store.ts":{"27":"b:/k/C8LzjAQDk/3cYH5BQ3Ox/Pcf3P/9/2P//BwA=","31":[86,124],"35":[86,124],"39":[86,124],"43":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/agents/composables/useAgentCapabilitiesActions.ts":{"108":"b:9k/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","132":[86,124],"146":[86,124],"160":[86,124],"166":[86,124],"192":[86,124],"196":[86,124],"199":[86,124],"200":[86,124],"205":[86,124],"219":[86,124],"235":[86,124],"236":[86,124],"237":[86,124],"243":[86,124],"245":[86,124],"273":[86,124],"274":[86,124],"275":[86,124],"280":[86,124],"285":[1,2,86,124],"311":[86,124],"312":[86,124],"330":[86,124],"334":[86,124],"363":[86,124],"364":[86,124],"371":[86,124],"373":[86,124],"378":[86,124],"387":[86,124],"391":[86,124],"398":[86,124],"401":[86,124],"403":[86,124],"407":[86,124],"408":[86,124],"414":[86,124],"423":[86,124],"432":[86,124],"446":[86,124],"502":[86,124],"513":[86,124],"517":[86,124]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentConfig.ts":{"6":"b:/k/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","27":"b:/k/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","39":"b:9k/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","46":[1,2,3,86,124],"70":[86,124]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentNavigation.ts":{"11":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","23":[86,124],"42":[86,124],"62":[86,124],"66":[86,124]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentPermissions.ts":{"21":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","28":[86,16,89,155,19,91,124,45,194,99],"31":[86,16,89,155,19,91,124,45,194,99],"34":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","37":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","39":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","42":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","43":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","51":[1,2,86,124],"52":[86,124]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentScopeProjectId.ts":{"15":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","19":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA="},"packages/frontend/editor-ui/src/features/agents/composables/useAgentTelemetry.ts":{"20":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","25":[86,124],"28":[86,124],"36":[86,124],"44":[86,124],"53":[86,124],"67":[86,124],"84":[86,124],"92":[86,124],"100":[86,124],"107":[86,124],"124":[86,124],"132":[86,124],"145":[86,124],"160":[86,124],"177":[86,124],"184":[86,124],"195":[86,124],"212":[86,124],"221":[86,124],"236":[86,124,161]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentsN8nChatFlag.ts":{"8":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","17":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","24":"b:AAABMB4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","27":"b:AAABMB4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","31":"b:AAABMB4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","32":"b:AAABMB4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","43":[86,124]},"packages/frontend/editor-ui/src/features/agents/composables/useCreateAgent.ts":{"17":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","21":[86,124]},"packages/frontend/editor-ui/src/features/agents/module.descriptor.ts":{"22":[86,124],"23":[86,124],"24":[1,2,3,86,124],"25":[1,2,3,86,124],"26":[1,2,86,124],"27":[1,2,86,124],"28":[3,86,124],"29":[3,86,124],"30":[3,86,124],"31":[3,86,124],"32":[86,124],"33":[86,124],"34":[86,124],"35":[86,124],"39":[86,124],"54":[86,124],"172":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA="},"packages/frontend/editor-ui/src/features/agents/n8nChatPage/n8nChatThreads.store.ts":{"20":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA="},"packages/frontend/editor-ui/src/features/agents/n8nChatPage/useRecentChats.ts":{"19":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","25":[88,22,25,44,45,63],"31":[88,22,25,44,45,63]},"packages/frontend/editor-ui/src/features/agents/utils/agentNode.ts":{"10":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","27":[86,124],"32":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/assistant.store.ts":{"37":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","45":"b:8E/CAKDjAQDk/3cIH5BQHOx/DUfwP/9/mP//BwA=","58":[6,86,124],"59":[6,86,124],"79":[5,6,7,8,144,86,146,11,124,131],"80":[5,6,8,86,124],"82":[5,6,7,8,86,124],"84":[5,6,7,8,144,86,146,11,124,131],"94":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","96":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","100":[5,6,7,86,124],"102":[5,7,86,124],"107":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","115":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","119":[5,6,7,8,86,124],"123":[5,6,7,8,86,124],"136":[5,6,7,8,86,124],"138":[5,6,7,8,86,124],"142":[5,6,7,8,86,124],"199":[5,6,86,124],"210":[7,86,124],"216":[5,6,7,8,86,124],"220":[5,6,7,8,86,124],"232":[86,124],"236":[86,124],"247":[5,6,7,8,86,124],"251":[5,7,8,86,124],"261":[86,124],"277":[5,6,7,8,86,124],"297":[5,6,7,8,86,124],"301":[5,6,7,8,86,124],"305":[5,6,7,8,86,124],"309":[86,124],"317":[7,86,124],"336":[5,8,86,124],"420":[5,7,8,86,124],"480":[5,7,8,86,124],"481":[5,7,8,86,124],"482":[86,124],"487":[86,124],"493":[5,6,86,124],"554":[5,6,86,124],"555":[5,6,86,124],"556":[86,124],"557":[86,124],"562":[6,86,124],"590":[6,86,124],"591":[6,86,124],"592":[86,124],"593":[86,124],"598":"b:cEcAEAjDAABAG3AIA5AQ2IQ3CAQAPjMlQOC3AwA=","629":[5,8,86,124],"639":[86,124],"640":[86,124],"679":[5,8,86,124],"680":[5,8,86,124],"681":[86,124],"692":[5,8,86,124],"706":[5,6,7,8,144,86,146,11,124,131],"746":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","747":"b:4EGCAKAiAUDkfXcIHxA0EOx7CQfwL5t/CPfuBwA=","753":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","756":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","764":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/builder.store.ts":{"166":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","188":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","190":[86,124],"202":[86,124],"211":[86,124],"230":"b:8E/+M6z7AYDk/3c4H5BQ3Px/v9/3//9/+P//BwA=","259":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","262":[144,86,11,124],"265":[144,86,11,124],"292":[86,124],"297":[86,124],"304":[144,86,11,124],"307":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","315":[86,124],"316":[86,124],"323":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","327":[144,86,11,124],"329":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","331":[86,124],"332":[86,124],"335":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","351":[86,124],"355":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","367":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","371":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","374":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","376":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","388":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","404":[86,124],"410":[144,86,11,124],"420":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","432":"b:8E/+M6z7AYDk/3c4H5BQ3Px/v9/3//9/+P//BwA=","450":[86,124],"457":[86,124],"462":"b:cEcAEAjDAABAG3AIA5AQ2IQ3AAQAPjMlQOC3AwA=","469":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","477":[144,86,11,124],"481":[144,86,11,124],"485":[86,124],"491":[86,124],"503":[144,86,11,124],"530":[144,86,11,124],"531":[144,86,11,124],"541":[86,124],"573":[86,124],"580":[144,86,11,124],"644":[86,11,124],"655":[86,11,124],"664":[86,11,124],"695":[144,86,11,124],"726":[144,86,11,124],"727":[86,124],"729":[86,124],"739":[144,86,11,124],"816":[144,86,11,124],"832":[144,86,11,124],"864":[144,86,124],"889":[144,86,11,124],"912":[86,124],"1014":[86,124],"1025":[144,86,124],"1028":[144,86,124],"1050":[144,86,124],"1057":[86,11,124],"1067":[86,124],"1078":[86,124],"1128":[144,86,146,11,124],"1221":[86,124],"1235":[86,124],"1353":[86,124],"1364":[86,124],"1372":[86,124],"1387":[86,124],"1397":[144,86,124],"1402":[144,86,124],"1404":[86,124],"1411":[86,124],"1424":[86,124],"1429":[144,86,11,124],"1440":"b:AAEAAAAAAACkCVEAAxAQEMA4AQAAIAIBAGSgAwA=","1448":"b:AAEAAAAAAACkCVEAAxAQEMA4AQAAIAIBAGSgAwA=","1456":[144,86,124],"1460":[144,86,146,11,124],"1465":[144,86,146,11,124],"1479":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","1480":"b:8E/CAKDjAQDk/3cIH5BQHOx/P0fwP/9/+P//BwA=","1513":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","1525":[144,86,124],"1546":[144,86,124],"1577":[86,124],"1605":[86,124],"1610":[86,124],"1632":[86,124],"1648":[86,124],"1677":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA="},"packages/frontend/editor-ui/src/features/ai/assistant/chatPanel.store.ts":{"32":[5,6,7,8,144,86,146,11,124,131],"39":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","50":[5,6,7,8,86,124,131],"58":[5,6,7,8,144,86,146,11,124,131],"63":[86,124],"64":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","66":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","69":[5,6,7,8,144,86,146,11,124,131],"103":[5,7,86,124],"110":[5,6,7,8,144,86,11,124,131],"119":[5,86,124],"127":[5,86,124],"142":[5,8,144,86,146,11,124,131],"150":[5,6,7,8,144,86,11,124,131],"168":[86,124],"182":[7,86,124],"200":[5,6,86,124],"216":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","217":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","254":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","255":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","256":[86,124],"257":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/chatPanelState.store.ts":{"14":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/AskAssistantBuild.vue":{"71":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","84":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","106":[86,124],"114":[144,86,124],"121":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","122":[86,124],"128":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","132":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","137":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","141":[86,124],"147":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","152":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","163":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","164":[144,86,11,124],"166":[144,86,11,124],"174":[144,86,11,124],"175":[144,86,11,124],"178":[144,86,11,124],"194":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","195":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","196":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","199":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","205":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","212":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","219":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","223":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","236":[86,124],"241":[144,86,124],"246":[86,124],"254":[86,124],"263":[86,124],"275":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","299":[86,124],"303":[86,124],"307":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","323":[86,124],"325":[86,124],"339":"b:EE6CAKDjAUDk/3cIH5B0HOR/OUfwP/9/mP+/BwA=","341":[144,86,11,124],"352":[86,124],"354":[86,124],"357":[86,124],"360":[86,124],"388":[144,86,11,124],"404":[144,86,124],"413":"b:AAA+Mww4AYAgg1Y4HAAA0DADgJgHwAAACAiAAwA=","421":[86,124],"439":[86,124],"509":[86,124],"512":[86,124],"527":[86,124],"539":[144,86,124],"553":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","555":"b:AAg+Mww4AYAgg1Y4HAAA0DADgZgHwAAACAiAAwA=","590":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","591":[144,86,11,124],"603":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","605":[144,86,11,124],"634":[86,124],"668":[86,124],"680":"b:AAA+Mww4AYAgg1Y4HAAA0DADgJgHwAAACAiAAwA=","687":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","688":[86,124],"690":[86,124],"699":[144,86,11,124],"705":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","708":[144,86,11,124],"727":[86,124],"729":[86,124],"735":[86,124],"739":[144,86,146,11,124],"741":[86,124],"745":[144,86,124],"749":[86,124],"752":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","766":[86,124],"767":[86,124],"770":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","775":[144,86,11,124],"782":"b:EEaCAKDjAUDk/3cIH5B0HOR/OEfwP/9/mP+/BwA=","785":[144,86,124],"791":[86,124],"805":[86,124],"806":[86,124],"837":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","867":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","869":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","877":"b:EE6CAKDjAUDk/3cIH5B0HOR/OUfwP/9/mP+/BwA=","905":[86,124],"907":"b:EE6CAKDjAUDk/3cIH5B0HOR/OUfwP/9/mP+/BwA="},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/BuildModeEmptyState.vue":{"5":"b:EEaCAKDjAUDk/3cIH5B0HOR/OEfwP/9/mP+/BwA=","6":"b:EEaCAKDjAUDk33cIH5B0HOR/OEfwP/9/mP+/BwA="},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/PlanModeSelector.vue":{"14":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","24":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","43":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","44":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","47":[86,124],"50":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","65":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","68":"b:Pk7/8777Adzk/3c7H5B83vT/v///////////BwA=","70":"b:Pk7/8777Adzk/3c7H5B83vT/v///////////BwA=","72":"b:Pk7/8777Adzk/3c7H5B83vT/v///////////BwA="},"packages/frontend/editor-ui/src/features/ai/assistant/components/AssistantsHub.vue":{"19":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","36":[86,124],"39":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","40":[5,6,7,8,144,86,146,11,124,131],"51":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","55":[86,124],"59":[86,124],"63":[86,124],"85":[5,86,124],"89":[5,6,7,8,144,86,11,124,131],"98":"b:8E8AEAjDAABAG3AIA5AQ2Iw3DQQAPjMlQOC3AwA=","106":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","112":"b:5E2+M6w6AZBk/3c4HxBQ1PR/iZ9X/7d/Cf7/AwA=","124":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","137":[86,124],"141":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","150":"b:/k//87z7Adzk33c7H5B83vz/v///////////BwA=","164":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","169":[144,86,146,11,124],"175":[86,124],"176":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/components/FocusedNodes/ChatInputWithMention.vue":{"24":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","45":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","66":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","67":[144,86,11,124],"73":[144,86,11,124],"91":[86,124],"92":[86,124],"93":[86,124],"95":[86,124],"99":[86,124],"103":[144,86,124],"114":[144,86,11,124],"121":[144,86,11,124],"127":[86,11,124],"131":[86,124],"135":[86,124],"138":[86,124],"144":[86,124],"146":[86,124],"151":[86,124],"155":[86,124],"159":[144,86,11,124],"163":[86,124],"174":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","199":[86,124],"216":[86,124],"219":[86,124],"220":[86,124],"223":[86,124],"242":[86,124],"245":[86,124],"254":[86,124],"267":[86,124],"283":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","288":[86,124],"293":[86,124],"306":[86,124],"309":[86,124],"310":[86,124],"317":[86,124],"344":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useAIAssistantHelpers.ts":{"45":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","47":[5,6,7,86,124],"62":[5,6,7,86,124],"74":[86,124],"81":[5,6,7,86,124],"100":[86,124],"101":[86,124],"113":[86,124],"122":[86,124],"131":[86,124],"137":[86,124],"163":[86,124],"180":[86,124],"207":[5,6,86,124],"214":[5,6,86,124],"227":[5,6,7,8,86,124],"251":[7,86,124],"276":[5,6,86,124],"298":[5,6,7,86,124],"301":[5,6,7,86,124],"309":[5,6,7,144,86,124],"335":[5,8,86,124],"357":[8,86,124],"379":[8,86,124],"420":[5,8,144,86,11,124],"428":[86,124],"447":[86,124],"465":[86,124],"509":[86,124],"582":[86,124],"596":[86,124],"632":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useAskModeCoachmark.ts":{"14":[144,86,146,11,124],"17":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","25":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","27":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","35":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","49":[86,124],"59":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useBuilderMessages.ts":{"29":[86,124],"44":[86,124],"55":[86,124],"69":[86,124],"82":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","88":[144,86,11,124],"89":[144,86,11,124],"104":[86,124],"141":[86,124],"166":[86,124],"173":[86,124],"208":[144,86,124],"262":[86,124],"269":[86,124],"276":[86,124],"282":[86,124],"326":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","327":[144,86,11,124],"330":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","331":[86,124],"342":[144,86,124],"354":[86,124],"355":[86,124],"395":[144,86,124],"419":[144,86,124],"436":[144,86,124],"460":[144,86,124],"462":[144,86,124],"471":[144,86,11,124],"492":[86,124],"517":[86,11,124],"541":[86,124],"556":"b:8E/+M6z7AYDk/3c4H5BQ3Px/v9/3//9/+P//BwA=","560":[86,124],"567":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useBuilderTodos.ts":{"37":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","47":[144,86,124],"89":[144,86,124],"129":[144,86,11,124],"138":[144,86,124],"151":[144,86,11,124],"206":[144,86,11,124],"212":[144,86,124],"221":[86,124],"246":[144,86,11,124],"247":[144,86,124],"254":[144,86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useCodeDiff.ts":{"28":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","31":[6,86,124],"41":[6,86,124],"43":[6,86,124],"64":[6,86,124],"68":[6,86,124],"74":[6,86,124],"87":[6,86,124],"133":[6,86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useFocusedNodesChipUI.ts":{"14":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","19":[86,124],"20":[86,124],"21":[86,124],"22":[86,124],"24":[86,124],"31":[86,124],"39":[86,124],"40":[86,124],"42":[86,124],"48":[86,124],"54":[86,124],"58":[86,124],"68":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useNodeMention.ts":{"32":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","46":[86,124],"51":[86,124],"54":[86,124],"61":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","62":"b:AECCkKwiAADk/XEIDxAQ0ORqCQFAIJhOSN8qAAA=","70":[86,124],"85":[86,124],"104":[86,124],"126":[86,124],"155":[144,86,11,124],"200":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useReviewChanges.ts":{"34":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","46":[86,124],"51":[86,124],"71":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","73":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","100":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","101":[144,86,124],"115":[144,86,124],"116":[86,124],"134":[144,86,124],"138":[86,124],"140":[86,124],"141":[86,124],"163":[144,86,124],"168":[144,86,124],"205":[86,124],"210":[86,124],"212":[86,124],"213":[86,124],"227":[86,124],"231":[86,124],"241":[86,124],"255":[5,6,7,8,86,124,131],"269":[86,124],"278":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","279":[144,86,11,124],"288":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","289":[144,86,124],"299":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","300":[144,86,146,11,124],"309":[5,6,7,8,86,124,131],"313":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","322":[86,124],"328":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/focusedNodes.store.ts":{"27":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","29":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","36":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","42":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","52":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","53":[86,124],"56":[86,124],"57":[86,124],"60":[86,124],"73":[86,124],"78":[86,124],"80":[86,124],"82":[86,124],"84":[86,124],"88":[86,124],"92":[86,124],"93":[86,124],"101":[86,124],"139":[86,124],"169":[86,124],"174":[86,124],"189":[86,124],"206":[86,124],"219":[86,124],"226":[86,124],"233":[86,124],"240":[86,124],"241":[86,124],"247":[144,86,11,124],"249":[86,124],"273":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","274":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","289":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","290":"b:8E/CkKzjAUDk/3cIH5B03Ox/P0fwP/9/+P//BwA=","292":"b:8EeCkKzjAUDk/3cIH5B03Ox/OUfwP/9/2P+/BwA=","318":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","319":"b:8E/CkKzjAUDk/3cIH5B03Ox/P0fwP/9/+P//BwA=","331":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","332":"b:4EWCAKgiAEBkfXEIBxB0FOR/KAdQO7d/CPY/AAA=","341":[144,86,11,124]},"packages/frontend/editor-ui/src/features/ai/chatHub/chat.store.ts":{"108":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","137":[86,18,155,19,156,20,21,124],"140":[86,18,155,19,156,20,21,124],"147":[86,18,155,19,156,20,21,124],"163":[86,18,155,19,156,20,21,124],"173":[86,18,155,19,156,20,21,124],"177":[86,18,155,19,156,20,21,124],"214":[86,18,155,19,156,20,21,124],"237":[86,124],"279":[86,18,155,19,156,20,21,124],"291":[86,124],"305":[86,18,155,19,156,124],"315":[86,18,155,19,156,20,21,124],"334":[86,18,155,19,156,20,21,124],"341":[86,20,124],"347":[86,124],"349":[86,124],"355":[86,124],"357":[86,124],"363":[86,124],"365":[86,124],"368":[86,18,155,19,156,20,21,124],"371":[86,18,155,19,156,20,21,124],"377":[86,18,155,19,156,20,21,124],"382":[86,18,155,19,156,20,21,124],"411":[86,18,155,19,156,20,21,124],"435":[86,124],"441":[86,18,124],"447":[86,18,124],"458":[86,18,155,19,156,20,21,124],"467":[86,18,155,19,156,20,21,124],"484":[86,20,21,124],"497":[86,124],"517":[86,124],"544":[86,124],"555":[86,124],"568":[86,124],"595":[86,18,155,19,156,20,21,124],"610":[86,18,124],"657":[86,20,124],"694":[86,124],"715":[86,124],"729":[86,124],"797":[86,124],"868":[86,124],"883":[86,124],"894":[86,124],"900":[86,124],"907":[86,124],"915":[86,124],"925":[86,124],"931":[86,124],"942":[86,124],"946":[86,124],"949":[86,124],"961":[86,156,124],"967":[86,124],"968":[86,124],"973":[86,124],"985":[86,156,124],"996":[86,156,124],"999":[86,124],"1031":[86,156,124],"1052":[86,124],"1056":[86,156,124],"1076":[86,156,124],"1081":[86,156,124],"1091":[86,18,155,19,156,20,21,124],"1095":[86,18,155,19,156,20,21,124],"1106":[86,157,124],"1117":[86,157,124],"1127":[86,124],"1133":[86,157,124],"1150":[86,18,155,19,156,20,21,124],"1196":[86,18,155,19,156,124],"1214":[86,18,155,19,156,20,21,124],"1230":[86,20,21,124],"1252":[86,18,155,19,156,20,21,124],"1294":[86,18,155,19,156,20,21,124],"1335":[86,18,155,19,156,20,21,124],"1362":[86,18,155,19,156,20,21,124],"1392":[86,18,124],"1413":[86,124],"1447":[86,124],"1465":[86,124],"1492":[86,124],"1519":[86,124],"1531":[86,18,155,19,156,20,21,124],"1532":[86,18,155,19,156,20,21,124],"1557":[86,18,155,19,156,20,21,124],"1558":[86,18,155,19,156,20,21,124]},"packages/frontend/editor-ui/src/features/ai/chatHub/chatHubPanel.store.ts":{"12":[86,124],"19":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","29":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/2P//BwA=","39":[86,124],"45":[86,124],"52":[86,124],"60":[86,124],"66":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","67":"b:gAA+Mww4AYAgg1Y4HAAA0DADgJgHwAAACAiAAwA="},"packages/frontend/editor-ui/src/features/ai/chatHub/module.descriptor.ts":{"18":[86,18,155,19,156,20,21,124],"19":[86,21,124],"20":[86,21,124],"21":[86,156,124],"22":[86,156,124],"23":[86,157,124],"24":[86,157,124],"34":[86,124],"40":[86,124],"46":[86,20,124],"51":[86,124],"57":[86,156,124],"62":[86,124],"63":[86,124],"69":[86,19,124],"75":[86,124],"81":[86,124],"87":[86,124],"93":[86,157,124],"99":[86,124],"100":[86,124],"113":[86,124],"127":[86,124],"141":[86,124],"155":[86,124],"176":[86,124],"203":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA="},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/components/EvaluationsCanvasInfoCard/EvaluationsCanvasInfoCard.vue":{"25":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","74":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","85":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","99":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","103":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","134":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","159":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","182":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA="},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/composables/useAiRootNodes.ts":{"15":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA="},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/composables/useEvaluationsLicense.ts":{"9":[145],"12":"b:8E/CkKzjAQDk/zcIH5BQzOx/P0fwP/9/2P//BwA="},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/evaluation.store.ts":{"11":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/D0fwP/9/mP//BwA=","26":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","28":[86,124],"30":[86,124],"31":[86,124],"45":[145,86,124],"52":[145,86,124],"65":[145,86,124],"69":[145,86,124],"81":[86,124],"87":[86,124],"99":[86,124],"108":[86,124],"127":[86,124],"138":[145,86,124],"147":[86,124],"160":[86,124],"175":[86,124],"176":[86,124],"182":[86,124],"187":[86,124],"198":[86,124],"199":[86,124]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/wizardSidepanel.store.ts":{"29":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","32":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useAddNodesToChat.ts":{"18":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","27":[86,124],"43":[86,124]},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useInstanceAiAvailability.ts":{"14":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","16":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","42":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","45":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useInstanceAiHandoff.ts":{"43":[86,124],"52":[86,124],"53":[86,124],"66":[86,124],"78":[86,124],"89":[86,124,30,92,31,161,36],"90":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","92":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","93":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","95":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","97":[86,124,30,92,31,161,162,36],"113":[86,124],"134":[86,124],"165":[86,124,36],"173":[86,124,30,92,31,161,36],"197":[86,124],"204":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","215":[86,124,161],"224":[86,124],"235":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","260":[86,124,161],"264":[86,124],"271":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","282":[86,124,161],"291":[86,124,162],"298":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","311":[86,124,161],"321":[86,124,162],"325":[86,124,30,92,31,161,36],"332":[86,124,161],"337":[86,124,161],"341":[86,124,30,92,31,161,162,36],"344":[86,124],"354":[86,124,161],"358":[86,124,30,92,31,161,162,36],"369":[86,124,161],"380":[86,124,36],"398":[86,124,36],"422":[86,124,162],"456":[86,124],"483":[86,124],"525":[86,124],"549":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","564":[86,124],"568":[86,124],"575":[86,124],"615":[86,124],"683":[86,124],"718":[86,124]},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useInstanceAiHandoffCapability.ts":{"37":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","51":[86,124],"71":[86,124],"79":[86,124],"93":[86,124],"132":[86,124],"168":[86,124],"194":[86,124]},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useIsNodeContextEnabled.ts":{"8":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","12":"b:8E+CkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/2P+/BwA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAi.memory.api.ts":{"17":"b:Hkbj8777AZjk/3c5F5BQ3vR/isf3//9/mf//BwA=","23":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","30":[86,124,30,92,31,161],"37":[86,124,161],"41":[86,124,161],"51":[86,124],"61":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","68":[86,124,28,126,34,35,127],"82":[86,124],"95":[86,124,30,92,31,161,162,36],"112":[86,124,30,92,126,31,161,35,36],"119":[86,124],"126":[86,124]},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAi.store.ts":{"54":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","62":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","90":[86,124],"94":[86,124,28,29,92,126,159,160,161,35,127],"97":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","101":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","106":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","113":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","117":[86,124,161],"128":[86,124],"129":[86,124],"130":[86,124],"133":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","144":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","156":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","165":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","168":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","176":[86,124],"190":[86,124],"197":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","210":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","221":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","222":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","225":"b:Hkbj8777AZjk/3c5F5BQ3vR/isf3//9/mf//BwA=","233":"b:AAAA8BgAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","234":"b:AAAA8BgAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","244":[86,124,30,92,31,161],"247":[86,124,30,92,31,161],"256":"b:AAAAMAwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","262":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","288":[86,124],"289":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","294":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","315":[86,124,159,160,161],"335":[86,124,161],"353":[86,124,161],"354":[86,124,161],"360":[86,124,161],"378":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","379":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","383":[86,124],"384":[86,124],"393":[86,124],"394":[86,124],"398":[86,124],"414":[86,124],"415":[86,124],"428":[86,124],"435":[86,124],"440":[86,124],"449":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","452":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","458":[86,124,28,126,159,160,34,35,127],"465":[86,124],"526":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","536":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAiPermissions.ts":{"4":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","9":"b:/k/38777Ad7k/3c5F5B83vz/j///////n///BwA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAiSettings.store.ts":{"52":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","82":[86,124],"91":[86,124],"94":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","98":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","101":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","104":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","110":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","113":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","122":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","128":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","131":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","134":[86,16,124],"137":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","142":[86,124,33],"175":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","178":[86,124],"181":[86,124,33],"185":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","225":[86,124,33],"241":[86,124],"253":[86,124],"260":[86,124],"279":[86,124],"293":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","300":[86,124],"301":[86,124],"305":[86,124],"309":[86,124],"315":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","324":[86,124],"342":[86,124,33],"350":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","356":[86,124],"361":[86,124],"371":[86,16,124,33],"386":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","399":[86,124],"409":[86,124],"427":[86,124],"454":[86,124],"498":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","501":[86,124,28,126,31,34,35,127],"520":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","521":[86,16,124],"531":[86,124],"542":[86,124],"550":[86,124],"570":[86,124,33],"579":[86,124],"588":[86,124],"594":[86,124],"595":[86,124],"599":[86,124],"600":[86,124],"609":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","613":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","621":[86,124],"627":[86,124],"633":[86,124,33]},"packages/frontend/editor-ui/src/features/ai/instanceAi/module.descriptor.ts":{"41":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA=","61":[86,124],"78":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","79":"b:AAABMB4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","80":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","81":[86,124],"82":[86,124],"93":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","103":[86,124,162,36],"158":"b:AAABMB4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","187":[86,124],"191":[86,124],"202":[86,124],"222":[86,124],"232":[86,124],"250":[86,124],"251":[86,124],"254":[86,124],"255":[86,124],"268":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA="},"packages/frontend/editor-ui/src/features/collaboration/collaboration/collaboration.store.ts":{"33":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","77":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","81":[86,124],"85":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","86":"b:8EeCkIyjAADk+3UIH5BQ3Ox/CUUAPndlmP7/AwA=","89":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","93":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","97":"b:8E+CkIzjAADk+3cIH5BQ3Ox/C0UAPndlmP7/AwA=","119":"b:8E+CkIzjAADk+3UIH5BQ3Ox/C0UAPndlmP7/AwA=","124":[86,124,28,127,45,203,98,79],"128":[86,124,28,127,45,203,98,79],"133":"b:8E+CkIzrAADk+3cIH5BQ3Ox/C0UAPndlmP7/AwA=","140":"b:8E+CkIzjAADk+3UIH5BQ3Ox/C0UAPndlmP7/AwA=","145":"b:wAGCEAAgAADk6VEADxAQkOx6AQAAMBJFAH6qAwA=","152":[86,124],"164":"b:wAGCAAAAAADk6VEADxAQEOx6AQAAMBJFAHaqAwA=","172":"b:wAGCEAAgAADk6VEADxAQkOx6AQAAMBJFAH6qAwA=","183":[86,124],"198":[86,124],"204":[86,124],"209":[86,124],"214":[86,124],"218":"b:wAGCAAAAAADk6VEADxAQEOx6AQAAMBJFAHaqAwA=","222":"b:4EmCAKAiAADk/XcIDxAQEOx7CQfwP5t/CPfuBwA=","243":[86,124],"261":[86,124,98],"280":"b:AAQAAAAgAAAAA1AgAQAAEEASAEAAIAAAEARkAQA=","295":"b:8E+CkIzjAADk+3UIH5BQ3Ox/C0UAPndlmP7/AwA=","302":"b:8E+CkIzjAADk+3UIH5BQ3Ox/C0UAPndlmP7/AwA=","307":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","311":"b:4EGCEAAiAEDkuXcIFxAUkOR7CQQALANlAO7mAwA=","316":[86,124,173],"326":[86,124,173],"332":"b:AAEAAACAAACkiVEAAxAQEMA4AQAAMAIBAGTgAwA=","359":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","360":"b:4EGCAKAiAUDkfXcIHxA0EOx7CQfwL5t/CPfuBwA=","369":"b:8EeCkIyjAADk+3UIH5BQ3Ox/C0UAPndlmP7/AwA=","372":[86,17,23,124,70,134,201,135,202,75,209,142],"381":"b:8E+CkIzjAADk+3cIH5BQ3Ox/C0UAPndlmP7/AwA=","404":"b:8EeCkIzjAADk+3UIH5BQ3Ox/C0UAPndlmP7/AwA=","460":[86,124,28,127,45,203,98,79]},"packages/frontend/editor-ui/src/features/collaboration/collaboration/components/CollaborationPane.vue":{"11":"b:8E+CkIzrAADk+zcIH5BQzOx/C0UAPndlmP7/AwA=","15":[122,31,43,47,66,96,134,71,204,98,213,99,81],"24":"b:8E+CkIzrAADk+zcIH5BQzOx/C0UAPndlmP7/AwA=","26":[43,99],"27":[43,99],"29":[43,99],"35":[43,99],"37":"b:8E+CkIzrAADk+zcIH5BQzOx/C0UAPndlmP7/AwA=","41":[28,127,43,45,203,98,79],"44":"b:8E+CkIzrAADk+zcIH5BQzOx/C0UAPndlmP7/AwA="},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectCardBadge.vue":{"23":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","32":"b:AACCAgA4ABAAAEIJHAAAEjAAAAAEAAAAAAgAAAA=","37":"b:AACCAgA4ABAAAEIJHAAAEjAAAAAEAAAAAAgAAAA=","46":"b:AACCAgA4ABAAAEIJHAAAEjAAAAAEAAAAAAgAAAA=","50":"b:AACCAgA4ABAAAEIJHAAAEjAAAAAEAAAAAAgAAAA=","73":"b:AACCAgA4ABAAAEIJHAAAEjAAAAAEAAAAAAgAAAA=","77":"b:AACCAgA4ABAAAEIJHAAAEjAAAAAEAAAAAAgAAAA=","89":"b:AACCAgA4ABAAAEIJHAAAEjAAAAAEAAAAAAgAAAA=","105":"b:AACCAgA4ABAAAEIJHAAAEjAAAAAEAAAAAAgAAAA=","148":"b:AACCAgA4ABAAAEIJHAAAEjAAAAAEAAAAAAgAAAA=","162":"b:AACCAgA4ABAAAEIJHAAAEjAAAAAEAAAAAAgAAAA=","174":"b:AACCAgA4ABAAAEIJHAAAEjAAAAAEAAAAAAgAAAA=","177":[86,121,88,162,43,44,45,203,98,99,81,100],"182":[86],"197":[86],"215":[86]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectIcon.vue":{"13":"b:/k/i87z7ARDk/3c5H5BQ3vx/D+f3//9/mP//BwA=","14":"b:/k/i87z7ARDk33c5H5BQ3vx/D+f3//9/mP//BwA=","35":[86,45]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectNavigation.vue":{"48":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","77":"b:/k/j8777ARjk/zc7H5BQzvx/j8f3//9/nf//BwA=","78":[63],"79":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","85":"b:/k/j8777ARjk/zc7H5BQzvx/j8f3//9/nf//BwA=","86":"b:/k/j8777ARjk/zc7H5BQzvx/j8f3//9/nf//BwA=","89":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","101":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","108":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","132":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","141":"b:/k/j8777ARjk/zc7H5BQzvx/j8f3//9/nf//BwA=","150":"b:AACiAoC4ABAEQQMgHgBQCsxFBUIQyNtqmBBgAQA=","162":"b:/k/j8777ARjk/zc7H5BQzvx/j8f3//9/nf//BwA=","174":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","176":"b:Hkbj8777AZjk/zc5F5BQzvR/isf3//9/mf//BwA=","186":[161],"190":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","192":"b:HkbjM777AZjk/zc5F5BQzvR/isf3//9/mf//BwA=","197":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","223":[21],"236":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","243":[162,45,195,203,98,99,79,81,82,100],"248":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","403":[25,44,45,99],"420":"b:AACiAoC4ABAEQQMgHgBQCsxFBUIQyNtqmBBgAQA="},"packages/frontend/editor-ui/src/features/collaboration/projects/composables/useFavoriteNavItems.ts":{"23":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA=","155":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/nf//BwA="},"packages/frontend/editor-ui/src/features/collaboration/projects/composables/useMoveResourceToProjectToast.ts":{"21":"b:8E/CkKzzAQDk/3cIH5BQ3Ox/D0fwP/9/mP//BwA=","26":[86,124,44],"45":[86,124]},"packages/frontend/editor-ui/src/features/collaboration/projects/composables/useProjectPages.ts":{"9":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/3f//BwA=","13":"b:AACiAgA4ABAAAAIgCAAAAgAAAAAAwAAACAAAAAA=","16":"b:gACjAwA4AJgAgAIrHAAAAjAAgAAEwAAADQgAAAA=","19":"b:gACjAwA4AJgAgAIrHAAAAjAAgAAEwAAADQgAAAA="},"packages/frontend/editor-ui/src/features/collaboration/projects/projects.api.ts":{"9":[86,21,124,175,45,60],"13":[86,124,44,118,81],"29":[86,157,91,124,194,195,132,133,196,81],"47":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","51":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","55":"b:jgCiAwA4ABAEwEIoDABAGjBAAQAAwAAACAAAAAA=","59":[86,124,175,45],"66":[86,124,175,45],"74":[86,124],"87":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","91":[86,21,124,175],"99":[86,21,124],"108":[86,124],"116":[86,124]},"packages/frontend/editor-ui/src/features/collaboration/projects/projects.routes.ts":{"9":"b:AAABAwA4AIgAgEIjHAAAEgAAgAAEwAAADAgAAAA=","10":[7,86,17,23,91,124,44,45,60,132,133],"11":[7,86,17,23,91,124,44,45,60,132,133],"12":[86,21,124,175,45],"13":[86,124],"14":[86,124],"15":[86,124,192],"17":"b:gAADAQAwAIgAAEILHAAAEjAAgAAEgAAABQgAAAA=","18":"b:gAADAQAwAIgAAEILHAAAEjAAgAAEgAAABQgAAAA=","19":"b:gAADAQAwAIgAAEILHAAAEjAAgAAEgAAABQgAAAA=","25":[86,124],"28":"b:gACLAwA4AJgAgEIrHAAAEjAAgAAEwAAADQgAAAA=","32":"b:gACCAwA4ABAAgEIoCAAAEjAAAAAAQAAACAAAAAA=","43":"b:AAAJAwA4AIgAgEIjHAAAEgAAgAAEwAAADAgAAAA=","54":[7,86,17,23,91,124,44,45,60,132,133],"64":[86,124],"74":[86,124,93,43,174],"84":[86,124,192],"144":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","156":[86,21,124,175,45],"157":[86,21,124,175,45],"183":"b:gAALAQAwAIgAAEILHAAAEjAAgAAEgAAABQgAAAA=","197":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","218":[86,124],"230":[86,124]},"packages/frontend/editor-ui/src/features/collaboration/projects/projects.store.ts":{"42":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","62":[86,124,44,118,81],"65":[86,124,81],"69":"b:/k//8777Ad7k/3c7H5B83vz/v///////////BwA=","75":[86,124,81],"76":[86,124],"77":[86,124],"79":[86,157,91,124,132,133],"80":"b:/k/38777Ad7k/3c7H5B83vz/j///////n///BwA=","81":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","82":"b:/k/38777Ad7k/3c7H5B83vz/j///////n///BwA=","83":[86,124],"86":"b:/k/38777Ad7k/3c7H5B83vz/j///////n///BwA=","92":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","95":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","100":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","101":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","106":"b:gAC/8x4wAIgAQEIbHAAA2jBAgZgHgAAABQgAAAA=","110":[86,21,124,175,45,60],"114":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","118":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","122":[86,124],"130":[86,124,44,118,81],"140":[86,157,91,124,194,195,132,133,196,81],"150":"b:jgCiAwA4ABAEwEIoDABAGjBAAQAAwAAACAAAAAA=","153":"b:jgCiAwA4ABAEgEIoCABAEjAAAAAAwAAACAAAAAA=","157":[144,86,17,123,23,124,45,78,98,142],"164":"b:/k//8777Ad7k/3c7H5B83vz/v///////////BwA=","170":[86,124,175,45],"177":[86,124,175,45],"185":[86,124,175,45],"203":[86,124],"211":[86,124],"222":[86,21,124,175],"230":[86,21,124],"239":[86,124],"244":[86,124],"247":[86,124],"250":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","254":"b:EAYAkAzhAACEo1YAHYBQ3GwfAkAAEnYBmDi3AwA=","262":[86,124,133],"294":[86,124,44],"317":[86,124],"331":[86,21,124,175,45],"342":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/features/collaboration/projects/projects.utils.ts":{"21":[86,157,91,124,194,195,132,133,196,81],"25":[86,157,91,124,194,195,132,133,196,81],"39":"b:AACCAAA4ABAAAEIpHABAEjAAAAAEQAAAAQgAAAA=","41":[86,44,118,81],"50":[86],"58":"b:gACCAoC4ABAgYHYIHABAEDAAACgAAIAAHAAAAAA=","74":[86,124],"78":[86,124],"86":[86,124,44],"91":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/features/core/dataTable/components/NodeStorageLimitCallout.vue":{"9":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","13":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","28":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","31":[86,124]},"packages/frontend/editor-ui/src/features/core/dataTable/dataTable.api.ts":{"13":"b:AAABAwAwAIgAAEIDHAAAEgAAgAAEgAAABAAAAAA=","40":[86,124,24,25],"61":[86,124,25],"77":[86,124,24],"93":[86,124,24],"109":[86,124,24],"122":[86,124,24],"139":[86,124],"156":[86,124,24,25],"176":[86,124,24],"193":[86,124,24],"214":[86,124,24],"220":[86,124,24],"238":"b:/k/38777Ad7k/3c7H5B83vz/j///////n///BwA=","246":[86,124],"269":[86,124],"283":[86,124]},"packages/frontend/editor-ui/src/features/core/dataTable/dataTable.store.ts":{"37":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","50":[86,124,24,25],"56":"b:/k/38777Ad7k/3c7H5B83vz/j///////n///BwA=","60":[86,124],"64":[86,124,24,25],"72":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","76":"b:AAABAwAwAIgAAEIDHAAAEgAAgAAEgAAABAAAAAA=","101":[86,124,24,25],"127":[86,124],"131":[86,124],"158":[86,124],"172":[86,124],"176":[86,124,25],"179":[86,124,25],"185":[86,124,24],"197":[86,124,24],"199":[86,124,24],"207":[86,124,24],"215":[86,124,24],"224":[86,124],"238":[86,124],"246":[86,124,24,25],"247":[86,124,24,25],"254":[86,124,24],"266":[86,124,24],"274":[86,124,24],"288":[86,124,24],"289":[86,124,24],"299":[86,124],"313":[86,124],"317":[86,124],"323":[86,124,24,25],"341":[86,124,24],"353":[86,124],"363":[86,124,24],"378":[86,124,24],"382":"b:/k/38777Ad7k/3c7H5B83vz/j///////n///BwA=","396":[86,124],"403":[86,124],"424":[86,124],"445":[86,124],"446":[86,124]},"packages/frontend/editor-ui/src/features/core/folders/components/FolderBreadcrumbs.vue":{"59":"b:8E/CkKz7AQDk/zcoH5BQzOx/D0fwf/9/mP//BwA=","65":"b:8E/CkKz7AQDk/zcoH5BQzOx/D0fwf/9/mP//BwA=","67":"b:8E/CkKz7AQDk/zcoH5BQzOx/D0fwf/9/mP//BwA=","76":[43],"88":"b:8E/CkKz7AQDk/zcoH5BQzOx/D0fwf/9/mP//BwA=","92":[43,174],"96":[93,43,174,44,99,81],"107":"b:8E/CkKz7AQDk/zcoH5BQzOx/D0fwf/9/mP//BwA=","111":"b:8E/CkKz7AQDk/zcoH5BQzOx/D0fwf/9/mP//BwA=","147":[43],"162":[43],"174":[43,174],"185":[43,174],"196":[43],"208":"b:8E/CkKz7AQDk/zcoH5BQzOx/D0fwf/9/mP//BwA=","209":"b:8E/CkKz7AQDk/zcoH5BQzOx/D0fwf/9/mP//BwA=","212":"b:8E/CkKz7AQDk/zcoH5BQzOx/D0fwf/9/mP//BwA=","219":[28,127,174,44,45,203,98,99,79],"242":[43,174],"249":[43,174],"275":[93,43,174,44,99,81],"305":[43,174]},"packages/frontend/editor-ui/src/features/core/folders/components/ProjectBreadcrumb.vue":{"30":"b:8E/Ck6z7AQDk/zcoH5BQzOx/D0fwf/9/mP//BwA=","52":"b:8E/Ck6z7AQDk/zcoH5BQzOx/D0fwf/9/mP//BwA=","63":"b:8E/Ck6z7AQDk/zcoH5BQzOx/D0fwf/9/mP//BwA=","75":[43,174],"91":[43,174],"100":"b:8E/Ck6z7AQDk/zcoH5BQzOx/D0fwf/9/mP//BwA="},"packages/frontend/editor-ui/src/features/core/folders/composables/useFolders.ts":{"12":[86,124,93],"16":[86,124,93],"20":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","25":[86,124,93,43,174],"29":[86,124,43,174],"63":[86,124,93],"80":[86,124,93],"86":[86,124,93,43,174],"101":[86,124,93,43,174,44,81],"109":[86,124,93],"130":[86,124,93,43,174]},"packages/frontend/editor-ui/src/features/core/folders/composables/useParentFolder.ts":{"5":"b:8E/CkKzjAQDk/zcIH5BQzOx/P0fwP/9/+P//BwA=","11":"b:4EnCAKAiAABg/TMIBxAQCORrPQfwL4l+aMdOBQA="},"packages/frontend/editor-ui/src/features/core/folders/folders.constants.ts":{"16":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/features/core/folders/folders.store.ts":{"23":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","40":"b:AAABAwA4AIgAAEIhHABAEgAAAAAEwAAADAgAAAA=","41":[86,124,93,43,174],"52":[86,124,43,174],"56":[86,124,43,174],"64":[86,124,43,174],"75":[86,124,43,174],"81":[86,124,43,174],"99":"b:AAABAwA4AIgAgEIjHAAAEgAAgAAEwAAADAgAAAA=","115":[86,124,174],"116":[86,124,174],"121":[86,124,174],"125":[86,124,174],"130":[86,124],"134":[86,124,44,118],"174":[86,124],"183":[86,124],"190":[86,124],"206":[86,124],"219":[86,124,93],"229":[86,124],"249":[86,124,174],"262":[86,124,43],"273":[86,124,43],"286":[86,124],"342":[86,124,43]},"packages/frontend/editor-ui/src/features/credentials/components/NodeCredentials.vue":{"179":[7,84,85,86,17,23,124,39,183,77,78],"183":[86,124],"193":"b:gACSAIAAAAAAYHAIAAAAECAAAQAAIIAACAAAAAA=","211":[86,124],"225":"b:gACCAIQiAAAgYHEAAgAAEGAYAQNQAYVAAAQKAAA=","231":"b:AACSAAAAAAAAYHAIAABAFCQCAQAAIIAACAAAAAA=","237":[7,84,85,86,17,23,124,39,183,77,78],"239":"b:gACSAIQiAAAgYHEIAgBAFGQaAQNQIYVACAQKAAA=","255":"b:gEGSAKQiAABgZXEIAgBAFGQbCQdQIYVKCCQKAAA=","257":"b:4EWSAKyiAABkfXEIBxBQFOR/CQdQO7d/iPY/AgA=","269":"b:4EWSAKyiAABkfXEIBxBQFOR/CQdQO7d/iPY/AgA=","270":[86,153,23,124,130,173,77],"271":"b:gACSAKQiAAAgYHEIAgBAFGQaAQNQIYVACAQKAAA=","277":"b:gACSAKQiAAAgYHEAAgBAEGQaAQNQIYVACAQKAAA=","288":"b:gACSAKQiAAAgYHEIAgBAFGQaAQNQIYVACAQKAAA=","292":[86,124],"293":[86,124],"296":[86,124],"306":"b:gACSAKQiAAAgYHEIAgBAFGQaAQNQIYVACAQKAAA=","313":"b:AACSAAAAAAAAYHAIAABAFCQCAQAAIIAACAAAAAA=","319":"b:AACSAAAAAAAAYHAIAAAAECAAAQAAIIAACAAAAAA=","324":[86,124],"331":[86,124],"355":"b:AACSAAAgAAAAYHAIAABAFCQCAQAAIIAACAAAAAA=","359":"b:AACSAAAgAAAAIHAIAABAFCQCAQAAIIAACAAAAAA=","363":"b:AACSAAAAAAAAIHAIAABAFCQCAQAAIIAACAAAAAA=","368":"b:AACSAAAAAAAAYHAIAABAFCQCAQAAIIAACAAAAAA=","376":"b:gACSAKQiAAAgYHEIAgBAFGQaAQNQIYVACAQKAAA=","384":[86,124],"388":[86,124],"393":[86,124],"398":[86,124],"414":[86,124],"423":[86,124],"443":[86,124],"451":[86,124],"459":"b:4EWSAKyiAABkfXEIBxBQFOR/CQdQO7d/iPY/AgA=","460":"b:4EWSAKyiAABkfXEIBxBQFOR/CQdQO7d/iPY/AgA=","496":"b:4EWSAKyiAABkfXEIBxBQFOR/CQdQO7d/iPY/AgA=","561":"b:4EWCAKyiAABkfXEIBxBQFOR/CQdQO7d/iPY/AgA=","575":"b:4EWSAKyiAABkfXEIBxBQFOR/CQdQO7d/iPY/AgA=","576":"b:4EWSAKyiAABkfXEIBxBQFOR/CQdQO7d/iPY/AgA=","583":[7,84,85,17,23,124,39,183,77,78],"675":"b:4EWSAKiiAABkfXEIBxBQFOR/CQdQO7d/iPY/AgA=","680":"b:AACSAAAAAAAAYHAIAABAFCQCAQAAIIAACAAAAAA=","690":[86,122,124],"701":"b:AACSAAAAAAAAYHAIAABAFCQCAQAAIIAACAAAAAA=","713":[86,23,124],"732":[7,84,85,86,17,23,124,39,183,77,78],"770":[86,124,78],"780":"b:AACSAAAAAAAAYHAIAAAAECAAAQAAIIAACAAAAAA=","898":[86,17,23,124,195,133,77],"929":[86,124],"944":"b:gACSAKQiAAAgYHEIAgBAFGQaAQNQIYVACAQKAAA=","956":[86,124],"972":"b:gACSAIQiAAAgYHEIAgBAFGQaAQNQIYVACAQKAAA=","985":[86,124],"986":[86,124],"1002":[86,124],"1029":[86,124],"1036":[86,124],"1073":"b:AACSAAAAAAAAYHAIAABAFCQCAQAAIIAACAAAAAA=","1086":[86,124],"1094":[86,23,124],"1115":"b:gACSAKQiAAAgYHEIAgBAFGQaAQNQIYVACAQKAAA=","1135":[84,86,20,91,124,173,118],"1139":[84,86,122,20,23,91,124,173,195,118,133],"1150":[86,124],"1156":"b:AACSAAAAAAAAYHAIAABAFCQCAQAAIIAACAAAAAA=","1182":"b:4EWSAKyiAABkfXEIBxBQFOR/CQdQO7d/iPY/AgA=","1185":[86,124],"1193":[86,124],"1201":[86,124],"1220":"b:AACSAAAAAAAAYHAIAABAFCQCAQAAIIAACAAAAAA=","1228":"b:AACSAAAAAAAAYHAIAABAFCQCAQAAIIAACAAAAAA=","1247":"b:AACSAAAAAAAAYHAIAABAFCQCAQAAIIAACAAAAAA=","1269":[86,124],"1295":"b:AACSAAAAAAAAYHAIAABAFCQCAQAAIIAACAAAAAA=","1301":[86,124],"1309":"b:AACSAAAAAAAAYHAIAABAFCQCAQAAIIAACAAAAAA=","1313":"b:AACSAAAAAAAAIHAIAABAFCQCAQAAIIAACAAAAAA=","1314":"b:AACSAAAAAAAAIHAIAABAFCQCAQAAIIAACAAAAAA=","1324":[86,124],"1328":[86,124],"1356":"b:gACSAIQiAAAgYHEIAgBAFGQaAQNQIYVACAQKAAA=","1360":"b:AACSAAAAAAAAYHAIAABAFCQCAQAAIIAACAAAAAA=","1366":[86,124],"1371":[86,20,91,124,173],"1382":[7,84,85,86,17,23,124,39,183,77],"1383":[84,86,124],"1388":"b:gACCAKQiAAAgYHEAAgAAEGAYAQNQAYVAAAQKAAA=","1393":"b:gACCAKQiAAAgYHEAAgAAEGAYAQNQAYVAAAQKAAA=","1401":"b:gACCAAAgAAAAYAEAAgAAECAQAAFQAAQAAAAKAAA=","1406":"b:gACCAKQiAAAgYHEAAgAAEGAYAQNQAYVAAAQKAAA=","1413":"b:gACCAKQiAAAgYHEAAgAAEGAYAQNQAYVAAAQKAAA=","1417":"b:gACCAKQiAAAgYHEAAgAAEGAYAQNQIYVAAAQKAAA=","1421":"b:gACCAIQiAAAgYHEAAgAAEGAYAQNQIYVAAAQKAAA=","1428":"b:gACSAKQiAAAgYHEIAgBAFGQaAQNQIYVACAQKAAA=","1440":"b:gACSAIQiAAAgYHEIAgBAFGQaAQNQIYVACAQKAAA=","1452":[7,86,124,37],"1461":[86,124],"1485":"b:4EWSAKyiAABkfXEIBxBQFOR/CQdQO7d/iPY/AgA=","1495":"b:gACSAKQiAAAgQHEIAgBAFGQaAQNQIYVACAQKAAA=","1505":"b:gACSAKQiAAAgYHEIAgBAFGQaAQNQIYVACAQKAAA=","1507":[144,124],"1530":[124],"1531":[124],"1549":[124],"1553":[7,124],"1561":[7,124],"1562":[7,124],"1578":[7,84,85,17,23,124,39,183,77],"1591":[124],"1593":[124],"1602":[124],"1607":[124],"1610":[124],"1618":[124],"1623":[124],"1624":[124],"1630":[124],"1635":[124],"1638":[124],"1687":[20,91,124,173],"1688":[84,122,20,23,91,124,173,195,118,133],"1689":[84,20,91,124,173,118],"1692":"b:AACSAAAAAAAAYDAIAABAFCQCAQAAIIAACAAAAAA=","1704":[124],"1708":[124],"1714":[124],"1725":"b:AACSAAAAAAAAIDAIAABAFCQCAQAAIIAACAAAAAA=","1733":[124],"1734":[124],"1743":[124],"1750":[124],"1758":[124],"1765":[124],"1782":"b:AACSAAAAAAAAYDAIAABAFCQCAQAAIIAACAAAAAA=","1790":"b:AACSAAAAAAAAYDAIAABAFCQCAQAAIIAACAAAAAA=","1795":[124],"1797":[124],"1806":"b:AACSAAAAAAAAYDAIAABAFCQCAQAAIIAACAAAAAA=","1823":"b:AACSAAAAAAAAYDAIAABAFCQCAQAAIIAACAAAAAA=","1824":"b:AACSAAAAAAAAYDAIAABAFCQCAQAAIIAACAAAAAA=","1830":[84,124],"1854":[124],"1860":[124],"1861":[124],"1876":[124],"1886":[124],"1890":[122,124],"1902":[124],"1920":[23,124],"1934":[124],"1935":[124],"1936":[124]},"packages/frontend/editor-ui/src/features/credentials/composables/useCredentialOAuth.ts":{"52":"b:5kWT8L6yABRkfXUYBxBQ1PR/Ka/XO7f/iPY/AgA=","69":"b:gACCAKQiABAgYHUIAgAAAHAYAStQAYVAAAQKAAA=","87":"b:gACCAKQiABAgYHUIAgAAAHAYAStQAYVAAAQKAAA=","100":"b:gACCAKAgABAAYHQIAAAAADAAACgAAIAAAAAAAAA=","110":"b:gACCAKQiAAAgYHEAAgAAAGAYAQNQAYVAAAQKAAA=","127":"b:gACCAAAgAAAAYAEAAgAAACAQAAFAAAQAAAAKAAA=","137":[7],"149":"b:gACCACAgAAAAYEEAAgAAACAQAAFAAAQAAAAKAAA=","156":"b:gACCACAgAAAAYEEAAgAAACAQAAFAAAQAAAAKAAA=","162":"b:gACCACAgAAAAYEEAAgAAACAQAAFAAAQAAAAKAAA=","181":[7,86,37],"185":[86],"208":[86],"217":[86],"224":[86],"231":[86],"236":[86],"243":[86],"258":[86],"299":[86],"308":[86],"358":[86],"367":[86],"384":[86],"393":[86],"418":[86],"440":[86],"490":[86],"527":[86],"535":[86],"545":"b:4EWSAKiiAABkfXEIBxBQBOR/CQdQO7d/iPY/AgA=","554":[86]},"packages/frontend/editor-ui/src/features/credentials/composables/useCredentialSharing.ts":{"9":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","12":"b:8E/SkKzjAQDk/3cIH5BQ3Ox/D0fwP/9/+P//BwA="},"packages/frontend/editor-ui/src/features/credentials/composables/useNodeCredentialOptions.ts":{"23":"b:4EWSAKyiAABkfXEIDxBQFOR/KQdQP79/iPY/BgA=","38":"b:gACSAKQiAAAgYHEAAgBAEGQaAQNQIYVACAQKBAA=","39":"b:gACSAKQiAAAgYHEIAgBAFGQaAQNQIYVACAQKBAA=","44":"b:4EWSAKyiAABkfXEIDxBQFOR/CQdQP79/iPY/BgA=","51":"b:4EWSAKyiAABkfXEIDxBQFOR/CQdQP79/iPY/BgA=","52":"b:gACSAKQiAAAgYHEIAgBAFGQaAQNQIYVACAQKBAA=","58":[124],"59":[124],"62":"b:gACSAKQiAAAgYHEIAgBAFGQaAQNQIYVACAQKBAA=","65":"b:gACSAKQiAAAgYHEIAgBAFGQaAQNQIYVACAQKBAA=","71":[124],"74":"b:AACSAAAAAAAAIDAIAABAFCQCAQAAIIAACAAAAAA=","81":"b:AACSAAAAAAAAIDAIAABAFCQCAQAAIIAACAAAAAA=","84":[122,23,91,124],"90":"b:gEGSAKQiAABgZXEIAgBAFGQbCQdQIYVKCCYKBAA=","108":"b:gACSAKAiAAAgYHEIAgBAEGQaAANQIYVACAQKBAA=","119":[153,23,124,130,173,77],"127":"b:gACSAKAiAAAgYHEAAgBAEGQaAANQIYVACAQKBAA=","140":"b:gACSAKQiAAAgYHEIAgBAFGQaAQNQIYVACAQKBAA=","152":"b:gACCAAAgAAAAYAEAAgBAECAQAAFQAAQACAAKAAA=","157":"b:gACSAKQiAAAgYHEIAgBAFGQaAQNQIYVACAQKAAA=","166":"b:AACSAAAAAAAAIDAIAABAFCQCAQAAIIAACAAAAAA="},"packages/frontend/editor-ui/src/features/credentials/composables/useUnusableWorkflowCredentials.ts":{"15":[86,124],"33":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","40":[86,124],"54":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/D0fwP/9/+P//BwA=","57":[86,124],"64":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/D0fwP/9/+P//BwA=","66":[86,124],"68":[86,124],"70":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/D0fwP/9/+P//BwA="},"packages/frontend/editor-ui/src/features/credentials/credentials.api.ts":{"26":"b:9k//kK7zAVTk/3cIH5B03Px/D3/wP///mP//BwA=","44":"b:9k//kK7zAVTk/3cIH5B03Px/D3/wP///mP//BwA=","48":"b:gACCAIAgABAAYHQIAAAAEDAAAAgAAIAAAAAAAAA=","71":"b:gACDAQAwANgAAEYLHABkEjAAgCAEgAAABAAAAAA=","87":[86,124],"101":"b:9k/+kKzjAQDk/3cIH5BQ3Ox/D1/wP/9/mP//BwA=","110":"b:AACCAAAgABAAYHQIAAAAEDAAAAgAAIAAAAAAAAA=","117":[86,23,124],"121":[86,124],"125":[86,124],"129":[86,157,23,91,124,132,133],"142":[144,86,19,157,23,91,124,82],"152":[86,124,82],"163":[86,124,78],"173":"b:AACCAAAgAAAAIHQAAAAAEDAAASgAAIAAAAAAAAA=","190":[86,124],"213":[86,124],"220":[86,124]},"packages/frontend/editor-ui/src/features/credentials/credentials.store.ts":{"46":"b:9k/+kKzjAQDk/3cIH5BQ3Ox/D1/wP/9/mP//BwA=","49":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","71":"b:oECCAAAAAABgaVEAAxAAEORqCQQAIAFkAEYOAAA=","82":[144,86,124],"86":[144,86,124],"96":[86,124],"100":"b:9k//kK7zAVTk/3cIH5B03Px/D3/wP///mP//BwA=","101":"b:9k/+kKzjARDk/3cIH5BQ3Px/DX/wP/9/mP//BwA=","106":"b:gAC/AwA5AZhE4HYrHoBAFnQCgTgE8IAADAoAAAA=","107":"b:AACwAAAQAAAAIFQAAAAAFDQAADAAMIAAAAIAAAA=","110":"b:AAC+AAAhAQAEYHQAAIBAFCQCATgAMIAACAAAAAA=","113":"b:AAC+AAAhAQAEIHQAAIBAFCQCATgAMIAACAAAAAA=","115":"b:AAC+AAABAAAEIHQAAIBAFCQCATgAMIAACAAAAAA=","124":"b:hgCSAKQiAAAgYHEIAgBAFGQaAQNQIYVACAQKBAA=","132":[84,122,23,124,164,130,176,183,133,77],"138":[84,85,86,17,23,124,183,77,78],"139":[84,85,86,17,23,124,183,78],"143":[84,85,86,17,23,124,183,77],"147":[86,124],"155":"b:5kWeAKyzARBkfXUIH5BQFPR/KT9QP79/iPY/BgA=","156":"b:5kWeAKyzARBkfXUIH5BQFPR/KT9QP79/iPY/BgA=","159":"b:gAC+AIAhABAEYHQIAIBAFHQCATgAMIAACAAABAA=","160":"b:gAC+AIAhABAEYHQIAIBAFHQCATgAMIAACAAABAA=","163":[84,85,86,17,20,23,91,124,173,183,77,78],"164":[84,85,86,17,20,23,91,124,173,183,78],"170":"b:AAC+AAAhAQAEYHQAAIBAFCQCATgAMIAACAAAAAA=","171":"b:AAC+AAAhAQAEQHQAAIBAFCQCATgAMIAACAAAAAA=","176":[1,2,86,124],"177":[1,2,86,124],"181":[86,124],"183":"b:AACCAAAgAAAAIHQIAAAAEDAAASgAAIAAAAAAAAA=","184":"b:AACCAAAgAAAAAHQIAAAAEDAAASgAAIAAAAAAAAA=","194":[86,23,91,124,82],"197":[86,23,91,124,82],"200":[86,23,91,124,82],"208":[86,122,23,124],"209":[86,122,23,124],"215":[86,122,23,124],"239":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","240":"b:gACCAIAgABAAQHQIAAAAEDAAACgAAIAAAAAAAAA=","257":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","258":"b:gACCAIAgABAAQHQIAAAAEDAAACgAAIAAAAAAAAA=","265":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","266":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","277":"b:9k/+kK7zAVDk/3cIH5B03Px/D3/wP///mP//BwA=","278":"b:9k/+kK7zAVDk/3cIH5B03Px/D3/wP///mP//BwA=","288":[86,124],"289":[86,124],"296":"b:9k//kazzAdjk/3cJH5B03vx/D3/0v/9/nP//BwA=","297":"b:AAC+AAAxABAEIDQIAIBwFDQCAT4QOP8/mGOLAwA=","308":"b:AACCAAAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","321":"b:9k//kK7zAVTk/3cIH5B03Px/D3/wP///mP//BwA=","329":"b:gACDAQAwANgAAEYLHABkEjAAgCAEgAAABAAAAAA=","361":"b:9k/+kKzjAQDk/3cIH5BQ3Ox/D1/wP/9/mP//BwA=","387":"b:AAC+AAABAAAEIDQIAIBQFCQCAR4QOP8/mGOLAwA=","404":[86,124],"415":[1,2,86,124],"416":[1,2,86,124],"422":[144,86,19,157,23,91,124,82],"430":"b:4EWSAKyiAABkfXEIDxBQFOR/KQdQP79/iPY/BgA=","443":"b:AACCAAAgABAAYHQIAAAAEDAAAAgAAIAAAAAAAAA=","485":[86,157,23,91,124,132,133],"503":[86,23,124],"512":[86,124],"517":[86,124],"526":[86,124],"543":[86,124,78],"547":[86,124,82],"551":"b:AACCAAAgAAAAIHQAAAAAEDAAASgAAIAAAAAAAAA=","575":"b:gACCAIAgABAAYHQIAAAAEDAAAAgAAIAAAAAAAAA=","596":[86,124],"605":[86,124,132,133],"615":[86,124,132,133],"627":[86,124],"633":[86,124],"698":"b:AAAJ8B4AAQAAAEQQAAAA0AAAAaAHAAAAAAAAAAA=","707":[144,86,19,157,124,28,126,31,34,35,127,82],"709":[144,86,19,157,124,28,126,31,34,35,127,82]},"packages/frontend/editor-ui/src/features/credentials/gatewayCreditsPromotion/useGatewayCreditsPromotion.ts":{"7":[86,124],"16":"b:4EWCAKiiABBkfXUIBxBQFPR/KC/QO7d/iPY/AgA=","26":"b:4EWCAKiiABBkfXUIBxBQFPR/KC/QO7d/iPY/AgA=","39":"b:4EWCAKiiABBkfXUIBxBQFPR/KC/QO7d/iPY/AgA=","48":[86,124],"53":[86,124],"57":"b:4EWCAKiiABBkfXUIBxBQFPR/KC/QO7d/iPY/AgA="},"packages/frontend/editor-ui/src/features/credentials/quickConnect/composables/useQuickConnect.ts":{"20":"b:4EWSAKyiABRkfXUIBxBQFPR/KS/QO7f/iPY/AgA=","35":"b:4EWCAKyiAABkfXEIBxBQFOR/KQdQO7d/iPY/AgA=","43":"b:gACCAIAAAARkaGEAAxAAEORgCAGQIRCACEYOAAA=","53":"b:gACCAKQiAAAgYHEAAgAAEGAYAQNQAYVAAAQKAAA=","66":"b:gACCAIAAAARkaGEAAxAAEORgCAGQIRCACEYOAAA=","73":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","86":[86,124],"87":[86,124],"89":[86,124],"91":[86,124],"92":[86,124],"97":[86,124],"101":[86,124],"106":[86,124],"119":"b:4EWSAKiiABBkfXUIBxBQFPR/CS/QO7f/iPY/AgA=","120":[86,124],"129":[86,124],"135":[86,124],"143":[86,124]},"packages/frontend/editor-ui/src/features/execution/executions/composables/useExecutionData.ts":{"8":"b:YEQAAAiCAAAAEQAAAgAQAIQ3CAQAOgIgAKA3AgA=","10":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","14":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","18":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA="},"packages/frontend/editor-ui/src/features/execution/executions/composables/useExecutionHelpers.ts":{"19":"b:AEYAAAiCAAAAG1AAAgAQEIQzKAQAOgIhAOS3AwA=","24":[86,124,47,72,136,73,137,215,216,217],"69":[86,124,47,72,136,73,137,215,216,217],"74":[86,124,47,72,136,73,137,215,216,217],"78":[86,124],"87":[86,124,212,213],"107":[86,124]},"packages/frontend/editor-ui/src/features/execution/executions/composables/useExecutionRedaction.ts":{"13":"b:4EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","22":[9,84,85,10,86,124,47,184,137,217],"26":[9,84,85,10,86,124,184,137,217],"28":[86,124,47],"30":[86,124,47],"34":[86,124]},"packages/frontend/editor-ui/src/features/execution/executions/executions.store.ts":{"33":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","46":[84,86,124,47,72,136,73,137,215,216,217],"55":[86,124],"70":[84,86,124,47,72,136,73,137,215,216,217],"78":[84,86,124,47,72,136,73,137,215,216,217],"79":[86,124,47,72,136,73,137,215,216,217],"89":[86,124],"95":[86,124],"108":[84,86,124,47,72,136,73,137,215,216,217],"116":[84,86,124,47,72,136,73,137,215,216,217],"117":[86,124],"126":[86,124],"128":[86,124,47,72,136,73,137,215,216,217],"138":[86,124],"145":[86,124,136],"150":[86,124,215],"154":[86,124,215],"158":[84,86,124,47,72,136,73,137,215,216,217],"162":[84,86,124,47,72,136,73,137,215,216,217],"171":[84,86,124,47,72,136,73,137,215,216,217],"186":[84,86,124,47,72,136,73,137,215,216,217],"214":[86,124,47,72,136,73,137,215,216,217],"245":[84,86,124,47,72,136,73,137,215,216,217],"250":[86,124,73,216],"255":[86,124],"259":[3,86,124,47,72,136,73,137,215,216,217],"273":[84,86,124,47,72,136,73,137,215,216,217],"279":[86,124],"287":[84,86,124,47,72,136,73,137,215,216,217],"292":[84,86,124,47,72,136,73,137,215,216,217],"299":[86,124],"340":[86,124],"351":[86,124,136,137],"359":[86,124],"373":[86,124,136],"387":[86,124],"395":[84,86,124,72,215,216,217],"406":[84,86,124,72,215,216,217]},"packages/frontend/editor-ui/src/features/execution/executions/executions.utils.ts":{"50":[84,86,124,47,72,136,73,137,215,216,217],"53":[86,124,47,72,136,73,137,215,216,217],"56":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","69":[84,86,124,47,72,136,73,137,215,216,217],"127":[86,14,147,124,158,130],"140":"b:cEcAEAjDAABAG3AIA5AQ2IQ3CEQAPjMlQOC3AwA=","142":"b:cEcAAAjDAABAG3AIA5AQmIQ3CEQAPjMlQOC3AwA=","193":[86,124,137],"250":"b:aEYAAAiCAAAAGXAAAwAQEIQ3CAQAOjMlAOA3AgA=","251":"b:aEYAAAiCAAAAGXAAAwAQEIQ3CAQAOjMlAOA3AgA=","259":"b:aEYAAAiCAAAAGXAAAwAQEIQ3CAQAOjMlAOA3AgA=","268":"b:aEYAAAiCAAAAGXAAAwAQEIQ3CAQAOjMlAOA3AgA=","269":"b:aEYAAAiCAAAAGXAAAwAQEIQ3CAQAOjMlAOA3AgA=","272":[86,124],"327":"b:cEcAEAjDAABAG3AIA5AQ2IQ3AAQAPjMlAOC3AwA=","365":"b:YAAAAAAAAAAAAXAAAAAAEAADAAAAABAAACCCAQA=","414":"b:eEcAEAjDAABAG3AIA5AQ2IQ3AAQAPjMlAOC3AwA=","431":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","445":[144,86,124,209],"452":[144,86,124,172,136,205,209,97],"458":"b:8EWCkIzjAQDk/1cIH5BQ3Ox/OUfwPz8+mP6/BwA=","464":[86,124],"500":[86,124],"522":[86,124]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsOverviewPanel.vue":{"39":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","51":"b:AAYAEAgAAAAAADAAAAAAwAACAAAAAEABQAAAAgA=","52":[9,84,85,10,28,126,35,127,184,198,137,217],"57":[9,84,85,10,28,126,35,127,184,198,137,217],"59":[9,84,85,10,28,126,35,127,184,198,137,217],"67":[9,84,85,10,28,126,35,127,184,198,137,217],"72":[9,84,85,10,28,126,35,127,184,198,137,217],"75":[9,84,85,10,28,126,35,127,184,198,137,217],"80":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","94":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","98":"b:cEcAEAjDAABAGzAIA5AQyIQ3AAQAPjMlAOC3AwA=","107":"b:cEcAEAjDAABAGzAIA5AQyIQ3AAQAPjMlAOC3AwA=","125":"b:AAYAEAgAAAAAADAAAAAAwAACAAAAAEABQAAAAgA=","161":[137],"162":[9,137]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsPanel.vue":{"21":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","31":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","68":[9,84,85,10,184,137,217],"71":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","72":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","75":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","84":[9,84,85,10,184,137,217],"89":[9,84,85,10,184,137,217],"95":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","134":[137],"141":[137],"163":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","192":"b:AAaAACAAAAAAADAAAAAAAAgKAAAAAMBBQAAAAAA=","217":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","261":[9,84,85,10,184,137,217]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsPanelActions.vue":{"20":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","27":"b:AAYAEAgAAAAAADAAAAAAwAACAAAAAEABQAAAAgA=","29":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","30":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","33":"b:AAYAEAgAAAAAADAAAAAAwAACAAAAAEABQAAAAgA=","51":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","58":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","77":[137],"84":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA="},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsPanelHeader.vue":{"8":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","10":[9,84,182,137,217],"13":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","20":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA="},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsViewKeyboardEventListener.vue":{"8":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","11":"b:YAGCgAAAAADgqRcAHwBAAEAKAQUQBYk8QBPnBwA=","24":[198],"27":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA="},"packages/frontend/editor-ui/src/features/execution/logs/composables/useChatState.ts":{"41":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","59":[9,84,85,10,182,184,198,137],"60":[137],"63":[9,84,85,10,182,184,198,137],"66":"b:AAaAACAAAAAAADAAAAAAAAgKAAAAAMBBQAAAAAA=","74":"b:AAaAACAAAAAAADAAAAAAAAgKAAAAAMBBQAAAAAA=","101":"b:AAaAACAAAAAAADAAAAAAAAgKAAAAAMBBQAAAAAA=","120":"b:AAaAACAAAAAAADAAAAAAAAgKAAAAAMBBQAAAAAA=","125":"b:AAaAACAAAAAAADAAAAAAAAgKAAAAAMBBQAAAAAA=","130":"b:AAaAACAAAAAAADAAAAAAAAgKAAAAAMBBQAAAAAA=","135":[9,84,85,10,182,184,198,137],"149":[9,84,85,10,182,184,198,137],"165":[9,84,85,10,184,198,137],"230":[9,84,85,10,182,184,198,137],"276":[9,84,85,10,184,198,137],"290":[9,84,85,10,184,198,137],"321":[137],"329":[9,84,10,45,198,137],"350":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","351":"b:8E/CAKDjAQDk/zcIH5BQDOx/DUfwP/9/2P//BwA=","362":"b:AAaAACAAAAAAADAAAAAAAAgKAAAAAMBBQAAAAAA="},"packages/frontend/editor-ui/src/features/execution/logs/composables/useClearExecutionButtonVisible.ts":{"8":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","13":"b:8EeCkKzjAQDk/zcIH5BQzOx/CUfwP/9/mP6/BwA=","14":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","15":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","17":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","18":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","20":"b:8EeCkKzjAQDk/zcIH5BQzOx/CUfwP/9/mP+/BwA=","21":"b:8EeCkKzjAQDk/zcIH5BQzOx/CUfwP/9/mP6/BwA=","24":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA="},"packages/frontend/editor-ui/src/features/execution/logs/composables/useLogsExecutionData.ts":{"36":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","42":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","49":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","56":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","63":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","64":"b:cEcAEAjDAABAGzAIE5AQyIQ3CEQAPjMlQOC3AwA=","79":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","89":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","94":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","118":"b:8E/CAKDjAQDk/zcIH5BQDOx/DUfwP/9/2P//BwA=","157":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","158":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","159":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","160":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","161":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","163":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","187":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","188":"b:8E/CAKDjAQDk/zcIH5BQDOx/DUfwP/9/2P//BwA=","197":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","207":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA="},"packages/frontend/editor-ui/src/features/execution/logs/composables/useLogsPanelLayout.ts":{"25":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","41":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","44":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","48":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","63":"b:AAaAACAAAAAAADAAAAAAAAgKAAAAAMBBQAAAAAA=","74":"b:AAaAACAAAAAAADAAAAAAAAgKAAAAAMBBQAAAAgA=","84":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","89":[9,84,85,10,184,137,217],"90":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","91":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","93":[9,84,182,137,217],"118":[9,84,182,137,217],"147":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","170":"b:AAAAEAAAAAAggxAABAAAgAADAAAAAAAAAAiAAwA="},"packages/frontend/editor-ui/src/features/execution/logs/composables/useLogsSelection.ts":{"25":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","34":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","35":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","43":[9,137],"58":[9,137],"116":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","127":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","156":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","162":[84,85,10,184,137,217],"183":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","222":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","224":[9,84,85,10,184,137,217],"229":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","230":[84,85,137]},"packages/frontend/editor-ui/src/features/execution/logs/composables/useLogsTreeExpand.ts":{"15":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","19":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","23":[84,137]},"packages/frontend/editor-ui/src/features/execution/logs/composables/usePopOutWindow.ts":{"77":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","88":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","89":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","90":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","93":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","171":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","180":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","185":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","194":"b:AAAAEAAAAAAggxAABAAAgAADAAAAAAAAAAiAAwA=","199":"b:AAAAEAAAAAAggxAABAAAgAADAAAAAAAAAAiAAwA="},"packages/frontend/editor-ui/src/features/execution/logs/logs.utils.ts":{"45":[3,9,84,85,10,28,126,35,127,184,198,137,217],"46":[3,9,84,85,10,28,126,35,127,184,198,137,217],"60":[3,9,84,85,10,28,126,35,127,184,198,137,217],"68":[3,9,84,85,10,28,126,35,127,184,198,137,217],"93":[3,9,84,85,10,28,126,35,127,184,198,137,217],"124":[84,85,137],"132":[84,85,137],"133":[84,85,137],"137":[84,85,137],"158":[3,9,84,85,10,28,126,35,127,184,198,137,217],"176":[3,9,84,85,10,28,126,35,127,184,198,137,217],"180":[3,9,84,85,10,28,126,35,127,184,198,137,217],"186":[3,9,84,85,10,28,126,35,127,184,198,137,217],"274":"b:cEcAEAjDAABAGzAIA5AQyIQ3AAQAPjMlAOC3AwA=","275":[9,84,85,184,137,217],"281":[9,84,184,137,217],"298":[3,9,84,85,10,28,126,35,127,184,198,137,217],"304":[3,9,84,85,10,28,126,35,127,184,198,137,217],"320":[3,9,84,85,10,28,126,35,127,184,198,137,217],"333":[84,85,137],"351":[3,9,84,85,10,28,126,35,127,184,198,137,217],"367":[3,9,84,85,10,28,126,35,127,184,198,137,217],"513":[3,9,84,85,10,28,126,35,127,184,198,137,217],"575":[3,9,84,85,10,28,126,35,127,184,198,137,217],"602":"b:8EeCEKjjAADk/zUID5BQzOx/CAfwP79/iPe/BwA=","621":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","632":[9,84,85,10,184,137,217],"657":"b:+E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","673":[3,9,84,85,10,28,126,35,127,184,198,137,217],"692":[3,9,84,85,10,28,126,35,127,184,198,137,217],"714":[9,84,85,10,28,126,35,127,184,198,137,217],"728":[9,84,85,10,28,126,35,127,184,198,137,217],"733":[9,84,85,10,28,126,35,127,184,198,137],"738":[9,84,85,10,28,126,35,127,184,198,137],"748":[137],"750":[9,84,85,10,28,126,35,127,184,198,137],"773":[3,9,84,85,10,28,126,35,127,184,198,137,217],"777":[3,9,84,85,10,28,126,35,127,184,198,137,217],"788":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","791":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/2P//BwA=","811":[9,137],"823":[137],"834":[137],"859":[137],"911":[137],"918":[137],"930":[137],"993":[9,84,85,10,184,137,217],"1002":[9,84,85,10,184,137,217],"1012":"b:cEcAEAjDAABAGzAIE5AQyIQ3CEQAPjMlQOC3AwA=","1020":"b:cEcAEAjDAABAGzAIA5AQyIQ3CAQAPjMlQOC3AwA="},"packages/frontend/editor-ui/src/features/integrations/externalSecrets.ee/externalSecrets.ee.store.ts":{"21":[86,124,60],"24":[86,124,60],"28":[86,124,60],"61":"b:4EWSAKyyAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","67":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","79":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","85":[86,124],"93":[86,124,60],"94":[86,124,60],"95":[86,124],"96":[86,124],"98":[86,124,60],"101":[86,124,60],"102":[86,124,60],"119":[86,124],"132":[86,124],"142":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","156":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","182":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","201":[86,124],"217":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","224":[86,124],"233":[86,124],"239":[86,124],"247":[86,124],"253":[86,124],"263":[86,124],"264":[86,124],"279":[86,124],"287":[86,124],"295":[86,124]},"packages/frontend/editor-ui/src/features/integrations/logStreaming.ee/module.descriptor.ts":{"9":[86,124,117,114,62],"10":[86,124],"11":[86,124],"30":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA=","35":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA="},"packages/frontend/editor-ui/src/features/integrations/sourceControl.ee/sourceControl.api.ts":{"22":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","24":[86,124,59],"30":[86,124],"37":[86,124],"44":[86,124,59],"53":[86,124,59],"61":[86,124],"65":[86,124],"76":[86,124],"87":[86,124],"96":[86,124]},"packages/frontend/editor-ui/src/features/integrations/sourceControl.ee/sourceControl.store.ts":{"14":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","18":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","24":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","45":[86,124],"58":[86,124],"62":[86,124,59],"66":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","68":[86,124,59],"73":[86,124,59],"78":[86,124,59],"87":[86,124],"102":[86,124],"112":[86,124],"116":[86,124],"124":[86,124]},"packages/frontend/editor-ui/src/features/ndv/agents/composables/useInlineAgentConfig.ts":{"38":[86,124],"65":[86,124],"69":[86,124],"70":[86,124],"85":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","89":[86,124],"99":[86,124],"106":[86,124],"109":[86,124],"115":[86,124],"124":[86,124],"135":[86,124],"149":[86,124],"170":[86,124],"175":[86,124],"201":[86,124]},"packages/frontend/editor-ui/src/features/ndv/agents/composables/useNdvAgentConfig.ts":{"28":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","33":[86,124],"35":[86,124],"42":[86,124]},"packages/frontend/editor-ui/src/features/ndv/agents/composables/useReferencedAgentSummary.ts":{"23":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","29":[86,124],"32":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","36":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","56":[86,124],"59":[86,124],"80":[86,124],"87":[86,124],"95":[86,124],"112":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","131":[86,124],"138":"b:AAAAEAAgAAAgg1AAFAAAkAADAAAAAAAAAAiAAwA=","145":[86,124],"163":[86,124]},"packages/frontend/editor-ui/src/features/ndv/panel/components/InputPanel.vue":{"60":"b:4EWCAKiiAABkfXEIBxBQFOR/CAdQM7d/iPY/AgA=","108":"b:4EWCAKiiAABkfXEIBxBQFOR/CAdQM7d/iPY/AgA=","114":"b:4EWCAKiiAABkfXEIBxBQFOR/CAdQM7d/iPY/AgA=","118":[86,124],"122":"b:4EWCAKiiAABkfXEIBxBQFOR/CAdQM7d/iPY/AgA=","126":"b:4EWCAKAiAABkfXEIBxBQFOR+CAdQI6dfiPYeAAA=","132":[86,124],"143":"b:4EWCAKiiAABkfXEIBxBQFOR/CAdQM7d/iPY/AgA=","145":"b:4EWCAKiiAABkfXEIBxBQFOR/CAdQM7d/iPY/AgA=","154":"b:4EWCAKiiAABkfXEIBxBQFOR/CAdQM7d/iPY/AgA=","178":"b:4EWCAKiiAABkfXEIBxBQFOR/CAdQM5d/iPY/AgA=","179":[84,86,124,77],"183":"b:4EWCAKiiAABkfXEIBxBQFOR/CAdQM7d/iPY/AgA=","191":"b:4EWCAKiiAABkfXEIBxBQFOR/CAdQM7d/iPY/AgA=","207":"b:YAAAAAACAAAAGEAAAgAQEIA0AAQAAgIAAOAWAAA=","216":"b:4EWCAKAiAABkfXEIBxBQFOR+CAdQI6dfiPYeAAA=","221":"b:4EWCAKiiAABkfXEIBxBQFOR/CAdQM7d/iPY/AgA=","236":"b:4EWCAKiiAABkfXEIBxBQFOR/CAdQM7d/iPY/AgA=","237":"b:4EWCAKiiAABkfXEIBxBQFOR/CAdQM4d/iPY/AgA=","240":"b:4EWCAKiiAABkfXEIBxBQFOR/CAdQM7d/iPY/AgA=","247":"b:4EWCAKiiAABkfXEIBxBQFOR/CAdQM4d/iPY/AgA=","251":"b:4EWCAKiiAABkfXEIBxBQFOR/CAdQM7d/iPY/AgA=","252":"b:4EWCAKiiAABkfXEIBxBQFOR/CAdQM4d/iPY/AgA=","258":"b:4EWCAKiiAABkfXEIBxBQFOR/CAdQM7d/iPY/AgA=","263":[86,124],"277":"b:4EWCAKAiAABkbXEIBxBQFOR+CAdQI4ZfCGYeAAA=","282":"b:4EWCAKiiAABkfXEIBxBQFOR/CAdQM7d/iPY/AgA=","299":"b:AAAAAAAAAAAAOEAAAgAQEAQwCAAAIABAgMAAAAA=","302":"b:AAAAAAAAAAAAOEAAAgAQEAQgCAAAIAAAAMAAAAA=","312":"b:4EWCAKiiAABkfXEIBxBQFOR/CAdQM5d/iPY/AgA=","321":[86,124],"325":[86,124],"332":[86,124,116],"345":"b:4EWCAKiiAABkfXEIBxBQFOR/CAdQM7d/iPY/AgA=","349":[10,86,124,210],"353":"b:4EWCAKAiAABkfXEIBxBQFOR+CAdQI6dfiPYeAAA=","357":[86,124,208],"361":[86,124,116,210,140],"370":[86,124,137,116,208,209,210,140],"374":[86,124,116,140],"375":[86,124,116,140],"379":[86,124],"391":"b:AAQAAAAAAABAYEAAAAAQEAAaAAAAADAAAAAHAAA=","395":[86,124],"397":"b:4EWCAKiiAABkfXEIBxBQFOR/CAdQM7d/iPY/AgA=","433":[86,124,181,137,116,208,209,210,140],"436":"b:4EWCAKiiAABkfXEIBxBQFOR/CAdQM7d/iPY/AgA=","443":"b:4EWCAKiiAABkfXEIBxBQFOR/CAdQM7d/iPY/AgA=","455":[86,124,181,137,116,208,209,210,140],"464":[85,86,23,124,181,183,77],"468":[85,86,23,124,181,183,77],"477":"b:4EWCAKAiAABkbXEIBxBQFOR+CAdQI5ZfCGYeAAA=","484":[86,124],"511":"b:4EWCAKAiAABkbXEIBxBQFOR+CAdQI4ZfCGYeAAA=","528":"b:4EWCAKAiAABkbXEIBxBQFOR+CAdQI4ZfCGYeAAA=","545":[86,124],"554":[86,124],"556":[86,124],"560":[86,124],"572":"b:AACAAAAAAAAAIGAABgAAECAAAAEAIJAAAAACAAA=","575":[86,124],"577":[86,124],"592":[86,124],"594":[86,124],"598":[10,86,124],"602":[86,124],"604":[86,124],"608":[86,124,47],"618":[86,124]},"packages/frontend/editor-ui/src/features/ndv/panel/components/NDVEmptyState.vue":{"21":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA="},"packages/frontend/editor-ui/src/features/ndv/panel/components/NDVFloatingNodes.vue":{"13":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","18":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","30":[139],"37":"b:AAGCAAAAAABAfBAABgBQAEAoAAEQAYIMANYHAAA=","51":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","53":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQM6d/CPY/AgA=","63":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQM6d/CPY/AgA=","66":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","95":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","99":"b:oEWAACAgAABkOTEIBxBQAMQ7CAFQK7RfAPYvAgA=","105":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","123":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQM6d/CPY/AgA=","129":[135,202,139,141]},"packages/frontend/editor-ui/src/features/ndv/panel/components/NDVHeader.vue":{"27":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","34":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","62":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","64":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","70":[84,171,188,118,135,209],"72":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA="},"packages/frontend/editor-ui/src/features/ndv/panel/components/NDVSubConnections.vue":{"25":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/CPY/AgA=","57":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/CPY/AgA=","61":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/CPY/AgA=","66":[85,86,124,139],"72":[86,124],"84":[84,85,86,23,124,37,183,190,69,70,139,77],"87":[84,85,86,23,124,37,183,190,69,70,139,77],"99":[85,86,124,139],"110":[84,85,86,23,124,37,183,190,69,70,139,77],"127":[84,85,86,23,124,37,183,190,69,70,139,77],"131":[84,85,86,23,124,37,183,190,69,70,139,77],"133":[84,85,86,23,124,37,183,190,69,70,139,77],"137":[84,85,86,23,124,37,183,190,69,70,139,77],"145":[84,85,86,23,124,37,183,190,69,70,139,77],"152":[84,85,86,23,124,37,190,69,139,77],"161":[86,124],"167":[84,85,86,23,124,37,183,190,69,70,139,77],"169":[85,86,124,139],"183":[85,86,124,139],"186":[84,85,86,23,124,37,183,190,69,70,139,77],"193":"b:4EWCAKiiAABkfXEIBxBQFOR/CAdQM5d/CPY/AgA=","201":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/CPY/AgA=","210":"b:4EWCAKiiAABkfXEIBxBQFOR/CAdQM5d/CPY/AgA=","219":[86,124],"231":[86,124,139],"250":"b:YAAAAAACAAAAEEAAAgAQEIAwAAQACAIAAKAGAAA=","253":"b:YAAAAAACAAAAEEAAAgAQEIAwAAQACAIAAKAGAAA=","259":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/CPY/AgA=","260":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/CPY/AgA=","262":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/CPY/AgA=","274":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/CPY/AgA=","283":[84,85,86,23,124,37,183,190,69,70,139],"296":[84,85,86,23,124,37,190,69,139,77],"297":[84,85,86,23,124,37,183,190,69,70,139,77],"305":[86,124,139],"317":[86,124,139],"329":[86,124],"335":[84,85,86,23,124,37,183,190,69,70,139,77],"355":[85,86,124,139],"370":[86,124],"376":[85,86,124,139],"382":[86,124]},"packages/frontend/editor-ui/src/features/ndv/panel/components/OutputPanel.vue":{"34":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","85":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","86":"b:YEQAAAiCAAAAEQAAAgAQAIQ3CAQAOgIgAKA3AgA=","111":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","115":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","123":"b:4EWCAKAiAABkfTEIBxBQBOR/CAdQK7dfCPYeAAA=","127":"b:4EWCAKAiAABkfTEIBxBQBOR/CAdQK7dfCPYeAAA=","135":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","154":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","157":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","161":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","169":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","171":"b:YEQAAAiCAAAAEQAAAgAQAIQ3CAQAOgIgAKA3AgA=","179":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","181":"b:YEQAAAiCAAAAEQAAAgAQAIQ3CAQAOgIgAKA3AgA=","189":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","193":"b:4EWCAKAiAABkfTEIBxBQBOR/CAdQK7dfCPYeAAA=","197":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","238":[210],"242":[210],"261":[10,210,140,212],"266":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","279":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","285":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","316":"b:AEQAAAiCAAAAGQAAAgAQAIQzKAQAOgIgAOQ3AgA=","317":[10,116,208,210,140],"318":[208,210],"319":[202,136,138,210,140],"322":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","348":"b:4EWCAKAiAABkfTEIBxBQBOR/CAdQK7dfCPYeAAA=","371":"b:oACAAAAAAAAgWDEAAwAQAARJCAMQKAQAAOYKAAA=","379":"b:4EWCAKAiAABkfTEIBxBQBOR+CAdQI7dfCPYeAAA=","381":"b:4EWCAKAiAABkfTEIBxBQBOR/CAdQK7dfCPYeAAA=","392":"b:AACAACAAAAAAIDAAAAAAAAAaAABAAqBEAAAAAAA=","418":"b:4EWCAKAiAABkfTEIBxBQBOR9CAdQK5dfCPYeAAA=","422":"b:4EWCAKAiAABkfTEIBxBQBOR/CAdQK7dfCPYeAAA=","439":[137],"441":[137],"445":[10],"463":[47],"484":[10,137,210,140,212]},"packages/frontend/editor-ui/src/features/ndv/panel/components/PanelDragButton.vue":{"6":"b:4EWCAKiiAABkfTEIBxBQBOR/CAdQM7d/CPY/AgA=","22":"b:4EWCAKiiAABkfTEIBxBQBOR/CAdQM7d/CPY/AgA="},"packages/frontend/editor-ui/src/features/ndv/panel/composables/useNdvLayout.ts":{"21":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","29":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","35":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","37":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","41":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","45":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","46":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","51":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","53":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","81":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","117":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","195":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","202":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA="},"packages/frontend/editor-ui/src/features/ndv/parameters/components/Collection/CollectionParameter.vue":{"9":"b:oEWQACiiAEBgfXAIBwA0FERfKAdQM6RvgPY/AAA=","25":"b:oEWQACiiAEBgXXAIBwA0FERfKAdQM6RvgPY/AAA=","34":[86,124,130,173,190],"39":[86,124],"40":[86,124]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/Collection/CollectionParameterLegacy.vue":{"25":"b:oEWQACiiAEBgfXAIBwA0FERfKAdQM6RvgPY/AAA=","46":"b:oEWQACiiAEBgfXAIBwA0FERfKAdQM6RvgPY/AAA=","50":"b:oEWQACgiAEBgfXAIBwA0FERfCAdQM6RvgPYvAAA=","57":"b:oEWQACgiAEBgfXAIBwA0FEQfCAdQM6RvgPYPAAA=","63":"b:oEWQACgiAEBgfXAIBwA0FEQfCAdQM6RvgPYPAAA=","75":"b:oEWQACiiAEBgfXAIBwA0FERfKAdQM6RvgPY/AAA=","91":[8,86,154,124,130,173,178,190,138,210,212],"95":[8,86,154,124,130,173,178,190,138,210,212],"100":[86,124],"112":"b:oEWQACiiAEBgfXAIBwA0FERfKAdQM6RvgPY/AAA=","114":"b:oEWQACiiAEBgfXAIBwA0FERfKAdQM6RvgPY/AAA=","115":[8,86,154,124,130,173,178,190,138,210,212],"118":[8,86,154,124,130,173,178,190,138,210,212],"120":[8,86,154,124,130,173,178,190,138,210,212],"131":"b:oEWQACiiAEBgfXAIBwA0FERfKAdQM6RvgPY/AAA=","133":"b:oEWQACiiAEBgfXAIBwA0FERfKAdQM6RvgPY/AAA=","148":"b:oEWQACiiAEBgfXAIBwA0FERfKAdQM6RvgPY/AAA=","149":"b:oEWQACiiAEBgfXAIBwA0FERfKAdQM6RvgPY/AAA=","152":[86,124,130,173,190],"206":[86,124,130,173,190],"208":"b:oEWQACiiAEBgfXAIBwA0FERfKAdQM6RvgPY/AAA=","212":[86,124],"215":"b:oESQACiiAEBgfXAIBwA0FERbKANQM6RvgPYvAAA=","238":[86,124],"248":"b:oEWQACgiAEBgfXAIBwA0FEQfCAdQM6RvgPYPAAA=","251":"b:oEWQACgiAEBgXXAIBwA0FEQfCAdQM6RvgPYPAAA="},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ExpressionEditModal.vue":{"40":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","70":[86,124,75],"88":[86,124,75],"89":[86,124],"90":[86,124,75],"95":[86,124,75],"98":[86,124],"104":[86,124],"109":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","110":[86,124,75],"138":[86,124],"146":[86,124,75],"151":[86,124,75],"155":[86,124],"161":[86,124],"166":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","177":[86,124,75],"189":[86,124,75],"197":[86,124,75],"218":[86,124,75],"228":[86,124,75],"252":[86,124,75]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ExpressionEditorModal/theme.ts":{"4":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","33":[86,124,75],"39":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA="},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FilterConditions/CombinatorSelect.vue":{"14":[86,124,169],"20":[86,124],"22":[86,124,169],"31":[86,124,169],"32":[86,124,169]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FilterConditions/Condition.vue":{"43":[86,124,169],"63":[86,124,169],"67":[86,124,169],"69":[86,124],"79":[86,124,169],"97":[86,124,169],"110":[86,124,169],"118":[86,124],"120":[86,124,169],"131":[86,124,169],"143":[86,124,169],"145":[86,124,169],"150":[86,124],"155":[86,124],"166":[86,124,169],"170":[86,124,169],"174":[86,124],"184":[86,124],"192":[86,124],"215":[86,124,169],"216":[86,124],"221":[86,124,169],"250":[86,124,169],"269":[86,124,169],"278":[86,124,169],"304":[86,124],"306":[86,124,169],"314":[86,124],"316":[86,124,169]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FilterConditions/FilterConditions.vue":{"39":[86,124,169],"62":[86,124,169],"71":[86,124,169],"75":[86,124,169],"78":[86,124,169],"90":[86,124,169],"94":[86,124,169],"96":[86,124,169],"100":[86,124,169],"105":[86,124,169],"134":[86,124,169],"135":[86,124,169],"144":[86,124,169],"145":[86,124,169],"152":[86,124,169],"160":[86,124,169],"164":[86,124,169],"168":[86,124],"172":[86,124,169],"176":[86,124,169],"178":[86,124,169],"210":[86,124,169],"232":[86,124,169],"233":[86,124,169]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FilterConditions/OperatorSelect.vue":{"19":[86,124,169],"30":[86,124,169],"31":[86,124,169],"34":[86,124,169],"36":[86,124,169],"38":[86,124,169],"41":[86,124,169],"42":[86,124,169],"55":[86,124,169],"69":[86,124],"73":[86,124,169],"86":[86,124,169],"88":[86,124,169]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FilterConditions/constants.ts":{"299":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","305":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","311":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","317":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","323":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","329":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FilterConditions/utils.ts":{"20":[86,124,169],"23":[86,124],"29":[86,124],"46":[86,124],"78":[86,124],"82":[86,124,169],"106":[86,124],"130":[86,124,169],"151":[86,124,169]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/InputTriple/InputTriple.vue":{"10":"b:IAAAAAiAAAAAMEAAAgAQEAADAAIAMgQhgKAEAAA=","13":"b:IAAAAAiAAAAAMEAAAgAQEAADAAIAMgQhgKAEAAA=","21":"b:IAAAAAiAAAAAMEAAAgAQEAADAAIAMgQhgKAEAAA=","22":"b:IAAAAAiAAAAAMEAAAgAQEAADAAIAMgQhgKAEAAA="},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInput.vue":{"143":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","229":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","231":[86,124,75,209],"246":[86,124],"253":[86,124],"262":[86,124],"274":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","280":[86,152,124,209,77],"284":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","290":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","294":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","296":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","300":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","309":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","316":"b:4EWSAKgiAFBkfXUIBxB0FPR/CS9QO7d/iPY/AAA=","320":"b:AEGCAAAiABAAIXQIAAAUEDQgCA4AIoBAAAACAAA=","324":[86,124],"334":[10,86,122,124,168,117,134,77,212],"337":[86,124],"350":[10,86,122,124,168,117,134,77,212],"354":[10,86,122,124,168,117,134,77,212],"362":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","366":"b:4EWSAKiiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","391":"b:gACSAIAgAAAgaEEAAgBAEGQ0CAFQISUACEQOAAA=","402":"b:4EWSAKiiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","405":[86,124,77],"412":[86,14,153,23,91,124,166,39,130,173,135,77],"416":"b:AECQAIAAAAAAIEAIAAAAEIQAAAJAIAAAAAAAAAA=","420":"b:QAQAAAAAAABEIFAAARAgFMAAAAEAARAQAAYSAgA=","429":"b:gACCAAQgAAAgYHEAAABAECBKAABQAIAACAAiAAA=","433":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","442":[86,124],"452":[86,124],"457":"b:4EWSAKiiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","473":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","476":"b:QAAAAAAAAABEAFAAARAAEMAAAAEAABAQAAICAgA=","484":"b:4EWSAKiiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","488":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","496":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","500":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","575":"b:oEQAAAAAAAAgOFUAAwAEEAA7IAJQKAZEAPIOAAA=","583":"b:oEQAAAAAAAAgOFUAAwAEEAA7IAJQKAZEAPIOAAA=","585":"b:oACCACQgABBgfHEAAgBQECB7AABQEIVhCMAiAAA=","600":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","633":"b:4EWSAKiiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","656":"b:4EWSAKiiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","660":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","703":"b:4EWSAKiiAEBkfXEIBxB0FOR/KAdQO7d/iPY/AgA=","734":[86,124,213,142],"753":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","767":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","774":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","778":[86,124],"782":[86,20,23,124,181,190,139],"786":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","813":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","832":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","836":"b:4EWSAKiiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","837":[86,124],"840":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","846":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","850":[86,124,202],"852":"b:AEGSAIAiABAAfXQIAgAUELQwCA5AIoJAgMACAAA=","853":"b:AECQAIAAAAAAOEAIAAAUEIQwAAJAIAIAAEAAAAA=","855":[86,124,177,116],"856":"b:AEGCAAAiABAAfXQIAAAUEDQgCA4AIoJAgEACAAA=","863":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","875":[84,86,124],"877":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","886":"b:4EWSAKiiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","890":"b:4EWSAKiiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","894":[86,23,91,124],"912":"b:4EWSAKiiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","919":"b:4EWSAKiiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","931":"b:4EWSAKiiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","939":"b:4EWSAKiiABBkfXUIBxBQFPR/KC9QO7d/iPY/AgA=","947":[86,152,124,209,77,78],"999":[86,124,209],"1004":[86,124,209],"1009":[86,124,75],"1013":[86,124,75],"1031":[86,124],"1035":[86,124],"1043":[86,124,209],"1055":[86,124,75],"1062":[86,124],"1070":"b:AEGSAIAiABAAfXQIAgAUELRwCA5AIoJAgMACAAA=","1078":"b:AEGSAIAiABAAfXQIAgAUELRwCA5AIoJAgMACAAA=","1125":[86,124],"1132":[86,124],"1139":"b:AEGCAAAiABAAIXQIAAAUEDQgCA4AIoBAAAACAAA=","1149":[86,124],"1162":"b:QEGSAIAiABBEfXQIAxAUEPRgCA9AIpJQAMYiAAA=","1249":"b:AAAAAAAAABAAfEAAAgAQEAAgAAAAAAAAAMAAAAA=","1256":"b:AEGSAAAiABAAfXQIAAAUELRgCA5AIoJAgMACAAA=","1261":[86,124],"1285":[86,124],"1295":[86,124],"1299":[86,124],"1318":[86,124],"1323":"b:AEGCAAAiABAAIXQIAAAUEDQgCA4AIoBAAAACAAA=","1330":"b:AAAAAAAAABAAfEAAAgAQEABgAAAAAABAAMAAAAA=","1361":[86,124],"1410":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","1444":[86,20,23,124,181,190,139],"1469":[86,124],"1470":[86,124],"1473":"b:oEWSACAgAFBkeXUIBxBQEPR7CClQK7RfgPYvAgA=","1480":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","1482":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","1496":[86,124],"1510":[86,124,209,77,78],"1516":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","1517":"b:wEGCAIAiABBEfXQIAxAUEPRgCC8AIpJAAMYiAAA=","1527":[86,152,124,209,77],"1532":"b:AAAAAAAAABAAfEAAAgAQEABgAAAAAABAAMAAAAA=","1542":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","1545":[7,86,153,23,124],"1561":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","1574":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","1580":"b:AAAAAAAAAAAAdEAAAgAUEAAgAAAAAAIAAMQCAAA=","1743":[86,124,209],"1827":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","1832":[86,124,209],"1852":[86,124,202],"1856":[86,124],"1874":[86,124],"1878":[86,124],"1897":[86,124,202],"1901":[86,124],"1920":[84,86,124],"1925":[86,124],"1943":[10,86,122,124,168,117,134,77,212],"1947":[86,124],"1958":[86,124],"1972":"b:AEGCAAAiABAAIXQIAAAUEDQgCA4AIoBAAAACAAA=","1992":[8,86,124,114,116,209,77],"1997":"b:4EWSAKiiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","2006":[86,124],"2038":[86,124],"2071":[86,124],"2108":[86,122,23,91,124],"2127":[86,124],"2131":"b:4EWSAKiiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","2133":"b:4EWSAKiiAFBkXXUIBxB0FPR/KS9QO7d/iPY/AgA=","2139":"b:4EWSAKiiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","2168":[86,124],"2171":[86,152,124,164,78],"2173":[86,152,124,164,78],"2178":[86,152,124,164,78],"2197":[86,124]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputFull.vue":{"67":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","105":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","119":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","122":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","131":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","136":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","141":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","145":[86,124,116],"151":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","159":"b:oEWSAKgiAABgfXEIBwB0FGR/CQdQO6dviPI/AAA=","164":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","172":[86,124],"176":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","194":"b:AEGQAIACAAAAfUAIAgAUEIRwCAZAIgJAgMACAAA=","202":"b:AEGQAAACAAAAfUAIAAAUEIRgCAZAIgJAgMACAAA=","214":[86,124],"218":"b:AECQAIACAEAAfFAIAgBQFIRzCQZAIgRBAOQWAAA=","222":"b:AECQAIACAEAAeFAIAgBQFIRzCAZAIgQBAOQUAAA=","226":[86,124,74,206,75,76,207,77,97,78,141,142],"243":"b:AEGQAIACAABEfVAIAxAUEMRgCAcAIhJQAMYiAAA=","247":"b:AEEAAAACAAAAIUAIAAAUEAQgCAYAIgBAAAACAAA=","255":[86,124,116],"263":[86,124,116],"278":[86,124],"280":[86,124],"334":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","339":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","340":[86,124,141],"349":"b:AECQAIACAEAAfFAIAgBQFIRzCQZAIgRBAOQWAAA=","354":[86,20,23,124,181,190,139],"358":[86,20,124],"378":[86,124],"399":[86,124],"403":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","421":[86,124],"456":[86,124],"490":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","494":[86,20,23,124,181,190,139],"507":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","529":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","534":[86,124],"564":[86,20,23,124,181,190,139]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputList.vue":{"67":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","68":"b:oEGCAAAgAAAgOHEAAwAQFCRYCAZQKAQACOIPAAA=","71":"b:oEWQACiiAEBgfXAIBwA0FERfKAdQM6RvgPY/AAA=","129":"b:4EWSACiiAEBkfXEIBxB0FORfKAdQO7R/iPY/AgA=","131":[86,124],"150":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","155":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","162":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","192":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","205":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","211":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","212":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","240":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","285":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","312":"b:AAQQAAAAAEAAIEAAAAAAEIBoAAAAAAARAAQAAAA=","313":"b:AAQQAAAAAEAAIEAAAAAAEIBoAAAAAAARAAQAAAA=","319":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","320":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","323":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","324":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","327":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","344":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","353":[86,147,124,130],"356":[86,147,124,130],"379":[86,147,124,130],"397":[86,14,124],"400":[86,14,124],"407":[86,124],"417":[86,124],"438":[84,85,86,23,124,37,183,190,70,139],"445":[84,86,124,70],"449":[84,86,124,70],"464":[86,147,124,130],"467":[86,147,124,130],"471":[86,147,124,130],"476":"b:AEGQAAACAAAAfUAIAAAUEIRgCAZAIAJAAEACAAA=","480":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","487":"b:gEGCAAQiAABAZWEIAgBAFCQbKQdQIAQKCCAKAAA=","494":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","498":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","502":[86,124],"513":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","526":[86,124,137],"541":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","558":"b:AEGQAIACAABEfVAIAxAUEMRgCAcAIhJQAOYiAAA=","562":[86,124],"568":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","583":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","587":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","615":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","621":[86,124,77],"625":[86,124,77],"635":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","640":"b:AACSAAAgAAAAIHAIAABAFCQCAQAAIIAACAAAAAA=","656":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","659":[86,124],"664":[86,124],"667":[86,124],"675":[86,124],"679":[86,124],"680":[86,124],"687":[86,124],"691":[86,124],"706":[86,124],"726":[86,124],"734":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","736":[86,124,190],"752":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","757":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","824":[86,124,77],"838":[86,124],"839":[86,124,77],"845":[86,124,77],"853":[86,124],"887":[86,124,142],"889":[86,124],"890":[86,124],"891":[86,124,142],"897":"b:oEWSACiiAEBgfXEIBwA0FGRfKAdQO6RviPY/AAA=","920":"b:oEWSACiiAEBgfXEIBwA0FGRfKAdQO6RviPY/AAA=","922":"b:oEWSACiiAEBgXXEIBwA0FGRfKAdQO6RviPY/AAA=","938":[86,124],"951":[86,124],"955":[86,124],"970":[86,124],"1024":[86,124],"1046":[86,124],"1048":"b:AEGQAAACAAAAfUAIAAAUEIRgCAZAIAJAAEACAAA=","1057":[86,124]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputWrapper.vue":{"51":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","71":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","75":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","86":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","92":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","103":[86,124,178,60,74,206,116,75,76,140,78,141],"105":[86,124,140],"109":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","114":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","131":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","135":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","142":"b:AEGSAIAiABAAfXQIAgAUELRwCA5AIoJAgMACAAA=","146":"b:AEGSAAAiABAAfXQIAAAUELRgCA5AIoJAgMACAAA=","150":[86,124],"154":"b:AEGSAIAiABBEfXQIAxAUEPRgCA8AIpJQAMYiAAA=","158":"b:AEGCAAAiABAAIXQIAAAUEDQgCA4AIoBAAAACAAA=","163":[86,20,23,124,181,190,139],"164":[86,124],"168":[86,124],"169":[86,124],"171":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","176":[86,124],"178":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","210":"b:4EWSAKyiAFBkXXUIBxB0FPR/KS9QO7d/iPY/AgA="},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterOptions.vue":{"41":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","62":"b:4EWSAKwiAFBkfXUIBxB0FPR/CS9QO7d/iPY/AAA=","63":"b:4EWSAKwiAFBkfXUIBxB0FPR/CS9QO7d/iPY/AAA=","64":"b:oEWCAKgiABBgfXUIBwB0FHR/CC9QO6dviPY/AAA=","68":"b:4EWSAKwiAFBkfXUIBxB0FPR/CS9QO7d/iPY/AAA=","71":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","81":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","100":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","119":"b:oEWCAKgiABBgfXUIBwB0FHR/CC9QO6dviPI/AAA=","120":"b:4EWSAKwiAFBkfXUIBxB0FPR/CS9QO7d/iPY/AAA=","124":"b:4EWSAKwiAFBkfXUIBxB0FPR/CS9QO7d/iPY/AAA=","132":"b:4EWSAKwiAFBkfXUIBxB0FPR/CS9QO7d/iPY/AAA=","177":[86,124,141],"178":"b:AAAAAAAAABAAfEAAAgAAEABgAAAAAAAAAMAAAAA=","185":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","193":[86,124,141],"207":[86,124],"219":[86,124,141]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/TextEdit.vue":{"11":"b:4EWSAKiiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","31":[86,124],"33":"b:4EWSAKiiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","35":[86,124],"43":"b:4EWSAKiiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","44":"b:wEGCAIAiABBEYXQIARAUEPQgCC8AIpAAAAYCAAA=","50":"b:4EWSAKiiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","54":[86,124],"58":[86,124],"64":[86,124],"68":"b:4EWSAKiiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","82":[86,124],"86":[86,124],"87":[86,124]},"packages/frontend/editor-ui/src/features/ndv/parameters/composables/useParameterInputContribution.ts":{"16":[86,124],"38":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","39":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","41":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","45":"b:4EWSAKyiAFBkfXUIBxB0FPR/KQ9QO7d/iPY/AgA="},"packages/frontend/editor-ui/src/features/ndv/parameters/utils/fromAIOverride.utils.ts":{"42":[86,20,124],"83":[86,124,181],"90":[86,20,23,124,181,190,139],"106":[86,20,124],"117":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","121":[86,20,124],"132":[86,20,124],"138":[86,20,124],"139":[86,124],"153":[86,20,124],"157":[86,20,124],"184":[86,124],"189":[86,124],"210":[86,23,124,190],"246":[86,20,23,124,181,190,139],"268":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","277":[86,124],"285":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","286":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","302":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","309":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA=","321":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA="},"packages/frontend/editor-ui/src/features/ndv/runData/components/MappingPill.vue":{"13":"b:AEYAAAiCAAAAGVAAAgAQEIQzKAQAOgIhAOQ3AgA="},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunData.vue":{"105":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","106":[86,124,181,136,137,116,210],"108":"b:aEQAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","109":[86,124],"111":[84,86,124,137],"113":"b:aEYAAAiCAAAAOVAAAwAQEIQ3KAQAOiMlgOQ3AgA=","238":"b:4EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","239":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","269":"b:YEIAAAgCAAAAGUAAAgAQEIQ3CAQAOgIgAOQ3AAA=","270":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO5d/CPY/AgA=","271":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","277":"b:AAAAAAAAAAAAGVAAAgAQEAAXAAAAACIAANQHAAA=","278":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","284":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","285":"b:aEQAAAiCAAAAOVAAAwAQEIA3AAQAEiMkgOQ3AgA=","287":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","288":"b:YEQAAAiCAAAAOUAAAwAQEIQ3KAQAOiMkAOQ3AgA=","289":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","290":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","291":"b:4EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/CPY/AgA=","294":"b:4EWCAKiiAABkfXEIBxBQFOR/CAdQM6Z/CPY/AAA=","298":"b:4EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/CPY/AgA=","306":"b:aEQAAAiCAAAAOVAAAwAQEIA3AAQAEiMsgPQ/AgA=","307":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","308":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","309":"b:AEAAAAiCAAAAGUAAAgAQEIQ3KAQAOgIgAOQ3AgA=","317":"b:aEQAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","326":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","331":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","353":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","357":"b:aEYAAAiCAAAAOXAAAwAQEIQ3KAQAOiMtgPQ/AgA=","361":"b:aEYAAAiCAAAAOVAAAwAQEIQ3KAQAOiMtgPQ/AgA=","370":"b:aEYAAAiCAAAAOVAAAwAQEIQ3KAQAOiMtgPQ/AgA=","374":"b:aEYAAAiCAAAAOVAAAwAQEIQ3KAQAOiMtgPQ/AgA=","384":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/CPY/AgA=","386":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","395":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","412":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","421":"b:aEYAAAiCAAAAOXAAAwAQEIQ3KAQAOiMlgOQ3AgA=","425":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","430":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","443":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/CPY/AgA=","449":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","456":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","466":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","469":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","479":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","483":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","487":"b:YAIAAAACAAAAGEAAAgAQEIQ0CAQAKgIAAOAXAAA=","491":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","499":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","502":"b:KEIAAAiAAAAAOVAAAwAQEAATIAQAEiElgOQnAgA=","503":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","511":"b:AEYAAAiCAAAAGVAAAgAQEIQzKAQAOgIhAOQ3AgA=","512":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","516":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","521":[10,86,124,137,210,140,212],"531":[10,86,124,137,210,140,212],"537":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","541":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","542":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","543":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","547":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","548":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","553":[86,124,138],"555":[86,124],"556":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","566":[84,10,86,124,169,137,208,209,210,140],"567":[84,10,86,124,169,137,208,209,210,140],"607":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","611":"b:4EWCAKgiAABkfXEIBxBQFOR/CAdQO5d/CPY/AAA=","612":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","618":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","629":"b:aEYAAAiCAAAAOVAAAwAQEIQ3KAQAOiMtgPQ/AgA=","633":"b:4EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/CPY/AgA=","645":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","662":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","667":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","676":"b:AEAAAAiCAAAAGUAAAgAQEIQ3KAQAOgIgAOQ3AgA=","680":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","698":[10,86,124],"704":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","707":"b:6EWCAKiiAABkfXEIBxBQFOR/CAdQM6d/iPY/AgA=","710":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","713":"b:AAAAAAAAAAAAAEAAAgAAEAAAAAAAEAQIADQcAAA=","714":"b:AAAAAAAAAAAAAEAAAgAAEAAAAAAAEAQIADQcAAA=","731":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","738":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","742":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","743":[3,84,86,124,137],"746":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","750":[86,124,137],"756":"b:AAIAAAAAAAAAIFAAAAAQEIB6AAAAAAAAAAQAAAA=","761":"b:YAYAAAACAAAAGHAAAgAQEIQ2CAQAKgIBAOQXAAA=","771":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","776":"b:aEYAAAiCAAAAOVAAAwAQEIQ3KAQAOiIlgOQ3AgA=","783":"b:YAaAACACAAAAOXAAAgAQEIR+CAQAKqJBAOQXAAA=","792":"b:YAYAAAACAAAAGHAAAgAQEIQ2CAQAKgIBAOAXAAA=","800":[5,6,86,124,137,209,140],"807":[86,124,208,210],"813":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","822":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","843":[86,124,137],"854":"b:qEeAACAgAABkOXEIBxBQEMQ7CAFQK7RfgPYvAgA=","859":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","875":[86,124,166,176,178,186,136,210,211,142],"905":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","927":[86,124],"943":[10,86,124,116,208,210,140],"955":[86,124],"965":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/CPY/AgA=","981":"b:YAIAAAACAAAAGEAAAgAQEIQgAAAAIAIAAOQBAAA=","989":"b:qEeAACAgAABkOXEIBxBQEMQ7CAFQK7RfgPYvAgA=","997":"b:YAIAAAACAAAAGUAAAgAQEIQiCAQAKAIAAOQDAAA=","1002":[86,124,202,204,206,116,75,76,207,140,97],"1038":[86,124,202,204,206,116,75,76,207,140,97],"1056":[86,124],"1062":[86,124,202,206,116,75,76,207,140,97],"1094":[86,124,202,206,116,75,76,207,140,97],"1108":[86,124,202,72,206,116,75,76,207,140,97],"1113":[86,124,72,97],"1167":[86,124,138],"1171":[86,124,140],"1183":[86,124],"1195":[10,86,124,210],"1203":[10,86,124,210],"1207":[10,86,124,210],"1211":[86,124,177],"1224":"b:YAYAAAACAAAAGFAAAgAQEIQ2CAQAKgIBAMQXAAA=","1231":[86,124],"1247":"b:AAAAAAAAAAAAAFAAAAAQEAAXAAAAACAAAAAHAAA=","1278":[10,86,124,137,210,140,212],"1306":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","1331":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","1334":"b:AAAAAAAAAAAAOUAAAgAQEAAQIAAAAAAAgOQlAAA=","1346":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","1352":[86,124,208,210],"1355":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","1373":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","1383":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","1408":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","1412":[86,124],"1421":[86,124],"1435":[84,10,86,124,169,137,208,209,210,140],"1453":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","1456":"b:aEYAAAiCAAAAOVAAAwAQEIQ3KAQAOiIlgOQ3AgA=","1462":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","1469":[10,86,124,210,140,212],"1473":[86,124],"1486":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/CPY/AgA=","1492":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/CPY/AgA=","1498":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/CPY/AgA=","1502":[86,124],"1507":[86,124],"1515":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","1549":[86,124],"1550":"b:AAAAAAAAAAAAGUAAAgAQEAAQAAAAAAAAAMQFAAA=","1554":"b:AAAAAAAAAAAAGUAAAgAQEAAQIAAAAAAAAMQFAAA=","1562":"b:AAAAAAAAAAAAGUAAAgAQEAAQIAAAAAAAAMQFAAA=","1574":[86,124],"1587":[86,124,202,72,204,206,116,75,76,207,140,97],"1607":[86,124],"1638":[86,124,202,204,206,116,75,76,207,140,97],"1651":[86,124,72,97],"1697":[10,86,124,210,140,212],"1699":[10,86,124,137,210,140,212],"1700":[10,86,124,137,210,140,212],"1701":[10,86,124,137,210,140,212],"1710":[86,124],"1712":[10,86,124,210,140],"1738":[86,124],"1802":[86,124],"1819":"b:YAYAAAACAAAAGHAAAgAQEIQ2CAQAKgIBAOAWAAA=","1848":[86,124],"1849":[86,124],"1856":[86,124,204],"1862":[86,124,202,206,116,75,76,207,140,97],"1867":[86,124,202,204,206,116,75,76,207,140,97],"1869":[86,124,202,204,206,116,75,76,207,140,97],"1876":[86,124],"1986":[86,124,47],"2061":[86,124],"2103":[86,124],"2104":[86,124],"2128":"b:KEIAAAiAAAAAOVAAAwAQEAATIAQAEiElgOQnAgA=","2143":[86,124],"2171":[86,124,208],"2173":[86,124,208],"2196":"b:AEYAAAiCAAAAGVAAAgAQEIQzKAQAOgIhAOQ3AgA=","2199":[86,124]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataDisplayModeSelect.vue":{"18":"b:4EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/CPY/AgA=","21":"b:4EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/CPY/AgA=","45":"b:4EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/CPY/AgA=","47":"b:4EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/CPY/AgA=","53":"b:4EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/CPY/AgA=","62":[86,124,181,136,137,116,138,208,209,210,140],"64":[9,84,85,10,86,124,184,137,217]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataItemCount.vue":{"16":"b:YEYAAAiCAAAAGXAAAgAQEIQ3KAQAOiIhAOQ3AgA=","17":"b:YEYAAAiCAAAAGXAAAgAQEIQ3KAQAOiIhAOQ3AgA=","21":[86,124,208,210],"29":"b:YEYAAAiCAAAAGXAAAgAQEIQ3KAQAOiIhAOQ3AgA="},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataPinButton.vue":{"6":"b:AEAAAAiCAAAAGUAAAgAQEIQ3KAQAOgIgAOQ3AgA=","24":"b:AEAAAAiCAAAAGUAAAgAQEIQ3KAQAOgIgAOQ3AgA=","27":"b:AEAAAAiCAAAAGUAAAgAQEIQ3KAQAOgIgAOQ3AgA=","31":[86,124,130,173],"45":[86,124],"48":[86,124],"49":"b:AEAAAAiCAAAAGUAAAgAQEIQ3KAQAOgIgAOQ3AgA=","67":[86,124,72,97]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataSearch.vue":{"44":"b:aEYAAAiCAAAAORAAAwAQAIQ3KAQAOiMlgOQ3AgA=","50":"b:aEYAAAiCAAAAORAAAwAQAIQ3KAQAOiMlgOQ3AgA=","68":"b:aEYAAAiCAAAAORAAAwAQAIQ3KAQAOiMlgOQ3AgA=","72":[177,186,206,116,75,76,207,208,210,77,97],"99":[208,210],"104":[208,210],"109":[208,210],"115":[208,210],"121":[208,210],"134":[177,186,206,116,75,76,207,208,210,77,97],"152":"b:aEYAAAiCAAAAORAAAwAQAIQ3KAQAOiMlgOQ3AgA=","153":[208,210]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataTable.vue":{"87":"b:AEQAAAiCAAAAGQAAAgAQAIQzKAQAOgIgAOQ3AgA=","88":"b:AEYAAAiCAAAAGRAAAgAQAIQzKAQAOgIhAOQ3AgA=","89":"b:AEYAAAiCAAAAGRAAAgAQAIQzKAQAOgIhAOQ3AgA=","91":"b:AEYAAAiCAAAAGRAAAgAQAIQzKAQAOgIhAOQ3AgA=","92":"b:AEYAAAiCAAAAGRAAAgAQAIQzKAQAOgIhAOQ3AgA=","93":[116,208,210,140],"96":"b:AEYAAAiCAAAAGRAAAgAQAIQzKAQAOgIhAOQ3AgA=","97":"b:AEYAAAiCAAAAGRAAAgAQAIQzKAQAOgIhAOQ3AgA=","105":"b:AEYAAAiCAAAAGRAAAgAQAIQzKAQAOgIhAOQ3AgA=","116":"b:AEYAAAiCAAAAGRAAAgAQAIQzKAQAOgIhAOQ3AgA=","153":[212],"165":[10,116,208,210,140],"187":[10,116,210,140],"194":[116],"198":[116],"202":[116,208],"208":"b:AEYAAAiCAAAAGRAAAgAQAIQzKAQAOgIhAOQ3AgA=","221":"b:AEYAAAiCAAAAGRAAAgAQAIQzKAQAOgIhAOQ3AgA=","228":[10,149,169,173,72,137,116,207,208,210,140],"241":[10,149,169,173,72,137,116,207,208,210,140],"254":"b:AEYAAAiCAAAAGRAAAgAQAIQzKAQAOgIhAOQ3AgA=","264":"b:AEYAAAiCAAAAGRAAAgAQAIQzKAQAOgIhAOQ3AgA=","286":[116],"296":[116],"304":[116],"310":[10,149,169,173,72,137,116,207,208,210,140],"318":[116],"320":[116],"342":"b:AEYAAAiCAAAAGRAAAgAQAIQzKAQAOgIhAOQ3AgA=","351":[10,149,169,173,72,137,116,207,208,210,140],"355":"b:AEYAAAiCAAAAGRAAAgAQAIQzKAQAOgIhAOQ3AgA=","359":"b:AEYAAAiCAAAAGRAAAgAQAIQzKAQAOgIhAOQ3AgA=","371":"b:AEYAAAiCAAAAGRAAAgAQAIQzKAQAOgIhAOQ3AgA=","396":[169,177,136,137,116,208,209,210,140,97,212],"414":"b:AEYAAAiCAAAAGRAAAgAQAIQzKAQAOgIhAOQ3AgA=","430":"b:AEYAAAiCAAAAGRAAAgAQAIQzKAQAOgIhAOQ3AgA=","458":[173,177,116,140,97],"459":[173,177,116,140,97],"468":"b:AEYAAAiCAAAAGRAAAgAQAIQzKAQAOgIhAOQ3AgA=","513":[137,209,210,97],"570":"b:AEYAAAiCAAAAGRAAAgAQAIQzKAQAOgIhAOQ3AgA=","582":"b:AEYAAAiCAAAAGRAAAgAQAIQzKAQAOgIhAOQ3AgA=","591":[116],"593":"b:AEYAAAiCAAAAGRAAAgAQAIQzKAQAOgIhAOQ3AgA=","596":"b:AEYAAAiCAAAAGRAAAgAQAIQzKAQAOgIhAOQ3AgA=","613":"b:AEYAAAiCAAAAGRAAAgAQAIQzKAQAOgIhAOQ3AgA=","669":"b:AEYAAAiCAAAAGRAAAgAQAIQzKAQAOgIhAOQ3AgA=","699":[212],"713":"b:AEYAAAiCAAAAGRAAAgAQAIQzKAQAOgIhAOQ3AgA=","731":[10,149,169,173,72,137,116,207,208,210,140],"745":[116],"754":[10,149,169,173,72,137,116,207,208,210,140]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunInfo.vue":{"7":"b:YEQAAAiCAAAAEQAAAgAQAIQ3CAQAOgIgAKA3AgA=","15":"b:YEQAAAiCAAAAEQAAAgAQAIQ3CAQAOgIgAKA3AgA=","19":"b:YEQAAAiCAAAAEQAAAgAQAIQ3CAQAOgIgAKA3AgA=","23":"b:YEQAAAiCAAAAEQAAAgAQAIQ3CAQAOgIgAKA3AgA=","33":"b:YEQAAAiCAAAAEQAAAgAQAIQ3CAQAOgIgAKA3AgA="},"packages/frontend/editor-ui/src/features/ndv/runData/components/TextWithHighlights.vue":{"6":"b:aEYAAAiCAAAAOVAAAwAQEIQ3KAQAOiMtgPQ/AgA=","11":"b:aEYAAAiCAAAAOVAAAwAQEIQ3KAQAOiMtgPQ/AgA=","16":"b:aEYAAAiCAAAAOVAAAwAQEIQ3KAQAOiMtgPQ/AgA=","20":[86,124,208,210],"29":"b:aEYAAAiCAAAAOVAAAwAQEIQ3KAQAOiMtgPQ/AgA="},"packages/frontend/editor-ui/src/features/ndv/runData/components/VirtualSchema.vue":{"69":"b:aEQAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","107":"b:aEQAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","108":"b:aEQAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","110":[86,124],"114":[86,124,116],"117":[86,124,116],"123":"b:YEAAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","134":"b:YEAAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","143":"b:YEAAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","159":[86,124,137,209,140],"165":"b:YEAAAAiCAAAAGUAAAwAQEIA3AAQAEiMkAPA3AgA=","176":"b:YEAAAAiCAAAAGUAAAwAQEIA3AAQAEiMkAPA3AgA=","205":"b:YEAAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","209":"b:YEAAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","231":"b:YEAAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","254":"b:YEAAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","286":"b:aEQAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","298":"b:YEAAAAiCAAAACUAAAwAAEIA3AAQAEiMsADAeAgA=","320":"b:aEQAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","366":"b:YEAAAAiCAAAAOUAAAwAQEIA3AAQAEiMkgPQ/AgA=","384":"b:YEAAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","388":[3,10,86,124,137,210],"403":"b:aEQAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","405":"b:aEQAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","431":"b:aEQAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","439":"b:aEQAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","443":"b:aEQAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","444":[86,124,210],"456":"b:aEQAAAiCAAAAOUAAAwAQEIA3AAQAEiMkgPQ/AgA=","461":"b:YEAAAAiCAAAAOUAAAwAQEIA3AAQAEiMkgPQ/AgA=","463":"b:YEAAAAiCAAAAOUAAAwAQEIA3AAQAEiMkgPQ/AgA=","466":"b:aEQAAAiCAAAAOUAAAwAQEIA3AAQAEiMkgPQ/AgA=","467":[86,124],"473":[86,124,116],"482":[86,124,116],"484":[86,124,116],"486":[86,124,116],"511":"b:aEQAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","523":[86,124,210],"524":[86,124,210],"525":[86,124],"543":"b:aEQAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","545":"b:aEQAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","552":"b:aEQAAAiCAAAAGUAAAwAQEIA3AAQAEiMsgPQ/AgA=","558":"b:aEQAAAiCAAAAGUAAAwAQEIA3AAQAEiMsgPQ/AgA=","563":[86,124],"564":[86,124,116],"565":[86,124],"574":[86,124,210],"579":[86,124,205,211],"593":[86,124],"602":[86,124,136],"610":[86,124],"622":"b:aEAAAAiCAAAACUAAAAAAEIAjAAQAAAMEABAGAgA=","628":[86,124,136,204,75]},"packages/frontend/editor-ui/src/features/ndv/runData/components/VirtualSchemaHeader.vue":{"10":"b:YEAAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","22":"b:YEAAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","24":"b:YEAAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","32":[86,124],"63":[86,124],"70":[86,124,204],"71":[86,124],"72":[86,124,204],"77":[86,124,205,211],"78":[86,124],"79":[86,124,205,211],"82":[86,124,205,211],"84":[86,124,205,211]},"packages/frontend/editor-ui/src/features/ndv/runData/components/VirtualSchemaItem.vue":{"37":"b:aEQAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","41":[86,124],"60":[86,124],"70":"b:aEQAAAiCAAAAOUAAAwAQEIA3AAQAEiMsgPQ/AgA=","77":[86,124,210],"105":[86,124],"107":"b:YEAAAAiCAAAAOUAAAwAQEIA3AAQAEiMsAPQqAgA="},"packages/frontend/editor-ui/src/features/ndv/runData/schemaPreview.store.ts":{"12":"b:+EeCEKjjAABkf3EIB5BQ3OR/KAdQP7d/yPa/AwA=","22":"b:cEcAEAjDAABAG3AIA5AQ2IQ3CAQAPjctQPS/AwA=","31":"b:AAAAAAAAAAAACEAAAgAAEAAQAAAAEAUMADQcAgA=","50":"b:cEcAEAjDAABAG3AIA5AQ2IQ3CAQAPjMlQOC3AwA="},"packages/frontend/editor-ui/src/features/ndv/settings/components/NodeSettings.vue":{"80":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","141":"b:4EWCAKiiAABkfXEIBxBQFOR/CAdQO7d/iPY/AgA=","154":[86,124],"171":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","174":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","175":[86,124,45],"178":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","179":[86,124,45],"182":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","192":"b:4EWCAKiiAABkfXEIBxBQFOR/CAdQO7d/iPY/AgA=","195":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","196":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","198":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","204":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","207":[86,124,202,204,206,116,75,76,207,140,97],"209":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","211":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO5d/iPY/AgA=","213":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/CPY/AgA=","217":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","222":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","224":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","228":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","242":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","256":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","264":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","268":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","272":"b:gEGCAKAiAABgZXEIAgBAFGQbKAdQIYVKCCQKAAA=","276":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","279":"b:gEGCAKAiAABgZXEIAgBAFGQbKAdQIYVKCCQKAAA=","280":"b:gACCAKAiAAAgYHEAAgBAEGQaAANQIYVACAQKAAA=","284":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","288":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","297":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","298":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","303":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","306":"b:4EWAAKiiAABkfXEIBxAQFMR/KAdQOrZ/gPY/AgA=","309":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","311":[86,124,209],"312":[86,124],"314":[86,124],"315":[86,124],"316":[86,124],"322":[86,124],"324":[86,124],"332":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","339":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","348":"b:QEGCAIACAABEfVAIAxAQEORoCAcAIhJQCOYiAAA=","506":[86,124],"518":[86,124],"522":[86,124,139],"530":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","533":"b:oECCAKAiAABkfXEIBxAQEORqCANQK5BeiNYKAAA=","539":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","554":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","555":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","556":[86,124],"558":"b:AEGAAAACAAAAbVAIAABAEIRgCAZAIAIAAEACAAA=","559":"b:AECAAAACAAAAbVAIAAAAEIRgCAJAIAAAAEACAAA=","562":[86,124],"567":"b:YAAAAAACAAAAEEAAAgAQEIAwAAQACAIAAKAGAAA=","573":[84,85,86,17,23,124,173,183,195,133,77,78],"587":[86,124],"597":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","614":[86,124],"618":[86,124],"622":[86,124,209],"626":[86,124],"639":[10,86,124,184,135,202,139,77,141,142],"643":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","654":"b:oEWAACAgAABkOXEIBxBQEMQ7CAFQK7RfgPYvAgA=","660":"b:gEGCAKAiAABgZXEIAgBAFGQbKAdQIYVKCCQKAAA=","672":[86,124],"684":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","712":[86,124],"714":[86,124],"746":[86,124],"758":[86,124],"805":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA="},"packages/frontend/editor-ui/src/features/ndv/settings/components/NodeSettingsHeader.vue":{"25":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","29":"b:YAAAAAACAAAAGEAAAgAQEIQ2CAQAKgIAAOAXAAA=","33":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","49":[86,124,209],"70":"b:YAAAAAACAAAAEEAAAgAQEIAwAAQACAIAAKAGAAA=","71":[86,124],"72":[86,124]},"packages/frontend/editor-ui/src/features/ndv/settings/components/NodeSettingsHint.vue":{"13":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/CPY/AgA=","16":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/CPY/AgA=","68":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/CPY/AgA=","72":[86,124,209],"77":[86,124,209]},"packages/frontend/editor-ui/src/features/ndv/settings/components/NodeSettingsTabs.vue":{"28":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","43":[86,124,188,199],"45":[86,124],"47":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","51":[86,124,39],"53":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","61":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","127":[86,124,209],"155":[86,124],"158":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA="},"packages/frontend/editor-ui/src/features/ndv/settings/components/NodeWebhooks.vue":{"21":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","38":"b:AACAAAAAAAAAQEAAAgAAEAQBKAMQIAAAACACAAA=","45":"b:AAAAAAAAAAAAAEAAAgAAEAQBKAMAIAAAACACAAA=","53":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","58":"b:gECAAAAAAAAAYGAAAgAAEAQTKANQIAQAACACAAA=","70":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","124":"b:AACAAAAAAAAAQEAAAgAAEAQBKAMQIAAAACACAAA=","177":[86,124],"192":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","193":[86,124,135,202,139,77,141,142],"200":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","208":[86,124],"218":"b:AAAAAAAAAAAAAEAAAgAAEAQBKAMAIAAAACACAAA=","224":"b:AAAAAAAAAAAAAEAAAgAAEAQBKAMAIAAAACACAAA=","229":"b:AAAAAAAAAAAAAEAAAgAAEAQBKAMAIAAAACACAAA=","235":[86,124],"242":[86,124]},"packages/frontend/editor-ui/src/features/ndv/settings/composables/useNodeSettingsParameters.ts":{"40":[86,124],"43":[86,124],"60":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","62":[86,124],"72":"b:QEGCAIACAABEfVAIAxAQEORoCAcAIhJQCOYiAAA=","146":[86,124,77],"186":[86,124],"203":"b:4EWSAKyiAEBkfXEIBxB0FOR/KQdQO7d/iPY/AgA="},"packages/frontend/editor-ui/src/features/ndv/shared/composables/useBinaryDataAccessTooltip.ts":{"9":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","13":[86,124]},"packages/frontend/editor-ui/src/features/ndv/shared/ndv.store.ts":{"41":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","45":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","46":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","109":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","113":"b:4EWCAKiiABBkfXUIBxBQFPR/KA9QO7d/iPY/AgA=","138":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","142":"b:4EWCAKiiABBkfXUIBxBQFPR/KA9QO7d/iPY/AgA=","149":"b:AEGCAAAiABAAfXQIAgAQEDQwCA4AIoJAgMQCAAA=","153":"b:4EWSAKwiABBkfXEIBxB0FOR/CQdQO7d/iPY/AAA=","155":[86,124,116],"157":[86,124,116],"159":"b:aEYAAAiCAAAAOVAAAwAQEIQ3KAQAOiMtgPQ/AgA=","161":"b:6EeCAKiiAABkfXEIBxBQFOR/KQdQO7d/iPY/AgA=","163":"b:aEYAAAiCAAAAOVAAAwAQEIQ3KAQAOiMtgPQ/AgA=","165":"b:YEAAAAiCAAAAOUAAAwAQEIA3AAQAEiMkgPQ/AgA=","185":"b:YAAAAAAAAAAAfHAAAgAQEIA7AAAAEAQAAMQCAAA=","187":"b:IAAAAAAAAAAAfHAAAgAQEAA7AAAAEAQAAMQCAAA=","189":"b:AAAAAAAAABAAeEAAAgAQEAAwAAAAAAJAAMQAAAA=","191":[86,124],"193":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","206":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","214":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","231":"b:8E/CAKDjAQDk/3cIH5BQHOx/P0fwP/9/+P//BwA=","233":"b:oE2AAKAgAEBkOXEIBxBQEMQ7CQFwK7RfAPYvAwA=","238":"b:4EWCAKiiAEBkfXEIBxB0FOR/KAdQO7d/CPY/AgA=","247":"b:4EWCAKiiAABkfXEIBxBQFOR/CAdQM6d/CPY/AgA=","251":[10,86,124,210,140],"255":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/CPY/AgA=","259":[86,124],"269":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/CPY/AgA=","273":"b:oEGAACAgAABkGXEIBxBQEMQ7CQFQK7ReAPYvAgA=","277":"b:AAAAAAAAAAAAAEAAAAAQEAAXAAAAACAAAAQHAAA=","288":[86,124,202,204,206,116,75,76,207,140,97],"292":[86,124,202,204,206,116,75,76,207,140,97],"296":"b:AEGAAAACAAAAfUAIAgAQEARwCAYAIgJAgMACAAA=","300":[86,124,116],"318":[86,124,116],"328":[86,124,116],"332":[86,124,116],"336":[86,124,116],"340":[10,86,124,116,208,210,140],"345":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","353":"b:6EeCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","361":[86,124,116],"366":[10,86,124,116,208,210,140],"371":[86,124],"376":"b:AEEAAAACABAAfUAIAgAQEAQwCAYAIgBAAMQAAAA=","380":[86,124],"393":"b:AEGQAIACAAAAfUAIAgAUEIRwCAZAIgJAgMACAAA=","470":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","474":"b:CAAQEAAgAAAAgUAAFAAAkAABAAAAAAAAAAgAAwA=","498":"b:+E/SkKzjAVDk/3cIH5B03Px/PW/wP/9/2P//BwA=","501":"b:+E/SkKzjAVDk/3cIH5B03Px/PW/wP/9/2P//BwA=","525":"b:8E/SkKzjAVDk/3cIH5B03Px/L2/wP/9/mP//BwA=","528":"b:8E/SkKzjAVDk/3cIH5B03Px/L2/wP/9/mP//BwA="},"packages/frontend/editor-ui/src/features/ndv/shared/ndv.utils.ts":{"42":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","58":"b:QEGCAIACAABEfVAIAxAQEORoCAcAIhJQCOYiAAA=","133":"b:QEGCAIACAABEfVAIAxAQEORoCAcAIhJQCOYiAAA=","172":[86,124],"226":[86,124],"262":"b:QEGSAIACAABEfVAIAxAQEORgCAcAIhJQCOYiAAA=","268":"b:QEGSAIACAABEfVAIAxAQEORgCAcAIhJQCOYiAAA=","290":[86,20,124,77,78],"291":[86,20,124,77,78],"294":[86,124,77],"308":"b:QEGCAIACAABEfVAIAxAQEORoCAcAIhJQCOYiAAA=","329":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","336":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","340":"b:4EWSAKiiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","346":[86,124],"362":"b:QEGCAIACAABEfVAIAxAQEORoCAcAIhJQCOYiAAA=","368":"b:AAAAAAAAABAAfEAAAgAQEABgAAAAAABAAMAAAAA=","404":[86,124],"414":[86,124],"448":"b:4EWSAKiiAEBkfXEIBxB0FOR/KAdQO7d/iPY/AgA=","459":"b:4EWSAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","623":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","735":"b:4EWSAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","783":"b:QEGSAIACAABEfVAIAxAQEORoCAcAIhJQCOYiAAA=","789":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","798":"b:QEGSAIACAABEfVAIAxAQEORoCAcAIhJQCOYiAAA=","804":"b:QEGSAIACAABEfVAIAxAQEORoCAcAIhJQCOYiAAA=","811":"b:QACAAAAAAABEAEAAARAAEMBAAAMAIBAQAAIiAAA=","820":"b:QACAAAAAAABEAEAAARAAEMBAAAMAIBAQAAIiAAA=","826":"b:QACAAAAAAABEAEAAARAAEMBAAAMAIBAQAAIiAAA=","837":"b:QEGSAIACAABEfVAIAxAQEORoCAcAIhJQCOYiAAA=","846":"b:QACAAAAAAABEAEAAARAAEMBAAAMAIBAQAAIiAAA=","849":"b:QACAAAAAAABEAEAAARAAEMBAAAMAIBAQAAIiAAA=","857":"b:QACAAAAAAABEAEAAARAAEMBAAAMAIBAQAAIiAAA="},"packages/frontend/editor-ui/src/features/ndv/shared/views/NodeDetailsView.vue":{"77":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","78":"b:4EWCAKgiAABkfTEIBxBQBOR/CAdQO7d/CPY/AAA=","99":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","118":"b:4EWCAKiiAABkfTEIBxBQBOR/KQdQO7d/CPY/AgA=","120":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","124":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","133":[5,6,177,135,116,210,97],"135":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","149":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","154":"b:4EWCAKiiAABkfTEIBxBQBOR/CAdQM4d/CPY/AgA=","161":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","174":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","180":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","201":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","208":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","210":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","214":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","231":[147,130,173,136],"237":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","242":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","244":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","262":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","268":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","289":"b:4EWCAKiiAABkfTEIBxBQBOR/CAdQM6d/CPY/AgA=","304":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","315":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","319":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","321":"b:oEGAACAgAABkGTEIBxBQAMQ7CQFQK7ReAPYvAgA=","323":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","325":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","329":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","331":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","335":"b:4EWCAKgiAABkfTEIBxBQBOR/CAdQO7d/CPY/AAA=","337":"b:4EWCAKiiAABkfTEIBxBQBOR/CAdQM7d/CPY/AgA=","339":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","341":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","343":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","347":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","358":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","383":"b:YAIAAAACAAAAGAAAAgAQAIQgAAAAIAIAAOQBAAA=","387":[137],"391":"b:AAGCAAAAAABAfBAABgBQAEAoAAEQAYIMANYHAAA=","397":[116,210,140],"412":[137,116,208,209,210,140],"421":[10,116,208,210,140],"455":[210],"460":"b:4EWCAKAiAABkfTEIBxBQBOR+CAdQI6dfCPYeAAA=","466":"b:YAAAAAACAAAAEAAAAgAQAIAwAAQACAIAAKAGAAA=","467":[5,6,177,135,116,210,97],"484":"b:4EWCAKAiAABkfTEIBxBQBOR+CAdQI6dfCPYeAAA=","493":[10,210],"499":[135,202,139,141],"503":[139],"507":"b:oEGAACAgAABkGTEIBxBQAMQ7CQFQK7ReAPYvAgA=","554":"b:4EWCAKiiAABkfTEIBxBQBOR/CAdQM7d/CPY/AgA=","563":[10,210,140,212],"568":"b:4EWCAKiiAABkfTEIBxBQBOR/CAdQM7d/CPY/AgA=","576":"b:AEQAAAiCAAAAGQAAAgAQAIQzKAQAOgIgAOQ3AgA=","580":[116,140],"598":"b:AAQAAAAAAABAYAAAAAAQAAAaAAAAADAAAAAHAAA=","603":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","608":[208,210],"612":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","616":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","624":[181,202,136,137,116,138,208,209,210,140],"630":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","648":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","658":"b:4ESCAAAgAABkfTEIAxAQAMR7CAIAIIBEAMYfAAA=","696":[10,137,210,140,212],"700":[10,210,140],"704":"b:4EWCAKiiAABkfTEIBxBQBOR/CAdQM6d/CPY/AgA=","705":"b:4EWCAKiiAABkfTEIBxBQBOR/CAdQM6d/CPY/AgA=","710":[10,210,140],"711":[10,210,140],"716":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","721":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","724":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","745":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","751":"b:AAAAEAAgAAAggxAAFAAAgAADAAAAAAAAAAiAAwA=","825":"b:4EWCAKAiAABkfTEIBxBQBOR+CAdQI6dfCPYeAAA=","833":[181,137,116,208,209,210,140],"851":"b:4EWCAKiiAABkfTEIBxBQBOR/KAdQO7d/CPY/AgA=","891":[210],"898":[202,136,138,210,140]},"packages/frontend/editor-ui/src/features/resolvers/composables/useDynamicCredentials.ts":{"13":"b:/k/38777Adzk/3c5F5B83vz/j///////n///BwA=","17":"b:/k/38777Adzk/3c5F5B83vz/j///////n///BwA="},"packages/frontend/editor-ui/src/features/resolvers/composables/useNodePrivateCredential.ts":{"14":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","20":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","22":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","26":"b:AACCAAAhAAAEIHQIAIBAFCQCAQAAMIAACAAAAAA=","32":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","41":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","47":[86,124]},"packages/frontend/editor-ui/src/features/resolvers/composables/usePrivateCredentials.ts":{"12":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","15":"b:8EeykKz7ARDk/zcpH5BQ3vx/OW/0f/9/+P6/BwA="},"packages/frontend/editor-ui/src/features/settings/communityNodes/communityNodes.store.ts":{"12":"b:4EWSAKiiAARkfXEIBxBQFOR/KAdQO7f/iPY/AgA=","22":[86,124,39,191,58],"23":[86,124],"30":[86,124,191,58],"36":[86,124,39,191,58],"37":[86,124,191,58],"46":[86,124,39,191,58],"55":[86,124,39,191,58],"60":[86,124,191,58],"65":[86,124,191],"70":[86,124,191],"75":[86,124,191],"79":[86,124,191,58],"89":[86,124,39],"94":[86,124]},"packages/frontend/editor-ui/src/features/settings/communityNodes/composables/useInstalledCommunityPackage.ts":{"9":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","17":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","18":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","26":[86,124,39],"33":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","35":[10,86,124,39,184,139],"45":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","55":"b:4EWCAKiiAABkfXEIBxBQFOR/KAdQO7d/iPY/AgA=","59":[86,124,39]},"packages/frontend/editor-ui/src/features/settings/context/context.utils.ts":{"29":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA=","43":[86,124],"48":[86,124],"59":[86,124],"82":[86,124],"97":[86,124],"103":[86,124],"108":[86,124],"112":[86,124],"122":[86,124],"124":[86,124],"128":[86,124],"143":[86,124]},"packages/frontend/editor-ui/src/features/settings/environments.ee/environments.store.ts":{"13":"b:/k/z8777Adjk/3c7H5B03vx/v+/3//9//f//BwA=","18":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","21":"b:AAABAwA4AIgAgEIjHAAAEgAAgAAEwAAADQgAAAA=","22":[86,124,192,203],"29":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","30":[86,124,210,212],"35":[86,124,192],"36":[86,124,192],"39":[86,124,192,203,210,212,218],"47":[86,124,192],"51":[86,124],"52":[86,124],"60":[86,124,192],"68":[86,124,192],"71":[86,124,192],"76":[86,124,192],"81":[86,124,192],"86":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","90":[86,124]},"packages/frontend/editor-ui/src/features/settings/sso/sso.store.ts":{"18":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","25":[86,16,151,124,63],"35":[86,124],"43":[86,124],"58":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","110":[86,16,151,143,124,193,63,194],"111":[86,124],"118":[86,124],"122":[86,124],"124":[86,124],"132":[86,124],"135":[86,124],"157":[86,124],"164":[86,124],"170":[86,124],"173":[86,16,151,124,63,194],"174":[86,124],"179":[86,124],"194":[86,16,151,124,63],"196":[86,124],"198":[86,124],"203":[86,124],"208":[86,124],"213":[86,124],"218":[86,124],"223":[86,124]},"packages/frontend/editor-ui/src/features/settings/usage/usage.store.ts":{"38":"b:8E/Dk6z7AYjk/3crH5BQ3ux/v0f0//9/3P//BwA=","45":[86,124],"46":[86,124],"47":[86,124],"48":[86,124],"49":[145,86,124],"52":[86,124],"55":[86,124],"58":[86,124],"59":[86,124],"60":[86,124],"61":[86,124],"64":[86,124],"70":[86,124],"74":"b:8E/Dk6z7AYjk/3cpH5BQ3ux/v0f0//9/3P//BwA=","79":"b:8E/Dk6z7AYjk/3crH5BQ3ux/v0f0//9/3P//BwA=","84":[86,124],"94":[86,124],"103":[86,124],"107":[86,124],"129":[86,124],"135":[86,124],"138":[86,124],"142":[86,124],"143":[86,124]},"packages/frontend/editor-ui/src/features/setupPanel/setupPanel.store.ts":{"10":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","14":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","20":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","22":[144,86,124],"29":[144,86,124],"34":[144,86,124]},"packages/frontend/editor-ui/src/features/shared/banners/banners.store.ts":{"14":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","28":[86,124],"32":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","58":[86,124],"70":[86,124],"71":[86,124],"80":[86,124,172,69,79,80],"81":[86,124],"84":[86,124],"96":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","100":[86,22,124],"105":[86,124],"109":[86,124],"113":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","116":[86,124],"117":[86,124]},"packages/frontend/editor-ui/src/features/shared/banners/components/BannerStack.vue":{"38":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","46":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","51":[86,22,124],"55":[86,22,124],"56":[86,22,124],"59":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","65":[86,22,124],"86":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","89":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useAgentNavigationCommands.ts":{"28":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","40":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","42":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","43":[86,16,89,155,19,91,124,45,194,99],"45":[86,124],"50":[86,124],"55":[86,124],"61":[86,124],"72":[86,124],"78":[86,124],"97":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","116":[86,124]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useChatHubCommands.ts":{"27":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","36":[86,18,155,19,156,20,21,124],"43":[86,18,155,19,156,20,21,124],"48":[86,124],"77":[86,18,155,19,156,20,21,124],"78":[86,18,155,19,156,20,21,124],"83":[86,18,155,19,156,20,21,124],"85":[86,18,155,19,156,20,21,124],"86":[86,18,155,19,156,20,21,124],"101":[86,18,155,19,156,20,21,124],"117":[86,124],"123":[86,18,155,19,156,20,21,124],"124":[86,18,155,19,156,20,21,124],"127":[86,18,155,19,156,20,21,124],"142":[86,124],"148":[86,18,155,19,156,20,21,124],"149":[86,18,155,19,156,20,21,124],"152":[86,18,155,19,156,20,21,124],"161":[86,124],"167":[86,18,155,19,156,20,21,124],"168":[86,18,155,19,156,20,21,124],"171":[86,18,155,19,156,20,21,124],"177":[86,124],"246":[86,124]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useCommandBar.ts":{"88":[86,124],"92":[86,124,216],"108":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","116":"b:/k/38777Ad7k/3c7H5B83vz/j///////n///BwA=","123":"b:/k/38777Ad7k/3c7H5B83vz/j///////n///BwA=","150":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","151":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","153":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","160":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","168":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","177":"b:/k/CA6DzARDk/3cIH5BQHPx/DUfwP/9/mP//BwA=","180":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","183":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","188":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","190":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","191":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","194":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","196":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","198":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","202":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","206":[86,124],"211":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","213":[86,124],"225":[86,124],"228":[86,124],"234":[86,124],"238":[86,124],"259":[86,124],"260":[86,124],"282":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","285":[86,124,216],"288":[86,124,216],"299":[86,124],"303":[86,124],"313":[86,124],"323":[86,124],"341":[86,124],"351":[86,124,216],"378":[86,124],"379":[86,124],"394":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","398":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","406":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","411":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","415":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","417":[86,124],"426":[86,124],"431":[86,124],"454":[86,124],"461":[86,124],"473":[86,124,216],"477":[86,124,216],"482":[86,124,216],"493":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","494":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useCredentialNavigationCommands.ts":{"26":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","40":[86,124],"41":[86,124],"44":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","46":[86,124],"53":[86,124],"73":[86,124],"79":[86,124],"96":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","118":[86,124],"149":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","152":[86,124,216]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useDataTableNavigationCommands.ts":{"24":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","37":[86,124],"43":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","45":[86,124],"46":[86,124],"49":[86,124],"56":[86,124],"72":[86,124],"78":[86,124],"98":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","119":[86,124],"136":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useExecutionCommands.ts":{"27":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","38":[86,124,47,72,136,73,137,215,216,217],"40":[86,124,47,72,136,73,137,215,216,217],"46":[86,124,47,72,136,73,137,215,216,217],"50":[86,124,47,72,136,73,137,215,216,217],"56":[86,124,47,72,136,73,137,215,216,217],"61":[86,124],"67":[86,124],"69":[86,124],"78":[86,124,47,72,136,73,137,215,216,217],"84":[86,124,47,72,136,73,137,215,216,217],"89":[86,124],"113":[86,124],"132":[86,124],"149":[86,124],"178":[86,124],"194":[86,124],"204":[86,124],"214":[86,124,47,72,136,73,137,215,216,217],"242":[86,124],"255":[86,124],"288":[86,124],"304":[86,124]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useExecutionNavigationCommands.ts":{"10":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","18":[86,124],"19":[86,124],"22":[86,124],"28":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","44":[86,124]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useGenericCommands.ts":{"31":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","40":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","45":[86,124],"65":[86,124],"84":[86,124],"107":[86,124],"126":[86,124],"143":[86,124],"158":[86,124],"173":[86,124],"188":[86,124],"203":[86,124],"218":[86,124],"233":[86,124],"248":[86,124]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useInstanceAiCommands.ts":{"20":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","26":"b:/k/38777Ad7k/3c5F5B83vz/j///////n///BwA=","27":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","32":[86,124],"38":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","46":[86,124],"59":[86,124],"85":[86,124,216]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useNodeCommands.ts":{"25":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","38":"b:8E/CAKDjAQDk/3cIH5BQHOx/DUfwP/9/mP//BwA=","41":"b:8E/CAKDjAQDk/3cIH5BQHOx/DUfwP/9/mP//BwA=","43":"b:8E/CAKDjAQDk/3cIH5BQHOx/DUfwP/9/mP//BwA=","47":"b:8E/CAKDjAQDk/3cIH5BQHOx/DUfwP/9/mP//BwA=","52":[86,124],"56":[86,124],"57":[86,124],"60":[86,124],"73":[86,124],"81":[86,124],"97":[86,124],"103":[86,124],"104":[86,124],"107":[86,124],"108":[86,124],"111":[86,124],"115":[86,124],"116":[86,124],"121":"b:8E/CAKDjAQDk/3cIH5BQHOx/DUfwP/9/mP//BwA=","135":[86,124],"154":"b:8E/CAKDjAQDk/3cIH5BQHOx/DUfwP/9/mP//BwA="},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useProjectNavigationCommands.ts":{"22":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","30":[86,124],"47":[86,124],"53":[86,124],"71":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","88":[86,124],"101":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useRecentResources.ts":{"55":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","73":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","92":[1,2,3,86],"95":[1,2,86],"99":"b:8E+CAIDjAADk+3cIH5BQDOx/CUUAPndlmP7/AwA=","105":"b:4EWCAIAiAABkeVEABxBQBOR/CAUAOjdlAPY/AAA=","108":"b:IACCAAAAAABEKVAABwBQBMA7AAAAIjQAAHYPAAA=","124":[86,216],"132":[86,216],"140":[86,216],"144":[86],"162":[86],"172":[86,216],"184":[86],"190":[86],"202":[86],"208":[86,216],"210":[86,216],"214":[86],"216":[86,216],"219":[86,216],"224":[86,216],"228":[86,216],"237":[86,216],"242":[86],"245":[86,216],"246":[86,216],"252":[86,216],"259":[86],"260":[86],"263":[86],"264":[86]},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useWorkflowCommands.ts":{"50":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","67":"b:8E/CAKDjAQDk/3cIH5BQHOx/DUfwP/9/mP//BwA=","70":"b:8E/CAKDjAQDk/3cIH5BQHOx/DUfwP/9/mP//BwA=","72":"b:8E/CAKDjAQDk/3cIH5BQHOx/DUfwP/9/mP//BwA=","76":"b:8E/CAKDjAQDk/3cIH5BQHOx/DUfwP/9/mP//BwA=","80":"b:8E/CAKDjAQDk/3cIH5BQHOx/DUfwP/9/mP//BwA=","83":"b:8EeCAKDjAQDk/3cIH5BQHOx/CUfwP/9/mP+/BwA=","84":"b:AACCAAAhAAAEIHQIAIBAFCQCAQAAMIAACAAAAAA=","96":"b:AACCAAAhAAAEIHQIAIBAFCQCAQAAMIAACAAAAAA=","99":[86,124],"116":"b:8E/CAKDjAQDk/3cIH5BQHOx/DUfwP/9/mP//BwA=","123":[86,124],"137":[86,124],"162":[86,124],"182":[86,124],"198":[86,124],"212":[86,124],"233":[86,124],"247":[86,124],"263":[86,124],"286":"b:8E/CAKDjAQDk/3cIH5BQHOx/DUfwP/9/mP//BwA=","288":"b:8EeCAKDjAQDk/3cIH5BQHOx/CUfwP/9/mP+/BwA=","289":[86,124,212,213,142],"290":[86,124,212,213,142],"296":[86,124,213,142],"306":[86,124,213,142],"309":[86,124],"328":"b:8E/CAKDjAQDk/3cIH5BQHOx/DUfwP/9/mP//BwA=","334":[86,124],"343":[86,124],"369":"b:8E/CAKDjAQDk/3cIH5BQHOx/DUfwP/9/mP//BwA=","385":[86,124],"399":[86,124],"406":"b:8E/CAKDjAQDk/3cIH5BQHOx/DUfwP/9/mP//BwA=","422":[86,124],"439":[86,124],"453":[86,124],"460":"b:8E/CAKDjAQDk/3cIH5BQHOx/DUfwP/9/mP//BwA=","470":"b:8E/CAKDjAQDk/3cIH5BQHOx/DUfwP/9/mP//BwA="},"packages/frontend/editor-ui/src/features/shared/commandBar/composables/useWorkflowNavigationCommands.ts":{"29":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","44":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","46":[86,124],"57":[86,124],"71":[86,124],"80":[86,124],"98":[86,124],"104":[86,124],"105":[86,124],"107":[86,124],"115":[86,124],"160":[86,124],"167":[86,124],"170":[86,124],"174":"b:/k//8777Ad7k/3c7H5B83vz/j///////n///BwA=","196":[86,124],"216":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","219":[86,124,216]},"packages/frontend/editor-ui/src/features/shared/contextMenu/components/ContextMenu.vue":{"17":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","26":[84,86,124,184,96,134,71,200,201,205,97,213],"30":[84,86,124,184,96,134,71,200,201,205,97,213],"51":[84,86,124,184,96,134,71,200,201,205,97,213],"59":[84,86,124,184,96,134,71,200,201,205,97,213],"66":[84,86,124,184,96,134,71,200,201,205,97,213],"69":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","76":[84,86,124,184,96,134,71,200,201,205,97,213],"77":[84,86,124,184,96,134,71,200,201,205,97,213],"93":[84,86,124,184,96,134,71,200,201,205,97,213],"94":[84,86,124,184,96,134,71,200,201,205,97,213],"106":[84,86,124,184,96,134,71,200,201,205,97,213],"107":[84,86,124,184,96,134,71,200,201,205,97,213]},"packages/frontend/editor-ui/src/features/shared/contextMenu/composables/contextMenuGroupView.ts":{"20":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA="},"packages/frontend/editor-ui/src/features/shared/contextMenu/composables/useContextMenu.ts":{"28":[86,124],"32":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","35":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","37":[84,86,124,184,96,134,71,200,201,205,97,213],"49":[86,124],"56":[84,86,124,184,96,134,71,200,201,205,97,213],"60":[84,86,124,184,96,134,71,200,201,205,97,213],"62":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","67":[84,86,124,184,96,134,71,200,201,205,97,213],"88":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","94":[84,86,124,184,96,134,71,200,201,205,97,213]},"packages/frontend/editor-ui/src/features/shared/contextMenu/composables/useContextMenuItems.ts":{"78":[84,86,124,184,96,134,71,200,201,205,97,213],"84":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","105":"b:AAAAAAAAAACAAFAAAwAAEEAAAAAAAAARACMgAAA=","109":"b:AAAAAAAAAACAAFAAAwAAEEAAAAAAAAARACMgAAA=","119":[86,124],"129":"b:AAAAAAAAAACAAFAAAwAAEEAAAAAAAAARACMgAAA=","131":"b:AAAAAAAAAACAAFAAAwAAEEAAAAAAAAARACMgAAA=","135":"b:AAAAAAAAAACAAFAAAwAAEEAAAAAAAAARACMgAAA=","145":"b:AAAAAAAAAACAAFAAAwAAEEAAAAAAAAARACMgAAA=","147":"b:AAAAAAAAAACAAFAAAwAAEEAAAAAAAAARACMgAAA=","148":"b:AAAAAAAAAACAAFAAAwAAEEAAAAAAAAARACMgAAA=","154":"b:AAAAAAAAAACAAFAAAwAAEEAAAAAAAAARACMgAAA=","156":"b:AAAAAAAAAACAAFAAAwAAEEAAAAAAAAARACMgAAA=","166":[84,86,124,184,188,96,134,71,201,205,97,213],"170":"b:AAAAAAAAAACAAFAAAwAAEEAAAAAAAAARACMgAAA=","185":[84,86,124,184,96,134,71,200,201,205,97,213],"194":[84,86,124,184,188,96,134,71,201,205,97,213],"199":"b:AAAAAAAAAACAAFAAAwAAEEAAAAAAAAARACMgAAA=","206":"b:AAAAAAAAAACAAFAAAwAAEEAAAAAAAAARACMgAAA=","209":[86,124,71],"214":[86,124],"217":[86,124],"239":"b:AAAAAAAAAACAAFAAAwAAEEAAAAAAAAARACMgAAA=","243":[86,124],"288":"b:AAAAAAAAAACAAFAAAwAAEEAAAAAAAAARACMgAAA=","398":"b:AAAAAAAAAACAAFAAAwAAEEAAAAAAAAARACMgAAA=","421":[86,124,71],"429":[86,124,71],"447":[86,124,71],"456":[86,124,71],"481":[86,124],"488":[84,86,124,184,188,96,134,71,201,205,97,213],"496":[84,86,124,184,188,96,134,71,201,205,97,213],"503":[84,86,124,184,188,96,134,71,201,205,97,213]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/completions/js.snippets.ts":{"8":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/features/shared/editors/components/InlineExpressionEditor/InlineExpressionTip.vue":{"28":"b:AEEAAAACABAAfUAIAgAQEAQwCAYAIgBAAMQAAAA=","41":"b:AAAAAAAAABAAeEAAAgAQEAAwAAAAAABAAMQAAAA=","45":[86,124,206,116,75,76,207,77,140,97],"47":"b:AEEAAAACABAAfUAIAgAQEAQwCAYAIgBAAMQAAAA=","68":[86,124,60,206,116,75,76,207,77,97,78,141],"94":"b:AEEAAAACABAAfUAIAAAQEAQgCAYAIgAAAMQAAAA=","99":"b:AEEAAAACABAAfUAIAgAQEAQwCAYAIgBAAMQAAAA=","107":"b:AEEAAAACABAAfUAIAgAQEAQwCAYAIgBAAMQAAAA=","108":[86,124,60,206,116,75,76,207,77,97,78,141],"111":[86,124],"117":"b:AEEAAAACABAAfUAIAgAQEAQwCAYAIgBAAMQAAAA=","121":"b:AEEAAAACABAAfUAIAgAQEAQwCAYAIgBAAMQAAAA=","125":[86,124,116,76,207,77,97],"131":[86,124,116,76,207,77,97]},"packages/frontend/editor-ui/src/features/shared/editors/composables/useRedactionHint.ts":{"11":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","15":"b:AACAACAAABBAfHAAAgAQEAA7AAAAEIRhAMAAAAA=","19":"b:AACAACAAABBAfHAAAgAQEAA7AAAAEIRhAMAAAAA=","21":[86,124]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/constants.ts":{"467":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","471":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/datatype.completions.ts":{"75":"b:AAAAAAAAABAAfEAAAgAQEAAgAAAAAAAAAMQAAAA=","163":[86,124,206,116,77,97],"179":[86,124,206,116,76,207,77,97],"181":[86,124,206,116,76,207,77,97],"187":[86,124,206,116,76,207,77],"188":[86,124,206,116,76,207,77],"205":[86,124,206,116,76,207,77,97],"208":[86,124,206,116,76,207,77,97],"210":[86,124,206,116,76,207,77,97],"211":[86,124,206,116,76,207,77,97],"215":[86,124,76,207],"231":[86,124],"240":[86,124,206,116,76,207,77,97],"261":[86,124,206,116,76,207,77,97],"263":[86,124],"285":[86,124,206,116,76,207,77],"287":[86,124],"292":[86,124,206,116,76,207,77],"315":[86,124,206,116,76,207,77],"318":[86,124],"324":[86,124,206,116,76,207,77],"330":[86,124,206,116,76,207,77],"342":[86,124,206,116,77],"348":[86,124,206,116,77],"353":[86,124,206,116,77],"362":[86,124,206,116,77],"368":[86,124,206,116,76,207,77],"372":[86,124],"380":[86,124,206,116,76,207,77],"381":[86,124,206,116,76,207,77],"382":[86,124,206,116,76,207,77],"392":[86,124,206,116,76,207,77,97],"396":[86,124],"414":[86,124,206,116,76,207,77],"422":[86,124,206,116,77,97],"453":[86,124,206,116,77,97],"457":[86,124],"466":[86,124],"472":[86,124,97],"476":[86,124,206,116,77],"477":[86,124,206,116,77],"527":[86,124,206,116,76,207,77,97],"545":[86,124,206,116,76,207,77,97],"553":[86,124,206,116,76,207,77,97],"561":[86,124,206,116,76,207,77,97],"562":[86,124,206,116,76,207,77,97],"573":[86,124,76,207],"574":[86,124,76,207],"578":[86,124,76,207],"583":[86,124,76,207],"633":[86,124,76,207],"668":[86,124],"677":[86,124],"681":[86,124],"700":[86,124,207],"731":[86,124,207],"737":[86,124],"739":[86,124],"744":[86,124,76],"752":[86,124,76],"763":[86,124,207],"776":[86,124,207],"779":[86,124],"784":[86,124,206,116,77],"793":[86,124],"797":[86,124],"818":[86,124],"820":[86,124],"838":[86,124],"863":[86,124],"866":[86,124],"897":[86,124],"900":[86,124],"982":[86,124],"985":[86,124,97],"1077":[86,124,97],"1078":[86,124,97],"1084":[86,124],"1150":[86,124],"1151":[86,124],"1157":[86,124],"1174":[86,124],"1177":[86,124],"1191":[86,124],"1194":[86,124],"1231":[86,124],"1234":[86,124],"1251":[86,124],"1254":[86,124],"1272":[86,124],"1295":[86,124],"1299":[86,124],"1322":[86,124],"1327":[86,124],"1330":[86,124],"1352":[86,124,76],"1354":[86,124],"1362":[86,124,76],"1363":[86,124,76],"1364":[86,124,76],"1380":[86,124,76],"1385":[86,124,76],"1386":[86,124,76],"1397":[86,124,76],"1402":[86,124],"1454":[86,124],"1537":[86,124],"1560":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/infoBoxRenderer.ts":{"6":[86,124,76,207],"18":[86,124,76,207],"31":[86,124,76,207],"64":[86,124,97],"76":[86,124,76,207,97],"100":[86,124],"117":[86,124,76,207],"166":[86,124,76,207],"170":[86,124,76,207],"177":[86,124,76,207],"189":[86,124,76,207],"217":[86,124,76,207],"238":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","239":[86,124,76,207,97]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/utils.ts":{"27":[86,124,202,74,206,116,75,76,207,77,97],"48":[86,124],"52":[86,124],"60":[86,124],"64":[86,124],"72":[86,124],"83":[86,124,74,206,116,76,207,77,97],"91":[86,124],"94":[86,124],"119":[86,124,206,116,77,97],"122":[86,124,206,116,77,97],"131":"b:AAAAAAAAABAAPEAAAgAQEAAgAAAAAAAAAMQAAAA=","134":[86,124,206,116,77],"143":[86,124,206,116,77],"159":[86,124],"169":[86,124,202,74,206,116,75,76,207,77,97,141],"183":[86,124,97],"207":"b:AAAAAAAAABAAPEAAAgAQEAAgAAAAAAAAAMQAAAA=","232":"b:IACAACAAABBAfHAAAgAQEAA7AAAAEIRBAMQAAAA=","234":"b:AAAAAAAAABAAPEAAAgAQEAAgAAAAAAAAAMQAAAA=","252":[86,124,202,74,206,116,75,76,207,77,97,141],"269":[86,124,206,116,77,97],"271":[86,124,206,116,77,97],"274":"b:QAAAAAAAAABEPEAAAxAQEMAgAAEAABAQAMYCAgA=","292":[86,124],"298":"b:QAAAAAAAAABEPEAAAxAQEMAgAAEAABAQAMYCAgA=","302":"b:QAAAAAAAAABEPEAAAxAQEMAgAAEAAAAQAMYCAgA=","303":"b:QAAAAAAAAABEPEAAAxAQEMAgAAEAAAAQAMYCAgA=","310":"b:AAAAAAAAABAAPEAAAgAQEAAgAAAAAAAAAMQAAAA=","314":"b:AAAAAAAAABAAPEAAAgAQEAAgAAAAAAAAAMQAAAA=","315":"b:AAAAAAAAABAAPEAAAgAQEAAgAAAAAAAAAMQAAAA=","319":"b:AAAAAAAAABAAPEAAAgAQEAAgAAAAAAAAAMQAAAA=","328":"b:AAAAAAAAABAAPEAAAgAQEAAgAAAAAAAAAMQAAAA=","339":[86,124],"353":[86,124,206,116,76,207,77,97],"356":[86,124,206,116,76,207,77,97],"357":[86,124,206,116,76,207,77,97],"358":[86,124,206,116,76,207,77,97],"362":[86,124],"376":[86,124,202,74,206,116,75,76,207,77,97,141],"380":[86,124],"385":[86,124],"406":[86,124],"416":[86,124],"432":[86,124,206,116,76,207,77,97],"434":[86,124,206,116,76,207,77,97],"438":[86,124,206,116,76,207,77],"439":[86,124,206,116,76,207,77],"442":[86,124,206,116,77,97],"453":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","458":[86,124],"464":[86,124,206,116,77],"481":[86,124,206,116,76,207,77,97]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/format.ts":{"10":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","13":[86,124],"14":[86,124],"19":[86,124]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/keymap.ts":{"83":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","100":[86,124,116],"261":"b:AAAAAAAAAAAAfEAAAgAQEAAgAAAAAAAAAMQCAAA="},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/multiCursor.ts":{"4":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","5":[86,124],"23":[86,124]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/resolvableHighlighter.ts":{"56":[86,124],"64":[86,124],"75":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","76":"b:IAAAAAAAABAAfHAAAgAQEAA7AAAAEARAAMQAAAA=","79":"b:IAAAAAAAABAAfHAAAgAQEAA7AAAAEARAAMQAAAA=","105":[86,124,202,116,76,207],"111":[86,124,116,77,140,141],"131":"b:IAAAAAAAABAAfHAAAgAQEAA7AAAAEARAAMQAAAA=","132":"b:IAAAAAAAABAAfHAAAgAQEAA7AAAAEARAAMQAAAA=","145":"b:IAAAAAAAABAAfHAAAgAQEAA7AAAAEARAAMQAAAA=","146":[86,124,178,202,136,116,75,76,207,77]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/tooltips/InfoBoxTooltip.ts":{"27":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","28":"b:IACAACAAAABAXHAAAgAQEAA7AAAAEIVhAMACAAA=","44":[86,124,74,206,76,207,97,141],"55":[86,124,76,207],"74":[86,124,206,76,207,97,141],"96":[86,124,206,75,76,207,140,97,141],"116":[86,124,206,75,76,207,140,97,141],"119":"b:IACAACAAABBAfHAAAgAQEAA7AAAAEIVhAMACAAA=","123":"b:IACAACAAAABAfHAAAgAQEAA7AAAAEIVhAMACAAA=","127":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMACAAA=","142":[86,124,74,206,76,207,97,141],"143":[86,124,206,75,76,207,140,97,141],"166":[86,124,74,206,76,207,97,141],"188":[86,124,76,207],"202":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMACAAA=","256":[86,124,206,76,207,97,141],"262":[86,124,76,207],"274":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMACAAA=","282":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMACAAA=","291":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMACAAA=","315":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","319":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMACAAA=","322":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMACAAA=","352":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMACAAA=","360":[86,124,74,76,207,97],"378":[86,124,74,76,207],"381":[86,124,207],"423":"b:YACAACAAABBEeHAAARAQEMA4AAEAAJBQAMYCAAA=","435":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMACAAA=","436":[86,124],"443":"b:IACAACAAABBAGHAAAAAAEAAbAAAAAIRBAEAAAAA=","449":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMACAAA="},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/typescript/client/facet.ts":{"9":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/features/shared/envFeatureFlag/useEnvFeatureFlag.ts":{"5":"b:/k//8777Adzk/3c7H5B83vz/r///////n///BwA=","8":"b:/k/38777Adzk/3c5F5B83vz/j///////n///BwA="},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/CategoryItem.vue":{"12":"b:oACCAKAiAABkeTEAAxAQAOxpCAPwK5BACMYOAAA=","16":"b:oACCAKAiAABkeTEAAxAQAOxpCAPwK5BACMYOAAA=","20":"b:oACCAKAiAABkeTEAAxAQAOxpCAPwK5BACMYOAAA="},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/NodeItem.vue":{"41":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","56":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","63":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","84":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","100":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","101":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","106":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","111":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","115":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","119":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","125":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","127":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","132":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","133":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","135":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","144":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","148":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","152":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","160":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","172":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","198":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","220":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","233":"b:AACCAAAAAABkIDEAAxAQAOAIAANwI5BACAYKAAA=","236":"b:AACCAAAAAABkIDEAAxAQAOAIAANwI5BACAYKAAA=","246":[39],"251":[39],"266":[66],"273":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA="},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/SubcategoryItem.vue":{"13":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","15":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","16":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA="},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/Modes/NodesMode.vue":{"50":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","75":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","76":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","79":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","83":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","85":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","86":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","90":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","92":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","105":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","108":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","120":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","122":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","201":"b:gACCAAAAAABkaCEAAxAAAORgCAGQIRAACEYOAAA=","245":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","257":[152,70],"265":[152,70],"273":[152,70],"283":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","301":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA="},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/NodeCreator.vue":{"58":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","65":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","73":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","81":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","89":[70],"100":"b:oEiCEKAiAABkfzEIBxAQAOxrCQPwK5BOCN6OAwA=","104":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","108":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","136":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","140":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","141":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","151":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","159":[152,165,77],"162":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","166":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","177":"b:AAgAEAAgAAAgAxAABAAAAAADAQAAAAAAAAiAAwA=","182":[210]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/NodeCreatorShortcutCoachmark.vue":{"14":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","28":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA="},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/Panel/NodesListPanel.vue":{"34":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","46":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","57":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","59":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","61":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","63":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","65":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","67":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","87":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","92":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","94":[39],"98":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","105":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","117":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAAA=","143":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAAA=","153":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAAA=","164":[5,152,164,165,70,134,201,77],"172":"b:gACCAKAAAABkaDEAAxAAAORoCAHwIRBACEYOAAA=","179":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","183":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","191":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","197":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","198":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","225":[165,167],"227":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","239":[152,164,165,134,201]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/Panel/SearchBar.vue":{"16":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","26":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","30":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAAA=","39":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","44":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","52":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA="},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/Renderers/CategorizedItemsRenderer.vue":{"28":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAAA=","38":"b:oACCAKAiAABkeTEAAxAQAOxpCAPwK5BACMYOAAA=","39":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAAA=","41":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAAA=","45":[168],"49":[168],"62":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAAA=","83":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAAA=","97":[152,70],"106":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAAA=","122":"b:oACCAKAiAABkeTEAAxAQAOxpCAPwK5BACMYOAAA=","153":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAAA=","154":[164,209,77,78,141]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/Renderers/ItemsRenderer.vue":{"30":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","45":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","47":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","49":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","53":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","63":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","80":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","122":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","126":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","133":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","134":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAAA=","141":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","154":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","163":[84,166,139],"186":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA="},"packages/frontend/editor-ui/src/features/shared/nodeCreator/composables/useActions.ts":{"58":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","65":"b:gACCAAAAAABkaGEAAxAAEORgCAGQIRAACEYOAAA=","72":"b:gACCAAAAAABkaGEAAxAAEORgCAGQIRAACEYOAAA=","76":"b:gACCAAAAAABkaGEAAxAAEORgCAGQIRAACEYOAAA=","77":"b:gACCAAAAAABkaGEAAxAAEORgCAGQIRAACEYOAAA=","97":"b:gACCAAAAAABkaGEAAxAAEORgCAGQIRAACEYOAAA=","98":"b:gACCAAAAAABkaGEAAxAAEORgCAGQIRAACEYOAAA=","103":"b:gACCAAAAAABkaGEAAxAAEORgCAGQIRAACEYOAAA=","154":"b:gACCAAAAAABkaGEAAxAAEORgCAGQIRAACEYOAAA=","170":"b:gACCAAAAAABkaGEAAxAAEORgCAEQIRAACEYKAAA=","173":"b:gACCAAAAAABkaEEAAxAAEOAAAAEAARAACEYKAAA=","188":"b:gACCAAAAAABkaGEAAxAAEORgCAEQIRAACEYKAAA=","217":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","243":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwKJBOCNcKAQA=","251":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNcKAQA=","253":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNcKAQA=","256":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNcKAQA=","268":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNcKAQA=","278":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNcKAQA=","283":[84,86,124],"287":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNcKAQA=","291":"b:oECCAKAiAABkfXEIBxAQEORpCAPwK5BOCNcKAQA=","306":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNcKAQA=","315":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNcKAQA=","318":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNcKAQA=","325":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNcKAQA=","367":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNcKAQA=","401":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNcKAQA=","405":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNcKAQA=","406":"b:AACAAKAAAAAAYHAAAAAAEAAoAAJQA4BGAAACAAA=","415":"b:gACCAAAAAABkaGEAAxAAEORgCAFQIRAACEYKAAA=","420":"b:gACCAAAAAABkaGEAAxAAEORgCAFQIRAACEYKAAA=","430":"b:gACCAAAAAABkaGEAAxAAEORgCAEQIRAACEYKAAA="},"packages/frontend/editor-ui/src/features/shared/nodeCreator/composables/useActionsGeneration.ts":{"32":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","38":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","46":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","49":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","62":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","68":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","83":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","104":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","114":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","120":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","126":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","133":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","148":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","153":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","157":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","161":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","179":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","184":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","192":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","210":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","213":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","234":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","245":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","264":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","267":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","271":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","273":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","274":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","278":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","291":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","329":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","330":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","348":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","351":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","362":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","392":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","399":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","421":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","422":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","427":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","433":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","444":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","445":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","449":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA="},"packages/frontend/editor-ui/src/features/shared/nodeCreator/composables/useGetNodeCreatorFilter.ts":{"9":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","13":[84,85,86,124,37,190,139,77],"30":[84,85,86,124,37,190,139,77],"49":[84,86,124,37,190,139]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/composables/useKeyboardNavigation.ts":{"14":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","20":[86,152,124,165,70,77],"43":[86,152,124,70],"46":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","51":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","52":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","55":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","64":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","72":[86,152,124,165,70,77],"74":[86,152,124,165,70,77],"76":[86,152,124,165,70,77],"89":[5,86,152,124,164,165,70,134,201,77],"112":[86,152,124,165,70,77],"137":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","141":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","151":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","157":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","161":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","170":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","171":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","180":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","185":"b:gACCAKAAAABkaHEAAxAAEORgCAHwIRAACEYOAAA=","186":"b:gACCAKAAAABkaHEAAxAAEORgCAHwIRAACEYOAAA="},"packages/frontend/editor-ui/src/features/shared/nodeCreator/composables/useNodeCreatorShortcutCoachmark.ts":{"7":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","12":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","16":[86,124],"22":"b:AAgAEAAgAAAgA1AABAAAEAADAQAAAAAAAAiAAwA=","26":[86,124]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/composables/useViewStacks.ts":{"119":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","126":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","136":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","168":[86,124],"171":[86,124],"182":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAAA=","201":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","214":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","218":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","222":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","226":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","230":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAAA=","231":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAAA=","237":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","255":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAAA=","256":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAAA=","258":[86,124],"269":[86,124,165,77],"271":[86,124],"272":[86,124],"284":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","286":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAAA=","290":[84,85,86,23,124,37,183,190,139,77],"291":[84,85,86,23,124,37,183,190,139,77],"302":[84,85,86,124,37,190,139,77],"303":[84,85,86,124,37,190,139],"305":[86,124],"306":[86,124],"317":[84,86,124,37,190,139],"325":[84,86,124,37,190,139],"326":[84,86,124,37,190,139],"329":[84,86,124,37,190,139],"343":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","348":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","360":[84,85,86,23,124,37,190,139,77],"401":[84,86,124,37,190,139],"433":[84,86,124,37,190,139],"448":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAAA=","449":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAAA=","465":[84,85,86,124,37,190,139,77],"484":[84,85,86,124,37,190,139,77],"517":[84,85,86,124,37,190,139,77],"533":[84,86,124,37,190,139],"540":[84,85,86,124,37,190,139,77],"554":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","569":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","583":[84,86,124,37,165,166],"609":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","633":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","634":[84,86,124,37,165,166],"638":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","653":"b:oECCAIAiAABkfXEIBxAQEOxgCAHgIJAOCNYOAAA=","658":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","659":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","665":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","668":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","673":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","674":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","681":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","682":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","684":"b:oECCAKAiAABkfXEIBxAQEOxgCAHgIJAOCNYOAAA=","689":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","700":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","705":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","706":[86,124,77],"713":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","725":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","747":[86,124,165,167],"754":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","756":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","760":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","769":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA="},"packages/frontend/editor-ui/src/features/shared/nodeCreator/nodeCreator.store.ts":{"51":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","53":"b:oAAAAIAAAAAAKEAAAAAAEEAJAAEgAQAAAAYAAQA=","73":[84,85,86,124,37,190,139,77],"74":[84,85,86,124,37,190,139,77],"77":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","81":[86,124],"82":[86,124],"85":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","89":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","93":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","97":[86,124,139,77],"118":[86,124,139,77],"143":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA=","182":"b:AAAAACAAAABAIHAAAAAAEAAoAAHgAABOABAAAAA=","233":[86,124],"237":[86,124],"274":"b:oAAAAIAAAAAACEAAAAAAEEABAAEgAQAAAAYAAQA=","285":[86,124],"296":[86,124],"301":[86,124],"309":[86,124],"334":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","340":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","344":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","351":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","379":"b:gECCAIAiAABkfXEIAxAQEORpCANAIIBGCMYKAAA=","395":"b:gECCAIAiAABkfXEIAxAQEORpCANAIIBGCMYKAAA=","435":[86,124,168],"439":"b:gACCAAAAAABkaGEAAxAAEORgCAGQIRAACEYOAAA=","448":[86,124],"452":[84,86,124,37,165,166],"459":[86,124],"463":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYKAQA=","479":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/P0fwP/9/+P//BwA="},"packages/frontend/editor-ui/src/features/shared/nodeCreator/nodeCreator.utils.ts":{"66":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","70":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","96":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","100":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","103":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","109":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","113":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","125":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","136":"b:oECCAKAiAABkfXEIBxAQEOxoCAHwIZBOCNYOAAA=","137":"b:oECCAKAiAABkfXEIBxAQEOxoCAHwIZBOCNYOAAA=","149":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAAA=","154":"b:oACCAIAiAABgfVEIAxAQEOhBAAHgCAAACMYCAAA=","174":[86,124],"177":[86,124],"186":[86,124],"193":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","206":[86,124],"221":[86,124],"231":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAAA=","250":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAAA=","257":[86,124],"269":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAAA=","285":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAAA=","294":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAAA=","297":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","298":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","304":"b:oECSAKAiAABkfXEIBxAQEOxpCAPwK5BOCNcOAQA=","308":"b:oECSAKAiAABkfXEIBxAQEOxpCAPwK5BOCNcOAQA=","315":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","319":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","333":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","337":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAAA=","340":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAAA=","341":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAAA=","349":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","363":[84,86,124,37,190,139],"368":[84,86,124,37,190,139],"382":[84,86,124,37,190,139],"397":"b:oECCAKAiAABkfXEIBxAQEOxoCAHgIJBOCNYOAAA=","402":"b:oECCAKAiAABkfXEIBxAQEOxoCAHgIJBOCNYOAAA=","406":"b:oECCAKAiAABkfXEIBxAQEOxoCAHgIJBOCNYOAAA=","407":"b:oECCAKAiAABkfXEIBxAQEOxoCAHgIJBOCNYOAAA=","408":"b:oECCAKAiAABkfXEIBxAQEOxoCAHgIJBOCNYOAAA=","417":"b:oECCAKAiAABkfXEIBxAQEOxoCAHgIJBOCNYOAAA=","421":"b:oECCAKAiAABkfXEIBxAQEOxoCAHgIJBOCNYOAAA=","432":"b:oECCAKAiAABkfXEIBxAQEOxoCAHgIJBOCNYOAAA=","433":"b:oECCAKAiAABkfXEIBxAQEOxoCAHgIJBOCNYOAAA=","449":"b:oECCAKAiAABkfXEIBxAQEOxoCAHgIJBOCNYOAAA=","451":"b:oECCAIAiAABkfXEIBxAQEOxoCAHgIJAOCNYOAAA=","465":"b:oECCAKAiAABkfXEIBxAQEOxoCAHgIJBOCNYOAAA=","473":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","481":"b:+E/CkKzjAQTk/3cIH5BQ3Ox/PUfwP///2P//BwA=","484":"b:+EeSkKzjARDk/3cIH5BQ3Px/OUfwP/9/+P6/BwA=","490":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","507":[84,85,86,124,139],"531":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","577":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","579":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","592":[86,124,190],"598":[86,124,190],"603":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","628":[86,124,190],"629":[86,124,190],"633":"b:oACCAIAiAABkeXEABxAQEOxpCAPwK5BOCNYOAAA=","638":[86,124,39],"661":[86,124],"687":[86,124,167],"705":"b:oECCAIAiAABkfXEIBxAQEOxgCAHgIJAOCNYOAAA=","726":"b:oECCAIAiAABkfXEIBxAQEOxgCAHgIJAOCNYOAAA=","728":"b:oECCAIAiAABkfXEIBxAQEOxgCAHgIJAOCNYOAAA=","729":"b:oECCAIAiAABkfXEIBxAQEOxgCAHgIJAOCNYOAAA=","735":[86,124],"753":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","762":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","768":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","775":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","783":[86,124,166],"784":[86,124,166]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/views/NodeCreation.vue":{"51":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","80":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","87":"b:oECCAKAiAABkfTEIBxAQAOxoCAPwKpBGCMYOAAA=","94":[200],"116":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYOAQA=","123":"b:oECCAKAiAABkfTEIBxAQAOxpCAPwK5BOCNYKAQA=","133":[188,199],"155":[5,8,131],"194":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","196":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","200":"b:8E/CkKjjAQDk3zcIH5BQzOx/DUfwP/9/mP//BwA=","216":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","231":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","245":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","265":"b:EEbCAKDjAQDk/zcAF5BQDOR/CEfwP/9/mP//BwA=","281":[5,6,7,8,144,146,11,131],"290":[5,6,7,8,144,146,11,131]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/views/viewsData.ts":{"123":[84,85,86,124,37,190,139,77],"140":"b:oECCAIAiAABkfXEIBxAQEOxgCAHgIJAOCNYOAAA=","157":"b:oECCAIAiAABkfXEIBxAQEOxgCAHgIJAOCNYOAAA=","159":"b:oECCAIAiAABkfXEIBxAQEOxgCAHgIJAOCNYOAAA=","163":"b:oECCAIAiAABkfXEIBxAQEOxgCAHgIJAOCNYOAAA=","166":"b:oECCAIAiAABkfXEIBxAQEOxgCAHgIJAOCNYOAAA=","192":"b:oECCAIAiAABkfXEIBxAQEOxgCAHgIJAOCNYOAAA=","202":"b:oECCAIAiAABkfXEIBxAQEOxgCAHgIJAOCNYOAAA=","207":"b:oECCAIAiAABkfXEIBxAQEOxgCAHgIJAOCNYOAAA=","247":[84,85,86,124,37,190,139,77],"250":[84,85,86,124,37,190,139,77],"260":[84,85,86,124,37,190,139,77],"386":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","398":"b:oECCAKAiAABkfXEIBxAQEOxpCAPwK5BOCNYOAQA=","525":"b:oECCAIAiAABkfXEIBxAQEOxgCAHgIJAOCNYOAAA=","690":[86,124],"695":[86,124],"697":[86,124],"721":"b:oECCAIAiAABkfXEIBxAQEOxgCAHgIJAOCNYOAAA="},"packages/frontend/editor-ui/src/features/shared/promotions/usePromotionsEnabled.ts":{"9":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA=","13":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA="},"packages/frontend/editor-ui/src/features/shared/tags/tags.api.ts":{"8":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","10":"b:AAAAAAAAAAAAIEIABgAAEAAAAAAABAAYAABEBQA=","13":[86,124,188,98,214,218],"19":[86,124],"26":[86,124,214]},"packages/frontend/editor-ui/src/features/shared/tags/tags.store.ts":{"34":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","39":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","51":[86,124,214,81],"52":[86,124,214,81],"55":[86,124,214,81],"57":[86,124],"61":"b:AAAAAAAAAAAAIEIABgAAEAAAAAAABAAYAABEBQA=","62":[86,124,214,218,81],"70":"b:EAYAkAzhAACEo1YAHYBQ3GwfMkAAEnYR2Dj3BwA=","71":[86,124,188,98,214,218],"92":[86,124,214],"97":"b:AAAAAAAAAAAAIEIABgAAEAAAAAAABAAYAABEBQA=","119":[86,124,188,98,214,218],"131":[86,124],"142":[86,124],"152":[86,124,214]},"packages/frontend/editor-ui/src/features/workflow-reviews/composables/useWorkflowReviewDialogPreferences.ts":{"10":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA="},"packages/frontend/editor-ui/src/features/workflow-reviews/composables/useWorkflowReviewStatusSync.ts":{"14":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","20":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","30":"b:8EeCkIzrAADk+zUIH5BQzOx/C0UAPndlmP7/AwA=","42":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","43":"b:4EmCAIAqAABg+TcIFxAAAORrCQUALAFkAMZOAQA=","50":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","51":[43],"57":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","60":[43],"63":[28,127,43,45,203,98,79]},"packages/frontend/editor-ui/src/features/workflow-reviews/composables/useWorkflowReviewsFeature.ts":{"6":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","9":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","15":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA="},"packages/frontend/editor-ui/src/features/workflow-reviews/reviewRequired.store.ts":{"7":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","15":[43],"17":[43]},"packages/frontend/editor-ui/src/features/workflow-reviews/reviewStatus.store.ts":{"17":"b:8E/CkKzrAQDk/zcIH5BQzOx/D0fwP/9/mP//BwA=","24":[43],"32":[43],"38":[43],"43":[43],"46":[43],"82":[43]},"packages/frontend/editor-ui/src/features/workflows/canvas/canvas.types.ts":{"32":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","59":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","174":[86,124,31,71],"178":"b:4EeCgKiiAADk/XUIDxBQFOx/KAfwP79/iPe/BwA=","228":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA="},"packages/frontend/editor-ui/src/features/workflows/canvas/canvas.utils.ts":{"37":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","51":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/2P6/BwA=","60":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/yP6/BwA=","61":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/2P6/BwA=","63":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/yP6/BwA=","64":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/2P6/BwA=","80":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","97":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","124":[86,124],"132":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","137":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","139":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","145":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","147":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","148":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","205":[86,124,201,213],"237":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUfwP/9/6P+/BwA=","257":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","272":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","283":[86,124,186,187,70,71,201],"300":"b:4EGCAKAiAADkfXEIBxAQEORqCQdQJ5l+CNcuBAA=","334":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","343":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","351":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","368":[86,124,187,71,200,212],"386":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","403":"b:8EeCkKjjAQDk/3cIH5BQnOx/CUfwP/9/uP6/BwA=","413":"b:8EeCkKjjAQDk/3cIH5BQnOx/CUfwP/9/uP6/BwA=","417":"b:8EeCkKjjAQDk/3cIH5BQnOx/CUfwP/9/uP6/BwA=","431":"b:YAGCgAAAAADgqVcAHwBAEEAKAQUQBYk8QBPnBwA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/Canvas.vue":{"253":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","255":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","256":[86,124,197],"293":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","294":[86,124],"307":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","308":"b:4EeCAKiiAADk/XEIDxBQFOx/KAfwP79/iPe/BwA=","310":[86,124,70,96,134,201,99,82],"311":[86,124,70,96,134,201,99],"319":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","336":"b:AAAAAAAAAADAgEQAGQAAEEAAAAAAAAAAAAMiAAA=","342":"b:IAEAAAAAAADA/EQAGwAAEEAgAQAAAAAAAMciAAA=","362":[86,124],"380":"b:YAGCgAAAAADgqVcAHwBAEEAKAQUQBYk8QBPnBwA=","382":[86,124,70],"390":[86,124,70],"398":[86,124],"400":[86,124],"409":[86,124],"411":[86,124],"420":[86,124,213],"422":[86,124,213],"425":[86,124,70],"427":[86,124,70],"430":[86,124],"442":[86,124,71],"449":[86,124,71],"465":[86,124,71],"472":[86,124,31,71],"478":[86,124],"479":[86,124],"485":[86,124,31,71],"497":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","507":[86,124,71],"510":[86,124],"524":[86,124],"529":[86,124,71],"534":[86,124],"541":"b:YAEAgAAAAADgoUcAHwBAEEACAQQABAk4QAPmBwA=","543":[86,124],"545":[86,124,70,99,82],"546":[86,124,70,99,82],"548":[86,124],"551":[86,124],"552":[86,124],"553":[86,124,134],"554":[86,124],"561":[86,124],"562":[86,124],"563":[86,124],"569":[86,124],"572":[86,124],"576":[86,124],"580":[86,124],"586":[86,124],"588":[86,124,134],"589":[86,124,134,201,72,80,215,216,217],"590":[86,124],"591":[86,124,134],"592":[86,124],"594":[86,124],"595":[86,124],"600":[86,124,200],"601":[86,124,200],"603":[86,124],"605":[86,124],"606":[86,124],"608":[86,124,100],"612":[86,124],"613":[86,124],"615":[86,124],"617":[86,124],"618":[86,124],"620":[86,124],"621":[86,124],"625":[86,124],"626":[86,124],"629":[86,124],"635":[86,124],"639":[86,124],"640":[86,124],"658":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","664":"b:AAAAAAAAAABAAUUACQAAEEAAAAAAAAAAAAOgAwA=","675":[86,124],"678":[86,124],"680":[86,124],"685":[86,124],"695":[86,124],"704":"b:8E8AAKigAADkuXUACwBQFMQ/LQXgMz9/gH+3BwA=","705":"b:8E8AAKigAADkuXEACwBQFMQ/LQXgMz9/gH+3BwA=","714":"b:cEcAACigAADkuXUACwBQFMQ/KAXgMj9/gH63BwA=","721":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","722":"b:4EeCAKCiAADkfXEIDxAQEOR/CAdALq9/iOe/AwA=","730":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","731":"b:4EeCAKAiAADk/XUIDxBQFOx/CAfgPqd/COa/AwA=","745":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","752":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","753":"b:4EeCAKiiAADk/XEIDxBQFOx/KAfwP79/iPe/BwA=","755":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","758":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","759":[5,6,7,8,144,86,146,11,124,131],"767":"b:AAAAACAAAABAAHAAAAAAEAAgAAHgAABCABAAAAA=","771":[86,124],"775":[86,124],"779":[86,124,184,70,96,71,201,99],"786":[86,124],"790":[144,86,124,185,197],"792":[144,86,124,185],"797":[144,86,124,185],"800":[144,86,124,185],"812":[86,124,71],"816":[86,124],"827":[86,124,184,70,96,71,201,99],"828":[86,124,71],"829":[86,124,71],"830":[86,124,184,70,96,71,201,99],"831":[86,124,184,70,96,71,201,99],"832":[86,124,71],"845":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","846":[86,124,71],"847":"b:4EeCAKiiAADk/XUIDxBQFOx/KAfwP79/iPe/BwA=","849":[86,124,71],"855":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","866":[86,124,184,70,96,71,201,99],"870":[86,124,184,70,96,71,201,99],"874":[86,124,184,70,96,71,201,99],"879":[86,124],"883":[86,124],"887":[86,124,71],"911":[86,124,71],"912":[86,124,71],"927":[86,124,71],"928":[86,124,71],"933":[86,124,71],"949":[86,124],"961":[86,124],"974":[86,124],"992":[86,124],"1016":[86,124],"1033":[86,124],"1037":[86,124,71],"1061":[86,124],"1067":[86,124,31,71],"1072":[86,124,31,71],"1077":[86,124],"1086":[86,124],"1101":[86,124],"1103":[86,124],"1111":[86,124],"1114":[86,124],"1115":[86,124],"1120":[86,124],"1128":[86,124],"1140":[86,124],"1154":[86,124],"1167":[86,124,70,96,201],"1175":[86,124,70,96,71,201],"1178":[86,124],"1179":[86,124],"1190":"b:YEUAAAigAADEuWUACwBQFMQfKAQAMjcxgHa3AwA=","1229":[86,124],"1234":"b:EAYAAAAgAADAAEAAAAAAEEACAAEAIAABgAEmAAA=","1244":"b:YEUAAAigAAAEOWAAAgBQFMQfKAQAEjcxAHQ3AgA=","1249":[86,124],"1253":"b:4EOCAKAiAADkfXEIDxAQEOxrCAfwL5l/CPcuBQA=","1257":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","1258":[86,124],"1262":[86,124,70,96,134,201,99,82],"1266":"b:4EeCAKiiAADk/XUIDxBQFOx/KAfwP79/iPe/BwA=","1270":"b:4EOCAKAiAADkfXEIDxAQEOxrCAfwL5l/CPcuBQA=","1275":"b:4EOCAKAiAADkfXEIDxAQEOxrCAfwL5l/CPcuBQA=","1300":[86,124,69,70,137],"1304":[86,124,179,180,70,137],"1308":[86,124],"1312":[84,86,124],"1316":[84,86,124],"1319":[86,153,124,173],"1323":[86,153,124,173],"1326":[86,124],"1339":[86,124],"1343":[86,124],"1348":[86,124],"1364":"b:AAAAACAAAADAAHAAAAAAEAAgAAHgAABCABAgAAA=","1377":[86,124,71,213],"1394":"b:AAAAACAAAADAAHAAAAAAEAAgAAHgAABCABAgAAA=","1411":"b:AAAAACAAAADAAHAAAAAAEAAgAAHgAABCABAgAAA=","1419":[86,124,71,213],"1427":"b:AAAAACAAAADAAHAAAAAAEAAgAAHgAABCABAgAAA=","1438":[86,124,70,71,201],"1442":[86,124,186,187,70],"1455":"b:AAAAAAAgAADAAEAAAAAAkEACAAAAAAAcAAIAAAA=","1461":[86,124,186,187,188,70,71,201],"1479":"b:AAAAAAAgAADAAEAAAAAAkEACAAAAAAAcAAIAAAA=","1484":[86,124,45,186,187,188,70,134,71,201,137],"1491":"b:8E0AEKygAADkuXUACwBQFMQ/LQXgMz97gHe3BwA=","1495":"b:8E0AEKigAADkuXUACwBQFMQ/KQXgMzd7gHe3BwA=","1503":[4,10,86,124,35,181,70,136,205,206,75],"1511":"b:YAEAgAAAAADgoUcAHwBAEEACAQQABAk4QAPmBwA=","1512":[86,124,70,134,201,72,99,80,215,216,217,82],"1519":"b:YAEAgAAAAADgoUcAHwBAEEACAQQABAk4QAPmBwA=","1520":[86,124,70,134,213],"1527":[86,124],"1535":[86,124],"1556":"b:cEcAACigAADEuXUACwBQFMQ/KAXgMjdzgHe3AwA=","1566":"b:EAYAAAAgAADAAEAAAAAAEEACAAEAIAABgAEmAAA=","1570":[86,124],"1574":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","1582":[86,124,134],"1586":[86,124,134,203],"1590":[86,124,134],"1594":[86,124,134],"1598":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","1607":[86,124],"1611":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","1617":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","1618":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","1626":[86,124],"1627":[86,124],"1644":[84,86,124,184,96,134,71,200,201,205,97,213],"1646":[86,124,96,134,200,213],"1660":[86,124],"1664":[84,86,124,184,96,134,71,200,201,205,97,213],"1679":[86,124],"1709":[84,86,124,184,96,134,71,200,201,205,97,213],"1810":[144,86,124,185,197],"1812":[86,124],"1845":[86,124,70],"1849":[86,124,70],"1859":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","1863":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","1868":[86,124],"1876":[86,124],"1885":[86,124],"1886":[86,124],"1891":[86,124],"1895":[86,124],"1903":[86,124],"1922":"b:AAAAgACIAACEIEIADwAAFEQAAAAAAgAAAFAgAAA=","1929":[86,148,149,124,198],"1937":[86,148,149,124,198],"1945":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","1956":"b:AAAAEAAgAAAgg1AAFAAAkAADAAAAAAAAAAiAAwA=","1967":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","1976":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","1992":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","2002":"b:EAYAAAAgAADAAEAAAAAAEEACAAEAIAABgAEmAAA=","2006":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","2009":[86,124],"2016":[86,124],"2043":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","2087":[86,124,31,71],"2106":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","2107":"b:8E/CkKzjAQDk33cIH5BQ3Ox/PUfwP/9/2P//BwA=","2133":[86,124],"2135":[86,124],"2142":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","2143":"b:8EeCkKzjAQDkX3UIH5BQ3Ox/OUdQN/9/yP6/BwA=","2152":[86,124,45,186,187,188,70,134,71,201,137],"2157":"b:AAAAACAAAADAAHAAAAAAEAAgAAHgAABCABAgAAA=","2159":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","2163":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","2175":[86,124],"2176":[86,124],"2180":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","2208":[86,124,185]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/WorkflowCanvas.vue":{"83":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","84":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","88":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","94":"b:AAAAEAAgAAAggxAAFAAAgAADAAAAAAAAAAiAAwA=","98":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","103":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","106":"b:8E/CkKzjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","107":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","108":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","109":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","113":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","114":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","115":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","119":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","120":[198],"128":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","129":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","130":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","133":"b:8EeCkKzjAQDk/zcIH5BQzOx/OUfwP/9/2P6/BwA=","151":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","166":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","174":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","181":[31,71],"182":[31,71],"183":[31,71],"185":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","191":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","194":[31,71],"195":[31,71],"196":[31,71],"197":[31,71],"203":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","213":[71],"218":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA=","234":[134,201,97,99,218],"242":[134,201,97,99,218],"248":[134,201,97,99],"299":"b:8E/CkKzjAQDk/zcIH5BQzOx/PUfwP/9/2P//BwA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/background/CanvasBackground.vue":{"13":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","18":"b:AAgAEAyAAAAAg0AAGAAA0AADMQAAAAAAQAiAAwA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/buttons/CanvasControlButtons.vue":{"10":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","35":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","37":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","39":[86,124,134,203],"43":[86,124,134],"47":"b:EAYAAAAAAADAAFAAAQAAEEATAAAAAAAxgCo2BAA=","51":[86,124,185],"55":[86,124],"57":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","61":"b:8E/CkKzjAQDk33cIH5BQ3Ox/PUfwP/9/+P//BwA=","62":"b:8E/CkKzjAQDk33cIH5BQ3Ox/PUfwP/9/+P//BwA=","65":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","78":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","91":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","109":[86,124],"121":[86,124],"128":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","144":[86,124],"157":[86,124]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/buttons/CanvasRunWorkflowButton.vue":{"49":"b:8EWCkIjjAQDk/1cIH5BQ3Ox/CUfwPz8+mP6/BwA=","53":"b:8EWCkIjjAQDk/1cIH5BQ3Ox/CUfwPz8+mP6/BwA=","54":"b:8EWCkIjjAQDk/1cIH5BQ3Ox/CUfwPz8+mP6/BwA=","58":"b:8EWCkIjjAQDk/1cIH5BQ3Ox/CUfwPz8+mP6/BwA=","71":[144,86,124,172,201,136,205,209,97],"73":[144,86,124,172,201,136,205,209,97],"74":[144,86,124,172,201,136,205,209,97],"80":[144,86,124,172,201,136,205,209,97],"86":"b:8EWCkIjjAQDk/1cIH5BQ3Ox/CUfwPz8+mP6/BwA=","91":"b:8EWCkIjjAQDk/1cIH5BQ3Ox/CUfwPz8+mP6/BwA=","93":"b:8EWCkIjjAQDk/1cIH5BQ3Ox/CUfwPz8+mP6/BwA=","96":"b:8EWCkIjjAQDk/1cIH5BQ3Ox/CUfwPz8+mP6/BwA=","101":"b:8EWCkIjjAQDk/1cIH5BQ3Ox/CUfwPz8+mP6/BwA=","108":"b:8EWCkIjjAQDk/1cIH5BQ3Ox/CUfwPz8+mP6/BwA=","109":"b:8EWCkIjjAQDk/1cIH5BQ3Ox/CUfwPz8+mP6/BwA=","114":"b:8EWCkIjjAQDk/1cIH5BQ3Ox/CUfwPz8+mP6/BwA=","116":"b:8EWCkIjjAQDk/1cIH5BQ3Ox/CUfwPz8+mP6/BwA=","118":[86,124,28,126,31,35,127],"119":"b:8EWCkIjjAQDk/1cIH5BQ3Ox/CUfwPz8+mP6/BwA=","125":"b:AACAAAAAAQAAQEQAEAAAEAAAAQEQAAAAAAAKBAA=","131":"b:8EWCkIjjAQDk/1cIH5BQ3Ox/CUfwPz8+mP6/BwA=","140":[86,124],"141":[86,124],"150":[86,124],"153":"b:8EWCkIjjAQDk/1cIH5BQ3Ox/CUfwPz8+mP6/BwA=","172":"b:8EWCkIjjAQDk/1cIH5BQ3Ox/CUfwPz8+mP6/BwA=","183":"b:AEEAAAjBAAAAA1AIA5AAmAQXCEQANhEkACC3AwA=","184":"b:AEEAAAjBAAAAA0AIA5AAmAQXCEQANhEkACC3AwA=","185":"b:AEEAAAjBAAAAA1AIA5AAmAQXCEQANhEkACC3AwA=","186":"b:8EWCkIjjAQDk/1cIH5BQ3Ox/CUfwPz8+mP6/BwA=","188":"b:8EWCkIjjAQDk/1cIH5BQ3Ox/CUfwPz8+mP6/BwA=","211":[144,86,124,172,201,136,205,209,97],"222":[86,124]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/buttons/CanvasStopCurrentExecutionButton.vue":{"6":"b:cEcAEAjDAABAGzAIE5AQiIQ3CEQAPjMlQOC3AwA=","13":"b:cEcAEAjDAABAGzAIE5AQiIQ3CEQAPjMlQOC3AwA=","18":"b:cEcAEAjDAABAGzAIE5AQiIQ3CEQAPjMlQOC3AwA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/edges/CanvasArrowHeadMarker.vue":{"6":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/edges/CanvasEdge.vue":{"16":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","37":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","46":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","47":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","53":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/KUdQN/9/6P6/BwA=","61":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","63":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","65":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","67":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","72":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","78":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","83":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","90":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","96":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","98":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","100":[86,124,186,187,70,71,201],"110":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","120":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","121":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","125":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","136":[86,124,186,187,70],"140":[86,124,70,71,201],"144":[86,124,45,186,187,188,70,134,71,201,137],"148":[86,124,45,186,187,188,70,134],"150":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","164":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/edges/utils/getEdgeRenderData.ts":{"11":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUfwN/9/6P6/BwA=","13":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUfwN/9/6P6/BwA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/handles/CanvasHandleRenderer.vue":{"16":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","46":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","50":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","56":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","60":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","64":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","70":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","80":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","88":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","98":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","100":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","124":"b:AAAAACAAAABAAHAAAAAAEAAgAAHgAABCABAAAAA=","153":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","166":"b:8EeCkKzjAQDk33cIH5BQ3Ox/OUfwP/9/+P6/BwA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/handles/render-types/CanvasHandleMainInput.vue":{"14":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","22":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","26":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","27":"b:8EeCkKzjAQDkX3UIH5BQ3Ox/OUdQN/9/6P6/BwA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/handles/render-types/CanvasHandleMainOutput.vue":{"22":"b:8EeCkKjjAQDk/3cIH5BQnOx/CUfwP/9/uP6/BwA=","27":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","29":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","38":"b:8EeCkKjjAQDk/3cIH5BQ3Ox/CUfwP/9/uP6/BwA=","40":"b:cEQAEAjDAAAAC3AIA5AQ2IQ3AAQANjMkAGC3AwA=","49":"b:8EeCkKjjAQDk/3cIH5BQ3Ox/CUfwP/9/uP6/BwA=","51":"b:8EeCkKjjAQDk/3cIH5BQ3Ox/CUfwP/9/uP6/BwA=","53":"b:8EeCkKjjAQDk/3cIH5BQ3Ox/CUfwP/9/uP6/BwA=","58":"b:AAAAgACAAACAAEIAEwAQGAATIQNAMgkMACoHBAA=","63":"b:cEQAEAjDAAAAC3AIA5AQ2IQ3AAQANjMkAGC3AwA=","70":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","75":"b:AAAAAAAAAABAAEAAAAAAEEAgAAHgAAACABIgAAA=","79":"b:AAAAAAAAAABAAEAAAAAAEEAgAAHAAAACABIgAAA=","83":[86,152,124,165,166,167,185,70,204,141],"85":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","93":"b:8EeCkKzjAQDk33cIH5BQ3Ox/OUfwP/9/+P6/BwA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/handles/render-types/parts/CanvasHandleDot.vue":{"4":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","13":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","14":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/handles/render-types/parts/CanvasHandlePlus.vue":{"6":"b:8EeCkKjjAQDk/3cIH5BQ3Ox/CUfwP/9/uP6/BwA=","34":"b:8EeCkKjjAQDk/3cIH5BQ3Ox/CUfwP/9/uP6/BwA=","41":"b:8EeCkKjjAQDk/3cIH5BQ3Ox/CUfwP/9/uP6/BwA=","57":"b:8EeCkKjjAQDk/3cIH5BQ3Ox/CUfwP/9/uP6/BwA=","64":"b:8EeCkKjjAQDk/3cIH5BQ3Ox/CUfwP/9/uP6/BwA=","89":"b:8EeCkKjjAQDk/3cIH5BQ3Ox/CUfwP/9/uP6/BwA=","102":"b:AAAAACAAAABAAHAAAAAAEAAgAAHgAABCABAAAAA=","104":"b:8EeCkKjjAQDk/3cIH5BQ3Ox/CUfwP/9/uP6/BwA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/CanvasNode.vue":{"50":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","91":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","92":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","93":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","107":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","109":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","117":[86,124],"120":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","122":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","138":"b:YEUAAAigAAAEOWAAAgBQFMQfKAQAEjcxAHU3AgA=","148":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","152":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","156":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","163":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","167":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","174":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","178":"b:8E/CkKzjAQDk33cIH5BQ3Ox/PUfwP/9/+P//BwA=","253":"b:AAAAACAAAABAAHAAAAAAEAAgAAHgAABCABAAAAA=","257":[86,124,179,180,70,137],"261":[4,10,86,124,35,181,70,136,205,206,75],"265":[86,124,69,70,137],"269":"b:YEUAAAigAAAEOWAAAgBQFIQfKAQAEjcxAHQ3AgA=","273":[86,124],"277":[86,124,134],"281":[84,86,124,184,96,134,71,200,201,205,97,213],"285":[86,124],"289":[86,124],"293":[86,124],"297":[86,124],"301":[86,124],"305":[86,124],"309":[86,124],"312":[86,124],"334":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","339":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","348":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","349":"b:4EeCAKiiAADk/XUIDxBQFOx/KAfwP79/iPe/BwA=","355":[84,86,124],"361":[86,153,124,173],"367":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","372":"b:4EmCEKAiAADg/3EIFxAQkORrGQfwL5l+CM+uBwA=","376":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","386":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","403":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/CanvasNodeRenderer.vue":{"11":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","13":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","37":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/CanvasNodeToolbar.vue":{"19":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/2P+/BwA=","58":[86,124],"59":[86,124],"63":"b:EASAACAAAAAAIHAAAAAAEAAKAAAAAKBAAAAAAAA=","66":"b:EASAACAAAAAAIHAAAAAAEAAKAAAAAKBAAAAAAAA=","68":"b:8EeCkKjjAQDk/3cIH5BQ3Ox/CUfwP/9/mP6/BwA=","72":"b:8EeCkKjjAQDk/3cIH5BQ3Ox/CUfwP/9/2P6/BwA=","83":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/2P+/BwA=","90":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/2P+/BwA=","108":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/2P+/BwA=","115":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/2P+/BwA=","117":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/2P+/BwA=","119":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/2P+/BwA=","126":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/2P+/BwA=","137":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/2P+/BwA=","141":[4,10,86,124,35,181,70,136,205,206,75],"145":[86,124,69,70,137],"149":[86,124,179,180,70,137],"153":[86,124],"159":[86,124,134],"163":"b:EAQAAAAAAADgCEAAAAAAEEADAAAAADgAAGAAAAA=","167":"b:EAQAAAAAAACgCEAAAAAAEEADAAAAACAAAGAAAAA=","171":[86,124],"177":[86,124],"183":[86,124],"186":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/2P+/BwA=","196":"b:EAQAAAAAAABgCEAAAAAAEEADAAAAADgAAGAAAAA=","197":[86,124],"201":"b:8EeCkKjjAQDk/3cIH5BQ3Ox/CUfwP/9/2P6/BwA=","212":"b:8EeCkKjjAQDk/3cIH5BQ3Ox/CUfwP/9/mP6/BwA=","225":"b:8EeCkKjjAQDk/3cIH5BQ3Ox/CUfwP/9/mP+/BwA=","249":[86,124],"263":[86,124],"275":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/2P+/BwA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/CanvasNodeAddNodes.vue":{"18":"b:4EHCAKAiAABg/XMIBxAQGORrCAfwL4l+CMdOBQA=","26":"b:4EHCAKAiAABg/XMIBxAQGORrCAfwL4l+CMdOBQA=","30":"b:4EHCAKAiAABg/XMIBxAQGORrCAfwL4l+CMdOBQA=","35":"b:4EGCAKAiAABgfXEIBxAQEORrCAfwL4l+CMcOBQA=","40":[86,124],"44":[86,124],"48":"b:oAAAAIAAAAAACEAAAAAAEEABAAEgAQAAAAYAAAA=","55":[86,124],"63":"b:4EHCAKAiAABg/XMIBxAQGORrCAfwL4l+CMdOBQA=","71":[86,124],"83":[86,124]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/CanvasNodeDefault.vue":{"23":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","56":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","57":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","58":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","61":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","66":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","71":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","80":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","81":[86,124],"83":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","110":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","116":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","129":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","136":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","149":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","158":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","183":"b:EAYAkAzhAQCEo1YAHYBQ3GwfMEAAEnYB8Di3AwA=","189":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUdQP/9/+P6/BwA=","191":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUdQP/9/+P6/BwA=","196":[84,86,124,184,96,134,71,201,205,97,213],"200":"b:YEUAAAigAAAEOWAAAgBQFIQfKAQAEjcxAHQ3AgA=","207":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/parts/CanvasNodeSettingsIcons.vue":{"12":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","13":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","19":[86,124],"28":[86,124,209],"36":[86,124],"45":[86,124],"53":[86,124],"62":[86,124],"72":[86,124],"81":[86,124]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/parts/CanvasNodeStatusIcons.vue":{"25":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","46":"b:4EGCAKQiAQBgZXUIEgBQFGRbCQNQIaVKCASKBAA=","53":[86,124],"60":[86,124],"65":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","68":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","69":"b:8EeCkKzjAADk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","74":"b:8EeCkKzjAADk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","79":"b:8EeCkKzjAADk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","82":"b:4EGCAKQiAQBgZXUIEgBQFGRbCQNQIbVKCASKBQA=","83":[86,124],"84":"b:8EeCkKzjAADk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","88":"b:8EeCEKzjAQBkf3UIE5BQ3OR/KQdQP7dvyOa/BwA=","94":[86,124],"102":[86,124],"103":[86,124],"111":[86,124],"115":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","124":[86,124],"125":[86,124,66],"134":[86,124],"135":[86,124],"147":[86,124],"149":"b:YAAAAAAAAAAAAXAAAAAAEAADAAAAABAAAACCAQA=","159":[86,124],"163":"b:4EGCAKQiAQBgZXUIEgBQFGRbCQNQIaVKCASKBAA=","182":[86,124],"185":[86,124,173,177,186,135,205,97,141,213]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/parts/CanvasNodeStatusMark.vue":{"5":"b:cEcAEAjDAABAG3AIA5AQ2IQ3CAQAPjMlQOC3AwA=","10":"b:cEcAEAjDAABAG3AIA5AQ2IQ3CAQAPjMlQOC3AwA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/parts/CanvasNodeTrigger.vue":{"34":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","35":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","46":"b:8EeCkKjjAQDk/3cIH5BQ3Ox/CUfwP/9/uP6/BwA=","53":[86,124],"54":[86,124],"58":[86,124],"59":[86,124],"63":"b:AAaAACAAAAAAAHAAAAAAEAgKAAAAAMBBAAAAAAA=","68":[86,124],"69":"b:AAaAACAAAAAAAHAAAAAAEAgKAAAAAMBBAAAAAAA=","72":"b:8EeCkKjjAQDk/3cIH5BQ3Ox/CUfwP/9/uP6/BwA=","73":"b:8EeCkKjjAQDk/3cIH5BQ3Ox/CUfwP/9/uP6/BwA=","75":[86,124],"83":[86,124],"91":[86,124,172,136],"94":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","99":[86,124,172,136],"121":"b:AAaAACAAAAAAAHAAAAAAEAgKAAAAAMBBAAAAAAA=","137":"b:8EWCkIjjAQDk/1cIH5BQ3Ox/CUfwPz8+uP6/BwA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/selection/CanvasSelectionToolbar.vue":{"16":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","39":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","40":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","50":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","52":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","62":"b:4EuCEIyiAADg/3UIHxAQ0OxbOQfwLA04yO6vBwA=","66":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","72":[86,124],"79":[86,124,71,213],"91":[86,124,187,71,213],"99":[86,124,71],"104":[86,124],"106":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","118":[86,124,71],"125":[86,124,187,71,213],"141":[86,124,71,213],"153":[86,124],"160":[86,124]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvas.ts":{"4":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA="},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasAgentNodeGeometry.ts":{"16":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","19":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","57":"b:AAAAEAAgAAAgg1AAFAAAkAADAAAAAAAAAAiAAwA="},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasGroupIdStorage.ts":{"10":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","11":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","22":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","26":[86,124,31,71]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasLayout.ts":{"116":[86,124],"120":[86,124],"130":[86,124],"134":[86,124],"138":[86,124],"151":[86,124],"154":[86,124],"165":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","172":[144,86,124,185,197],"175":[86,124],"181":[144,86,124,185,197],"186":[144,86,124,185,197],"192":[86,124],"194":[86,124],"198":[86,124],"200":[144,86,124,185,197],"203":[144,86,124,185,197],"209":[144,86,124,185,197],"219":[86,124],"223":[144,86,124,185,197],"224":[86,124],"231":[86,124],"244":[144,86,124,185,197],"254":[86,124],"255":[86,124],"256":[86,124],"261":[86,124],"264":[86,124],"265":[86,124],"276":[86,124],"282":[86,124],"283":[86,124],"289":[86,124],"299":[86,124],"301":[86,124],"359":[86,124],"362":[86,124],"363":[86,124],"369":[86,124],"374":[86,124],"381":[86,124],"384":[86,124],"388":[86,124],"391":[86,124],"394":[86,124],"395":[86,124],"408":[86,124],"410":[86,124],"414":[86,124],"419":[86,124],"423":[86,124],"426":[86,124],"461":[144,86,124,185,197],"502":[144,86,124,185,197],"507":[144,86,124,185,197],"520":[144,86,124,185,197],"534":[144,86,124,185,197],"543":[144,86,124,185,197],"550":[144,86,124,185,197],"602":[144,86,124,185,197],"604":[144,86,124,185,197],"606":[86,124],"609":[144,86,124,185,197],"610":[144,86,124,185,197],"614":[144,86,124,185,197],"616":[144,86,124,185,197],"624":[144,86,124,185,197],"626":[144,86,124,185,197],"631":[144,86,124,185,197],"645":[86,124],"650":[144,86,124,185,197],"651":[144,86,124,185,197],"657":[144,86,124,185,197],"658":[144,86,124,185,197],"663":[144,86,124,185,197],"672":[144,86,124],"674":[144,86,124,185,197],"678":[144,86,124,185,197],"686":[86,124],"700":[86,124],"705":[86,124],"706":[86,124],"712":[86,124],"713":[86,124],"719":[144,86,124,185,197],"720":[144,86,124,185,197],"742":[144,86,124,185,197],"756":[144,86,124,185,197],"765":[144,86,124,185,197],"767":[144,86,124,185,197],"771":[144,86,124,185,197],"776":[144,86,124,185,197],"781":[86,124],"795":[86,124],"801":[86,124],"819":[86,124],"828":[86,124],"843":[144,86,124,185,197],"850":[86,124],"854":[86,124],"855":[86,124],"885":[144,86,124,185,197],"898":[144,86,124,185,197],"902":[144,86,124,185,197],"907":[86,124],"918":[86,124],"921":[86,124],"929":[86,124],"940":[144,86,124,185,197],"949":[144,86,124,185,197],"952":[86,124],"958":[144,86,124,185,197],"971":[86,124],"982":[86,124],"1001":[144,86,124,185,197],"1013":[144,86,124,185,197],"1014":[86,124],"1017":[86,124],"1023":[86,124],"1024":[86,124],"1038":[144,86,124,185,197],"1044":[86,124],"1047":[144,86,124,185,197],"1067":[86,124],"1080":[144,86,124,185,197],"1081":[144,86,124,185,197],"1128":[144,86,124,185,197],"1134":[144,86,124,185,197],"1138":[86,124],"1140":[144,86,124,185,197],"1141":[144,86,124,185,197],"1152":[86,124],"1157":[86,124],"1171":[86,124],"1176":[86,124],"1178":[86,124],"1187":[144,86,124,185,197],"1202":[86,124]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasMapping.groups.ts":{"46":[86,124,31,71],"54":[86,124,31,71],"71":[86,124,31,71],"93":[86,124,31,71],"100":[86,124,31,71],"118":[86,124,31,71],"124":[86,124,31,71],"172":[86,124,31,71],"187":[86,124,31,71],"217":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","230":[86,124,31,71],"237":[86,124,31,71],"243":[86,124,31,71],"251":[86,124,31,71],"284":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","310":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA="},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasMapping.ts":{"54":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","73":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","79":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","80":"b:cEcAEAjDAABAG3AIA5AQ2IQ3CAQAPjMlQOC3AwA=","84":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","112":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","114":[86,124,31,71],"120":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","144":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","152":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","159":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","211":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","214":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","223":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","251":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","254":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","266":[86,124],"275":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","276":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA=","288":"b:8EeCkKzjAQDkf3UIH5BQ3Ox/OUdQN/9/6P6/BwA="},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasNode.ts":{"9":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","11":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","34":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","35":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","37":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","38":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","39":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","41":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","42":[86,124,176,187,71,200,136,212,218,100],"43":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","45":[86,124],"46":[86,124],"47":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","49":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","50":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","51":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","52":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","54":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","55":"b:cEcAEAjDAABAG3AIA5AQ2IQ3CAQAPjMlQOC3AwA=","56":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","58":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","60":[86,124,176,187,71,200,136,212,218,100],"64":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","70":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA="},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasNodeGroupActions.ts":{"21":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","30":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","32":"b:8E/CkKjjAQDk/3cIH5BQ3Ox/DUfwP/9/mP//BwA=","34":"b:4EeCAKgiAADkfXEIDxBQFOx/CAfwP79/iPe/BwA=","35":"b:4EeCAKgiAADkfXEIDxBQFOx/CAfwP79/iPe/BwA=","38":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","43":[86,124],"59":[86,124],"64":[86,124],"70":[86,124],"79":[86,124,71],"91":[86,124,71],"95":[86,124,71],"108":[86,124],"121":[86,124,71]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasNodeGroupDescriptionVisibility.ts":{"16":[86,124,31,71],"33":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","39":[86,124],"43":[86,124,31,71],"47":[86,124,71],"59":[86,124],"65":[86,124],"82":[86,124,71],"88":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","89":[86,124],"91":[86,124],"94":[86,148,149,124,47,71,137,214,79,216,217],"110":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","114":[86,124]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasNodeGroupDrag.ts":{"38":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","46":[86,124,71],"52":[86,124,71],"71":[86,124,71],"82":[86,124,71],"108":[86,124,71],"113":[86,124,184,70,96,71,201,99],"118":[86,124,184,70,96,71,201,99],"130":[86,124,184,70,96,71,201,99],"131":[86,124,184,70,96,71,201,99],"142":[86,124,184,70,96,71,201,99],"190":[86,124,71],"198":[86,124,184,70,96,71,201,99],"205":[86,124,184,70,96,71,201,99],"223":[86,124,184,70,96,71,201,99],"235":[86,124,184,70,96,71,201,99],"246":[86,124,71],"255":[86,124,184,70,96,71,201,99],"274":[86,124],"284":[86,124],"288":[86,124]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasNodeGroupLayout.ts":{"69":[86,124,31,71],"81":[86,124,31,71],"114":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","126":[86,124,31,71],"133":[86,124,71],"137":[86,124,71],"141":[86,124,71],"145":[86,124,71],"149":[86,124,71],"160":[86,124,71],"164":[86,124,71],"244":[86,124],"260":[86,124,31,71],"270":[86,124,71],"276":[86,124],"279":[86,124,31,71],"284":[86,124,71],"287":[86,124,31,71],"291":[86,124],"302":[86,124,71],"309":[86,124],"341":[86,124,71],"359":[86,124],"365":[86,124],"373":[86,124,71],"381":[86,124],"401":[86,124],"402":[86,124],"421":[86,124,71],"483":[86,124,71],"505":[86,124,31,71],"517":[86,124,71],"519":[86,124,71]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasNodeGroupOperationGuards.ts":{"57":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","59":"b:4EGCAKAiAADkfXEIBxAQAORqCQdQJ4l+CNYuBAA=","69":[86,71],"89":[86,71],"98":[86,71],"106":[86,71],"128":"b:4EGCAKAiAADkfXEIBxAQAORqCQdQJ4l+CNYuBAA=","140":[86,71],"143":[86,71],"154":[86],"179":[86],"190":[86],"203":[86],"209":[86],"227":[86,71],"237":[86,71],"253":[86,71],"272":[86,71],"277":"b:4EGCAKAiAADkfXEIBxAQAORqCQdQJ4l+CNYuBAA=","323":[144,86,70,71,201],"344":[86],"387":[86],"390":[86]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasNodeGroupSelection.ts":{"37":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","53":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","55":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","58":[86,124,31,71],"63":"b:4EeCAKiiAADk/XUIDxBQFOx/KAfwP79/iPe/BwA=","70":"b:4EeCAKiiAADk/XUIDxBQFOx/KAfwP79/iPe/BwA=","77":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","78":"b:4EeCAKiiAADk/XEIDxBQFOx/KAfwP79/iPe/BwA=","79":"b:4EeCAKCiAADkfXEIDxAQEOR/CAdALq9/iOe/AwA=","93":[86,124,71],"120":[86,124,71],"130":[86,124,71],"131":[86,124,71],"140":[86,124,71],"141":[86,124],"143":[86,124],"151":"b:8EeCAKiiAADk/XUIDxBQFOx/KAfwP79/iPe/BwA=","157":[86,124,71],"168":"b:EAYAAAAgAADAAEAAAAAAEEACAAEAIAABgAEmAAA=","177":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","188":"b:4EeCAKiiAADk/XEIDxBQFOx/KAfwP79/iPe/BwA=","189":"b:4EeCAKCiAADkfXEIDxAQEOR/CAdALq9/iOe/AwA=","202":"b:4EeCAKiiAADk/XEIDxBQFOx/KAfwP79/iPe/BwA=","207":"b:4EeCAKiiAADk/XEIDxBQFOx/KAfwP79/iPe/BwA=","222":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","255":[86,124]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasNodeGroupTelemetry.ts":{"25":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","32":[86,71],"45":[86,71],"64":[86,71],"76":[86],"94":[86,71],"97":[86,71],"100":[86,71]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasNodeGroupView.ts":{"37":[86,124,71],"62":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","66":[144,86,124,31,184,185,70,96,71,201,99],"69":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","74":[86,124,31,71],"77":[86,124,71],"81":[86,124,31,71],"89":[86,124,31,71],"92":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","94":[86,124,31,71],"99":[86,124,71],"106":[86,124,71],"107":[86,124,71],"109":[86,124,71],"115":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","126":[86,124,71],"132":[86,124,71],"139":[86,124,71],"143":[86,124,71],"148":[86,124,31,71],"150":[86,124,71],"154":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","158":[86,124,31,71],"162":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","167":[86,124,71],"177":[86,124,71],"181":[86,124],"182":[86,124],"196":[86,124,71],"208":[86,124,71],"223":[144,86,124,184,185,70,96,71,201,99],"230":[86,124,71],"259":[86,124],"263":[86,124,71],"268":[86,124],"282":[86,124],"294":[86,148,149,124,47,71,137,214,79,216,217],"296":[86,124],"314":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA="},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasNodeHandle.ts":{"11":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","14":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","15":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","16":"b:8EeCkKjjAQDk/3cIH5BQ3Ox/CUfwP/9/uP6/BwA=","17":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","18":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","19":[4,84,85,10,86,124,37,181,190,137,139],"20":[86,124],"21":[86,124],"22":[86,124],"23":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA="},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasNodeHover.ts":{"10":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","17":"b:8E8AAKigAADkuXUACwBQFMQ/LQXgMz9/gH+3BwA=","31":"b:cEcAACigAADkuXEACwBQFMQ/KAXgMj9/gH63BwA=","64":[86,124],"73":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","77":"b:AAAAEAAgAAAgg1AAFAAAkAADAAAAAAAAAAiAAwA="},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasTraversal.ts":{"4":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","5":[86,124,70],"6":[86,124],"9":[86,124,70],"13":[86,124,70],"17":[86,124],"18":[86,124],"21":[86,124],"26":[86,124],"27":[86,124],"32":[86,124,213],"42":[86,124,213],"43":[86,124,213],"46":[86,124,70],"56":[86,124,70],"57":[86,124,70]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useEmptyCanvasGroupsFlag.ts":{"6":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","9":"b:4EeCAKgiAADkfXUIDxBQBOx/CQfwP79/iPe/BwA="},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useNodeGroupsSubscription.ts":{"18":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","21":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","30":"b:AAAAEAAgAAAgg1AAFAAAkAADAAAAAAAAAAiAAwA="},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useViewportAutoAdjust.ts":{"7":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","21":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","27":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","46":"b:AAAAEAAgAAAgg1AAFAAAkAADAAAAAAAAAAiAAwA=","51":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA="},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useVueFlowTransformPaneTeleport.ts":{"9":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","14":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA=","16":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA="},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useZoomAdjustedValues.ts":{"8":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","17":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","39":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","40":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","60":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","61":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","76":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","77":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","92":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","94":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA="},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/composables/useIsInExperimentalNdv.ts":{"4":"b:4EWSAKyiAFBkfXUIBxB0FPR/KS9QO7d/iPY/AgA=","8":"b:AAAAAAAAAFAAfEAAAgAQEAAwAAAAAABQgMAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/experimentalNdv.store.ts":{"17":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","19":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","24":"b:8E/CkKzjAUDk/3cIH5B03Ox/PUfwP/9/2P//BwA=","29":[86,124],"36":[86,124],"43":[86,124],"44":[86,124],"50":[86,124],"54":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","58":[86,124],"62":[144,86,124,188,199],"72":[86,124],"107":[86,124],"121":[86,124],"122":[86,124],"138":[86,124],"139":[86,124],"140":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","141":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/2P//BwA="},"packages/frontend/editor-ui/src/features/workflows/readyToRun/composables/useEmptyStateDetection.ts":{"13":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/3f//BwA=","26":"b:AAABAQAwAIgAAAIDHAAAAgAAgAAEgAAABAgAAAA=","45":"b:AAABAwA4AIgAgAIhHAAAAgAAAAAEwAAADAgAAAA="},"packages/frontend/editor-ui/src/features/workflows/readyToRun/stores/readyToRun.store.ts":{"22":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/3f//BwA=","59":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/3f//BwA=","66":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/3f//BwA=","74":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/3f//BwA=","90":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/3f//BwA=","91":"b:/k/j8777AZjk/zc7H5BQzvx/j8f3//9/3f//BwA=","110":"b:gACDAwA4AJgAgAIpHAAAAjAAAAAEwAAADQgAAAA=","208":"b:gACCAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","220":"b:AAABAwA4AIgAgAIhHAAAAgAAAAAEwAAADAgAAAA=","224":[48]},"packages/frontend/editor-ui/src/features/workflows/templates/components/SetupWorkflowCredentialsButton.vue":{"32":[48,82,100],"34":[48],"38":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","42":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","49":"b:8EGCkKjjAQDk/zUIH5BQzOR/CUfwP71+mO+/BwA=","54":"b:8EGCkKjjAQDk/zUIH5BQzOR/CUfwP71+mO+/BwA=","57":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","63":[48,82,100],"67":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","84":[48,82,100],"92":"b:gACCAKACAAAgYDUAAgAAAGAIAANQIYFICAQKBAA=","107":[48],"111":[48],"119":"b:AAgAEAAgAAAgAxAABAAAAAADAQAAAAAAAAiAAwA=","123":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA=","139":"b:8E/CkKjjAQDk/zcIH5BQzOx/DUfwP/9/mP//BwA="},"packages/frontend/editor-ui/src/features/workflows/templates/templates.store.ts":{"49":[86,124,100],"55":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","90":[86,124,100],"91":[86,124,100],"96":[86,124,82],"97":[86,124,82],"100":[86,124,82,100],"101":[86,124,82,100],"107":[86,124,82],"109":[86,124,100],"110":[86,124,100],"113":[86,124,100],"114":[86,124,100],"121":[86,124,100],"125":[86,124,100],"126":[86,124,100],"133":[86,124,100],"137":[86,124,100],"138":[86,124,100],"146":[86,124],"147":[86,124],"155":[86,124],"156":[86,124],"166":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","170":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","186":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","194":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","212":"b:/k/j8777AZjk/3c7H5BQ3vx/j8f3//9/nf//BwA=","217":"b:oECCAIAiAABkfXEIBxAQEOxgCAHgIJAOCNYOAAA=","224":[86,124,100],"228":[86,124,82,100],"231":[86,124,82,100],"232":[86,124,82,100],"243":[86,124,82,100],"244":[86,124,82,100],"250":[86,124,100],"254":[86,124,100],"262":[86,124,100],"267":[86,124,100],"286":[86,124],"299":[86,124],"312":"b:/k//8777Adzk/3c7H5B83vz/v///////////BwA=","317":[86,124,48,82,100],"323":[86,124,82,100],"339":[86,124,82],"357":[86,124,100],"373":[86,124,100],"388":[86,124,100],"393":[86,124,100],"413":[86,124],"439":[86,124,48,82,100],"447":[86,124,48,82,100],"455":[86,124,48,82,100]},"packages/frontend/editor-ui/src/features/workflows/templates/utils/typeGuards.ts":{"8":[86,124,82],"14":[86,124,82],"20":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/frontend/editor-ui/src/features/workflows/templates/utils/workflowSamples.ts":{"9":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","17":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","21":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","30":[86,124],"35":[86,124]},"packages/frontend/editor-ui/src/features/workflows/workflowHistory/workflowHistory.store.ts":{"24":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","31":[86,124,203],"33":[86,124,203],"37":[86,124,203],"41":[86,124,203],"47":"b:AAAAAACAAAAAA0AAAAAAEAADAQAAAAAAAAiAAwA=","53":[86,124],"78":[86,124],"104":[86,124],"120":[86,124],"133":[86,124],"141":[86,124],"147":[86,124]},"packages/modules/instance-registry/frontend/src/instance-registry.store.ts":{"7":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA=","12":[86,124],"14":[86,124,201]},"packages/modules/mcp/frontend/src/mcp.module.ts":{"11":[86,124,163],"12":[86,124],"13":[86,124],"14":[86,124],"76":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA=","81":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA="},"packages/modules/mcp/frontend/src/mcp.store.ts":{"38":"b:9k/Dk6z7AYjk/3crH5BQ3ux/v0f8//9/3P//BwA=","70":"b:YAEAAAAAAABAIEQADgAAEEACAAQIBAk4AAIGBAA=","71":[86,124,163],"72":[86,124],"78":[86,124,163],"83":[86,124,163],"99":[86,124],"113":[86,124],"120":[86,124,163],"132":[86,124],"141":[86,124],"150":[86,124],"158":[86,124],"167":[86,124],"199":[86,124],"223":[86,124],"250":[86,124],"257":[86,124],"263":[86,124],"269":[86,124],"273":[86,124,163],"279":[86,124],"321":[86,124,163],"346":[86,124],"351":[86,124],"358":[86,124],"364":[86,124],"371":[86,124,163],"390":[86,124],"408":[86,124],"416":[86,124],"424":[86,124,163],"428":[86,124],"432":[86,124,163],"438":[86,124]},"packages/modules/otel/frontend/src/otel.module.ts":{"10":[86,124],"40":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA=","45":"b:/k//8777Adzk/3c7H5B83vz/j///////n///BwA="},"packages/modules/type-availability-policies/frontend/src/composables/useNodeTypeRestriction.ts":{"19":"b:8EeSkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","24":"b:oECCAIAiAABkfXEIBxAQEOxgCAHgIpAOCNYOAAA=","39":"b:8EeSkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","50":"b:AAAAAAAAAADAAFQACwAAEEAAAAAAAAARACMgAAA=","59":[86,124,66],"81":[86,124],"93":"b:8E/CkKzjAQDk/3cIH5BQ3Ox/PUfwP/9/+P//BwA=","94":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","99":"b:8EeCkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P6/BwA=","100":[86,124,66]},"packages/modules/type-availability-policies/frontend/src/type-availability-policies.store.ts":{"16":[86,124,66],"19":[86,124,66],"23":"b:9k/SkKzjAQTk/3cIH5BQ3Ox/PUfwP///+P//BwA=","37":"b:9k/SkKzjAQDk/3cIH5BQ3Ox/DUfwP///2P//BwA=","41":"b:9k/SkKzjAQDk/3cIH5BQ3Ox/DUfwP/9/2P//BwA=","56":[86,124,191],"67":[86,124,66],"92":"b:8EeSkKzjAQDk/3cIH5BQ3Ox/OUfwP/9/+P+/BwA=","98":[86,124],"102":"b:pkCCAIAiAABkfXEIBxAQEOxgCAHgIpAOCNYOAAA=","108":[86,124]},"packages/vite/source-map-js-shim.ts":{"1":"b:/k//8777Ad7k/3c7H5B83vz/////////////BwA="},"packages/@n8n/db/src/repositories/tag.repository.ts":{"15":[46,188,72,73,98,214,215,216,218],"19":[46,188,72,73,98,214,215,216,218],"27":[46,188,72,73,98,214,215,216,218],"38":[46,188,72,73,98,214,215,216,218],"44":[46,188,72,73,98,214,215,216,218],"59":[46,188,72,73,98,214,215,216,218],"68":[46,188,72,73,98,214,215,216,218],"80":[46,188,72,73,98,214,215,216,218],"103":[46,188,72,73,98,214,215,216,218],"117":[46,188,72,73,98,214,215,216,218],"129":[46,188,72,73,98,214,215,216,218]},"packages/@n8n/db/src/repositories/workflow-tag-mapping.repository.ts":{"10":"b:wAECAIAgAAC0KBIAARAABOgIAAAAIAIAAABAAAA=","14":"b:wAECAIAgAAC0KBIAARAABOgIAAAAIAIAAABAAAA=","15":"b:wAECAIAgAAC0KBIAARAABOgIAAAAIAIAAABAAAA=","18":"b:wAECAIAgAAC0KBIAARAABOgIAAAAIAIAAABAAAA="},"packages/cli/src/collaboration/collaboration.service.ts":{"40":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","50":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","51":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","76":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","85":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","111":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","127":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","149":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","153":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","159":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","161":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","171":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","197":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","212":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","223":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","229":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","245":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","247":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","260":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","262":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","276":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","283":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","314":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","320":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","340":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","342":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","360":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","374":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","388":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","431":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","444":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","448":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","452":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","464":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","482":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","484":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","490":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","492":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","502":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","528":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","543":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","554":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","560":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","574":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","576":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","597":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","614":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","628":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","660":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA=","676":"b:9v+ilOztviH3vn9oDZmATOgKAAEAMAIAABhgoAA="},"packages/cli/src/controllers/tags.controller.ts":{"20":[170,93,187,188,210,77,97,98,214,216,218,81],"24":[170,93,187,188,210,77,97,98,214,216,218,81],"30":[170,93,187,188,210,77,97,98,214,216,218,81],"43":[170,93,187,188,210,77,97,98,214,216,218,81],"56":[170,93,187,188,210,77,97,98,214,216,218,81]},"packages/cli/src/services/tag.service.ts":{"14":"b:8A2CACBoACBgP34oDxEAKUAKAAEABAAYAADEBQA=","20":"b:8A2CACBoACBgP34oDxEAKUAKAAEABAAYAADEBQA=","26":"b:8A2CACBoACBgP34oDxEAKUAKAAEABAAYAADEBQA=","46":"b:8A2CACBoACBgP34oDxEAKUAKAAEABAAYAADEBQA=","49":"b:8A2CACBoACBgP34oDxEAKUAKAAEABAAYAADEBQA=","53":"b:8A2CACBoACBgP34oDxEAKUAKAAEABAAYAADEBQA=","63":"b:8A2CACBoACBgP34oDxEAKUAKAAEABAAYAADEBQA=","82":"b:8A2CACBoACBgP34oDxEAKUAKAAEABAAYAADEBQA=","95":"b:8A2CACBoACBgP34oDxEAKUAKAAEABAAYAADEBQA=","101":"b:8A2CACBoACBgP34oDxEAKUAKAAEABAAYAADEBQA=","106":"b:8A2CACBoACBgP34oDxEAKUAKAAEABAAYAADEBQA=","111":"b:8A2CACBoACBgP34oDxEAKUAKAAEABAAYAADEBQA=","119":"b:8A2CACBoACBgP34oDxEAKUAKAAEABAAYAADEBQA=","133":"b:8A2CACBoACBgP34oDxEAKUAKAAEABAAYAADEBQA=","134":"b:8A2CACBoACBgP34oDxEAKUAKAAEABAAYAADEBQA=","139":"b:8A2CACBoACBgP34oDxEAKUAKAAEABAAYAADEBQA=","148":"b:8A2CACBoACBgP34oDxEAKUAKAAEABAAYAADEBQA=","150":"b:8A2CACBoACBgP34oDxEAKUAKAAEABAAYAADEBQA=","155":"b:8A2CACBoACBgP34oDxEAKUAKAAEABAAYAADEBQA="},"localhost-34343/assets/index-BoK1c_f3.js":{"3":[93,136,214]},"localhost-34343/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[93,136,214],"9":[93,136,214],"10":[93,136,214],"19":[93,136,214],"23":[93,136,214],"29":[93,136,214],"33":[93,136,214],"34":[93,136,214]},"packages/frontend/@n8n/design-system/src/components/N8nDropdownMenu/DropdownMenuItem.vue":{"71":"b:5AGIgwCYAFAgoEIgBgBAEAAiAD4CZAm4HApGBAA=","73":"b:YAEIAAAAAAAAIEAABgAAEAACABwABAk4AAIGBAA=","75":"b:YAEIAAAAAAAAIEAABgAAEAACABwABAk4AAIGBAA=","78":[86,124],"82":"b:5AGIgwCYAFAgoEIgBgBAEAAiAD4CZAm4HApGBAA=","83":"b:5AGIgwCYAFAgoEIgBgBAEAAiAD4CZAm4HApGBAA=","85":"b:YAEIgACIAAAgIEAgBgBAEAACABwARAk4GApGBAA=","91":[86,124],"95":"b:5AGIgwCYAFAgoEIgBgBAEAAiAD4CZAm4HApGBAA=","99":"b:5AGIgwCYAFAgoEIgBgBAEAAiAD4CZAm4HApGBAA=","103":"b:5AGIgwCYAFAgoEIgBgBAEAAiAD4CZAm4HApGBAA=","107":"b:5AGAAgCYAFAgoEIABgBAEAAiACYAZAm4HApGBAA=","109":"b:YAEIAAAAAAAAIEAABgAAEAACABwABAk4AAIGBAA=","113":"b:5AGIAwCYAFAgoEIgBgBAEAAiAD4CZAm4HApGBAA=","120":"b:5AGIAwCYAFAgoEIgBgBAEAAiAD4CZAm4HApGBAA=","125":[86,124],"130":[86,124],"146":[86,124],"152":[86,124],"158":"b:YAEIAAAAAAAAIEAABgAAEAACAAQABAk4AAIGBAA=","169":[86,19,124],"175":"b:YAEIAAAAAAAAIEAABgAAEAACABwABAk4AAIGBAA=","181":"b:YAEIAAAAAAAAIEAABgAAEAACABwABAk4AAIGBAA=","185":"b:YAEIAAAAAAAAIEAABgAAEAACABwABAk4AAIGBAA=","195":[86,124],"203":[86,124],"210":[86,124],"222":[86,124],"227":"b:5AGIgwCYAFAgoEIgBgBAEAAiAD4CZAm4HApGBAA=","228":"b:5AGIgwCYAFAgoEIgBgBAEAAiAD4CZAm4HApGBAA=","237":"b:YAEIAAAAAAAAIEAABgAAEAACABwABAk4AAIGBAA=","247":"b:4AGIgwCYAFAgoEIgBgBAEAAiAD4CZAm4HApGBAA=","250":"b:5AGIgwCYAFAgoEIgBgBAEAAiAD4CZAm4HApGBAA=","257":[86,124,31,161],"264":"b:YAEIgACIAAAgoEAgBgBAEAACABwARAk4GApGBAA=","279":"b:YAEIgACIAAAgoEAgBgBAEAACABwARAk4GApGBAA=","281":"b:YAEAAACIAAAgoEAgBgBAEAACAAQARAk4GApGBAA=","299":[86,124],"304":[86,124],"310":"b:YAEAAACAAAAgoEAABgBAEAACAAQABAk4GApGBAA=","315":"b:YAEAAACAAAAggEAABgBAEAACAAQABAk4GApGBAA=","357":"b:YAEIgACIAAAgoEAgBgBAEAACABwARAk4GApGBAA=","370":"b:YAEIAAAAAAAAAEAABgAAEAACABwABAk4AAIGBAA=","380":[86,124],"384":[86,124],"387":[86,124],"400":[86,124],"411":[86,124],"414":[86,124],"416":[86,124],"419":[86,124],"422":[86,124],"436":[86,124],"445":"b:YAEIAAAAAAAAIEAABgAAEAACABwABAk4AAIGBAA=","453":"b:YAEIAAAAAAAAIEAABgAAEAACABwABAk4AAIGBAA=","456":"b:YAEIAAAAAAAAIEAABgAAEAACABwABAk4AAIGBAA=","459":"b:YAEIAAAAAAAAIEAABgAAEAACABwABAk4AAIGBAA=","486":[2,86,124],"488":[2,86,124],"500":[2,86,124],"505":[2,86,124],"526":"b:5AGIgwCYAFAgoEIgBgBAEAAiAD4CZAm4HApGBAA=","528":"b:5AGAAgCYAFAgoEIgBgBAEAAiADYCZAm4HApGBAA=","540":"b:5AGAAgCYAFAgoEIABgBAEAAiACYAZAm4HApGBAA=","545":"b:5AGAAgCYAFAggEIABgBAEAAiACYAZAm4HApGBAA="},"packages/frontend/@n8n/design-system/src/components/N8nDropdownMenu/DropdownMenuItems.vue":{"37":"b:5AGIgwCYAFAgoEIgBgBAEAAiAD4CZAm4HApGBAA=","53":"b:5AGIgwCYAFAggEIgBgBAEAAiAD4CZAm4HApGBAA=","60":[86,124,31,43],"74":"b:5AGIgwCYAFAgoEIgBgBAEAAiAD4CZAm4HApGBAA=","76":"b:5AGIgwCYAFAggEIgBgBAEAAiAD4CZAm4HApGBAA=","84":"b:5AGIAwCYAFAgoEIgBgBAEAAiAD4CZAm4HApGBAA=","85":[86,124],"86":"b:YAEIAAAAAAAAIEAABgAAEAACABwABAk4AAIGBAA=","87":"b:5AGIAwCYAFAgoEIgBgBAEAAiAD4CZAm4HApGBAA=","88":[86,124],"90":[86,155,19,156,124,24,31,161,137],"93":[86,155,19,156,124,24,31,161,93,43,174,137],"96":"b:BAAIgwAYAFAAAEIAAAAAEAAiADgCQACABAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/archive--outline-16.svg":{"9":"b:YAEAAACgAAAgoEAABgBAEAACAAQABAk4GApGBAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/arrow-to-bracket-down--outline-16.svg":{"9":"b:YAEAAACgAAAgoEAABgBAEAACAAQABAk4GApGBAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/chevron-right--outline-12.svg":{"9":"b:YAF8ggC4AIAgoEAjDgBAEAACABwARAk4GApGBAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/copy--outline-16.svg":{"9":"b:ZAE88AiAAAAgoEAQBgBA0AACABwLBAk4GApGBQA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/gear--outline-16.svg":{"9":"b:YAE8AACAAAAgoEIABgBAEAACABwABAk4GApGBQA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/git-branch--outline-16.svg":{"9":"b:YAFAAACAANwgoEAABgBsEACCACQIBAm4HgpGBAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/history--outline-16.svg":{"9":"b:ZgEB8B6gAAAgoEAQBgBA0AACAIQHBAk4GApGBAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/layers--outline-16.svg":{"9":"b:AACiAoC4ABAEQUMoHgBQGvxFBWIQyNtqnBBgAQA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/list-checks--outline-16.svg":{"9":[1,2,86,124,47,195,118,196,69,203,214,79]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/plus-circle--outline-16.svg":{"9":[86,124,45,214]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/star--outline-16.svg":{"9":"b:YAGiAgC4ABAgoEIgDgBAEgACAAQAxAk4GApGBAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/tags--outline-16.svg":{"9":"b:YAEAAACgAAAgoEAABgBAEAACAAQABAk4GApGBAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/svgContentDirective.ts":{"13":"b:YAEAAACgAAAgoEAABgBAEAACAAQABAk4GApGBAA=","16":[86,124,69],"21":"b:YAEAAACgAAAgoEAABgBAEAACAAQABAk4GApGBAA="},"packages/frontend/editor-ui/src/app/components/MainHeader/utils.ts":{"1":[43,118,214]},"packages/frontend/editor-ui/src/app/components/Modal.vue":{"11":"b:oACaAwCwAVQggEMIAABkEDAAADAAUACAHQJgBAA=","61":"b:oACaAwCwAVQggEMIAABkEDAAADAAUACAHQJgBAA=","83":"b:oACaAwCwAVQggEMIAABkEDAAADAAUACAHQJgBAA=","92":"b:oACaAwCwAFQggEcIAABAEDAAADAAEACAFQJgBAA=","99":[86,124,24],"104":"b:oACaAwCwAFQggEMIAAAkEDAAADAAEACAFQJgBAA=","111":[86,124,24,201],"115":"b:gACaAACgAFQggEEIAABAEDAAACAAEACAFQJgBAA=","127":[86,19,20,124,192,62,118,218],"131":"b:oACaAwCwAVQggEcIAABkEDAAADAAUACAHQJgBAA=","139":"b:oACaAwCwAVQggEcIAABkEDAAADAAUACAHQJgBAA=","164":"b:oACaAwCwAVQggEcIAABkEDAAADAAUACAHQJgBAA=","166":"b:oACaAwAwAVAggEcIAAAkEDAAADAAEAAAAAAAAAA=","169":"b:AAAAAACQABQggEMAAABAEAAAAAAAUACAHQJgBAA=","171":"b:AAAAAACQABQggEMAAABAEAAAAAAAUACAHQJgBAA=","174":[86,124],"180":[86,124,44,201]},"packages/frontend/editor-ui/src/app/composables/useDependencyMenu.ts":{"59":"b:AAAAAAAhAAAEAAQIEIBABDQAAAAAEAAAAAAAAAA=","80":[118],"125":"b:YAEAAACAAAAgoAAABgBAAAACAAQABAk4GApGBAA="},"packages/frontend/editor-ui/src/features/shared/tags/components/TagsDropdown.vue":{"58":[86,124,214,81],"72":[86,124,214,81],"73":[86,124,214,81],"78":[86,124,214,81],"79":[86,124,214,81],"82":[86,124,214,81],"86":[86,124,214,81],"95":[86,124,214,81],"96":[86,124,214,81],"104":[86,124,214,81],"112":[86,124,214],"130":[86,124,214,81],"134":[86,124],"139":[86,124,214,81],"141":[86,124,214,81],"144":[86,124,214],"160":[86,124,214,81],"161":[86,124,214,81],"162":[86,124,214,81],"171":[86,124,214,81],"180":[86,124,214,81],"191":[86,124,214],"198":[86,124,214,81],"207":[86,124,214],"208":[86,124,214],"214":[86,124,214,81],"220":[86,124,214,81],"223":[86,124],"241":[86,124,214,81],"248":[86,124,214],"255":[86,124,214,81],"269":[86,124,214,81],"279":[86,124,214,81]},"packages/frontend/editor-ui/src/features/shared/tags/components/TagsManager/NoTagsView.vue":{"21":[86,124,214],"22":[86,124,214],"27":[86,124,214],"31":[86,124,214],"41":[86,124,214]},"packages/frontend/editor-ui/src/features/shared/tags/components/TagsManager/TagsManager.vue":{"31":[86,124,214],"44":[86,124,214],"48":[86,124,214],"50":[86,124,214],"51":[86,124,214],"53":[86,124,214],"57":[86,124,214],"61":[86,124,214],"65":[86,124,214],"69":[86,124,214],"86":[86,124],"91":[86,124],"111":[86,124],"119":[86,124,214],"120":[86,124,214],"132":[86,124,214],"135":[86,124,214],"143":[86,124],"150":[86,124,214],"163":[86,124,214],"189":[86,124,214]},"packages/frontend/editor-ui/src/features/shared/tags/components/TagsManager/TagsView/TagsTable.vue":{"33":[86,124,214],"42":[86,124,214],"46":[86,124,214],"65":[86,124],"73":[86,124,214],"80":[86,124],"84":[86,124,214],"88":[86,124,214],"92":[86,124,214],"93":[86,124,214],"100":[86,124,214],"101":[86,124,214],"109":[86,124,214],"118":[86,124,214],"119":[86,124,214],"127":[86,124,214],"132":[86,124,214],"145":[86,124,214],"147":[86,124,214],"148":[86,124,214],"150":[86,124,214],"169":[86,124,214],"171":[86,124,214],"181":[86,124,214],"183":[86,124,214],"228":[86,124],"235":[86,124,214]},"packages/frontend/editor-ui/src/features/shared/tags/components/TagsManager/TagsView/TagsTableHeader.vue":{"21":[86,124,214],"30":[86,124,214],"34":[86,124],"36":[86,124,214],"41":[86,124,214],"42":[86,124,214],"50":[86,124,214],"56":[86,124,214]},"packages/frontend/editor-ui/src/features/shared/tags/components/TagsManager/TagsView/TagsView.vue":{"12":[86,124,214],"35":[86,124,214],"48":[86,124,214],"52":[86,124,214],"53":[86,124,214],"60":[86,124,214],"61":[86,124,214],"76":[86,124,214],"80":[86,124],"85":[86,124,214],"89":[86,124],"93":[86,124],"98":[86,124],"101":[86,124],"112":[86,124,214],"116":[86,124,214],"120":[86,124,214],"122":[86,124,214],"132":[86,124,214],"137":[86,124,214],"142":[86,124,214],"145":[86,124,214],"156":[86,124,214],"168":[86,124],"177":[86,124,214]},"packages/frontend/editor-ui/src/features/shared/tags/components/TagsManager/WorkflowTagsManager.vue":{"11":[86,124,214],"16":[86,124,214],"17":[86,124,214],"19":[86,124,214],"29":[86,124,214],"44":[86,124],"64":[86,124,214],"85":[86,124,214]},"packages/frontend/editor-ui/src/features/shared/tags/components/WorkflowTagsDropdown.vue":{"18":[86,124,214,81],"36":[86,124,214,81],"37":[86,124,214,81],"40":[86,124,214,81],"41":[86,124,214,81],"42":[86,124,214,81],"44":[86,124,214,81],"45":[86,124,214,81],"48":[86,124,214,81],"50":[86,124,214,81],"54":[86,124,214],"58":[86,124,214],"62":[86,124],"66":[86,124,214,81],"72":[86,124,214,81]},"packages/frontend/editor-ui/src/features/shared/tags/useTagPermissions.ts":{"4":[86,124,214,81],"5":[86,124],"6":[86,124,214,81],"7":[86,124,214],"8":[86,124,214],"11":[86,124,214,81],"16":[86,124],"17":[86,124],"20":[86,124],"23":[86,124],"28":[86,124]},"packages/frontend/editor-ui/src/features/workflows/components/WorkflowDescriptionModal.vue":{"21":[86,124,214],"51":[86,124,214],"55":[86,124,214],"57":[86,124,214],"58":[86,124,214],"60":[86,124,214],"63":[86,124,214],"66":[86,124,214],"70":[86,124,214],"76":[86,124,214],"82":[86,124,214],"138":[86,124,214],"169":[86,124],"173":[86,124,214],"178":[86,124],"198":[86,124,214],"199":[86,124,214],"203":[86,124,214],"214":[86,124,214],"220":[86,124,214],"230":[86,124,214],"234":[86,124,214],"243":[86,124,214]},"packages/@n8n/ai-utilities/src/guards.ts":{"7":[4,84,85,10,18,19,20],"9":[4,84,85,10,18,19,20],"17":[4,84,85,10,18,19,20],"21":[4,84,85,10,18,19,20],"25":[4,84,85,10,18,19,20],"31":[4,84,85,10,18,19,20]},"packages/@n8n/ai-utilities/src/index.ts":{"8":"b:ECScACAAAABAIHAAAAAAIAAIAAAAACAAAAAAIAA=","13":"b:ECScACAAAABAIHAAAAAAIAAIAAAAACAAAAAAIAA=","14":"b:ECScACAAAABAIHAAAAAAIAAIAAAAACAAAAAAIAA=","15":"b:ECScACAAAABAIHAAAAAAIAAIAAAAACAAAAAAIAA=","17":"b:ECScACAAAABAIHAAAAAAIAAIAAAAACAAAAAAIAA=","53":"b:ECScACAAAABAIHAAAAAAIAAIAAAAACAAAAAAIAA=","90":"b:ECScACAAAABAIHAAAAAAIAAIAAAAACAAAAAAIAA=","99":"b:ECScACAAAABAIHAAAAAAIAAIAAAAACAAAAAAIAA=","100":"b:ECScACAAAABAIHAAAAAAIAAIAAAAACAAAAAAIAA=","129":"b:ECScACAAAABAIHAAAAAAIAAIAAAAACAAAAAAIAA=","130":"b:ECScACAAAABAIHAAAAAAIAAIAAAAACAAAAAAIAA=","134":"b:ECScACAAAABAIHAAAAAAIAAIAAAAACAAAAAAIAA="},"packages/@n8n/ai-utilities/src/model-discovery/index.ts":{"45":[84,18,19,20],"49":[84,18,19,20],"81":[84,18,19,20],"94":[84,18,19,20]},"packages/@n8n/ai-utilities/src/model-discovery/providers/openai.ts":{"6":[84],"23":[84],"49":[84],"57":[84]},"packages/@n8n/ai-utilities/src/model-discovery/request.ts":{"6":[84,18,19,20],"25":[84,18,19,20],"34":[84,18,19,20],"45":[84,18,19,20],"64":[84,18,19,20],"68":[84,18,19,20],"77":[84,18,19,20],"79":[84,18,19,20],"80":[84,18,19,20],"87":[84,18,19,20],"88":[84,18,19,20]},"packages/@n8n/ai-utilities/src/utils/failed-attempt-handler/n8nDefaultFailedAttemptHandler.ts":{"20":[84,85,20,21]},"packages/@n8n/ai-utilities/src/utils/failed-attempt-handler/n8nLlmFailedAttemptHandler.ts":{"13":[84,85,18,19,20,21],"17":[84,85,18,19,20,21]},"packages/@n8n/ai-utilities/src/utils/helpers.ts":{"3":[4,84,85,10,18,19,20],"17":[4,84,85,10,18,19,20],"37":[4,84,85,10,18,19,20]},"packages/@n8n/ai-utilities/src/utils/http-proxy-agent.ts":{"63":[84,85,18,19,20],"74":[84,85,18,19,20],"105":[84,85,18,19,20],"130":[84,85,18,19,20],"175":[84,85,18,19,20],"216":[84,85,18,19,20],"228":[84,85,18,19,20],"244":[84,85,18,19,20],"247":[84,85,18,19,20],"255":[84,85,18,19,20],"257":[84,85,18,19,20]},"packages/@n8n/ai-utilities/src/utils/log-ai-event.ts":{"6":[4,84,85,10,18,19,20,125,221]},"packages/@n8n/ai-utilities/src/utils/n8n-llm-tracing.ts":{"37":[84,85,18,19,20,21,137],"78":[84,85,18,19,20,21,137],"116":[84,85,18,19,20,21,137],"131":[84,85,18,19,20,21,137],"134":[84,85,18,19,20,21,137],"146":[84,85,18,19,20,21,137],"147":[84,85,18,19,20,21,137],"151":[84,85,18,19,20,21,137],"156":[84,85,18,19,20,21,137],"161":[84,85,18,19,20,21,137],"162":[84,85,18,19,20,21,137],"212":[84,85,18,19,20,21,137],"237":[84,85,18,19,20,21,137],"273":[84,85,18,19,20,21,137],"304":[84,85,18,19,20,21,137],"308":[84,85,18,19,20,21,137]},"packages/@n8n/ai-utilities/src/utils/redact-headers.ts":{"12":[84,85,18,19,20],"28":[84,85,18,19,20],"31":[84,85,18,19,20],"57":[84,85,18,19,20],"63":[84,85,18,19,20]},"packages/@n8n/ai-utilities/src/utils/shared-fields.ts":{"37":"b:ECScACAAAABAIHAAAAAAIAAIAAAAACAAAAAAIAA=","46":"b:ECScACAAAABAIHAAAAAAIAAIAAAAACAAAAAAIAA=","110":"b:ECScACAAAABAIHAAAAAAIAAIAAAAACAAAAAAIAA=","115":"b:ECScACAAAABAIHAAAAAAIAAIAAAAACAAAAAAIAA=","120":"b:ECScACAAAABAIHAAAAAAIAAIAAAAACAAAAAAIAA=","125":"b:ECScACAAAABAIHAAAAAAIAAIAAAAACAAAAAAIAA=","132":"b:ECScACAAAABAIHAAAAAAIAAIAAAAACAAAAAAIAA=","158":"b:ECScACAAAABAIHAAAAAAIAAIAAAAACAAAAAAIAA=","164":"b:ECScACAAAABAIHAAAAAAIAAIAAAAACAAAAAAIAA="},"packages/@n8n/ai-utilities/src/utils/strip-non-x-headers.ts":{"4":[84,85,20,21]},"packages/@n8n/ai-utilities/src/utils/tokenizer/tiktoken.ts":{"9":[84,85,18,19,20,28,29,31,35],"15":[84,85,18,19,20,28,29,31,35],"18":[84,85,18,19,20,28,29,31,35],"34":[84,85,18,19,20,28,29,31,35],"43":[84,85,18,19,20,28,29,31,35]},"packages/@n8n/ai-utilities/src/utils/tokenizer/token-estimator.ts":{"33":[84,85,18,19,20],"70":[84,85,18,19,20],"129":[84,85,18,19,20],"141":[84,85,18,19,20],"169":[84,85,18,19,20]},"packages/@n8n/api-types/src/schemas/node-version.schema.ts":{"6":[86,124],"7":[84,152,45,65,66,209,77,78,141,213]},"packages/@n8n/backend-network/src/egress.ts":{"9":[84,85,18,19,20]},"packages/@n8n/backend-network/src/http/axios/config.ts":{"16":"b:8E/CsCzpHwT0PnToCTAAAEAIAIEAAAAAAAAAAAA=","27":"b:8E/CsCzpHwT0PnToCTAAAEAIAIEAAAAAAAAAAAA=","38":"b:8E/CsCzpHwT0PnToCTAAAEAIAIEAAAAAAAAAAAA=","52":"b:8E/CsCzpHwT0PnToCTAAAEAIAIEAAAAAAAAAAAA=","53":"b:8E/CsCzpHwT0PnToCTAAAEAIAIEAAAAAAAAAAAA="},"packages/@n8n/backend-network/src/http/axios/invoke.ts":{"7":"b:8E/CACDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","36":"b:8E/CACDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA="},"packages/@n8n/backend-network/src/http/axios/redirect.ts":{"50":"b:8E/CACDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","68":"b:8E/CACDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","73":"b:8E/CACDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","81":"b:8E/CACDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","96":"b:8E/CACDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","108":"b:8E/CACDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","114":"b:8E/CACDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","120":"b:8E/CACDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","135":"b:8E/CACDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","151":"b:8E/CACDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","183":"b:8E/CACDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","206":"b:8E/CACDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","219":"b:8E/CACDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","227":"b:8E/CACDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","234":"b:8E/CACDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","238":"b:8E/CACDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA="},"packages/@n8n/backend-network/src/http/axios/request.ts":{"28":"b:8E/CACDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","78":"b:8E/CACDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","129":"b:8E/CACDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","133":"b:8E/CACDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","145":"b:8E/CACDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","160":"b:8E/CACDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","184":"b:8E/CACDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA="},"packages/@n8n/backend-network/src/http/axios/user-agent.ts":{"11":"b:8E/CACDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","28":"b:8E/CACDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","40":"b:8E/CACDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","54":"b:8E/CACDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA="},"packages/@n8n/backend-network/src/http/axios/utils.ts":{"21":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","36":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","45":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","57":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","64":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","73":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","86":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","106":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","125":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","133":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","173":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","180":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","185":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","188":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","191":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","224":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","234":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","237":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","241":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","257":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","273":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","293":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","300":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","310":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","318":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","325":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","326":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","341":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","377":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","389":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","410":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","425":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","445":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA=","451":"b:8E/CBCDrHwT0P3ToCTAAAEAIAAUAAAAAACAAAAA="},"packages/@n8n/backend-network/src/http/client-default-headers.ts":{"18":"b:8E/CACDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA="},"packages/@n8n/backend-network/src/http/client-request-error.ts":{"13":"b:YAAwABgAAgAAADSAAAAAAAABAAABABAAAACAAAE=","53":"b:YAAwABgAAgAAADSAAAAAAAABAAABABAAAACAAAE=","65":"b:YAAwABgAAgAAADSAAAAAAAABAAABABAAAACAAAE=","69":"b:YAAwABgAAgAAADSAAAAAAAABAAABABAAAACAAAE=","99":"b:YAAwABgAAgAAADSAAAAAAAABAAABABAAAACAAAE=","110":"b:YAAwABgAAgAAADSAAAAAAAABAAABABAAAACAAAE=","141":"b:YAAwABgAAgAAADSAAAAAAAABAAABABAAAACAAAE=","157":"b:YAAwABgAAgAAADSAAAAAAAABAAABABAAAACAAAE="},"packages/@n8n/backend-network/src/http/env-proxy-https-agent.ts":{"18":"b:8E/CsCzpAQT0PnSoCTACAEAIAIEAAAAAAAAAAAA=","20":"b:8E/CsCzpAQT0PnSoCTACAEAIAIEAAAAAAAAAAAA=","25":"b:8E/CsCzpAQT0PnSoCTACAEAIAIEAAAAAAAAAAAA="},"packages/@n8n/backend-network/src/http/env-proxy-router.ts":{"22":"b:8E/CsCzpHwT0PnToCTACAEAIAIEAAAAAAAAAAAA=","31":"b:8E/CsCzpHwT0PnToCTACAEAIAIEAAAAAAAAAAAA=","51":"b:8E/CsCzpHwT0PnToCTACAEAIAIEAAAAAAAAAAAA=","64":"b:8E/CsCzpHwT0PnToCTACAEAIAIEAAAAAAAAAAAA="},"packages/@n8n/backend-network/src/http/node-agents.ts":{"23":"b:8E/CACDpHwT0PnToCTACAEAIAAEAAAAAAAAAAAA=","88":"b:8E/CACDpHwT0PnToCTACAEAIAAEAAAAAAAAAAAA=","137":"b:8E/CACDpHwT0PnToCTACAEAIAAEAAAAAAAAAAAA="},"packages/@n8n/backend-network/src/http/outbound-http.ts":{"175":"b:8E/eBCDrHwT0P3ToCTACAEAIAAUAAAAAACAAAAA=","185":"b:8E/eBCDrHwT0P3ToCTACAEAIAAUAAAAAACAAAAA=","189":"b:8E/eBCDrHwT0P3ToCTACAEAIAAUAAAAAACAAAAA=","201":"b:8E/eBCDrHwT0P3ToCTACAEAIAAUAAAAAACAAAAA=","212":"b:8E/eBCDrHwT0P3ToCTACAEAIAAUAAAAAACAAAAA=","227":"b:8E/eBCDrHwT0P3ToCTACAEAIAAUAAAAAACAAAAA=","237":"b:8E/eBCDrHwT0P3ToCTACAEAIAAUAAAAAACAAAAA=","240":"b:8E/eBCDrHwT0P3ToCTACAEAIAAUAAAAAACAAAAA=","241":"b:8E/eBCDrHwT0P3ToCTACAEAIAAUAAAAAACAAAAA=","242":"b:8E/eBCDrHwT0P3ToCTACAEAIAAUAAAAAACAAAAA=","253":"b:8E/eBCDrHwT0P3ToCTACAEAIAAUAAAAAACAAAAA=","263":"b:8E/eBCDrHwT0P3ToCTACAEAIAAUAAAAAACAAAAA=","274":"b:8E/eBCDrHwT0P3ToCTACAEAIAAUAAAAAACAAAAA=","276":"b:8E/eBCDrHwT0P3ToCTACAEAIAAUAAAAAACAAAAA="},"packages/@n8n/backend-network/src/http/undici/transport.ts":{"110":[83,84,85,89,18,19,20,28,29,31,159,34,35],"125":[83,84,85,89,18,19,20,28,29,31,159,34,35],"154":[83,84,85,89,18,19,20,28,29,31,159,34,35],"162":[83,84,85,89,18,19,20,28,29,31,159,34,35],"176":[83,84,85,89,18,19,20,28,29,31,159,34,35],"189":[83,84,85,89,18,19,20,28,29,31,159,34,35],"197":[83,84,85,89,18,19,20,28,29,31,159,34,35],"214":[83,84,85,89,18,19,20,28,29,31,159,34,35],"223":[83,84,85,89,18,19,20,28,29,31,159,34,35],"229":[83,84,85,89,18,19,20,28,29,31,159,34,35],"231":[83,84,85,89,18,19,20,28,29,31,159,34,35],"235":[83,84,85,89,18,19,20,28,29,31,159,34,35],"237":[83,84,85,89,18,19,20,28,29,31,159,34,35],"246":[83,84,85,89,18,19,20,28,29,31,159,34,35],"264":[83,84,85,89,18,19,20,28,29,31,159,34,35],"267":[83,84,85,89,18,19,20,28,29,31,159,34,35],"271":[83,84,85,89,18,19,20,28,29,31,159,34,35],"278":[83,84,85,89,18,19,20,28,29,31,159,34,35],"298":[83,84,85,89,18,19,20,28,29,31,159,34,35],"301":[83,84,85,89,18,19,20,28,29,31,159,34,35],"305":[83,84,85,89,18,19,20,28,29,31,159,34,35],"306":[83,84,85,89,18,19,20,28,29,31,159,34,35],"329":[83,84,85,89,18,19,20,28,29,31,159,34,35],"340":[83,84,85,89,18,19,20,28,29,31,159,34,35],"362":[83,84,85,89,18,19,20,28,29,31,159,34,35],"371":[83,84,85,89,18,19,20,28,29,31,159,34,35],"377":[83,84,85,89,18,19,20,28,29,31,159,34,35],"391":[83,84,85,89,18,19,20,28,29,31,159,34,35],"410":[83,84,85,89,18,19,20,28,29,31,159,34,35]},"packages/@n8n/backend-network/src/proxy/index.ts":{"20":[84,85,18,19,20,109]},"packages/@n8n/backend-network/src/proxy/proxied-agents.ts":{"37":"b:AAwAsAwAHgAAADBAAAAAAAAAAIQAAAAAAAAAAAA=","38":"b:AAwAsAwAHgAAADBAAAAAAAAAAIQAAAAAAAAAAAA=","41":"b:AAwAsAwAHgAAADBAAAAAAAAAAIQAAAAAAAAAAAA=","42":"b:AAwAsAwAHgAAADBAAAAAAAAAAIQAAAAAAAAAAAA=","45":"b:AAwAsAwAHgAAADBAAAAAAAAAAIQAAAAAAAAAAAA=","49":"b:AAwAsAwAHgAAADBAAAAAAAAAAIQAAAAAAAAAAAA=","56":"b:AAwAsAwAHgAAADBAAAAAAAAAAIQAAAAAAAAAAAA=","61":"b:AAwAsAwAHgAAADBAAAAAAAAAAIQAAAAAAAAAAAA=","73":"b:AAwAsAwAHgAAADBAAAAAAAAAAIQAAAAAAAAAAAA=","87":"b:AAwAsAwAHgAAADBAAAAAAAAAAIQAAAAAAAAAAAA="},"packages/@n8n/backend-network/src/proxy/proxy-resolution.ts":{"20":[84,85,18,19,20,109],"32":[84,85,18,19,20,109],"44":[84,85,18,19,20,109],"66":[84,85,18,19,20,109],"81":[84,85,18,19,20,109],"89":[84,85,18,19,20,109]},"packages/@n8n/backend-network/src/ssrf/index.ts":{"1":[84,85,18,19,20],"3":[84,85,18,19,20]},"packages/@n8n/backend-services/src/credentials/credentials-finder.service.ts":{"38":"b:9m/+mCz5AQD3fnwoCTBAVHQKASkAMAAACAAAYAA=","46":"b:9m/+mCz5AQD3fnwoCTBAVHQKASkAMAAACAAAYAA=","50":"b:9m/+mCz5AQD3fnwoCTBAVHQKASkAMAAACAAAYAA=","55":"b:9m/+mCz5AQD3fnwoCTBAVHQKASkAMAAACAAAYAA=","64":"b:9m/+mCz5AQD3fnwoCTBAVHQKASkAMAAACAAAYAA=","87":"b:9m/+mCz5AQD3fnwoCTBAVHQKASkAMAAACAAAYAA=","89":"b:9m/+mCz5AQD3fnwoCTBAVHQKASkAMAAACAAAYAA=","97":"b:9m/+mCz5AQD3fnwoCTBAVHQKASkAMAAACAAAYAA=","106":"b:9m/+mCz5AQD3fnwoCTBAVHQKASkAMAAACAAAYAA=","113":"b:9m/+mCz5AQD3fnwoCTBAVHQKASkAMAAACAAAYAA=","123":"b:9m/+mCz5AQD3fnwoCTBAVHQKASkAMAAACAAAYAA=","140":"b:9m/+mCz5AQD3fnwoCTBAVHQKASkAMAAACAAAYAA=","145":"b:9m/+mCz5AQD3fnwoCTBAVHQKASkAMAAACAAAYAA=","147":"b:9m/+mCz5AQD3fnwoCTBAVHQKASkAMAAACAAAYAA=","149":"b:9m/+mCz5AQD3fnwoCTBAVHQKASkAMAAACAAAYAA=","161":"b:9m/+mCz5AQD3fnwoCTBAVHQKASkAMAAACAAAYAA=","181":"b:9m/+mCz5AQD3fnwoCTBAVHQKASkAMAAACAAAYAA=","222":"b:9m/+mCz5AQD3fnwoCTBAVHQKASkAMAAACAAAYAA=","240":"b:9m/+mCz5AQD3fnwoCTBAVHQKASkAMAAACAAAYAA=","242":"b:9m/+mCz5AQD3fnwoCTBAVHQKASkAMAAACAAAYAA=","276":"b:9m/+mCz5AQD3fnwoCTBAVHQKASkAMAAACAAAYAA=","293":"b:9m/+mCz5AQD3fnwoCTBAVHQKASkAMAAACAAAYAA=","305":"b:9m/+mCz5AQD3fnwoCTBAVHQKASkAMAAACAAAYAA=","314":"b:9m/+mCz5AQD3fnwoCTBAVHQKASkAMAAACAAAYAA=","321":"b:9m/+mCz5AQD3fnwoCTBAVHQKASkAMAAACAAAYAA=","323":"b:9m/+mCz5AQD3fnwoCTBAVHQKASkAMAAACAAAYAA=","334":"b:9m/+mCz5AQD3fnwoCTBAVHQKASkAMAAACAAAYAA=","373":"b:9m/+mCz5AQD3fnwoCTBAVHQKASkAMAAACAAAYAA=","385":"b:9m/+mCz5AQD3fnwoCTBAVHQKASkAMAAACAAAYAA=","393":"b:9m/+mCz5AQD3fnwoCTBAVHQKASkAMAAACAAAYAA="},"packages/@n8n/backend-services/src/services/role-cache.service.ts":{"38":"b:ArAJlwy8vqkxghpuqImASiCCAAgAEAAAAAAAoAA=","47":"b:ArAJlwy8vqkxghpuqImASiCCAAgAEAAAAAAAoAA=","55":"b:ArAJlwy8vqkxghpuqImASiCCAAgAEAAAAAAAoAA=","69":"b:ArAJlwy8vqkxghpuqImASiCCAAgAEAAAAAAAoAA=","78":"b:ArAJlwy8vqkxghpuqImASiCCAAgAEAAAAAAAoAA=","94":"b:ArAJlwy8vqkxghpuqImASiCCAAgAEAAAAAAAoAA=","106":"b:ArAJlwy8vqkxghpuqImASiCCAAgAEAAAAAAAoAA=","113":"b:ArAJlwy8vqkxghpuqImASiCCAAgAEAAAAAAAoAA="},"packages/@n8n/config/src/configs/ai.config.ts":{"6":[84,85],"56":[84,85]},"packages/@n8n/db/src/entities/index.ts":{"12":"b:ACaeAAAxABAHYDwIACABBCAAAQAAIAABQAAAYAA=","17":"b:ACaeAAAxABAHYDwIACABBCAAAQAAIAABQAAAYAA=","33":"b:ACaeAAAxABAHYDwIACABBCAAAQAAIAABQAAAYAA=","34":"b:ACaeAAAxABAHYDwIACABBCAAAQAAIAABQAAAYAA=","46":"b:ACaeAAAxABAHYDwIACABBCAAAQAAIAABQAAAYAA=","49":"b:ACaeAAAxABAHYDwIACABBCAAAQAAIAABQAAAYAA=","53":"b:ACaeAAAxABAHYDwIACABBCAAAQAAIAABQAAAYAA=","62":"b:ACaeAAAxABAHYDwIACABBCAAAQAAIAABQAAAYAA=","70":"b:ACaeAAAxABAHYDwIACABBCAAAQAAIAABQAAAYAA=","73":"b:ACaeAAAxABAHYDwIACABBCAAAQAAIAABQAAAYAA=","77":"b:ACaeAAAxABAHYDwIACABBCAAAQAAIAABQAAAYAA=","79":"b:ACaeAAAxABAHYDwIACABBCAAAQAAIAABQAAAYAA=","82":"b:ACaeAAAxABAHYDwIACABBCAAAQAAIAABQAAAYAA=","83":"b:ACaeAAAxABAHYDwIACABBCAAAQAAIAABQAAAYAA=","88":"b:ACaeAAAxABAHYDwIACABBCAAAQAAIAABQAAAYAA="},"packages/@n8n/db/src/entities/user.ts":{"60":"b:9k+CkCypAAD0PnQqCRAAQEAKAAEAAAAAAAAAAAA=","84":"b:9k+CkCypAAD0PnQqCRAAQEAKAAEAAAAAAAAAAAA=","115":"b:9k+CkCypAAD0PnQqCRAAQEAKAAEAAAAAAAAAAAA=","117":"b:9k+CkCypAAD0PnQqCRAAQEAKAAEAAAAAAAAAAAA=","124":"b:9k+CkCypAAD0PnQqCRAAQEAKAAEAAAAAAAAAAAA=","129":"b:9k+CkCypAAD0PnQqCRAAQEAKAAEAAAAAAAAAAAA=","139":"b:9k+CkCypAAD0PnQqCRAAQEAKAAEAAAAAAAAAAAA="},"packages/@n8n/db/src/repositories/credential-access.repository.ts":{"18":"b:9m/+mCz5AQD3fnwoCTBAVHQKASEAMAAAAAAAYAA=","22":"b:9m/+mCz5AQD3fnwoCTBAVHQKASEAMAAAAAAAYAA=","26":"b:9m/+mCz5AQD3fnwoCTBAVHQKASEAMAAAAAAAYAA=","37":"b:9m/+mCz5AQD3fnwoCTBAVHQKASEAMAAAAAAAYAA=","48":"b:9m/+mCz5AQD3fnwoCTBAVHQKASEAMAAAAAAAYAA=","62":"b:9m/+mCz5AQD3fnwoCTBAVHQKASEAMAAAAAAAYAA=","72":"b:9m/+mCz5AQD3fnwoCTBAVHQKASEAMAAAAAAAYAA=","99":"b:9m/+mCz5AQD3fnwoCTBAVHQKASEAMAAAAAAAYAA=","127":"b:9m/+mCz5AQD3fnwoCTBAVHQKASEAMAAAAAAAYAA=","149":"b:9m/+mCz5AQD3fnwoCTBAVHQKASEAMAAAAAAAYAA=","152":"b:9m/+mCz5AQD3fnwoCTBAVHQKASEAMAAAAAAAYAA=","183":"b:9m/+mCz5AQD3fnwoCTBAVHQKASEAMAAAAAAAYAA=","200":"b:9m/+mCz5AQD3fnwoCTBAVHQKASEAMAAAAAAAYAA=","205":"b:9m/+mCz5AQD3fnwoCTBAVHQKASEAMAAAAAAAYAA=","214":"b:9m/+mCz5AQD3fnwoCTBAVHQKASEAMAAAAAAAYAA=","217":"b:9m/+mCz5AQD3fnwoCTBAVHQKASEAMAAAAAAAYAA=","228":"b:9m/+mCz5AQD3fnwoCTBAVHQKASEAMAAAAAAAYAA=","244":"b:9m/+mCz5AQD3fnwoCTBAVHQKASEAMAAAAAAAYAA=","261":"b:9m/+mCz5AQD3fnwoCTBAVHQKASEAMAAAAAAAYAA="},"packages/@n8n/db/src/repositories/credential-dependency.repository.ts":{"25":"b:ACCeAAAxABAHYDwIACAABDAAASAAIAAAAAAAYAA=","64":"b:ACCeAAAxABAHYDwIACAABDAAASAAIAAAAAAAYAA=","68":"b:ACCeAAAxABAHYDwIACAABDAAASAAIAAAAAAAYAA=","77":"b:ACCeAAAxABAHYDwIACAABDAAASAAIAAAAAAAYAA=","80":"b:ACCeAAAxABAHYDwIACAABDAAASAAIAAAAAAAYAA=","95":"b:ACCeAAAxABAHYDwIACAABDAAASAAIAAAAAAAYAA=","105":"b:ACCeAAAxABAHYDwIACAABDAAASAAIAAAAAAAYAA=","118":"b:ACCeAAAxABAHYDwIACAABDAAASAAIAAAAAAAYAA=","119":"b:ACCeAAAxABAHYDwIACAABDAAASAAIAAAAAAAYAA=","120":"b:ACCeAAAxABAHYDwIACAABDAAASAAIAAAAAAAYAA=","140":"b:ACCeAAAxABAHYDwIACAABDAAASAAIAAAAAAAYAA=","151":"b:ACCeAAAxABAHYDwIACAABDAAASAAIAAAAAAAYAA="},"packages/@n8n/db/src/repositories/execution-metadata.repository.ts":{"8":[9,84,85,10,18,19,20,184,198]},"packages/@n8n/db/src/repositories/secrets-provider-connection.repository.ee.ts":{"9":"b:gCC+AoAxABAHYD4ICCAAFjAAASAAIIAAAAAAYAA=","13":"b:gCC+AoAxABAHYD4ICCAAFjAAASAAIIAAAAAAYAA=","17":"b:gCC+AoAxABAHYD4ICCAAFjAAASAAIIAAAAAAYAA=","27":"b:gCC+AoAxABAHYD4ICCAAFjAAASAAIIAAAAAAYAA=","38":"b:gCC+AoAxABAHYD4ICCAAFjAAASAAIIAAAAAAYAA=","41":"b:gCC+AoAxABAHYD4ICCAAFjAAASAAIIAAAAAAYAA=","60":"b:gCC+AoAxABAHYD4ICCAAFjAAASAAIIAAAAAAYAA=","94":"b:gCC+AoAxABAHYD4ICCAAFjAAASAAIIAAAAAAYAA=","124":"b:gCC+AoAxABAHYD4ICCAAFjAAASAAIIAAAAAAYAA=","130":"b:gCC+AoAxABAHYD4ICCAAFjAAASAAIIAAAAAAYAA=","145":"b:gCC+AoAxABAHYD4ICCAAFjAAASAAIIAAAAAAYAA=","169":"b:gCC+AoAxABAHYD4ICCAAFjAAASAAIIAAAAAAYAA=","187":"b:gCC+AoAxABAHYD4ICCAAFjAAASAAIIAAAAAAYAA=","195":"b:gCC+AoAxABAHYD4ICCAAFjAAASAAIIAAAAAAYAA=","205":"b:gCC+AoAxABAHYD4ICCAAFjAAASAAIIAAAAAAYAA=","215":"b:gCC+AoAxABAHYD4ICCAAFjAAASAAIIAAAAAAYAA=","227":"b:gCC+AoAxABAHYD4ICCAAFjAAASAAIIAAAAAAYAA="},"packages/@n8n/db/src/repositories/shared-credentials.repository.ts":{"13":"b:gCCfBACxABAHYDwKCCAABDAAAQgAIAAABAAAYAA=","17":"b:gCCfBACxABAHYDwKCCAABDAAAQgAIAAABAAAYAA=","28":"b:gCCfBACxABAHYDwKCCAABDAAAQgAIAAABAAAYAA=","36":"b:gCCfBACxABAHYDwKCCAABDAAAQgAIAAABAAAYAA=","39":"b:gCCfBACxABAHYDwKCCAABDAAAQgAIAAABAAAYAA=","51":"b:gCCfBACxABAHYDwKCCAABDAAAQgAIAAABAAAYAA=","61":"b:gCCfBACxABAHYDwKCCAABDAAAQgAIAAABAAAYAA=","66":"b:gCCfBACxABAHYDwKCCAABDAAAQgAIAAABAAAYAA=","77":"b:gCCfBACxABAHYDwKCCAABDAAAQgAIAAABAAAYAA=","86":"b:gCCfBACxABAHYDwKCCAABDAAAQgAIAAABAAAYAA=","98":"b:gCCfBACxABAHYDwKCCAABDAAAQgAIAAABAAAYAA=","101":"b:gCCfBACxABAHYDwKCCAABDAAAQgAIAAABAAAYAA=","110":"b:gCCfBACxABAHYDwKCCAABDAAAQgAIAAABAAAYAA=","119":"b:gCCfBACxABAHYDwKCCAABDAAAQgAIAAABAAAYAA=","124":"b:gCCfBACxABAHYDwKCCAABDAAAQgAIAAABAAAYAA=","137":"b:gCCfBACxABAHYDwKCCAABDAAAQgAIAAABAAAYAA=","153":"b:gCCfBACxABAHYDwKCCAABDAAAQgAIAAABAAAYAA=","181":"b:gCCfBACxABAHYDwKCCAABDAAAQgAIAAABAAAYAA=","190":"b:gCCfBACxABAHYDwKCCAABDAAAQgAIAAABAAAYAA=","191":"b:gCCfBACxABAHYDwKCCAABDAAAQgAIAAABAAAYAA=","206":"b:gCCfBACxABAHYDwKCCAABDAAAQgAIAAABAAAYAA=","207":"b:gCCfBACxABAHYDwKCCAABDAAAQgAIAAABAAAYAA=","217":"b:gCCfBACxABAHYDwKCCAABDAAAQgAIAAABAAAYAA="},"packages/@n8n/db/src/repositories/workflow-history.repository.ts":{"20":"b:wAECEIwkAAD2KFgAAREAROgKAAAAIAIAAACCAAA=","24":"b:wAECEIwkAAD2KFgAAREAROgKAAAAIAIAAACCAAA=","39":"b:wAECEIwkAAD2KFgAAREAROgKAAAAIAIAAACCAAA=","62":"b:wAECEIwkAAD2KFgAAREAROgKAAAAIAIAAACCAAA=","66":"b:wAECEIwkAAD2KFgAAREAROgKAAAAIAIAAACCAAA=","83":"b:wAECEIwkAAD2KFgAAREAROgKAAAAIAIAAACCAAA=","105":"b:wAECEIwkAAD2KFgAAREAROgKAAAAIAIAAACCAAA=","159":"b:wAECEIwkAAD2KFgAAREAROgKAAAAIAIAAACCAAA=","160":"b:wAECEIwkAAD2KFgAAREAROgKAAAAIAIAAACCAAA=","164":"b:wAECEIwkAAD2KFgAAREAROgKAAAAIAIAAACCAAA=","178":"b:wAECEIwkAAD2KFgAAREAROgKAAAAIAIAAACCAAA=","184":"b:wAECEIwkAAD2KFgAAREAROgKAAAAIAIAAACCAAA=","220":"b:wAECEIwkAAD2KFgAAREAROgKAAAAIAIAAACCAAA=","235":"b:wAECEIwkAAD2KFgAAREAROgKAAAAIAIAAACCAAA="},"packages/@n8n/db/src/repositories/workflow-publication-outbox.repository.ts":{"24":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","36":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","44":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","66":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","72":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","82":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","94":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","113":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","139":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","153":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","182":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","195":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","233":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","265":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","287":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","313":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","334":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","363":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","375":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","383":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","425":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","428":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","446":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","453":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","484":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","502":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","517":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","533":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","553":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","573":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","598":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","607":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","629":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","638":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","650":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","660":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","672":"b:8P+ilGztviH1vndoiZmASEAKAAEAEAAAAAAgoAA="},"packages/@n8n/db/src/repositories/workflow-publication-trigger-status.repository.ts":{"30":"b:8P+ilCztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","35":"b:8P+ilCztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","40":"b:8P+ilCztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","45":"b:8P+ilCztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","50":"b:8P+ilCztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","65":"b:8P+ilCztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","70":"b:8P+ilCztviH1vndoiZmASEAKAAEAEAAAAAAgoAA=","97":"b:8P+ilCztviH1vndoiZmASEAKAAEAEAAAAAAgoAA="},"packages/@n8n/db/src/repositories/workflow-publish-history.repository.ts":{"14":"b:EPYglAzlviG1gldgDYmATGwKAUAAEgAAAAgioAA=","18":"b:EPYglAzlviG1gldgDYmATGwKAUAAEgAAAAgioAA=","26":"b:EPYglAzlviG1gldgDYmATGwKAUAAEgAAAAgioAA=","48":"b:EPYglAzlviG1gldgDYmATGwKAUAAEgAAAAgioAA=","70":"b:EPYglAzlviG1gldgDYmATGwKAUAAEgAAAAgioAA=","94":"b:EPYglAzlviG1gldgDYmATGwKAUAAEgAAAAgioAA=","115":"b:EPYglAzlviG1gldgDYmATGwKAUAAEgAAAAgioAA=","132":"b:EPYglAzlviG1gldgDYmATGwKAUAAEgAAAAgioAA=","153":"b:EPYglAzlviG1gldgDYmATGwKAUAAEgAAAAgioAA="},"packages/@n8n/db/src/subscribers/user-subscriber.ts":{"12":"b:ABAAACCEvqFwIPBAAIkAACCKCAAAgABAAgAgkAA=","15":"b:ABAAACCEvqFwIPBAAIkAACCKCAAAgABAAgAgkAA=","19":"b:ABAAACCEvqFwIPBAAIkAACCKCAAAgABAAgAgkAA=","24":"b:ABAAACCEvqFwIPBAAIkAACCKCAAAgABAAgAgkAA="},"packages/@n8n/errors/src/index.ts":{"4":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","8":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","9":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","10":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","11":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","13":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","14":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","15":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","16":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","17":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","18":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","19":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","20":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE="},"packages/@n8n/errors/src/operational.error.ts":{"15":"b:IAAwAAAAAAAGQFgAEAAAEAABAAEAAAAAAAACIAA="},"packages/@n8n/expression-runtime/src/bridge/host-functions.ts":{"17":"b:ELYcCAAAACAAEHgAwQGQEQQRAEAAAgAAAIAmgAQ=","34":"b:ELYcCAAAACAAEHgAwQGQEQQRAEAAAgAAAIAmgAQ=","37":"b:ELYcCAAAACAAEHgAwQGQEQQRAEAAAgAAAIAmgAQ=","56":"b:ELYcCAAAACAAEHgAwQGQEQQRAEAAAgAAAIAmgAQ=","88":"b:ELYcCAAAACAAEHgAwQGQEQQRAEAAAgAAAIAmgAQ=","154":"b:ELYcCAAAACAAEHgAwQGQEQQRAEAAAgAAAIAmgAQ=","249":"b:ELYcCAAAACAAEHgAwQGQEQQRAEAAAgAAAIAmgAQ="},"packages/@n8n/expression-runtime/src/runtime/luxon-transfer.ts":{"49":"b:ELYcCAAAACAAEHgAQQGAEQQRAEAAAAEAAIAEgAA=","53":"b:ELYcCAAAACAAEHgAQQGAEQQRAEAAAAEAAIAEgAA=","57":"b:ELYcCAAAACAAEHgAQQGAEQQRAEAAAAEAAIAEgAA=","61":"b:ELYcCAAAACAAEHgAQQGAEQQRAEAAAAEAAIAEgAA=","65":"b:ELYcCAAAACAAEDgAQQGAAQQRAEAAAAEAAIAEgAA=","83":"b:ELYcCAAAACAAEDgAQQGAAQQRAEAAAAEAAIAEgAA=","94":"b:ELYcCAAAACAAEDgAQQGAAQQRAEAAAAEAAIAEgAA=","139":"b:ELYcCAAAACAAEHgAQQGAEQQRAEAAAAEAAIAEgAA=","150":"b:ELYcCAAAACAAEHgAQQGAEQQRAEAAAAEAAIAEgAA=","158":"b:ELYcCAAAACAAEHgAQQGAEQQRAEAAAAEAAIAEgAA=","160":[86,124],"161":"b:ELYcCAAAACAAEDgAQQGAAQQRAEAAAAEAAIAEgAA=","166":"b:ELYcCAAAACAAEHgAQQGAEQQRAEAAAAEAAIAEgAA=","179":"b:ELYcCAAAACAAEHgAQQGAEQQRAEAAAAEAAIAEgAA=","187":"b:ELYcCAAAACAAEHgAQQGAEQQRAEAAAAEAAIAEgAA=","196":"b:ELYcCAAAACAAEHgAQQGAEQQRAEAAAAEAAIAEgAA=","208":"b:ELYcCAAAACAAEDgAQQGAAQQRAEAAAAEAAIAEgAA=","221":"b:ELYcCAAAACAAEDgAQQGAAQQRAEAAAAEAAIAEgAA=","227":"b:ELYcCAAAACAAEDgAQQGAAQQRAEAAAAEAAIAEgAA="},"packages/@n8n/expression-runtime/src/runtime/transfer.ts":{"64":"b:ELYcCAAAACAAEHgAwQGAEQQRCEAAAgEAAIAEgAA=","70":"b:ELYcCAAAACAAEHgAwQGAEQQRCEAAAgEAAIAEgAA=","75":"b:ELYcCAAAACAAEDgAwQGAAQQRCEAAAgEAAIAEgAA=","79":"b:ELYcCAAAACAAEHgAwQGAEQQRCEAAAgEAAIAEgAA=","87":"b:ELYcCAAAACAAEHgAwQGAEQQRCEAAAgEAAIAEgAA=","92":"b:ELYcCAAAACAAEHgAwQGAEQQRCEAAAgEAAIAEgAA=","98":"b:ELYcCAAAACAAEDgAwQGAAQQRCEAAAgEAAIAEgAA=","111":"b:ELYcCAAAACAAEDgAwQGAAQQRCEAAAgEAAIAEgAA=","126":"b:ELYcCAAAACAAEDgAwQGAAQQRCEAAAgEAAIAEgAA=","134":"b:ELYcCAAAACAAEDgAwQGAAQQRCEAAAgEAAIAEgAA=","164":"b:ELYcCAAAACAAEDgAwQGAAQQRCEAAAgEAAIAEgAA=","195":"b:ELYcCAAAACAAEDgAwQGAAQQRCEAAAgEAAIAEgAA="},"packages/@n8n/instance-ai/src/runtime/background-task-manager.ts":{"125":"b:oACT8x2oANzAOBQ4CRAAAgCAoI0AAAAAAAAAABA=","135":"b:oACT8x2oANzAOBQ4CRAAAgCAoI0AAAAAAAAAABA=","139":"b:oACT8x2oANzAOBQ4CRAAAgCAoI0AAAAAAAAAABA=","166":"b:oACT8x2oANzAOBQ4CRAAAgCAoI0AAAAAAAAAABA=","167":"b:oACT8x2oANzAOBQ4CRAAAgCAoI0AAAAAAAAAABA=","170":"b:oACT8x2oANzAOBQ4CRAAAgCAoI0AAAAAAAAAABA=","172":"b:oACT8x2oANzAOBQ4CRAAAgCAoI0AAAAAAAAAABA=","177":"b:oACT8x2oANzAOBQ4CRAAAgCAoI0AAAAAAAAAABA=","178":"b:oACT8x2oANzAOBQ4CRAAAgCAoI0AAAAAAAAAABA=","182":"b:oACT8x2oANzAOBQ4CRAAAgCAoI0AAAAAAAAAABA=","196":"b:oACT8x2oANzAOBQ4CRAAAgCAoI0AAAAAAAAAABA=","201":"b:oACT8x2oANzAOBQ4CRAAAgCAoI0AAAAAAAAAABA=","208":"b:oACT8x2oANzAOBQ4CRAAAgCAoI0AAAAAAAAAABA=","226":"b:oACT8x2oANzAOBQ4CRAAAgCAoI0AAAAAAAAAABA=","238":"b:oACT8x2oANzAOBQ4CRAAAgCAoI0AAAAAAAAAABA=","252":"b:oACT8x2oANzAOBQ4CRAAAgCAoI0AAAAAAAAAABA=","265":"b:oACT8x2oANzAOBQ4CRAAAgCAoI0AAAAAAAAAABA=","272":"b:oACT8x2oANzAOBQ4CRAAAgCAoI0AAAAAAAAAABA=","294":"b:oACT8x2oANzAOBQ4CRAAAgCAoI0AAAAAAAAAABA=","354":"b:oACT8x2oANzAOBQ4CRAAAgCAoI0AAAAAAAAAABA=","371":"b:oACT8x2oANzAOBQ4CRAAAgCAoI0AAAAAAAAAABA=","375":"b:oACT8x2oANzAOBQ4CRAAAgCAoI0AAAAAAAAAABA=","381":"b:oACT8x2oANzAOBQ4CRAAAgCAoI0AAAAAAAAAABA=","382":"b:oACT8x2oANzAOBQ4CRAAAgCAoI0AAAAAAAAAABA=","426":"b:oACT8x2oANzAOBQ4CRAAAgCAoI0AAAAAAAAAABA=","452":"b:oACT8x2oANzAOBQ4CRAAAgCAoI0AAAAAAAAAABA="},"packages/@n8n/instance-ai/src/runtime/run-state-registry.ts":{"175":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","177":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","216":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","226":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","239":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","240":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","252":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","256":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","260":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","264":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","268":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","277":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","278":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","283":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","287":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","298":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","321":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","331":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","335":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","339":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","350":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","355":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","363":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","378":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","385":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","393":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","422":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","430":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","434":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","442":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","449":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","456":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","463":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","476":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","498":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","506":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","509":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","525":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","529":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","534":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","539":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","544":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","549":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","553":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","557":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","562":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","567":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","571":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","576":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","580":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","584":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","608":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","707":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","716":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","725":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","771":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","777":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA=","783":"b:oICT8xyoANzAOBQ4CRAAQgCAoI0AAAAAAAAAAAA="},"packages/@n8n/nodes-langchain/nodes/agents/Agent/Agent.node.ts":{"9":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/V1/AgentV1.node.ts":{"37":[84,13,18,19,20,23,37,181,70,137,139],"53":[84,13,18,19,20,23,37,181,70,137,139],"63":[84,13,18,19,20,23,37,181,70,137,139],"221":[84,13,18,19,20,23,37,181,70,137,139],"276":[84,13,18,19,20,23,37,181,70,137,139],"349":[84,13,18,19,20,23,37,181,70,137,139],"458":[84,13,18,19,20,23,37,181,70,137,139]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/V2/AgentV2.node.ts":{"24":[84,13,18,19,20,23,37,181,70,139],"134":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/V3/AgentV3.node.ts":{"28":[84,13,18,19,20,23,37,181,70,139],"144":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ConversationalAgent/execute.ts":{"16":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/OpenAiFunctionsAgent/execute.ts":{"15":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/PlanAndExecuteAgent/execute.ts":{"18":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ReActAgent/execute.ts":{"21":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/SqlAgent/execute.ts":{"25":[84,13,18,19,20,23,37,181,70,139],"28":[84,13,18,19,20,23,37,181,70,139],"29":[84,13,18,19,20,23,37,181,70,139],"31":[84,13,18,19,20,23,37,181,70,139],"37":[84,13,18,19,20,23,37,181,70,139],"54":[84,13,18,19,20,23,37,181,70,139],"67":[84,13,18,19,20,23,37,181,70,139],"156":[84,13,18,19,20,23,37,181,70,139],"162":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/SqlAgent/other/handlers/mysql.ts":{"4":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/SqlAgent/other/handlers/postgres.ts":{"6":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/SqlAgent/other/handlers/sqlite.ts":{"8":[84,13,18,19,20,23,37,181,70,139],"38":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V1/execute.ts":{"36":[84,13,18,19,20,23,37,181,70,137,139]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V2/description.ts":{"15":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V2/execute.ts":{"62":[84,13,18,19,20,23,37,181,70,139],"110":[84,13,18,19,20,23,37,181,70,139],"115":[84,13,18,19,20,23,37,181,70,139],"120":[84,13,18,19,20,23,37,181,70,139],"150":[84,13,18,19,20,23,37,181,70,139],"224":[84,13,18,19,20,23,37,181,70,139],"240":[84,13,18,19,20,23,37,181,70,139],"264":[84,13,18,19,20,23,37,181,70,139],"323":[84,13,18,19,20,23,37,181,70,139],"427":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/execute.ts":{"34":[84,13,18,19,20,23,37,181,70,139],"59":[84,13,18,19,20,23,37,181,70,139],"139":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/buildExecutionContext.ts":{"29":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/checkMaxIterations.ts":{"27":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/createAgentSequence.ts":{"25":[84,13,18,19,20,23,37,181,70,139],"73":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/executeBatch.ts":{"40":[84,13,18,19,20,23,37,181,70,139],"78":[84,13,18,19,20,23,37,181,70,139],"108":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/finalizeResult.ts":{"21":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/index.ts":{"11":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/prepareItemContext.ts":{"41":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/resolveSubAgentRequest.ts":{"25":[84,13,18,19,20,23,37,181,70,139],"40":[84,13,18,19,20,23,37,181,70,139],"49":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/runAgent.ts":{"32":[84,13,18,19,20,23,37,181,70,139],"42":[84,13,18,19,20,23,37,181,70,139],"43":[84,13,18,19,20,23,37,181,70,139],"72":[84,13,18,19,20,23,37,181,70,139],"85":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/common.ts":{"32":[84,13,18,19,20,23,37,181,70,137,139],"45":[84,13,18,19,20,23,37,181,70,137,139],"56":[84,13,18,19,20,23,37,181,70,137,139],"60":[84,13,18,19,20,23,37,181,70,137,139],"78":[84,13,18,19,20,23,37,181,70,137,139],"112":[84,13,18,19,20,23,37,181,70,137,139],"133":[84,13,18,19,20,23,37,181,70,137,139],"218":[84,13,18,19,20,23,37,181,70,137,139],"228":[84,13,18,19,20,23,37,181,70,137,139],"229":[84,13,18,19,20,23,37,181,70,137,139],"280":[84,13,18,19,20,23,37,181,70,137,139],"285":[84,13,18,19,20,23,37,181,70,137,139],"288":[84,13,18,19,20,23,37,181,70,137,139],"290":[84,13,18,19,20,23,37,181,70,137,139],"336":[84,13,18,19,20,23,37,181,70,137,139],"357":[84,13,18,19,20,23,37,181,70,137,139],"358":[84,13,18,19,20,23,37,181,70,137,139],"368":[84,13,18,19,20,23,37,181,70,137,139],"369":[84,13,18,19,20,23,37,181,70,137,139],"395":[84,13,18,19,20,23,37,181,70,137,139],"415":[84,13,18,19,20,23,37,181,70,137,139],"416":[84,13,18,19,20,23,37,181,70,137,139],"419":[84,13,18,19,20,23,37,181,70,137,139],"485":[84,13,18,19,20,23,37,181,70,137,139],"519":[84,13,18,19,20,23,37,181,70,137,139],"535":[84,13,18,19,20,23,37,181,70,137,139],"550":[84,13,18,19,20,23,37,181,70,137,139],"565":[84,13,18,19,20,23,37,181,70,137,139],"622":[84,13,18,19,20,23,37,181,70,137,139]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/utils.ts":{"18":[84,13,18,19,20,23,37,181,70,139],"24":[84,13,18,19,20,23,37,181,70,139],"41":[84,13,18,19,20,23,37,181,70,139],"47":[84,13,18,19,20,23,37,181,70,139],"50":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/utils.ts":{"11":[84,13,18,19,20,23,37,181,70,139],"23":[84,13,18,19,20,23,37,181,70,139],"26":[84,13,18,19,20,23,37,181,70,139],"86":[84,13,18,19,20,23,37,181,70,139],"89":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/nodes/llms/LMChatOpenAi/LmChatOpenAi.node.ts":{"76":[84,85,181,139],"753":[84,85,181,139]},"packages/@n8n/nodes-langchain/nodes/llms/LMChatOpenAi/common.ts":{"17":[84,85,181,139],"20":[84,85,181,139],"23":[84,85,181,139],"26":[84,85,181,139],"29":[84,85,181,139],"32":[84,85,181,139],"84":[84,85,181,139]},"packages/@n8n/nodes-langchain/nodes/llms/LMChatOpenAi/methods/loadModels.ts":{"10":[84,85,181,139],"30":[84,85,181,139],"35":[84,85,181,139],"36":[84,85,181,139]},"packages/@n8n/nodes-langchain/nodes/llms/shared/extra-body.ts":{"13":[84,85,181,139],"26":[84,85,181,139],"58":[84,85,181,139]},"packages/@n8n/nodes-langchain/nodes/memory/MemoryRedisChat/MemoryRedisChat.node.ts":{"26":[84,139],"114":[84,139],"152":[84,139],"182":[84,139]},"packages/@n8n/nodes-langchain/nodes/memory/descriptions.ts":{"28":[84,18,19,20,139,77],"63":[84,18,19,20,139,77]},"packages/@n8n/nodes-langchain/nodes/output_parser/OutputParserAutofixing/OutputParserAutofixing.node.ts":{"19":[84,13],"102":[84,13]},"packages/@n8n/nodes-langchain/nodes/tools/ToolCalculator/ToolCalculator.node.ts":{"15":[84],"21":[84],"55":[84],"61":[84]},"packages/@n8n/nodes-langchain/nodes/tools/ToolCode/ToolCode.node.ts":{"44":[84,125,221],"70":[84,125,221],"90":[84,125,221],"178":[84,125,221],"331":[84,125,221],"336":[84,125,221]},"packages/@n8n/nodes-langchain/nodes/tools/ToolWikipedia/ToolWikipedia.node.ts":{"17":[84,77],"25":[84,77],"58":[84,77],"64":[84,77]},"packages/@n8n/nodes-langchain/nodes/trigger/ChatTrigger/ChatTrigger.node.ts":{"50":"b:AAacACAAAAAAADAAAAAAAAAKAAAAAEABQAAAAAA=","66":"b:AAacACAAAAAAADAAAAAAAAAKAAAAAEABQAAAAAA=","70":"b:AAacACAAAAAAADAAAAAAAAAKAAAAAEABQAAAAAA=","293":"b:AAacACAAAAAAADAAAAAAAAAKAAAAAEABQAAAAAA=","853":"b:AAacACAAAAAAADAAAAAAAAAKAAAAAEABQAAAAAA=","916":"b:AAacACAAAAAAADAAAAAAAAAKAAAAAEABQAAAAAA=","1134":"b:AAacACAAAAAAADAAAAAAAAAKAAAAAEABQAAAAAA=","1135":"b:AAacACAAAAAAADAAAAAAAAAKAAAAAEABQAAAAAA="},"packages/@n8n/nodes-langchain/nodes/trigger/ChatTrigger/GenericFunctions.ts":{"17":[9,84,85,10,18,19,20,23,37,182,184,139],"26":[9,84,85,10,18,19,20,23,37,182,184,139],"30":[9,84,85,10,18,19,20,23,37,182,184,139],"46":[9,84,85,10,18,19,20,23,37,182,184,139],"64":[9,84,85,10,18,19,20,23,37,182,184,139],"158":[9,84,85,10,18,19,20,23,37,182,184,139],"270":[9,84,85,10,18,19,20,23,37,182,184,139],"305":[9,84,85,10,18,19,20,23,37,182,184,139],"362":[9,84,85,10,18,19,20,23,37,182,184,139]},"packages/@n8n/nodes-langchain/nodes/trigger/ChatTrigger/connect-panel.ts":{"6":[9,84,85,10,18,19,20,23,37,182,184,139],"13":[9,84,85,10,18,19,20,23,37,182,184,139],"17":[9,84,85,10,18,19,20,23,37,182,184,139],"18":[9,84,85,10,18,19,20,23,37,182,184,139],"32":[9,84,85,10,18,19,20,23,37,182,184,139],"49":[9,84,85,10,18,19,20,23,37,182,184,139]},"packages/@n8n/nodes-langchain/nodes/trigger/ChatTrigger/error.ts":{"4":[9,84,85,10,18,19,20,23,37,182,184,139]},"packages/@n8n/nodes-langchain/nodes/trigger/ChatTrigger/shell.ts":{"21":[9,84,85,10,18,19,20,23,37,182,184,139],"27":[9,84,85,10,18,19,20,23,37,182,184,139],"45":[9,84,85,10,18,19,20,23,37,182,184,139],"78":[9,84,85,10,18,19,20,23,37,182,184,139],"88":[9,84,85,10,18,19,20,23,37,182,184,139],"104":[9,84,85,10,18,19,20,23,37,182,184,139],"122":[9,84,85,10,18,19,20,23,37,182,184,139],"134":[9,84,85,10,18,19,20,23,37,182,184,139],"144":[9,84,85,10,18,19,20,23,37,182,184,139],"150":[9,84,85,10,18,19,20,23,37,182,184,139],"164":[9,84,85,10,18,19,20,23,37,182,184,139],"168":[9,84,85,10,18,19,20,23,37,182,184,139],"180":[9,84,85,10,18,19,20,23,37,182,184,139],"184":[9,84,85,10,18,19,20,23,37,182,184,139],"197":[9,84,85,10,18,19,20,23,37,182,184,139]},"packages/@n8n/nodes-langchain/nodes/trigger/ChatTrigger/templates.ts":{"23":[9,84,85,10,18,19,20,23,37,182,184,139],"24":[9,84,85,10,18,19,20,23,37,182,184,139],"27":[9,84,85,10,18,19,20,23,37,182,184,139],"43":[9,84,85,10,18,19,20,23,37,182,184,139],"48":[9,84,85,10,18,19,20,23,37,182,184,139],"49":[9,84,85,10,18,19,20,23,37,182,184,139],"52":[9,84,85,10,18,19,20,23,37,182,184,139],"78":[9,84,85,10,18,19,20,23,37,182,184,139],"116":[9,84,85,10,18,19,20,23,37,182,184,139],"336":[9,84,85,10,18,19,20,23,37,182,184,139]},"packages/@n8n/nodes-langchain/nodes/trigger/ChatTrigger/types.ts":{"62":"b:AAacACAAAAAAADAAAAAAAAAKAAAAAEABQAAAAAA=","66":"b:AAacACAAAAAAADAAAAAAAAAKAAAAAEABQAAAAAA="},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/helpers/credentials.ts":{"16":[84,85,181,69,139]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/helpers/error-handling.ts":{"11":[84,85,181,69,139],"15":[84,85,181,69,139],"19":[84,85,181,69,139],"36":[84,85,181,69,139]},"packages/@n8n/nodes-langchain/utils/N8nTool.ts":{"11":"b:ACScACAAAABgIDAAAAAAIAAIAAAAACAAAAAAIAA=","25":"b:ACScACAAAABgIDAAAAAAIAAIAAAAACAAAAAAIAA=","28":"b:ACScACAAAABgIDAAAAAAIAAIAAAAACAAAAAAIAA=","33":"b:ACScACAAAABgIDAAAAAAIAAIAAAAACAAAAAAIAA=","50":"b:ACScACAAAABgIDAAAAAAIAAIAAAAACAAAAAAIAA=","57":"b:ACScACAAAABgIDAAAAAAIAAIAAAAACAAAAAAIAA=","62":"b:ACScACAAAABgIDAAAAAAIAAIAAAAACAAAAAAIAA="},"packages/@n8n/nodes-langchain/utils/agent-execution/buildResponseMetadata.ts":{"17":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/utils/agent-execution/buildSteps.ts":{"36":[84,13,18,19,20,23,37,181,70,139],"93":[84,13,18,19,20,23,37,181,70,139],"141":[84,13,18,19,20,23,37,181,70,139],"165":[84,13,18,19,20,23,37,181,70,139],"206":[84,13,18,19,20,23,37,181,70,139],"217":[84,13,18,19,20,23,37,181,70,139],"224":[84,13,18,19,20,23,37,181,70,139],"236":[84,13,18,19,20,23,37,181,70,139],"288":[84,13,18,19,20,23,37,181,70,139],"292":[84,13,18,19,20,23,37,181,70,139],"299":[84,13,18,19,20,23,37,181,70,139],"312":[84,13,18,19,20,23,37,181,70,139],"316":[84,13,18,19,20,23,37,181,70,139],"345":[84,13,18,19,20,23,37,181,70,139],"367":[84,13,18,19,20,23,37,181,70,139],"389":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/utils/agent-execution/createEngineRequests.ts":{"16":[84,13,18,19,20,23,37,181,70,139],"25":[84,13,18,19,20,23,37,181,70,139],"43":[84,13,18,19,20,23,37,181,70,139],"76":[84,13,18,19,20,23,37,181,70,139],"150":[84,13,18,19,20,23,37,181,70,139],"157":[84,13,18,19,20,23,37,181,70,139],"214":[84,13,18,19,20,23,37,181,70,139],"222":[84,13,18,19,20,23,37,181,70,139],"225":[84,13,18,19,20,23,37,181,70,139],"230":[84,13,18,19,20,23,37,181,70,139],"232":[84,13,18,19,20,23,37,181,70,139],"272":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/utils/agent-execution/executeEngineAction.ts":{"17":[84,13,18,19,20,23,37,181,70,139],"22":[84,13,18,19,20,23,37,181,70,139],"47":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/utils/agent-execution/index.ts":{"13":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/utils/agent-execution/memoryManagement.ts":{"25":[84,13,18,19,20,23,37,181,70,139],"81":[84,13,18,19,20,23,37,181,70,139],"148":[84,13,18,19,20,23,37,181,70,139],"151":[84,13,18,19,20,23,37,181,70,139],"164":[84,13,18,19,20,23,37,181,70,139],"242":[84,13,18,19,20,23,37,181,70,139],"294":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/utils/agent-execution/processEventStream.ts":{"22":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/utils/agent-execution/processHitlResponses.ts":{"26":[84,13,18,19,20,23,37,181,70,139],"38":[84,13,18,19,20,23,37,181,70,139],"47":[84,13,18,19,20,23,37,181,70,139],"54":[84,13,18,19,20,23,37,181,70,139],"71":[84,13,18,19,20,23,37,181,70,139],"80":[84,13,18,19,20,23,37,181,70,139],"106":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/utils/agent-execution/serializeIntermediateSteps.ts":{"10":[84,13,18,19,20,23,37,181,70,139],"15":[84,13,18,19,20,23,37,181,70,139],"29":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/utils/agent-execution/types.ts":{"198":[84,13,18,19,20,23,37,181,70,139],"214":[84,13,18,19,20,23,37,181,70,139],"228":[84,13,18,19,20,23,37,181,70,139]},"packages/@n8n/nodes-langchain/utils/chatModelMessageWrapper.ts":{"29":[84,85,181,139],"30":[84,85,181,139],"57":[84,85,181,139],"68":[84,85,181,139],"71":[84,85,181,139]},"packages/@n8n/nodes-langchain/utils/descriptions.ts":{"28":"b:ACScACAAAABgIDAAAAAAIAAIAAAAACAAAAAAIAA=","54":"b:ACScACAAAABgIDAAAAAAIAAIAAAAACAAAAAAIAA=","72":"b:ACScACAAAABgIDAAAAAAIAAIAAAAACAAAAAAIAA="},"packages/@n8n/nodes-langchain/utils/helpers.ts":{"23":"b:ACScACAAAABgIDAAAAAAIAAIAAAAACAAAAAAIAA=","30":"b:ACScACAAAABgIDAAAAAAIAAIAAAAACAAAAAAIAA=","77":"b:ACScACAAAABgIDAAAAAAIAAIAAAAACAAAAAAIAA=","90":"b:ACScACAAAABgIDAAAAAAIAAIAAAAACAAAAAAIAA=","99":"b:ACScACAAAABgIDAAAAAAIAAIAAAAACAAAAAAIAA=","114":"b:ACScACAAAABgIDAAAAAAIAAIAAAAACAAAAAAIAA=","183":"b:ACScACAAAABgIDAAAAAAIAAIAAAAACAAAAAAIAA=","185":"b:ACScACAAAABgIDAAAAAAIAAIAAAAACAAAAAAIAA=","197":"b:ACScACAAAABgIDAAAAAAIAAIAAAAACAAAAAAIAA=","218":"b:ACScACAAAABgIDAAAAAAIAAIAAAAACAAAAAAIAA=","230":"b:ACScACAAAABgIDAAAAAAIAAIAAAAACAAAAAAIAA=","253":"b:ACScACAAAABgIDAAAAAAIAAIAAAAACAAAAAAIAA=","257":"b:ACScACAAAABgIDAAAAAAIAAIAAAAACAAAAAAIAA=","261":"b:ACScACAAAABgIDAAAAAAIAAIAAAAACAAAAAAIAA=","311":"b:ACScACAAAABgIDAAAAAAIAAIAAAAACAAAAAAIAA=","329":"b:ACScACAAAABgIDAAAAAAIAAIAAAAACAAAAAAIAA=","347":"b:ACScACAAAABgIDAAAAAAIAAIAAAAACAAAAAAIAA="},"packages/@n8n/nodes-langchain/utils/output_parsers/N8nItemListOutputParser.ts":{"10":[84,85,13,18,19,20,23,37,181,70,139,77],"26":[84,85,13,18,19,20,23,37,181,70,139,77],"29":[84,85,13,18,19,20,23,37,181,70,139,77],"30":[84,85,13,18,19,20,23,37,181,70,139,77],"42":[84,85,13,18,19,20,23,37,181,70,139,77],"57":[84,85,13,18,19,20,23,37,181,70,139,77]},"packages/@n8n/nodes-langchain/utils/output_parsers/N8nOutputFixingParser.ts":{"15":[84,85,13,18,19,20,23,37,181,70,139,77],"24":[84,85,13,18,19,20,23,37,181,70,139,77],"35":[84,85,13,18,19,20,23,37,181,70,139,77],"42":[84,85,13,18,19,20,23,37,181,70,139,77],"88":[84,85,13,18,19,20,23,37,181,70,139,77],"92":[84,85,13,18,19,20,23,37,181,70,139,77]},"packages/@n8n/nodes-langchain/utils/output_parsers/N8nOutputParser.ts":{"4":[84,85,13,18,19,20,23,37,181,70,139,77],"5":[84,85,13,18,19,20,23,37,181,70,139,77],"15":[84,85,13,18,19,20,23,37,181,70,139,77]},"packages/@n8n/nodes-langchain/utils/output_parsers/N8nStructuredOutputParser.ts":{"22":[84,85,13,18,19,20,23,37,181,70,139,77],"31":[84,85,13,18,19,20,23,37,181,70,139,77],"131":[84,85,13,18,19,20,23,37,181,70,139,77],"148":[84,85,13,18,19,20,23,37,181,70,139,77],"175":[84,85,13,18,19,20,23,37,181,70,139,77]},"packages/@n8n/nodes-langchain/utils/output_parsers/langchainParserError.ts":{"13":[84,85,13,18,19,20,21,23,37,181,70,139,77],"21":[84,85,13,18,19,20,21,23,37,181,70,139,77],"29":[84,85,13,18,19,20,21,23,37,181,70,139,77],"33":[84,85,13,18,19,20,21,23,37,181,70,139,77],"36":[84,85,13,18,19,20,21,23,37,181,70,139,77],"49":[84,85,13,18,19,20,21,23,37,181,70,139,77],"60":[84,85,13,18,19,20,21,23,37,181,70,139,77],"66":[84,85,13,18,19,20,21,23,37,181,70,139,77],"98":[84,85,13,18,19,20,21,23,37,181,70,139,77]},"packages/@n8n/nodes-langchain/utils/tracing.ts":{"19":[84,85,10,13,18,19,20,23,37,181,69,70,139],"83":[84,85,10,13,18,19,20,23,37,181,69,70,139]},"packages/cli/src/abstract-server.ts":{"83":"b:ggSQuwywAABwHhQoCRAAAKCAAEoAKAAACgAAAAA=","116":"b:ggSQuwywAABwHhQoCRAAAKCAAEoAKAAACgAAAAA=","120":"b:ggSQuwywAABwHhQoCRAAAKCAAEoAKAAACgAAAAA=","128":"b:ggSQuwywAABwHhQoCRAAAKCAAEoAKAAACgAAAAA=","136":"b:ggSQuwywAABwHhQoCRAAAKCAAEoAKAAACgAAAAA=","140":"b:ggSQuwywAABwHhQoCRAAAKCAAEoAKAAACgAAAAA=","143":"b:ggSQuwywAABwHhQoCRAAAKCAAEoAKAAACgAAAAA=","147":"b:ggSQuwywAABwHhQoCRAAAKCAAEoAKAAACgAAAAA=","154":"b:ggSQuwywAABwHhQoCRAAAKCAAEoAKAAACgAAAAA=","160":"b:ggSQuwywAABwHhQoCRAAAKCAAEoAKAAACgAAAAA=","169":"b:ggSQuwywAABwHhQoCRAAAKCAAEoAKAAACgAAAAA=","181":"b:ggSQuwywAABwHhQoCRAAAKCAAEoAKAAACgAAAAA=","189":"b:ggSQuwywAABwHhQoCRAAAKCAAEoAKAAACgAAAAA=","209":"b:ggSQuwywAABwHhQoCRAAAKCAAEoAKAAACgAAAAA=","239":"b:ggSQuwywAABwHhQoCRAAAKCAAEoAKAAACgAAAAA=","248":"b:ggSQuwywAABwHhQoCRAAAKCAAEoAKAAACgAAAAA=","321":"b:ggSQuwywAABwHhQoCRAAAKCAAEoAKAAACgAAAAA=","325":"b:ggSQuwywAABwHhQoCRAAAKCAAEoAKAAACgAAAAA=","364":"b:ggSQuwywAABwHhQoCRAAAKCAAEoAKAAACgAAAAA=","373":"b:ggSQuwywAABwHhQoCRAAAKCAAEoAKAAACgAAAAA="},"packages/cli/src/collaboration/collaboration.message.ts":{"133":"b:9k+CkCypAAD0PnQoCRAAQEAKAAEAAAAAAAAAAAA="},"packages/cli/src/collaboration/collaboration.state.ts":{"40":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","57":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","62":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","67":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","78":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","90":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","96":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","124":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","128":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","143":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","150":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","155":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","187":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","198":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","209":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","215":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","223":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","225":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","235":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","249":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","254":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","264":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","266":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","274":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","285":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","291":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","304":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","316":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","322":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","350":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","354":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","358":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","363":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","373":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","379":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","387":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","389":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","398":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","407":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","412":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","414":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","422":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","430":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","432":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","440":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","451":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA=","457":"b:9v+ilCztviH3vnxoDRkAROAKAAEAMAIAABggAAA="},"packages/cli/src/controllers/active-workflows.controller.ts":{"8":"b:8E/Ckyz5AYj0PnQrCRAAQAACAAAAAAAAAAAAAAA=","11":"b:8E/Ckyz5AYj0PnQrCRAAQAACAAAAAAAAAAAAAAA=","16":"b:8E/Ckyz5AYj0PnQrCRAAQAACAAAAAAAAAAAAAAA="},"packages/cli/src/controllers/dynamic-node-parameters.controller.ts":{"18":[84,152,45,65,66,209,77,78,141,213,142],"34":[84,152,45,65,66,209,77,78,141,213,142],"57":[84,152,45,65,66,209,77,78,141,213,142],"107":[84,152,45,65,66,209,77,78,141,213,142],"146":[84,152,45,65,66,209,77,78,141,213,142],"175":[84,152,45,65,66,209,77,78,141,213,142],"201":[84,152,45,65,66,209,77,78,141,213,142]},"packages/cli/src/controllers/me.controller.ts":{"31":"b:AAAAACAAAIBgIHAAAAAAAAAKAAAAAABBAgAAAAA=","47":"b:AAAAACAAAIBgIHAAAAAAAAAKAAAAAABBAgAAAAA=","97":"b:AAAAACAAAIBgIHAAAAAAAAAKAAAAAABBAgAAAAA=","109":"b:AAAAACAAAIBgIHAAAAAAAAAKAAAAAABBAgAAAAA=","118":"b:AAAAACAAAIBgIHAAAAAAAAAKAAAAAABBAgAAAAA=","128":"b:AAAAACAAAIBgIHAAAAAAAAAKAAAAAABBAgAAAAA=","166":"b:AAAAACAAAIBgIHAAAAAAAAAKAAAAAABBAgAAAAA=","199":"b:AAAAACAAAIBgIHAAAAAAAAAKAAAAAABBAgAAAAA=","244":"b:AAAAACAAAIBgIHAAAAAAAAAKAAAAAABBAgAAAAA="},"packages/cli/src/credential-types.ts":{"8":"b:ACCeAAYxABAHYDwIECAABCABAQEAIAAAAAAAIAA=","10":"b:ACCeAAYxABAHYDwIECAABCABAQEAIAAAAAAAIAA=","15":"b:ACCeAAYxABAHYDwIECAABCABAQEAIAAAAAAAIAA=","19":"b:ACCeAAYxABAHYDwIECAABCABAQEAIAAAAAAAIAA=","23":"b:ACCeAAYxABAHYDwIECAABCABAQEAIAAAAAAAIAA=","30":"b:ACCeAAYxABAHYDwIECAABCABAQEAIAAAAAAAIAA="},"packages/cli/src/credentials/credential-dependency.service.ts":{"13":"b:ACCeAAAxABAHYDwIACAABDAAASAAIAAAAAAAYAA=","22":"b:ACCeAAAxABAHYDwIACAABDAAASAAIAAAAAAAYAA=","27":"b:ACCeAAAxABAHYDwIACAABDAAASAAIAAAAAAAYAA=","42":"b:ACCeAAAxABAHYDwIACAABDAAASAAIAAAAAAAYAA=","53":"b:ACCeAAAxABAHYDwIACAABDAAASAAIAAAAAAAYAA=","74":"b:ACCeAAAxABAHYDwIACAABDAAASAAIAAAAAAAYAA=","95":"b:ACCeAAAxABAHYDwIACAABDAAASAAIAAAAAAAYAA=","111":"b:ACCeAAAxABAHYDwIACAABDAAASAAIAAAAAAAYAA="},"packages/cli/src/credentials/credential-descriptions.service.ts":{"8":"b:9m/eky75AdjXPnwrCTAEQAAAAAAAAAAAAAAAAAA=","10":"b:9m/eky75AdjXPnwrCTAEQAAAAAAAAAAAAAAAAAA=","17":"b:9m/eky75AdjXPnwrCTAEQAAAAAAAAAAAAAAAAAA="},"packages/cli/src/credentials/credentials.controller.ts":{"55":"b:9m//k6z5Adj3fn4rDTAkVnAIgSkEMIAADAAAYAA=","73":"b:9m//k6z5Adj3fn4rDTAkVnAIgSkEMIAADAAAYAA=","89":"b:9m//k6z5Adj3fn4rDTAkVnAIgSkEMIAADAAAYAA=","104":"b:9m//k6z5Adj3fn4rDTAkVnAIgSkEMIAADAAAYAA=","114":"b:9m//k6z5Adj3fn4rDTAkVnAIgSkEMIAADAAAYAA=","126":"b:9m//k6z5Adj3fn4rDTAkVnAIgSkEMIAADAAAYAA=","140":"b:9m//k6z5Adj3fn4rDTAkVnAIgSkEMIAADAAAYAA=","170":"b:9m//k6z5Adj3fn4rDTAkVnAIgSkEMIAADAAAYAA=","197":"b:9m//k6z5Adj3fn4rDTAkVnAIgSkEMIAADAAAYAA=","222":"b:9m//k6z5Adj3fn4rDTAkVnAIgSkEMIAADAAAYAA=","270":"b:9m//k6z5Adj3fn4rDTAkVnAIgSkEMIAADAAAYAA=","451":"b:9m//k6z5Adj3fn4rDTAkVnAIgSkEMIAADAAAYAA=","485":"b:9m//k6z5Adj3fn4rDTAkVnAIgSkEMIAADAAAYAA=","514":"b:9m//k6z5Adj3fn4rDTAkVnAIgSkEMIAADAAAYAA=","520":"b:9m//k6z5Adj3fn4rDTAkVnAIgSkEMIAADAAAYAA=","539":"b:9m//k6z5Adj3fn4rDTAkVnAIgSkEMIAADAAAYAA=","540":"b:9m//k6z5Adj3fn4rDTAkVnAIgSkEMIAADAAAYAA=","543":"b:9m//k6z5Adj3fn4rDTAkVnAIgSkEMIAADAAAYAA=","544":"b:9m//k6z5Adj3fn4rDTAkVnAIgSkEMIAADAAAYAA=","568":"b:9m//k6z5Adj3fn4rDTAkVnAIgSkEMIAADAAAYAA=","608":"b:9m//k6z5Adj3fn4rDTAkVnAIgSkEMIAADAAAYAA=","615":"b:9m//k6z5Adj3fn4rDTAkVnAIgSkEMIAADAAAYAA="},"packages/cli/src/credentials/credentials.service.ts":{"120":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","125":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","240":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","245":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","249":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","255":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","283":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","295":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","299":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","304":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","322":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","335":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","395":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","437":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","508":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","531":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","568":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","582":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","584":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","585":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","589":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","592":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","597":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","600":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","604":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","637":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","654":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","655":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","666":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","672":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","680":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","686":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","687":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","692":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","719":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","730":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","731":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","740":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","747":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","754":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","768":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","785":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","815":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","833":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","864":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","934":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","946":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","958":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","987":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","994":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1021":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1045":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1058":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1074":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1095":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1109":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1144":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1171":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1185":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1257":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1274":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1308":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1348":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1369":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1376":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1403":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1415":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1425":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1490":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1505":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1527":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1537":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1553":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1586":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1634":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1648":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1662":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1677":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1721":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1736":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1737":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1740":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1752":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1755":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1768":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1777":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1802":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1814":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1831":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1856":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1946":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1948":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1967":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1976":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1984":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1985":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1996":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","1997":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","2002":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","2009":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","2017":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","2038":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","2046":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","2058":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","2101":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","2117":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","2127":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","2159":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","2173":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","2201":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","2210":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","2224":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","2235":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","2321":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","2334":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","2399":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","2431":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","2440":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA=","2470":"b:9m//ky75Adj3fn4rDTAkXvALgSEUMAEABAIAYAA="},"packages/cli/src/credentials/dynamic-credentials-proxy.ts":{"30":[84,18,19,20,91,109,26,158,40,221,172,67,78],"32":[84,18,19,20,91,109,26,158,40,221,172,67,78],"36":[84,18,19,20,91,109,26,158,40,221,172,67,78],"46":[84,18,19,20,91,109,26,158,40,221,172,67,78],"58":[84,18,19,20,91,109,26,158,40,221,172,67,78],"64":[84,18,19,20,91,109,26,158,40,221,172,67,78],"89":[84,18,19,20,91,109,26,158,40,221,172,67,78],"119":[84,18,19,20,91,109,26,158,40,221,172,67,78]},"packages/cli/src/credentials/external-secrets.utils.ts":{"14":"b:ACCeAAIxABAHYDwIACAABCAAAQAAIAAAAAAAYAA=","23":"b:ACCeAAIxABAHYDwIACAABCAAAQAAIAAAAAAAYAA=","32":"b:ACCeAAIxABAHYDwIACAABCAAAQAAIAAAAAAAYAA=","70":"b:ACCeAAIxABAHYDwIACAABCAAAQAAIAAAAAAAYAA="},"packages/cli/src/credentials/mock-node-types.ts":{"18":"b:AAAcAAAAAAAAQBwAAKAAEAQAAAAAIAAAAAAAIAA=","29":"b:AAAcAAAAAAAAQBwAAKAAEAQAAAAAIAAAAAAAIAA=","32":"b:AAAcAAAAAAAAQBwAAKAAEAQAAAAAIAAAAAAAIAA=","35":"b:AAAcAAAAAAAAQBwAAKAAEAQAAAAAIAAAAAAAIAA="},"packages/cli/src/credentials/validation.ts":{"20":"b:ACCeAAAxABAHYDwIACAABDAAASAAIAAAAAAAYAA=","27":"b:ACCeAAAxABAHYDwIACAABDAAASAAIAAAAAAAYAA=","55":"b:ACCeAAAxABAHYDwIACAABDAAASAAIAAAAAAAYAA=","91":"b:ACCeAAAxABAHYDwIACAABDAAASAAIAAAAAAAYAA=","134":"b:ACCeAAAxABAHYDwIACAABDAAASAAIAAAAAAAYAA=","152":"b:ACCeAAAxABAHYDwIACAABDAAASAAIAAAAAAAYAA=","153":"b:ACCeAAAxABAHYDwIACAABDAAASAAIAAAAAAAYAA=","165":"b:ACCeAAAxABAHYDwIACAABDAAASAAIAAAAAAAYAA=","182":"b:ACCeAAAxABAHYDwIACAABDAAASAAIAAAAAAAYAA="},"packages/cli/src/credentials-helper.ts":{"67":"b:ACCeBAIxABAHYDwIEKAgFDQBASEAMAAAAAACYAA=","73":"b:ACCeBAIxABAHYDwIEKAgFDQBASEAMAAAAAACYAA=","106":"b:ACCeBAIxABAHYDwIEKAgFDQBASEAMAAAAAACYAA=","122":"b:ACCeBAIxABAHYDwIEKAgFDQBASEAMAAAAAACYAA=","139":"b:ACCeBAIxABAHYDwIEKAgFDQBASEAMAAAAAACYAA=","175":"b:ACCeBAIxABAHYDwIEKAgFDQBASEAMAAAAAACYAA=","176":"b:ACCeBAIxABAHYDwIEKAgFDQBASEAMAAAAAACYAA=","202":"b:ACCeBAIxABAHYDwIEKAgFDQBASEAMAAAAAACYAA=","212":"b:ACCeBAIxABAHYDwIEKAgFDQBASEAMAAAAAACYAA=","276":"b:ACCeBAIxABAHYDwIEKAgFDQBASEAMAAAAAACYAA=","295":"b:ACCeBAIxABAHYDwIEKAgFDQBASEAMAAAAAACYAA=","324":"b:ACCeBAIxABAHYDwIEKAgFDQBASEAMAAAAAACYAA=","331":"b:ACCeBAIxABAHYDwIEKAgFDQBASEAMAAAAAACYAA=","347":"b:ACCeBAIxABAHYDwIEKAgFDQBASEAMAAAAAACYAA=","378":"b:ACCeBAIxABAHYDwIEKAgFDQBASEAMAAAAAACYAA=","397":"b:ACCeBAIxABAHYDwIEKAgFDQBASEAMAAAAAACYAA=","435":"b:ACCeBAIxABAHYDwIEKAgFDQBASEAMAAAAAACYAA=","466":"b:ACCeBAIxABAHYDwIEKAgFDQBASEAMAAAAAACYAA=","475":"b:ACCeBAIxABAHYDwIEKAgFDQBASEAMAAAAAACYAA=","507":"b:ACCeBAIxABAHYDwIEKAgFDQBASEAMAAAAAACYAA=","531":"b:ACCeBAIxABAHYDwIEKAgFDQBASEAMAAAAAACYAA=","541":"b:ACCeBAIxABAHYDwIEKAgFDQBASEAMAAAAAACYAA=","568":"b:ACCeBAIxABAHYDwIEKAgFDQBASEAMAAAAAACYAA=","713":"b:ACCeBAIxABAHYDwIEKAgFDQBASEAMAAAAAACYAA=","726":"b:ACCeBAIxABAHYDwIEKAgFDQBASEAMAAAAAACYAA=","740":"b:ACCeBAIxABAHYDwIEKAgFDQBASEAMAAAAAACYAA=","844":"b:ACCeBAIxABAHYDwIEKAgFDQBASEAMAAAAAACYAA=","871":"b:ACCeBAIxABAHYDwIEKAgFDQBASEAMAAAAAACYAA=","950":"b:ACCeBAIxABAHYDwIEKAgFDQBASEAMAAAAAACYAA="},"packages/cli/src/credentials-overwrites.ts":{"23":"b:ACCeAAQxABAHYDwIACAAFCQAAQAAIAAAAAAAYAA=","34":"b:ACCeAAQxABAHYDwIACAAFCQAAQAAIAAAAAAAYAA=","38":"b:ACCeAAQxABAHYDwIACAAFCQAAQAAIAAAAAAAYAA=","60":"b:ACCeAAQxABAHYDwIACAAFCQAAQAAIAAAAAAAYAA=","64":"b:ACCeAAQxABAHYDwIACAAFCQAAQAAIAAAAAAAYAA=","86":"b:ACCeAAQxABAHYDwIACAAFCQAAQAAIAAAAAAAYAA=","91":"b:ACCeAAQxABAHYDwIACAAFCQAAQAAIAAAAAAAYAA=","105":"b:ACCeAAQxABAHYDwIACAAFCQAAQAAIAAAAAAAYAA=","110":"b:ACCeAAQxABAHYDwIACAAFCQAAQAAIAAAAAAAYAA=","125":"b:ACCeAAQxABAHYDwIACAAFCQAAQAAIAAAAAAAYAA=","140":"b:ACCeAAQxABAHYDwIACAAFCQAAQAAIAAAAAAAYAA=","152":"b:ACCeAAQxABAHYDwIACAAFCQAAQAAIAAAAAAAYAA=","180":"b:ACCeAAQxABAHYDwIACAAFCQAAQAAIAAAAAAAYAA=","212":"b:ACCeAAQxABAHYDwIACAAFCQAAQAAIAAAAAAAYAA=","216":"b:ACCeAAQxABAHYDwIACAAFCQAAQAAIAAAAAAAYAA=","217":"b:ACCeAAQxABAHYDwIACAAFCQAAQAAIAAAAAAAYAA=","222":"b:ACCeAAQxABAHYDwIACAAFCQAAQAAIAAAAAAAYAA=","227":"b:ACCeAAQxABAHYDwIACAAFCQAAQAAIAAAAAAAYAA=","231":"b:ACCeAAQxABAHYDwIACAAFCQAAQAAIAAAAAAAYAA=","240":"b:ACCeAAQxABAHYDwIACAAFCQAAQAAIAAAAAAAYAA=","247":"b:ACCeAAQxABAHYDwIACAAFCQAAQAAIAAAAAAAYAA=","258":"b:ACCeAAQxABAHYDwIACAAFCQAAQAAIAAAAAAAYAA=","261":"b:ACCeAAQxABAHYDwIACAAFCQAAQAAIAAAAAAAYAA=","268":"b:ACCeAAQxABAHYDwIACAAFCQAAQAAIAAAAAAAYAA="},"packages/cli/src/eventbus/event-message-classes/event-message-ai-node.ts":{"33":[4,84,85,10,18,19,20,125,221],"41":[4,84,85,10,18,19,20,125,221]},"packages/cli/src/executions/execution-cursor.ts":{"12":"b:AAAABAiEviEBAxhAIIGAAEEDAAAAEAAAAACAAQA=","30":"b:AAAABAiEviEBAxhAIIGAAEEDAAAAEAAAAACAAQA=","43":"b:AAAABAiEviEBAxhAIIGAAEEDAAAAEAAAAACAAQA=","47":"b:AAAABAiEviEBAxhAIIGAAEEDAAAAEAAAAACAAQA="},"packages/cli/src/executions/execution-list-v1.service.ts":{"21":"b:AAAABAiEviEBAxhAIIGAAEEDAAAAEAAAAACAAQA=","27":"b:AAAABAiEviEBAxhAIIGAAEEDAAAAEAAAAACAAQA=","38":"b:AAAABAiEviEBAxhAIIGAAEEDAAAAEAAAAACAAQA=","73":"b:AAAABAiEviEBAxhAIIGAAEEDAAAAEAAAAACAAQA=","93":"b:AAAABAiEviEBAxhAIIGAAEEDAAAAEAAAAACAAQA=","108":"b:AAAABAiEviEBAxhAIIGAAEEDAAAAEAAAAACAAQA=","129":"b:AAAABAiEviEBAxhAIIGAAEEDAAAAEAAAAACAAQA="},"packages/cli/src/executions/execution-list.service.ts":{"24":"b:AAAABAiEviEBAxhAIIGAAEEDAAAAEAAAAACAAAA=","32":"b:AAAABAiEviEBAxhAIIGAAEEDAAAAEAAAAACAAAA=","62":"b:AAAABAiEviEBAxhAIIGAAEEDAAAAEAAAAACAAAA=","72":"b:AAAABAiEviEBAxhAIIGAAEEDAAAAEAAAAACAAAA=","73":"b:AAAABAiEviEBAxhAIIGAAEEDAAAAEAAAAACAAAA=","89":"b:AAAABAiEviEBAxhAIIGAAEEDAAAAEAAAAACAAAA=","98":"b:AAAABAiEviEBAxhAIIGAAEEDAAAAEAAAAACAAAA="},"packages/cli/src/executions/parse-range-query.middleware.ts":{"16":"b:AAAABAiEviEBAxhAIIGAAEEDAAAAEAAAAACAAAA=","19":"b:AAAABAiEviEBAxhAIIGAAEEDAAAAEAAAAACAAAA=","38":"b:AAAABAiEviEBAxhAIIGAAEEDAAAAEAAAAACAAAA="},"packages/cli/src/license/license.controller.ts":{"15":"b:8E/Ckyz5AYj0PnQrCRAAQAACAAAAAAAAAAAAAAA=","22":"b:8E/Ckyz5AYj0PnQrCRAAQAACAAAAAAAAAAAAAAA=","28":"b:8E/Ckyz5AYj0PnQrCRAAQAACAAAAAAAAAAAAAAA=","45":"b:8E/Ckyz5AYj0PnQrCRAAQAACAAAAAAAAAAAAAAA=","61":"b:8E/Ckyz5AYj0PnQrCRAAQAACAAAAAAAAAAAAAAA=","73":"b:8E/Ckyz5AYj0PnQrCRAAQAACAAAAAAAAAAAAAAA=","78":"b:8E/Ckyz5AYj0PnQrCRAAQAACAAAAAAAAAAAAAAA="},"packages/cli/src/license/license.service.ts":{"29":"b:8E/Ckyz5AYj0PnQrCRAAQAACAAAAAAAAAAAAAAA=","44":"b:8E/Ckyz5AYj0PnQrCRAAQAACAAAAAAAAAAAAAAA=","70":"b:8E/Ckyz5AYj0PnQrCRAAQAACAAAAAAAAAAAAAAA=","85":"b:8E/Ckyz5AYj0PnQrCRAAQAACAAAAAAAAAAAAAAA=","128":"b:8E/Ckyz5AYj0PnQrCRAAQAACAAAAAAAAAAAAAAA=","136":"b:8E/Ckyz5AYj0PnQrCRAAQAACAAAAAAAAAAAAAAA=","162":"b:8E/Ckyz5AYj0PnQrCRAAQAACAAAAAAAAAAAAAAA=","180":"b:8E/Ckyz5AYj0PnQrCRAAQAACAAAAAAAAAAAAAAA=","195":"b:8E/Ckyz5AYj0PnQrCRAAQAACAAAAAAAAAAAAAAA=","209":"b:8E/Ckyz5AYj0PnQrCRAAQAACAAAAAAAAAAAAAAA="},"packages/cli/src/metrics/prometheus/webhook-and-form-metrics.service.ts":{"18":"b:ANYADACAACABADAAgAmAAAQDCAAAAAAAAAAAgAA=","20":"b:ANYADACAACABADAAgAmAAAQDCAAAAAAAAAAAgAA=","24":"b:ANYADACAACABADAAgAmAAAQDCAAAAAAAAAAAgAA=","46":"b:ANYADACAACABADAAgAmAAAQDCAAAAAAAAAAAgAA=","67":"b:ANYADACAACABADAAgAmAAAQDCAAAAAAAAAAAgAA="},"packages/cli/src/modules/agents/agent-dependency-index.listener.ts":{"9":"b:wvEiFIykviG3KBhgAZkATOgIAAAAMAIAAAAAAAA=","17":"b:wvEiFIykviG3KBhgAZkATOgIAAAAMAIAAAAAAAA=","18":"b:wvEiFIykviG3KBhgAZkATOgIAAAAMAIAAAAAAAA=","19":"b:wvEiFIykviG3KBhgAZkATOgIAAAAMAIAAAAAAAA=","23":"b:wvEiFIykviG3KBhgAZkATOgIAAAAMAIAAAAAAAA=","24":"b:wvEiFIykviG3KBhgAZkATOgIAAAAMAIAAAAAAAA=","28":"b:wvEiFIykviG3KBhgAZkATOgIAAAAMAIAAAAAAAA=","29":"b:wvEiFIykviG3KBhgAZkATOgIAAAAMAIAAAAAAAA=","43":"b:wvEiFIykviG3KBhgAZkATOgIAAAAMAIAAAAAAAA=","44":"b:wvEiFIykviG3KBhgAZkATOgIAAAAMAIAAAAAAAA=","45":"b:wvEiFIykviG3KBhgAZkATOgIAAAAMAIAAAAAAAA=","49":"b:wvEiFIykviG3KBhgAZkATOgIAAAAMAIAAAAAAAA=","58":"b:wvEiFIykviG3KBhgAZkATOgIAAAAMAIAAAAAAAA="},"packages/cli/src/modules/agents/agent-dependency-index.service.ts":{"16":"b:wvEiFAykviG3KBhgAZkATOgIAAAAEAAAAAAAAAA=","28":"b:wvEiFAykviG3KBhgAZkATOgIAAAAEAAAAAAAAAA=","33":"b:wvEiFAykviG3KBhgAZkATOgIAAAAEAAAAAAAAAA=","42":"b:wvEiFAykviG3KBhgAZkATOgIAAAAEAAAAAAAAAA=","47":"b:wvEiFAykviG3KBhgAZkATOgIAAAAEAAAAAAAAAA="},"packages/cli/src/modules/agents/integrations/agent-channel-reconciler.service.ts":{"81":"b:oACTExioANzAOBQ4CRAAAgCAoA0AAAAAAAAAAAA=","103":"b:oACTExioANzAOBQ4CRAAAgCAoA0AAAAAAAAAAAA=","111":"b:oACTExioANzAOBQ4CRAAAgCAoA0AAAAAAAAAAAA=","130":"b:oACTExioANzAOBQ4CRAAAgCAoA0AAAAAAAAAAAA=","146":"b:oACTExioANzAOBQ4CRAAAgCAoA0AAAAAAAAAAAA=","151":"b:oACTExioANzAOBQ4CRAAAgCAoA0AAAAAAAAAAAA=","156":"b:oACTExioANzAOBQ4CRAAAgCAoA0AAAAAAAAAAAA=","168":"b:oACTExioANzAOBQ4CRAAAgCAoA0AAAAAAAAAAAA=","178":"b:oACTExioANzAOBQ4CRAAAgCAoA0AAAAAAAAAAAA=","186":"b:oACTExioANzAOBQ4CRAAAgCAoA0AAAAAAAAAAAA=","189":"b:oACTExioANzAOBQ4CRAAAgCAoA0AAAAAAAAAAAA=","190":"b:oACTExioANzAOBQ4CRAAAgCAoA0AAAAAAAAAAAA=","202":"b:oACTExioANzAOBQ4CRAAAgCAoA0AAAAAAAAAAAA=","223":"b:oACTExioANzAOBQ4CRAAAgCAoA0AAAAAAAAAAAA=","232":"b:oACTExioANzAOBQ4CRAAAgCAoA0AAAAAAAAAAAA=","237":"b:oACTExioANzAOBQ4CRAAAgCAoA0AAAAAAAAAAAA=","256":"b:oACTExioANzAOBQ4CRAAAgCAoA0AAAAAAAAAAAA=","279":"b:oACTExioANzAOBQ4CRAAAgCAoA0AAAAAAAAAAAA=","310":"b:oACTExioANzAOBQ4CRAAAgCAoA0AAAAAAAAAAAA=","335":"b:oACTExioANzAOBQ4CRAAAgCAoA0AAAAAAAAAAAA=","352":"b:oACTExioANzAOBQ4CRAAAgCAoA0AAAAAAAAAAAA=","356":"b:oACTExioANzAOBQ4CRAAAgCAoA0AAAAAAAAAAAA=","368":"b:oACTExioANzAOBQ4CRAAAgCAoA0AAAAAAAAAAAA=","393":"b:oACTExioANzAOBQ4CRAAAgCAoA0AAAAAAAAAAAA="},"packages/cli/src/modules/agents/register-agent-usage-provider.ts":{"9":"b:EAaAkwz5AAC0ghQpCQAARiQCgAAAEgAAAAgAAAA=","15":"b:EAaAkwz5AAC0ghQpCQAARiQCgAAAEgAAAAgAAAA=","18":"b:EAaAkwz5AAC0ghQpCQAARiQCgAAAEgAAAAgAAAA=","26":"b:EAaAkwz5AAC0ghQpCQAARiQCgAAAEgAAAAgAAAA=","34":"b:EAaAkwz5AAC0ghQpCQAARiQCgAAAEgAAAAgAAAA="},"packages/cli/src/modules/agents/repositories/agent-workflow-dependency.repository.ts":{"22":"b:0vcilAz9viG3KhxgCRkARGgKAAAAEAAAAAAAAAA=","29":"b:0vcilAz9viG3KhxgCRkARGgKAAAAEAAAAAAAAAA=","30":"b:0vcilAz9viG3KhxgCRkARGgKAAAAEAAAAAAAAAA=","62":"b:0vcilAz9viG3KhxgCRkARGgKAAAAEAAAAAAAAAA=","65":"b:0vcilAz9viG3KhxgCRkARGgKAAAAEAAAAAAAAAA=","82":"b:0vcilAz9viG3KhxgCRkARGgKAAAAEAAAAAAAAAA=","90":"b:0vcilAz9viG3KhxgCRkARGgKAAAAEAAAAAAAAAA=","94":"b:0vcilAz9viG3KhxgCRkARGgKAAAAEAAAAAAAAAA=","103":"b:0vcilAz9viG3KhxgCRkARGgKAAAAEAAAAAAAAAA=","113":"b:0vcilAz9viG3KhxgCRkARGgKAAAAEAAAAAAAAAA=","116":"b:0vcilAz9viG3KhxgCRkARGgKAAAAEAAAAAAAAAA=","129":"b:0vcilAz9viG3KhxgCRkARGgKAAAAEAAAAAAAAAA="},"packages/cli/src/modules/dynamic-credentials.ee/services/dynamic-credential.service.ts":{"43":"b:AAA8BAABAAAIQBAIACAAAAAAAEAAEAAAAAAAIAA=","64":"b:AAA8BAABAAAIQBAIACAAAAAAAEAAEAAAAAAAIAA=","195":"b:AAA8BAABAAAIQBAIACAAAAAAAEAAEAAAAAAAIAA=","212":"b:AAA8BAABAAAIQBAIACAAAAAAAEAAEAAAAAAAIAA=","244":"b:AAA8BAABAAAIQBAIACAAAAAAAEAAEAAAAAAAIAA=","275":"b:AAA8BAABAAAIQBAIACAAAAAAAEAAEAAAAAAAIAA=","321":"b:AAA8BAABAAAIQBAIACAAAAAAAEAAEAAAAAAAIAA=","336":"b:AAA8BAABAAAIQBAIACAAAAAAAEAAEAAAAAAAIAA=","353":"b:AAA8BAABAAAIQBAIACAAAAAAAEAAEAAAAAAAIAA=","366":"b:AAA8BAABAAAIQBAIACAAAAAAAEAAEAAAAAAAIAA=","369":"b:AAA8BAABAAAIQBAIACAAAAAAAEAAEAAAAAAAIAA=","389":"b:AAA8BAABAAAIQBAIACAAAAAAAEAAEAAAAAAAIAA="},"packages/cli/src/modules/external-secrets.ee/provider-registry.service.ts":{"10":"b:gACCAIAgABCA4DSIBgBCEDBAACAE4IAIAFYEAAA=","13":"b:gACCAIAgABCA4DSIBgBCEDBAACAE4IAIAFYEAAA=","17":"b:gACCAIAgABCA4DSIBgBCEDBAACAE4IAIAFYEAAA=","21":"b:gACCAIAgABCA4DSIBgBCEDBAACAE4IAIAFYEAAA=","25":"b:gACCAIAgABCA4DSIBgBCEDBAACAE4IAIAFYEAAA=","29":"b:gACCAIAgABCA4DSIBgBCEDBAACAE4IAIAFYEAAA=","33":"b:gACCAIAgABCA4DSIBgBCEDBAACAE4IAIAFYEAAA=","43":"b:gACCAIAgABCA4DSIBgBCEDBAACAE4IAIAFYEAAA=","47":"b:gACCAIAgABCA4DSIBgBCEDBAACAE4IAIAFYEAAA=","51":"b:gACCAIAgABCA4DSIBgBCEDBAACAE4IAIAFYEAAA=","55":"b:gACCAIAgABCA4DSIBgBCEDBAACAE4IAIAFYEAAA=","57":"b:gACCAIAgABCA4DSIBgBCEDBAACAE4IAIAFYEAAA=","58":"b:gACCAIAgABCA4DSIBgBCEDBAACAE4IAIAFYEAAA="},"packages/cli/src/modules/external-secrets.ee/secrets-providers-completions.controller.ee.ts":{"15":"b:gACCAIAgABAAYDQIAAAAEDAAACAAAIAAAAAAAAA=","24":"b:gACCAIAgABAAYDQIAAAAEDAAACAAAIAAAAAAAAA=","55":"b:gACCAIAgABAAYDQIAAAAEDAAACAAAIAAAAAAAAA=","72":"b:gACCAIAgABAAYDQIAAAAEDAAACAAAIAAAAAAAAA=","84":"b:gACCAIAgABAAYDQIAAAAEDAAACAAAIAAAAAAAAA="},"packages/cli/src/modules/external-secrets.ee/secrets-providers-connections.service.ee.ts":{"38":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","52":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","78":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","106":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","123":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","140":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","145":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","146":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","151":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","152":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","167":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","189":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","211":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","220":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","243":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","251":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","261":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","265":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","273":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","281":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","285":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","287":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","294":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","309":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","319":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","337":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","338":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","349":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","375":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","402":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","406":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","419":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","436":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","440":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","467":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","471":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","484":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","500":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA=","522":"b:gAC2AoAgABAAYDYICAAAEjAAACAAAIAAAAAAAAA="},"packages/cli/src/modules/instance-ai/liveness/instance-ai-liveness.service.ts":{"114":"b:oACT8xyoANzAOBQ4CRAAAgCAoI0AAAAAAAAAAAA=","116":"b:oACT8xyoANzAOBQ4CRAAAgCAoI0AAAAAAAAAAAA=","120":"b:oACT8xyoANzAOBQ4CRAAAgCAoI0AAAAAAAAAAAA=","123":"b:oACT8xyoANzAOBQ4CRAAAgCAoI0AAAAAAAAAAAA=","128":"b:oACT8xyoANzAOBQ4CRAAAgCAoI0AAAAAAAAAAAA=","138":"b:oACT8xyoANzAOBQ4CRAAAgCAoI0AAAAAAAAAAAA=","142":"b:oACT8xyoANzAOBQ4CRAAAgCAoI0AAAAAAAAAAAA=","146":"b:oACT8xyoANzAOBQ4CRAAAgCAoI0AAAAAAAAAAAA=","152":"b:oACT8xyoANzAOBQ4CRAAAgCAoI0AAAAAAAAAAAA=","161":"b:oACT8xyoANzAOBQ4CRAAAgCAoI0AAAAAAAAAAAA=","165":"b:oACT8xyoANzAOBQ4CRAAAgCAoI0AAAAAAAAAAAA=","206":"b:oACT8xyoANzAOBQ4CRAAAgCAoI0AAAAAAAAAAAA=","225":"b:oACT8xyoANzAOBQ4CRAAAgCAoI0AAAAAAAAAAAA=","235":"b:oACT8xyoANzAOBQ4CRAAAgCAoI0AAAAAAAAAAAA=","244":"b:oACT8xyoANzAOBQ4CRAAAgCAoI0AAAAAAAAAAAA=","267":"b:oACT8xyoANzAOBQ4CRAAAgCAoI0AAAAAAAAAAAA="},"packages/cli/src/modules/redaction/redaction-enforcement.service.ts":{"20":"b:wAECEIykAAD2KBgkAREAROgIAAAAIAIAAAAAAAA=","24":"b:wAECEIykAAD2KBgkAREAROgIAAAAIAIAAAAAAAA=","50":"b:wAECEIykAAD2KBgkAREAROgIAAAAIAIAAAAAAAA="},"packages/cli/src/modules/workflow-index/agent-usage-provider-proxy.service.ts":{"16":"b:EAaAkwz5AAC0ghQpCQAARiQCgAAAEgAAAAgAAAA=","19":"b:EAaAkwz5AAC0ghQpCQAARiQCgAAAEgAAAAgAAAA=","23":"b:EAaAkwz5AAC0ghQpCQAARiQCgAAAEgAAAAgAAAA=","30":"b:EAaAkwz5AAC0ghQpCQAARiQCgAAAEgAAAAgAAAA="},"packages/cli/src/modules/workflow-index/workflow-dependency-query.service.ts":{"68":"b:EAaAkwz5AAC0ghYpCQBARnxKgAAAUgAACAgAAAA=","87":"b:EAaAkwz5AAC0ghYpCQBARnxKgAAAUgAACAgAAAA=","130":"b:EAaAkwz5AAC0ghYpCQBARnxKgAAAUgAACAgAAAA=","156":"b:EAaAkwz5AAC0ghYpCQBARnxKgAAAUgAACAgAAAA=","250":"b:EAaAkwz5AAC0ghYpCQBARnxKgAAAUgAACAgAAAA=","252":"b:EAaAkwz5AAC0ghYpCQBARnxKgAAAUgAACAgAAAA=","263":"b:EAaAkwz5AAC0ghYpCQBARnxKgAAAUgAACAgAAAA=","294":"b:EAaAkwz5AAC0ghYpCQBARnxKgAAAUgAACAgAAAA=","320":"b:EAaAkwz5AAC0ghYpCQBARnxKgAAAUgAACAgAAAA=","348":"b:EAaAkwz5AAC0ghYpCQBARnxKgAAAUgAACAgAAAA=","355":"b:EAaAkwz5AAC0ghYpCQBARnxKgAAAUgAACAgAAAA=","421":"b:EAaAkwz5AAC0ghYpCQBARnxKgAAAUgAACAgAAAA=","459":"b:EAaAkwz5AAC0ghYpCQBARnxKgAAAUgAACAgAAAA=","479":"b:EAaAkwz5AAC0ghYpCQBARnxKgAAAUgAACAgAAAA=","529":"b:EAaAkwz5AAC0ghYpCQBARnxKgAAAUgAACAgAAAA=","543":"b:EAaAkwz5AAC0ghYpCQBARnxKgAAAUgAACAgAAAA=","553":"b:EAaAkwz5AAC0ghYpCQBARnxKgAAAUgAACAgAAAA=","561":"b:EAaAkwz5AAC0ghYpCQBARnxKgAAAUgAACAgAAAA=","574":"b:EAaAkwz5AAC0ghYpCQBARnxKgAAAUgAACAgAAAA=","577":"b:EAaAkwz5AAC0ghYpCQBARnxKgAAAUgAACAgAAAA=","587":"b:EAaAkwz5AAC0ghYpCQBARnxKgAAAUgAACAgAAAA="},"packages/cli/src/modules/workflow-index/workflow-dependency.controller.ts":{"9":"b:EAaAkwz5AAC0ghYpCQBARiRCgAAAUgAACAgAAAA=","12":"b:EAaAkwz5AAC0ghYpCQBARiRCgAAAUgAACAgAAAA=","25":"b:EAaAkwz5AAC0ghYpCQBARiRCgAAAUgAACAgAAAA=","41":"b:EAaAkwz5AAC0ghYpCQBARiRCgAAAUgAACAgAAAA="},"packages/cli/src/services/access.service.ts":{"13":"b:8E+CkCzpAAD0PnQoCRAAROAKAAEAMAIAABAAAAA=","19":"b:8E+CkCzpAAD0PnQoCRAAROAKAAEAMAIAABAAAAA=","31":"b:8E+CkCzpAAD0PnQoCRAAROAKAAEAMAIAABAAAAA="},"packages/cli/src/services/active-workflows.service.ts":{"16":"b:8E/Ckyz5AYj0PncrCxAASBACAAAAAAAABAIgAAA=","26":"b:8E/Ckyz5AYj0PncrCxAASBACAAAAAAAABAIgAAA=","30":"b:8E/Ckyz5AYj0PncrCxAASBACAAAAAAAABAIgAAA=","44":"b:8E/Ckyz5AYj0PncrCxAASBACAAAAAAAABAIgAAA=","48":"b:8E/Ckyz5AYj0PncrCxAASBACAAAAAAAABAIgAAA=","80":"b:8E/Ckyz5AYj0PncrCxAASBACAAAAAAAABAIgAAA=","82":"b:8E/Ckyz5AYj0PncrCxAASBACAAAAAAAABAIgAAA=","87":"b:8E/Ckyz5AYj0PncrCxAASBACAAAAAAAABAIgAAA="},"packages/cli/src/services/dynamic-node-parameters.service.ts":{"63":"b:AAAcAAAgAAAGYBAAAAAAAABgAAEAAAAAAAAiAAA=","72":"b:AAAcAAAgAAAGYBAAAAAAAABgAAEAAAAAAAAiAAA=","112":"b:AAAcAAAgAAAGYBAAAAAAAABgAAEAAAAAAAAiAAA=","113":"b:AAAcAAAgAAAGYBAAAAAAAABgAAEAAAAAAAAiAAA=","122":"b:AAAcAAAgAAAGYBAAAAAAAABgAAEAAAAAAAAiAAA=","141":"b:AAAcAAAgAAAGYBAAAAAAAABgAAEAAAAAAAAiAAA=","143":"b:AAAcAAAgAAAGYBAAAAAAAABgAAEAAAAAAAAiAAA=","152":"b:AAAcAAAgAAAGYBAAAAAAAABgAAEAAAAAAAAiAAA=","160":"b:AAAcAAAgAAAGYBAAAAAAAABgAAEAAAAAAAAiAAA=","172":"b:AAAcAAAgAAAGYBAAAAAAAABgAAEAAAAAAAAiAAA=","183":"b:AAAcAAAgAAAGYBAAAAAAAABgAAEAAAAAAAAiAAA=","217":"b:AAAcAAAgAAAGYBAAAAAAAABgAAEAAAAAAAAiAAA=","284":"b:AAAcAAAgAAAGYBAAAAAAAABgAAEAAAAAAAAiAAA=","295":"b:AAAcAAAgAAAGYBAAAAAAAABgAAEAAAAAAAAiAAA=","299":"b:AAAcAAAgAAAGYBAAAAAAAABgAAEAAAAAAAAiAAA=","313":"b:AAAcAAAgAAAGYBAAAAAAAABgAAEAAAAAAAAiAAA=","324":"b:AAAcAAAgAAAGYBAAAAAAAABgAAEAAAAAAAAiAAA=","336":"b:AAAcAAAgAAAGYBAAAAAAAABgAAEAAAAAAAAiAAA=","342":"b:AAAcAAAgAAAGYBAAAAAAAABgAAEAAAAAAAAiAAA=","355":"b:AAAcAAAgAAAGYBAAAAAAAABgAAEAAAAAAAAiAAA=","368":"b:AAAcAAAgAAAGYBAAAAAAAABgAAEAAAAAAAAiAAA=","394":"b:AAAcAAAgAAAGYBAAAAAAAABgAAEAAAAAAAAiAAA=","437":"b:AAAcAAAgAAAGYBAAAAAAAABgAAEAAAAAAAAiAAA=","441":"b:AAAcAAAgAAAGYBAAAAAAAABgAAEAAAAAAAAiAAA=","467":"b:AAAcAAAgAAAGYBAAAAAAAABgAAEAAAAAAAAiAAA=","476":"b:AAAcAAAgAAAGYBAAAAAAAABgAAEAAAAAAAAiAAA=","488":"b:AAAcAAAgAAAGYBAAAAAAAABgAAEAAAAAAAAiAAA=","492":"b:AAAcAAAgAAAGYBAAAAAAAABgAAEAAAAAAAAiAAA="},"packages/cli/src/services/engine-data-plane-proxy.service.ts":{"25":"b:AAAABAiEviEBAxhAIIGAAEEDAAAAEAAAAACAAAA=","73":"b:AAAABAiEviEBAxhAIIGAAEEDAAAAEAAAAACAAAA=","76":"b:AAAABAiEviEBAxhAIIGAAEEDAAAAEAAAAACAAAA=","81":"b:AAAABAiEviEBAxhAIIGAAEEDAAAAEAAAAACAAAA=","85":"b:AAAABAiEviEBAxhAIIGAAEEDAAAAEAAAAACAAAA=","90":"b:AAAABAiEviEBAxhAIIGAAEEDAAAAEAAAAACAAAA=","101":"b:AAAABAiEviEBAxhAIIGAAEEDAAAAEAAAAACAAAA=","111":"b:AAAABAiEviEBAxhAIIGAAEEDAAAAEAAAAACAAAA="},"packages/cli/src/services/execution-metadata.service.ts":{"7":[9,84,85,10,18,19,20,184,198],"9":[9,84,85,10,18,19,20,184,198]},"packages/cli/src/services/naming.service.ts":{"6":"b:4EnCAKAoARBgfHQoCRAAEPAKIA1AAYEAAAAEAAA=","11":"b:4EnCAKAoARBgfHQoCRAAEPAKIA1AAYEAAAAEAAA=","15":"b:4EnCAKAoARBgfHQoCRAAEPAKIA1AAYEAAAAEAAA=","19":"b:4EnCAKAoARBgfHQoCRAAEPAKIA1AAYEAAAAEAAA=","28":"b:4EnCAKAoARBgfHQoCRAAEPAKIA1AAYEAAAAEAAA="},"packages/cli/src/utils/get-item-count-by-connection-type.ts":{"4":"b:cEcAEAjBAABAGjAIAxAAQMQ3AAAACAAAAAAAAAA=","15":"b:cEcAEAjBAABAGjAIAxAAQMQ3AAAACAAAAAAAAAA="},"packages/cli/src/utils/strapi-utils.ts":{"57":"b:8E/CACDpAQD0PnQoCRAAAEAIAAEAAAAAAAAAAAA=","69":"b:8E/CACDpAQD0PnQoCRAAAEAIAAEAAAAAAAAAAAA=","79":"b:8E/CACDpAQD0PnQoCRAAAEAIAAEAAAAAAAAAAAA=","135":"b:8E/CACDpAQD0PnQoCRAAAEAIAAEAAAAAAAAAAAA="},"packages/cli/src/wait-tracker.ts":{"37":"b:oACSExioANzEGDw4SQiAAgCDsAkAAAAAAAAAAQY=","54":"b:oACSExioANzEGDw4SQiAAgCDsAkAAAAAAAAAAQY=","67":"b:oACSExioANzEGDw4SQiAAgCDsAkAAAAAAAAAAQY=","72":"b:oACSExioANzEGDw4SQiAAgCDsAkAAAAAAAAAAQY=","76":"b:oACSExioANzEGDw4SQiAAgCDsAkAAAAAAAAAAQY=","81":"b:oACSExioANzEGDw4SQiAAgCDsAkAAAAAAAAAAQY=","83":"b:oACSExioANzEGDw4SQiAAgCDsAkAAAAAAAAAAQY=","94":"b:oACSExioANzEGDw4SQiAAgCDsAkAAAAAAAAAAQY=","103":"b:oACSExioANzEGDw4SQiAAgCDsAkAAAAAAAAAAQY=","116":"b:oACSExioANzEGDw4SQiAAgCDsAkAAAAAAAAAAQY=","117":"b:oACSExioANzEGDw4SQiAAgCDsAkAAAAAAAAAAQY=","137":"b:oACSExioANzEGDw4SQiAAgCDsAkAAAAAAAAAAQY=","145":"b:oACSExioANzEGDw4SQiAAgCDsAkAAAAAAAAAAQY=","215":"b:oACSExioANzEGDw4SQiAAgCDsAkAAAAAAAAAAQY=","254":"b:oACSExioANzEGDw4SQiAAgCDsAkAAAAAAAAAAQY=","263":"b:oACSExioANzEGDw4SQiAAgCDsAkAAAAAAAAAAQY=","283":"b:oACSExioANzEGDw4SQiAAgCDsAkAAAAAAAAAAQY=","289":"b:oACSExioANzEGDw4SQiAAgCDsAkAAAAAAAAAAQY=","291":"b:oACSExioANzEGDw4SQiAAgCDsAkAAAAAAAAAAQY=","312":"b:oACSExioANzEGDw4SQiAAgCDsAkAAAAAAAAAAQY=","347":"b:oACSExioANzEGDw4SQiAAgCDsAkAAAAAAAAAAQY=","357":"b:oACSExioANzEGDw4SQiAAgCDsAkAAAAAAAAAAQY=","365":"b:oACSExioANzEGDw4SQiAAgCDsAkAAAAAAAAAAQY=","412":"b:oACSExioANzEGDw4SQiAAgCDsAkAAAAAAAAAAQY=","415":"b:oACSExioANzEGDw4SQiAAgCDsAkAAAAAAAAAAQY=","429":"b:oACSExioANzEGDw4SQiAAgCDsAkAAAAAAAAAAQY=","433":"b:oACSExioANzEGDw4SQiAAgCDsAkAAAAAAAAAAQY="},"packages/cli/src/webhooks/engine-v2-webhooks.ts":{"71":"b:ANYABACAACABADgAgAmAAAQDAEAAAAAAAAAAoAA=","77":"b:ANYABACAACABADgAgAmAAAQDAEAAAAAAAAAAoAA=","96":"b:ANYABACAACABADgAgAmAAAQDAEAAAAAAAAAAoAA=","144":"b:ANYABACAACABADgAgAmAAAQDAEAAAAAAAAAAoAA=","152":"b:ANYABACAACABADgAgAmAAAQDAEAAAAAAAAAAoAA="},"packages/cli/src/webhooks/node-type-matcher.ts":{"5":"b:ANYABACAACABADAAgAmAAAQDAEAAAAAAAAAAoAA="},"packages/cli/src/webhooks/test-webhook-registrations.service.ts":{"41":"b:AAYAAAAAAAAAADAAEgAAAAQDCEAAQAAAQAAAAAA=","52":"b:AAYAAAAAAAAAADAAEgAAAAQDCEAAQAAAQAAAAAA=","60":"b:AAYAAAAAAAAAADAAEgAAAAQDCEAAQAAAQAAAAAA=","67":"b:AAYAAAAAAAAAADAAEgAAAAQDCEAAQAAAQAAAAAA=","107":"b:AAYAAAAAAAAAADAAEgAAAAQDCEAAQAAAQAAAAAA=","116":"b:AAYAAAAAAAAAADAAEgAAAAQDCEAAQAAAQAAAAAA=","122":"b:AAYAAAAAAAAAADAAEgAAAAQDCEAAQAAAQAAAAAA=","130":"b:AAYAAAAAAAAAADAAEgAAAAQDCEAAQAAAQAAAAAA=","140":"b:AAYAAAAAAAAAADAAEgAAAAQDCEAAQAAAQAAAAAA=","155":"b:AAYAAAAAAAAAADAAEgAAAAQDCEAAQAAAQAAAAAA=","164":"b:AAYAAAAAAAAAADAAEgAAAAQDCEAAQAAAQAAAAAA="},"packages/cli/src/webhooks/webhook-execution-context.ts":{"21":"b:ANYABACAACABADgAgAmAAAQDAEAAAAAAAAAAoAA=","32":"b:ANYABACAACABADgAgAmAAAQDAEAAAAAAAAAAoAA=","53":"b:ANYABACAACABADgAgAmAAAQDAEAAAAAAAAAAoAA=","80":"b:ANYABACAACABADgAgAmAAAQDAEAAAAAAAAAAoAA="},"packages/cli/src/webhooks/webhook-last-node-response-extractor.ts":{"30":[9,84,10,223,15,103,107,173,137,97],"72":[9,84,10,223,15,103,107,173,137,97],"117":[9,84,10,223,15,103,107,173,137,97],"184":[9,84,10,223,15,103,107,173,137,97]},"packages/cli/src/webhooks/webhook-request-handler.ts":{"34":"b:ANYADACAACABADgAggmAAAQDAEAAMAAAQAAAsAI=","43":"b:ANYADACAACABADgAggmAAAQDAEAAMAAAQAAAsAI=","97":"b:ANYADACAACABADgAggmAAAQDAEAAMAAAQAAAsAI=","113":"b:ANYADACAACABADgAggmAAAQDAEAAMAAAQAAAsAI=","122":"b:ANYADACAACABADgAggmAAAQDAEAAMAAAQAAAsAI=","125":"b:ANYADACAACABADgAggmAAAQDAEAAMAAAQAAAsAI=","138":"b:ANYADACAACABADgAggmAAAQDAEAAMAAAQAAAsAI=","144":"b:ANYADACAACABADgAggmAAAQDAEAAMAAAQAAAsAI=","153":"b:ANYADACAACABADgAggmAAAQDAEAAMAAAQAAAsAI=","183":"b:ANYADACAACABADgAggmAAAQDAEAAMAAAQAAAsAI=","237":"b:ANYADACAACABADgAggmAAAQDAEAAMAAAQAAAsAI=","245":"b:ANYADACAACABADgAggmAAAQDAEAAMAAAQAAAsAI=","284":"b:ANYADACAACABADgAggmAAAQDAEAAMAAAQAAAsAI=","291":"b:ANYADACAACABADgAggmAAAQDAEAAMAAAQAAAsAI="},"packages/cli/src/webhooks/webhook-responder.ts":{"20":"b:ANYADACAACABADgAgAmAAAQDAEAAMAAAAAAAoAk=","23":"b:ANYADACAACABADgAgAmAAAQDAEAAMAAAAAAAoAk=","28":"b:ANYADACAACABADgAgAmAAAQDAEAAMAAAAAAAoAk=","36":"b:ANYADACAACABADgAgAmAAAQDAEAAMAAAAAAAoAk=","42":"b:ANYADACAACABADgAgAmAAAQDAEAAMAAAAAAAoAk=","51":"b:ANYADACAACABADgAgAmAAAQDAEAAMAAAAAAAoAk="},"packages/cli/src/webhooks/webhook-response-headers.ts":{"33":"b:ANYABACAACABADgAgAmAAAQDAEAAMAAAAAAAoAg=","37":"b:ANYABACAACABADgAgAmAAAQDAEAAMAAAAAAAoAg=","44":"b:ANYABACAACABADgAgAmAAAQDAEAAMAAAAAAAoAg=","66":"b:ANYABACAACABADgAgAmAAAQDAEAAMAAAAAAAoAg=","73":"b:ANYABACAACABADgAgAmAAAQDAEAAMAAAAAAAoAg=","82":"b:ANYABACAACABADgAgAmAAAQDAEAAMAAAAAAAoAg=","90":"b:ANYABACAACABADgAgAmAAAQDAEAAMAAAAAAAoAg=","99":"b:ANYABACAACABADgAgAmAAAQDAEAAMAAAAAAAoAg="},"packages/cli/src/webhooks/webhook-response.ts":{"37":"b:ANYABACAACABADgAggmAAAQDAEAAMAAAAAAAoAA=","41":"b:ANYABACAACABADgAggmAAAQDAEAAMAAAAAAAoAA=","45":"b:ANYABACAACABADgAggmAAAQDAEAAMAAAAAAAoAA=","49":"b:ANYABACAACABADgAggmAAAQDAEAAMAAAAAAAoAA=","53":"b:ANYABACAACABADgAggmAAAQDAEAAMAAAAAAAoAA=","59":"b:ANYABACAACABADgAggmAAAQDAEAAMAAAAAAAoAA=","72":"b:ANYABACAACABADgAggmAAAQDAEAAMAAAAAAAoAA="},"packages/cli/src/workflows/error-workflow-validation.service.ts":{"36":"b:wAECEIykAAD2KBggAREAROgIAAAAIAIAAAAAAAA=","49":"b:wAECEIykAAD2KBggAREAROgIAAAAIAIAAAAAAAA=","77":"b:wAECEIykAAD2KBggAREAROgIAAAAIAIAAAAAAAA=","86":"b:wAECEIykAAD2KBggAREAROgIAAAAIAIAAAAAAAA=","130":"b:wAECEIykAAD2KBggAREAROgIAAAAIAIAAAAAAAA="},"packages/cli/src/workflows/publication/workflow-publication-status.service.ts":{"16":"b:8G+CkGzpAAD0PncpCxAASEAKAAEAAAAAAAIgAAA=","31":"b:8G+CkGzpAAD0PncpCxAASEAKAAEAAAAAAAIgAAA=","40":"b:8G+CkGzpAAD0PncpCxAASEAKAAEAAAAAAAIgAAA=","50":"b:8G+CkGzpAAD0PncpCxAASEAKAAEAAAAAAAIgAAA=","64":"b:8G+CkGzpAAD0PncpCxAASEAKAAEAAAAAAAIgAAA=","83":"b:8G+CkGzpAAD0PncpCxAASEAKAAEAAAAAAAIgAAA=","90":"b:8G+CkGzpAAD0PncpCxAASEAKAAEAAAAAAAIgAAA=","91":"b:8G+CkGzpAAD0PncpCxAASEAKAAEAAAAAAAIgAAA=","92":"b:8G+CkGzpAAD0PncpCxAASEAKAAEAAAAAAAIgAAA=","94":"b:8G+CkGzpAAD0PncpCxAASEAKAAEAAAAAAAIgAAA=","101":"b:8G+CkGzpAAD0PncpCxAASEAKAAEAAAAAAAIgAAA=","107":"b:8G+CkGzpAAD0PncpCxAASEAKAAEAAAAAAAIgAAA=","115":"b:8G+CkGzpAAD0PncpCxAASEAKAAEAAAAAAAIgAAA="},"packages/cli/src/workflows/workflow-history/workflow-history.controller.ts":{"20":"b:EA4AkAzhAACUghQgDQAAQGxKEUAAEgYAAAgAAAA=","23":"b:EA4AkAzhAACUghQgDQAAQGxKEUAAEgYAAAgAAAA=","40":"b:EA4AkAzhAACUghQgDQAAQGxKEUAAEgYAAAgAAAA=","59":"b:EA4AkAzhAACUghQgDQAAQGxKEUAAEgYAAAgAAAA=","80":"b:EA4AkAzhAACUghQgDQAAQGxKEUAAEgYAAAgAAAA=","100":"b:EA4AkAzhAACUghQgDQAAQGxKEUAAEgYAAAgAAAA="},"packages/cli/src/workflows/workflow-static-data.service.ts":{"11":"b:APYgBACE/iExgDtAgImBCAQDAAAAEAAAAAAgoAA=","18":"b:APYgBACE/iExgDtAgImBCAQDAAAAEAAAAAAgoAA=","27":"b:APYgBACE/iExgDtAgImBCAQDAAAAEAAAAAAgoAA=","48":"b:APYgBACE/iExgDtAgImBCAQDAAAAEAAAAAAgoAA=","54":"b:APYgBACE/iExgDtAgImBCAQDAAAAEAAAAAAgoAA="},"packages/community-node-types-utils.ts":{"33":"b:8E/CACDpAQD0PnQoCRAAAEAIAAEAAAAAAAAAAAA=","41":"b:8E/CACDpAQD0PnQoCRAAAEAIAAEAAAAAAAAAAAA=","53":"b:8E/CACDpAQD0PnQoCRAAAEAIAAEAAAAAAAAAAAA=","59":"b:8E/CACDpAQD0PnQoCRAAAEAIAAEAAAAAAAAAAAA=","78":"b:8E/CACDpAQD0PnQoCRAAAEAIAAEAAAAAAAAAAAA="},"packages/community-node-types.controller.ts":{"9":"b:8E/CkCzpAQT0PnQoCRAAQEAIAAEAAACAAAAAAAA=","12":"b:8E/CkCzpAQT0PnQoCRAAQEAIAAEAAACAAAAAAAA=","17":"b:8E/CkCzpAQT0PnQoCRAAQEAIAAEAAACAAAAAAAA="},"packages/community-node-types.service.ts":{"32":"b:8E/CkCzpAQT0PnQoCRAAQEAIAAEAAACAAAAAAAA=","43":"b:8E/CkCzpAQT0PnQoCRAAQEAIAAEAAACAAAAAAAA=","55":"b:8E/CkCzpAQT0PnQoCRAAQEAIAAEAAACAAAAAAAA=","73":"b:8E/CkCzpAQT0PnQoCRAAQEAIAAEAAACAAAAAAAA=","104":"b:8E/CkCzpAQT0PnQoCRAAQEAIAAEAAACAAAAAAAA=","152":"b:8E/CkCzpAQT0PnQoCRAAQEAIAAEAAACAAAAAAAA=","160":"b:8E/CkCzpAQT0PnQoCRAAQEAIAAEAAACAAAAAAAA=","176":"b:8E/CkCzpAQT0PnQoCRAAQEAIAAEAAACAAAAAAAA=","178":"b:8E/CkCzpAQT0PnQoCRAAQEAIAAEAAACAAAAAAAA=","191":"b:8E/CkCzpAQT0PnQoCRAAQEAIAAEAAACAAAAAAAA=","213":"b:8E/CkCzpAQT0PnQoCRAAQEAIAAEAAACAAAAAAAA=","219":"b:8E/CkCzpAQT0PnQoCRAAQEAIAAEAAACAAAAAAAA=","224":"b:8E/CkCzpAQT0PnQoCRAAQEAIAAEAAACAAAAAAAA=","229":"b:8E/CkCzpAQT0PnQoCRAAQEAIAAEAAACAAAAAAAA=","231":"b:8E/CkCzpAQT0PnQoCRAAQEAIAAEAAACAAAAAAAA=","237":"b:8E/CkCzpAQT0PnQoCRAAQEAIAAEAAACAAAAAAAA=","241":"b:8E/CkCzpAQT0PnQoCRAAQEAIAAEAAACAAAAAAAA=","249":"b:8E/CkCzpAQT0PnQoCRAAQEAIAAEAAACAAAAAAAA=","250":"b:8E/CkCzpAQT0PnQoCRAAQEAIAAEAAACAAAAAAAA=","256":"b:8E/CkCzpAQT0PnQoCRAAQEAIAAEAAACAAAAAAAA=","271":"b:8E/CkCzpAQT0PnQoCRAAQEAIAAEAAACAAAAAAAA=","278":"b:8E/CkCzpAQT0PnQoCRAAQEAIAAEAAACAAAAAAAA=","283":"b:8E/CkCzpAQT0PnQoCRAAQEAIAAEAAACAAAAAAAA="},"packages/core/src/credentials.ts":{"11":"b:ACCeAAIxABAHYDwIACAAFCAAAQAAIAAAAAAAYAA=","19":"b:ACCeAAIxABAHYDwIACAAFCAAAQAAIAAAAAAAYAA=","27":"b:ACCeAAIxABAHYDwIACAAFCAAAQAAIAAAAAAAYAA=","37":"b:ACCeAAIxABAHYDwIACAAFCAAAQAAIAAAAAAAYAA=","48":"b:ACCeAAIxABAHYDwIACAAFCAAAQAAIAAAAAAAYAA=","72":"b:ACCeAAIxABAHYDwIACAAFCAAAQAAIAAAAAAAYAA="},"packages/core/src/errors/error-reporter.ts":{"100":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","117":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","125":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","157":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","163":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","184":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","190":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","195":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","239":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","240":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","286":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","287":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","300":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","327":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","331":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","346":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","352":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","400":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","406":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","410":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","414":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","421":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","426":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","430":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","434":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","446":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE=","468":"b:YAAwAhiAAAAGYDQAEAAAAAABAAEBAAAAACAAAAE="},"packages/core/src/execution-engine/node-execution-context/load-options-context.ts":{"21":[84,152,18,19,20,65,66,209,77,78,141],"42":[84,152,18,19,20,65,66,209,77,78,141],"46":[84,152,18,19,20,65,66,209,77,78,141],"50":[84,152,18,19,20,65,66,209,77,78,141],"79":[84,152,18,19,20,65,66,209,77,78,141]},"packages/core/src/execution-engine/node-execution-context/supply-data-context.ts":{"64":[4,84,85,10,18,19,20,125,221],"109":[4,84,85,10,18,19,20,125,221],"111":[4,84,85,10,18,19,20,125,221],"119":[4,84,85,10,18,19,20,125,221],"126":[4,84,85,10,18,19,20,125,221],"141":[4,84,85,10,18,19,20,125,221],"168":[4,84,85,10,18,19,20,125,221],"176":[4,84,85,10,18,19,20,125,221],"197":[4,84,85,10,18,19,20,125,221],"205":[4,84,85,10,18,19,20,125,221],"211":[4,84,85,10,18,19,20,125,221],"216":[4,84,85,10,18,19,20,125,221],"232":[4,84,85,10,18,19,20,125,221],"245":[4,84,85,10,18,19,20,125,221],"261":[4,84,85,10,18,19,20,125,221],"271":[4,84,85,10,18,19,20,125,221],"410":[4,84,85,10,18,19,20,125,221],"437":[4,84,85,10,18,19,20,125,221],"439":[4,84,85,10,18,19,20,125,221],"454":[4,84,85,10,18,19,20,125,221]},"packages/core/src/execution-engine/node-execution-context/trigger-context.ts":{"21":"b:cCUAEAjFoAFwghAIY4AASMEXAAQAAAAAAAAAAAA=","25":"b:cCUAEAjFoAFwghAIY4AASMEXAAQAAAAAAAAAAAA=","29":"b:cCUAEAjFoAFwghAIY4AASMEXAAQAAAAAAAAAAAA=","36":"b:cCUAEAjFoAFwghAIY4AASMEXAAQAAAAAAAAAAAA=","63":"b:cCUAEAjFoAFwghAIY4AASMEXAAQAAAAAAAAAAAA=","67":"b:cCUAEAjFoAFwghAIY4AASMEXAAQAAAAAAAAAAAA=","72":"b:cCUAEAjFoAFwghAIY4AASMEXAAQAAAAAAAAAAAA="},"packages/core/src/execution-engine/node-execution-context/utils/ai-tool-types.ts":{"13":[4,84,85,10,18,19,20,125,221],"17":[4,84,85,10,18,19,20,125,221],"23":[4,84,85,10,18,19,20,125,221]},"packages/core/src/execution-engine/node-execution-context/utils/execution-metadata.ts":{"10":[9,84,85,10,18,19,184,198,137],"52":[9,84,85,10,18,19,184,198,137],"57":[9,84,85,10,18,19,184,198,137],"69":[9,84,85,10,18,19,184,198,137],"76":[9,84,85,10,18,19,184,198,137]},"packages/core/src/execution-engine/node-execution-context/utils/get-input-connection-data.ts":{"46":[4,84,85,10,18,19,20,125,221],"52":[4,84,85,10,18,19,20,125,221],"64":[4,84,85,10,18,19,20,125,221],"68":[4,84,85,10,18,19,20,125,221],"78":[4,84,85,10,18,19,20,125,221],"91":[4,84,85,10,18,19,20,125,221],"118":[4,84,85,10,18,19,20,125,221],"158":[4,84,85,10,18,19,20,125,221],"162":[4,84,85,10,18,19,20,125,221],"171":[4,84,85,10,18,19,20,125,221],"174":[4,84,85,10,18,19,20,125,221],"183":[4,84,85,10,18,19,20,125,221],"184":[4,84,85,10,18,19,20,125,221],"192":[4,84,85,10,18,19,20,125,221],"223":[4,84,85,10,18,19,20,125,221],"235":[4,84,85,10,18,19,20,125,221],"249":[4,84,85,10,18,19,20,125,221],"343":[4,84,85,10,18,19,20,125,221],"363":[4,84,85,10,18,19,20,125,221],"366":[4,84,85,10,18,19,20,125,221],"380":[4,84,85,10,18,19,20,125,221],"395":[4,84,85,10,18,19,20,125,221],"411":[4,84,85,10,18,19,20,125,221],"420":[4,84,85,10,18,19,20,125,221],"473":[4,84,85,10,18,19,20,125,221],"496":[4,84,85,10,18,19,20,125,221],"579":[4,84,85,10,18,19,20,125,221]},"packages/core/src/execution-engine/node-execution-context/utils/get-secrets-proxy.ts":{"4":"b:AAAcAAABAAAAQDwIACAAEAQAAAAAIAAAAAAAIAA=","6":"b:AAAcAAABAAAAQDwIACAAEAQAAAAAIAAAAAAAIAA=","25":"b:AAAcAAABAAAAQDwIACAAEAQAAAAAIAAAAAAAIAA=","30":"b:AAAcAAABAAAAQDwIACAAEAQAAAAAIAAAAAAAIAA=","50":"b:AAAcAAABAAAAQDwIACAAEAQAAAAAIAAAAAAAIAA=","66":"b:AAAcAAABAAAAQDwIACAAEAQAAAAAIAAAAAAAIAA=","69":"b:AAAcAAABAAAAQDwIACAAEAQAAAAAIAAAAAAAIAA=","75":"b:AAAcAAABAAAAQDwIACAAEAQAAAAAIAAAAAAAIAA=","78":"b:AAAcAAABAAAAQDwIACAAEAQAAAAAIAAAAAAAIAA="},"packages/core/src/execution-engine/node-execution-context/utils/return-json-array.ts":{"8":"b:cAcAEAjFHgBAAjBIYwAAQME3AAAAAAAAAAAAAAA=","15":"b:cAcAEAjFHgBAAjBIYwAAQME3AAAAAAAAAAAAAAA="},"packages/core/src/execution-engine/node-execution-context/utils/scheduling-helper-functions.ts":{"8":"b:cAUAEAjFHgBAAhBIYwAASME3AAQAAAAAAAAAAAA=","15":"b:cAUAEAjFHgBAAhBIYwAASME3AAQAAAAAAAAAAAA="},"packages/core/src/execution-engine/node-execution-context/webhook-context.ts":{"41":"b:ANYADACAACAJADgAgAmAKAQDCEAAMAABQAAAoAA=","95":"b:ANYADACAACAJADgAgAmAKAQDCEAAMAABQAAAoAA=","99":"b:ANYADACAACAJADgAgAmAKAQDCEAAMAABQAAAoAA=","103":"b:ANYADACAACAJADgAgAmAKAQDCEAAMAABQAAAoAA=","107":"b:ANYADACAACAJADgAgAmAKAQDCEAAMAABQAAAoAA=","111":"b:ANYADACAACAJADgAgAmAKAQDCEAAMAABQAAAoAA=","115":"b:ANYADACAACAJADgAgAmAKAQDCEAAMAABQAAAoAA=","119":"b:ANYADACAACAJADgAgAmAKAQDCEAAMAABQAAAoAA=","126":"b:ANYADACAACAJADgAgAmAKAQDCEAAMAABQAAAoAA=","134":"b:ANYADACAACAJADgAgAmAKAQDCEAAMAABQAAAoAA=","145":"b:ANYADACAACAJADgAgAmAKAQDCEAAMAABQAAAoAA=","159":"b:ANYADACAACAJADgAgAmAKAQDCEAAMAABQAAAoAA=","163":"b:ANYADACAACAJADgAgAmAKAQDCEAAMAABQAAAoAA=","167":"b:ANYADACAACAJADgAgAmAKAQDCEAAMAABQAAAoAA=","176":"b:ANYADACAACAJADgAgAmAKAQDCEAAMAABQAAAoAA=","184":"b:ANYADACAACAJADgAgAmAKAQDCEAAMAABQAAAoAA=","191":"b:ANYADACAACAJADgAgAmAKAQDCEAAMAABQAAAoAA=","201":"b:ANYADACAACAJADgAgAmAKAQDCEAAMAABQAAAoAA=","208":"b:ANYADACAACAJADgAgAmAKAQDCEAAMAABQAAAoAA=","218":"b:ANYADACAACAJADgAgAmAKAQDCEAAMAABQAAAoAA=","228":"b:ANYADACAACAJADgAgAmAKAQDCEAAMAABQAAAoAA=","235":"b:ANYADACAACAJADgAgAmAKAQDCEAAMAABQAAAoAA=","242":"b:ANYADACAACAJADgAgAmAKAQDCEAAMAABQAAAoAA="},"packages/core/src/execution-engine/triggers-and-pollers.ts":{"25":"b:cCUAEAjFvgFwghBIYwAASME3AAQAAAAAAAAAAAA=","60":"b:cCUAEAjFvgFwghBIYwAASME3AAQAAAAAAAAAAAA=","68":"b:cCUAEAjFvgFwghBIYwAASME3AAQAAAAAAAAAAAA=","79":"b:cCUAEAjFvgFwghBIYwAASME3AAQAAAAAAAAAAAA=","104":"b:cCUAEAjFvgFwghBIYwAASME3AAQAAAAAAAAAAAA=","108":"b:cCUAEAjFvgFwghBIYwAASME3AAQAAAAAAAAAAAA=","114":"b:cCUAEAjFvgFwghBIYwAASME3AAQAAAAAAAAAAAA=","118":"b:cCUAEAjFvgFwghBIYwAASME3AAQAAAAAAAAAAAA=","124":"b:cCUAEAjFvgFwghBIYwAASME3AAQAAAAAAAAAAAA=","129":"b:cCUAEAjFvgFwghBIYwAASME3AAQAAAAAAAAAAAA=","134":"b:cCUAEAjFvgFwghBIYwAASME3AAQAAAAAAAAAAAA=","150":"b:cCUAEAjFvgFwghBIYwAASME3AAQAAAAAAAAAAAA=","156":"b:cCUAEAjFvgFwghBIYwAASME3AAQAAAAAAAAAAAA=","157":"b:cCUAEAjFvgFwghBIYwAASME3AAQAAAAAAAAAAAA=","165":"b:cCUAEAjFvgFwghBIYwAASME3AAQAAAAAAAAAAAA="},"packages/core/src/html-sandbox.ts":{"4":"b:ANYADACAACABABgAoAmAAAQHAEAAEAAAAAAAgAA=","8":"b:ANYADACAACABABgAoAmAAAQHAEAAEAAAAAAAgAA=","15":"b:ANYADACAACABABgAoAmAAAQHAEAAEAAAAAAAgAA="},"packages/core/src/instance-settings/instance-settings.ts":{"96":[9,84,85,10,147,158,130,198,136,137,97,100],"123":[9,84,85,10,147,158,130,198,136,137,97,100],"133":[9,84,85,10,147,158,130,198,136,137,97,100],"134":[9,84,85,10,147,158,130,198,136,137,97,100],"143":[9,84,85,10,147,158,130,198,136,137,97,100],"144":[9,84,85,10,147,158,130,198,136,137,97,100],"151":[9,84,85,10,147,158,130,198,136,137,97,100],"180":[9,84,85,10,147,158,130,198,136,137,97,100],"229":[9,84,85,10,147,158,130,198,136,137,97,100],"233":[9,84,85,10,147,158,130,198,136,137,97,100],"238":[9,84,85,10,147,158,130,198,136,137,97,100],"243":[9,84,85,10,147,158,130,198,136,137,97,100],"247":[9,84,85,10,147,158,130,198,136,137,97,100],"251":[9,84,85,10,147,158,130,198,136,137,97,100],"255":[9,84,85,10,147,158,130,198,136,137,97,100],"259":[9,84,85,10,147,158,130,198,136,137,97,100],"263":[9,84,85,10,147,158,130,198,136,137,97,100],"267":[9,84,85,10,147,158,130,198,136,137,97,100],"271":[9,84,85,10,147,158,130,198,136,137,97,100],"275":[9,84,85,10,147,158,130,198,136,137,97,100],"279":[9,84,85,10,147,158,130,198,136,137,97,100],"287":[9,84,85,10,147,158,130,198,136,137,97,100],"310":[9,84,85,10,147,158,130,198,136,137,97,100],"318":[9,84,85,10,147,158,130,198,136,137,97,100],"365":[9,84,85,10,147,158,130,198,136,137,97,100],"372":[9,84,85,10,147,158,130,198,136,137,97,100],"380":[9,84,85,10,147,158,130,198,136,137,97,100],"388":[9,84,85,10,147,158,130,198,136,137,97,100],"416":[9,84,85,10,147,158,130,198,136,137,97,100],"421":[9,84,85,10,147,158,130,198,136,137,97,100],"442":[9,84,85,10,147,158,130,198,136,137,97,100],"454":[9,84,85,10,147,158,130,198,136,137,97,100]},"packages/core/src/node-execute-functions.ts":{"17":"b:cAUAEAjBAABAAhAIYwAASME3AAQAAAAAAAAAAAA=","31":"b:cAUAEAjBAABAAhAIYwAASME3AAQAAAAAAAAAAAA="},"packages/nodes-base/nodes/Code/JsCodeValidator.ts":{"8":"b:cCQAAADAAABEAhQAIRAAIMMTAAAAAAAIAAgAAAA=","15":"b:cCQAAADAAABEAhQAIRAAIMMTAAAAAAAIAAgAAAA=","42":"b:cCQAAADAAABEAhQAIRAAIMMTAAAAAAAIAAgAAAA=","54":"b:cCQAAADAAABEAhQAIRAAIMMTAAAAAAAIAAgAAAA="},"packages/nodes-base/nodes/Code/JsTaskRunnerSandbox.ts":{"20":"b:cAQAAADAAABEAhQAoRAAIMMTAAAAAAAIAAgEIAA=","30":"b:cAQAAADAAABEAhQAoRAAIMMTAAAAAAAIAAgEIAA=","56":"b:cAQAAADAAABEAhQAoRAAIMMTAAAAAAAIAAgEIAA=","78":"b:cAQAAADAAABEAhQAoRAAIMMTAAAAAAAIAAgEIAA=","123":"b:cAQAAADAAABEAhQAoRAAIMMTAAAAAAAIAAgEIAA=","145":"b:cAQAAADAAABEAhQAoRAAIMMTAAAAAAAIAAgEIAA="},"packages/nodes-base/nodes/Code/PythonTaskRunnerSandbox.ts":{"18":"b:cAQAAADAAABEAhQAIRAAIMETAAAAAAAIAAgAAAA=","26":"b:cAQAAADAAABEAhQAIRAAIMETAAAAAAAIAAgAAAA=","42":"b:cAQAAADAAABEAhQAIRAAIMETAAAAAAAIAAgAAAA=","80":"b:cAQAAADAAABEAhQAIRAAIMETAAAAAAAIAAgAAAA=","98":"b:cAQAAADAAABEAhQAIRAAIMETAAAAAAAIAAgAAAA="},"packages/nodes-base/nodes/Code/ValidationError.ts":{"12":"b:cCQAAADAAABEAhQAIRAAIMETAAAAAAAIAAgAAAA="},"packages/nodes-base/nodes/Code/errors/WrappedExecutionError.ts":{"19":"b:cAQAAADAAABEAhQAIRAAIMETAAAAABAIAAiAAAA=","29":"b:cAQAAADAAABEAhQAIRAAIMETAAAAABAIAAiAAAA=","37":"b:cAQAAADAAABEAhQAIRAAIMETAAAAABAIAAiAAAA="},"packages/nodes-base/nodes/Code/reserved-key-found-error.ts":{"4":"b:cCQAAADAAABEAhQAIRAAIMETAAAAAAAIAAgAAAA="},"packages/nodes-base/nodes/Code/result-validation.ts":{"16":"b:cCQAAADAAABEAxQAoRAAIMMTAAAAAAAIAAgEAAA=","25":"b:cCQAAADAAABEAxQAoRAAIMMTAAAAAAAIAAgEAAA=","31":"b:cCQAAADAAABEAxQAoRAAIMMTAAAAAAAIAAgEAAA=","61":"b:cCQAAADAAABEAxQAoRAAIMMTAAAAAAAIAAgEAAA=","86":"b:cCQAAADAAABEAxQAoRAAIMMTAAAAAAAIAAgEAAA=","126":"b:cCQAAADAAABEAxQAoRAAIMMTAAAAAAAIAAgEAAA=","159":"b:cCQAAADAAABEAxQAoRAAIMMTAAAAAAAIAAgEAAA=","160":"b:cCQAAADAAABEAxQAoRAAIMMTAAAAAAAIAAgEAAA=","172":"b:cCQAAADAAABEAxQAoRAAIMMTAAAAAAAIAAgEAAA="},"packages/nodes-base/nodes/Code/throw-execution-error.ts":{"5":"b:cAQAAADAAABEAhQAIRAAIMETAAAAABAIAAiAAAA="},"packages/nodes-base/nodes/Code/utils.ts":{"3":"b:cCQAAADAAABEAxQAoRAAIMETAAAAAAAIAAgEAAA=","9":"b:cCQAAADAAABEAxQAoRAAIMETAAAAAAAIAAgEAAA=","16":"b:cCQAAADAAABEAxQAoRAAIMETAAAAAAAIAAgEAAA=","17":"b:cCQAAADAAABEAxQAoRAAIMETAAAAAAAIAAgEAAA=","40":"b:cCQAAADAAABEAxQAoRAAIMETAAAAAAAIAAgEAAA=","47":"b:cCQAAADAAABEAxQAoRAAIMETAAAAAAAIAAgEAAA="},"packages/nodes-base/nodes/ManualTrigger/ManualTrigger.node.ts":{"40":"b:8AWCkAzhAADAJlAMawAASME/AAUAAAAAAAAAAAA=","41":"b:8AWCkAzhAADAJlAMawAASME/AAUAAAAAAAAAAAA="},"packages/nodes-base/nodes/Schedule/GenericFunctions.ts":{"17":"b:oCAAAEAA4AE2mBEABwAAAAADAAAACAAAACIAAAA=","18":"b:oCAAAEAA4AE2mBEABwAAAAADAAAACAAAACIAAAA=","20":"b:oCAAAEAA4AE2mBEABwAAAAADAAAACAAAACIAAAA=","54":"b:oCAAAEAA4AE2mBEABwAAAAADAAAACAAAACIAAAA=","87":"b:oCAAAEAA4AE2mBEABwAAAAADAAAACAAAACIAAAA=","164":"b:oCAAAEAA4AE2mBEABwAAAAADAAAACAAAACIAAAA=","169":"b:oCAAAEAA4AE2mBEABwAAAAADAAAACAAAACIAAAA=","217":"b:oCAAAEAA4AE2mBEABwAAAAADAAAACAAAACIAAAA=","236":"b:oCAAAEAA4AE2mBEABwAAAAADAAAACAAAACIAAAA=","309":"b:oCAAAEAA4AE2mBEABwAAAAADAAAACAAAACIAAAA=","339":"b:oCAAAEAA4AE2mBEABwAAAAADAAAACAAAACIAAAA=","346":"b:oCAAAEAA4AE2mBEABwAAAAADAAAACAAAACIAAAA="},"packages/nodes-base/nodes/Schedule/ScheduleTrigger.node.ts":{"484":"b:oCAAAEAAoAE2mBEABwAAAAADAAAACAAAACIAAAA=","509":"b:oCAAAEAAoAE2mBEABwAAAAADAAAACAAAACIAAAA=","550":"b:oCAAAEAAoAE2mBEABwAAAAADAAAACAAAACIAAAA=","567":"b:oCAAAEAAoAE2mBEABwAAAAADAAAACAAAACIAAAA=","582":"b:oCAAAEAAoAE2mBEABwAAAAADAAAACAAAACIAAAA="},"packages/workflow/src/common/get-parent-nodes.ts":{"11":"b:cLYcFAyEviF3GDJAAImAQYQRAAAAAAAAAAAEoAA="},"packages/workflow/src/credential-domain-restrictions.ts":{"55":"b:8E/CBCDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","59":"b:8E/CBCDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","66":"b:8E/CBCDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","75":"b:8E/CBCDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","90":"b:8E/CBCDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","95":"b:8E/CBCDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","102":"b:8E/CBCDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","113":"b:8E/CBCDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","134":"b:8E/CBCDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","145":"b:8E/CBCDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","155":"b:8E/CBCDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","180":"b:8E/CBCDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","233":"b:8E/CBCDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA=","291":"b:8E/CBCDpHwT0PnToCTAAAEAIAAEAAAAAAAAAAAA="},"packages/workflow/src/errors/abstract/execution-base.error.ts":{"28":"b:IAAwAAAAAgAGQDgAEACAAAABAAEAAAAAAAAAAAE=","50":"b:IAAwAAAAAgAGQDgAEACAAAABAAEAAAAAAAAAAAE="},"packages/workflow/src/errors/abstract/node.error.ts":{"44":"b:IAAwAAAAAgAGQDAAEAAAAAABAAEAAAAAAAACAAE=","83":"b:IAAwAAAAAgAGQDAAEAAAAAABAAEAAAAAAAACAAE=","107":"b:IAAwAAAAAgAGQDAAEAAAAAABAAEAAAAAAAACAAE=","115":"b:IAAwAAAAAgAGQDAAEAAAAAABAAEAAAAAAAACAAE=","147":"b:IAAwAAAAAgAGQDAAEAAAAAABAAEAAAAAAAACAAE=","157":"b:IAAwAAAAAgAGQDAAEAAAAAABAAEAAAAAAAACAAE="},"packages/workflow/src/errors/node-api.error.ts":{"127":[84,85,152,20,21,209,78],"287":[84,85,152,20,21,209,78],"295":[84,85,152,20,21,209,78],"311":[84,85,152,20,21,209,78]},"packages/workflow/src/errors/node-operation.error.ts":{"12":[5,84,85,224,152,20,21,49,65,66,136,78,100],"34":[5,84,85,224,152,20,21,49,65,66,136,78,100]},"packages/workflow/src/expression-sandboxing.ts":{"28":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","32":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","34":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","82":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","83":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","85":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","98":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","134":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","193":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","194":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","207":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","212":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","222":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","224":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","256":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","280":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","296":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","333":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","335":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","389":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","391":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","400":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","417":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","426":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","434":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","443":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","461":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","470":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","479":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","488":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","497":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","536":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","561":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk=","577":"b:ELYcCAAAACAAEDkAQQGAAQQRAEAAAAEAAIAkoAk="},"packages/workflow/src/extensions/expression-extension.ts":{"25":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA=","29":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA=","64":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA=","66":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA=","69":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA=","77":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA=","79":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA=","95":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA=","124":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA=","133":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA=","160":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA=","174":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA=","183":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA=","196":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA=","208":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA=","387":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA=","405":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA=","440":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA=","457":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA=","519":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA=","527":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA=","535":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA=","555":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA=","571":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA=","579":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA=","583":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA=","584":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA=","599":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA="},"packages/workflow/src/extensions/expression-parser.ts":{"20":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA=","24":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA=","93":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA=","97":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA=","99":"b:MLYcCAAAACAAEDgAQQGAAQQRCEAAAAEAAIAkgAA="},"packages/workflow/src/highlighted-data.ts":{"3":[9,84,85,10,18,19,20,184,198],"7":[9,84,85,10,18,19,20,184,198]},"packages/workflow/src/index.ts":{"30":"b:9v++nGzpACT3fn+o+zngzeQ/CEFAPgAAAAAkoAM=","114":"b:9v++nGzpACT3fn+o+zngzeQ/CEFAPgAAAAAkoAM=","123":"b:9v++nGzpACT3fn+o+zngzeQ/CEFAPgAAAAAkoAM="},"packages/workflow/src/node-parameters/parameter-type-validation.ts":{"15":[9,84,85,10,18,19,20,184,198,137],"30":[9,84,85,10,18,19,20,184,198,137],"39":[9,84,85,10,18,19,20,184,198,137],"47":[9,84,85,10,18,19,20,184,198,137],"55":[9,84,85,10,18,19,20,184,198,137],"69":[9,84,85,10,18,19,20,184,198,137],"75":[9,84,85,10,18,19,20,184,198,137],"82":[9,84,85,10,18,19,20,184,198,137],"103":[9,84,85,10,18,19,20,184,198,137],"110":[9,84,85,10,18,19,20,184,198,137],"121":[9,84,85,10,18,19,20,184,198,137],"133":[9,84,85,10,18,19,20,184,198,137],"141":[9,84,85,10,18,19,20,184,198,137],"142":[9,84,85,10,18,19,20,184,198,137],"148":[9,84,85,10,18,19,20,184,198,137],"162":[9,84,85,10,18,19,20,184,198,137],"175":[9,84,85,10,18,19,20,184,198,137],"197":[9,84,85,10,18,19,20,184,198,137],"246":[9,84,85,10,18,19,20,184,198,137],"259":[9,84,85,10,18,19,20,184,198,137]},"packages/workflow/src/sub-workflow-output.ts":{"18":"b:AIYAAAAAAAAAADAAgAiAAAQCAAAAIAAAAAAwgAo=","22":"b:AIYAAAAAAAAAADAAgAiAAAQCAAAAIAAAAAAwgAo=","28":"b:AIYAAAAAAAAAADAAgAiAAAQCAAAAIAAAAAAwgAo=","32":"b:AIYAAAAAAAAAADAAgAiAAAQCAAAAIAAAAAAwgAo=","37":"b:AIYAAAAAAAAAADAAgAiAAAQCAAAAIAAAAAAwgAo=","50":"b:AIYAAAAAAAAAADAAgAiAAAQCAAAAIAAAAAAwgAo=","59":"b:AIYAAAAAAAAAADAAgAiAAAQCAAAAIAAAAAAwgAo=","82":"b:AIYAAAAAAAAAADAAgAiAAAQCAAAAIAAAAAAwgAo=","84":"b:AIYAAAAAAAAAADAAgAiAAAQCAAAAIAAAAAAwgAo=","90":"b:AIYAAAAAAAAAADAAgAiAAAQCAAAAIAAAAAAwgAo=","91":"b:AIYAAAAAAAAAADAAgAiAAAQCAAAAIAAAAAAwgAo=","92":"b:AIYAAAAAAAAAADAAgAiAAAQCAAAAIAAAAAAwgAo=","93":"b:AIYAAAAAAAAAADAAgAiAAAQCAAAAIAAAAAAwgAo="},"packages/workflow/src/trigger-identity.ts":{"31":[9,84,85,10,26,184,198,137],"46":[9,84,85,10,26,184,198,137],"64":[9,84,85,10,26,184,198,137]},"packages/workflow/src/type-guards.ts":{"15":"b:cPc8FAzBACBBGjkIAzmAQcQ3AEAAHgAAAAAkoAI=","21":"b:cPc8FAzBACBBGjkIAzmAQcQ3AEAAHgAAAAAkoAI=","25":"b:cPc8FAzBACBBGjkIAzmAQcQ3AEAAHgAAAAAkoAI=","29":"b:cPc8FAzBACBBGjkIAzmAQcQ3AEAAHgAAAAAkoAI=","33":"b:cPc8FAzBACBBGjkIAzmAQcQ3AEAAHgAAAAAkoAI=","37":"b:cPc8FAzBACBBGjkIAzmAQcQ3AEAAHgAAAAAkoAI=","41":"b:cPc8FAzBACBBGjkIAzmAQcQ3AEAAHgAAAAAkoAI=","47":"b:cPc8FAzBACBBGjkIAzmAQcQ3AEAAHgAAAAAkoAI=","60":"b:cPc8FAzBACBBGjkIAzmAQcQ3AEAAHgAAAAAkoAI=","70":"b:cPc8FAzBACBBGjkIAzmAQcQ3AEAAHgAAAAAkoAI=","83":"b:cPc8FAzBACBBGjkIAzmAQcQ3AEAAHgAAAAAkoAI=","93":"b:cPc8FAzBACBBGjkIAzmAQcQ3AEAAHgAAAAAkoAI=","99":"b:cPc8FAzBACBBGjkIAzmAQcQ3AEAAHgAAAAAkoAI=","103":"b:cPc8FAzBACBBGjkIAzmAQcQ3AEAAHgAAAAAkoAI="},"packages/workflow/src/webhook-description-fields.ts":{"48":"b:ANYgBACAACABADsA0AmAiAQDAEAAEAAAAAAAoAE=","50":"b:ANYgBACAACABADsA0AmAiAQDAEAAEAAAAAAAoAE=","55":"b:ANYgBACAACABADsA0AmAiAQDAEAAEAAAAAAAoAE=","82":"b:ANYgBACAACABADsA0AmAiAQDAEAAEAAAAAAAoAE=","106":"b:ANYgBACAACABADsA0AmAiAQDAEAAEAAAAAAAoAE=","117":"b:ANYgBACAACABADsA0AmAiAQDAEAAEAAAAAAAoAE=","144":"b:ANYgBACAACABADsA0AmAiAQDAEAAEAAAAAAAoAE=","162":"b:ANYgBACAACABADsA0AmAiAQDAEAAEAAAAAAAoAE=","165":"b:ANYgBACAACABADsA0AmAiAQDAEAAEAAAAAAAoAE=","175":"b:ANYgBACAACABADsA0AmAiAQDAEAAEAAAAAAAoAE=","179":"b:ANYgBACAACABADsA0AmAiAQDAEAAEAAAAAAAoAE=","186":"b:ANYgBACAACABADsA0AmAiAQDAEAAEAAAAAAAoAE="},"packages/workflow/src/workflow-data-proxy-env-provider.ts":{"13":"b:cLYcCADAACAAEjgAYQGAAcQRAEAAAAAAAIAEgAA=","41":"b:cLYcCADAACAAEjgAYQGAAcQRAEAAAAAAAIAEgAA=","49":"b:cLYcCADAACAAEjgAYQGAAcQRAEAAAAAAAIAEgAA=","53":"b:cLYcCADAACAAEjgAYQGAAcQRAEAAAAAAAIAEgAA="},"packages/workflow/src/workflow-data-proxy.ts":{"49":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","74":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","79":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","100":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","139":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","144":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","156":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","178":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","179":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","187":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","193":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","205":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","211":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","212":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","216":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","250":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","275":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","276":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","282":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","284":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","286":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","295":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","296":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","298":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","299":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","313":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","318":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","319":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","322":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","328":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","331":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","336":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","337":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","349":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","356":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","357":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","360":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","366":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","368":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","429":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","461":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","578":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","589":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","590":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","697":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","704":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","705":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","708":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","714":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","745":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","752":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","753":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","756":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","762":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","790":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","795":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","796":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","820":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","824":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","851":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","901":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","923":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","938":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","949":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","960":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","972":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","985":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","996":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1007":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1016":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1035":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1044":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1047":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1065":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1080":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1092":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1122":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1145":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1149":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1167":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1174":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1237":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1262":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1280":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1303":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1304":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1317":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1350":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1360":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1458":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1477":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1501":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1532":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1533":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1536":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1542":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1557":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1572":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1587":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1633":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1660":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1684":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1740":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY=","1741":"b:MPY8CAAAACAAUDkAQQGAAQQTCEAAAgEAAIA2oAY="},"localhost-35901/assets/index-BoK1c_f3.js":{"3":[84]},"localhost-35901/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[84],"9":[84],"10":[84],"19":[84],"23":[84],"29":[84],"33":[84],"34":[84]},"localhost-35901/assets/verified-Pt0guxqN.js":{"8":[84]},"packages/@n8n/utils/src/assert.ts":{"4":"b:YAmCAAAgABAAIHQIEAAEEDAAADgAAIAAAAAAAAA="},"packages/frontend/@n8n/chat/src/api/generic.ts":{"1":[9,84,85,10,184,198,137],"5":[9,84,85,10,184,198,137],"49":[9,84,85,10,184,198,137]},"packages/frontend/@n8n/chat/src/api/message.ts":{"24":[9,84,85,10,184,198,137]},"packages/frontend/@n8n/chat/src/components/Chat.vue":{"15":[9,84,85,10,182,184,198,137],"21":[9,84,85,10,182,184,198,137],"32":[9,84,85,10,182,184,198,137],"37":[9,84,85,10,182,184,198,137],"42":[9,84,85,10,182,184,198,137],"47":[9,84,85,10,182,184,198,137],"108":[9,84,85,10,182,184,198,137],"114":[84,137],"122":[9,84,85,10,184,198,137],"136":[9,84,85,10,182,184,198,137],"140":[9,84,85,10,182,184,198,137],"158":[9,84,85,10,182,184,198,137]},"packages/frontend/@n8n/chat/src/components/GetStartedFooter.vue":{"5":[9,84,85,10,182,184,198,137]},"packages/frontend/@n8n/chat/src/components/Input.vue":{"23":[9,84,85,10,182,184,198,137],"48":[9,84,85,10,182,184,198,137],"53":[9,84,85,10,182,184,198,137],"60":[9,84,85,10,182,184,198,137],"66":[9,84,85,10,182,184,198,137],"69":[9,84,85,10,182,184,198,137],"105":[9,84,85,10,182,184,198,137],"112":[9,84,85,10,182,184,198,137],"143":[9,84,85,10,184,198,137],"154":[9,84,85,10,184,198,137],"290":[9,84,85,10,184,198,137],"320":[198],"342":[198],"358":[9,84,85,10,182,184,198,137],"366":[9,84,85,10,182,184,198,137],"377":[9,84,85,10,184,198,137]},"packages/frontend/@n8n/chat/src/components/Layout.vue":{"6":[9,84,85,10,182,184,198,137],"8":[9,84,85,10,182,184,198,137],"15":[9,84,85,10,182,184,198,137],"24":[9,84,85,10,182,184,198,137]},"packages/frontend/@n8n/chat/src/components/MarkdownRenderer.vue":{"16":[9,84,85,10,86,124,184,198,137],"22":[9,84,85,10,86,124,184,198,137],"32":[86,124],"42":[9,84,85,10,86,124,184,198,137]},"packages/frontend/@n8n/chat/src/components/Message.vue":{"20":[9,84,85,10,184,198,137],"25":[9,84,85,10,184,198,137],"29":[9,84,85,10,184,198,137],"37":[9,84,85,10,184,198,137],"57":[9,84,85,10,184,198,137],"69":[9,84,85,10,184,198,137]},"packages/frontend/@n8n/chat/src/components/MessageActions.vue":{"8":[9,84,85,10,184,198,137],"35":[9,84,85,10,184,198,137]},"packages/frontend/@n8n/chat/src/components/MessageTyping.vue":{"8":[9,84,85,10,184,198,137],"23":[9,84,85,10,184,198,137],"31":[9,84,85,10,184,198,137],"34":[9,84,85,10,184,198,137]},"packages/frontend/@n8n/chat/src/components/MessagesList.vue":{"19":[9,84,85,10,182,184,198,137],"23":[9,84,85,10,182,184,198,137],"24":[9,84,85,10,184,198,137],"32":[9,84,85,10,182,184,198,137],"53":[9,84,85,10,184,198,137],"55":[9,84,85,10,184,198,137]},"packages/frontend/@n8n/chat/src/components/PoweredBy.vue":{"2":[9,84,85,10,182,184,198,137]},"packages/frontend/@n8n/chat/src/composables/useI18n.ts":{"5":[9,84,85,10,86,124,182,184,198,137],"9":[9,84,85,10,86,124,182,184,198,137],"17":[9,84,85,10,86,124,182,184,198,137]},"packages/frontend/@n8n/chat/src/composables/useOptions.ts":{"6":[9,84,85,10,86,124,182,184,198,137]},"packages/frontend/@n8n/chat/src/plugins/chat.ts":{"27":[9,84,85,10,184,198,137],"42":[9,84,85,10,184,198,137],"194":[9,84,85,10,184,198,137],"211":[9,84,85,10,182,184,198,137],"220":[9,84,85,10,182,184,198,137],"228":[9,84,85,10,184,198,137],"237":[9,84,85,10,184,198,137],"297":[9,84,85,10,184,198,137],"304":[9,84,85,10,182,184,198,137],"336":[9,84,85,10,182,184,198,137]},"packages/frontend/@n8n/chat/src/utils/credentialStatus.ts":{"40":[9,84,85,10,182,184,198,137],"43":[84,10,184,137]},"packages/frontend/@n8n/chat/src/utils/streaming.ts":{"28":[9,84,85,10,184,198,137],"130":[9,84,85,10,184,198,137]},"packages/frontend/@n8n/design-system/src/components/InlineAskAssistantButton/InlineAskAssistantButton.vue":{"8":"b:4AGCAIAgABAAYHAIAAAAEDgCAAAAAIAAAAACAAA=","39":"b:4AGCAIAgABAAYHAIAAAAEDgCAAAAAIAAAAACAAA=","41":[5,6,7,86,124],"44":"b:4AGCAIAgABAAYHAIAAAAEDgCAAAAAIAAAAACAAA="},"packages/frontend/@n8n/design-system/src/components/N8nBadge/Badge.vue":{"12":"b:iADjAyK4ANxgoHIpHAAsEjCIAiAMwIDAHwiAAAA=","18":[3,86,91,45,132,133,100],"27":"b:iADjAyK4ANxgoHIpHAAsEjCIAiAMwIDAHwiAAAA=","39":"b:iADjAyK4ANxgoHIpHAAsEjCIAiAMwIDAHwiAAAA=","47":"b:iADjAyC4ANxggHIpHAAsEjCIAiAMwIDAHwiAAAA=","62":"b:iADjAyK4ANxgoHIpHAAsEjCIAiAMwIDAHwiAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nDialog/DialogClose.vue":{"17":"b:gACCAIIgAJAAYHQIAAAAEDAAACgIAIAAAAAAAQA=","18":[86,124,216],"25":"b:gACCAIIgAJAAYHQIAAAAEDAAACgIAIAAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nDialog/DialogHeader.vue":{"6":"b:gACCAICgAJAAYHQIAAAAEDAAACgIAIAAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nDialog/DialogTitle.vue":{"15":"b:gACCAICgAJAAYHQIAAAAEDAAACgIAIAAAAAAAAA=","16":"b:gACCAICgAJAAQHQIAAAAEDAAACgIAIAAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/arrow-u-up-left--outline-16.svg":{"9":"b:RgaAACAAAAAAAHAAAAAAEAgKAAAAAMBBQAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/arrow-u-up-right--outline-16.svg":{"9":"b:BgYAAAAAAAAAAXAAAAAAEAACAAAAAAABQACAAQA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/brackets-curly--outline-16.svg":{"9":[9,84,85,10,86,124,184,137,217]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/brain--outline-16.svg":{"9":[84,85,86,124,37,45,190,139,77]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/briefcase--outline-16.svg":{"9":"b:oECCAIAiAABkfXEIBxAQEOxgCAHgIJAOCNYOAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/chat-bubble--outline-16.svg":{"9":"b:AAb8ACCAANwAAHAAAAAsEAiKADgIAMDBRgAAAQA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/check-seal--outline-16.svg":{"9":"b:AAAAMD4AAAAAAFAQAAAA0AAIAIAHAABAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/chevrons-left-right--outline-16.svg":{"9":[4,84,85,10,86,20,124,37,190,139,77]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/database--outline-16.svg":{"9":"b:AAAAAyAAAAAAAFAAAAAAEAAIAACAAABAAQgUBAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/exclamation-triangle--outline-16.svg":{"9":"b:4kGTAIigABAAZ3YIAABQFDRrCqgBAIQAAQSCAwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/exclamation-triangle--solid-16.svg":{"9":"b:4EGCAKQiAQBgZXUIEgBQFGRbCQNQIaVKCASKBAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/file-arrow-in--outline-16.svg":{"9":"b:YAEAACAgAAAAIHAABgAAEAAKAAQABAl4AAIGBAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/files--outline-16.svg":{"9":"b:YAYAAAAgAAAAAHAAAAAQEAADAAAAACABQAAGAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/filter--outline-16.svg":{"9":"b:CACCAwC4ABAAA1IpHAAAEjADAAAEQAAAAQiAAwA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/flow--outline-16.svg":{"9":"b:oECCAIAiAABkfXEIBxAQEOxgCAHgIJAOCNYOAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/globe--outline-16.svg":{"9":"b:oECCAKAiABBkfXEIBxAQEPxoCCHgIJBOCNYOAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/key--outline-16.svg":{"9":"b:gACaAAAwABAAYHQIAABAFDQCASAAIIAACAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/lightning--outline-16.svg":{"9":"b:oEDCAIAiAABkfXEIBxAQEOxgCAHgIJAOCNYOAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/list-tree--outline-16.svg":{"9":[9,84,85,10,86,124,45,184,137,217]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/pencil-compose--outline-16.svg":{"9":"b:AAYAEAgAAAAAAHAAAAAA0AACAAAAAAABQAAAAgA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/play--outline-16.svg":{"9":"b:AAYQEAggAAAAYHAAAAAA0AAiAAAAAAARwAAAAgA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/robot--outline-16.svg":{"9":"b:pkD/AaCiANxkfXEIBxA8EOzoCDnoILDODtYOAQA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/table--outline-16.svg":{"9":[9,84,85,10,86,124,24,25,184,137,216,217]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/grip-lines-vertical.svg":{"9":[84,85,86,124,37,190,139,77]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/mcp.svg":{"13":"b:AABAACC4ANwAAFIhHAAsEgCIACAMQADABggAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/node-execution-error.svg":{"11":"b:YAAAAAAAAAAAAXAAAAAAEAADAAAAABAAAACCAQA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/text.svg":{"8":[84,86,124,137]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/vector-square.svg":{"9":[84,85,86,124,37,45,190,139,77]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/ai-agent.svg":{"11":[84,85,20,23,37,181,183,190,70,137,139,77]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/calculator.svg":{"11":[84,20]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/call-n8n-sub-workflow-tool.svg":{"11":[84,20,37,190,139]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/compression.svg":{"11":[84,20]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/data-table.svg":{"11":[84,17,20,23,195,133,66,202,209,77,80]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/date-and-time.svg":{"11":[84,20]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/http-request.svg":{"11":"b:AAGQACACABBABRAIEgAABBAIAAcAIABKAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/item-list-output-parser.svg":{"11":[84]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/model-selector.svg":{"11":[84,85,139]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/rss-read.svg":{"11":[84,20]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/send-mail.svg":{"11":[84,14,20,166,40]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/simple-memory.svg":{"11":[84,139]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/structured-output-parser.svg":{"11":[84,77]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/think-tool.svg":{"11":[84,20]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/totp.svg":{"11":[84,20]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/vector-store-question-answer-tool.svg":{"11":[84]},"packages/frontend/@n8n/design-system/src/components/N8nInfoAccordion/InfoAccordion.vue":{"29":"b:AAAAAACAAAAAA1AAAgAAEAQDAAMAIAAAACCCAwA=","40":"b:AAAAAACAAAAAA1AAAgAAEAQDAAMAIAAAACCCAwA=","41":[86,124],"47":[86,124],"51":[86,124],"53":[86,124],"54":"b:AAAAAACAAAAAA1AAAgAAEAQDAAMAIAAAACCCAwA=","61":"b:AAAAAACAAAAAA1AAAgAAEAQDAAMAIAAAACCCAwA=","72":[86,124],"74":[86,124],"75":[86,124],"76":[86,124],"79":[86,124],"83":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nInputNumber/InputNumber.vue":{"24":"b:oEQAAACAABAgfFUAAwAUEAA7ICJQKAZEAPYOAAA=","25":"b:oEQAAACAABAgfFUAAwAUEAA7ICJQKAZEAPYOAAA=","26":"b:oEQAAACAABAgfFUAAwAUEAA7ICJQKAZEAPYOAAA=","40":"b:oEQAAACAABAgfFUAAwAUEAA7ICJQKAZEAPYOAAA=","41":"b:oEQAAACAABAgfFUAAwAUEAA7ICJQKAZEAPYOAAA=","48":[86,153,124,173,177,114,206,75,76,141],"53":[86,153,124,173,177,114,206,75,76,141],"54":[86,124],"55":[86,124],"62":"b:oEQAAACAABAgfFUAAwAUEAA7ICJQKAZEAPYOAAA=","93":[86,153,124,173,177,114,206,75,76,141],"98":[86,124,206,75,76,141],"105":[86,124],"113":[86,124],"126":[86,153,124,173,177,114,141],"143":[86,124],"163":"b:oEQAAACAABAgfFUAAwAUEAA7ICJQKAZEAPYOAAA=","164":"b:oEQAAACAABAgfFUAAwAUEAA7ICJQKAZEAPYOAAA=","173":"b:oEQAAACAABAgXFUAAwAUEAA7ICJQKAZEAPYOAAA=","183":[86,124],"206":[86,153,124,173,177,114,206,75,76,141],"210":[86,124],"223":[86,157,124,47,69],"234":[86,157,124,47,69]},"packages/frontend/@n8n/design-system/src/components/N8nKeyboardShortcut/N8nKeyboardShortcut.vue":{"7":"b:AAAAAAAAAACAAFAAAwAAEEAAAAAAAAARACMgAQA=","10":"b:AAAAAAAAAACAAFAAAwAAEEAAAAAAAAARACMgAQA=","25":"b:AAAAAAAAAACAAFAAAwAAEEAAAAAAAAARACMgAQA=","29":"b:AAAAAAAAAACAAFAAAwAAEEAAAAAAAAARACMgAQA=","33":"b:AAAAAAAAAACAAFAAAwAAEEAAAAAAAAARACMgAQA="},"packages/frontend/@n8n/design-system/src/components/N8nNotice/Notice.vue":{"16":"b:4EWCAAAiARhkfXUIAxBQFORLKAdQKJTeCOYzAgA=","30":"b:4EWCAAAiARhkfXUIAxBQFORLKAdQKJTeCOYzAgA=","31":[86,124],"34":"b:4EWCAAAiABBkfXEIAxBQFOQLKAdQKJTeCOYTAgA=","50":[86,124,77],"66":"b:4EWCAAAiARhkfXUIAxBQFORLKAdQKJTeCOYzAgA=","75":"b:4EWCAAAiARhkXXUIAxBQFORLKAdQKJTeCOYzAgA="},"packages/frontend/@n8n/design-system/src/components/PreviewBadge/PreviewBadge.vue":{"9":"b:gADjAyK4ANxAoHIpHAAsEjCIACAMwIDADwgAAAA=","17":"b:gADjAyK4ANxAoHIpHAAsEjCIACAMwIDADwgAAAA=","22":"b:gADjAyK4ANxAoHIpHAAsEjCIACAMwIDADwgAAAA=","26":"b:gADjAyC4ANxAgHIpHAAsEjCIACAMwIDADwgAAAA="},"packages/frontend/@n8n/design-system/src/v2/components/Checkbox/Checkbox.vue":{"11":"b:CAAAAACAAAwgg1MAEAAAEAADAAAAEACAIACAAwA=","14":"b:CAAAAACAAAwgg1MAEAAAEAADAAAAEACAIACAAwA=","19":"b:CAAAAACAAAwgg1MAEAAAEAADAAAAEACAIACAAwA=","22":"b:CAAAAACAAAwgg1MAEAAAEAADAAAAEACAIACAAwA=","28":[86,124,191,58,69,137,81,100],"32":"b:CAAAAACAAAwgg1MAEAAAEAADAAAAEACAIACAAwA=","37":"b:CAAAAACAAAwgg1MAEAAAEAADAAAAEACAIACAAwA=","45":"b:CAAAAACAAAwgg1MAEAAAEAADAAAAEACAIACAAwA=","47":"b:CAAAAACAAAQgA1IAEAAAEAADAAAAAACAIACAAwA=","56":"b:CAAAAACAAAwgg1MAEAAAEAADAAAAEACAIACAAwA=","57":"b:CAAAAACAAAAAA1IAEAAAEAADAAAAAAAAIACAAwA="},"packages/frontend/@n8n/rest-api-client/src/api/externalSecrets.ee.ts":{"6":[86,124],"15":[86,124],"24":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","38":[86,17,23,124,45,60,78],"49":[86,124],"55":[86,124],"62":[86,124],"70":[86,124],"78":[86,124],"85":[86,124],"95":[86,124]},"packages/frontend/editor-ui/src/app/components/Banner.vue":{"22":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","36":[86,124],"40":[86,124],"48":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","58":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","65":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","71":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","78":"b:gACCAIAgABAAQHQIAAAAEDAAACgAAIAAAAAAAAA=","86":[86]},"packages/frontend/editor-ui/src/app/components/DropArea/DropArea.vue":{"4":"b:IAAAAAggAABAMFAABwAQEAADAAIAMAQngLIOAAA=","6":[86,124],"8":"b:IAAAAAggAABAMFAABwAQEAADAAIAMAQngLIOAAA=","13":"b:IAAAAAggAABAEFAABwAQEAADAAIAMAQngLIOAAA="},"packages/frontend/editor-ui/src/app/components/EnterpriseEdition.ee.vue":{"6":"b:gACCAICwABAAYHYIAABAEDAAACgAAIAAGAAAAAA=","17":"b:gACCAICwABAAYHYIAABAEDAAACgAAIAAGAAAAAA=","18":"b:gACCAICwABAAYHYIAABAEDAAACgAAIAAGAAAAAA=","23":"b:gACCAICwABAAYHYIAABAEDAAACgAAIAAGAAAAAA="},"packages/frontend/editor-ui/src/app/components/SaveButton.vue":{"12":"b:gACCAIAgAFAAYHQIAAAkEDAAACgAAIAAAAAAAAA=","36":"b:gACCAIAgABAAYHQIAAAEEDAAACgAAIAAAAAAAAA=","42":[86,124],"45":"b:gACCAIAgAFAAYHQIAAAkEDAAACgAAIAAAAAAAAA=","49":[86],"58":[86],"64":[86],"73":"b:AACCAAAgABAAIHQIAAAEADAAACgAAIAAAAAAAAA="},"packages/frontend/editor-ui/src/app/composables/canvasConnectionReplacement.utils.ts":{"86":"b:gECCAKAiAABkfXEIBxAQEORoCAFAIIBOCNcKAAA=","94":"b:gECCAIAiAABkfXEIBxAQEORACAEAIIAACMcKAAA=","102":"b:gECCAKAiAABkfXEIBxAQEORoCAFAIIBOCNcKAAA=","138":[86,124],"184":[86,124],"189":[86,124],"192":[86,124,186,187,70],"212":[86,124,186,187,70],"221":[86,124,186,187,70],"228":[86,124,186,187,70],"262":[86,124,186,187,70],"277":[86,124,186,187,70]},"packages/frontend/editor-ui/src/app/composables/useAutocompleteTelemetry.ts":{"12":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMACAAA=","22":[86,124],"26":[86,124],"27":[86,124],"36":[86,124],"49":[86,124],"57":"b:AAAAAAAAABAAfEAAAgAQEAAgAAAAAAAAAMAAAAA=","61":"b:AAAAAAAAABAAfEAAAgAQEAAgAAAAAAAAAMAAAAA=","70":[86,124],"96":"b:AAAAAAAAABAAfEAAAgAQEAAgAAAAAAAAAMAAAAA=","103":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMACAAA=","109":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMACAAA="},"packages/frontend/editor-ui/src/app/composables/useIntersectionObserver.ts":{"45":"b:AAAAMAwAAAAAAxAQAAAAwAAAAIAHAAAAAAgAAwA=","56":[73,216],"62":[73,216],"82":"b:AAAAMAwAAAAAARAQAAAAwAAAAIAHAAAAAAgAAwA="},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/testWebhookReceived.ts":{"8":"b:AAYAAAAAAAAAADAAAgAACAQDCAAAIAABQAAAAAA="},"packages/frontend/editor-ui/src/features/agents/composables/useAgentAssistantCredentialHelp.ts":{"8":"b:gACCAIQwABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","11":"b:gACCAIQgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","15":[86,124],"20":[86,124]},"packages/frontend/editor-ui/src/features/agents/composables/useMessageAgentSessionLink.ts":{"33":[9,84,85,10,184,137,217],"61":[9,84,85,10,184,137,217],"66":[9,84,85,10,184,137,217]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialConfig.vue":{"103":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","137":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","140":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","161":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","164":[7,86,23,124],"169":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","170":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","176":[86,124,78,82],"181":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","211":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","216":[7,86,23,124],"224":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","233":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","242":[86,124],"248":[86,124],"255":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","263":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","271":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","273":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","275":[7,86,155,157,124,78,82],"286":[7,86,124],"290":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","292":"b:AACCAAAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","296":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","303":[86,23,124,78],"309":[7,86,23,124,78,82],"318":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","329":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","338":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","340":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","345":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","347":[86,124],"349":"b:gACCAAAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","353":"b:AACCAAAgABAAIHQIAAAAEDAAAAgAAIAAAAAAAAA=","360":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","367":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","373":[86,124],"382":[7,86,23,124],"390":[86,124],"418":[7,86,124],"436":[86,124],"441":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","445":[86],"451":[86],"476":[86],"495":[7,86,155,157,82],"497":[7,86,155,157,82],"524":[84,85,86,17,23,91,45,183,60,132,133,77,78],"576":[86],"581":[86],"586":[86],"594":[86],"622":[86],"633":[86],"655":[86],"665":[86],"666":[86],"671":[86],"675":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","681":[86],"689":[86],"704":[86],"720":[86],"723":[86],"724":[86],"729":[86],"733":[7,86,23,124,78],"734":[86],"738":"b:gACCAIAgABAAYHQIAAAAADAAACgAAIAAAAAAAAA=","745":[86],"768":[86],"770":[86],"800":[86],"804":"b:gACCAIAgAAAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","806":"b:gACCAIAgAAAAQHQIAAAAADAAACgAAIAAAAAAAAA=","808":"b:gACCAIAgAAAAQHQIAAAAADAAACgAAIAAAAAAAAA="},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialEdit.vue":{"105":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","113":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","115":[86,23,124,78,82],"120":[86,23,124],"146":[86,124],"152":[86,124],"158":[86,124],"165":[86,124],"199":"b:AACCAAAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","211":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","213":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","221":"b:AACCAAAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","226":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","236":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","242":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","247":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","248":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","249":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","250":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","251":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","252":"b:gACCAIAgABAAYHQIAAAAEDAAAAgAAIAAAAAAAAA=","253":"b:gACCAIAgABAAYHQIAAAAEDAAAAgAAIAAAAAAAAA=","254":"b:gACCAIAgABAAYHQIAAAAEDAAAAgAAIAAAAAAAAA=","255":"b:gACCAIAgABAAYHQIAAAAEDAAAAgAAIAAAAAAAAA=","258":[86,124],"305":"b:AACCAAAgABAAIHQIAAAAEDAAACgAAIAAAAAAAAA=","309":"b:AACCAAAgABAAIHQIAAAAEDAAACgAAIAAAAAAAAA=","318":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","323":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","327":"b:AACCAAAgABAAIHQIAAAAEDAAACgAAIAAAAAAAAA=","331":"b:AACCAAAgABAAYHQIAAAAEDAAAAgAAIAAAAAAAAA=","335":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","340":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","344":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","348":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","381":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","391":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","402":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","411":[86,157,23,91,124,132,133],"413":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","429":[86,124],"447":[86,124],"460":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","534":[86,124],"538":"b:gACCAIAgABAAIHQIAAAAEDAAACgAAIAAAAAAAAA=","560":"b:gACCAAAgAAAAIHQAAAAAEDAAAAgAAIAAAAAAAAA=","566":"b:AACCAAAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","605":[86,124],"621":[86,157,91,124,132,133],"636":[86,124,132,133],"645":[86,157,91,124],"650":[7,86,23,124],"658":[7,86,23,124],"665":[7,86,23,124],"674":[86,124],"732":"b:AACCAAAgABAAIHQIAAAAEDAAAAgAAIAAAAAAAAA=","736":"b:AACCAAAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","753":"b:AACCAAAgABAAQEQIAAAAEDAAACgAAAAAAAAAAAA=","758":[86,124],"764":[86,124],"771":[86,124],"817":[86,17,23,91,124,60,132,133,82],"823":[86,124],"829":"b:AACCAAAgAAAAIHQAAAAAEDAAACgAAIAAAAAAAAA=","830":"b:AACCAAAgAAAAIHQAAAAAEDAAACgAAIAAAAAAAAA=","837":[86,124],"838":[86,124],"845":[86,124],"862":"b:AACCAAAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","892":"b:AACCAAAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","994":"b:AACCAAAgABAAIHQIAAAAEDAAACgAAIAAAAAAAAA=","1061":"b:AACCAAAgABAAIHQIAAAAEDAAACgAAIAAAAAAAAA=","1075":[86],"1094":"b:AACCAAAgABAAYHQIAAAAEDAAAAgAAIAAAAAAAAA=","1114":"b:AACCAAAgABAAYHQIAAAAEDAAAAgAAIAAAAAAAAA=","1187":[86,157,23,91,124,132,133],"1242":[86,23,124],"1312":[86,124,78,82],"1420":[86,124],"1448":[86,124],"1454":[86,124],"1474":[86],"1482":[86],"1494":[86,124],"1537":[7,86,23,124],"1584":[86,124],"1609":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","1619":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","1623":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","1624":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","1657":"b:gACCAIAgABAAQHQIAAAAEDAAACgAAIAAAAAAAAA=","1706":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","1710":[86,157,91,132,133],"1719":[86],"1725":[86],"1729":[86],"1731":[86],"1819":[86,124],"1820":[86,124]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialInputs.vue":{"28":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","31":[86,124],"39":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","43":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","44":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","53":"b:AACCAAAgABAAIHQIAAAAEDAAAAgAAIAAAAAAAAA=","55":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","62":[86],"65":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","69":[86],"78":[86],"97":[86],"123":[86],"132":[86]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialModeSelector.vue":{"27":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","46":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","47":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","52":[7,84,85,86,17,23,124,39,183,77,78],"53":[7,84,85,86,17,23,124,39,183,77,78],"63":[7,86,124],"65":"b:gACCAIAgABAAAHQIAAAAEDAAACgAAIAAAAAAAAA=","66":"b:gACCAIAgABAAAHQIAAAAEDAAACgAAIAAAAAAAAA=","67":[86,124],"71":[7,86,124],"92":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","103":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","115":[7,86,17,23,124,77,78],"128":[7,86,17,23,124,77,78],"133":[7,86,17,23,124,77,78],"145":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","167":[7,86,17,23,124,77,78],"194":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","195":[7,86,17,23,124,77,78],"196":[7,86,17,23,124,77,78],"199":[7,86,17,23,124,77,78],"206":[7,86,17,23,124,77,78],"207":[7,86,17,23,124,77,78],"214":[7,86,23,124],"217":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","224":[7,86,17,23,124,77,78],"234":[7,86,17,23,124,77,78],"236":[7,86,17,23,124,78]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialIcon.vue":{"13":"b:gACeAKQyABAgYHUIAgAAEHAYATtQAYVAAAQKAAA=","24":"b:gACeAKQyABAgYHUIAgAAEHAYATtQAYVAAAQKAAA=","26":"b:gACeAKQyABAgYHUIAgAAEHAYATtQAYVAAAQKAAA=","30":"b:gACeAKQyABAgYHUIAgAAEHAYATtQAYVAAAQKAAA=","42":"b:gACeAKQyABAgYHUIAgAAEHAYATtQAYVAAAQKAAA=","53":"b:gACeAKQyABAgYHUIAgAAEHAYATtQAYVAAAQKAAA=","59":"b:gACeAKQyABAgYHUIAgAAEHAYATtQAYVAAAQKAAA=","69":"b:gACeAKQyABAgYHUIAgAAEHAYATtQAYVAAAQKAAA=","79":"b:gACeAKQyABAgYHUIAgAAEHAYATtQAYVAAAQKAAA=","95":[86],"103":"b:gACeAKQyABAgYHUIAgAAEHAYATtQAYVAAAQKAAA="},"packages/frontend/editor-ui/src/features/credentials/composables/useCredentialForm.ts":{"87":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","117":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","122":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","126":[86,124],"130":[86,124],"137":"b:gACCAIAgABAAYHQIAAAAEDAAAAgAAIAAAAAAAAA=","147":[7,84,85,86,17,23,124,39,183,77,78],"159":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","168":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","179":[86,124],"183":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","188":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","198":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","203":[7,84,85,86,17,23,124,39,183,77,78],"208":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","212":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","223":[86,124],"225":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","231":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","235":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","245":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","249":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","256":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","260":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","273":[86],"274":[86],"276":[86],"306":"b:AACCAAAgABAAIHQIAAAAEDAAACgAAIAAAAAAAAA=","313":"b:AACCAAAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","318":"b:AACCAAAgABAAIHQIAAAAADAAACgAAIAAAAAAAAA=","329":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","347":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","357":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","371":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","402":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","411":"b:AACCAAAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","412":"b:AACCAAAgABAAIHQIAAAAEDAAACgAAIAAAAAAAAA=","419":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","435":[7,86,23,124],"460":[86,157,23,91,124],"462":[86,157,23,91,124],"468":[86,157,23,91,124],"505":[86,157,23,91,124],"518":[86,124],"538":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","564":[86,124],"593":"b:AACCAAAgABAAIHQIAAAAEDAAAAgAAIAAAAAAAAA=","612":[86,124],"615":[86,124],"616":[86,124],"617":[86,124],"620":"b:AACCAAAgAAAAIHQAAAAAEDAAACgAAIAAAAAAAAA=","649":[86,157,23,91,124]},"packages/frontend/editor-ui/src/features/credentials/credentials.utils.ts":{"21":"b:4AGSAKQCAAAgYHEIDgAAEGAaAQdQJY14CAYOBAA=","37":"b:gACSAKQCAAAgYHEIAgAAEGAaAQNQIYVACAQKBAA=","40":[23,124,133,77]},"packages/frontend/editor-ui/src/features/credentials/quickConnect/components/QuickConnectButton.vue":{"9":"b:gACCAKAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","35":"b:gACCAKAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","44":"b:gACCAKAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","48":[86,124],"49":"b:gACCAKAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","54":[86,124],"63":[86,124],"64":"b:gACCAKAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA="},"packages/frontend/editor-ui/src/features/execution/executions/components/ExecutionStopAllText.vue":{"11":[84,47,72,136,73,137,215,216,217],"18":[84,47,72,136,73,137,215,216,217],"25":[84,47,72,136,73,137,215,216,217]},"packages/frontend/editor-ui/src/features/execution/executions/components/ExecutionsFilter.vue":{"42":[84,47,72,136,73,137,215,216,217],"64":[215],"67":[215],"69":[84,47,72,136,73,137,215,216,217],"87":[215],"104":[215],"113":[215],"120":[215],"127":[215],"139":[215],"155":[84,47,72,136,73,137,215,216,217],"200":[215],"214":[84,47,72,136,73,137,215,216,217],"217":[84,47,72,136,73,137,215,216,217],"228":[84,47,72,136,73,137,215,216,217],"244":[215],"251":[215],"284":[215],"336":[215],"348":[215],"357":[215],"359":[215],"362":[215],"394":[215],"413":[215],"439":[215],"461":[215],"485":[215]},"packages/frontend/editor-ui/src/features/execution/executions/components/workflow/WorkflowExecutionsInfoAccordion.vue":{"58":[84,47,72,136,73,137,215,216,217],"78":[84,47,72,136,73,137,215,216,217],"88":[84,47,72,136,73,137,215,216,217],"96":[84,47,72,136,73,137,215,216,217],"109":[84,47,72,136,73,137,215,216,217],"110":[84,47,72,136,73,137,215,216,217],"119":[216],"123":[84,47,72,136,73,137,215,216,217],"130":[84,47,72,136,73,137,215,216,217]},"packages/frontend/editor-ui/src/features/execution/executions/components/workflow/WorkflowExecutionsLandingPage.vue":{"22":[84,72,136,73,137,215,216,217],"25":[84,72,136,73,137,215,216,217],"27":[216],"45":[216],"48":[216],"56":[84,72,136,73,137,215,216,217]},"packages/frontend/editor-ui/src/features/execution/executions/components/workflow/WorkflowExecutionsList.vue":{"12":[84,47,72,136,73,137,215,216,217],"42":[84,47,72,136,73,137,215,216,217],"43":[47,72,136,73,137,215,216,217],"48":[84,47,72,136,73,137,215,216,217],"52":[136],"73":[84,72,216,217],"81":[84,47,72,136,73,137,215,216,217],"92":[137],"94":[215]},"packages/frontend/editor-ui/src/features/execution/executions/components/workflow/WorkflowExecutionsSidebar.vue":{"26":[84,47,72,136,73,137,215,216,217],"63":[73,216],"70":[84,47,72,136,73,137,215,216,217],"79":[47,72,136,73,137,215,216,217],"83":[84,47,72,136,73,137,215,216,217],"87":[84,47,72,136,73,137,215,216,217],"97":[84,47,72,136,73,137,215,216,217],"98":[47,72,136,73,137,215,216,217],"107":[47,72,136,73,137,215,216,217],"116":[47,72,136,73,137,215,216,217],"125":[47,72,136,73,137,215,216,217],"136":[215],"143":[137],"147":[72,215],"169":[84,47,72,136,73,137,215,216,217],"176":[84,47,72,136,73,137,215,216,217],"219":[84,47,72,136,73,137,215,216,217],"224":[136,215],"232":[84,47,72,136,73,137,215,216,217],"235":[47,72,136,73,137,215,216,217]},"packages/frontend/editor-ui/src/features/execution/executions/views/WorkflowExecutionsView.vue":{"36":[84,47,72,136,73,137,215,216,217],"40":[84,47,72,136,73,137,215,216,217],"45":[84,47,72,136,73,137,215,216,217],"54":[84,47,72,136,73,137,215,216,217],"55":[47,72,136,73,137,215,216,217],"73":[84,47,72,136,73,137,215,216,217],"77":[84,47,72,136,73,137,215,216,217],"84":[84,47,72,136,73,137,215,216,217],"86":[72,136,73,137,215,216,217],"91":[84,47,72,136,73,137,215,216,217],"102":[84,72,216,217],"107":[84,47,72,136,73,137,215,216,217],"133":[47],"141":[84,47,72,136,73,137,215,216,217],"153":[84,47,72,136,73,137,215,216,217],"165":[137],"200":[215],"228":[136],"234":[136],"305":[73,216],"311":[84,47,72,136,73,137,215,216,217],"317":[73,216]},"packages/frontend/editor-ui/src/features/execution/logs/components/ChatMessagesPanel.vue":{"30":"b:AAaAACAAAAAAADAAAAAAAAgKAAAAAMBBQAAAAAA=","57":[9,84,85,10,182,184,198,137],"61":"b:AAaAACAAAAAAADAAAAAAAAgKAAAAAMBBQAAAAAA=","67":[9],"76":[9,84,85,10,182,184,198,137],"96":[9,84,85,10,182,184,198,137],"105":"b:AAaAACAAAAAAADAAAAAAAAgKAAAAAMBBQAAAAAA=","107":[9,84,85,10,182,184,198,137],"117":"b:AAaAACAAAAAAADAAAAAAAAgKAAAAAMBBQAAAAAA=","135":"b:AAaAACAAAAAAADAAAAAAAAgKAAAAAMBBQAAAAAA=","137":"b:AAaAACAAAAAAADAAAAAAAAgKAAAAAMBBQAAAAAA=","154":"b:AAaAACAAAAAAADAAAAAAAAgKAAAAAMBBQAAAAAA=","166":"b:AAaAACAAAAAAADAAAAAAAAgKAAAAAMBBQAAAAAA=","182":"b:AAaAACAAAAAAADAAAAAAAAgKAAAAAMBBQAAAAAA=","190":[9,84,10,137],"193":"b:AAaAACAAAAAAADAAAAAAAAgKAAAAAMBBQAAAAAA=","208":"b:AAaAACAAAAAAADAAAAAAAAgKAAAAAMBBQAAAAAA=","214":"b:AAaAACAAAAAAADAAAAAAAAgKAAAAAMBBQAAAAAA=","221":"b:AAaAACAAAAAAADAAAAAAAAgKAAAAAMBBQAAAAAA=","227":"b:AAaAACAAAAAAADAAAAAAAAgKAAAAAMBBQAAAAAA="},"packages/frontend/editor-ui/src/features/execution/logs/components/LogDetailsPanel.vue":{"41":[9,84,85,10,184,137,217],"79":[9,84,85,10,184,137,217],"80":[9,84,85,10,184,137,217],"81":[9,84,85,10,184,137,217],"86":[9,84,85,10,184,137,217],"93":[9,84,85,10,184,137,217],"94":[9,84,137],"102":[9,84,85,10,184,137,217],"103":[9,84,85,10,184,137,217],"104":[9,84,85,10,184,137,217],"110":[84,137],"114":[84,137],"122":[84,137],"123":[9,84,85,10,184,137,217],"138":[9,84,85,10,184,137,217],"149":[9,84,85,10,184,137,217],"163":[9,84,85,10,184,137,217],"178":[9,84,85,10,184,137,217],"184":[9,84,85,10,184,137,217],"191":[9,84,85,10,184,137,217],"197":[9,84,85,10,184,137,217],"225":[84,137]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsOverviewRow.vue":{"57":[3,9,84,85,10,28,126,35,127,184,198,137,217],"58":[3,9,84,85,10,28,126,35,127,184,198,137,217],"59":[3,9,84,85,10,28,126,35,127,184,198,137,217],"60":[3,9,84,85,10,28,126,35,127,184,198,137,217],"61":[3,9,84,85,10,28,126,35,127,184,198,137,217],"64":[3,9,84,85,10,28,126,35,127,184,198,137,217],"73":[3,9,84,85,10,28,126,35,127,184,198,137,217],"76":[3,9,84,85,10,28,126,35,127,184,198,137,217],"79":[9,84,85,10,28,126,35,127,184,198,137],"80":[3,9,84,85,10,28,126,35,127,184,198,137,217],"83":[9,84,85,10,28,126,35,127,184,198,137],"93":[9,84,85,10,28,126,35,127,184,198,137],"96":[9,84,85,10,28,126,35,127,184,198,137],"109":[9,84,85,10,28,126,35,127,184,198,137],"112":[9,84,85,10,28,126,35,127,184,198,137],"136":[9,84,85,10,28,126,35,127,184,198,137],"140":[3,9,84,85,10,28,126,35,127,184,198,137,217],"144":[3,9,84,85,10,28,126,35,127,184,198,137,217],"161":[3,9,84,85,10,28,126,35,127,184,198,137,217],"162":[3,9,84,85,10,28,126,35,127,184,198,137,217],"164":[3,9,84,85,10,28,126,35,127,184,198,137,217],"198":[84,85,137],"224":[9,84,85,10,28,126,35,127,184,198,137],"225":[9,84,85,10,28,126,35,127,184,198,137],"227":[9,84,85,10,28,126,35,127,184,198,137],"233":[9,84,85,10,28,126,35,127,184,198,137],"243":[9,84,85,10,28,126,35,127,184,198,137],"271":[9,84,85,10,28,126,35,127,184,198,137,217],"294":[9,84,85,10,28,126,35,127,184,198,137,217]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsOverviewRows.vue":{"44":[9,84,85,10,28,126,35,127,184,198,137,217],"45":[9,84,85,10,28,126,35,127,184,198,137,217],"51":[9,84,85,10,28,126,35,127,184,198,137,217],"55":[9,84,85,10,28,126,35,127,184,198,137,217],"59":[137],"79":[9,84,85,10,28,126,35,127,184,198,137,217],"80":[9,84,85,10,28,126,35,127,184,198,137,217],"81":[9,84,85,10,28,126,35,127,184,198,137,217],"91":[9,84,85,10,28,126,35,127,184,198,137,217],"93":[9,84,85,10,28,126,35,127,184,198,137,217],"94":[9,84,85,10,28,126,35,127,184,198,137,217],"99":[9,84,85,10,184,137,217],"110":[9,84,85,10,28,126,35,127,184,198,137,217],"127":[137],"128":[137],"129":[9,137]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsViewExecutionSummary.vue":{"18":[9,84,85,10,28,126,35,127,184,198,137,217],"20":[9,84,85,10,28,126,35,127,184,198,137,217],"37":[9,84,85,10,28,126,35,127,184,198,137,217]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsViewNodeName.vue":{"12":[3,9,84,85,10,28,126,35,127,184,198,137,217],"18":[3,9,84,85,10,28,126,35,127,184,198,137,217]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsViewRunData.vue":{"43":[9,84,85,10,184,137,217],"55":[9,84,85,10,184,137,217],"58":[9,84,85,10,184,137,217],"81":[9,84,85,10,184,137,217],"92":[84,137],"94":[9,84,85,10,184,137,217],"124":[9,84,85,10,184,137,217],"126":[9,84,85,10,184,137,217],"130":[9,84,85,10,184,137,217],"137":[84,137],"141":[137],"143":[137]},"packages/frontend/editor-ui/src/features/execution/logs/logs.types.ts":{"55":[3,9,84,85,10,28,126,35,127,184,198,137,217],"59":[3,9,84,85,10,28,126,35,127,184,198,137,217]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/AssignmentCollection/AssignmentCollection.vue":{"39":"b:IAAAAAigAABAMFAABwAQEAADAAIAMAQngLIOAAA=","53":"b:IAAAAAigAABAMFAABwAQEAADAAIAMAQngLIOAAA=","56":"b:IAAAAAiAAAAAIEAAAAAQEAADAAAAEAQhgCAEAAA=","72":"b:IAAAAAiAAAAAMEAAAgAQEAADAAIAMAQhgKAEAAA=","77":"b:IAAAAAigAABAMFAABwAQEAADAAIAMAQngLIOAAA=","78":"b:IAAAAAigAABAMFAABwAQEAADAAIAMAQngLIOAAA=","79":[86,124],"82":[86,124],"85":[86,124],"90":[86,124,116],"91":"b:IAAAAAigAABAMFAABwAQEAADAAIAMAQngLIOAAA=","92":"b:IAAAAAigAABAMFAABwAQEAADAAIAMAQngLIOAAA=","107":"b:IAAAAAigAABAMFAABwAQEAADAAIAMAQngLIOAAA=","108":[86,124],"116":"b:IAAAAAigAABAMFAABwAQEAADAAIAMAQngLIOAAA=","117":[86,153,124,173,205,116,76,207,77,97],"119":[86,153,124,173,205,116,76,207,77,97],"129":[86,153,124,173,205,76,207,97],"138":[86,124],"150":[86,153,124,173,199,116,76,207,77],"154":[86,124],"158":"b:IAAAAAiAAAAAMEAAAgAQEAADAAIAMAQhgKAEAAA=","162":[86,124],"168":"b:IAAAAAigAABAMFAABwAQEAADAAIAMAQngLIOAAA=","190":"b:IAAAAAigAABAMFAABwAQEAADAAIAMAQngLIOAAA=","225":"b:IAAAAAiAAAAAMEAAAgAQEAADAAIAMAQhgKAEAAA=","234":[86,153,124,173,199,116,76,207,77],"235":[86,124],"241":[86,124],"252":[86,124],"262":"b:IAAAAAggAABAMFAABwAQEAADAAIAMAQngLIOAAA="},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ExpressionFunctionIcon.vue":{"8":"b:AACAACAAABBAXHAAAAAQEAB5AAAAAIVAAEACAAA="},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ExpressionParameterInput.vue":{"26":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMACAAA=","67":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMACAAA=","68":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMACAAA=","72":[86,124],"78":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMAAAAA=","84":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMAAAAA=","89":[86,124,60,206,116,75,76,207,77,140,78,141],"97":"b:IACAACAAABAAeHAAAAAQEAA7AAAAAARBAMACAAA=","100":"b:IAAAAAAAABAAeFAAAAAQEAA7AAAAAAAAAMAAAAA=","128":"b:IAAAAAAAABAAfHAAAgAQEAA7AAAAEAQAAMAAAAA=","137":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMACAAA=","148":[86,124,116],"160":[86,124,116],"166":[86,124,116],"175":[86,124,116],"181":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMACAAA=","185":"b:IACAACAAABBAGHAAAAAAEAAbAAAAAIRBAEAAAAA=","189":[86,124,116],"196":"b:IACAACAAABAAeHAAAAAQEAA7AAAAAARBAMACAAA=","199":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMACAAA=","219":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMACAAA=","244":[86,124,75]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FixedCollection/FixedCollectionParameterLegacy.vue":{"66":"b:oEGCAAAgAAAgODEAAwAQBCQYCAZQCAQACOIPAAA=","71":"b:oEEAAAAAAAAgOBEAAwAQBAQQCAYQKAQAAOIOAAA=","73":"b:oEEAAAAAAAAgOBEAAwAQBAQQCAYQKAQAAOIOAAA=","76":"b:oEEAAAAAAAAgOBEAAwAQBAQQCAYQKAQAAOIOAAA=","80":"b:oEGCAAAgAAAgODEAAwAQBCQYCAZQKAQACOIPAAA=","81":"b:AECCAAAgAAAAICEAAAAQACQYCABAAAAACCAHAAA=","82":"b:oEEAAAAAAAAgOBEAAwAQBAQQCAYQCAQAAOIOAAA=","83":"b:oEEAAAAAAAAgOBEAAwAQBAQQCAYQKAQAAOIOAAA=","85":"b:oEGCAAAgAAAgODEAAwAQBCQYCAZQCAQACOIPAAA=","92":"b:oEGCAAAgAAAgODEAAwAQBCQYCAZQKAQACOIPAAA=","94":"b:oEGCAAAgAAAgODEAAwAQBCQYCAZQKAQACOIPAAA=","105":"b:oEGCAAAgAAAgODEAAwAQBCQYCAZQKAQACOIPAAA=","108":[166,130,173],"111":"b:oEGCAAAgAAAgODEAAwAQBCQYCAZQKAQACOIPAAA=","115":[147,130],"122":[147,130],"126":[147,130],"140":"b:oEGCAAAgAAAgODEAAwAQBCQYCAZQKAQACOIPAAA=","155":[147,130],"160":[147,130],"191":[147,130],"196":"b:oEEAAAAAAAAgOBEAAwAQBAQQCAYQKAQAAOIOAAA=","207":[147,130],"232":"b:oEEAAAAAAAAgOBEAAwAQBAQQCAYQKAQAAOIOAAA=","242":[147,130],"263":[130],"276":[130],"299":"b:oEGCAAAgAAAgODEAAwAQBCQYCAZQKAQACOIPAAA=","300":"b:AEGCAAAAAAAAMAAAAAAQACQICAQAIAAAAEAAAAA=","307":"b:oEGCAAAgAAAgODEAAwAQBCQYCAZQKAQACOIPAAA=","339":[14,147,130,116,77],"362":[14,147,130,116,77],"368":[14,147,130,116,77],"382":[14,147,130,116,77],"389":[14,147,130,173,206,116,76],"421":"b:oEEAAAAAAAAgOBEAAwAQBAQQCAYQCAQAAOIOAAA=","423":"b:oEGCAAAgAAAgODEAAwAQBCQYCAZQKAQACOIPAAA=","439":"b:oEEAAAAAAAAgOBEAAwAQBAQQCAYQKAQAAOIOAAA=","461":"b:oEEAAAAAAAAgOBEAAwAQBAQQCAYQCAQAAOIOAAA=","531":[130],"532":[147,130],"636":[14,147,130,116,77],"644":[205,116,209,210,140]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputExpanded.vue":{"24":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","25":[86,124],"62":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","66":[86,124],"78":[86,124],"85":[86,124],"93":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","115":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","123":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","130":"b:AACCAAAgABAAIHQIAAAAEDAAAAgAAIAAAAAAAAA=","134":"b:AACCAAAgABAAIHQIAAAAEDAAAAgAAIAAAAAAAAA=","139":[86,124],"143":[86,124,60],"147":"b:AACCAAAgABAAIHQIAAAAEDAAAAgAAIAAAAAAAAA=","160":[86,124],"170":[86,124],"172":"b:gACCAIAgABAAYHQIAAAAEDAAACgAAIAAAAAAAAA=","185":"b:gACCAIAgABAAYHQIAAAAADAAACgAAIAAAAAAAAA=","196":"b:gACCAIAgABAAYHQIAAAAADAAACgAAIAAAAAAAAA=","219":[86],"226":[86]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputHint.vue":{"14":"b:oAAAAAAAABAgfHEAAwAQEAA/AAAQOIQgAOYCAAA=","23":"b:oAAAAAAAABAgfHEAAwAQEAA/AAAQOIQgAOYCAAA=","25":[86,124,178],"29":"b:IAAAAAAAABAAfEAAAgAQEAAzAAAAEAQgAMAAAAA=","41":"b:oAAAAAAAABAgfHEAAwAQEAA/AAAQOIQgAOYCAAA=","45":"b:oAAAAAAAABAgfHEAAwAQEAA/AAAQOIQgAOYCAAA="},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ResourceLocator/ResourceLocator.vue":{"82":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","165":[86,124,209,78],"179":[86,124,77,78],"188":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","201":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","203":[86,124,77,78],"210":[86,124,209,78],"213":[86,124,209,78],"222":[84,86,124,209,78],"235":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","238":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","246":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","261":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","265":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","269":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","270":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","283":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","340":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","350":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","352":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","365":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","367":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","370":[86,124,78],"378":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","380":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","387":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","391":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","392":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","393":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","394":[86,124],"396":[84,86,124,209,78],"400":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","414":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","420":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","426":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","430":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","454":[86,124],"517":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","523":[86,124,209,78],"531":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","533":[86,124],"542":[86,124,77,78],"552":[86,124,209,78],"560":[86,124],"572":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","573":[86,124,209,77,78],"593":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","595":[84,85,86,17,23,124,183,133,77,78],"620":[86,124],"640":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","644":"b:gACCAAAgAAAgYHEAAABAECAKAABQAIAACAACAAA=","649":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","654":"b:AAAAAAAAAAAgIHEAAABAEAAKAABQAIAAAAACAAA=","662":"b:gACCAAAAAAAgYHEAAABAECAKAABAAIAACAACAAA=","669":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","675":[86,124,77,78],"686":[86,124],"691":[86,124],"697":[86,124],"702":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","709":[86,124],"725":[86,124,78],"745":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","747":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","752":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","760":[86,124,77,78],"763":[86,124],"779":[86,124,78],"785":[86,124,78],"791":[86,124,77,78],"810":[86,124,77,78],"822":[86,124],"827":[86,124],"832":[86,124,209,78],"839":[86,124,78],"851":[84,86,124,209,78],"862":[84,86,124,209,78],"979":[84,86,124,78],"992":[84,86,124,78],"1000":[86,124,209,77,78],"1009":[86,124],"1012":[86,124],"1025":"b:gACCAAAAAAAgYHEAAABAECAKAABAAIAACAACAAA=","1033":[86,124,209,78],"1039":[86,124,209,78],"1047":[86,124],"1052":[86,124,209,77,78],"1065":[86,124],"1080":[86,124],"1091":[86,124],"1095":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","1121":[86,124],"1126":[86,124,209,78],"1133":[86,124,209,78],"1138":[86,124,78],"1149":[86,124],"1166":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","1186":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","1188":"b:gACCAAQgAAAgQHEAAABAECAKAABQAIAACAACAAA=","1195":"b:gACCAAQgAAAgQHEAAABAECAKAABQAIAACAACAAA=","1217":"b:gACCAAQgAAAgYHEAAABAECAKAABQAIAACAACAAA=","1243":[86,124],"1269":"b:gACAAAAAAAAgYHAAAABAEAAKAABQAIAAAAACAAA=","1298":[86,124],"1299":[86,124,77,78],"1312":[86,124]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ResourceLocator/ResourceLocatorDropdown.vue":{"15":"b:gACCAAQgAAAgYHEAAABAECBKAABQAIAACAAiAAA=","61":[86,124,78],"79":[86,124,78,142],"81":[86,124,78,142],"121":"b:gACCAAQgAAAgYHEAAABAECBKAABQAIAACAAiAAA=","122":[86,124,209,78,142],"128":[86,124,209,78,142],"137":"b:gACCAAQgAAAgYHEAAABAECBKAABQAIAACAAiAAA=","141":"b:AAAAAAAAAAAgIHEAAABAEABKAABQAIAAAAAiAAA=","145":[86,124],"152":[86,124],"204":[86,124,142],"208":[86,124,142],"221":[86,124,142],"224":[86,124,142],"231":[86,124],"235":[86,124,142],"250":"b:gACCAAAAAAAAYHAAAABAECBIAABAAIAACAAAAAA=","256":"b:gACCAAQgAAAgYHEAAABAECBKAABQAIAACAAiAAA=","258":"b:gACCAAQgAAAgYHEAAABAECBKAABQAIAACAAiAAA=","272":"b:gACCAAQgAAAgYHEAAABAECBKAABQAIAACAAiAAA=","284":"b:gACCAAQgAAAgYHEAAABAECBKAABQAIAACAAiAAA=","287":[86,124,209,78,142],"309":[86,124,78,142],"346":[86,124,142],"347":[86,124],"348":[86,124,142],"356":[86,124,78,142],"367":[86,124,142],"368":[86,124,142],"369":[86,124],"380":[86,124],"389":[86,124],"395":[86,124,78],"403":[86,124]},"packages/frontend/editor-ui/src/features/ndv/runData/components/error/NodeErrorView.vue":{"47":[5,6,84,85,86,124,137,209],"64":[86,124],"70":[86,124,209],"71":[86,124],"72":[86,124],"74":[86,124],"78":[5,6,84,85,86,124,137,209],"82":[5,86,124,209],"95":[5,6,84,85,86,124,137,209],"106":[5,6,84,85,86,124,137,209],"110":[84,85,86,124],"119":[5,6,84,85,86,124,137,209],"126":[84,85,86,124],"128":[86,124],"150":[5,6,84,85,86,124,137,209],"167":[5,6,84,85,86,124,137,209],"172":[5,6,86,124],"179":[5,6,84,85,86,124,137,209],"186":[5,84,85,86,124,209],"202":[5,6,84,85,86,124,209],"206":[5,6,84,85,86,124,209],"231":[5,6,84,85,86,124,137,209],"243":[5,6,84,85,86,124,137,209],"246":[5,6,84,85,86,124,137,209],"271":[5,86,124,209],"281":[5,86,124,209],"287":[5,86,124,209],"301":[5,86,124,209],"331":[86,124],"416":[86,124],"423":[5,6,84,85,86,124,209],"428":[86,124],"457":[5,6,86,124],"486":[86,124],"488":[5,6,84,85,86,124,137,209],"544":[5,6,84,85,86,124,137,209],"583":[84,85,86,124]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/theme.ts":{"91":"b:QAQAAAAAAABEOFAAAxAwFMAQAAEAARAQANYSAgA="},"packages/frontend/editor-ui/src/features/shared/editors/components/InlineExpressionEditor/InlineExpressionEditorInput.vue":{"26":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMACAAA=","39":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMACAAA=","51":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMACAAA=","55":[86,124],"75":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMACAAA=","81":"b:IAAAAAAAABAAfHAAAgAQEAA7AAAAEAQAAMAAAAA=","88":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMACAAA=","97":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMAAAAA=","104":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMAAAAA=","107":"b:AAAAAAAAABAAfEAAAgAQEAAgAAAAAABAAMAAAAA=","112":[86,124],"118":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMACAAA="},"packages/frontend/editor-ui/src/features/shared/editors/components/InlineExpressionEditor/InlineExpressionEditorOutput.vue":{"26":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMQCAAA=","39":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMQAAAA=","40":"b:AAAAAAAAABAANEAAAgAQEAAwAAAAAAAAAMQAAAA=","45":"b:IACAACAAABBAGHAAAAAAEAAbAAAAAIRBAEQAAAA=","52":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMQCAAA=","69":"b:AAAAAAAAABAAXEAAAgAQEAAwAAAAAABAAMQAAAA=","73":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMQAAAA=","79":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMQAAAA="},"packages/frontend/editor-ui/src/features/shared/editors/components/InlineExpressionEditor/theme.ts":{"4":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMQCAAA=","18":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMACAAA=","58":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMQCAAA="},"packages/frontend/editor-ui/src/features/shared/editors/components/JsEditor/JsEditor.vue":{"31":[84,86,124],"36":[84,86,124],"40":[84,86,124],"41":[86,124],"57":[84,86,124],"65":[86,124],"73":[84,86,124],"77":[84,86,124],"102":[84,86,124],"111":[86,124],"121":[84,86,124]},"packages/frontend/editor-ui/src/features/shared/editors/composables/useExpressionEditor.ts":{"73":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMQCAAA=","84":"b:AAAAAAAAABAAfEAAAgAQEAAgAAAAAAAAAMAAAAA=","99":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMQCAAA=","118":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMQCAAA=","123":"b:IACAACAAABBAfHAAAgAQEAA7AAAAEIRBAMQAAAA=","137":"b:IACAACAAABBAfHAAAgAQEAA7AAAAEIRBAMQAAAA=","157":"b:IACAACAAABBAfHAAAgAQEAA7AAAAEIRBAMQAAAA=","192":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMQCAAA=","196":"b:IAAAAAAAABAAfHAAAgAQEAA7AAAAEAQAAMQAAAA=","202":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMQCAAA=","213":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMQCAAA=","217":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMQCAAA=","228":"b:IACAACAAABBAeHAAAAAQEAA4AAAAAIBAAMQCAAA=","236":"b:IACAACAAABBAfHAAAgAQEAA4AAAAAIBAAMQCAAA=","243":"b:AAAAAAAAAAAAfEAAAgAQEAAgAAAAAAAAAMQAAAA=","254":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMACAAA=","265":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMQCAAA=","292":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMQAAAA=","297":"b:AAAAAAAAABAAfEAAAgAQEAAgAAAAAABAAMAAAAA=","309":"b:AAAAAAAAABAAfEAAAgAAEAAwAAAAAAAAAMQAAAA=","327":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMQCAAA=","335":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMQCAAA=","345":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMQCAAA=","357":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMQCAAA=","368":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMQCAAA=","372":"b:IACAACAAABBAGHAAAAAAEAAbAAAAAIRBAEQAAAA=","379":[84,85,86,23,124,37,183,184,190,70,206,139],"381":[84,85,86,23,124,37,183,184,190,70,206,139],"387":[84,85,86,23,124,37,183,184,190,70,206,139],"397":"b:IACAACAAABBAfHAAAgAQEAA7AAAAEIRBAMQAAAA=","485":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMQCAAA=","487":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMQCAAA=","488":"b:IAAAAAAAABAAfHAAAgAQEAA7AAAAEAQAAMQAAAA=","491":"b:IAAAAAAAABAAfHAAAgAQEAA7AAAAEAQAAMQAAAA=","492":"b:IAAAAAAAABAAfHAAAgAQEAA7AAAAEAQAAMQAAAA=","495":[86,124],"496":[86,124],"522":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMACAAA=","525":"b:IAAAAAAAABAAfHAAAgAQEAA7AAAAEAQAAMAAAAA=","555":"b:IAAAAAAAABAAfHAAAgAQEAA7AAAAEAQAAMAAAAA=","571":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMQCAAA=","572":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMQCAAA=","582":"b:AAAAAAAAABAAfEAAAgAQEAAgAAAAAABAAMAAAAA=","594":[86,124],"600":[86,124],"602":"b:AAAAAAAAABAAfEAAAgAQEAAgAAAAAABAAMAAAAA="},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/addCompletions.ts":{"8":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMQCAAA=","15":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMQCAAA="},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/dragAndDrop.ts":{"9":[86,124],"15":"b:YASAACAAABBEfHAAAxAwFMB7AAEAEZVxANYSAgA=","18":"b:YACAACAAABBAfHAAAhAQEIB7AAAAEIVxAMQSAAA=","20":"b:YACAACAAABBAfHAAAhAQEIB7AAAAEIVhAMQSAAA=","35":"b:YASAACAAABBEfHAAAxAwFMB7AAEAEZVxANYSAgA=","42":"b:YASAACAAABBEfHAAAxAwFMB7AAEAEZVxANYSAgA=","46":"b:YASAACAAABBEfHAAAxAwEMB7AAEAEZVxANYSAgA=","67":[86,124],"80":[86,124],"93":"b:IASAACAAABBEOHAAAxAQEMAbAAEAAZRRAMYCAgA=","97":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAAAAAMQSAAA=","104":"b:AAAAAAAAABAAfEAAAgAQEIAwAAAAAAAAAMQCAAA=","112":"b:AAAAAAAAABAAeEAAAgAQEAAwAAAAAAAAAMQQAAA=","115":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAAAAAMQCAAA=","123":[86,124,116],"127":[86,124,116],"139":[86,124,116],"143":[86,124,116],"156":[86,124],"163":"b:YASAACAAABBEfHAAAxAwFMB7AAEAEZVxANYSAgA="},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/expressionCloseBrackets.ts":{"10":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMQCAAA=","14":"b:AAAAAAAAABAAfEAAAgAQEAAgAAAAAAAAAMQAAAA=","36":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMQCAAA="},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/expressionDeprecations.ts":{"11":"b:IACAACAAABBAfHAAAgAQEAA7AAAAEIRBAMQAAAA=","15":"b:IACAACAAABBAfHAAAgAQEAA7AAAAEIRBAMQAAAA="},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/n8nLang.ts":{"11":[86,124,178,206,116,75,76,207],"14":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMACAAA=","25":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMACAAA=","28":"b:IACAACAAABBAfHAAAgAQEAB7AAAAEIVhAMACAAA=","32":"b:IASAACAAABBAfHAAAgAwFEB7AAAAEYVhANQSAAA=","37":[86,124,206,116,77,97]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/ViewItem.vue":{"16":"b:oECCAIAiAABkfTEIBxAQAOxgCAHgIJAOCNYOAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/buttons/CanvasChatButton.vue":{"9":"b:AAaAACAAAAAAADAAAAAAAAgKAAAAAMBBQAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/buttons/CanvasStopWaitingForWebhookButton.vue":{"5":"b:AAYAAAAAAAAAADAAAgAACAQDCEAAIAABQAAAAAA=","9":"b:AAYAAAAAAAAAADAAAgAACAQDCEAAIAABQAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/edges/CanvasConnectionLine.vue":{"11":"b:AAAAACAAAADAAHAAAAAAEAAgAAHgAABCABAgAAA=","17":"b:AAAAACAAAADAAHAAAAAAEAAgAAHgAABCABAgAAA=","21":"b:AAAAACAAAADAAHAAAAAAEAAgAAHgAABCABAgAAA=","25":"b:AAAAACAAAADAAHAAAAAAEAAgAAHgAABCABAgAAA=","32":"b:AAAAACAAAADAAHAAAAAAEAAgAAHgAABCABAgAAA=","40":"b:AAAAACAAAADAAHAAAAAAEAAgAAHgAABCABAgAAA=","47":"b:AAAAACAAAADAAHAAAAAAEAAgAAHgAABCABAgAAA=","55":"b:AAAAACAAAADAAHAAAAAAEAAgAAHgAABCABAgAAA=","56":"b:AAAAACAAAABAAHAAAAAAEAAgAAHgAABCABAgAAA=","60":"b:AAAAACAAAADAAHAAAAAAEAAgAAHgAABCABAgAAA=","64":"b:AAAAACAAAADAAHAAAAAAEAAgAAHgAABCABAgAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/handles/render-types/CanvasHandleNonMainInput.vue":{"19":"b:EASAACAAAABgIHAAAAAAEAAKAAAAAKBAAAAAAAA=","21":"b:EASAACAAAABgIHAAAAAAEAAKAAAAAKBAAAAAAAA=","27":"b:EASAACAAAABgIHAAAAAAEAAKAAAAAKBAAAAAAAA=","33":"b:AACAACAAAABgIHAAAAAAEAAKAAAAAKBAAAAAAAA=","39":"b:EASAACAAAABgIHAAAAAAEAAKAAAAAKBAAAAAAAA=","44":[84,85,86,124,37,190],"48":[84,85,86,124,37,190],"52":[84,85,86,124,37,190],"54":"b:EASAACAAAABgIHAAAAAAEAAKAAAAAKBAAAAAAAA=","61":"b:EASAACAAAABgAHAAAAAAEAAKAAAAAKBAAAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/handles/render-types/CanvasHandleNonMainOutput.vue":{"13":"b:EASAACAAAAAAIHAAAAAAEAAKAAAAAKBAAAAAAAA=","15":"b:EASAACAAAAAAIHAAAAAAEAAKAAAAAKBAAAAAAAA=","23":"b:EASAACAAAAAAIHAAAAAAEAAKAAAAAKBAAAAAAAA=","27":"b:EASAACAAAAAAIHAAAAAAEAAKAAAAAKBAAAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/handles/render-types/parts/CanvasHandleDiamond.vue":{"13":"b:EASAACAAAABgIHAAAAAAEAAKAAAAAKBAAAAAAAA="},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/parts/CanvasNodeTooltip.vue":{"11":"b:AAYAAAAAAAAAAHAAEgAAGAQDCEAAIAABAAAAAAA=","13":"b:AAYAAAAAAAAAAHAAEgAAGAQDCEAAIAABAAAAAAA=","14":"b:AAYAAAAAAAAAAHAAEgAAGAQDCEAAIAABAAAAAAA=","26":"b:AAYAAAAAAAAAAHAAEgAAGAQDCEAAIAABAAAAAAA=","28":"b:AAYAAAAAAAAAAHAAEgAAGAQDCEAAIAABAAAAAAA="},"packages/modules/type-availability-policies/frontend/src/policy-violations/policyViolations.ts":{"10":"b:YAAAAAAAAAAAAXAAAAAAEAADAAAAABAAACCCAQA=","16":"b:YAAAAAAAAAAAAXAAAAAAEAADAAAAABAAACCCAQA="},"packages/@n8n/backend-network/src/http/env-proxy-http-agent.ts":{"26":"b:8EPCACDpHwT0PkToCTACAEAIAAUAAAAAACAAAAA=","28":"b:8EPCACDpHwT0PkToCTACAEAIAAUAAAAAACAAAAA=","33":"b:8EPCACDpHwT0PkToCTACAEAIAAUAAAAAACAAAAA="},"packages/@n8n/db/src/repositories/deployment-key.repository.ts":{"36":"b:oACTGxioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA=","40":"b:oACTGxioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA=","49":"b:oACTGxioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA=","71":"b:oACTGxioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA=","111":"b:oACTGxioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA=","125":"b:oACTGxioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA=","126":"b:oACTGxioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA=","145":"b:oACTGxioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA=","149":"b:oACTGxioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA=","153":"b:oACTGxioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA=","157":"b:oACTGxioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA=","161":"b:oACTGxioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA=","165":"b:oACTGxioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA=","169":"b:oACTGxioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA=","175":"b:oACTGxioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA=","184":"b:oACTGxioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA=","190":"b:oACTGxioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA=","201":"b:oACTGxioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA=","240":"b:oACTGxioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA=","247":"b:oACTGxioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA=","257":"b:oACTGxioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA=","268":"b:oACTGxioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA=","269":"b:oACTGxioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA=","285":"b:oACTGxioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA=","289":"b:oACTGxioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA=","295":"b:oACTGxioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA=","305":"b:oACTGxioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA=","312":"b:oACTGxioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA=","320":"b:oACTGxioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA="},"packages/@n8n/db/src/utils/sql.ts":{"4":"b:gAACAwAwAJoAAAIrHAAAAjAAgAAEAAAACQAAAAA="},"packages/@n8n/inbound-auth/src/trusted-source.ts":{"66":[86,124],"67":"b:oACTExioANzAOEQ4ARAAEgCAoA0AAAAAAAAAAAA=","102":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","110":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","112":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","129":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA="},"packages/cli/src/middlewares/list-query/dtos/base.filter.dto.ts":{"7":"b:gACDkwy4AJgigAIrCAAAQjAAgAAAAAAABAgAAAA=","23":"b:gACDkwy4AJgigAIrCAAAQjAAgAAAAAAABAgAAAA="},"packages/cli/src/middlewares/list-query/dtos/credentials.filter.dto.ts":{"22":[7,17,23,91,124,44,45,60,132,133,65,81]},"packages/cli/src/middlewares/list-query/filter.ts":{"11":"b:gACDkwy4ANgCgAYrCAAkQjAAgCAAAAAABAgACAA="},"packages/cli/src/middlewares/list-query/pagination.ts":{"10":"b:gACDkwy4ANgCgAYrCAAkQjAAgCAAAAAABAgACAA="},"packages/cli/src/middlewares/list-query/select.ts":{"11":"b:gACDkwy4ANgCgAYrCAAkQjAAgCAAAAAABAgACAA="},"packages/cli/src/middlewares/list-query/sort-by.ts":{"12":"b:gACDkwy4ANgCgAYrCAAkQjAAgCAAAAAABAgACAA="},"packages/cli/src/modules/data-table/data-table-file-cleanup.service.ts":{"11":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","19":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","28":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","36":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","73":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA="},"packages/cli/src/modules/data-table/data-table-file-cleanup.task.ts":{"21":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","26":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA="},"packages/cli/src/modules/inbound-auth-core/database/repositories/trusted-source.repository.ts":{"15":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","19":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","73":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","82":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","86":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","90":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","99":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","122":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","131":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","145":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","149":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","154":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","167":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","178":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","190":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA="},"packages/cli/src/modules/inbound-auth-core/trusted-source-discovery.service.ts":{"30":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","37":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","42":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","46":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","57":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","71":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","84":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA="},"packages/cli/src/modules/inbound-auth-core/trusted-source-discovery.task.ts":{"21":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","23":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA="},"packages/cli/src/modules/inbound-auth-core/trusted-source.store.ts":{"43":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","48":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","49":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","70":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","81":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","84":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","88":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","91":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","96":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","100":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","105":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","107":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","111":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","117":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","118":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","122":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","135":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","150":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","170":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","196":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","208":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","219":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","272":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","280":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","293":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","308":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","310":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","311":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","314":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","332":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA="},"packages/cli/src/modules/mcp/mcp-protected-resource.ts":{"66":"b:oACTG1ioANzIOAQ4AVAAAgCAoE0IAAAAAAAAAAA=","76":"b:oACTG1ioANzIOAQ4AVAAAgCAoE0IAAAAAAAAAAA=","78":"b:oACTG1ioANzIOAQ4AVAAAgCAoE0IAAAAAAAAAAA=","85":"b:oACTG1ioANzIOAQ4AVAAAgCAoE0IAAAAAAAAAAA=","103":"b:oACTG1ioANzIOAQ4AVAAAgCAoE0IAAAAAAAAAAA=","104":"b:oACTG1ioANzIOAQ4AVAAAgCAoE0IAAAAAAAAAAA=","107":"b:oACTG1ioANzIOAQ4AVAAAgCAoE0IAAAAAAAAAAA=","118":"b:oACTG1ioANzIOAQ4AVAAAgCAoE0IAAAAAAAAAAA=","134":"b:oACTG1ioANzIOAQ4AVAAAgCAoE0IAAAAAAAAAAA=","145":"b:oACTG1ioANzIOAQ4AVAAAgCAoE0IAAAAAAAAAAA=","150":"b:oACTG1ioANzIOAQ4AVAAAgCAoE0IAAAAAAAAAAA=","156":"b:oACTG1ioANzIOAQ4AVAAAgCAoE0IAAAAAAAAAAA=","173":"b:oACTG1ioANzIOAQ4AVAAAgCAoE0IAAAAAAAAAAA=","187":"b:oACTG1ioANzIOAQ4AVAAAgCAoE0IAAAAAAAAAAA=","193":"b:oACTG1ioANzIOAQ4AVAAAgCAoE0IAAAAAAAAAAA=","202":"b:oACTG1ioANzIOAQ4AVAAAgCAoE0IAAAAAAAAAAA=","206":"b:oACTG1ioANzIOAQ4AVAAAgCAoE0IAAAAAAAAAAA="},"packages/cli/src/modules/mcp/mcp-tool-availability.ts":{"19":"b:oACTG1ioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA=","23":"b:oACTG1ioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA=","51":"b:oACTG1ioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA="},"packages/cli/src/modules/oauth-server/oauth-local-authorization-server.ts":{"20":"b:oACTExioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA=","37":"b:oACTExioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA=","64":"b:oACTExioANzAOAQ4AVAAAgCAoA0AAAAAAAAAAAA="},"packages/cli/src/modules/oauth-server/oauth-signing-jwks.provider.ts":{"15":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","20":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","24":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","25":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA=","31":"b:oACTExioANzAOAQ4ARAAAgCAoA0AAAAAAAAAAAA="},"packages/cli/src/modules/oauth-server/oauth-signing-key.service.ts":{"83":"b:oACTGxioANzIOAQ4AVAAAgCAoE0AAAAAAAAAAAA=","95":"b:oACTGxioANzIOAQ4AVAAAgCAoE0AAAAAAAAAAAA=","115":"b:oACTGxioANzIOAQ4AVAAAgCAoE0AAAAAAAAAAAA=","132":"b:oACTGxioANzIOAQ4AVAAAgCAoE0AAAAAAAAAAAA=","134":"b:oACTGxioANzIOAQ4AVAAAgCAoE0AAAAAAAAAAAA=","142":"b:oACTGxioANzIOAQ4AVAAAgCAoE0AAAAAAAAAAAA=","163":"b:oACTGxioANzIOAQ4AVAAAgCAoE0AAAAAAAAAAAA=","179":"b:oACTGxioANzIOAQ4AVAAAgCAoE0AAAAAAAAAAAA=","181":"b:oACTGxioANzIOAQ4AVAAAgCAoE0AAAAAAAAAAAA=","185":"b:oACTGxioANzIOAQ4AVAAAgCAoE0AAAAAAAAAAAA=","189":"b:oACTGxioANzIOAQ4AVAAAgCAoE0AAAAAAAAAAAA=","199":"b:oACTGxioANzIOAQ4AVAAAgCAoE0AAAAAAAAAAAA=","204":"b:oACTGxioANzIOAQ4AVAAAgCAoE0AAAAAAAAAAAA=","208":"b:oACTGxioANzIOAQ4AVAAAgCAoE0AAAAAAAAAAAA=","212":"b:oACTGxioANzIOAQ4AVAAAgCAoE0AAAAAAAAAAAA=","219":"b:oACTGxioANzIOAQ4AVAAAgCAoE0AAAAAAAAAAAA=","222":"b:oACTGxioANzIOAQ4AVAAAgCAoE0AAAAAAAAAAAA=","223":"b:oACTGxioANzIOAQ4AVAAAgCAoE0AAAAAAAAAAAA=","238":"b:oACTGxioANzIOAQ4AVAAAgCAoE0AAAAAAAAAAAA=","250":"b:oACTGxioANzIOAQ4AVAAAgCAoE0AAAAAAAAAAAA=","291":"b:oACTGxioANzIOAQ4AVAAAgCAoE0AAAAAAAAAAAA=","313":"b:oACTGxioANzIOAQ4AVAAAgCAoE0AAAAAAAAAAAA=","321":"b:oACTGxioANzIOAQ4AVAAAgCAoE0AAAAAAAAAAAA=","322":"b:oACTGxioANzIOAQ4AVAAAgCAoE0AAAAAAAAAAAA=","323":"b:oACTGxioANzIOAQ4AVAAAgCAoE0AAAAAAAAAAAA="},"packages/cli/src/requests.ts":{"54":"b:gAC/kwy4AJwigAIrCAAAQjBAgAAIAAAAFAgACAA=","63":"b:gAC/kwy4AJwigAIrCAAAQjBAgAAIAAAAFAgACAA=","66":"b:gAC/kwy4AJwigAIrCAAAQjBAgAAIAAAAFAgACAA="},"packages/cli/src/scheduling/system-tasks/in-memory-system-task-runner.ts":{"63":"b:oACTFxioANzAOAQ6ARAAAgCAoA0AAAAAAAAAAAA=","73":"b:oACTFxioANzAOAQ6ARAAAgCAoA0AAAAAAAAAAAA=","81":"b:oACTFxioANzAOAQ6ARAAAgCAoA0AAAAAAAAAAAA=","99":"b:oACTFxioANzAOAQ6ARAAAgCAoA0AAAAAAAAAAAA=","116":"b:oACTFxioANzAOAQ6ARAAAgCAoA0AAAAAAAAAAAA=","125":"b:oACTFxioANzAOAQ6ARAAAgCAoA0AAAAAAAAAAAA=","132":"b:oACTFxioANzAOAQ6ARAAAgCAoA0AAAAAAAAAAAA=","139":"b:oACTFxioANzAOAQ6ARAAAgCAoA0AAAAAAAAAAAA=","144":"b:oACTFxioANzAOAQ6ARAAAgCAoA0AAAAAAAAAAAA=","151":"b:oACTFxioANzAOAQ6ARAAAgCAoA0AAAAAAAAAAAA=","158":"b:oACTFxioANzAOAQ6ARAAAgCAoA0AAAAAAAAAAAA=","169":"b:oACTFxioANzAOAQ6ARAAAgCAoA0AAAAAAAAAAAA=","179":"b:oACTFxioANzAOAQ6ARAAAgCAoA0AAAAAAAAAAAA=","193":"b:oACTFxioANzAOAQ6ARAAAgCAoA0AAAAAAAAAAAA=","206":"b:oACTFxioANzAOAQ6ARAAAgCAoA0AAAAAAAAAAAA=","229":"b:oACTFxioANzAOAQ6ARAAAgCAoA0AAAAAAAAAAAA=","233":"b:oACTFxioANzAOAQ6ARAAAgCAoA0AAAAAAAAAAAA=","243":"b:oACTFxioANzAOAQ6ARAAAgCAoA0AAAAAAAAAAAA=","248":"b:oACTFxioANzAOAQ6ARAAAgCAoA0AAAAAAAAAAAA="},"packages/cli/src/scheduling/system-tasks/system-task-timer.ts":{"37":"b:oACTFxioANzAOAQ6ARAAAgCAoA0AAAAAAAAAAAA=","45":"b:oACTFxioANzAOAQ6ARAAAgCAoA0AAAAAAAAAAAA=","50":"b:oACTFxioANzAOAQ6ARAAAgCAoA0AAAAAAAAAAAA=","55":"b:oACTFxioANzAOAQ6ARAAAgCAoA0AAAAAAAAAAAA=","99":"b:oACTFxioANzAOAQ6ARAAAgCAoA0AAAAAAAAAAAA=","117":"b:oACTFxioANzAOAQ6ARAAAgCAoA0AAAAAAAAAAAA=","140":"b:oACTFxioANzAOAQ6ARAAAgCAoA0AAAAAAAAAAAA=","143":"b:oACTFxioANzAOAQ6ARAAAgCAoA0AAAAAAAAAAAA=","148":"b:oACTFxioANzAOAQ6ARAAAgCAoA0AAAAAAAAAAAA="},"packages/cli/src/services/protected-resource.registry.ts":{"46":"b:oACTGxioANzIOAQ4AVAAAgCAoE0IAAAAAAAAAAA=","49":"b:oACTGxioANzIOAQ4AVAAAgCAoE0IAAAAAAAAAAA=","54":"b:oACTGxioANzIOAQ4AVAAAgCAoE0IAAAAAAAAAAA=","68":"b:oACTGxioANzIOAQ4AVAAAgCAoE0IAAAAAAAAAAA=","70":"b:oACTGxioANzIOAQ4AVAAAgCAoE0IAAAAAAAAAAA=","74":"b:oACTGxioANzIOAQ4AVAAAgCAoE0IAAAAAAAAAAA=","78":"b:oACTGxioANzIOAQ4AVAAAgCAoE0IAAAAAAAAAAA=","83":"b:oACTGxioANzIOAQ4AVAAAgCAoE0IAAAAAAAAAAA=","86":"b:oACTGxioANzIOAQ4AVAAAgCAoE0IAAAAAAAAAAA=","102":"b:oACTGxioANzIOAQ4AVAAAgCAoE0IAAAAAAAAAAA=","137":"b:oACTGxioANzIOAQ4AVAAAgCAoE0IAAAAAAAAAAA=","143":"b:oACTGxioANzIOAQ4AVAAAgCAoE0IAAAAAAAAAAA=","148":"b:oACTGxioANzIOAQ4AVAAAgCAoE0IAAAAAAAAAAA=","164":"b:oACTGxioANzIOAQ4AVAAAgCAoE0IAAAAAAAAAAA=","173":"b:oACTGxioANzIOAQ4AVAAAgCAoE0IAAAAAAAAAAA="},"packages/nodes-base/nodes/Notion/Notion.node.ts":{"9":[17,45,195,118,133,77,80]},"packages/nodes-base/nodes/Notion/shared/GenericFunctions.ts":{"33":[17,45,195,118,133,201,77,80],"54":[17,45,195,118,133,201,77,80],"90":[17,45,195,118,133,201,77,80],"124":[17,45,195,118,133,201,77,80],"145":[17,45,195,118,133,201,77,80],"166":[17,45,195,118,133,201,77,80],"211":[17,45,195,118,133,201,77,80],"219":[17,45,195,118,133,201,77,80],"225":[17,45,195,118,133,201,77,80],"231":[17,45,195,118,133,201,77,80],"255":[17,45,195,118,133,201,77,80],"302":[17,45,195,118,133,201,77,80],"311":[17,45,195,118,133,201,77,80],"327":[17,45,195,118,133,201,77,80],"334":[17,45,195,118,133,201,77,80],"338":[17,45,195,118,133,201,77,80],"345":[17,45,195,118,133,201,77,80],"364":[17,45,195,118,133,201,77,80],"373":[17,45,195,118,133,201,77,80],"376":[17,45,195,118,133,201,77,80],"377":[17,45,195,118,133,201,77,80],"379":[17,45,195,118,133,201,77,80],"382":[17,45,195,118,133,201,77,80],"400":[17,45,195,118,133,201,77,80],"402":[17,45,195,118,133,201,77,80],"403":[17,45,195,118,133,201,77,80],"420":[17,45,195,118,133,201,77,80],"479":[17,45,195,118,133,201,77,80],"491":[17,45,195,118,133,201,77,80],"503":[17,45,195,118,133,201,77,80],"511":[17,45,195,118,133,201,77,80],"513":[17,45,195,118,133,201,77,80],"517":[17,45,195,118,133,201,77,80],"518":[17,45,195,118,133,201,77,80],"524":[17,45,195,118,133,201,77,80],"525":[17,45,195,118,133,201,77,80],"534":[17,45,195,118,133,201,77,80],"535":[17,45,195,118,133,201,77,80],"583":[17,45,195,118,133,201,77,80],"590":[17,45,195,118,133,201,77,80],"611":[17,45,195,118,133,201,77,80],"617":[17,45,195,118,133,201,77,80],"619":[17,45,195,118,133,201,77,80],"623":[17,45,195,118,133,201,77,80],"642":[17,45,195,118,133,201,77,80],"650":[17,45,195,118,133,201,77,80],"658":[17,45,195,118,133,201,77,80],"660":[17,45,195,118,133,201,77,80],"666":[17,45,195,118,133,201,77,80],"668":[17,45,195,118,133,201,77,80],"678":[17,45,195,118,133,201,77,80],"731":[17,45,195,118,133,201,77,80],"740":[17,45,195,118,133,201,77,80],"827":[17,45,195,118,133,201,77,80],"845":[17,45,195,118,133,201,77,80],"861":[17,45,195,118,133,201,77,80],"882":[17,45,195,118,133,201,77,80],"922":[17,45,195,118,133,201,77,80],"931":[17,45,195,118,133,201,77,80],"957":[17,45,195,118,133,201,77,80],"970":[17,45,195,118,133,201,77,80],"1090":[17,45,195,118,133,201,77,80],"1104":[17,45,195,118,133,201,77,80],"1105":[17,45,195,118,133,201,77,80],"1118":[17,45,195,118,133,201,77,80],"1134":[17,45,195,118,133,201,77,80],"1139":[17,45,195,118,133,201,77,80],"1147":[17,45,195,118,133,201,77,80],"1164":[17,45,195,118,133,201,77,80],"1176":[17,45,195,118,133,201,77,80],"1216":[17,45,195,118,133,201,77,80]},"packages/nodes-base/nodes/Notion/shared/descriptions/Blocks.ts":{"164":[17,45,195,118,133,77,80],"171":[17,45,195,118,133,77,80],"407":[17,45,195,118,133,77,80],"459":[17,45,195,118,133,77,80],"475":[17,45,195,118,133,77,80],"491":[17,45,195,118,133,77,80],"501":[17,45,195,118,133,77,80],"511":[17,45,195,118,133,77,80],"526":[17,45,195,118,133,77,80],"602":[17,45,195,118,133,77,80]},"packages/nodes-base/nodes/Notion/shared/descriptions/Filters.ts":{"1":[17,45,195,118,133,201,77,80]},"packages/nodes-base/nodes/Notion/shared/methods/listSearch.ts":{"10":[17,45,195,118,133,201,77,80],"28":[17,45,195,118,133,201,77,80]},"packages/nodes-base/nodes/Notion/v1/NotionV1.node.ts":{"35":[17,45,195,118,133,77,80],"45":[17,45,195,118,133,77,80],"74":[17,45,195,118,133,77,80],"85":[17,45,195,118,133,77,80],"101":[17,45,195,118,133,77,80],"112":[17,45,195,118,133,77,80],"115":[17,45,195,118,133,77,80],"129":[17,45,195,118,133,77,80],"134":[17,45,195,118,133,77,80],"140":[17,45,195,118,133,77,80],"145":[17,45,195,118,133,77,80],"158":[17,45,195,118,133,77,80],"189":[17,45,195,118,133,77,80],"201":[17,45,195,118,133,77,80],"216":[17,45,195,118,133,77,80],"224":[17,45,195,118,133,77,80],"244":[17,45,195,118,133,77,80],"429":[17,45,195,118,133,77,80],"434":[17,45,195,118,133,77,80]},"packages/nodes-base/nodes/Notion/v2/NotionV2.node.ts":{"38":[17,45,195,118,133,77,80],"47":[17,45,195,118,133,77,80],"140":[17,45,195,118,133,77,80],"465":[17,45,195,118,133,77,80],"469":[17,45,195,118,133,77,80]},"packages/nodes-base/nodes/Notion/v2/methods/loadOptions.ts":{"12":[17,45,195,118,133,77,80],"42":[17,45,195,118,133,77,80],"54":[17,45,195,118,133,77,80],"72":[17,45,195,118,133,77,80],"84":[17,45,195,118,133,77,80],"88":[17,45,195,118,133,77,80],"104":[17,45,195,118,133,77,80],"112":[17,45,195,118,133,77,80],"118":[17,45,195,118,133,77,80],"124":[17,45,195,118,133,77,80],"138":[17,45,195,118,133,77,80],"171":[17,45,195,118,133,77,80],"183":[17,45,195,118,133,77,80],"202":[17,45,195,118,133,77,80],"210":[17,45,195,118,133,77,80]},"packages/nodes-base/nodes/Notion/v3/NotionV3.node.ts":{"15":[17,45,195,118,133,77,80],"24":[17,45,195,118,133,77,80]},"packages/nodes-base/nodes/Notion/v3/actions/block/Block.resource.ts":{"19":[17,45,195,118,133,77,80],"48":[17,45,195,118,133,77,80],"147":[17,45,195,118,133,77,80],"182":[17,45,195,118,133,77,80],"210":[17,45,195,118,133,77,80]},"packages/nodes-base/nodes/Notion/v3/actions/common.descriptions.ts":{"212":[17,45,195,118,133,77,80],"231":[17,45,195,118,133,77,80],"251":[17,45,195,118,133,77,80],"299":[17,45,195,118,133,77,80],"319":[17,45,195,118,133,77,80]},"packages/nodes-base/nodes/Notion/v3/actions/dataSource/DataSource.resource.ts":{"85":[17,45,195,118,133,77,80],"113":[17,45,195,118,133,77,80]},"packages/nodes-base/nodes/Notion/v3/actions/database/Database.resource.ts":{"52":[17,45,195,118,133,77,80]},"packages/nodes-base/nodes/Notion/v3/actions/databasePage/DataSourceFilters.ts":{"105":[17,45,195,118,133,77,80],"106":[17,45,195,118,133,77,80],"112":[17,45,195,118,133,77,80],"113":[17,45,195,118,133,77,80],"130":[17,45,195,118,133,77,80],"131":[17,45,195,118,133,77,80],"136":[17,45,195,118,133,77,80],"141":[17,45,195,118,133,77,80],"148":[17,45,195,118,133,77,80],"152":[17,45,195,118,133,77,80],"161":[17,45,195,118,133,77,80],"197":[17,45,195,118,133,77,80],"207":[17,45,195,118,133,77,80],"217":[17,45,195,118,133,77,80],"265":[17,45,195,118,133,77,80],"266":[17,45,195,118,133,77,80],"272":[17,45,195,118,133,77,80],"358":[17,45,195,118,133,77,80],"365":[17,45,195,118,133,77,80],"371":[17,45,195,118,133,77,80],"373":[17,45,195,118,133,77,80]},"packages/nodes-base/nodes/Notion/v3/actions/databasePage/DatabasePage.resource.ts":{"40":[17,45,195,118,133,77,80],"127":[17,45,195,118,133,77,80],"482":[17,45,195,118,133,77,80],"498":[17,45,195,118,133,77,80],"573":[17,45,195,118,133,77,80],"603":[17,45,195,118,133,77,80],"665":[17,45,195,118,133,77,80]},"packages/nodes-base/nodes/Notion/v3/actions/page/Page.resource.ts":{"211":[17,45,195,118,133,77,80],"235":[17,45,195,118,133,77,80],"266":[17,45,195,118,133,77,80],"290":[17,45,195,118,133,77,80],"324":[17,45,195,118,133,77,80]},"packages/nodes-base/nodes/Notion/v3/actions/router.ts":{"22":[17,45,195,118,133,77,80]},"packages/nodes-base/nodes/Notion/v3/actions/user/User.resource.ts":{"37":[17,45,195,118,133,77,80],"59":[17,45,195,118,133,77,80]},"packages/nodes-base/nodes/Notion/v3/helpers/utils.ts":{"12":[17,45,195,118,133,201,77,80],"38":[17,45,195,118,133,201,77,80],"48":[17,45,195,118,133,201,77,80],"74":[17,45,195,118,133,201,77,80],"78":[17,45,195,118,133,201,77,80],"79":[17,45,195,118,133,201,77,80],"102":[17,45,195,118,133,201,77,80],"106":[17,45,195,118,133,201,77,80],"113":[17,45,195,118,133,201,77,80],"119":[17,45,195,118,133,201,77,80],"150":[17,45,195,118,133,201,77,80],"156":[17,45,195,118,133,201,77,80],"190":[17,45,195,118,133,201,77,80],"199":[17,45,195,118,133,201,77,80],"237":[17,45,195,118,133,201,77,80],"245":[17,45,195,118,133,201,77,80],"253":[17,45,195,118,133,201,77,80],"261":[17,45,195,118,133,201,77,80],"285":[17,45,195,118,133,201,77,80],"309":[17,45,195,118,133,201,77,80],"324":[17,45,195,118,133,201,77,80],"340":[17,45,195,118,133,201,77,80],"360":[17,45,195,118,133,201,77,80],"371":[17,45,195,118,133,201,77,80],"389":[17,45,195,118,133,201,77,80],"398":[17,45,195,118,133,201,77,80],"420":[17,45,195,118,133,201,77,80]},"packages/nodes-base/nodes/Notion/v3/methods/listSearch.ts":{"10":[17,45,195,118,133,201,77,80],"15":[17,45,195,118,133,201,77,80],"21":[17,45,195,118,133,201,77,80],"26":[17,45,195,118,133,201,77,80],"32":[17,45,195,118,133,201,77,80],"38":[17,45,195,118,133,201,77,80],"47":[17,45,195,118,133,201,77,80],"64":[17,45,195,118,133,201,77,80],"68":[17,45,195,118,133,201,77,80],"88":[17,45,195,118,133,201,77,80]},"packages/nodes-base/nodes/Notion/v3/methods/loadOptions.ts":{"23":[17,45,195,118,133,201,77,80],"38":[17,45,195,118,133,201,77,80],"57":[17,45,195,118,133,201,77,80],"60":[17,45,195,118,133,201,77,80],"61":[17,45,195,118,133,201,77,80],"71":[17,45,195,118,133,201,77,80],"78":[17,45,195,118,133,201,77,80],"85":[17,45,195,118,133,201,77,80],"89":[17,45,195,118,133,201,77,80],"110":[17,45,195,118,133,201,77,80],"124":[17,45,195,118,133,201,77,80],"143":[17,45,195,118,133,201,77,80],"156":[17,45,195,118,133,201,77,80],"179":[17,45,195,118,133,201,77,80]},"packages/nodes-base/nodes/Notion/v3/transport/index.ts":{"17":[17,45,195,118,133,201,77,80],"21":[17,45,195,118,133,201,77,80],"54":[17,45,195,118,133,201,77,80],"88":[17,45,195,118,133,201,77,80]},"localhost-33943/assets/index-BoK1c_f3.js":{"3":[17,153,130]},"localhost-33943/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[17,153,130],"9":[17,153,130],"10":[17,153,130],"19":[17,153,130],"23":[17,153,130],"29":[17,153,130],"33":[17,153,130],"34":[17,153,130]},"localhost-33943/assets/verified-Pt0guxqN.js":{"8":[17,153]},"packages/@n8n/utils/src/string/truncate.ts":{"1":"b:CAC+sgw4ABAAAEIJHAAQEjASAJgEACAAAQgHAAA=","11":"b:BgA8sAwAAAAAAEAAAgAAEAABAZgAEAAAACICAAA=","29":[86,124,28,29,31,159,34,35]},"packages/frontend/@n8n/design-system/src/components/N8nCard/Card.vue":{"9":"b:CACTAwA4ANgAAEIpHAAkEjAAAAgEQAAABAgAAAA=","15":"b:CACSAwA4ANAAAEIpHAAkEjAAAAgEQAAAAAgAAAA=","20":"b:CACTAwA4ANgAAEIpHAAkEjAAAAgEQAAABAgAAAA=","26":"b:CACTAwA4ANgAAEIpHAAkEjAAAAgEQAAABAgAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nEmptyState/EmptyState.vue":{"35":"b:gADiAwA4AFQAAEIIAAAsEjAAACAAwACACQAAAAA=","55":"b:gADCAwA4AFQAAEIIAAAsEjAAACAAwACACQAAAAA=","61":[86,124],"64":"b:gADiAwA4AFQAAEIIAAAIEjAAACAAwACACQAAAAA=","71":[86,124],"73":"b:gADCAwA4AFQAAEIIAAAsEjAAAAAAwACACQAAAAA=","81":[86,17,124,58,192,60,114,62],"92":[86,124],"94":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/dots-horizontal--outline-12.svg":{"9":"b:AACiAwA4AFQAAEIpHAAkEjAAACAEwACABAgAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIconPicker/types.ts":{"17":"b:AACichw4ABAEQEI4HABA2jBAAaADwAAACAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nRecycleScroller/RecycleScroller.vue":{"8":[86,17,23,91,124,44,45,60,132,133],"24":[86,17,23,91,124,44,45,60,132,133],"25":[86,17,23,91,124,44,45,60,132,133],"44":[86,17,23,91,124,44,45,60,132,133],"46":[86,17,23,91,124,44,45,60,132,133],"56":[86,17,23,91,124,44,45,60,132,133],"57":[86,17,23,91,124,44,45,60,132,133],"68":[86,17,23,91,124,44,45,60,132,133],"72":[86,17,23,91,124,44,45,60,132,133],"73":[86,17,23,91,124,44,45,60,132,133],"75":[86,17,23,91,124,44,45,60,132,133],"77":[86,17,23,91,124,44,45,60,132,133],"90":[86,17,23,91,124,44,45,60,132,133],"100":[86,17,23,91,124,44,45,60,132,133],"104":[86,17,23,91,124,44,45,60,132,133],"114":[86,17,23,91,124,44,45,60,132,133],"118":[86,17,23,91,124,44,45,60,132,133],"131":[86,17,23,91,124,44,45,60,132,133],"141":[86,17,23,91,124,44,45,60,132,133],"147":[86,17,23,91,124,44,45,60,132,133],"148":[86,17,23,91,124,44,45,60,132,133],"167":[86,17,23,91,124,44,45,60,132,133],"170":[86,17,23,91,124,44,45,60,132,133],"178":[86],"186":[86],"195":[86],"205":[86,17,23,91,124,44,45,60,132,133],"212":[86,17,23,91,124,44,45,60,132,133],"214":[86,17,23,91,124,44,45,60,132,133]},"packages/frontend/@n8n/design-system/src/components/N8nTimeAgo/TimeAgo.vue":{"22":"b:AACCAwA4ABAAAEYpHAAAEjAAACAEQAAAAAgAAAA=","32":[86],"33":[86],"38":"b:AACCAwA4ABAAAEYpHAAAEjAAACAEQAAAAAgAAAA=","50":"b:AACCAwA4ABAAAEYpHAAAEjAAACAEQAAAAAgAAAA=","51":"b:AACCAwA4ABAAAEYpHAAAEjAAACAEQAAAAAgAAAA="},"packages/frontend/@n8n/design-system/src/directives/n8n-truncate.ts":{"19":"b:AACCAgA4ABAAAEIJHAAAEjAAAAAEAAAAAQgAAAA="},"packages/frontend/editor-ui/src/app/components/TimeAgo.vue":{"16":"b:AACCAwA4ABAAAEYpHAAAEjAAACAEQAAAAAgAAAA=","17":"b:AACCAwA4ABAAAEYpHAAAEjAAACAEQAAAAAgAAAA="},"packages/frontend/editor-ui/src/app/components/forms/ResourceFiltersDropdown.vue":{"22":"b:AACCAAA4ABAAAAIpHAAAEjAAAAAEQAAAAQgAAAA=","51":[81],"63":"b:AACCAAA4ABAAAAIpHAAAEjAAAAAEQAAAAQgAAAA=","66":"b:AACCAAA4ABAAAAIpHAAAEjAAAAAEQAAAAQgAAAA=","89":"b:AACCAAA4ABAAAAIpHAAAEjAAAAAEQAAAAQgAAAA=","91":[81],"115":"b:AACCAAA4ABAAAAIpHAAAEjAAAAAEQAAAAQgAAAA=","119":[81],"122":"b:AACCAAA4ABAAAAIpHAAAEjAAAAAEQAAAAQgAAAA=","126":"b:AACCAAA4ABAAAAIpHAAAEjAAAAAEQAAAAQgAAAA=","130":"b:AACCAAA4ABAAAAIpHAAAEjAAAAAEQAAAAQgAAAA=","142":"b:AACCAAA4ABAAAAIpHAAAEjAAAAAEQAAAAQgAAAA=","148":[81],"158":[81],"164":[81],"183":[81]},"packages/frontend/editor-ui/src/app/components/layouts/ResourcesListEmptyState.vue":{"61":[192],"84":"b:gACCAwA4ABAAAAIIAAAAAjAAAAAAwAAACQAAAAA=","99":[17,192,60]},"packages/frontend/editor-ui/src/app/components/layouts/ResourcesListLayout.vue":{"150":"b:gACCAwA4ABAAgAIpHAAAEjAAAAAEwAAACQgAAAA=","151":[124,81],"154":"b:gACCAwA4ABAAAAIpHAAAEjAAAAAEwAAACQgAAAA=","167":"b:gACCAwA4ABAAgAIpHAAAEjAAAAAEwAAACQgAAAA=","177":"b:gACCAwA4ABAAAAIpHAAAEjAAAAAEwAAACQgAAAA=","181":"b:gACCAwA4ABAAAAIpHAAAEjAAAAAEQAAAAQgAAAA=","185":[17,23,91,124,44,45,192,60,132,133],"210":[23,124,44,192,132,133],"254":"b:gACCAwA4ABAAgAIpHAAAEjAAAAAEwAAACQgAAAA=","255":[124,81],"264":"b:gACCAwA4ABAAgAIpHAAAEjAAAAAEwAAACQgAAAA=","265":[124],"271":"b:gACCAwA4ABAAgAIpHAAAEjAAAAAEwAAACQgAAAA=","272":[124,24,93,43,174,44,99,81],"278":"b:gACCAwA4ABAAgAIpHAAAEjAAAAAEwAAACQgAAAA=","279":[124],"285":"b:gACCAwA4ABAAgAIpHAAAEjAAAAAEwAAACQgAAAA=","286":[124,43,192,81],"290":"b:gACCAwA4ABAAgAIpHAAAEjAAAAAEwAAACQgAAAA=","291":[7,17,91,124,132,133],"297":"b:gACCAwA4ABAAgAIpHAAAEjAAAAAEwAAACQgAAAA=","298":[124],"304":"b:gACCAwA4ABAAgAIpHAAAEjAAAAAEwAAACQgAAAA=","311":"b:gACCAwA4ABAAgAIpHAAAEjAAAAAEwAAACQgAAAA=","323":[124,24,25,162,175,45,195,203,98,99,79,81],"328":[17,23,124,43,174,192,60,132,133,81],"336":[124],"342":"b:gACCAwA4ABAAAAIpHAAAEjAAAAAEwAAACQgAAAA=","356":"b:AACCAAA4ABAAAAIpHAAAEjAAAAAEQAAAAQgAAAA=","361":[81],"366":"b:gACCAwA4ABAAAAIpHAAAEjAAAAAEwAAACQgAAAA=","370":[124,25],"378":[23,124],"389":[7,17,91,124,24,25,93,43,174,44,132,133,99],"399":"b:gAACAwAYAAAAAAIoCAAAEDAAAAAAQAAAAAAAAAA=","407":[17,91,124,24,44,132,133,99],"414":"b:gAACAwAYAAAAAAIoCAAAEDAAAAAAQAAAAAAAAAA=","429":[124,192],"433":[124,81],"437":[7,17,91,124,24,25,93,43,174,44,132,133,99],"438":[7,17,91,124,24,25,93,43,174,44,132,133,99],"451":[17,23,91,124,44,45,60,132,133],"458":[124,192],"465":[23,124],"471":[124,81],"475":[124,43,192,81],"480":[124],"481":[124],"489":[23,124,25],"538":"b:gACCAwA4ABAAgAIpHAAAEjAAAAAEwAAACQgAAAA=","588":"b:AAAAAwA4AAAAgAIhHAAAEgAAAAAEwAAACAgAAAA=","604":"b:gACCAwA4ABAAgAIpHAAAEjAAAAAEwAAACQgAAAA=","622":"b:AACCAwA4ABAAAAIpHAAAEjAAAAAEQAAAAQgAAAA=","637":"b:AACCAwA4ABAAAAIpHAAAEjAAAAAEQAAAAQgAAAA=","647":[23],"648":"b:AACCAwA4ABAAAAIpHAAAEjAAAAAEQAAAAQgAAAA=","650":"b:AACCAwA4ABAAAAIpHAAAEjAAAAAEQAAAAQgAAAA=","668":[81],"686":"b:AACCAAA4ABAAAAIpHAAAEjAAAAAEQAAAAQgAAAA=","692":"b:AACCAAA4ABAAAAIpHAAAEjAAAAAEQAAAAQgAAAA=","719":[17,23,91,124,44,45,60,132,133],"730":"b:AAAAAwA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","760":[192],"764":[192],"775":[192,81]},"packages/frontend/editor-ui/src/app/composables/useLatestFetch.ts":{"4":"b:gACjAwA4AJgAgAIrHAAAAjAAgAAEwAAADQgAAAA=","6":"b:AAABAwA4AIgAAAIhHAAAAgAAAAAEwAAADAgAAAA="},"packages/frontend/editor-ui/src/app/composables/useN8nLocalStorage.ts":{"26":"b:gACCAwA4ABAAgAIpHAAAEjAAAAAEwAAACQgAAAA=","29":"b:AAAAAwA4AAAAgAIhHAAAEgAAAAAEwAAACAgAAAA=","33":[124,25],"58":"b:AAAAAwA4AAAAgAIhHAAAEgAAAAAEwAAACAgAAAA="},"packages/frontend/editor-ui/src/app/composables/useResourcesListI18n.ts":{"8":"b:gACCAwA4ABAAgAIpHAAAEjAAAAAEwAAACQgAAAA=","15":"b:AACCAwA4ABAAAAIpHAAAEjAAAAAEQAAAAQgAAAA="},"packages/frontend/editor-ui/src/app/layouts/DefaultLayout.vue":{"8":"b:jgCjAwA4AJgAgAYrHAAAAjAAgAAEwAAADQgAAAA=","10":"b:jgCjAwA4AJgAgAYrHAAAAjAAgAAEwAAADQgAAAA="},"packages/frontend/editor-ui/src/app/utils/modules/tabUtils.ts":{"11":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","34":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","38":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA="},"packages/frontend/editor-ui/src/app/utils/rbac/middleware/custom.ts":{"4":"b:jgCr8x44ANwAgEI7HAAk0jAAgIAPwACADQgAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useInstanceAiCredentialHelp.ts":{"21":[7,86,17,23,91,124,34,44,45,60,132,133],"38":[7,86,17,23,91,124,34,45,60,132,133],"42":[86,124],"50":[86,124]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectCreateResource.vue":{"14":"b:gACCAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","23":"b:gACCAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","34":[43,174],"35":"b:gACCAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA="},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectHeader.vue":{"46":"b:AACiAgA4ABAAAAIgCAAAAgAAAAAAwAAACAAAAAA=","48":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","50":"b:AACiAgA4ABAAAAIgCAAAAgAAAAAAwAAACAAAAAA=","70":"b:AACiAgA4ABAAAAIgCAAAAgAAAAAAwAAACAAAAAA=","82":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","84":[91,45,99],"86":"b:gACiAwA4ABAAgAIoCAAAAjAAAAAAwAAACAAAAAA=","90":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","107":"b:gACiAwA4ABAAgAIoCAAAAjAAAAAAwAAACAAAAAA=","110":[192],"113":[192],"117":[7,17,91,24,25,174,175,44,45,60,132,133,99],"121":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","132":"b:gACCAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","139":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","149":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","152":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","157":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","170":"b:AAAAAwA4AAAAgAIhHAAAAgAAAAAEwAAACAgAAAA=","180":[7,17,23,91,44,45,60,132,133],"190":[24,25],"200":[192],"218":"b:gACCAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","225":"b:gACCAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","241":"b:gACCAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","314":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","320":[7,17,23,91,195,132,133,81],"330":[195,81],"341":[7,17,23,91,195,132,133,81],"354":[195,81],"364":[7,17,23,91,132,133],"376":[43,174],"379":[24,25],"385":[192],"394":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","414":"b:AACiAgA4ABAAAAIgCAAAAgAAAAAAwAAACAAAAAA=","422":"b:AACiAgA4ABAAAAIgCAAAAgAAAAAAwAAACAAAAAA=","432":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","446":[175],"457":[7,17,23,91,24,25,43,174,192,195,132,133,81],"474":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","477":"b:gAACAwAwABAAgAIJHAAAAjAAAAAEwAAAAQgAAAA=","482":[175],"509":"b:gACCAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","517":[43,174],"518":"b:gACCAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","524":[7,17,23,91,24,25,192,195,132,133,81]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectTabs.vue":{"23":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","37":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","39":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","45":"b:gACiAwA4ABAAgAIoCAAAAjAAAAAAwAAACAAAAAA=","47":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","90":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","103":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","124":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","144":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","145":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","161":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA="},"packages/frontend/editor-ui/src/features/credentials/components/CredentialCard.vue":{"71":[17,23,91,124,44,45,60,132,133],"72":[17,23,91,124,44,45,60,132,133],"75":[17,23,91,124,44,45,60,132,133],"77":[17,23,91,124,44,45,60,132,133],"85":[17,23,91,124,44,45,60,132,133],"121":[17,23,91,124,44,45,60,132,133],"130":[17,23,91,124,44,45,60,132,133],"132":[91],"159":[44],"223":[44],"232":[17,23,91,124,44,45,60,132,133],"237":[17,23,91,124,44,45,60,132,133],"240":[17,23,91,124,44,45,60,132,133],"244":[91],"253":[17,23,91,124,44,45,60,132,133],"285":[17,23,91,124,44,45,60,132,133]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialsSelectModal.vue":{"16":[7,86,17,23,91,124,45,60,132,133],"32":[7,86,17,23,91,124,45,60,132,133],"37":[7,86,17,23,91,124,45,60,132,133],"44":[7,86,17,23,91,124,45,60,132,133],"52":[7,86,17,23,91,124,45,60,132,133],"53":[7,86,17,23,91,124,45,60,132,133],"58":[7,86,17,23,91,124,45,60,132,133],"61":[7,86,17,23,91,124,45,60,132,133],"64":[7,86,17,23,91,124,45,60,132,133],"68":[7,86,17,23,91,124,45,60,132,133],"72":[7,86,17,23,91,124,45,60,132,133],"100":[7,86,17,23,91,124,45,60,132,133],"113":[7,86,17,23,91,124,45,60,132,133],"118":[7,86,17,23,91,124,45,60,132,133],"134":[7,86,17,23,91,124,45,60,132,133],"136":[7,86,17,23,91,124,45,60,132,133],"138":[7,86,17,23,91,124,45,60,132,133],"148":[7,86,17,23,91,124,45,60,132,133]},"packages/frontend/editor-ui/src/features/credentials/views/CredentialsView.vue":{"65":[7,17,91,124,132,133],"69":[124],"82":[17,23,91,124,44,45,60,132,133],"92":[17,23,91,124,44,45,60,132,133],"95":[7,17,23,91,124,44,45,60,132,133],"96":[17,23,91,124,44,45,60,132,133],"116":[124],"118":[124],"122":[7,17,23,91,124,44,45,60,132,133],"124":[7,17,23,91,124,44,45,60,132,133],"130":[124],"134":[124],"140":[17,91,124,60],"144":[17,23,91,124,45,60,132,133],"152":[17,124,60],"161":[7,17,23,91,124,44,45,60,132,133],"172":[17,23,91,124,44,45,60,132,133],"195":[7,17,23,91,124,44,45,60,132,133],"206":[7,17,23,91,124,44,45,60,132,133],"231":[7,17,23,91,124,44,45,60,132,133],"257":[23,91,124,44,45,132,133],"261":[7,17,23,91,124,44,45,60,132,133],"263":[17,23,91,124,45,60,132,133],"269":[124],"271":[124],"276":[7,17,23,91,124,44,45,60,132,133],"278":[7,17,23,91,124,44,45,60,132,133],"279":[7,17,23,91,124,45,60,132,133],"288":[7,17,23,91,124,44,45,60,132,133],"290":[124],"298":[7,17,23,91,124,44,45,60,132,133],"317":[7,17,23,91,124,44,45,60,132,133],"327":[17,23,91,124,44,45,60,132,133]},"packages/frontend/editor-ui/src/features/integrations/promotions.ee/components/PromotionBanners.vue":{"18":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","25":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","26":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","38":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","46":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","50":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","56":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","91":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","97":[24,25,162,175,45,195,203,98,99,79,81],"136":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA="},"packages/frontend/editor-ui/src/features/integrations/promotions.ee/composables/usePromotionChangeCount.ts":{"8":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","19":"b:gACiAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA="},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/ActionItem.vue":{"19":"b:gACCAAAAAABkaCEAAxAAAORgCAGQIRAACEYOAAA=","35":"b:gACCAAAAAABkaCEAAxAAAORgCAGQIRAACEYOAAA=","42":"b:gACCAAAAAABkaCEAAxAAAORgCAGQIRAACEYOAAA=","99":"b:gACCAAAAAABkaCEAAxAAAORgCAGQIRAACEYOAAA=","111":"b:gACCAAAAAABkaCEAAxAAAORgCAGQIRAACEYOAAA=","117":"b:gACCAAAAAABkaCEAAxAAAORgCAGQIRAACEYOAAA="},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/LabelItem.vue":{"11":"b:gACCAAAAAAAgaAEAAgAAACAAAAEAAQAACEAKAAA="},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/Modes/ActionsMode.vue":{"44":"b:gACCAAAAAABkaCEAAxAAAORgCAGQIRAACEYOAAA=","67":"b:gACCAAAAAAAAYCEAAgAAACRgCAEQAQAACAQKAAA=","70":"b:gACCAAAAAABkaCEAAxAAAORgCAGQIRAACEYOAAA=","73":"b:gACCAAAAAABkaAEAAxAAAORgCAGAIBAACEYOAAA=","80":[85,152,23,164,168,209,77,78,141,211],"90":"b:gACCAAAAAAAAYCEAAgAAACRgCAEQAQAACAQKAAA=","96":"b:gACCAAAAAABkaCEAAxAAAORgCAGQIRAACEYOAAA=","97":"b:gACCAAAAAABkaCEAAxAAAORgCAGQIRAACEYOAAA=","102":"b:gACCAAAAAABkaCEAAxAAAORgCAGQIRAACEYOAAA=","104":"b:gACCAAAAAABkaCEAAxAAAORgCAGQIRAACEYOAAA=","106":"b:gACCAAAAAABkaCEAAxAAAORgCAGQIRAACEYOAAA=","108":"b:gACCAAAAAABkaCEAAxAAAORgCAGQIRAACEYOAAA=","113":"b:gACCAAAAAABkaCEAAxAAAORgCAGQIRAACEYOAAA=","124":"b:gACCAAAAAABkaCEAAxAAAORgCAGQIRAACEYOAAA=","130":"b:gACCAAAAAAAAYCEAAgAAACRgCAEQAQAACAQKAAA=","139":"b:gACCAAAAAABkaCEAAxAAAORgCAGQIRAACEYOAAA=","142":"b:gACCAAAAAABkaCEAAxAAAORgCAGQIRAACEYOAAA=","149":"b:gACCAAAAAABkaCEAAxAAAORgCAGQIRAACEYOAAA=","151":"b:gACCAAAAAABkaCEAAxAAAORgCAGQIRAACEYOAAA=","173":"b:gACCAAAAAABkaCEAAxAAAORgCAGQIRAACEYOAAA=","188":"b:gACCAAAAAABkaCEAAxAAAORgCAEQIRAACEYKAAA=","200":"b:gACCAAAAAABkaCEAAxAAAORgCAEQIRAACEYKAAA=","223":"b:gACCAAAAAABkaCEAAxAAAORgCAGQIRAACEYOAAA=","226":"b:gACCAAAAAABkaCEAAxAAAORgCAGQIRAACEYOAAA=","234":"b:gACCAAAAAABkaCEAAxAAAORgCAGQIRAACEYOAAA=","269":"b:gACCAAAAAABkaCEAAxAAAORgCAGQIRAACEYOAAA=","273":"b:gACCAAAAAABkaCEAAxAAAORgCAGQIRAACEYOAAA=","274":"b:gACCAAAAAABkaCEAAxAAAORgCAGQIRAACEYOAAA=","296":"b:gACCAAAAAAAAYCEAAgAAACRgCAEQAQAACAQKAAA=","309":[164,209,77,78,141],"315":[164,209,77,78,141],"336":"b:gACCAAAAAABkaCEAAxAAAORgCAGQIRAACEYOAAA=","351":[164,77,78,141]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/OrderSwitcher.vue":{"11":"b:gACCAAAAAABkaCEAAxAAAORgCAGQIRAACEYOAAA="},"packages/frontend/editor-ui/src/features/workflows/readyToRun/components/ReadyToRunButton.vue":{"13":"b:gACCAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","25":"b:gACCAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","31":"b:gACCAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA=","53":"b:gACCAwA4ABAAgAIpHAAAAjAAAAAEwAAACQgAAAA="},"packages/modules/insights/frontend/src/components/InsightsSummary.vue":{"31":"b:gAACAwAwAAAAAAIJFAAAAjAAAAAEgAAAAQgAAAA=","44":"b:gAACAwAwAAAAAAIJFAAAAjAAAAAEgAAAAQgAAAA=","52":"b:gAACAwAwAAAAAAIJFAAAAjAAAAAEgAAAAQgAAAA=","54":"b:gAACAwAwAAAAAAIJFAAAAjAAAAAEgAAAAQgAAAA=","57":"b:gAACAwAwAAAAAAIJFAAAAjAAAAAEgAAAAQgAAAA=","58":"b:gAACAwAwAAAAAAIJFAAAAjAAAAAEgAAAAQgAAAA=","116":"b:gAACAwAwAAAAAAIJFAAAAjAAAAAEgAAAAQgAAAA=","131":"b:gAACAwAwAAAAAAIJFAAAAjAAAAAEgAAAAQgAAAA="},"packages/modules/insights/frontend/src/insights.api.ts":{"17":"b:gAACAwAwAIgAAAIJFAAAAjAAgAAEgAAAAQgAAAA=","39":"b:gAACAwAwAIgAAAIJFAAAAjAAgAAEgAAAAQgAAAA="},"packages/modules/insights/frontend/src/insights.constants.ts":{"21":"b:gAACAwAwAIgAAAIJFAAAAjAAgAAEgAAAAQgAAAA=","22":"b:gAACAwAwAIgAAAIJFAAAAjAAgAAEgAAAAQgAAAA=","23":"b:gAACAwAwAIgAAAIJFAAAAjAAgAAEgAAAAQgAAAA=","24":"b:gAACAwAwAIgAAAIJFAAAAjAAgAAEgAAAAQgAAAA=","25":"b:gAACAwAwAIgAAAIJFAAAAjAAgAAEgAAAAQgAAAA="},"packages/modules/insights/frontend/src/insights.store.ts":{"13":"b:gACDAwA4AJgAgAIrHAAAAjAAgAAEwAAADQgAAAA=","18":"b:gAADAwAwAIgAAAILHAAAAjAAgAAEgAAABQgAAAA=","22":"b:gAACAwAwAIgAAAIJFAAAAjAAgAAEgAAAAQgAAAA=","26":"b:gAADAwAwAIgAAAILHAAAAjAAgAAEgAAABQgAAAA=","31":"b:gAACAwAwAIgAAAIJFAAAAjAAgAAEgAAAAQgAAAA="},"packages/modules/insights/frontend/src/insights.utils.ts":{"18":"b:gAACAwAwAIgAAAIJFAAAAjAAgAAEgAAAAQgAAAA=","20":"b:gAACAwAwAIgAAAIJFAAAAjAAgAAEgAAAAQgAAAA=","21":"b:gAACAwAwAIgAAAIJFAAAAjAAgAAEgAAAAQgAAAA=","24":"b:gAACAwAwAIgAAAIJFAAAAjAAgAAEgAAAAQgAAAA=","25":"b:gAACAwAwAIgAAAIJFAAAAjAAgAAEgAAAAQgAAAA=","53":"b:gAACAwAwAIgAAAIJFAAAAjAAgAAEgAAAAQgAAAA=","55":"b:gAACAwAwAIgAAAIJFAAAAjAAgAAEgAAAAQgAAAA=","80":"b:gAACAwAwAAAAAAIJFAAAAjAAAAAEgAAAAQgAAAA=","97":"b:gAACAwAwAAAAAAIJFAAAAjAAAAAEgAAAAQgAAAA=","118":"b:gAACAwAwAAAAAAIJFAAAAjAAAAAEgAAAAQgAAAA="},"packages/cli/src/modules/instance-registry/checks/check.service.ts":{"44":"b:AACgAgCgAIDgAAAAAAAgkKALAQIBYgEAA4YAAAA=","54":"b:AACgAgCgAIDgAAAAAAAgkKALAQIBYgEAA4YAAAA=","58":"b:AACgAgCgAIDgAAAAAAAgkKALAQIBYgEAA4YAAAA=","73":"b:AACgAgCgAIDgAAAAAAAgkKALAQIBYgEAA4YAAAA=","84":"b:AACgAgCgAIDgAAAAAAAgkKALAQIBYgEAA4YAAAA=","94":"b:AACgAgCgAIDgAAAAAAAgkKALAQIBYgEAA4YAAAA=","99":"b:AACgAgCgAIDgAAAAAAAgkKALAQIBYgEAA4YAAAA=","106":"b:AACgAgCgAIDgAAAAAAAgkKALAQIBYgEAA4YAAAA=","138":"b:AACgAgCgAIDgAAAAAAAgkKALAQIBYgEAA4YAAAA=","156":"b:AACgAgCgAIDgAAAAAAAgkKALAQIBYgEAA4YAAAA=","170":"b:AACgAgCgAIDgAAAAAAAgkKALAQIBYgEAA4YAAAA=","181":"b:AACgAgCgAIDgAAAAAAAgkKALAQIBYgEAA4YAAAA=","187":"b:AACgAgCgAIDgAAAAAAAgkKALAQIBYgEAA4YAAAA=","196":"b:AACgAgCgAIDgAAAAAAAgkKALAQIBYgEAA4YAAAA=","219":"b:AACgAgCgAIDgAAAAAAAgkKALAQIBYgEAA4YAAAA=","243":"b:AACgAgCgAIDgAAAAAAAgkKALAQIBYgEAA4YAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/file--outline-16.svg":{"9":[86,153,124,173,45]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/hash--outline-16.svg":{"9":"b:IAAAAQAAAAAAIEAAAwAQEAASAAIAIAAAgKAPAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/respond-to-webhook.svg":{"11":[152,153,173,209,97]},"packages/frontend/editor-ui/src/features/ndv/panel/components/TriggerPanel.vue":{"40":"b:AACAAAAAAAAAQAAAAgAAAAQBCAMQIAAAACAKAAA=","71":"b:AACAAAAAAAAAQAAAAgAAAAQBCAMQIAAAACAKAAA=","75":"b:AACAAAAAAAAAQAAAAgAAAAQBCAMQIAAAACAKAAA=","83":[147,152,153,130,173,136,205,209,97],"91":[147,152,153,130,173,136,205,209,97],"110":"b:AACAAAAAAAAAQAAAAgAAAAQBCAMQIAAAACAKAAA=","116":[152,153,173,205,209,97],"124":[147,130],"132":[147,152,153,130,173,136,205,209,97],"136":"b:AACAAAAAAAAAQAAAAgAAAAQBCAMQIAAAACAKAAA=","154":"b:AACAAAAAAAAAQAAAAgAAAAQBCAMQIAAAACAKAAA=","162":[147,152,153,130,173,136,205,209,97],"166":[147,130,173,205],"170":[147,152,153,130,173,136,205,209,97],"188":[147,152,153,130,173,205,209,97],"190":[147,152,153,130,173,205,209,97],"196":[147,152,153,130,173,205,209,97],"198":[147,130],"204":[147,130],"217":[147,152,153,130,173,205,209,97],"235":[147,152,153,130,173,205,209,97],"245":[147,152,153,130,173,205,209,97],"285":[147,152,153,130,173,205,209,97],"375":[136],"384":"b:AACAAAAAAAAAQAAAAgAAAAQBCAMQIAAAACAKAAA=","415":[173,136],"436":[147,130],"440":[147,130],"471":[152,153,130,173,205,209,97],"514":[152,153,130,173,205,209,97],"520":[152,153,130,173,205,209,97]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/AssignmentCollection/Assignment.vue":{"35":"b:IAAAAAiAAAAAMEAAAgAQEAADAAIAMAQhgKAEAAA=","39":"b:IAAAAAiAAAAAMEAAAgAQEAADAAIAMAQhgKAEAAA=","40":[86,124],"57":"b:IAAAAAiAAAAAMEAAAgAQEAADAAIAMAQhgKAEAAA=","81":"b:IAAAAAiAAAAAMEAAAgAQEAADAAIAMAQhgKAEAAA=","90":"b:IAAAAAiAAAAAMEAAAgAQEAADAAIAMAQhgKAEAAA=","104":"b:IAAAAAiAAAAAMEAAAgAQEAADAAIAMAQhgKAEAAA=","106":"b:IAAAAAiAAAAAMEAAAgAQEAADAAIAMAQhgKAEAAA=","115":"b:IAAAAAiAAAAAMEAAAgAQEAADAAIAMAQhgKAEAAA=","117":"b:IAAAAAAAAAAAMEAAAgAQEAADAAAAEAQgAIAAAAA=","119":[86,153,124,173,116],"123":[86,153,124,173],"131":[86,153,124,173,116,76,207,77,97],"135":[86,124],"139":[86,153,124,173,199,116,76,207,77],"143":[86,124,116],"156":"b:IAAAAAiAAAAAMEAAAgAQEAADAAIAMAQhgKAEAAA=","214":"b:IAAAAAiAAAAAMEAAAgAQEAADAAIAMAQhgKAEAAA=","230":"b:IAAAAAiAAAAAMEAAAgAQEAADAAIAMAQhgKAEAAA=","232":[86,124],"234":"b:IAAAAAiAAAAAMEAAAgAQEAADAAIAMAQhgKAEAAA=","244":"b:IAAAAAiAAAAAMEAAAgAQEAADAAIAMAQhgKAEAAA="},"packages/frontend/editor-ui/src/features/ndv/parameters/components/AssignmentCollection/TypeSelect.vue":{"17":"b:IAAAAAiAAAAAMEAAAgAQEAADAAIAMAQhgKAEAAA=","30":"b:IAAAAAiAAAAAMEAAAgAQEAADAAIAMAQhgKAEAAA=","32":"b:IAAAAAiAAAAAMEAAAgAQEAADAAIAMAQhgKAEAAA=","33":"b:IAAAAAiAAAAAMEAAAgAQEAADAAIAMAQhgKAEAAA=","43":[86,153,124,173],"45":"b:IAAAAAiAAAAAMEAAAgAQEAADAAIAMAQhgKAEAAA=","58":"b:IAAAAAiAAAAAEEAAAgAQEAADAAIAMAQhgKAEAAA=","60":"b:IAAAAAiAAAAAEEAAAgAQEAADAAIAMAQhgKAEAAA="},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ImportCurlParameter.vue":{"11":"b:AAGAAAACAABABUAIAgAAFAAIAAYAIAAKAAAAAAA=","14":[86,124],"16":"b:AAGAAAACAABABUAIAgAAFAAIAAYAIAAKAAAAAAA="},"packages/@n8n/agents/src/index.ts":{"119":[1,2,83,28,29,126,31,159,160,34,35,36],"121":[1,2,83,28,29,126,31,159,160,34,35,36],"167":[1,2,83,28,29,126,31,159,160,34,35,36],"196":[1,2,83,28,29,126,31,159,160,34,35,36],"197":[1,2,83,28,29,126,31,159,160,34,35,36],"198":[1,2,83,28,29,126,31,159,160,34,35,36],"200":[1,2,83,28,29,126,31,159,160,34,35,36],"260":[1,2,83,28,29,126,31,159,160,34,35,36],"364":[1,2,83,28,29,126,31,159,160,34,35,36],"368":[1,2,83,28,29,126,31,159,160,34,35,36],"370":[1,2,83,28,29,126,31,159,160,34,35,36],"430":[1,2,83,28,29,126,31,159,160,34,35,36],"477":[1,2,83,28,29,126,31,159,160,34,35,36],"478":[1,2,83,28,29,126,31,159,160,34,35,36],"479":[1,2,83,28,29,126,31,159,160,34,35,36],"486":[1,2,83,28,29,126,31,159,160,34,35,36],"523":[1,2,83,28,29,126,31,159,160,34,35,36]},"packages/@n8n/agents/src/runtime/guardrails/guardrail-runner.ts":{"19":[83,28,29,31,159,34,35],"25":[83,28,29,31,159,34,35],"33":[83,28,29,31,159,34,35],"37":[83,28,29,31,159,34,35],"46":[83,28,29,31,159,34,35],"54":[83,28,29,31,159,34,35],"60":[83,28,29,31,159,34,35],"68":[83,28,29,31,159,34,35]},"packages/@n8n/agents/src/runtime/loop/agent-runtime.ts":{"88":[83,28,29,126,31,159,160,34,35],"90":[83,28,29,126,31,159,160,34,35],"98":[83,28,29,126,31,159,160,34,35],"104":[83,28,29,126,31,159,160,34,35],"105":[83,28,29,126,31,159,160,34,35],"106":[83,28,29,126,31,159,160,34,35],"110":[83,28,29,126,31,159,160,34,35],"198":[83,28,29,126,31,159,160,34,35],"234":[83,28,29,126,31,159,160,34,35],"248":[83,28,29,126,31,159,160,34,35],"256":[83,28,29,126,31,159,160,34,35],"262":[83,28,29,126,31,159,160,34,35],"267":[83,28,29,126,31,159,160,34,35],"278":[83,28,29,126,31,159,160,34,35],"293":[83,28,29,126,31,159,160,34,35],"322":[83,28,29,126,31,159,160,34,35],"330":[83,28,29,126,31,159,160,34,35],"345":[83,28,29,126,31,159,160,34,35],"367":[83,28,29,126,31,159,160,34,35],"433":[83,28,29,126,31,159,160,34,35],"483":[83,28,29,126,31,159,160,34,35],"520":[83,28,29,126,31,159,160,34,35],"526":[83,28,29,126,31,159,160,34,35],"545":[83,28,29,126,31,159,160,34,35],"554":[83,28,29,126,31,159,160,34,35],"575":[83,28,29,126,31,159,160,34,35],"578":[83,28,29,126,31,159,160,34,35],"581":[83,28,29,126,31,159,160,34,35],"592":[83,28,29,126,31,159,160,34,35],"605":[83,28,29,126,31,159,160,34,35],"611":[83,28,29,126,31,159,160,34,35],"620":[83,28,29,126,31,159,160,34,35],"624":[83,28,29,126,31,159,160,34,35],"628":[83,28,29,126,31,159,160,34,35],"655":[83,28,29,126,31,159,160,34,35],"682":[83,28,29,126,31,159,160,34,35],"701":[83,28,29,126,31,159,160,34,35],"709":[83,28,29,126,31,159,160,34,35],"712":[83,28,29,126,31,159,160,34,35],"725":[83,28,29,126,31,159,160,34,35],"738":[83,28,29,126,31,159,160,34,35],"746":[83,28,29,126,31,159,160,34,35],"750":[83,28,29,126,31,159,160,34,35],"751":[83,28,29,126,31,159,160,34,35],"752":[83,28,29,126,31,159,160,34,35],"753":[83,28,29,126,31,159,160,34,35],"754":[83,28,29,126,31,159,160,34,35],"755":[83,28,29,126,31,159,160,34,35],"756":[83,28,29,126,31,159,160,34,35],"757":[83,28,29,126,31,159,160,34,35],"762":[83,28,29,126,31,159,160,34,35],"797":[83,28,29,126,31,159,160,34,35],"858":[83,28,29,126,31,159,160,34,35],"889":[83,28,29,126,31,159,160,34,35],"920":[83,28,29,126,31,159,160,34,35],"927":[83,28,29,126,31,159,160,34,35],"929":[83,28,29,126,31,159,160,34,35],"931":[83,28,29,126,31,159,160,34,35],"933":[83,28,29,126,31,159,160,34,35],"937":[83,28,29,126,31,159,160,34,35],"941":[83,28,29,126,31,159,160,34,35],"947":[83,28,29,126,31,159,160,34,35],"961":[83,28,29,126,31,159,160,34,35],"965":[83,28,29,126,31,159,160,34,35],"999":[83,28,29,126,31,159,160,34,35],"1053":[83,28,29,126,31,159,160,34,35],"1086":[83,28,29,126,31,159,160,34,35],"1091":[83,28,29,126,31,159,160,34,35],"1098":[83,28,29,126,31,159,160,34,35],"1105":[83,28,29,126,31,159,160,34,35],"1134":[83,28,29,126,31,159,160,34,35],"1145":[83,28,29,126,31,159,160,34,35],"1187":[83,28,29,126,31,159,160,34,35],"1204":[83,28,29,126,31,159,160,34,35],"1226":[83,28,29,126,31,159,160,34,35],"1246":[83,28,29,126,31,159,160,34,35],"1263":[83,28,29,126,31,159,160,34,35],"1265":[83,28,29,126,31,159,160,34,35],"1281":[83,28,29,126,31,159,160,34,35],"1287":[83,28,29,126,31,159,160,34,35],"1293":[83,28,29,126,31,159,160,34,35],"1294":[83,28,29,126,31,159,160,34,35],"1295":[83,28,29,126,31,159,160,34,35],"1296":[83,28,29,126,31,159,160,34,35],"1301":[83,28,29,126,31,159,160,34,35],"1321":[83,28,29,126,31,159,160,34,35],"1361":[83,28,29,126,31,159,160,34,35],"1382":[83,28,29,126,31,159,160,34,35],"1404":[83,28,29,126,31,159,160,34,35],"1405":[83,28,29,126,31,159,160,34,35],"1412":[83,28,29,126,31,159,160,34,35],"1417":[83,28,29,126,31,159,160,34,35],"1422":[83,28,29,126,31,159,160,34,35],"1433":[83,28,29,126,31,159,160,34,35],"1448":[83,28,29,126,31,159,160,34,35]},"packages/@n8n/agents/src/runtime/loop/checkpoint-data.ts":{"12":[126,34,35],"22":[126,34,35],"47":[126,34,35],"59":[126,34,35],"79":[126,34,35]},"packages/@n8n/agents/src/runtime/loop/execution-counter.ts":{"14":[83,28,29,31,159,34,35],"22":[83,28,29,31,159,34,35],"24":[83,28,29,31,159,34,35],"32":[83,28,29,31,159,34,35],"34":[83,28,29,31,159,34,35],"35":[83,28,29,31,159,34,35],"36":[83,28,29,31,159,34,35],"40":[83,28,29,31,159,34,35],"42":[83,28,29,31,159,34,35],"45":[83,28,29,31,159,34,35],"54":[83,28,29,31,159,34,35]},"packages/@n8n/agents/src/runtime/loop/hydrate-file-parts.ts":{"24":[83,28,29,31,159,34,35]},"packages/@n8n/agents/src/runtime/loop/run-output-sink.ts":{"15":[83,28,29,31,34,35]},"packages/@n8n/agents/src/runtime/loop/runtime-context.ts":{"45":[83,28,29,31,159,34,35],"47":[83,28,29,31,159,34,35],"50":[83,28,29,31,159,34,35],"73":[83,28,29,31,159,34,35],"78":[83,28,29,31,159,34,35],"83":[83,28,29,31,159,34,35],"108":[83,28,29,31,159,34,35],"120":[83,28,29,31,159,34,35],"129":[83,28,29,31,159,34,35],"153":[83,28,29,31,159,34,35],"167":[83,28,29,31,159,34,35],"168":[83,28,29,31,159,34,35],"179":[83,28,29,31,159,34,35],"207":[83,28,29,31,159,34,35],"212":[83,28,29,31,159,34,35],"234":[83,28,29,31,159,34,35],"252":[83,28,29,31,159,34,35],"267":[83,28,29,31,159,34,35],"283":[83,28,29,31,159,34,35],"297":[83,28,29,31,159,34,35],"305":[83,28,29,31,159,34,35],"332":[83,28,29,31,159,34,35],"343":[83,28,29,31,159,34,35],"345":[83,28,29,31,159,34,35],"363":[83,28,29,31,159,34,35],"365":[83,28,29,31,159,34,35],"375":[83,28,29,31,159,34,35],"395":[83,28,29,31,159,34,35]},"packages/@n8n/agents/src/runtime/loop/runtime-helpers.ts":{"15":[83,28,29,31,159,34,35],"23":[83,28,29,31,159,34,35],"34":[83,28,29,31,159,34,35],"65":[83,28,29,31,159,34,35],"67":[83,28,29,31,159,34,35],"71":[83,28,29,31,159,34,35],"79":[83,28,29,31,159,34,35],"81":[83,28,29,31,159,34,35],"85":[83,28,29,31,159,34,35],"90":[83,28,29,31,159,34,35],"109":[83,28,29,31,159,34,35],"148":[83,28,29,31,159,34,35],"169":[83,28,29,31,159,34,35],"171":[83,28,29,31,159,34,35],"172":[83,28,29,31,159,34,35],"180":[83,28,29,31,159,34,35],"183":[83,28,29,31,159,34,35],"184":[83,28,29,31,159,34,35],"185":[83,28,29,31,159,34,35],"190":[83,28,29,31,159,34,35]},"packages/@n8n/agents/src/runtime/loop/stream-sink.ts":{"58":[83,28,29,126,31,159,160,34,35],"61":[83,28,29,126,31,159,160,34,35],"64":[83,28,29,126,31,159,160,34,35],"73":[83,28,29,126,31,159,160,34,35],"91":[83,28,29,126,31,159,160,34,35],"97":[83,28,29,126,31,159,160,34,35],"109":[83,28,29,126,31,159,160,34,35],"125":[83,28,29,126,31,159,160,34,35],"139":[83,28,29,126,31,159,160,34,35],"155":[83,28,29,126,31,159,160,34,35],"159":[83,28,29,126,31,159,160,34,35],"161":[83,28,29,126,31,159,160,34,35],"173":[83,28,29,126,31,159,160,34,35],"185":[83,28,29,126,31,159,160,34,35],"205":[83,28,29,126,31,159,160,34,35],"226":[83,28,29,126,31,159,160,34,35],"235":[83,28,29,126,31,159,160,34,35],"251":[83,28,29,126,31,159,160,34,35],"266":[83,28,29,126,31,159,160,34,35],"267":[83,28,29,126,31,159,160,34,35],"268":[83,28,29,126,31,159,160,34,35],"283":[83,28,29,126,31,159,160,34,35],"329":[83,28,29,126,31,159,160,34,35],"347":[83,28,29,126,31,159,160,34,35],"372":[83,28,29,126,31,159,160,34,35],"381":[83,28,29,126,31,159,160,34,35],"383":[83,28,29,126,31,159,160,34,35],"408":[83,28,29,126,31,159,160,34,35],"434":[83,28,29,126,31,159,160,34,35],"461":[83,28,29,126,31,159,160,34,35]},"packages/@n8n/agents/src/runtime/mcp/mcp-tool-resolver.ts":{"30":[83,28,29,31,159,34,35],"31":[83,28,29,31,159,34,35],"34":[83,28,29,31,159,34,35],"38":[83,28,29,31,159,34,35],"49":[83,28,29,31,159,34,35],"52":[83,28,29,31,159,34,35],"74":[83,28,29,31,159,34,35],"75":[83,28,29,31,159,34,35],"94":[83,28,29,31,159,34,35],"98":[83,28,29,31,159,34,35],"99":[83,28,29,31,159,34,35],"102":[83,28,29,31,159,34,35],"119":[83,28,29,31,159,34,35],"124":[83,28,29,31,159,34,35],"140":[83,28,29,31,159,34,35],"151":[83,28,29,31,159,34,35]},"packages/@n8n/agents/src/runtime/memory/episodic-memory-capture.ts":{"83":[83,28,29,31,159,34,35],"105":[83,28,29,31,159,34,35],"118":[83,28,29,31,159,34,35],"192":[83,28,29,31,159,34,35],"204":[83,28,29,31,159,34,35],"223":[83,28,29,31,159,34,35],"264":[83,28,29,31,159,34,35],"278":[83,28,29,31,159,34,35],"281":[83,28,29,31,159,34,35],"290":[83,28,29,31,159,34,35],"307":[83,28,29,31,159,34,35],"311":[83,28,29,31,159,34,35],"319":[83,28,29,31,159,34,35],"326":[83,28,29,31,159,34,35],"344":[83,28,29,31,159,34,35],"356":[83,28,29,31,159,34,35],"361":[83,28,29,31,159,34,35],"364":[83,28,29,31,159,34,35],"400":[83,28,29,31,159,34,35],"401":[83,28,29,31,159,34,35],"409":[83,28,29,31,159,34,35],"420":[83,28,29,31,159,34,35],"424":[83,28,29,31,159,34,35],"449":[83,28,29,31,159,34,35],"463":[83,28,29,31,159,34,35],"479":[83,28,29,31,159,34,35],"486":[83,28,29,31,159,34,35],"487":[83,28,29,31,159,34,35],"493":[83,28,29,31,159,34,35],"501":[83,28,29,31,159,34,35],"506":[83,28,29,31,159,34,35],"515":[83,28,29,31,159,34,35],"522":[83,28,29,31,159,34,35],"526":[83,28,29,31,159,34,35]},"packages/@n8n/agents/src/runtime/memory/episodic-memory.ts":{"69":[28,29,31,159,34,35],"75":[28,29,31,159,34,35],"88":[28,29,31,159,34,35],"92":[28,29,31,159,34,35],"95":[28,29,31,159,34,35],"117":[28,29,31,159,34,35],"134":[28,29,31,159,34,35],"150":[28,29,31,159,34,35],"153":[28,29,31,159,34,35],"165":[28,29,31,159,34,35],"170":[28,29,31,159,34,35],"178":[28,29,31,159,34,35],"179":[28,29,31,159,34,35],"185":[28,29,31,159,34,35],"186":[28,29,31,159,34,35],"194":[28,29,31,159,34,35],"201":[28,29,31,159,34,35],"204":[28,29,31,159,34,35],"205":[28,29,31,159,34,35],"211":[28,29,31,159,34,35],"218":[28,29,31,159,34,35],"221":[28,29,31,159,34,35],"222":[28,29,31,159,34,35],"225":[28,29,31,159,34,35],"226":[28,29,31,159,34,35],"252":[28,29,31,159,34,35],"253":[28,29,31,159,34,35],"261":[28,29,31,159,34,35],"268":[28,29,31,159,34,35],"272":[28,29,31,159,34,35],"276":[28,29,31,159,34,35],"283":[28,29,31,159,34,35],"289":[28,29,31,159,34,35],"293":[28,29,31,159,34,35],"297":[28,29,31,159,34,35],"298":[28,29,31,159,34,35],"301":[28,29,31,159,34,35],"304":[28,29,31,159,34,35],"308":[28,29,31,159,34,35],"322":[28,29,31,159,34,35],"326":[28,29,31,159,34,35],"336":[28,29,31,159,34,35]},"packages/@n8n/agents/src/runtime/memory/memory-orchestrator.ts":{"65":[83,28,29,126,31,159,160,34,35],"73":[83,28,29,126,31,159,160,34,35],"88":[83,28,29,126,31,159,160,34,35],"92":[83,28,29,126,31,159,160,34,35],"95":[83,28,29,126,31,159,160,34,35],"103":[83,28,29,126,31,159,160,34,35],"115":[83,28,29,126,31,159,160,34,35],"123":[83,28,29,126,31,159,160,34,35],"173":[83,28,29,126,31,159,160,34,35],"181":[83,28,29,126,31,159,160,34,35],"195":[83,28,29,126,31,159,160,34,35],"196":[83,28,29,126,31,159,160,34,35],"216":[83,28,29,126,31,159,160,34,35],"218":[83,28,29,126,31,159,160,34,35],"219":[83,28,29,126,31,159,160,34,35],"220":[83,28,29,126,31,159,160,34,35],"229":[83,28,29,126,31,159,160,34,35],"254":[83,28,29,126,31,159,160,34,35],"266":[83,28,29,126,31,159,160,34,35],"267":[83,28,29,126,31,159,160,34,35],"272":[83,28,29,126,31,159,160,34,35],"273":[83,28,29,126,31,159,160,34,35],"280":[83,28,29,126,31,159,160,34,35],"306":[83,28,29,126,31,159,160,34,35],"329":[83,28,29,126,31,159,160,34,35],"376":[83,28,29,126,31,159,160,34,35],"389":[83,28,29,126,31,159,160,34,35],"431":[83,28,29,126,31,159,160,34,35],"485":[83,28,29,126,31,159,160,34,35],"504":[83,28,29,126,31,159,160,34,35],"513":[83,28,29,126,31,159,160,34,35],"523":[83,28,29,126,31,159,160,34,35],"600":[83,28,29,126,31,159,160,34,35],"610":[83,28,29,126,31,159,160,34,35],"622":[83,28,29,126,31,159,160,34,35],"623":[83,28,29,126,31,159,160,34,35],"633":[83,28,29,126,31,159,160,34,35],"651":[83,28,29,126,31,159,160,34,35],"672":[83,28,29,126,31,159,160,34,35],"692":[83,28,29,126,31,159,160,34,35],"706":[83,28,29,126,31,159,160,34,35],"715":[83,28,29,126,31,159,160,34,35],"721":[83,28,29,126,31,159,160,34,35],"743":[83,28,29,126,31,159,160,34,35],"762":[83,28,29,126,31,159,160,34,35],"775":[83,28,29,126,31,159,160,34,35],"785":[83,28,29,126,31,159,160,34,35],"805":[83,28,29,126,31,159,160,34,35],"814":[83,28,29,126,31,159,160,34,35],"827":[83,28,29,126,31,159,160,34,35],"836":[83,28,29,126,31,159,160,34,35],"849":[83,28,29,126,31,159,160,34,35],"851":[83,28,29,126,31,159,160,34,35],"862":[83,28,29,126,31,159,160,34,35],"890":[83,28,29,126,31,159,160,34,35],"902":[83,28,29,126,31,159,160,34,35],"911":[83,28,29,126,31,159,160,34,35],"916":[83,28,29,126,31,159,160,34,35],"935":[83,28,29,126,31,159,160,34,35],"946":[83,28,29,126,31,159,160,34,35]},"packages/@n8n/agents/src/runtime/memory/memory-store.ts":{"54":[28,29,31,159,34,35],"62":[28,29,31,159,34,35],"66":[28,29,31,159,34,35],"82":[28,29,31,159,34,35],"96":[28,29,31,159,34,35],"103":[28,29,31,159,34,35],"126":[28,29,31,159,34,35],"128":[28,29,31,159,34,35],"130":[28,29,31,159,34,35],"131":[28,29,31,159,34,35],"133":[28,29,31,159,34,35],"135":[28,29,31,159,34,35],"137":[28,29,31,159,34,35],"139":[28,29,31,159,34,35],"142":[28,29,31,159,34,35],"144":[28,29,31,159,34,35],"149":[28,29,31,159,34,35],"154":[28,29,31,159,34,35],"169":[28,29,31,159,34,35],"178":[28,29,31,159,34,35],"179":[28,29,31,159,34,35],"182":[28,29,31,159,34,35],"185":[28,29,31,159,34,35],"189":[28,29,31,159,34,35],"203":[28,29,31,159,34,35],"213":[28,29,31,159,34,35],"217":[28,29,31,159,34,35],"219":[28,29,31,159,34,35],"226":[28,29,31,159,34,35],"236":[28,29,31,159,34,35],"242":[28,29,31,159,34,35],"262":[28,29,31,159,34,35],"267":[28,29,31,159,34,35],"278":[28,29,31,159,34,35],"284":[28,29,31,159,34,35],"288":[28,29,31,159,34,35],"322":[28,29,31,159,34,35],"329":[28,29,31,159,34,35],"331":[28,29,31,159,34,35],"336":[28,29,31,159,34,35],"339":[28,29,31,159,34,35],"348":[28,29,31,159,34,35],"361":[28,29,31,159,34,35],"373":[28,29,31,159,34,35],"382":[28,29,31,159,34,35],"402":[28,29,31,159,34,35],"408":[28,29,31,159,34,35],"413":[28,29,31,159,34,35],"422":[28,29,31,159,34,35],"429":[28,29,31,159,34,35],"433":[28,29,31,159,34,35],"439":[28,29,31,159,34,35],"443":[28,29,31,159,34,35],"454":[28,29,31,159,34,35],"475":[28,29,31,159,34,35],"480":[28,29,31,159,34,35],"491":[28,29,31,159,34,35],"495":[28,29,31,159,34,35],"513":[28,29,31,159,34,35],"519":[28,29,31,159,34,35],"521":[28,29,31,159,34,35],"527":[28,29,31,159,34,35],"537":[28,29,31,159,34,35],"551":[28,29,31,159,34,35],"559":[28,29,31,159,34,35],"590":[28,29,31,159,34,35],"596":[28,29,31,159,34,35],"622":[28,29,31,159,34,35],"632":[28,29,31,159,34,35],"643":[28,29,31,159,34,35],"649":[28,29,31,159,34,35],"655":[28,29,31,159,34,35],"665":[28,29,31,159,34,35],"670":[28,29,31,159,34,35],"671":[28,29,31,159,34,35],"675":[28,29,31,159,34,35],"681":[28,29,31,159,34,35],"682":[28,29,31,159,34,35],"688":[28,29,31,159,34,35],"704":[28,29,31,159,34,35],"705":[28,29,31,159,34,35],"720":[28,29,31,159,34,35],"731":[28,29,31,159,34,35],"750":[28,29,31,159,34,35],"763":[28,29,31,159,34,35],"779":[28,29,31,159,34,35],"789":[28,29,31,159,34,35],"799":[28,29,31,159,34,35],"803":[28,29,31,159,34,35]},"packages/@n8n/agents/src/runtime/memory/observation-log-defaults.ts":{"139":[28,29,31,159,34,35],"154":[28,29,31,159,34,35],"158":[28,29,31,159,34,35],"298":[28,29,31,159,34,35],"310":[28,29,31,159,34,35],"314":[28,29,31,159,34,35],"316":[28,29,31,159,34,35],"317":[28,29,31,159,34,35],"318":[28,29,31,159,34,35],"319":[28,29,31,159,34,35],"321":[28,29,31,159,34,35],"347":[28,29,31,159,34,35],"355":[28,29,31,159,34,35]},"packages/@n8n/agents/src/runtime/memory/observation-log-observer.ts":{"65":[28,29,31,159,34,35],"111":[28,29,31,159,34,35],"144":[28,29,31,159,34,35],"157":[28,29,31,159,34,35],"158":[28,29,31,159,34,35],"192":[28,29,31,159,34,35],"222":[28,29,31,159,34,35],"267":[28,29,31,159,34,35],"281":[28,29,31,159,34,35],"332":[28,29,31,159,34,35],"334":[28,29,31,159,34,35],"337":[28,29,31,159,34,35],"341":[28,29,31,159,34,35],"345":[28,29,31,159,34,35],"351":[28,29,31,159,34,35],"363":[28,29,31,159,34,35],"377":[28,29,31,159,34,35],"388":[28,29,31,159,34,35],"408":[28,29,31,159,34,35],"432":[28,29,31,159,34,35],"456":[28,29,31,159,34,35],"461":[28,29,31,159,34,35],"469":[28,29,31,159,34,35],"477":[28,29,31,159,34,35]},"packages/@n8n/agents/src/runtime/memory/observation-log-reflector.ts":{"77":[28,29,31,35],"92":[28,29,31,35],"93":[28,29,31,35],"94":[28,29,31,35],"119":[28,29,31,35],"123":[28,29,31,35],"124":[28,29,31,35],"133":[28,29,31,35],"135":[28,29,31,35],"139":[28,29,31,35],"140":[28,29,31,35],"143":[28,29,31,35],"144":[28,29,31,35],"145":[28,29,31,35],"146":[28,29,31,35],"156":[28,29,31,35],"172":[28,29,31,35],"179":[28,29,31,35],"220":[28,29,31,35],"253":[28,29,31,35],"255":[28,29,31,35],"265":[28,29,31,35],"278":[28,29,31,35],"292":[28,29,31,35],"301":[28,29,31,35],"313":[28,29,31,35],"318":[28,29,31,35],"335":[28,29,31,35],"354":[28,29,31,35],"360":[28,29,31,35],"363":[28,29,31,35],"370":[28,29,31,35],"371":[28,29,31,35],"374":[28,29,31,35],"380":[28,29,31,35]},"packages/@n8n/agents/src/runtime/memory/observation-log-renderer.ts":{"35":[28,29,31,159,34,35],"41":[28,29,31,159,34,35],"47":[28,29,31,159,34,35],"51":[28,29,31,159,34,35],"55":[28,29,31,159,34,35],"56":[28,29,31,159,34,35],"99":[28,29,31,159,34,35],"137":[28,29,31,159,34,35],"141":[28,29,31,159,34,35]},"packages/@n8n/agents/src/runtime/memory/observation-log-store.ts":{"21":[28,29,31,159,34,35],"28":[28,29,31,159,34,35],"31":[28,29,31,159,34,35],"34":[28,29,31,159,34,35],"37":[28,29,31,159,34,35]},"packages/@n8n/agents/src/runtime/memory/scoped-memory-task-runner.ts":{"73":[28,29,31,35],"84":[28,29,31,35],"88":[28,29,31,35],"89":[28,29,31,35],"96":[28,29,31,35],"97":[28,29,31,35],"103":[28,29,31,35],"107":[28,29,31,35],"123":[28,29,31,35],"124":[28,29,31,35],"135":[28,29,31,35],"189":[28,29,31,35],"194":[28,29,31,35],"216":[28,29,31,35],"218":[28,29,31,35],"225":[28,29,31,35],"231":[28,29,31,35],"242":[28,29,31,35],"253":[28,29,31,35],"266":[28,29,31,35],"274":[28,29,31,35]},"packages/@n8n/agents/src/runtime/memory/strip-orphaned-tool-messages.ts":{"21":[83,28,29,31,159,160,34,35],"22":[83,28,29,31,159,160,34,35],"24":[83,28,29,31,159,160,34,35],"28":[83,28,29,31,159,160,34,35],"41":[83,28,29,31,159,160,34,35],"64":[83,28,29,31,159,160,34,35],"73":[83,28,29,31,159,160,34,35]},"packages/@n8n/agents/src/runtime/memory/title-generation.ts":{"74":[28,29,31,35],"81":[28,29,31,35],"117":[28,29,31,35],"161":[28,29,31,35],"225":[28,29,31,35],"249":[28,29,31,35],"253":[28,29,31,35],"254":[28,29,31,35],"306":[28,29,31,35]},"packages/@n8n/agents/src/runtime/memory/tool-result-memory.ts":{"17":[83,28,29,31,34,35],"26":[83,28,29,31,34,35],"35":[83,28,29,31,34,35],"38":[83,28,29,31,34,35],"46":[83,28,29,31,34,35],"66":[83,28,29,31,34,35],"69":[83,28,29,31,34,35]},"packages/@n8n/agents/src/runtime/model/attachment-validation-error.ts":{"31":[159,160,35],"32":[159,160,35],"35":[159,160,35],"39":[159,160,35],"42":[159,160,35],"43":[159,160,35],"45":[159,160,35],"49":[159,160,35],"59":[159,160,35],"61":[159,160,35]},"packages/@n8n/agents/src/runtime/model/google-vertex.ts":{"26":[83,28,29,31,159,34,35],"34":[83,28,29,31,159,34,35],"42":[83,28,29,31,159,34,35],"54":[83,28,29,31,159,34,35],"63":[83,28,29,31,159,34,35],"110":[83,28,29,31,159,34,35],"121":[83,28,29,31,159,34,35],"131":[83,28,29,31,159,34,35],"153":[83,28,29,31,159,34,35]},"packages/@n8n/agents/src/runtime/model/lazy-ai.ts":{"5":[83,28,29,31,159,34,35]},"packages/@n8n/agents/src/runtime/model/message-list.ts":{"48":[83,28,29,126,31,159,160,34,35],"65":[83,28,29,126,31,159,160,34,35],"121":[83,28,29,126,31,159,160,34,35],"157":[83,28,29,126,31,159,160,34,35],"180":[83,28,29,126,31,159,160,34,35],"186":[83,28,29,126,31,159,160,34,35],"187":[83,28,29,126,31,159,160,34,35],"220":[83,28,29,126,31,159,160,34,35],"226":[83,28,29,126,31,159,160,34,35],"234":[83,28,29,126,31,159,160,34,35],"242":[83,28,29,126,31,159,160,34,35],"257":[83,28,29,126,31,159,160,34,35],"291":[83,28,29,126,31,159,160,34,35],"313":[83,28,29,126,31,159,160,34,35],"328":[83,28,29,126,31,159,160,34,35],"339":[83,28,29,126,31,159,160,34,35],"346":[83,28,29,126,31,159,160,34,35],"354":[83,28,29,126,31,159,160,34,35],"357":[83,28,29,126,31,159,160,34,35],"368":[83,28,29,126,31,159,160,34,35],"408":[83,28,29,126,31,159,160,34,35],"424":[83,28,29,126,31,159,160,34,35],"427":[83,28,29,126,31,159,160,34,35],"441":[83,28,29,126,31,159,160,34,35],"442":[83,28,29,126,31,159,160,34,35],"449":[83,28,29,126,31,159,160,34,35],"450":[83,28,29,126,31,159,160,34,35],"457":[83,28,29,126,31,159,160,34,35],"458":[83,28,29,126,31,159,160,34,35],"461":[83,28,29,126,31,159,160,34,35],"463":[83,28,29,126,31,159,160,34,35],"471":[83,28,29,126,31,159,160,34,35],"475":[83,28,29,126,31,159,160,34,35],"476":[83,28,29,126,31,159,160,34,35],"486":[83,28,29,126,31,159,160,34,35]},"packages/@n8n/agents/src/runtime/model/messages.ts":{"35":[83,28,29,31,159,34,35],"39":[83,28,29,31,159,34,35],"43":[83,28,29,31,159,34,35],"47":[83,28,29,31,159,34,35],"51":[83,28,29,31,159,34,35],"55":[83,28,29,31,159,34,35],"63":[83,28,29,31,159,34,35],"69":[83,28,29,31,159,34,35],"98":[83,28,29,31,159,34,35],"102":[83,28,29,31,159,34,35],"106":[83,28,29,31,159,34,35],"110":[83,28,29,31,159,34,35],"114":[83,28,29,31,159,34,35],"119":[83,28,29,31,159,34,35],"121":[83,28,29,31,159,34,35],"126":[83,28,29,31,159,34,35],"129":[83,28,29,31,159,34,35],"135":[83,28,29,31,159,34,35],"141":[83,28,29,31,159,34,35],"149":[83,28,29,31,159,34,35],"164":[83,28,29,31,159,34,35],"186":[83,28,29,31,159,34,35],"197":[83,28,29,31,159,34,35],"203":[83,28,29,31,159,34,35],"212":[83,28,29,31,159,34,35],"270":[83,28,29,31,159,34,35],"306":[83,28,29,31,159,34,35],"318":[83,28,29,31,159,34,35],"398":[83,28,29,31,159,34,35],"403":[83,28,29,31,159,34,35],"412":[83,28,29,31,159,34,35],"489":[83,28,29,31,159,34,35],"490":[83,28,29,31,159,34,35],"505":[83,28,29,31,159,34,35],"523":[83,28,29,31,159,34,35],"529":[83,28,29,31,159,34,35],"571":[83,28,29,31,159,34,35],"595":[83,28,29,31,159,34,35]},"packages/@n8n/agents/src/runtime/model/model-factory.ts":{"40":[83,28,29,31,159,34,35],"56":[83,28,29,31,159,34,35],"58":[83,28,29,31,159,34,35],"65":[83,28,29,31,159,34,35],"110":[83,28,29,31,159,34,35],"126":[83,28,29,31,159,34,35],"152":[83,28,29,31,159,34,35],"154":[83,28,29,31,159,34,35],"166":[83,28,29,31,159,34,35],"193":[83,28,29,31,159,34,35],"198":[83,28,29,31,159,34,35],"221":[83,28,29,31,159,34,35],"227":[83,28,29,31,159,34,35],"239":[83,28,29,31,159,34,35],"267":[83,28,29,31,159,34,35],"274":[83,28,29,31,159,34,35],"280":[83,28,29,31,159,34,35],"298":[83,28,29,31,159,34,35],"313":[83,28,29,31,159,34,35],"330":[83,28,29,31,159,34,35],"336":[83,28,29,31,159,34,35],"342":[83,28,29,31,159,34,35],"348":[83,28,29,31,159,34,35],"354":[83,28,29,31,159,34,35],"360":[83,28,29,31,159,34,35],"366":[83,28,29,31,159,34,35],"374":[83,28,29,31,159,34,35],"381":[83,28,29,31,159,34,35],"393":[83,28,29,31,159,34,35],"404":[83,28,29,31,159,34,35],"466":[83,28,29,31,159,34,35],"486":[83,28,29,31,159,34,35],"530":[83,28,29,31,159,34,35],"565":[83,28,29,31,159,34,35]},"packages/@n8n/agents/src/runtime/model/model-token-counter.ts":{"6":[83,28,29,31,159,34,35],"7":[83,28,29,31,159,34,35],"19":[83,28,29,31,159,34,35]},"packages/@n8n/agents/src/runtime/model/prompt-cache.ts":{"15":[83,28,29,31,159,34,35],"18":[83,28,29,31,159,34,35],"31":[83,28,29,31,159,34,35],"41":[83,28,29,31,159,34,35],"51":[83,28,29,31,159,34,35],"60":[83,28,29,31,159,34,35],"77":[83,28,29,31,159,34,35],"91":[83,28,29,31,159,34,35],"98":[83,28,29,31,159,34,35],"110":[83,28,29,31,159,34,35],"125":[83,28,29,31,159,34,35],"150":[83,28,29,31,159,34,35],"167":[83,28,29,31,159,34,35],"180":[83,28,29,31,159,34,35],"220":[83,28,29,31,159,34,35]},"packages/@n8n/agents/src/runtime/model/provider-quirks.ts":{"35":[83,28,29,31,159,34,35],"70":[83,28,29,31,159,34,35],"77":[83,28,29,31,159,34,35],"82":[83,28,29,31,159,34,35],"138":[83,28,29,31,159,34,35],"158":[83,28,29,31,159,34,35],"171":[83,28,29,31,159,34,35],"181":[83,28,29,31,159,34,35],"198":[83,28,29,31,159,34,35],"207":[83,28,29,31,159,34,35]},"packages/@n8n/agents/src/runtime/model/raw-error.ts":{"36":[83,28,29,31,159,34,35],"44":[83,28,29,31,159,34,35],"55":[83,28,29,31,159,34,35],"56":[83,28,29,31,159,34,35],"64":[83,28,29,31,159,34,35]},"packages/@n8n/agents/src/runtime/model/raw-usage.ts":{"33":[28,29,31,159,160,34,35],"44":[28,29,31,159,160,34,35],"47":[28,29,31,159,160,34,35],"77":[28,29,31,159,160,34,35],"78":[28,29,31,159,160,34,35],"85":[28,29,31,159,160,34,35]},"packages/@n8n/agents/src/runtime/skills/active-skills.ts":{"44":[83,28,29,126,31,159,34,35],"50":[83,28,29,126,31,159,34,35],"67":[83,28,29,126,31,159,34,35],"69":[83,28,29,126,31,159,34,35],"79":[83,28,29,126,31,159,34,35],"83":[83,28,29,126,31,159,34,35],"87":[83,28,29,126,31,159,34,35],"108":[83,28,29,126,31,159,34,35],"110":[83,28,29,126,31,159,34,35],"132":[83,28,29,126,31,159,34,35],"140":[83,28,29,126,31,159,34,35],"144":[83,28,29,126,31,159,34,35],"179":[83,28,29,126,31,159,34,35],"198":[83,28,29,126,31,159,34,35],"208":[83,28,29,126,31,159,34,35],"226":[83,28,29,126,31,159,34,35],"240":[83,28,29,126,31,159,34,35],"242":[83,28,29,126,31,159,34,35],"246":[83,28,29,126,31,159,34,35],"270":[83,28,29,126,31,159,34,35],"286":[83,28,29,126,31,159,34,35],"292":[83,28,29,126,31,159,34,35],"293":[83,28,29,126,31,159,34,35],"303":[83,28,29,126,31,159,34,35],"304":[83,28,29,126,31,159,34,35]},"packages/@n8n/agents/src/runtime/skills/skill-dependency-tools.ts":{"9":[83,28,29,31,159,34,35],"12":[83,28,29,31,159,34,35],"14":[83,28,29,31,159,34,35],"20":[83,28,29,31,159,34,35]},"packages/@n8n/agents/src/runtime/state/background-task-tracker.ts":{"1":[83,28,29,31,159,34,35],"4":[83,28,29,31,159,34,35],"8":[83,28,29,31,159,34,35],"10":[83,28,29,31,159,34,35],"16":[83,28,29,31,159,34,35]},"packages/@n8n/agents/src/runtime/state/event-bus.ts":{"1":[83,28,29,31,159,34,35],"18":[83,28,29,31,159,34,35],"29":[83,28,29,31,159,34,35],"31":[83,28,29,31,159,34,35],"34":[83,28,29,31,159,34,35],"38":[83,28,29,31,159,34,35],"42":[83,28,29,31,159,34,35],"46":[83,28,29,31,159,34,35],"70":[83,28,29,31,159,34,35],"79":[83,28,29,31,159,34,35],"88":[83,28,29,31,159,34,35],"92":[83,28,29,31,159,34,35],"100":[83,28,29,31,159,34,35],"107":[83,28,29,31,159,34,35],"108":[83,28,29,31,159,34,35],"124":[83,28,29,31,159,34,35],"133":[83,28,29,31,159,34,35],"135":[83,28,29,31,159,34,35],"141":[83,28,29,31,159,34,35],"145":[83,28,29,31,159,34,35],"153":[83,28,29,31,159,34,35]},"packages/@n8n/agents/src/runtime/state/run-state.ts":{"11":[83,28,29,126,31,159,34,35],"25":[83,28,29,126,31,159,34,35],"28":[83,28,29,126,31,159,34,35],"32":[83,28,29,126,31,159,34,35],"36":[83,28,29,126,31,159,34,35],"43":[83,28,29,126,31,159,34,35],"56":[83,28,29,126,31,159,34,35],"61":[83,28,29,126,31,159,34,35],"71":[83,28,29,126,31,159,34,35],"81":[83,28,29,126,31,159,34,35],"89":[83,28,29,126,31,159,34,35],"98":[83,28,29,126,31,159,34,35],"112":[83,28,29,126,31,159,34,35],"117":[83,28,29,126,31,159,34,35],"123":[83,28,29,126,31,159,34,35]},"packages/@n8n/agents/src/runtime/streaming/stream-session.ts":{"45":[83,28,29,31,159,160,34,35],"52":[83,28,29,31,159,160,34,35],"61":[83,28,29,31,159,160,34,35],"71":[83,28,29,31,159,160,34,35],"76":[83,28,29,31,159,160,34,35],"81":[83,28,29,31,159,160,34,35],"94":[83,28,29,31,159,160,34,35],"95":[83,28,29,31,159,160,34,35],"120":[83,28,29,31,159,160,34,35]},"packages/@n8n/agents/src/runtime/streaming/stream-stall.ts":{"49":[83,28,29,31,159,34,35],"59":[83,28,29,31,159,34,35],"83":[83,28,29,31,159,34,35],"95":[83,28,29,31,159,34,35],"106":[83,28,29,31,159,34,35],"107":[83,28,29,31,159,34,35],"120":[83,28,29,31,159,34,35],"130":[83,28,29,31,159,34,35],"131":[83,28,29,31,159,34,35],"132":[83,28,29,31,159,34,35]},"packages/@n8n/agents/src/runtime/streaming/stream-writer-guard.ts":{"18":[83,28,29,31,159,160,34,35],"19":[83,28,29,31,159,160,34,35],"26":[83,28,29,31,159,160,34,35],"30":[83,28,29,31,159,160,34,35],"35":[83,28,29,31,159,160,34,35],"46":[83,28,29,31,159,160,34,35],"63":[83,28,29,31,159,160,34,35]},"packages/@n8n/agents/src/runtime/streaming/stream.ts":{"12":[83,28,29,31,159,160,34,35],"21":[83,28,29,31,159,160,34,35],"74":[83,28,29,31,159,160,34,35]},"packages/@n8n/agents/src/runtime/telemetry/runtime-telemetry.ts":{"38":[83,28,29,31,159,34,35],"46":[83,28,29,31,159,34,35],"54":[83,28,29,31,159,34,35],"62":[83,28,29,31,159,34,35],"73":[83,28,29,31,159,34,35],"85":[83,28,29,31,159,34,35],"96":[83,28,29,31,159,34,35],"103":[83,28,29,31,159,34,35],"107":[83,28,29,31,159,34,35],"108":[83,28,29,31,159,34,35],"118":[83,28,29,31,159,34,35],"179":[83,28,29,31,159,34,35],"193":[83,28,29,31,159,34,35],"226":[83,28,29,31,159,34,35],"240":[83,28,29,31,159,34,35],"268":[83,28,29,31,159,34,35],"276":[83,28,29,31,159,34,35],"287":[83,28,29,31,159,34,35],"292":[83,28,29,31,159,34,35],"300":[83,28,29,31,159,34,35],"326":[83,28,29,31,159,34,35],"340":[83,28,29,31,159,34,35],"371":[83,28,29,31,159,34,35],"394":[83,28,29,31,159,34,35],"431":[83,28,29,31,159,34,35],"436":[83,28,29,31,159,34,35],"440":[83,28,29,31,159,34,35]},"packages/@n8n/agents/src/runtime/telemetry/telemetry-options.ts":{"11":[83,28,29,31,159,34,35]},"packages/@n8n/agents/src/runtime/tools/deferred-tool-manager.ts":{"42":[28,29,31,159,34,35],"47":[28,29,31,159,34,35],"52":[28,29,31,159,34,35],"100":[28,29,31,159,34,35],"122":[28,29,31,159,34,35],"126":[28,29,31,159,34,35],"130":[28,29,31,159,34,35],"134":[28,29,31,159,34,35],"140":[28,29,31,159,34,35],"144":[28,29,31,159,34,35],"146":[28,29,31,159,34,35],"147":[28,29,31,159,34,35],"150":[28,29,31,159,34,35],"165":[28,29,31,159,34,35],"172":[28,29,31,159,34,35],"179":[28,29,31,159,34,35],"186":[28,29,31,159,34,35],"193":[28,29,31,159,34,35],"197":[28,29,31,159,34,35],"201":[28,29,31,159,34,35],"206":[28,29,31,159,34,35],"210":[28,29,31,159,34,35],"214":[28,29,31,159,34,35],"253":[28,29,31,159,34,35],"261":[28,29,31,159,34,35],"272":[28,29,31,159,34,35]},"packages/@n8n/agents/src/runtime/tools/delegate-sub-agent-tool.ts":{"59":[1,2,83,28,29,31,159,34,35],"84":[1,2,83,28,29,31,159,34,35],"99":[1,2,83,28,29,31,159,34,35],"110":[1,2,83,28,29,31,159,34,35],"132":[1,2,83,28,29,31,159,34,35],"170":[1,2,83,28,29,31,159,34,35],"186":[1,2,83,28,29,31,159,34,35],"205":[1,2,83,28,29,31,159,34,35],"233":[1,2,83,28,29,31,159,34,35],"245":[1,2,83,28,29,31,159,34,35],"266":[1,2,83,28,29,31,159,34,35],"272":[1,2,83,28,29,31,159,34,35],"282":[1,2,83,28,29,31,159,34,35],"331":[1,2,83,28,29,31,159,34,35],"340":[1,2,83,28,29,31,159,34,35],"344":[1,2,83,28,29,31,159,34,35],"351":[1,2,83,28,29,31,159,34,35],"358":[1,2,83,28,29,31,159,34,35]},"packages/@n8n/agents/src/runtime/tools/tool-adapter.ts":{"38":[83,28,29,126,31,159,34,35],"51":[83,28,29,126,31,159,34,35],"73":[83,28,29,126,31,159,34,35],"108":[83,28,29,126,31,159,34,35],"145":[83,28,29,126,31,159,34,35],"151":[83,28,29,126,31,159,34,35],"155":[83,28,29,126,31,159,34,35],"176":[83,28,29,126,31,159,34,35],"179":[83,28,29,126,31,159,34,35],"197":[83,28,29,126,31,159,34,35],"203":[83,28,29,126,31,159,34,35]},"packages/@n8n/agents/src/runtime/tools/tool-call-executor.ts":{"52":[83,28,29,126,31,159,34,35],"57":[83,28,29,126,31,159,34,35],"61":[83,28,29,126,31,159,34,35],"65":[83,28,29,126,31,159,34,35],"74":[83,28,29,126,31,159,34,35],"82":[83,28,29,126,31,159,34,35],"129":[83,28,29,126,31,159,34,35],"134":[83,28,29,126,31,159,34,35],"139":[83,28,29,126,31,159,34,35],"140":[83,28,29,126,31,159,34,35],"166":[83,28,29,126,31,159,34,35],"191":[83,28,29,126,31,159,34,35],"197":[83,28,29,126,31,159,34,35],"217":[83,28,29,126,31,159,34,35],"230":[83,28,29,126,31,159,34,35],"268":[83,28,29,126,31,159,34,35],"281":[83,28,29,126,31,159,34,35],"298":[83,28,29,126,31,159,34,35],"317":[83,28,29,126,31,159,34,35],"332":[83,28,29,126,31,159,34,35],"348":[83,28,29,126,31,159,34,35],"374":[83,28,29,126,31,159,34,35],"404":[83,28,29,126,31,159,34,35],"430":[83,28,29,126,31,159,34,35],"454":[83,28,29,126,31,159,34,35],"487":[83,28,29,126,31,159,34,35],"508":[83,28,29,126,31,159,34,35],"517":[83,28,29,126,31,159,34,35],"548":[83,28,29,126,31,159,34,35]},"packages/@n8n/agents/src/runtime/tools/tool-call-runner.ts":{"48":[83,28,29,126,31,159,34,35],"52":[83,28,29,126,31,159,34,35],"59":[83,28,29,126,31,159,34,35],"72":[83,28,29,126,31,159,34,35],"74":[83,28,29,126,31,159,34,35],"78":[83,28,29,126,31,159,34,35],"82":[83,28,29,126,31,159,34,35],"96":[83,28,29,126,31,159,34,35],"159":[83,28,29,126,31,159,34,35],"173":[83,28,29,126,31,159,34,35],"200":[83,28,29,126,31,159,34,35],"217":[83,28,29,126,31,159,34,35],"221":[83,28,29,126,31,159,34,35],"238":[83,28,29,126,31,159,34,35],"251":[83,28,29,126,31,159,34,35],"268":[83,28,29,126,31,159,34,35],"293":[83,28,29,126,31,159,34,35],"299":[83,28,29,126,31,159,34,35],"301":[83,28,29,126,31,159,34,35],"307":[83,28,29,126,31,159,34,35],"324":[83,28,29,126,31,159,34,35],"348":[83,28,29,126,31,159,34,35],"364":[83,28,29,126,31,159,34,35],"389":[83,28,29,126,31,159,34,35],"391":[83,28,29,126,31,159,34,35],"396":[83,28,29,126,31,159,34,35],"411":[83,28,29,126,31,159,34,35],"442":[83,28,29,126,31,159,34,35],"510":[83,28,29,126,31,159,34,35],"534":[83,28,29,126,31,159,34,35],"542":[83,28,29,126,31,159,34,35]},"packages/@n8n/agents/src/runtime/tools/tool-result-guard.ts":{"59":[83,28,29,34,35],"100":[83,28,29,34,35],"106":[83,28,29,34,35],"129":[83,28,29,34,35],"138":[83,28,29,34,35],"145":[83,28,29,34,35],"157":[83,28,29,34,35],"159":[83,28,29,34,35],"167":[83,28,29,34,35],"195":[83,28,29,34,35],"202":[83,28,29,34,35],"231":[83,28,29,34,35]},"packages/@n8n/agents/src/sdk/abort.ts":{"6":[83,28,29,31,159,34,35],"12":[83,28,29,31,159,34,35],"20":[83,28,29,31,159,34,35],"35":[83,28,29,31,159,34,35],"39":[83,28,29,31,159,34,35],"46":[83,28,29,31,159,34,35],"47":[83,28,29,31,159,34,35]},"packages/@n8n/agents/src/sdk/agent.ts":{"106":[83,28,29,126,31,159,34,35],"247":[83,28,29,126,31,159,34,35],"251":[83,28,29,126,31,159,34,35],"255":[83,28,29,126,31,159,34,35],"271":[83,28,29,126,31,159,34,35],"284":[83,28,29,126,31,159,34,35],"290":[83,28,29,126,31,159,34,35],"297":[83,28,29,126,31,159,34,35],"303":[83,28,29,126,31,159,34,35],"305":[83,28,29,126,31,159,34,35],"314":[83,28,29,126,31,159,34,35],"322":[83,28,29,126,31,159,34,35],"340":[83,28,29,126,31,159,34,35],"349":[83,28,29,126,31,159,34,35],"360":[83,28,29,126,31,159,34,35],"366":[83,28,29,126,31,159,34,35],"371":[83,28,29,126,31,159,34,35],"397":[83,28,29,126,31,159,34,35],"403":[83,28,29,126,31,159,34,35],"409":[83,28,29,126,31,159,34,35],"416":[83,28,29,126,31,159,34,35],"422":[83,28,29,126,31,159,34,35],"428":[83,28,29,126,31,159,34,35],"450":[83,28,29,126,31,159,34,35],"480":[83,28,29,126,31,159,34,35],"502":[83,28,29,126,31,159,34,35],"517":[83,28,29,126,31,159,34,35],"537":[83,28,29,126,31,159,34,35],"543":[83,28,29,126,31,159,34,35],"556":[83,28,29,126,31,159,34,35],"567":[83,28,29,126,31,159,34,35],"579":[83,28,29,126,31,159,34,35],"602":[83,28,29,126,31,159,34,35],"617":[83,28,29,126,31,159,34,35],"632":[83,28,29,126,31,159,34,35],"634":[83,28,29,126,31,159,34,35],"657":[83,28,29,126,31,159,34,35],"663":[83,28,29,126,31,159,34,35],"671":[83,28,29,126,31,159,34,35],"688":[83,28,29,126,31,159,34,35],"704":[83,28,29,126,31,159,34,35],"731":[83,28,29,126,31,159,34,35],"746":[83,28,29,126,31,159,34,35],"763":[83,28,29,126,31,159,34,35],"769":[83,28,29,126,31,159,34,35],"774":[83,28,29,126,31,159,34,35],"789":[83,28,29,126,31,159,34,35],"816":[83,28,29,126,31,159,34,35],"840":[83,28,29,126,31,159,34,35],"860":[83,28,29,126,31,159,34,35],"876":[83,28,29,126,31,159,34,35],"888":[83,28,29,126,31,159,34,35],"898":[83,28,29,126,31,159,34,35],"915":[83,28,29,126,31,159,34,35],"920":[83,28,29,126,31,159,34,35],"925":[83,28,29,126,31,159,34,35],"933":[83,28,29,126,31,159,34,35],"946":[83,28,29,126,31,159,34,35],"952":[83,28,29,126,31,159,34,35],"953":[83,28,29,126,31,159,34,35],"966":[83,28,29,126,31,159,34,35],"980":[83,28,29,126,31,159,34,35],"990":[83,28,29,126,31,159,34,35],"996":[83,28,29,126,31,159,34,35],"1002":[83,28,29,126,31,159,34,35],"1024":[83,28,29,126,31,159,34,35],"1025":[83,28,29,126,31,159,34,35],"1026":[83,28,29,126,31,159,34,35],"1036":[83,28,29,126,31,159,34,35],"1048":[83,28,29,126,31,159,34,35],"1073":[83,28,29,126,31,159,34,35],"1074":[83,28,29,126,31,159,34,35],"1086":[83,28,29,126,31,159,34,35],"1178":[83,28,29,126,31,159,34,35],"1189":[83,28,29,126,31,159,34,35],"1204":[83,28,29,126,31,159,34,35],"1209":[83,28,29,126,31,159,34,35],"1211":[83,28,29,126,31,159,34,35],"1225":[83,28,29,126,31,159,34,35],"1237":[83,28,29,126,31,159,34,35],"1264":[83,28,29,126,31,159,34,35],"1280":[83,28,29,126,31,159,34,35],"1408":[83,28,29,126,31,159,34,35],"1417":[83,28,29,126,31,159,34,35],"1422":[83,28,29,126,31,159,34,35],"1428":[83,28,29,126,31,159,34,35],"1439":[83,28,29,126,31,159,34,35],"1442":[83,28,29,126,31,159,34,35],"1447":[83,28,29,126,31,159,34,35],"1462":[83,28,29,126,31,159,34,35],"1468":[83,28,29,126,31,159,34,35],"1477":[83,28,29,126,31,159,34,35],"1481":[83,28,29,126,31,159,34,35],"1486":[83,28,29,126,31,159,34,35],"1489":[83,28,29,126,31,159,34,35]},"packages/@n8n/agents/src/sdk/cancellation.ts":{"18":[83,28,29,34,35],"22":[83,28,29,34,35]},"packages/@n8n/agents/src/sdk/catalog.ts":{"136":[1,2,83,28,29,31,159,34,35],"150":[1,2,83,28,29,31,159,34,35],"182":[1,2,83,28,29,31,159,34,35],"275":[1,2,83,28,29,31,159,34,35],"279":[1,2,83,28,29,31,159,34,35],"283":[1,2,83,28,29,31,159,34,35],"301":[1,2,83,28,29,31,159,34,35],"317":[1,2,83,28,29,31,159,34,35],"337":[1,2,83,28,29,31,159,34,35]},"packages/@n8n/agents/src/sdk/guardrails/redactor.ts":{"13":[1,2,83,28,29,31,159,34,35],"21":[1,2,83,28,29,31,159,34,35],"29":[1,2,83,28,29,31,159,34,35],"41":[1,2,83,28,29,31,159,34,35],"50":[1,2,83,28,29,31,159,34,35],"62":[1,2,83,28,29,31,159,34,35]},"packages/@n8n/agents/src/sdk/memory.ts":{"13":[28,29,31,159,34,35],"37":[28,29,31,159,34,35],"60":[28,29,31,159,34,35],"83":[28,29,31,159,34,35],"122":[28,29,31,159,34,35],"177":[28,29,31,159,34,35],"187":[28,29,31,159,34,35],"205":[28,29,31,159,34,35],"216":[28,29,31,159,34,35],"224":[28,29,31,159,34,35]},"packages/@n8n/agents/src/sdk/message.ts":{"3":[83,28,29,31,159,34,35],"19":[83,28,29,31,159,34,35],"23":[83,28,29,31,159,34,35]},"packages/@n8n/agents/src/sdk/telemetry.ts":{"29":[83,28,29,31,159,34,35],"31":[83,28,29,31,159,34,35],"54":[83,28,29,31,159,34,35],"66":[83,28,29,31,159,34,35],"70":[83,28,29,31,159,34,35],"74":[83,28,29,31,159,34,35],"78":[83,28,29,31,159,34,35],"84":[83,28,29,31,159,34,35],"95":[83,28,29,31,159,34,35],"103":[83,28,29,31,159,34,35],"110":[83,28,29,31,159,34,35],"123":[83,28,29,31,159,34,35],"132":[83,28,29,31,159,34,35],"140":[83,28,29,31,159,34,35],"149":[83,28,29,31,159,34,35],"198":[83,28,29,31,159,34,35],"233":[83,28,29,31,159,34,35],"239":[83,28,29,31,159,34,35],"247":[83,28,29,31,159,34,35],"252":[83,28,29,31,159,34,35],"258":[83,28,29,31,159,34,35],"264":[83,28,29,31,159,34,35],"270":[83,28,29,31,159,34,35],"276":[83,28,29,31,159,34,35],"282":[83,28,29,31,159,34,35],"292":[83,28,29,31,159,34,35],"298":[83,28,29,31,159,34,35],"309":[83,28,29,31,159,34,35],"321":[83,28,29,31,159,34,35],"327":[83,28,29,31,159,34,35],"343":[83,28,29,31,159,34,35],"352":[83,28,29,31,159,34,35],"378":[83,28,29,31,159,34,35],"385":[83,28,29,31,159,34,35]},"packages/@n8n/agents/src/sdk/tool.ts":{"47":[83,28,29,31,159,34,35],"61":[83,28,29,31,159,34,35],"67":[83,28,29,31,159,34,35],"78":[83,28,29,31,159,34,35],"91":[83,28,29,31,159,34,35],"98":[83,28,29,31,159,34,35],"112":[83,28,29,31,159,34,35],"175":[83,28,29,31,159,34,35],"256":[83,28,29,31,159,34,35],"261":[83,28,29,31,159,34,35],"275":[83,28,29,31,159,34,35],"281":[83,28,29,31,159,34,35],"288":[83,28,29,31,159,34,35],"295":[83,28,29,31,159,34,35],"302":[83,28,29,31,159,34,35],"312":[83,28,29,31,159,34,35],"322":[83,28,29,31,159,34,35],"334":[83,28,29,31,159,34,35],"340":[83,28,29,31,159,34,35],"346":[83,28,29,31,159,34,35],"355":[83,28,29,31,159,34,35],"361":[83,28,29,31,159,34,35],"367":[83,28,29,31,159,34,35],"378":[83,28,29,31,159,34,35],"389":[83,28,29,31,159,34,35],"459":[83,28,29,31,159,34,35],"496":[83,28,29,31,159,34,35]},"packages/@n8n/agents/src/skills/prompt.ts":{"7":[83,28,29,31,159,34,35],"11":[83,28,29,31,159,34,35],"16":[83,28,29,31,159,34,35],"57":[83,28,29,31,159,34,35],"69":[83,28,29,31,159,34,35],"73":[83,28,29,31,159,34,35]},"packages/@n8n/agents/src/skills/registry.ts":{"24":[83,28,29,31,159,34,35],"39":[83,28,29,31,159,34,35],"41":[83,28,29,31,159,34,35],"45":[83,28,29,31,159,34,35],"52":[83,28,29,31,159,34,35],"69":[83,28,29,31,159,34,35],"86":[83,28,29,31,159,34,35],"89":[83,28,29,31,159,34,35],"99":[83,28,29,31,159,34,35],"103":[83,28,29,31,159,34,35],"110":[83,28,29,31,159,34,35],"116":[83,28,29,31,159,34,35],"120":[83,28,29,31,159,34,35],"148":[83,28,29,31,159,34,35],"156":[83,28,29,31,159,34,35],"158":[83,28,29,31,159,34,35],"161":[83,28,29,31,159,34,35],"170":[83,28,29,31,159,34,35],"178":[83,28,29,31,159,34,35],"185":[83,28,29,31,159,34,35],"194":[83,28,29,31,159,34,35],"197":[83,28,29,31,159,34,35],"227":[83,28,29,31,159,34,35],"232":[83,28,29,31,159,34,35],"237":[83,28,29,31,159,34,35],"278":[83,28,29,31,159,34,35],"279":[83,28,29,31,159,34,35],"293":[83,28,29,31,159,34,35],"294":[83,28,29,31,159,34,35],"311":[83,28,29,31,159,34,35],"317":[83,28,29,31,159,34,35],"322":[83,28,29,31,159,34,35],"326":[83,28,29,31,159,34,35],"335":[83,28,29,31,159,34,35],"341":[83,28,29,31,159,34,35],"375":[83,28,29,31,159,34,35],"404":[83,28,29,31,159,34,35],"428":[83,28,29,31,159,34,35],"457":[83,28,29,31,159,34,35],"463":[83,28,29,31,159,34,35],"481":[83,28,29,31,159,34,35],"498":[83,28,29,31,159,34,35],"509":[83,28,29,31,159,34,35],"520":[83,28,29,31,159,34,35],"525":[83,28,29,31,159,34,35],"528":[83,28,29,31,159,34,35],"531":[83,28,29,31,159,34,35],"540":[83,28,29,31,159,34,35],"546":[83,28,29,31,159,34,35],"563":[83,28,29,31,159,34,35],"581":[83,28,29,31,159,34,35],"585":[83,28,29,31,159,34,35],"590":[83,28,29,31,159,34,35],"594":[83,28,29,31,159,34,35],"598":[83,28,29,31,159,34,35],"602":[83,28,29,31,159,34,35],"612":[83,28,29,31,159,34,35],"619":[83,28,29,31,159,34,35],"626":[83,28,29,31,159,34,35],"633":[83,28,29,31,159,34,35],"638":[83,28,29,31,159,34,35],"639":[83,28,29,31,159,34,35],"640":[83,28,29,31,159,34,35],"646":[83,28,29,31,159,34,35],"652":[83,28,29,31,159,34,35],"656":[83,28,29,31,159,34,35]},"packages/@n8n/agents/src/skills/tools.ts":{"52":[28,29,126,31,159,34,35],"66":[28,29,126,31,159,34,35],"104":[28,29,126,31,159,34,35],"108":[28,29,126,31,159,34,35],"117":[28,29,126,31,159,34,35],"131":[28,29,126,31,159,34,35],"137":[28,29,126,31,159,34,35],"162":[28,29,126,31,159,34,35],"231":[28,29,126,31,159,34,35],"245":[28,29,126,31,159,34,35],"260":[28,29,126,31,159,34,35],"267":[28,29,126,31,159,34,35],"268":[28,29,126,31,159,34,35],"277":[28,29,126,31,159,34,35],"293":[28,29,126,31,159,34,35],"297":[28,29,126,31,159,34,35],"301":[28,29,126,31,159,34,35],"311":[28,29,126,31,159,34,35],"318":[28,29,126,31,159,34,35],"325":[28,29,126,31,159,34,35],"329":[28,29,126,31,159,34,35],"334":[28,29,126,31,159,34,35],"339":[28,29,126,31,159,34,35],"345":[28,29,126,31,159,34,35],"360":[28,29,126,31,159,34,35],"365":[28,29,126,31,159,34,35],"371":[28,29,126,31,159,34,35],"382":[28,29,126,31,159,34,35],"386":[28,29,126,31,159,34,35]},"packages/@n8n/agents/src/skills/validator.ts":{"44":[28,29,31,159,34,35],"57":[28,29,31,159,34,35],"87":[28,29,31,159,34,35],"124":[28,29,31,159,34,35],"144":[28,29,31,159,34,35],"192":[28,29,31,159,34,35],"209":[28,29,31,159,34,35],"218":[28,29,31,159,34,35],"238":[28,29,31,159,34,35],"259":[28,29,31,159,34,35],"260":[28,29,31,159,34,35],"273":[28,29,31,159,34,35],"292":[28,29,31,159,34,35],"311":[28,29,31,159,34,35],"362":[28,29,31,159,34,35],"386":[28,29,31,159,34,35],"407":[28,29,31,159,34,35],"423":[28,29,31,159,34,35],"465":[28,29,31,159,34,35],"485":[28,29,31,159,34,35],"489":[28,29,31,159,34,35]},"packages/@n8n/agents/src/types/index.ts":{"67":[1,2,83,28,29,31,159,34,35],"190":[1,2,83,28,29,31,159,34,35]},"packages/@n8n/agents/src/types/sdk/agent.ts":{"40":[28,29,31,159,34,35],"41":[28,29,31,159,34,35]},"packages/@n8n/agents/src/utils/model.ts":{"3":[83,28,29,31,159,34,35],"22":[83,28,29,31,159,34,35]},"packages/@n8n/agents/src/utils/parse.ts":{"27":[83,28,29,126,34,35],"31":[83,28,29,126,34,35],"40":[83,28,29,126,34,35],"48":[83,28,29,126,34,35],"51":[83,28,29,126,34,35],"60":[83,28,29,126,34,35],"97":[83,28,29,126,34,35],"105":[83,28,29,126,34,35]},"packages/@n8n/agents/src/workspace/filesystem/base-filesystem.ts":{"39":[28,29,31,159,34,35],"44":[28,29,31,159,34,35],"64":[28,29,31,159,34,35],"83":[28,29,31,159,34,35],"87":[28,29,31,159,34,35],"96":[28,29,31,159,34,35],"114":[28,29,31,159,34,35],"139":[28,29,31,159,34,35]},"packages/@n8n/agents/src/workspace/filesystem/n8n-sandbox-filesystem.ts":{"22":[28,29,126,31,159,34,35],"37":[28,29,126,31,159,34,35],"45":[28,29,126,31,159,34,35],"53":[28,29,126,31,159,34,35],"61":[28,29,126,31,159,34,35],"67":[28,29,126,31,159,34,35],"68":[28,29,126,31,159,34,35],"77":[28,29,126,31,159,34,35],"78":[28,29,126,31,159,34,35],"89":[28,29,126,31,159,34,35],"90":[28,29,126,31,159,34,35],"95":[28,29,126,31,159,34,35],"96":[28,29,126,31,159,34,35],"104":[28,29,126,31,159,34,35],"105":[28,29,126,31,159,34,35],"115":[28,29,126,31,159,34,35],"116":[28,29,126,31,159,34,35],"125":[28,29,126,31,159,34,35],"126":[28,29,126,31,159,34,35],"131":[28,29,126,31,159,34,35],"135":[28,29,126,31,159,34,35],"136":[28,29,126,31,159,34,35],"138":[28,29,126,31,159,34,35],"146":[28,29,126,31,159,34,35],"158":[28,29,126,31,159,34,35],"159":[28,29,126,31,159,34,35]},"packages/@n8n/agents/src/workspace/index.ts":{"1":[1,2,83,28,29,31,159,34,35],"13":[1,2,83,28,29,31,159,34,35],"14":[1,2,83,28,29,31,159,34,35]},"packages/@n8n/agents/src/workspace/lifecycle.ts":{"14":[28,29,31,159,34,35]},"packages/@n8n/agents/src/workspace/sandbox/base-sandbox.ts":{"28":[83,28,29,31,159,34,35],"46":[83,28,29,31,159,34,35],"50":[83,28,29,31,159,34,35],"70":[83,28,29,31,159,34,35],"74":[83,28,29,31,159,34,35],"86":[83,28,29,31,159,34,35],"94":[83,28,29,31,159,34,35],"95":[83,28,29,31,159,34,35],"118":[83,28,29,31,159,34,35],"123":[83,28,29,31,159,34,35],"128":[83,28,29,31,159,34,35],"132":[83,28,29,31,159,34,35],"135":[83,28,29,31,159,34,35],"142":[83,28,29,31,159,34,35],"153":[83,28,29,31,159,34,35],"162":[83,28,29,31,159,34,35],"166":[83,28,29,31,159,34,35],"182":[83,28,29,31,159,34,35],"198":[83,28,29,31,159,34,35]},"packages/@n8n/agents/src/workspace/sandbox/create-workspace.ts":{"13":[83,28,29,31,159,34,35],"20":[83,28,29,31,159,34,35],"79":[83,28,29,31,159,34,35]},"packages/@n8n/agents/src/workspace/sandbox/index.ts":{"22":[83,28,29,126,31,159,34,35]},"packages/@n8n/agents/src/workspace/sandbox/n8n-sandbox-sandbox.ts":{"43":[28,29,92,31,159,34,35],"53":[28,29,92,31,159,34,35],"57":[28,29,92,31,159,34,35],"63":[28,29,92,31,159,34,35],"73":[28,29,92,31,159,34,35],"78":[28,29,92,31,159,34,35],"95":[28,29,92,31,159,34,35],"103":[28,29,92,31,159,34,35],"132":[28,29,92,31,159,34,35],"136":[28,29,92,31,159,34,35],"146":[28,29,92,31,159,34,35],"152":[28,29,92,31,159,34,35],"157":[28,29,92,31,159,34,35],"163":[28,29,92,31,159,34,35],"168":[28,29,92,31,159,34,35]},"packages/@n8n/agents/src/workspace/sandbox/run-in-sandbox.ts":{"39":[28,29,31,159,34,35],"56":[28,29,31,159,34,35]},"packages/@n8n/agents/src/workspace/sandbox/shell-command.ts":{"13":[28,29,31,159,34,35],"18":[28,29,31,159,34,35],"20":[28,29,31,159,34,35]},"packages/@n8n/agents/src/workspace/sandbox/workspace-root.ts":{"10":[28,29,31,159,34,35],"19":[28,29,31,159,34,35],"33":[28,29,31,159,34,35],"44":[28,29,31,159,34,35],"51":[28,29,31,159,34,35],"56":[28,29,31,159,34,35]},"packages/@n8n/agents/src/workspace/scoped-workspace.ts":{"22":[28,29,126,31,159,34,35],"27":[28,29,126,31,159,34,35],"51":[28,29,126,31,159,34,35],"57":[28,29,126,31,159,34,35],"61":[28,29,126,31,159,34,35],"65":[28,29,126,31,159,34,35],"69":[28,29,126,31,159,34,35],"73":[28,29,126,31,159,34,35],"77":[28,29,126,31,159,34,35],"81":[28,29,126,31,159,34,35],"85":[28,29,126,31,159,34,35],"99":[28,29,126,31,159,34,35],"100":[28,29,126,31,159,34,35],"105":[28,29,126,31,159,34,35],"110":[28,29,126,31,159,34,35],"114":[28,29,126,31,159,34,35],"118":[28,29,126,31,159,34,35],"122":[28,29,126,31,159,34,35],"126":[28,29,126,31,159,34,35],"131":[28,29,126,31,159,34,35],"136":[28,29,126,31,159,34,35],"140":[28,29,126,31,159,34,35],"144":[28,29,126,31,159,34,35],"148":[28,29,126,31,159,34,35],"152":[28,29,126,31,159,34,35],"160":[28,29,126,31,159,34,35],"168":[28,29,126,31,159,34,35],"184":[28,29,126,31,159,34,35],"188":[28,29,126,31,159,34,35],"192":[28,29,126,31,159,34,35],"196":[28,29,126,31,159,34,35],"200":[28,29,126,31,159,34,35],"204":[28,29,126,31,159,34,35],"208":[28,29,126,31,159,34,35],"214":[28,29,126,31,159,34,35],"225":[28,29,126,31,159,34,35],"229":[28,29,126,31,159,34,35],"238":[28,29,126,31,159,34,35]},"packages/@n8n/agents/src/workspace/tools/append-file.ts":{"7":[28,29,31,159,34,35],"21":[28,29,31,159,34,35]},"packages/@n8n/agents/src/workspace/tools/copy-file.ts":{"7":[28,29,31,159,34,35],"25":[28,29,31,159,34,35]},"packages/@n8n/agents/src/workspace/tools/delete-file.ts":{"7":[28,29,31,159,34,35],"25":[28,29,31,159,34,35]},"packages/@n8n/agents/src/workspace/tools/execute-command.ts":{"7":[28,29,31,159,34,35],"26":[28,29,31,159,34,35]},"packages/@n8n/agents/src/workspace/tools/file-stat.ts":{"7":[28,29,31,159,34,35],"25":[28,29,31,159,34,35]},"packages/@n8n/agents/src/workspace/tools/list-files.ts":{"7":[28,29,31,159,34,35],"29":[28,29,31,159,34,35]},"packages/@n8n/agents/src/workspace/tools/mkdir.ts":{"7":[28,29,31,159,34,35],"21":[28,29,31,159,34,35]},"packages/@n8n/agents/src/workspace/tools/move-file.ts":{"7":[28,29,31,159,34,35],"25":[28,29,31,159,34,35]},"packages/@n8n/agents/src/workspace/tools/read-file.ts":{"7":[28,29,31,159,34,35],"25":[28,29,31,159,34,35]},"packages/@n8n/agents/src/workspace/tools/read-tool-result.ts":{"114":[28,29,31,159,34,35],"124":[28,29,31,159,34,35],"129":[28,29,31,159,34,35],"159":[28,29,31,159,34,35],"194":[28,29,31,159,34,35],"207":[28,29,31,159,34,35],"235":[28,29,31,159,34,35],"256":[28,29,31,159,34,35],"293":[28,29,31,159,34,35],"314":[28,29,31,159,34,35],"343":[28,29,31,159,34,35],"372":[28,29,31,159,34,35],"379":[28,29,31,159,34,35],"383":[28,29,31,159,34,35],"393":[28,29,31,159,34,35],"397":[28,29,31,159,34,35]},"packages/@n8n/agents/src/workspace/tools/rmdir.ts":{"7":[28,29,31,159,34,35],"25":[28,29,31,159,34,35]},"packages/@n8n/agents/src/workspace/tools/str-replace-file.ts":{"45":[28,29,31,159,34,35],"52":[28,29,31,159,34,35],"58":[28,29,31,159,34,35],"65":[28,29,31,159,34,35]},"packages/@n8n/agents/src/workspace/tools/workspace-tools.ts":{"31":[28,29,31,159,34,35]},"packages/@n8n/agents/src/workspace/tools/write-file.ts":{"7":[28,29,31,159,34,35],"29":[28,29,31,159,34,35]},"packages/@n8n/agents/src/workspace/workspace.ts":{"24":[28,29,31,159,34,35],"31":[28,29,31,159,34,35],"35":[28,29,31,159,34,35],"39":[28,29,31,159,34,35],"43":[28,29,31,159,34,35],"59":[28,29,31,159,34,35],"80":[28,29,31,159,34,35],"93":[28,29,31,159,34,35],"97":[28,29,31,159,34,35],"126":[28,29,31,159,34,35]},"packages/@n8n/ai-utilities/src/agent-config/model-id.ts":{"2":[1,83,28,29,31,159,34,35],"15":[1,83,28,29,31,159,34,35]},"packages/@n8n/ai-utilities/src/json-schema/index.ts":{"6":[1,2,83,28,29,31,159,34,35,110,38,221],"7":[1,2,83,28,29,31,159,34,35,110,38,221],"15":[1,2,83,28,29,31,159,34,35,110,38,221]},"packages/@n8n/ai-utilities/src/node-catalog/index.ts":{"14":[28,29,31,159,34,35,127,110,38],"34":[28,29,31,159,34,35,127,110,38],"84":[28,29,31,159,34,35,127,110,38]},"packages/@n8n/ai-utilities/src/node-catalog/suggested.ts":{"25":[28,29,31,159,34,35,127,110,38],"34":[28,29,31,159,34,35,127,110,38],"59":[28,29,31,159,34,35,127,110,38],"93":[28,29,31,159,34,35,127,110,38]},"packages/@n8n/api-types/src/schemas/agent-run-reducer.ts":{"32":[86,124,28,29,30,92,31,34,35],"69":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","82":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","99":"b:AAAA8AwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","108":"b:AAAA8AwAAAAAAEAQAAAA0AAAAAADAAAAAAAAAAA=","117":[86,124,28,29,30,92,31,34,35],"129":"b:AAAA8AwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","141":[86,124,28,29,30,92,126,31,34,35,127],"146":"b:AAAA8AwAAAAAAEAQAAAA0AAAAAADAAAAAAAAAAA=","164":[86,124,28,29,30,92,126,31,34,161,35,127],"182":[86,124,28,29,30,92,31,34,161,35],"183":[86,124,28,29,30,92,31,34,35],"188":[28,29,30,92,31,34,35],"203":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","228":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","526":[86,124],"527":[28,29,30,92,31,34,35],"636":[86,124,28,29,92,126,160,161,35,127],"637":[28,29,30,92,31,34,35],"678":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","689":[86,124,28,29,30,92,31,34,161,35],"704":[86,124,28,29,30,92,31,34,161,35],"718":[86,124,28,29,30,92,31,34,161,35],"729":[86,124,28,29,30,92,31,34,35],"732":[86,124,28,29,30,92,31,34,35],"735":[86,124,28,29,30,92,31,34,161,35]},"packages/@n8n/api-types/src/schemas/timezone.schema.ts":{"3":[86,18,19,20,124,28,29,31,159,34,35]},"packages/@n8n/backend-common/src/modules/module-registry.ts":{"21":"b:AAAc+E8AAAAIAAAAAEAAAAAAAAAIAAAAAAAAAAA=","24":"b:AAAc+E8AAAAIAAAAAEAAAAAAAAAIAAAAAAAAAAA=","37":"b:AAAc+E8AAAAIAAAAAEAAAAAAAAAIAAAAAAAAAAA=","94":"b:AAAc+E8AAAAIAAAAAEAAAAAAAAAIAAAAAAAAAAA=","98":"b:AAAc+E8AAAAIAAAAAEAAAAAAAAAIAAAAAAAAAAA=","101":"b:AAAc+E8AAAAIAAAAAEAAAAAAAAAIAAAAAAAAAAA=","107":"b:AAAc+E8AAAAIAAAAAEAAAAAAAAAIAAAAAAAAAAA=","118":"b:AAAc+E8AAAAIAAAAAEAAAAAAAAAIAAAAAAAAAAA=","203":"b:AAAc+E8AAAAIAAAAAEAAAAAAAAAIAAAAAAAAAAA=","251":"b:AAAc+E8AAAAIAAAAAEAAAAAAAAAIAAAAAAAAAAA=","270":"b:AAAc+E8AAAAIAAAAAEAAAAAAAAAIAAAAAAAAAAA=","286":"b:AAAc+E8AAAAIAAAAAEAAAAAAAAAIAAAAAAAAAAA=","290":"b:AAAc+E8AAAAIAAAAAEAAAAAAAAAIAAAAAAAAAAA="},"packages/@n8n/db/src/repositories/ai-builder-temporary-workflow.repository.ts":{"9":[28,29,126,31,159,34,35],"13":[28,29,126,31,159,34,35],"23":[28,29,126,31,159,34,35],"27":[28,29,126,31,159,34,35],"34":[28,29,126,31,159,34,35]},"packages/@n8n/db/src/repositories/instance-credential-assignment.repository.ts":{"11":[83,16,28,29,30,31,32,33,34,35],"15":[83,16,28,29,30,31,32,33,34,35],"29":[83,16,28,29,30,31,32,33,34,35],"54":[83,16,28,29,30,31,32,33,34,35],"55":[83,16,28,29,30,31,32,33,34,35],"64":[83,16,28,29,30,31,32,33,34,35],"69":[83,16,28,29,30,31,32,33,34,35],"78":[83,16,28,29,30,31,32,33,34,35],"84":[83,16,28,29,30,31,32,33,34,35],"87":[83,16,28,29,30,31,32,33,34,35],"102":[83,16,28,29,30,31,32,33,34,35]},"packages/@n8n/db/src/repositories/settings.repository.ts":{"12":"b:AJAg+A+EviEBAAhAAImAAAAACAAAEAAAAAAwoAA=","16":"b:AJAg+A+EviEBAAhAAImAAAAACAAAEAAAAAAwoAA=","21":"b:AJAg+A+EviEBAAhAAImAAAAACAAAEAAAAAAwoAA=","25":"b:AJAg+A+EviEBAAhAAImAAAAACAAAEAAAAAAwoAA=","46":"b:AJAg+A+EviEBAAhAAImAAAAACAAAEAAAAAAwoAA=","61":"b:AJAg+A+EviEBAAhAAImAAAAACAAAEAAAAAAwoAA=","78":"b:AJAg+A+EviEBAAhAAImAAAAACAAAEAAAAAAwoAA=","90":"b:AJAg+A+EviEBAAhAAImAAAAACAAAEAAAAAAwoAA=","94":"b:AJAg+A+EviEBAAhAAImAAAAACAAAEAAAAAAwoAA="},"packages/@n8n/db/src/services/db-lock.service.ts":{"14":[28,29,30,31,32,33,34,35],"53":[28,29,30,31,32,33,34,35],"106":[28,29,30,31,32,33,34,35],"129":[28,29,30,31,32,33,34,35],"138":[28,29,30,31,32,33,34,35],"145":[28,29,30,31,32,33,34,35],"179":[28,29,30,31,32,33,34,35],"184":[28,29,30,31,32,33,34,35],"197":[28,29,30,31,32,33,34,35],"205":[28,29,30,31,32,33,34,35],"211":[28,29,30,31,32,33,34,35],"232":[28,29,30,31,32,33,34,35],"253":[28,29,30,31,32,33,34,35],"256":[28,29,30,31,32,33,34,35],"264":[28,29,30,31,32,33,34,35],"287":[28,29,30,31,32,33,34,35],"309":[28,29,30,31,32,33,34,35],"310":[28,29,30,31,32,33,34,35],"329":[28,29,30,31,32,33,34,35]},"packages/@n8n/db/src/utils/is-string-array.ts":{"1":"b:AAAhkwy4AIgggAInCAAAQgAAgAAIAAAABAgACQA=","2":"b:AAAhkwy4AIgggAInCAAAQgAAgAAIAAAABAgACQA="},"packages/@n8n/decorators/src/module/module-metadata.ts":{"17":"b:AAAc+E8AAAAIAAAAAEAAAAAAAAAIAAAAAAAAAAA=","20":"b:AAAc+E8AAAAIAAAAAEAAAAAAAAAIAAAAAAAAAAA=","24":"b:AAAc+E8AAAAIAAAAAEAAAAAAAAAIAAAAAAAAAAA=","28":"b:AAAc+E8AAAAIAAAAAEAAAAAAAAAIAAAAAAAAAAA=","32":"b:AAAc+E8AAAAIAAAAAEAAAAAAAAAIAAAAAAAAAAA=","33":"b:AAAc+E8AAAAIAAAAAEAAAAAAAAAIAAAAAAAAAAA="},"packages/@n8n/errors/src/response-errors/bad-request.error.ts":{"4":[12,13,28,29,31,159,34,35,227,80],"8":[12,13,28,29,31,159,34,35,227,80]},"packages/@n8n/instance-ai/src/agent/apply-agent-thinking.ts":{"11":[28,29,31,159,34,35],"17":[28,29,31,159,34,35],"26":[28,29,31,159,34,35],"28":[28,29,31,159,34,35],"32":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/agent/computer-use-prompt.ts":{"98":[28,29,31,159,34,35],"105":[28,29,31,159,34,35],"110":[28,29,31,159,34,35],"111":[28,29,31,159,34,35],"117":[28,29,31,159,34,35],"120":[28,29,31,159,34,35],"128":[28,29,31,159,34,35],"129":[28,29,31,159,34,35],"132":[28,29,31,159,34,35],"133":[28,29,31,159,34,35],"134":[28,29,31,159,34,35],"135":[28,29,31,159,34,35],"138":[28,29,31,159,34,35],"154":[28,29,31,159,34,35],"164":[28,29,31,159,34,35],"181":[28,29,31,159,34,35],"188":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/agent/instance-agent.ts":{"42":[28,29,31,159,34,35],"48":[28,29,31,159,34,35],"49":[28,29,31,159,34,35],"61":[28,29,31,159,34,35],"82":[28,29,31,159,34,35],"124":[28,29,31,159,34,35],"134":[28,29,31,159,34,35],"142":[28,29,31,159,34,35],"200":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/agent/mcp-tool-name-validation.ts":{"8":[28,29,31,159,34,35],"20":[28,29,31,159,34,35],"29":[28,29,31,159,34,35],"36":[28,29,31,159,34,35],"47":[28,29,31,159,34,35],"55":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/agent/model-config-identity.ts":{"4":[28,29,31,159,34,35],"8":[28,29,31,159,34,35],"13":[28,29,31,159,34,35],"18":[28,29,31,159,34,35],"23":[28,29,31,159,34,35],"35":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/agent/runtime-workspace.ts":{"10":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/agent/sanitize-mcp-descriptions.ts":{"71":[28,29,31,159,34,35],"107":[28,29,31,159,34,35],"114":[28,29,31,159,34,35],"116":[28,29,31,159,34,35],"125":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/agent/sanitize-mcp-schemas.ts":{"55":[28,29,31,159,34,35],"127":[28,29,31,159,34,35],"156":[28,29,31,159,34,35],"165":[28,29,31,159,34,35],"172":[28,29,31,159,34,35],"179":[28,29,31,159,34,35],"269":[28,29,31,159,34,35],"292":[28,29,31,159,34,35],"311":[28,29,31,159,34,35],"329":[28,29,31,159,34,35],"346":[28,29,31,159,34,35],"363":[28,29,31,159,34,35],"382":[28,29,31,159,34,35],"418":[28,29,31,159,34,35],"419":[28,29,31,159,34,35],"422":[28,29,31,159,34,35],"425":[28,29,31,159,34,35],"432":[28,29,31,159,34,35],"446":[28,29,31,159,34,35],"460":[28,29,31,159,34,35],"461":[28,29,31,159,34,35],"466":[28,29,31,159,34,35],"475":[28,29,31,159,34,35],"483":[28,29,31,159,34,35],"497":[28,29,31,159,34,35],"531":[28,29,31,159,34,35],"532":[28,29,31,159,34,35],"556":[28,29,31,159,34,35],"571":[28,29,31,159,34,35],"573":[28,29,31,159,34,35],"592":[28,29,31,159,34,35],"608":[28,29,31,159,34,35],"629":[28,29,31,159,34,35],"633":[28,29,31,159,34,35],"654":[28,29,31,159,34,35],"806":[28,29,31,159,34,35],"827":[28,29,31,159,34,35],"846":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/agent/shared-prompts.ts":{"22":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/agent/system-prompt.ts":{"33":[28,29,31,159,34,35],"42":[28,29,31,159,34,35],"81":[28,29,31,159,34,35],"130":[28,29,31,159,34,35],"150":[28,29,31,159,34,35],"157":[28,29,31,159,34,35],"171":[28,29,31,159,34,35],"178":[28,29,31,159,34,35],"186":[28,29,31,159,34,35],"190":[28,29,31,159,34,35],"212":[28,29,31,159,34,35],"232":[28,29,31,159,34,35],"244":[28,29,31,159,34,35],"245":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/domain-access/domain-access-tracker.ts":{"60":[28,29,31,159,34,35],"74":[28,29,31,159,34,35],"85":[28,29,31,159,34,35],"90":[28,29,31,159,34,35],"95":[28,29,31,159,34,35],"99":[28,29,31,159,34,35],"108":[28,29,31,159,34,35],"113":[28,29,31,159,34,35],"119":[28,29,31,159,34,35],"124":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/domain-access/domain-gating.ts":{"69":[28,29,31,159,34,35],"122":[28,29,31,159,34,35],"161":[28,29,31,159,34,35],"203":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/domain-access/index.ts":{"1":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/error-formatting.ts":{"10":[28,29,31,159,34,35],"21":[28,29,31,159,34,35],"36":[28,29,31,159,34,35],"53":[28,29,31,159,34,35],"54":[28,29,31,159,34,35],"57":[28,29,31,159,34,35],"71":[28,29,31,159,34,35],"82":[28,29,31,159,34,35],"91":[28,29,31,159,34,35],"98":[28,29,31,159,34,35],"102":[28,29,31,159,34,35],"109":[28,29,31,159,34,35],"113":[28,29,31,159,34,35],"138":[28,29,31,159,34,35],"152":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/errors/index.ts":{"3":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/errors/workflow-snapshot-changed.error.ts":{"8":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/index.ts":{"51":[28,29,30,92,126,31,159,160,34,161,35,228],"53":[28,29,30,92,126,31,159,160,34,161,35,228],"56":[28,29,30,92,126,31,159,160,34,161,35,228],"57":[28,29,30,92,126,31,159,160,34,161,35,228],"62":[28,29,30,92,126,31,159,160,34,161,35,228],"64":[28,29,30,92,126,31,159,160,34,161,35,228],"71":[28,29,30,92,126,31,159,160,34,161,35,228],"81":[28,29,30,92,126,31,159,160,34,161,35,228],"90":[28,29,30,92,126,31,159,160,34,161,35,228],"93":[28,29,30,92,126,31,159,160,34,161,35,228],"96":[28,29,30,92,126,31,159,160,34,161,35,228],"99":[28,29,30,92,126,31,159,160,34,161,35,228],"102":[28,29,30,92,126,31,159,160,34,161,35,228],"105":[28,29,30,92,126,31,159,160,34,161,35,228],"107":[28,29,30,92,126,31,159,160,34,161,35,228],"109":[28,29,30,92,126,31,159,160,34,161,35,228],"112":[28,29,30,92,126,31,159,160,34,161,35,228],"115":[28,29,30,92,126,31,159,160,34,161,35,228],"118":[28,29,30,92,126,31,159,160,34,161,35,228],"120":[28,29,30,92,126,31,159,160,34,161,35,228],"122":[28,29,30,92,126,31,159,160,34,161,35,228],"125":[28,29,30,92,126,31,159,160,34,161,35,228],"127":[28,29,30,92,126,31,159,160,34,161,35,228],"128":[28,29,30,92,126,31,159,160,34,161,35,228],"130":[28,29,30,92,126,31,159,160,34,161,35,228],"132":[28,29,30,92,126,31,159,160,34,161,35,228],"135":[28,29,30,92,126,31,159,160,34,161,35,228],"138":[28,29,30,92,126,31,159,160,34,161,35,228],"142":[28,29,30,92,126,31,159,160,34,161,35,228],"145":[28,29,30,92,126,31,159,160,34,161,35,228],"148":[28,29,30,92,126,31,159,160,34,161,35,228],"150":[28,29,30,92,126,31,159,160,34,161,35,228],"151":[28,29,30,92,126,31,159,160,34,161,35,228],"152":[28,29,30,92,126,31,159,160,34,161,35,228],"154":[28,29,30,92,126,31,159,160,34,161,35,228],"157":[28,29,30,92,126,31,159,160,34,161,35,228],"160":[28,29,30,92,126,31,159,160,34,161,35,228],"163":[28,29,30,92,126,31,159,160,34,161,35,228],"166":[28,29,30,92,126,31,159,160,34,161,35,228],"169":[28,29,30,92,126,31,159,160,34,161,35,228],"172":[28,29,30,92,126,31,159,160,34,161,35,228],"175":[28,29,30,92,126,31,159,160,34,161,35,228],"178":[28,29,30,92,126,31,159,160,34,161,35,228],"181":[28,29,30,92,126,31,159,160,34,161,35,228],"184":[28,29,30,92,126,31,159,160,34,161,35,228],"186":[28,29,30,92,126,31,159,160,34,161,35,228],"188":[28,29,30,92,126,31,159,160,34,161,35,228],"191":[28,29,30,92,126,31,159,160,34,161,35,228],"194":[28,29,30,92,126,31,159,160,34,161,35,228],"197":[28,29,30,92,126,31,159,160,34,161,35,228],"200":[28,29,30,92,126,31,159,160,34,161,35,228],"205":[28,29,30,92,126,31,159,160,34,161,35,228],"219":[28,29,30,92,126,31,159,160,34,161,35,228],"220":[28,29,30,92,126,31,159,160,34,161,35,228],"248":[28,29,30,92,126,31,159,160,34,161,35,228],"252":[28,29,30,92,126,31,159,160,34,161,35,228],"260":[28,29,30,92,126,31,159,160,34,161,35,228],"271":[28,29,30,92,126,31,159,160,34,161,35,228],"274":[28,29,30,92,126,31,159,160,34,161,35,228],"276":[28,29,30,92,126,31,159,160,34,161,35,228],"279":[28,29,30,92,126,31,159,160,34,161,35,228],"282":[28,29,30,92,126,31,159,160,34,161,35,228],"285":[28,29,30,92,126,31,159,160,34,161,35,228],"289":[28,29,30,92,126,31,159,160,34,161,35,228],"293":[28,29,30,92,126,31,159,160,34,161,35,228],"297":[28,29,30,92,126,31,159,160,34,161,35,228],"300":[28,29,30,92,126,31,159,160,34,161,35,228],"304":[28,29,30,92,126,31,159,160,34,161,35,228],"307":[28,29,30,92,126,31,159,160,34,161,35,228],"311":[28,29,30,92,126,31,159,160,34,161,35,228],"315":[28,29,30,92,126,31,159,160,34,161,35,228],"319":[28,29,30,92,126,31,159,160,34,161,35,228],"332":[28,29,30,92,126,31,159,160,34,161,35,228],"334":[28,29,30,92,126,31,159,160,34,161,35,228],"336":[28,29,30,92,126,31,159,160,34,161,35,228],"338":[28,29,30,92,126,31,159,160,34,161,35,228],"342":[28,29,30,92,126,31,159,160,34,161,35,228],"344":[28,29,30,92,126,31,159,160,34,161,35,228],"347":[28,29,30,92,126,31,159,160,34,161,35,228],"368":[28,29,30,92,126,31,159,160,34,161,35,228],"372":[28,29,30,92,126,31,159,160,34,161,35,228],"375":[28,29,30,92,126,31,159,160,34,161,35,228],"377":[28,29,30,92,126,31,159,160,34,161,35,228],"381":[28,29,30,92,126,31,159,160,34,161,35,228],"384":[28,29,30,92,126,31,159,160,34,161,35,228],"386":[28,29,30,92,126,31,159,160,34,161,35,228],"391":[28,29,30,92,126,31,159,160,34,161,35,228],"395":[28,29,30,92,126,31,159,160,34,161,35,228],"399":[28,29,30,92,126,31,159,160,34,161,35,228],"403":[28,29,30,92,126,31,159,160,34,161,35,228],"405":[28,29,30,92,126,31,159,160,34,161,35,228],"408":[28,29,30,92,126,31,159,160,34,161,35,228],"411":[28,29,30,92,126,31,159,160,34,161,35,228],"415":[28,29,30,92,126,31,159,160,34,161,35,228],"428":[28,29,30,92,126,31,159,160,34,161,35,228],"431":[28,29,30,92,126,31,159,160,34,161,35,228],"435":[28,29,30,92,126,31,159,160,34,161,35,228],"438":[28,29,30,92,126,31,159,160,34,161,35,228],"441":[28,29,30,92,126,31,159,160,34,161,35,228],"444":[28,29,30,92,126,31,159,160,34,161,35,228],"447":[28,29,30,92,126,31,159,160,34,161,35,228],"450":[28,29,30,92,126,31,159,160,34,161,35,228],"453":[28,29,30,92,126,31,159,160,34,161,35,228],"456":[28,29,30,92,126,31,159,160,34,161,35,228],"458":[28,29,30,92,126,31,159,160,34,161,35,228],"461":[28,29,30,92,126,31,159,160,34,161,35,228],"463":[28,29,30,92,126,31,159,160,34,161,35,228],"466":[28,29,30,92,126,31,159,160,34,161,35,228],"468":[28,29,30,92,126,31,159,160,34,161,35,228],"469":[28,29,30,92,126,31,159,160,34,161,35,228],"472":[28,29,30,92,126,31,159,160,34,161,35,228],"476":[28,29,30,92,126,31,159,160,34,161,35,228],"480":[28,29,30,92,126,31,159,160,34,161,35,228],"484":[28,29,30,92,126,31,159,160,34,161,35,228],"486":[28,29,30,92,126,31,159,160,34,161,35,228],"487":[28,29,30,92,126,31,159,160,34,161,35,228],"490":[28,29,30,92,126,31,159,160,34,161,35,228],"494":[28,29,30,92,126,31,159,160,34,161,35,228],"496":[28,29,30,92,126,31,159,160,34,161,35,228],"499":[28,29,30,92,126,31,159,160,34,161,35,228],"501":[28,29,30,92,126,31,159,160,34,161,35,228],"502":[28,29,30,92,126,31,159,160,34,161,35,228],"503":[28,29,30,92,126,31,159,160,34,161,35,228],"506":[28,29,30,92,126,31,159,160,34,161,35,228],"510":[28,29,30,92,126,31,159,160,34,161,35,228],"513":[28,29,30,92,126,31,159,160,34,161,35,228],"517":[28,29,30,92,126,31,159,160,34,161,35,228],"520":[28,29,30,92,126,31,159,160,34,161,35,228],"524":[28,29,30,92,126,31,159,160,34,161,35,228],"526":[28,29,30,92,126,31,159,160,34,161,35,228],"532":[28,29,30,92,126,31,159,160,34,161,35,228],"535":[28,29,30,92,126,31,159,160,34,161,35,228],"540":[28,29,30,92,126,31,159,160,34,161,35,228],"545":[28,29,30,92,126,31,159,160,34,161,35,228],"547":[28,29,30,92,126,31,159,160,34,161,35,228],"558":[28,29,30,92,126,31,159,160,34,161,35,228],"560":[28,29,30,92,126,31,159,160,34,161,35,228],"585":[28,29,30,92,126,31,159,160,34,161,35,228],"592":[28,29,30,92,126,31,159,160,34,161,35,228],"606":[28,29,30,92,126,31,159,160,34,161,35,228],"608":[28,29,30,92,126,31,159,160,34,161,35,228],"610":[28,29,30,92,126,31,159,160,34,161,35,228],"613":[28,29,30,92,126,31,159,160,34,161,35,228],"615":[28,29,30,92,126,31,159,160,34,161,35,228],"618":[28,29,30,92,126,31,159,160,34,161,35,228],"621":[28,29,30,92,126,31,159,160,34,161,35,228],"625":[28,29,30,92,126,31,159,160,34,161,35,228],"640":[28,29,30,92,126,31,159,160,34,161,35,228],"643":[28,29,30,92,126,31,159,160,34,161,35,228],"645":[28,29,30,92,126,31,159,160,34,161,35,228],"647":[28,29,30,92,126,31,159,160,34,161,35,228],"649":[28,29,30,92,126,31,159,160,34,161,35,228],"651":[28,29,30,92,126,31,159,160,34,161,35,228],"653":[28,29,30,92,126,31,159,160,34,161,35,228],"672":[28,29,30,92,126,31,159,160,34,161,35,228],"676":[28,29,30,92,126,31,159,160,34,161,35,228],"795":[28,29,30,92,126,31,159,160,34,161,35,228],"804":[28,29,30,92,126,31,159,160,34,161,35,228],"807":[28,29,30,92,126,31,159,160,34,161,35,228],"809":[28,29,30,92,126,31,159,160,34,161,35,228],"811":[28,29,30,92,126,31,159,160,34,161,35,228],"820":[28,29,30,92,126,31,159,160,34,161,35,228],"822":[28,29,30,92,126,31,159,160,34,161,35,228],"824":[28,29,30,92,126,31,159,160,34,161,35,228],"826":[28,29,30,92,126,31,159,160,34,161,35,228],"829":[28,29,30,92,126,31,159,160,34,161,35,228],"831":[28,29,30,92,126,31,159,160,34,161,35,228],"834":[28,29,30,92,126,31,159,160,34,161,35,228]},"packages/@n8n/instance-ai/src/knowledge-base/build-templates-index.ts":{"36":[28,29,126,31,159,34,35],"40":[28,29,126,31,159,34,35],"41":[28,29,126,31,159,34,35],"49":[28,29,126,31,159,34,35],"56":[28,29,126,31,159,34,35],"60":[28,29,126,31,159,34,35],"64":[28,29,126,31,159,34,35],"87":[28,29,126,31,159,34,35],"108":[28,29,126,31,159,34,35],"118":[28,29,126,31,159,34,35],"126":[28,29,126,31,159,34,35],"129":[28,29,126,31,159,34,35],"141":[28,29,126,31,159,34,35],"151":[28,29,126,31,159,34,35],"152":[28,29,126,31,159,34,35],"161":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/knowledge-base/extract-builder-templates-archive.ts":{"8":[28,29,126,31,159,34,35],"13":[28,29,126,31,159,34,35],"14":[28,29,126,31,159,34,35],"17":[28,29,126,31,159,34,35],"23":[28,29,126,31,159,34,35],"32":[28,29,126,31,159,34,35],"73":[28,29,126,31,159,34,35],"86":[28,29,126,31,159,34,35],"98":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/knowledge-base/materialize-knowledge-base.ts":{"107":[28,29,126,31,159,34,35],"186":[28,29,126,31,159,34,35],"217":[28,29,126,31,159,34,35],"218":[28,29,126,31,159,34,35],"230":[28,29,126,31,159,34,35],"305":[28,29,126,31,159,34,35],"326":[28,29,126,31,159,34,35],"332":[28,29,126,31,159,34,35],"336":[28,29,126,31,159,34,35],"342":[28,29,126,31,159,34,35],"346":[28,29,126,31,159,34,35],"352":[28,29,126,31,159,34,35],"353":[28,29,126,31,159,34,35],"354":[28,29,126,31,159,34,35],"356":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/mcp/connected-mcp-services.ts":{"6":[28,29,31,159,34,35],"19":[28,29,31,159,34,35],"20":[28,29,31,159,34,35],"21":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/mcp/mcp-client-manager.ts":{"32":[28,29,31,159,34,35],"78":[28,29,31,159,34,35],"88":[28,29,31,159,34,35],"91":[28,29,31,159,34,35],"114":[28,29,31,159,34,35],"118":[28,29,31,159,34,35],"119":[28,29,31,159,34,35],"133":[28,29,31,159,34,35],"134":[28,29,31,159,34,35],"145":[28,29,31,159,34,35],"146":[28,29,31,159,34,35],"155":[28,29,31,159,34,35],"160":[28,29,31,159,34,35],"185":[28,29,31,159,34,35],"190":[28,29,31,159,34,35],"210":[28,29,31,159,34,35],"223":[28,29,31,159,34,35],"228":[28,29,31,159,34,35],"231":[28,29,31,159,34,35],"243":[28,29,31,159,34,35],"257":[28,29,31,159,34,35],"285":[28,29,31,159,34,35],"306":[28,29,31,159,34,35],"307":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/memory/title-utils.ts":{"13":[28,29,31,159,34,35],"21":[28,29,31,159,34,35],"35":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/planned-tasks/planned-task-service.ts":{"20":[28,29,31,159,34,35],"26":[28,29,31,159,34,35],"27":[28,29,31,159,34,35],"30":[28,29,31,159,34,35],"35":[28,29,31,159,34,35],"36":[28,29,31,159,34,35],"50":[28,29,31,159,34,35],"63":[28,29,31,159,34,35],"83":[28,29,31,159,34,35],"87":[28,29,31,159,34,35],"104":[28,29,31,159,34,35],"109":[28,29,31,159,34,35],"118":[28,29,31,159,34,35],"120":[28,29,31,159,34,35],"139":[28,29,31,159,34,35],"156":[28,29,31,159,34,35],"157":[28,29,31,159,34,35],"172":[28,29,31,159,34,35],"173":[28,29,31,159,34,35],"181":[28,29,31,159,34,35],"185":[28,29,31,159,34,35],"190":[28,29,31,159,34,35],"191":[28,29,31,159,34,35],"202":[28,29,31,159,34,35],"207":[28,29,31,159,34,35],"208":[28,29,31,159,34,35],"219":[28,29,31,159,34,35],"224":[28,29,31,159,34,35],"225":[28,29,31,159,34,35],"232":[28,29,31,159,34,35],"261":[28,29,31,159,34,35],"268":[28,29,31,159,34,35],"269":[28,29,31,159,34,35],"283":[28,29,31,159,34,35],"311":[28,29,31,159,34,35],"318":[28,29,31,159,34,35],"325":[28,29,31,159,34,35],"332":[28,29,31,159,34,35],"333":[28,29,31,159,34,35],"347":[28,29,31,159,34,35],"361":[28,29,31,159,34,35],"374":[28,29,31,159,34,35],"375":[28,29,31,159,34,35],"393":[28,29,31,159,34,35],"422":[28,29,31,159,34,35],"427":[28,29,31,159,34,35],"428":[28,29,31,159,34,35],"437":[28,29,31,159,34,35],"448":[28,29,31,159,34,35],"454":[28,29,31,159,34,35],"478":[28,29,31,159,34,35],"501":[28,29,31,159,34,35],"504":[28,29,31,159,34,35],"514":[28,29,31,159,34,35],"520":[28,29,31,159,34,35],"534":[28,29,31,159,34,35],"549":[28,29,31,159,34,35],"550":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/prompts/prompt-profiles.ts":{"58":[28,29,31,159,34,35],"59":[28,29,31,159,34,35],"64":[28,29,31,159,34,35],"65":[28,29,31,159,34,35],"71":[28,29,31,159,34,35],"75":[28,29,31,159,34,35],"81":[28,29,31,159,34,35],"83":[28,29,31,159,34,35],"88":[28,29,31,159,34,35],"95":[28,29,31,159,34,35],"106":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/prompts/skill-variants.ts":{"20":[28,29,31,159,34,35],"47":[28,29,31,159,34,35],"54":[28,29,31,159,34,35],"55":[28,29,31,159,34,35],"84":[28,29,31,159,34,35],"85":[28,29,31,159,34,35],"88":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/runtime/confirmation-payload.ts":{"28":[126,35],"79":[126,35]},"packages/@n8n/instance-ai/src/runtime/liveness-policy.ts":{"41":[28,126,35],"69":[28,126,35],"71":[28,126,35],"72":[28,126,35],"75":[28,126,35],"106":[28,126,35]},"packages/@n8n/instance-ai/src/runtime/memory-task-registry.ts":{"11":[28,29,30,92,31,34,35],"43":[28,29,30,92,31,34,35],"47":[28,29,30,92,31,34,35]},"packages/@n8n/instance-ai/src/runtime/orchestrator-run-control.ts":{"20":[28,29,126,31,159,34,35],"26":[28,29,126,31,159,34,35],"29":[28,29,126,31,159,34,35],"32":[28,29,126,31,159,34,35],"38":[28,29,126,31,159,34,35],"44":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/runtime/resumable-stream-executor.ts":{"92":[28,29,126,31,159,34,35],"100":[28,29,126,31,159,34,35],"108":[28,29,126,31,159,34,35],"112":[28,29,126,31,159,34,35],"116":[28,29,126,31,159,34,35],"126":[28,29,126,31,159,34,35],"136":[28,29,126,31,159,34,35],"168":[28,29,126,31,159,34,35],"181":[28,29,126,31,159,34,35],"199":[28,29,126,31,159,34,35],"219":[28,29,126,31,159,34,35],"253":[28,29,126,31,159,34,35],"317":[28,29,126,31,159,34,35],"487":[28,29,126,31,159,34,35],"588":[28,29,126,31,159,34,35],"603":[28,29,126,31,159,34,35],"613":[28,29,126,31,159,34,35],"617":[28,29,126,31,159,34,35],"632":[28,29,126,31,159,34,35],"633":[28,29,126,31,159,34,35],"654":[28,29,126,31,159,34,35],"662":[28,29,126,31,159,34,35],"673":[28,29,126,31,159,34,35],"687":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/runtime/stream-runner.ts":{"47":[28,29,126,31,159,34,35],"59":[28,29,126,31,159,34,35],"71":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/runtime/terminal-response-guard.ts":{"48":[28,29,126,31,159,34,35],"52":[28,29,126,31,159,34,35],"64":[28,29,126,31,159,34,35],"74":[28,29,126,31,159,34,35],"76":[28,29,126,31,159,34,35],"177":[28,29,126,31,159,34,35],"219":[28,29,126,31,159,34,35],"227":[28,29,126,31,159,34,35],"233":[28,29,126,31,159,34,35],"237":[28,29,126,31,159,34,35],"240":[28,29,126,31,159,34,35],"244":[28,29,126,31,159,34,35],"246":[28,29,126,31,159,34,35],"251":[28,29,126,31,159,34,35],"256":[28,29,126,31,159,34,35],"262":[28,29,126,31,159,34,35],"282":[28,29,126,31,159,34,35],"303":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/skills/materialize-runtime-skills.ts":{"100":[28,29,126,31,159,160,34,35],"104":[28,29,126,31,159,160,34,35],"113":[28,29,126,31,159,160,34,35],"131":[28,29,126,31,159,160,34,35],"135":[28,29,126,31,159,160,34,35],"150":[28,29,126,31,159,160,34,35],"169":[28,29,126,31,159,160,34,35],"173":[28,29,126,31,159,160,34,35],"206":[28,29,126,31,159,160,34,35],"218":[28,29,126,31,159,160,34,35],"221":[28,29,126,31,159,160,34,35],"230":[28,29,126,31,159,160,34,35],"233":[28,29,126,31,159,160,34,35],"241":[28,29,126,31,159,160,34,35],"244":[28,29,126,31,159,160,34,35],"249":[28,29,126,31,159,160,34,35],"261":[28,29,126,31,159,160,34,35],"279":[28,29,126,31,159,160,34,35],"314":[28,29,126,31,159,160,34,35],"322":[28,29,126,31,159,160,34,35],"338":[28,29,126,31,159,160,34,35],"350":[28,29,126,31,159,160,34,35],"369":[28,29,126,31,159,160,34,35],"391":[28,29,126,31,159,160,34,35],"420":[28,29,126,31,159,160,34,35],"428":[28,29,126,31,159,160,34,35],"439":[28,29,126,31,159,160,34,35],"440":[28,29,126,31,159,160,34,35],"443":[28,29,126,31,159,160,34,35],"460":[28,29,126,31,159,160,34,35],"471":[28,29,126,31,159,160,34,35],"473":[28,29,126,31,159,160,34,35],"491":[28,29,126,31,159,160,34,35],"494":[28,29,126,31,159,160,34,35],"500":[28,29,126,31,159,160,34,35],"505":[28,29,126,31,159,160,34,35],"539":[28,29,126,31,159,160,34,35],"541":[28,29,126,31,159,160,34,35],"598":[28,29,126,31,159,160,34,35],"609":[28,29,126,31,159,160,34,35],"613":[28,29,126,31,159,160,34,35],"621":[28,29,126,31,159,160,34,35],"629":[28,29,126,31,159,160,34,35],"636":[28,29,126,31,159,160,34,35],"638":[28,29,126,31,159,160,34,35],"650":[28,29,126,31,159,160,34,35],"664":[28,29,126,31,159,160,34,35],"667":[28,29,126,31,159,160,34,35],"670":[28,29,126,31,159,160,34,35],"678":[28,29,126,31,159,160,34,35],"681":[28,29,126,31,159,160,34,35],"691":[28,29,126,31,159,160,34,35],"699":[28,29,126,31,159,160,34,35]},"packages/@n8n/instance-ai/src/skills/runtime-skills.ts":{"30":[28,29,31,159,34,35],"32":[28,29,31,159,34,35],"37":[28,29,31,159,34,35],"45":[28,29,31,159,34,35],"51":[28,29,31,159,34,35],"64":[28,29,31,159,34,35],"76":[28,29,31,159,34,35],"84":[28,29,31,159,34,35],"87":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/skills/skill-gates.ts":{"27":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/storage/index.ts":{"2":[28,29,30,31,159,34,35],"11":[28,29,30,31,159,34,35]},"packages/@n8n/instance-ai/src/storage/iteration-log.ts":{"30":[28,29,30,31,34,35],"33":[28,29,30,31,34,35]},"packages/@n8n/instance-ai/src/storage/planned-task-storage.ts":{"38":[28,29,30,31,159,34,35],"44":[28,29,30,31,159,34,35],"46":[28,29,30,31,159,34,35],"52":[28,29,30,31,159,34,35],"55":[28,29,30,31,159,34,35],"68":[28,29,30,31,159,34,35],"76":[28,29,30,31,159,34,35],"96":[28,29,30,31,159,34,35],"99":[28,29,30,31,159,34,35]},"packages/@n8n/instance-ai/src/storage/terminal-outcome-storage.ts":{"26":[28,29,30,31,34,35],"28":[28,29,30,31,34,35],"31":[28,29,30,31,34,35],"46":[28,29,30,31,34,35],"49":[28,29,30,31,34,35],"70":[28,29,30,31,34,35],"73":[28,29,30,31,34,35],"77":[28,29,30,31,34,35]},"packages/@n8n/instance-ai/src/storage/thread-iteration-log-storage.ts":{"12":[28,29,30,31,34,35],"14":[28,29,30,31,34,35],"17":[28,29,30,31,34,35],"34":[28,29,30,31,34,35],"42":[28,29,30,31,34,35],"45":[28,29,30,31,34,35],"53":[28,29,30,31,34,35]},"packages/@n8n/instance-ai/src/storage/thread-patch.ts":{"21":[28,29,30,31,34,35],"30":[28,29,30,31,34,35],"37":[28,29,30,31,34,35],"44":[28,29,30,31,34,35],"53":[28,29,30,31,34,35],"64":[28,29,30,31,34,35],"90":[28,29,30,31,34,35]},"packages/@n8n/instance-ai/src/storage/thread-task-storage.ts":{"10":[28,29,30,31,159,34,35],"12":[28,29,30,31,159,34,35],"19":[28,29,30,31,159,34,35],"22":[28,29,30,31,159,34,35]},"packages/@n8n/instance-ai/src/storage/workflow-loop-storage.ts":{"36":[28,29,30,126,31,159,34,35],"44":[28,29,30,126,31,159,34,35],"53":[28,29,30,126,31,159,34,35],"60":[28,29,30,126,31,159,34,35],"62":[28,29,30,126,31,159,34,35],"70":[28,29,30,126,31,159,34,35],"78":[28,29,30,126,31,159,34,35],"91":[28,29,30,126,31,159,34,35],"99":[28,29,30,126,31,159,34,35],"115":[28,29,30,126,31,159,34,35],"125":[28,29,30,126,31,159,34,35],"130":[28,29,30,126,31,159,34,35],"141":[28,29,30,126,31,159,34,35],"146":[28,29,30,126,31,159,34,35],"154":[28,29,30,126,31,159,34,35],"180":[28,29,30,126,31,159,34,35],"189":[28,29,30,126,31,159,34,35],"216":[28,29,30,126,31,159,34,35],"223":[28,29,30,126,31,159,34,35],"243":[28,29,30,126,31,159,34,35],"249":[28,29,30,126,31,159,34,35]},"packages/@n8n/instance-ai/src/stream/consume-with-hitl.ts":{"56":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/stream/instance-context-reach.ts":{"19":[28,29,126,31,159,34,35],"37":[28,29,126,31,159,34,35],"49":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/stream/map-chunk.ts":{"24":[28,29,126,31,159,160,34,35],"29":[28,29,126,31,159,160,34,35],"37":[28,29,126,31,159,160,34,35],"45":[28,29,126,31,159,160,34,35],"49":[28,29,126,31,159,160,34,35],"51":[28,29,126,31,159,160,34,35],"61":[28,29,126,31,159,160,34,35],"65":[28,29,126,31,159,160,34,35],"112":[28,29,126,31,159,160,34,35],"125":[28,29,126,31,159,160,34,35],"135":[28,29,126,31,159,160,34,35],"145":[28,29,126,31,159,160,34,35],"161":[28,29,126,31,159,160,34,35],"222":[28,29,126,31,159,160,34,35],"226":[28,29,126,31,159,160,34,35],"229":[28,29,126,31,159,160,34,35],"230":[28,29,126,31,159,160,34,35],"231":[28,29,126,31,159,160,34,35],"235":[28,29,126,31,159,160,34,35],"241":[28,29,126,31,159,160,34,35],"247":[28,29,126,31,159,160,34,35],"262":[28,29,126,31,159,160,34,35],"269":[28,29,126,31,159,160,34,35],"278":[28,29,126,31,159,160,34,35],"293":[28,29,126,31,159,160,34,35],"312":[28,29,126,31,159,160,34,35],"411":[28,29,126,31,159,160,34,35],"424":[28,29,126,31,159,160,34,35],"441":[28,29,126,31,159,160,34,35],"452":[28,29,126,31,159,160,34,35],"458":[28,29,126,31,159,160,34,35],"463":[28,29,126,31,159,160,34,35],"481":[28,29,126,31,159,160,34,35]},"packages/@n8n/instance-ai/src/stream/usage-accumulator.ts":{"83":[28,29,31,159,34,35],"119":[28,29,31,159,34,35],"124":[28,29,31,159,34,35],"150":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/stream/work-summary-accumulator.ts":{"31":[28,29,31,159,34,35],"57":[28,29,31,159,34,35],"115":[28,29,31,159,34,35],"116":[28,29,31,159,34,35],"120":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tool-registry.ts":{"5":[28,29,31,159,34,35],"15":[28,29,31,159,34,35],"23":[28,29,31,159,34,35],"36":[28,29,31,159,34,35],"49":[28,29,31,159,34,35],"53":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/agent-context.tool.ts":{"82":[28,29,31,159,34,35],"83":[28,29,31,159,34,35],"85":[28,29,31,159,34,35],"106":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/approval-copy.ts":{"22":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/credentials.tool.ts":{"136":[28,29,31,159,34,35],"148":[28,29,31,159,34,35],"158":[28,29,31,159,34,35],"179":[28,29,31,159,34,35],"184":[28,29,31,159,34,35],"214":[28,29,31,159,34,35],"242":[28,29,31,159,34,35],"262":[28,29,31,159,34,35],"289":[28,29,31,159,34,35],"300":[28,29,31,159,34,35],"310":[28,29,31,159,34,35],"511":[28,29,31,159,34,35],"515":[28,29,31,159,34,35],"518":[28,29,31,159,34,35],"522":[28,29,31,159,34,35],"558":[28,29,31,159,34,35],"562":[28,29,31,159,34,35],"563":[28,29,31,159,34,35],"570":[28,29,31,159,34,35],"624":[28,29,31,159,34,35],"671":[28,29,31,159,34,35],"691":[28,29,31,159,34,35],"706":[28,29,31,159,34,35],"719":[28,29,31,159,34,35],"751":[28,29,31,159,34,35],"758":[28,29,31,159,34,35],"775":[28,29,31,159,34,35],"793":[28,29,31,159,34,35],"800":[28,29,31,159,34,35],"839":[28,29,31,159,34,35],"849":[28,29,31,159,34,35],"853":[28,29,31,159,34,35],"869":[28,29,31,159,34,35],"889":[28,29,31,159,34,35],"900":[28,29,31,159,34,35],"909":[28,29,31,159,34,35],"915":[28,29,31,159,34,35],"955":[28,29,31,159,34,35],"956":[28,29,31,159,34,35],"966":[28,29,31,159,34,35],"987":[28,29,31,159,34,35],"1006":[28,29,31,159,34,35],"1016":[28,29,31,159,34,35],"1077":[28,29,31,159,34,35],"1085":[28,29,31,159,34,35],"1109":[28,29,31,159,34,35],"1116":[28,29,31,159,34,35],"1120":[28,29,31,159,34,35],"1136":[28,29,31,159,34,35],"1148":[28,29,31,159,34,35],"1170":[28,29,31,159,34,35],"1173":[28,29,31,159,34,35],"1192":[28,29,31,159,34,35],"1205":[28,29,31,159,34,35],"1216":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/data-tables.tool.ts":{"67":[28,29,31,159,34,35],"71":[28,29,31,159,34,35],"86":[28,29,31,159,34,35],"119":[28,29,31,159,34,35],"123":[28,29,31,159,34,35],"135":[28,29,31,159,34,35],"154":[28,29,31,159,34,35],"157":[28,29,31,159,34,35],"165":[28,29,31,159,34,35],"167":[28,29,31,159,34,35],"361":[28,29,31,159,34,35],"388":[28,29,31,159,34,35],"405":[28,29,31,159,34,35],"406":[28,29,31,159,34,35],"418":[28,29,31,159,34,35],"426":[28,29,31,159,34,35],"442":[28,29,31,159,34,35],"447":[28,29,31,159,34,35],"449":[28,29,31,159,34,35],"465":[28,29,31,159,34,35],"514":[28,29,31,159,34,35],"530":[28,29,31,159,34,35],"571":[28,29,31,159,34,35],"608":[28,29,31,159,34,35],"655":[28,29,31,159,34,35],"699":[28,29,31,159,34,35],"744":[28,29,31,159,34,35],"761":[28,29,31,159,34,35],"801":[28,29,31,159,34,35],"856":[28,29,31,159,34,35],"912":[28,29,31,159,34,35],"929":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/executions.tool.ts":{"256":[28,29,31,159,34,35],"274":[28,29,31,159,34,35],"292":[28,29,31,159,34,35],"296":[28,29,31,159,34,35],"300":[28,29,31,159,34,35],"314":[28,29,31,159,34,35],"322":[28,29,31,159,34,35],"329":[28,29,31,159,34,35],"356":[28,29,31,159,34,35],"359":[28,29,31,159,34,35],"360":[28,29,31,159,34,35],"457":[28,29,31,159,34,35],"509":[28,29,31,159,34,35],"510":[28,29,31,159,34,35],"541":[28,29,31,159,34,35],"545":[28,29,31,159,34,35],"555":[28,29,31,159,34,35],"569":[28,29,31,159,34,35],"575":[28,29,31,159,34,35],"594":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/filesystem/create-tools-from-mcp-server.ts":{"24":[28,29,31,159,34,35],"79":[28,29,31,159,34,35],"85":[28,29,31,159,34,35],"98":[28,29,31,159,34,35],"110":[28,29,31,159,34,35],"115":[28,29,31,159,34,35],"116":[28,29,31,159,34,35],"160":[28,29,31,159,34,35],"162":[28,29,31,159,34,35],"163":[28,29,31,159,34,35],"175":[28,29,31,159,34,35],"191":[28,29,31,159,34,35],"192":[28,29,31,159,34,35],"203":[28,29,31,159,34,35],"204":[28,29,31,159,34,35],"218":[28,29,31,159,34,35],"219":[28,29,31,159,34,35],"245":[28,29,31,159,34,35],"315":[28,29,31,159,34,35],"317":[28,29,31,159,34,35],"331":[28,29,31,159,34,35],"386":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/index.ts":{"10":[28,29,31,159,34,35],"12":[28,29,31,159,34,35],"16":[28,29,31,159,34,35],"19":[28,29,31,159,34,35],"22":[28,29,31,159,34,35],"25":[28,29,31,159,34,35],"28":[28,29,31,159,34,35],"31":[28,29,31,159,34,35],"33":[28,29,31,159,34,35],"35":[28,29,31,159,34,35],"38":[28,29,31,159,34,35],"41":[28,29,31,159,34,35],"44":[28,29,31,159,34,35],"47":[28,29,31,159,34,35],"50":[28,29,31,159,34,35],"53":[28,29,31,159,34,35],"57":[28,29,31,159,34,35],"61":[28,29,31,159,34,35],"65":[28,29,31,159,34,35],"68":[28,29,31,159,34,35],"72":[28,29,31,159,34,35],"76":[28,29,31,159,34,35],"79":[28,29,31,159,34,35],"82":[28,29,31,159,34,35],"86":[28,29,31,159,34,35],"89":[28,29,31,159,34,35],"93":[28,29,31,159,34,35],"97":[28,29,31,159,34,35],"100":[28,29,31,159,34,35],"105":[28,29,31,159,34,35],"109":[28,29,31,159,34,35],"110":[28,29,31,159,34,35],"111":[28,29,31,159,34,35],"112":[28,29,31,159,34,35],"113":[28,29,31,159,34,35],"114":[28,29,31,159,34,35],"115":[28,29,31,159,34,35],"116":[28,29,31,159,34,35],"117":[28,29,31,159,34,35],"118":[28,29,31,159,34,35],"121":[28,29,31,159,34,35],"130":[28,29,31,159,34,35],"139":[28,29,31,159,34,35],"149":[28,29,31,159,34,35],"159":[28,29,31,159,34,35],"167":[28,29,31,159,34,35],"173":[28,29,31,159,34,35],"176":[28,29,31,159,34,35],"187":[28,29,31,159,34,35],"194":[28,29,31,159,34,35],"202":[28,29,31,159,34,35],"203":[28,29,31,159,34,35],"207":[28,29,31,159,34,35],"209":[28,29,31,159,34,35],"219":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/mcp-servers.tool.ts":{"133":[28,29,31,159,34,35],"139":[28,29,31,159,34,35],"140":[28,29,31,159,34,35],"144":[28,29,31,159,34,35],"147":[28,29,31,159,34,35],"150":[28,29,31,159,34,35],"155":[28,29,31,159,34,35],"159":[28,29,31,159,34,35],"169":[28,29,31,159,34,35],"176":[28,29,31,159,34,35],"192":[28,29,31,159,34,35],"197":[28,29,31,159,34,35],"200":[28,29,31,159,34,35],"216":[28,29,31,159,34,35],"237":[28,29,31,159,34,35],"247":[28,29,31,159,34,35],"254":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/models/model-catalog.service.ts":{"25":[28,29,31,159,34,35],"55":[28,29,31,159,34,35],"71":[28,29,31,159,34,35],"86":[28,29,31,159,34,35],"113":[28,29,31,159,34,35],"119":[28,29,31,159,34,35],"134":[28,29,31,159,34,35],"136":[28,29,31,159,34,35],"139":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/n8n-docs/ranking.ts":{"24":[28,29,31,159,34,35],"32":[28,29,31,159,34,35],"35":[28,29,31,159,34,35],"53":[28,29,31,159,34,35],"71":[28,29,31,159,34,35],"75":[28,29,31,159,34,35],"76":[28,29,31,159,34,35],"79":[28,29,31,159,34,35],"85":[28,29,31,159,34,35],"90":[28,29,31,159,34,35],"94":[28,29,31,159,34,35],"98":[28,29,31,159,34,35],"102":[28,29,31,159,34,35],"113":[28,29,31,159,34,35],"203":[28,29,31,159,34,35],"210":[28,29,31,159,34,35],"211":[28,29,31,159,34,35],"212":[28,29,31,159,34,35],"215":[28,29,31,159,34,35],"221":[28,29,31,159,34,35],"226":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/n8n-docs/registry.ts":{"53":[28,29,31,159,34,35],"68":[28,29,31,159,34,35],"83":[28,29,31,159,34,35],"88":[28,29,31,159,34,35],"113":[28,29,31,159,34,35],"133":[28,29,31,159,34,35],"137":[28,29,31,159,34,35],"166":[28,29,31,159,34,35],"171":[28,29,31,159,34,35],"214":[28,29,31,159,34,35],"230":[28,29,31,159,34,35],"266":[28,29,31,159,34,35],"284":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/n8n-docs.tool.ts":{"13":[28,29,31,159,34,35],"16":[28,29,31,159,34,35],"19":[28,29,31,159,34,35],"53":[28,29,31,159,34,35],"58":[28,29,31,159,34,35],"67":[28,29,31,159,34,35],"95":[28,29,31,159,34,35],"104":[28,29,31,159,34,35],"126":[28,29,31,159,34,35],"147":[28,29,31,159,34,35],"167":[28,29,31,159,34,35],"180":[28,29,31,159,34,35],"199":[28,29,31,159,34,35],"200":[28,29,31,159,34,35],"226":[28,29,31,159,34,35],"232":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/nodes/model-selection.ts":{"11":[28,29,31,159,34,35,127],"15":[28,29,31,159,34,35,127],"18":[28,29,31,159,34,35,127],"26":[28,29,31,159,34,35,127],"29":[28,29,31,159,34,35,127]},"packages/@n8n/instance-ai/src/tools/nodes/preferred-chat-model.ts":{"48":[28,29,126,31,159,34,35],"52":[28,29,126,31,159,34,35],"61":[28,29,126,31,159,34,35],"72":[28,29,126,31,159,34,35],"73":[28,29,126,31,159,34,35],"76":[28,29,126,31,159,34,35],"80":[28,29,126,31,159,34,35],"88":[28,29,126,31,159,34,35],"92":[28,29,126,31,159,34,35],"95":[28,29,126,31,159,34,35],"98":[28,29,126,31,159,34,35],"108":[28,29,126,31,159,34,35],"113":[28,29,126,31,159,34,35],"133":[28,29,126,31,159,34,35],"141":[28,29,126,31,159,34,35],"153":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/nodes/setup-preference.ts":{"23":[28,29,31,159,34,35],"28":[28,29,31,159,34,35],"29":[28,29,31,159,34,35],"30":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/nodes.tool.ts":{"228":[28,29,31,159,34,35,127],"235":[28,29,31,159,34,35,127],"237":[28,29,31,159,34,35,127],"245":[28,29,31,159,34,35,127],"256":[28,29,31,159,34,35,127],"281":[28,29,31,159,34,35,127],"294":[28,29,31,159,34,35,127],"295":[28,29,31,159,34,35,127],"307":[28,29,31,159,34,35,127],"311":[28,29,31,159,34,35,127],"326":[28,29,31,159,34,35,127],"351":[28,29,31,159,34,35,127],"357":[28,29,31,159,34,35,127],"366":[28,29,31,159,34,35,127],"402":[28,29,31,159,34,35,127],"417":[28,29,31,159,34,35,127],"429":[28,29,31,159,34,35,127],"445":[28,29,31,159,34,35,127],"461":[28,29,31,159,34,35,127],"488":[28,29,31,159,34,35,127],"506":[28,29,31,159,34,35,127],"524":[28,29,31,159,34,35,127],"526":[28,29,31,159,34,35,127],"531":[28,29,31,159,34,35,127],"532":[28,29,31,159,34,35,127],"550":[28,29,31,159,34,35,127],"572":[28,29,31,159,34,35,127],"581":[28,29,31,159,34,35,127],"587":[28,29,31,159,34,35,127],"641":[28,29,31,159,34,35,127],"683":[28,29,31,159,34,35,127],"701":[28,29,31,159,34,35,127]},"packages/@n8n/instance-ai/src/tools/orchestration/agent-preview-session-binding.ts":{"22":[28,29,31,159,34,35],"27":[28,29,31,159,34,35],"41":[28,29,31,159,34,35],"55":[28,29,31,159,34,35],"69":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/orchestration/build-agent.tool.ts":{"88":[28,29,31,159,34,35],"94":[28,29,31,159,34,35],"101":[28,29,31,159,34,35],"106":[28,29,31,159,34,35],"110":[28,29,31,159,34,35],"111":[28,29,31,159,34,35],"118":[28,29,31,159,34,35],"126":[28,29,31,159,34,35],"128":[28,29,31,159,34,35],"139":[28,29,31,159,34,35],"154":[28,29,31,159,34,35],"164":[28,29,31,159,34,35],"191":[28,29,31,159,34,35],"349":[28,29,31,159,34,35],"378":[28,29,31,159,34,35],"399":[28,29,31,159,34,35],"409":[28,29,31,159,34,35],"440":[28,29,31,159,34,35],"483":[28,29,31,159,34,35],"500":[28,29,31,159,34,35],"538":[28,29,31,159,34,35],"565":[28,29,31,159,34,35],"715":[28,29,31,159,34,35],"733":[28,29,31,159,34,35],"778":[28,29,31,159,34,35],"843":[28,29,31,159,34,35],"859":[28,29,31,159,34,35],"864":[28,29,31,159,34,35],"885":[28,29,31,159,34,35],"1066":[28,29,31,159,34,35],"1093":[28,29,31,159,34,35],"1133":[28,29,31,159,34,35],"1174":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/orchestration/builder-thread-id.ts":{"6":[28,92,31,35]},"packages/@n8n/instance-ai/src/tools/orchestration/complete-checkpoint.tool.ts":{"44":[28,29,31,159,34,35],"49":[28,29,31,159,34,35],"55":[28,29,31,159,34,35],"58":[28,29,31,159,34,35],"61":[28,29,31,159,34,35],"68":[28,29,31,159,34,35],"73":[28,29,31,159,34,35],"74":[28,29,31,159,34,35],"75":[28,29,31,159,34,35],"80":[28,29,31,159,34,35],"110":[28,29,31,159,34,35],"119":[28,29,31,159,34,35],"129":[28,29,31,159,34,35],"130":[28,29,31,159,34,35],"164":[28,29,31,159,34,35],"174":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/orchestration/parent-handoff-state.ts":{"19":[28,29,31,159,34,35],"23":[28,29,31,159,34,35],"27":[28,29,31,159,34,35],"31":[28,29,31,159,34,35],"44":[28,29,31,159,34,35],"49":[28,29,31,159,34,35],"53":[28,29,31,159,34,35],"91":[28,29,31,159,34,35],"95":[28,29,31,159,34,35],"107":[28,29,31,159,34,35],"123":[28,29,31,159,34,35],"130":[28,29,31,159,34,35],"139":[28,29,31,159,34,35],"145":[28,29,31,159,34,35],"147":[28,29,31,159,34,35],"156":[28,29,31,159,34,35],"172":[28,29,31,159,34,35],"177":[28,29,31,159,34,35],"194":[28,29,31,159,34,35],"209":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/orchestration/plan.tool.ts":{"57":[28,29,31,159,34,35],"70":[28,29,31,159,34,35],"71":[28,29,31,159,34,35],"76":[28,29,31,159,34,35],"77":[28,29,31,159,34,35],"80":[28,29,31,159,34,35],"101":[28,29,31,159,34,35],"151":[28,29,31,159,34,35],"174":[28,29,31,159,34,35],"253":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/orchestration/report-verification-verdict.tool.ts":{"74":[28,29,31,159,34,35],"107":[28,29,31,159,34,35],"120":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/orchestration/tracing-utils.ts":{"18":[28,29,31,159,34,35],"41":[28,29,31,159,34,35],"53":[28,29,31,159,34,35],"62":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/orchestration/verification/analyze-result.ts":{"38":[28,29,126,31,159,34,35],"64":[28,29,126,31,159,34,35],"73":[28,29,126,31,159,34,35],"87":[28,29,126,31,159,34,35],"91":[28,29,126,31,159,34,35],"104":[28,29,126,31,159,34,35],"114":[28,29,126,31,159,34,35],"117":[28,29,126,31,159,34,35],"124":[28,29,126,31,159,34,35],"135":[28,29,126,31,159,34,35],"142":[28,29,126,31,159,34,35],"162":[28,29,126,31,159,34,35],"168":[28,29,126,31,159,34,35],"178":[28,29,126,31,159,34,35],"188":[28,29,126,31,159,34,35],"196":[28,29,126,31,159,34,35],"200":[28,29,126,31,159,34,35],"210":[28,29,126,31,159,34,35],"213":[28,29,126,31,159,34,35],"215":[28,29,126,31,159,34,35],"228":[28,29,126,31,159,34,35],"240":[28,29,126,31,159,34,35],"241":[28,29,126,31,159,34,35],"244":[28,29,126,31,159,34,35],"251":[28,29,126,31,159,34,35],"263":[28,29,126,31,159,34,35],"267":[28,29,126,31,159,34,35],"277":[28,29,126,31,159,34,35],"291":[28,29,126,31,159,34,35],"297":[28,29,126,31,159,34,35],"302":[28,29,126,31,159,34,35],"410":[28,29,126,31,159,34,35],"417":[28,29,126,31,159,34,35],"431":[28,29,126,31,159,34,35],"493":[28,29,126,31,159,34,35],"497":[28,29,126,31,159,34,35],"505":[28,29,126,31,159,34,35],"527":[28,29,126,31,159,34,35],"567":[28,29,126,31,159,34,35],"569":[28,29,126,31,159,34,35],"570":[28,29,126,31,159,34,35],"574":[28,29,126,31,159,34,35],"579":[28,29,126,31,159,34,35],"583":[28,29,126,31,159,34,35],"584":[28,29,126,31,159,34,35],"585":[28,29,126,31,159,34,35],"615":[28,29,126,31,159,34,35],"624":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/orchestration/verification/claim.ts":{"45":[28,29,126,31,159,34,35],"50":[28,29,126,31,159,34,35],"51":[28,29,126,31,159,34,35],"84":[28,29,126,31,159,34,35],"94":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/orchestration/verification/finalize-result.ts":{"25":[28,29,126,31,159,34,35],"37":[28,29,126,31,159,34,35],"106":[28,29,126,31,159,34,35],"167":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/orchestration/verification/prepare-run.ts":{"18":[28,29,126,31,159,34,35],"26":[28,29,126,31,159,34,35],"27":[28,29,126,31,159,34,35],"30":[28,29,126,31,159,34,35],"43":[28,29,126,31,159,34,35],"76":[28,29,126,31,159,34,35],"88":[28,29,126,31,159,34,35],"104":[28,29,126,31,159,34,35],"112":[28,29,126,31,159,34,35],"114":[28,29,126,31,159,34,35],"144":[28,29,126,31,159,34,35],"145":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/orchestration/verification/publish-state.ts":{"12":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/orchestration/verification/reconcile-plan.ts":{"15":[28,29,126,31,159,34,35],"36":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/orchestration/verification/record-live-run.ts":{"24":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/orchestration/verification/resolve-target.ts":{"33":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/orchestration/verification/resolved-parameter-warnings.ts":{"42":[28,29,126,31,159,34,35],"49":[28,29,126,31,159,34,35],"50":[28,29,126,31,159,34,35],"58":[28,29,126,31,159,34,35],"59":[28,29,126,31,159,34,35],"68":[28,29,126,31,159,34,35],"81":[28,29,126,31,159,34,35],"95":[28,29,126,31,159,34,35],"98":[28,29,126,31,159,34,35],"105":[28,29,126,31,159,34,35],"125":[28,29,126,31,159,34,35],"140":[28,29,126,31,159,34,35],"162":[28,29,126,31,159,34,35],"172":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/orchestration/verification/scripted-gate-run.ts":{"53":[28,29,31,159,34,35],"98":[28,29,31,159,34,35],"100":[28,29,31,159,34,35],"105":[28,29,31,159,34,35],"107":[28,29,31,159,34,35],"135":[28,29,31,159,34,35],"144":[28,29,31,159,34,35],"146":[28,29,31,159,34,35],"147":[28,29,31,159,34,35],"148":[28,29,31,159,34,35],"149":[28,29,31,159,34,35],"157":[28,29,31,159,34,35],"174":[28,29,31,159,34,35],"179":[28,29,31,159,34,35],"181":[28,29,31,159,34,35],"182":[28,29,31,159,34,35],"185":[28,29,31,159,34,35],"190":[28,29,31,159,34,35],"197":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/orchestration/verification/tool-simulation-preflight.ts":{"26":[28,29,126,31,159,34,35],"49":[28,29,126,31,159,34,35],"51":[28,29,126,31,159,34,35],"64":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/orchestration/verify-built-workflow.tool.ts":{"53":[28,29,126,31,159,34,35],"215":[28,29,126,31,159,34,35],"226":[28,29,126,31,159,34,35],"263":[28,29,126,31,159,34,35],"269":[28,29,126,31,159,34,35],"284":[28,29,126,31,159,34,35],"317":[28,29,126,31,159,34,35],"321":[28,29,126,31,159,34,35],"355":[28,29,126,31,159,34,35],"385":[28,29,126,31,159,34,35],"398":[28,29,126,31,159,34,35],"417":[28,29,126,31,159,34,35],"418":[28,29,126,31,159,34,35],"457":[28,29,126,31,159,34,35],"461":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/research.tool.ts":{"20":[28,29,31,159,34,35],"88":[28,29,31,159,34,35],"143":[28,29,31,159,34,35],"220":[28,29,31,159,34,35],"249":[28,29,31,159,34,35],"263":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/search-models.tool.ts":{"9":[28,29,31,159,34,35],"23":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/shared/ask-user.tool.ts":{"7":[28,29,31,159,34,35],"51":[28,29,31,159,34,35],"63":[28,29,31,159,34,35],"70":[28,29,31,159,34,35],"116":[28,29,31,159,34,35],"136":[28,29,31,159,34,35],"143":[28,29,31,159,34,35],"145":[28,29,31,159,34,35],"155":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/shared/safe-error-message.ts":{"3":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/task-control.tool.ts":{"57":[28,29,31,159,34,35],"72":[28,29,31,159,34,35],"83":[28,29,31,159,34,35],"110":[28,29,31,159,34,35],"116":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/web-research/sanitize-web-content.ts":{"13":[28,29,126,31,159,34,35],"23":[28,29,126,31,159,34,35],"44":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/apply-workflow-credentials.tool.ts":{"29":[28,29,31,159,34,35],"44":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/build-workflow.tool.ts":{"149":[28,29,126,31,159,34,35],"160":[28,29,126,31,159,34,35],"256":[28,29,126,31,159,34,35],"267":[28,29,126,31,159,34,35],"270":[28,29,126,31,159,34,35],"312":[28,29,126,31,159,34,35],"330":[28,29,126,31,159,34,35],"356":[28,29,126,31,159,34,35],"362":[28,29,126,31,159,34,35],"366":[28,29,126,31,159,34,35],"377":[28,29,126,31,159,34,35],"387":[28,29,126,31,159,34,35],"411":[28,29,126,31,159,34,35],"477":[28,29,126,31,159,34,35],"499":[28,29,126,31,159,34,35],"523":[28,29,126,31,159,34,35],"573":[28,29,126,31,159,34,35],"610":[28,29,126,31,159,34,35],"619":[28,29,126,31,159,34,35],"635":[28,29,126,31,159,34,35],"1033":[28,29,126,31,159,34,35],"1242":[28,29,126,31,159,34,35],"1251":[28,29,126,31,159,34,35],"1267":[28,29,126,31,159,34,35],"1279":[28,29,126,31,159,34,35],"1420":[28,29,126,31,159,34,35],"1480":[28,29,126,31,159,34,35],"1481":[28,29,126,31,159,34,35],"1483":[28,29,126,31,159,34,35],"1493":[28,29,126,31,159,34,35],"1497":[28,29,126,31,159,34,35],"1499":[28,29,126,31,159,34,35],"1520":[28,29,126,31,159,34,35],"1535":[28,29,126,31,159,34,35],"1553":[28,29,126,31,159,34,35],"1730":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/chat-model-validation.ts":{"30":[28,29,126,31,159,34,35],"38":[28,29,126,31,159,34,35],"45":[28,29,126,31,159,34,35],"56":[28,29,126,31,159,34,35],"66":[28,29,126,31,159,34,35],"79":[28,29,126,31,159,34,35],"85":[28,29,126,31,159,34,35],"90":[28,29,126,31,159,34,35],"93":[28,29,126,31,159,34,35],"98":[28,29,126,31,159,34,35],"103":[28,29,126,31,159,34,35],"148":[28,29,126,31,159,34,35],"153":[28,29,126,31,159,34,35],"154":[28,29,126,31,159,34,35],"164":[28,29,126,31,159,34,35],"176":[28,29,126,31,159,34,35],"184":[28,29,126,31,159,34,35],"195":[28,29,126,31,159,34,35],"241":[28,29,126,31,159,34,35],"250":[28,29,126,31,159,34,35],"268":[28,29,126,31,159,34,35],"282":[28,29,126,31,159,34,35],"304":[28,29,126,31,159,34,35],"337":[28,29,126,31,159,34,35],"360":[28,29,126,31,159,34,35],"392":[28,29,126,31,159,34,35],"424":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/classify-node-destructiveness.service.ts":{"83":[28,29,126,31,159,34,35],"193":[28,29,126,31,159,34,35],"200":[28,29,126,31,159,34,35],"208":[28,29,126,31,159,34,35],"288":[28,29,126,31,159,34,35],"317":[28,29,126,31,159,34,35],"348":[28,29,126,31,159,34,35],"355":[28,29,126,31,159,34,35],"364":[28,29,126,31,159,34,35],"376":[28,29,126,31,159,34,35],"389":[28,29,126,31,159,34,35],"398":[28,29,126,31,159,34,35],"406":[28,29,126,31,159,34,35],"443":[28,29,126,31,159,34,35],"444":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/credential-url-resolver.ts":{"24":[28,126,34,35],"32":[28,126,34,35],"33":[28,126,34,35],"41":[28,126,34,35],"43":[28,126,34,35],"78":[28,126,34,35],"94":[28,126,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/detect-array-input-collapse.ts":{"31":[28,29,126,31,159,34,35],"43":[28,29,126,31,159,34,35],"54":[28,29,126,31,159,34,35],"77":[28,29,126,31,159,34,35],"89":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/detect-python-code-constraints.ts":{"11":[28,29,126,31,159,34,35],"20":[28,29,126,31,159,34,35],"34":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/detect-slack-blocks-shape.ts":{"15":[28,29,126,31,159,34,35],"34":[28,29,126,31,159,34,35],"47":[28,29,126,31,159,34,35],"63":[28,29,126,31,159,34,35],"79":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/detect-unparseable-openai-schema.ts":{"14":[28,29,126,31,159,34,35],"38":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/detect-wrong-kind-locator.ts":{"7":[28,29,126,31,159,34,35],"8":[28,29,126,31,159,34,35],"12":[28,29,126,31,159,34,35],"15":[28,29,126,31,159,34,35],"18":[28,29,126,31,159,34,35],"19":[28,29,126,31,159,34,35],"22":[28,29,126,31,159,34,35],"31":[28,29,126,31,159,34,35],"36":[28,29,126,31,159,34,35],"45":[28,29,126,31,159,34,35],"65":[28,29,126,31,159,34,35],"111":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/generate-simulation-fixtures.service.ts":{"98":[28,29,126,31,159,34,35],"125":[28,29,126,31,159,34,35],"134":[28,29,126,31,159,34,35],"135":[28,29,126,31,159,34,35],"138":[28,29,126,31,159,34,35],"146":[28,29,126,31,159,34,35],"187":[28,29,126,31,159,34,35],"199":[28,29,126,31,159,34,35],"200":[28,29,126,31,159,34,35],"203":[28,29,126,31,159,34,35],"208":[28,29,126,31,159,34,35],"215":[28,29,126,31,159,34,35],"222":[28,29,126,31,159,34,35],"223":[28,29,126,31,159,34,35],"227":[28,29,126,31,159,34,35],"260":[28,29,126,31,159,34,35],"277":[28,29,126,31,159,34,35],"278":[28,29,126,31,159,34,35],"303":[28,29,126,31,159,34,35],"321":[28,29,126,31,159,34,35],"354":[28,29,126,31,159,34,35],"360":[28,29,126,31,159,34,35],"372":[28,29,126,31,159,34,35],"380":[28,29,126,31,159,34,35],"393":[28,29,126,31,159,34,35],"397":[28,29,126,31,159,34,35],"402":[28,29,126,31,159,34,35],"405":[28,29,126,31,159,34,35],"412":[28,29,126,31,159,34,35],"423":[28,29,126,31,159,34,35],"435":[28,29,126,31,159,34,35],"471":[28,29,126,31,159,34,35],"472":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/plan-verification-simulation.ts":{"81":[28,29,126,31,159,34,35],"85":[28,29,126,31,159,34,35],"118":[28,29,126,31,159,34,35],"124":[28,29,126,31,159,34,35],"127":[28,29,126,31,159,34,35],"153":[28,29,126,31,159,34,35],"160":[28,29,126,31,159,34,35],"169":[28,29,126,31,159,34,35],"186":[28,29,126,31,159,34,35],"193":[28,29,126,31,159,34,35],"196":[28,29,126,31,159,34,35],"202":[28,29,126,31,159,34,35],"214":[28,29,126,31,159,34,35],"239":[28,29,126,31,159,34,35],"245":[28,29,126,31,159,34,35],"248":[28,29,126,31,159,34,35],"251":[28,29,126,31,159,34,35],"261":[28,29,126,31,159,34,35],"266":[28,29,126,31,159,34,35],"270":[28,29,126,31,159,34,35],"277":[28,29,126,31,159,34,35],"278":[28,29,126,31,159,34,35],"316":[28,29,126,31,159,34,35],"325":[28,29,126,31,159,34,35],"330":[28,29,126,31,159,34,35],"341":[28,29,126,31,159,34,35],"372":[28,29,126,31,159,34,35],"398":[28,29,126,31,159,34,35],"399":[28,29,126,31,159,34,35],"400":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/prepare-workflow-setup.ts":{"25":[28,29,31,159,34,35],"30":[28,29,31,159,34,35],"40":[28,29,31,159,34,35],"54":[28,29,31,159,34,35],"81":[28,29,31,159,34,35],"84":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/preserve-node-positions.ts":{"38":[28,29,126,31,159,34,35],"42":[28,29,126,31,159,34,35],"43":[28,29,126,31,159,34,35],"48":[28,29,126,31,159,34,35],"51":[28,29,126,31,159,34,35],"62":[28,29,126,31,159,34,35],"63":[28,29,126,31,159,34,35],"64":[28,29,126,31,159,34,35],"75":[28,29,126,31,159,34,35],"77":[28,29,126,31,159,34,35],"80":[28,29,126,31,159,34,35],"81":[28,29,126,31,159,34,35],"85":[28,29,126,31,159,34,35],"100":[28,29,126,31,159,34,35],"103":[28,29,126,31,159,34,35],"124":[28,29,126,31,159,34,35],"125":[28,29,126,31,159,34,35],"135":[28,29,126,31,159,34,35],"137":[28,29,126,31,159,34,35],"149":[28,29,126,31,159,34,35],"157":[28,29,126,31,159,34,35],"158":[28,29,126,31,159,34,35],"159":[28,29,126,31,159,34,35],"160":[28,29,126,31,159,34,35],"165":[28,29,126,31,159,34,35],"171":[28,29,126,31,159,34,35],"172":[28,29,126,31,159,34,35],"176":[28,29,126,31,159,34,35],"177":[28,29,126,31,159,34,35],"184":[28,29,126,31,159,34,35],"185":[28,29,126,31,159,34,35],"188":[28,29,126,31,159,34,35],"197":[28,29,126,31,159,34,35],"213":[28,29,126,31,159,34,35],"231":[28,29,126,31,159,34,35],"239":[28,29,126,31,159,34,35],"240":[28,29,126,31,159,34,35],"247":[28,29,126,31,159,34,35],"269":[28,29,126,31,159,34,35],"270":[28,29,126,31,159,34,35],"271":[28,29,126,31,159,34,35],"272":[28,29,126,31,159,34,35],"277":[28,29,126,31,159,34,35],"283":[28,29,126,31,159,34,35],"291":[28,29,126,31,159,34,35],"324":[28,29,126,31,159,34,35],"331":[28,29,126,31,159,34,35],"336":[28,29,126,31,159,34,35],"338":[28,29,126,31,159,34,35],"339":[28,29,126,31,159,34,35],"341":[28,29,126,31,159,34,35],"344":[28,29,126,31,159,34,35],"346":[28,29,126,31,159,34,35],"350":[28,29,126,31,159,34,35],"351":[28,29,126,31,159,34,35],"355":[28,29,126,31,159,34,35],"358":[28,29,126,31,159,34,35],"360":[28,29,126,31,159,34,35],"361":[28,29,126,31,159,34,35],"367":[28,29,126,31,159,34,35],"369":[28,29,126,31,159,34,35],"370":[28,29,126,31,159,34,35],"374":[28,29,126,31,159,34,35],"394":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/reconcile-simulation-plan.ts":{"41":[28,29,31,159,34,35],"51":[28,29,31,159,34,35],"55":[28,29,31,159,34,35],"59":[28,29,31,159,34,35],"77":[28,29,31,159,34,35],"89":[28,29,31,159,34,35],"95":[28,29,31,159,34,35],"100":[28,29,31,159,34,35],"103":[28,29,31,159,34,35],"105":[28,29,31,159,34,35],"106":[28,29,31,159,34,35],"116":[28,29,31,159,34,35],"121":[28,29,31,159,34,35],"136":[28,29,31,159,34,35],"143":[28,29,31,159,34,35],"163":[28,29,31,159,34,35],"165":[28,29,31,159,34,35],"187":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/resolve-credentials.ts":{"50":[28,29,126,31,159,34,35],"95":[28,29,126,31,159,34,35],"152":[28,29,126,31,159,34,35],"156":[28,29,126,31,159,34,35],"157":[28,29,126,31,159,34,35],"180":[28,29,126,31,159,34,35],"197":[28,29,126,31,159,34,35],"203":[28,29,126,31,159,34,35],"208":[28,29,126,31,159,34,35],"213":[28,29,126,31,159,34,35],"228":[28,29,126,31,159,34,35],"234":[28,29,126,31,159,34,35],"242":[28,29,126,31,159,34,35],"257":[28,29,126,31,159,34,35],"264":[28,29,126,31,159,34,35],"292":[28,29,126,31,159,34,35],"330":[28,29,126,31,159,34,35],"336":[28,29,126,31,159,34,35],"353":[28,29,126,31,159,34,35],"363":[28,29,126,31,159,34,35],"384":[28,29,126,31,159,34,35],"393":[28,29,126,31,159,34,35],"410":[28,29,126,31,159,34,35],"440":[28,29,126,31,159,34,35],"599":[28,29,126,31,159,34,35],"608":[28,29,126,31,159,34,35],"617":[28,29,126,31,159,34,35],"628":[28,29,126,31,159,34,35],"637":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/saved-workflow-state.ts":{"19":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/setup-credential-selections.ts":{"25":[28,29,126,31,159,34,35],"34":[28,29,126,31,159,34,35],"40":[28,29,126,31,159,34,35],"50":[28,29,126,31,159,34,35],"70":[28,29,126,31,159,34,35],"71":[28,29,126,31,159,34,35],"81":[28,29,126,31,159,34,35],"87":[28,29,126,31,159,34,35],"98":[28,29,126,31,159,34,35],"113":[28,29,126,31,159,34,35],"124":[28,29,126,31,159,34,35],"132":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/setup-items.ts":{"24":[28,29,31,159,34,35],"31":[28,29,31,159,34,35],"32":[28,29,31,159,34,35],"35":[28,29,31,159,34,35],"59":[28,29,31,159,34,35],"77":[28,29,31,159,34,35],"84":[28,29,31,159,34,35],"85":[28,29,31,159,34,35],"104":[28,29,31,159,34,35],"113":[28,29,31,159,34,35],"121":[28,29,31,159,34,35],"134":[28,29,31,159,34,35],"146":[28,29,31,159,34,35],"157":[28,29,31,159,34,35],"174":[28,29,31,159,34,35],"201":[28,29,31,159,34,35],"208":[28,29,31,159,34,35],"220":[28,29,31,159,34,35],"229":[28,29,31,159,34,35],"236":[28,29,31,159,34,35],"241":[28,29,31,159,34,35],"255":[28,29,31,159,34,35],"272":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/setup-skip-state.ts":{"23":[28,29,126,31,159,34,35],"37":[28,29,126,31,159,34,35],"48":[28,29,126,31,159,34,35],"52":[28,29,126,31,159,34,35],"57":[28,29,126,31,159,34,35],"61":[28,29,126,31,159,34,35],"70":[28,29,126,31,159,34,35],"75":[28,29,126,31,159,34,35],"85":[28,29,126,31,159,34,35],"109":[28,29,126,31,159,34,35],"119":[28,29,126,31,159,34,35],"121":[28,29,126,31,159,34,35],"156":[28,29,126,31,159,34,35],"175":[28,29,126,31,159,34,35],"190":[28,29,126,31,159,34,35],"193":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/setup-workflow.service.ts":{"58":[28,29,126,31,159,34,35,127],"62":[28,29,126,31,159,34,35,127],"75":[28,29,126,31,159,34,35,127],"146":[28,29,126,31,159,34,35,127],"160":[28,29,126,31,159,34,35,127],"184":[28,29,126,31,159,34,35,127],"216":[28,29,126,31,159,34,35,127],"237":[28,29,126,31,159,34,35,127],"242":[28,29,126,31,159,34,35,127],"249":[28,29,126,31,159,34,35,127],"259":[28,29,126,31,159,34,35,127],"278":[28,29,126,31,159,34,35,127],"286":[28,29,126,31,159,34,35,127],"309":[28,29,126,31,159,34,35,127],"325":[28,29,126,31,159,34,35,127],"336":[28,29,126,31,159,34,35,127],"340":[28,29,126,31,159,34,35,127],"341":[28,29,126,31,159,34,35,127],"392":[28,29,126,31,159,34,35,127],"405":[28,29,126,31,159,34,35,127],"409":[28,29,126,31,159,34,35,127],"413":[28,29,126,31,159,34,35,127],"423":[28,29,126,31,159,34,35,127],"441":[28,29,126,31,159,34,35,127],"445":[28,29,126,31,159,34,35,127],"463":[28,29,126,31,159,34,35,127],"485":[28,29,126,31,159,34,35,127],"519":[28,29,126,31,159,34,35,127],"525":[28,29,126,31,159,34,35,127],"534":[28,29,126,31,159,34,35,127],"547":[28,29,126,31,159,34,35,127],"586":[28,29,126,31,159,34,35,127],"643":[28,29,126,31,159,34,35,127],"658":[28,29,126,31,159,34,35,127],"660":[28,29,126,31,159,34,35,127],"743":[28,29,126,31,159,34,35,127],"784":[28,29,126,31,159,34,35,127],"803":[28,29,126,31,159,34,35,127],"869":[28,29,126,31,159,34,35,127],"877":[28,29,126,31,159,34,35,127],"901":[28,29,126,31,159,34,35,127],"923":[28,29,126,31,159,34,35,127],"944":[28,29,126,31,159,34,35,127],"964":[28,29,126,31,159,34,35,127],"971":[28,29,126,31,159,34,35,127],"972":[28,29,126,31,159,34,35,127],"977":[28,29,126,31,159,34,35,127],"1005":[28,29,126,31,159,34,35,127],"1012":[28,29,126,31,159,34,35,127],"1028":[28,29,126,31,159,34,35,127],"1034":[28,29,126,31,159,34,35,127],"1051":[28,29,126,31,159,34,35,127],"1103":[28,29,126,31,159,34,35,127],"1161":[28,29,126,31,159,34,35,127],"1177":[28,29,126,31,159,34,35,127],"1199":[28,29,126,31,159,34,35,127],"1238":[28,29,126,31,159,34,35,127],"1263":[28,29,126,31,159,34,35,127],"1327":[28,29,126,31,159,34,35,127],"1384":[28,29,126,31,159,34,35,127],"1417":[28,29,126,31,159,34,35,127],"1434":[28,29,126,31,159,34,35,127],"1443":[28,29,126,31,159,34,35,127]},"packages/@n8n/instance-ai/src/tools/workflows/sticky-note-wrapping.ts":{"20":[28,29,31,159,34,35],"27":[28,29,31,159,34,35],"36":[28,29,31,159,34,35],"37":[28,29,31,159,34,35],"38":[28,29,31,159,34,35],"39":[28,29,31,159,34,35],"40":[28,29,31,159,34,35],"44":[28,29,31,159,34,35],"45":[28,29,31,159,34,35],"48":[28,29,31,159,34,35],"51":[28,29,31,159,34,35],"71":[28,29,31,159,34,35],"73":[28,29,31,159,34,35],"74":[28,29,31,159,34,35],"78":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/summarize-workflow.ts":{"16":[28,29,31,159,34,35],"23":[28,29,31,159,34,35],"29":[28,29,31,159,34,35],"40":[28,29,31,159,34,35],"50":[28,29,31,159,34,35],"59":[28,29,31,159,34,35],"69":[28,29,31,159,34,35],"88":[28,29,31,159,34,35],"97":[28,29,31,159,34,35],"111":[28,29,31,159,34,35],"113":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/validate-workflow.service.ts":{"46":[28,29,31,159,34,35],"50":[28,29,31,159,34,35],"62":[28,29,31,159,34,35],"63":[28,29,31,159,34,35],"70":[28,29,31,159,34,35],"75":[28,29,31,159,34,35],"82":[28,29,31,159,34,35],"87":[28,29,31,159,34,35],"92":[28,29,31,159,34,35],"101":[28,29,31,159,34,35],"114":[28,29,31,159,34,35],"138":[28,29,31,159,34,35],"186":[28,29,31,159,34,35],"232":[28,29,31,159,34,35],"236":[28,29,31,159,34,35],"257":[28,29,31,159,34,35],"303":[28,29,31,159,34,35],"318":[28,29,31,159,34,35],"335":[28,29,31,159,34,35],"419":[28,29,31,159,34,35],"429":[28,29,31,159,34,35],"456":[28,29,31,159,34,35],"466":[28,29,31,159,34,35],"475":[28,29,31,159,34,35],"479":[28,29,31,159,34,35],"500":[28,29,31,159,34,35],"520":[28,29,31,159,34,35],"603":[28,29,31,159,34,35],"646":[28,29,31,159,34,35],"687":[28,29,31,159,34,35],"705":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/verification-graph.ts":{"13":[28,29,126,31,159,34,35],"24":[28,29,126,31,159,34,35],"30":[28,29,126,31,159,34,35],"33":[28,29,126,31,159,34,35],"38":[28,29,126,31,159,34,35],"39":[28,29,126,31,159,34,35],"48":[28,29,126,31,159,34,35],"49":[28,29,126,31,159,34,35],"52":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/wait-gate-script.ts":{"34":[28,29,126,31,159,34,35],"40":[28,29,126,31,159,34,35],"56":[28,29,126,31,159,34,35],"67":[28,29,126,31,159,34,35],"83":[28,29,126,31,159,34,35],"105":[28,29,126,31,159,34,35],"109":[28,29,126,31,159,34,35],"112":[28,29,126,31,159,34,35],"120":[28,29,126,31,159,34,35],"136":[28,29,126,31,159,34,35],"144":[28,29,126,31,159,34,35],"145":[28,29,126,31,159,34,35],"156":[28,29,126,31,159,34,35],"172":[28,29,126,31,159,34,35],"176":[28,29,126,31,159,34,35],"181":[28,29,126,31,159,34,35],"201":[28,29,126,31,159,34,35],"229":[28,29,126,31,159,34,35],"237":[28,29,126,31,159,34,35],"259":[28,29,126,31,159,34,35],"263":[28,29,126,31,159,34,35],"267":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/workflow-build-context.ts":{"11":[28,29,126,31,159,34,35],"23":[28,29,126,31,159,34,35],"34":[28,29,126,31,159,34,35],"45":[28,29,126,31,159,34,35],"53":[28,29,126,31,159,34,35],"64":[28,29,126,31,159,34,35],"94":[28,29,126,31,159,34,35],"134":[28,29,126,31,159,34,35],"138":[28,29,126,31,159,34,35],"139":[28,29,126,31,159,34,35],"143":[28,29,126,31,159,34,35],"150":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/workflow-build-remediation.ts":{"15":[28,29,31,159,34,35],"19":[28,29,31,159,34,35],"34":[28,29,31,159,34,35],"44":[28,29,31,159,34,35],"56":[28,29,31,159,34,35],"64":[28,29,31,159,34,35],"74":[28,29,31,159,34,35],"134":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/workflow-build-reporting.ts":{"8":[28,29,126,31,159,34,35],"54":[28,29,126,31,159,34,35],"69":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/workflow-build-routing.ts":{"18":[28,29,126,31,159,34,35],"29":[28,29,126,31,159,34,35],"34":[28,29,126,31,159,34,35],"57":[28,29,126,31,159,34,35],"73":[28,29,126,31,159,34,35],"129":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/workflow-build-telemetry.ts":{"18":[28,29,126,31,159,34,35],"82":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/workflow-file-bindings.ts":{"36":[28,29,126,31,159,34,35],"40":[28,29,126,31,159,34,35],"50":[28,29,126,31,159,34,35],"55":[28,29,126,31,159,34,35],"65":[28,29,126,31,159,34,35],"90":[28,29,126,31,159,34,35],"111":[28,29,126,31,159,34,35],"124":[28,29,126,31,159,34,35],"130":[28,29,126,31,159,34,35],"147":[28,29,126,31,159,34,35],"169":[28,29,126,31,159,34,35],"184":[28,29,126,31,159,34,35],"196":[28,29,126,31,159,34,35],"213":[28,29,126,31,159,34,35],"233":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/workflow-json-utils.ts":{"37":[28,29,126,31,159,34,35],"46":[28,29,126,31,159,34,35],"58":[28,29,126,31,159,34,35],"68":[28,29,126,31,159,34,35],"100":[28,29,126,31,159,34,35],"110":[28,29,126,31,159,34,35],"114":[28,29,126,31,159,34,35],"137":[28,29,126,31,159,34,35],"180":[28,29,126,31,159,34,35],"192":[28,29,126,31,159,34,35],"221":[28,29,126,31,159,34,35],"263":[28,29,126,31,159,34,35],"317":[28,29,126,31,159,34,35],"332":[28,29,126,31,159,34,35],"342":[28,29,126,31,159,34,35],"349":[28,29,126,31,159,34,35],"358":[28,29,126,31,159,34,35],"369":[28,29,126,31,159,34,35],"389":[28,29,126,31,159,34,35],"393":[28,29,126,31,159,34,35],"399":[28,29,126,31,159,34,35],"410":[28,29,126,31,159,34,35],"414":[28,29,126,31,159,34,35],"422":[28,29,126,31,159,34,35],"430":[28,29,126,31,159,34,35],"448":[28,29,126,31,159,34,35],"464":[28,29,126,31,159,34,35],"480":[28,29,126,31,159,34,35],"500":[28,29,126,31,159,34,35],"501":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/workflow-node-diff.ts":{"30":[28,29,126,31,159,34,35],"37":[28,29,126,31,159,34,35],"42":[28,29,126,31,159,34,35],"52":[28,29,126,31,159,34,35],"59":[28,29,126,31,159,34,35],"70":[28,29,126,31,159,34,35],"90":[28,29,126,31,159,34,35],"102":[28,29,126,31,159,34,35],"110":[28,29,126,31,159,34,35],"124":[28,29,126,31,159,34,35],"146":[28,29,126,31,159,34,35],"167":[28,29,126,31,159,34,35],"180":[28,29,126,31,159,34,35],"186":[28,29,126,31,159,34,35],"196":[28,29,126,31,159,34,35],"198":[28,29,126,31,159,34,35],"232":[28,29,126,31,159,34,35],"233":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/workflow-source-compiler.ts":{"61":[28,29,126,31,159,34,35],"70":[28,29,126,31,159,34,35],"75":[28,29,126,31,159,34,35],"83":[28,29,126,31,159,34,35],"85":[28,29,126,31,159,34,35],"88":[28,29,126,31,159,34,35],"111":[28,29,126,31,159,34,35],"148":[28,29,126,31,159,34,35],"149":[28,29,126,31,159,34,35],"152":[28,29,126,31,159,34,35],"160":[28,29,126,31,159,34,35],"184":[28,29,126,31,159,34,35],"198":[28,29,126,31,159,34,35],"207":[28,29,126,31,159,34,35],"215":[28,29,126,31,159,34,35],"216":[28,29,126,31,159,34,35],"225":[28,29,126,31,159,34,35],"232":[28,29,126,31,159,34,35],"257":[28,29,126,31,159,34,35],"259":[28,29,126,31,159,34,35],"262":[28,29,126,31,159,34,35],"268":[28,29,126,31,159,34,35],"272":[28,29,126,31,159,34,35],"287":[28,29,126,31,159,34,35],"291":[28,29,126,31,159,34,35],"315":[28,29,126,31,159,34,35],"316":[28,29,126,31,159,34,35],"336":[28,29,126,31,159,34,35],"420":[28,29,126,31,159,34,35],"456":[28,29,126,31,159,34,35],"466":[28,29,126,31,159,34,35],"480":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/workflow-source-diagnostics.ts":{"14":[28,29,31,159,34,35],"25":[28,29,31,159,34,35],"31":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/workflow-source-materializer.ts":{"48":[28,29,126,31,159,34,35],"59":[28,29,126,31,159,34,35],"73":[28,29,126,31,159,34,35],"89":[28,29,126,31,159,34,35],"97":[28,29,126,31,159,34,35],"105":[28,29,126,31,159,34,35],"131":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows/workflow-validation-warnings.ts":{"38":[28,29,126,31,159,34,35],"60":[28,29,126,31,159,34,35],"71":[28,29,126,31,159,34,35],"83":[28,29,126,31,159,34,35],"104":[28,29,126,31,159,34,35],"118":[28,29,126,31,159,34,35],"149":[28,29,126,31,159,34,35],"167":[28,29,126,31,159,34,35],"173":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workflows.tool.ts":{"195":[28,29,126,31,159,34,35],"481":[28,29,126,31,159,34,35],"485":[28,29,126,31,159,34,35],"516":[28,29,126,31,159,34,35],"522":[28,29,126,31,159,34,35],"526":[28,29,126,31,159,34,35],"557":[28,29,126,31,159,34,35],"568":[28,29,126,31,159,34,35],"574":[28,29,126,31,159,34,35],"575":[28,29,126,31,159,34,35],"582":[28,29,126,31,159,34,35],"634":[28,29,126,31,159,34,35],"637":[28,29,126,31,159,34,35],"654":[28,29,126,31,159,34,35],"692":[28,29,126,31,159,34,35],"708":[28,29,126,31,159,34,35],"746":[28,29,126,31,159,34,35],"747":[28,29,126,31,159,34,35],"766":[28,29,126,31,159,34,35],"805":[28,29,126,31,159,34,35],"820":[28,29,126,31,159,34,35],"825":[28,29,126,31,159,34,35],"909":[28,29,126,31,159,34,35],"948":[28,29,126,31,159,34,35],"989":[28,29,126,31,159,34,35],"1011":[28,29,126,31,159,34,35],"1041":[28,29,126,31,159,34,35],"1048":[28,29,126,31,159,34,35],"1050":[28,29,126,31,159,34,35],"1058":[28,29,126,31,159,34,35],"1064":[28,29,126,31,159,34,35],"1065":[28,29,126,31,159,34,35],"1074":[28,29,126,31,159,34,35],"1081":[28,29,126,31,159,34,35],"1102":[28,29,126,31,159,34,35],"1121":[28,29,126,31,159,34,35],"1127":[28,29,126,31,159,34,35],"1133":[28,29,126,31,159,34,35],"1153":[28,29,126,31,159,34,35],"1174":[28,29,126,31,159,34,35],"1248":[28,29,126,31,159,34,35],"1258":[28,29,126,31,159,34,35],"1264":[28,29,126,31,159,34,35],"1265":[28,29,126,31,159,34,35],"1267":[28,29,126,31,159,34,35],"1274":[28,29,126,31,159,34,35],"1279":[28,29,126,31,159,34,35],"1306":[28,29,126,31,159,34,35],"1345":[28,29,126,31,159,34,35],"1348":[28,29,126,31,159,34,35],"1357":[28,29,126,31,159,34,35],"1358":[28,29,126,31,159,34,35],"1377":[28,29,126,31,159,34,35],"1425":[28,29,126,31,159,34,35],"1453":[28,29,126,31,159,34,35],"1482":[28,29,126,31,159,34,35],"1540":[28,29,126,31,159,34,35],"1581":[28,29,126,31,159,34,35],"1620":[28,29,126,31,159,34,35],"1648":[28,29,126,31,159,34,35],"1666":[28,29,126,31,159,34,35],"1667":[28,29,126,31,159,34,35],"1668":[28,29,126,31,159,34,35],"1696":[28,29,126,31,159,34,35],"1713":[28,29,126,31,159,34,35],"1724":[28,29,126,31,159,34,35],"1732":[28,29,126,31,159,34,35],"1733":[28,29,126,31,159,34,35],"1734":[28,29,126,31,159,34,35],"1740":[28,29,126,31,159,34,35],"1779":[28,29,126,31,159,34,35],"1780":[28,29,126,31,159,34,35],"1785":[28,29,126,31,159,34,35],"1842":[28,29,126,31,159,34,35],"1875":[28,29,126,31,159,34,35],"1899":[28,29,126,31,159,34,35],"2013":[28,29,126,31,159,34,35],"2027":[28,29,126,31,159,34,35],"2058":[28,29,126,31,159,34,35],"2069":[28,29,126,31,159,34,35],"2076":[28,29,126,31,159,34,35],"2083":[28,29,126,31,159,34,35],"2127":[28,29,126,31,159,34,35],"2138":[28,29,126,31,159,34,35],"2156":[28,29,126,31,159,34,35],"2209":[28,29,126,31,159,34,35],"2265":[28,29,126,31,159,34,35],"2270":[28,29,126,31,159,34,35],"2271":[28,29,126,31,159,34,35],"2278":[28,29,126,31,159,34,35],"2293":[28,29,126,31,159,34,35],"2311":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/tools/workspace.tool.ts":{"110":[28,29,31,159,34,35],"145":[28,29,31,159,34,35],"153":[28,29,31,159,34,35],"160":[28,29,31,159,34,35],"165":[28,29,31,159,34,35],"197":[28,29,31,159,34,35],"232":[28,29,31,159,34,35],"240":[28,29,31,159,34,35],"298":[28,29,31,159,34,35],"334":[28,29,31,159,34,35],"368":[28,29,31,159,34,35],"375":[28,29,31,159,34,35],"389":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tracing/agent-snapshot-event.ts":{"36":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tracing/langsmith-tracing.ts":{"102":[28,29,92,126,31,159,34,35,228],"110":[28,29,92,126,31,159,34,35,228],"113":[28,29,92,126,31,159,34,35,228],"121":[28,29,92,126,31,159,34,35,228],"126":[28,29,92,126,31,159,34,35,228],"130":[28,29,92,126,31,159,34,35,228],"136":[28,29,92,126,31,159,34,35,228],"137":[28,29,92,126,31,159,34,35,228],"150":[28,29,92,126,31,159,34,35,228],"152":[28,29,92,126,31,159,34,35,228],"162":[28,29,92,126,31,159,34,35,228],"206":[28,29,92,126,31,159,34,35,228],"214":[28,29,92,126,31,159,34,35,228],"221":[28,29,92,126,31,159,34,35,228],"226":[28,29,92,126,31,159,34,35,228],"230":[28,29,92,126,31,159,34,35,228],"243":[28,29,92,126,31,159,34,35,228],"263":[28,29,92,126,31,159,34,35,228],"269":[28,29,92,126,31,159,34,35,228],"295":[28,29,92,126,31,159,34,35,228],"333":[28,29,92,126,31,159,34,35,228],"341":[28,29,92,126,31,159,34,35,228],"406":[28,29,92,126,31,159,34,35,228],"471":[28,29,92,126,31,159,34,35,228],"493":[28,29,92,126,31,159,34,35,228],"503":[28,29,92,126,31,159,34,35,228],"526":[28,29,92,126,31,159,34,35,228],"528":[28,29,92,126,31,159,34,35,228],"532":[28,29,92,126,31,159,34,35,228],"547":[28,29,92,126,31,159,34,35,228],"557":[28,29,92,126,31,159,34,35,228],"573":[28,29,92,126,31,159,34,35,228],"585":[28,29,92,126,31,159,34,35,228],"589":[28,29,92,126,31,159,34,35,228],"596":[28,29,92,126,31,159,34,35,228],"608":[28,29,92,126,31,159,34,35,228],"635":[28,29,92,126,31,159,34,35,228],"641":[28,29,92,126,31,159,34,35,228],"653":[28,29,92,126,31,159,34,35,228],"668":[28,29,92,126,31,159,34,35,228],"687":[28,29,92,126,31,159,34,35,228],"706":[28,29,92,126,31,159,34,35,228],"715":[28,29,92,126,31,159,34,35,228],"718":[28,29,92,126,31,159,34,35,228],"785":[28,29,92,126,31,159,34,35,228],"793":[28,29,92,126,31,159,34,35,228],"797":[28,29,92,126,31,159,34,35,228],"821":[28,29,92,126,31,159,34,35,228],"828":[28,29,92,126,31,159,34,35,228],"829":[28,29,92,126,31,159,34,35,228],"834":[28,29,92,126,31,159,34,35,228],"855":[28,29,92,126,31,159,34,35,228],"882":[28,29,92,126,31,159,34,35,228],"893":[28,29,92,126,31,159,34,35,228],"908":[28,29,92,126,31,159,34,35,228],"924":[28,29,92,126,31,159,34,35,228],"937":[28,29,92,126,31,159,34,35,228],"947":[28,29,92,126,31,159,34,35,228],"960":[28,29,92,126,31,159,34,35,228],"966":[28,29,92,126,31,159,34,35,228],"974":[28,29,92,126,31,159,34,35,228],"991":[28,29,92,126,31,159,34,35,228],"1047":[28,29,92,126,31,159,34,35,228],"1067":[28,29,92,126,31,159,34,35,228],"1073":[28,29,92,126,31,159,34,35,228],"1079":[28,29,92,126,31,159,34,35,228],"1127":[28,29,92,126,31,159,34,35,228],"1171":[28,29,92,126,31,159,34,35,228],"1186":[28,29,92,126,31,159,34,35,228],"1225":[28,29,92,126,31,159,34,35,228],"1238":[28,29,92,126,31,159,34,35,228],"1257":[28,29,92,126,31,159,34,35,228],"1269":[28,29,92,126,31,159,34,35,228],"1273":[28,29,92,126,31,159,34,35,228],"1292":[28,29,92,126,31,159,34,35,228],"1295":[28,29,92,126,31,159,34,35,228],"1299":[28,29,92,126,31,159,34,35,228],"1306":[28,29,92,126,31,159,34,35,228],"1316":[28,29,92,126,31,159,34,35,228],"1321":[28,29,92,126,31,159,34,35,228],"1329":[28,29,92,126,31,159,34,35,228],"1339":[28,29,92,126,31,159,34,35,228],"1353":[28,29,92,126,31,159,34,35,228],"1356":[28,29,92,126,31,159,34,35,228],"1360":[28,29,92,126,31,159,34,35,228],"1364":[28,29,92,126,31,159,34,35,228],"1365":[28,29,92,126,31,159,34,35,228],"1368":[28,29,92,126,31,159,34,35,228],"1383":[28,29,92,126,31,159,34,35,228],"1392":[28,29,92,126,31,159,34,35,228],"1395":[28,29,92,126,31,159,34,35,228],"1399":[28,29,92,126,31,159,34,35,228],"1403":[28,29,92,126,31,159,34,35,228],"1428":[28,29,92,126,31,159,34,35,228],"1436":[28,29,92,126,31,159,34,35,228],"1452":[28,29,92,126,31,159,34,35,228],"1460":[28,29,92,126,31,159,34,35,228],"1472":[28,29,92,126,31,159,34,35,228],"1503":[28,29,92,126,31,159,34,35,228],"1510":[28,29,92,126,31,159,34,35,228],"1518":[28,29,92,126,31,159,34,35,228],"1563":[28,29,92,126,31,159,34,35,228],"1587":[28,29,92,126,31,159,34,35,228],"1607":[28,29,92,126,31,159,34,35,228],"1608":[28,29,92,126,31,159,34,35,228],"1609":[28,29,92,126,31,159,34,35,228],"1610":[28,29,92,126,31,159,34,35,228],"1611":[28,29,92,126,31,159,34,35,228],"1612":[28,29,92,126,31,159,34,35,228],"1613":[28,29,92,126,31,159,34,35,228],"1635":[28,29,92,126,31,159,34,35,228],"1644":[28,29,92,126,31,159,34,35,228],"1670":[28,29,92,126,31,159,34,35,228],"1671":[28,29,92,126,31,159,34,35,228],"1685":[28,29,92,126,31,159,34,35,228],"1718":[28,29,92,126,31,159,34,35,228],"1727":[28,29,92,126,31,159,34,35,228],"1737":[28,29,92,126,31,159,34,35,228],"1783":[28,29,92,126,31,159,34,35,228],"1800":[28,29,92,126,31,159,34,35,228],"1823":[28,29,92,126,31,159,34,35,228],"1853":[28,29,92,126,31,159,34,35,228],"1863":[28,29,92,126,31,159,34,35,228],"1887":[28,29,92,126,31,159,34,35,228],"1909":[28,29,92,126,31,159,34,35,228],"1946":[28,29,92,126,31,159,34,35,228],"1997":[28,29,92,126,31,159,34,35,228],"2011":[28,29,92,126,31,159,34,35,228],"2041":[28,29,92,126,31,159,34,35,228],"2044":[28,29,92,126,31,159,34,35,228],"2070":[28,29,92,126,31,159,34,35,228],"2081":[28,29,92,126,31,159,34,35,228],"2092":[28,29,92,126,31,159,34,35,228],"2107":[28,29,92,126,31,159,34,35,228],"2123":[28,29,92,126,31,159,34,35,228]},"packages/@n8n/instance-ai/src/tracing/sandbox-tracing.ts":{"17":[28,29,31,159,34,35],"39":[28,29,31,159,34,35],"43":[28,29,31,159,34,35],"47":[28,29,31,159,34,35],"51":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tracing/thread-provenance.ts":{"23":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tracing/trace-labels.ts":{"1":[28,29,31,159,34,35],"9":[28,29,31,159,34,35],"13":[28,29,31,159,34,35],"24":[28,29,31,159,34,35],"28":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tracing/trace-payloads.ts":{"61":[28,29,31,159,34,35],"78":[28,29,31,159,34,35],"113":[28,29,31,159,34,35],"121":[28,29,31,159,34,35],"135":[28,29,31,159,34,35],"136":[28,29,31,159,34,35],"138":[28,29,31,159,34,35],"141":[28,29,31,159,34,35],"144":[28,29,31,159,34,35],"157":[28,29,31,159,34,35],"179":[28,29,31,159,34,35],"202":[28,29,31,159,34,35],"216":[28,29,31,159,34,35],"228":[28,29,31,159,34,35],"264":[28,29,31,159,34,35],"277":[28,29,31,159,34,35],"292":[28,29,31,159,34,35],"299":[28,29,31,159,34,35],"306":[28,29,31,159,34,35],"322":[28,29,31,159,34,35],"349":[28,29,31,159,34,35],"383":[28,29,31,159,34,35],"420":[28,29,31,159,34,35],"445":[28,29,31,159,34,35],"447":[28,29,31,159,34,35],"451":[28,29,31,159,34,35],"453":[28,29,31,159,34,35],"460":[28,29,31,159,34,35],"464":[28,29,31,159,34,35],"474":[28,29,31,159,34,35],"489":[28,29,31,159,34,35],"515":[28,29,31,159,34,35],"546":[28,29,31,159,34,35],"557":[28,29,31,159,34,35],"572":[28,29,31,159,34,35],"586":[28,29,31,159,34,35],"593":[28,29,31,159,34,35],"606":[28,29,31,159,34,35],"624":[28,29,31,159,34,35],"646":[28,29,31,159,34,35],"674":[28,29,31,159,34,35],"726":[28,29,31,159,34,35],"771":[28,29,31,159,34,35],"808":[28,29,31,159,34,35],"821":[28,29,31,159,34,35],"829":[28,29,31,159,34,35],"862":[28,29,31,159,34,35],"867":[28,29,31,159,34,35],"877":[28,29,31,159,34,35],"886":[28,29,31,159,34,35],"897":[28,29,31,159,34,35],"934":[28,29,31,159,34,35],"968":[28,29,31,159,34,35],"977":[28,29,31,159,34,35],"992":[28,29,31,159,34,35],"996":[28,29,31,159,34,35],"1011":[28,29,31,159,34,35],"1042":[28,29,31,159,34,35],"1051":[28,29,31,159,34,35],"1075":[28,29,31,159,34,35],"1082":[28,29,31,159,34,35],"1086":[28,29,31,159,34,35],"1094":[28,29,31,159,34,35],"1117":[28,29,31,159,34,35],"1135":[28,29,31,159,34,35],"1158":[28,29,31,159,34,35],"1185":[28,29,31,159,34,35],"1217":[28,29,31,159,34,35],"1226":[28,29,31,159,34,35],"1228":[28,29,31,159,34,35],"1243":[28,29,31,159,34,35],"1255":[28,29,31,159,34,35],"1265":[28,29,31,159,34,35],"1266":[28,29,31,159,34,35],"1272":[28,29,31,159,34,35],"1281":[28,29,31,159,34,35],"1294":[28,29,31,159,34,35],"1307":[28,29,31,159,34,35],"1329":[28,29,31,159,34,35],"1347":[28,29,31,159,34,35],"1359":[28,29,31,159,34,35],"1371":[28,29,31,159,34,35],"1384":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/tracing/trace-replay.ts":{"45":[28,29,92,126,31,159,34,35],"61":[28,29,92,126,31,159,34,35],"76":[28,29,92,126,31,159,34,35],"96":[28,29,92,126,31,159,34,35],"137":[28,29,92,126,31,159,34,35],"152":[28,29,92,126,31,159,34,35],"158":[28,29,92,126,31,159,34,35],"162":[28,29,92,126,31,159,34,35],"200":[28,29,92,126,31,159,34,35],"224":[28,29,92,126,31,159,34,35],"240":[28,29,92,126,31,159,34,35],"262":[28,29,92,126,31,159,34,35],"267":[28,29,92,126,31,159,34,35],"275":[28,29,92,126,31,159,34,35],"279":[28,29,92,126,31,159,34,35],"303":[28,29,92,126,31,159,34,35],"312":[28,29,92,126,31,159,34,35],"328":[28,29,92,126,31,159,34,35],"346":[28,29,92,126,31,159,34,35],"364":[28,29,92,126,31,159,34,35],"368":[28,29,92,126,31,159,34,35],"369":[28,29,92,126,31,159,34,35],"377":[28,29,92,126,31,159,34,35],"383":[28,29,92,126,31,159,34,35]},"packages/@n8n/instance-ai/src/utils/custom-model-defaults.ts":{"52":[28,29,31,159,34,35],"61":[28,29,31,159,34,35],"75":[28,29,31,159,34,35],"79":[28,29,31,159,34,35],"93":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/utils/eval-agents.ts":{"49":[28,29,31,159,34,35],"64":[28,29,31,159,34,35],"70":[28,29,31,159,34,35],"101":[28,29,31,159,34,35],"107":[28,29,31,159,34,35],"111":[28,29,31,159,34,35],"118":[28,29,31,159,34,35],"135":[28,29,31,159,34,35],"141":[28,29,31,159,34,35],"147":[28,29,31,159,34,35],"150":[28,29,31,159,34,35],"155":[28,29,31,159,34,35],"184":[28,29,31,159,34,35],"200":[28,29,31,159,34,35],"209":[28,29,31,159,34,35],"212":[28,29,31,159,34,35],"238":[28,29,31,159,34,35],"277":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/utils/eval-usage.ts":{"13":[28,29,31,159,34,35],"17":[28,29,31,159,34,35],"31":[28,29,31,159,34,35],"32":[28,29,31,159,34,35],"37":[28,29,31,159,34,35],"44":[28,29,31,159,34,35],"52":[28,29,31,159,34,35],"70":[28,29,31,159,34,35],"72":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/utils/format-timestamp.ts":{"2":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/utils/generate-validated-json.ts":{"34":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/utils/modal-session.ts":{"7":[28,29,31,159,34,35],"25":[28,29,31,159,34,35],"35":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/utils/model-config-id.ts":{"6":[28,29,31,159,34,35],"22":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/utils/node-keyed-items.ts":{"12":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/utils/quota-error.ts":{"7":[28,29,31,159,160,34,35],"11":[28,29,31,159,160,34,35],"32":[28,29,31,159,160,34,35]},"packages/@n8n/instance-ai/src/utils/stream-helpers.ts":{"20":[28,29,126,31,159,34,35],"46":[28,29,126,31,159,34,35],"50":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/workflow-builder/build-failure-tracker.ts":{"7":[28,29,126,31,159,34,35],"9":[28,29,126,31,159,34,35],"36":[28,29,126,31,159,34,35],"63":[28,29,126,31,159,34,35],"85":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/workflow-loop/guidance.ts":{"15":[28,29,31,159,34,35],"57":[28,29,31,159,34,35],"63":[28,29,31,159,34,35],"67":[28,29,31,159,34,35],"75":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/workflow-loop/index.ts":{"61":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/workflow-loop/remediation.ts":{"11":[28,29,126,31,159,34,35],"22":[28,29,126,31,159,34,35],"29":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/workflow-loop/render-claim.ts":{"11":[28,29,126,31,159,34,35],"16":[28,29,126,31,159,34,35],"47":[28,29,126,31,159,34,35],"55":[28,29,126,31,159,34,35],"75":[28,29,126,31,159,34,35],"87":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/workflow-loop/runtime.ts":{"10":[28,29,126,31,159,34,35],"29":[28,29,126,31,159,34,35],"31":[28,29,126,31,159,34,35],"46":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/workflow-loop/setup-verification-policy.ts":{"8":[28,29,126,31,159,34,35,127],"14":[28,29,126,31,159,34,35,127],"19":[28,29,126,31,159,34,35,127],"33":[28,29,126,31,159,34,35,127],"69":[28,29,126,31,159,34,35,127],"78":[28,29,126,31,159,34,35,127]},"packages/@n8n/instance-ai/src/workflow-loop/verification-obligation.ts":{"49":[28,29,126,31,159,34,35,127],"70":[28,29,126,31,159,34,35,127],"84":[28,29,126,31,159,34,35,127],"88":[28,29,126,31,159,34,35,127],"99":[28,29,126,31,159,34,35,127],"144":[28,29,126,31,159,34,35,127],"153":[28,29,126,31,159,34,35,127],"221":[28,29,126,31,159,34,35,127],"225":[28,29,126,31,159,34,35,127],"268":[28,29,126,31,159,34,35,127],"280":[28,29,126,31,159,34,35,127]},"packages/@n8n/instance-ai/src/workflow-loop/verification-progress.ts":{"8":[28,29,126,31,159,34,35],"15":[28,29,126,31,159,34,35],"16":[28,29,126,31,159,34,35],"17":[28,29,126,31,159,34,35],"22":[28,29,126,31,159,34,35],"23":[28,29,126,31,159,34,35],"25":[28,29,126,31,159,34,35],"26":[28,29,126,31,159,34,35],"30":[28,29,126,31,159,34,35],"38":[28,29,126,31,159,34,35],"40":[28,29,126,31,159,34,35],"43":[28,29,126,31,159,34,35],"47":[28,29,126,31,159,34,35],"56":[28,29,126,31,159,34,35],"57":[28,29,126,31,159,34,35],"58":[28,29,126,31,159,34,35],"61":[28,29,126,31,159,34,35],"62":[28,29,126,31,159,34,35],"67":[28,29,126,31,159,34,35],"68":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/workflow-loop/workflow-loop-controller.ts":{"38":[28,29,126,31,159,34,35],"66":[28,29,126,31,159,34,35],"230":[28,29,126,31,159,34,35],"397":[28,29,126,31,159,34,35],"487":[28,29,126,31,159,34,35],"491":[28,29,126,31,159,34,35],"495":[28,29,126,31,159,34,35],"506":[28,29,126,31,159,34,35],"522":[28,29,126,31,159,34,35],"537":[28,29,126,31,159,34,35],"539":[28,29,126,31,159,34,35],"544":[28,29,126,31,159,34,35],"549":[28,29,126,31,159,34,35],"564":[28,29,126,31,159,34,35],"567":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/workflow-loop/workflow-loop-state.ts":{"47":[28,29,30,126,31,34,35],"57":[28,29,30,126,31,34,35],"63":[28,29,30,126,31,34,35]},"packages/@n8n/instance-ai/src/workflow-loop/workflow-task-service.ts":{"23":[28,29,126,31,159,34,35],"34":[28,29,126,31,159,34,35],"41":[28,29,126,31,159,34,35],"45":[28,29,126,31,159,34,35],"49":[28,29,126,31,159,34,35],"54":[28,29,126,31,159,34,35],"59":[28,29,126,31,159,34,35],"60":[28,29,126,31,159,34,35],"61":[28,29,126,31,159,34,35],"66":[28,29,126,31,159,34,35],"71":[28,29,126,31,159,34,35],"75":[28,29,126,31,159,34,35],"82":[28,29,126,31,159,34,35],"87":[28,29,126,31,159,34,35],"122":[28,29,126,31,159,34,35],"127":[28,29,126,31,159,34,35],"152":[28,29,126,31,159,34,35],"158":[28,29,126,31,159,34,35],"167":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/workspace/builder-templates-service.ts":{"144":[28,29,126,31,159,34,35],"158":[28,29,126,31,159,34,35],"162":[28,29,126,31,159,34,35],"166":[28,29,126,31,159,34,35],"171":[28,29,126,31,159,34,35],"194":[28,29,126,31,159,34,35],"202":[28,29,126,31,159,34,35],"213":[28,29,126,31,159,34,35],"221":[28,29,126,31,159,34,35],"226":[28,29,126,31,159,34,35],"235":[28,29,126,31,159,34,35],"280":[28,29,126,31,159,34,35],"289":[28,29,126,31,159,34,35],"298":[28,29,126,31,159,34,35],"308":[28,29,126,31,159,34,35],"344":[28,29,126,31,159,34,35],"366":[28,29,126,31,159,34,35],"446":[28,29,126,31,159,34,35],"479":[28,29,126,31,159,34,35],"511":[28,29,126,31,159,34,35],"517":[28,29,126,31,159,34,35],"526":[28,29,126,31,159,34,35],"535":[28,29,126,31,159,34,35],"541":[28,29,126,31,159,34,35],"546":[28,29,126,31,159,34,35],"561":[28,29,126,31,159,34,35],"569":[28,29,126,31,159,34,35],"586":[28,29,126,31,159,34,35],"603":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/workspace/compute-workspace-content-hash.ts":{"4":[28,29,126,31,159,34,35],"6":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/workspace/create-workspace.ts":{"38":[28,29,31,159,34,35],"39":[28,29,31,159,34,35],"40":[28,29,31,159,34,35],"41":[28,29,31,159,34,35],"45":[28,29,31,159,34,35],"49":[28,29,31,159,34,35],"67":[28,29,31,159,34,35],"79":[28,29,31,159,34,35],"162":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/workspace/lazy-runtime-workspace.ts":{"53":[28,29,126,31,159,34,35],"70":[28,29,126,31,159,34,35],"71":[28,29,126,31,159,34,35],"83":[28,29,126,31,159,34,35],"85":[28,29,126,31,159,34,35],"89":[28,29,126,31,159,34,35],"94":[28,29,126,31,159,34,35],"98":[28,29,126,31,159,34,35],"100":[28,29,126,31,159,34,35],"104":[28,29,126,31,159,34,35],"118":[28,29,126,31,159,34,35],"122":[28,29,126,31,159,34,35],"128":[28,29,126,31,159,34,35],"140":[28,29,126,31,159,34,35],"149":[28,29,126,31,159,34,35],"158":[28,29,126,31,159,34,35],"167":[28,29,126,31,159,34,35],"180":[28,29,126,31,159,34,35],"185":[28,29,126,31,159,34,35],"188":[28,29,126,31,159,34,35],"193":[28,29,126,31,159,34,35],"197":[28,29,126,31,159,34,35],"201":[28,29,126,31,159,34,35],"207":[28,29,126,31,159,34,35],"211":[28,29,126,31,159,34,35],"228":[28,29,126,31,159,34,35],"234":[28,29,126,31,159,34,35],"236":[28,29,126,31,159,34,35],"240":[28,29,126,31,159,34,35],"247":[28,29,126,31,159,34,35],"253":[28,29,126,31,159,34,35],"260":[28,29,126,31,159,34,35],"266":[28,29,126,31,159,34,35],"270":[28,29,126,31,159,34,35],"276":[28,29,126,31,159,34,35],"286":[28,29,126,31,159,34,35],"292":[28,29,126,31,159,34,35],"302":[28,29,126,31,159,34,35],"308":[28,29,126,31,159,34,35],"312":[28,29,126,31,159,34,35],"318":[28,29,126,31,159,34,35],"322":[28,29,126,31,159,34,35],"328":[28,29,126,31,159,34,35],"332":[28,29,126,31,159,34,35],"336":[28,29,126,31,159,34,35],"340":[28,29,126,31,159,34,35],"342":[28,29,126,31,159,34,35],"349":[28,29,126,31,159,34,35],"360":[28,29,126,31,159,34,35],"365":[28,29,126,31,159,34,35],"368":[28,29,126,31,159,34,35],"373":[28,29,126,31,159,34,35],"379":[28,29,126,31,159,34,35],"386":[28,29,126,31,159,34,35],"390":[28,29,126,31,159,34,35],"408":[28,29,126,31,159,34,35],"415":[28,29,126,31,159,34,35],"417":[28,29,126,31,159,34,35],"426":[28,29,126,31,159,34,35],"441":[28,29,126,31,159,34,35],"442":[28,29,126,31,159,34,35],"447":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/workspace/pack-workspace-sdk.ts":{"76":[28,29,31,159,34,35],"84":[28,29,31,159,34,35],"143":[28,29,31,159,34,35],"175":[28,29,31,159,34,35],"194":[28,29,31,159,34,35],"202":[28,29,31,159,34,35],"235":[28,29,31,159,34,35],"261":[28,29,31,159,34,35],"266":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/workspace/prebaked-workspace-bundle.ts":{"44":[28,29,31,159,34,35],"55":[28,29,31,159,34,35],"59":[28,29,31,159,34,35],"129":[28,29,31,159,34,35],"137":[28,29,31,159,34,35],"144":[28,29,31,159,34,35],"150":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/workspace/sandbox-fs.ts":{"61":[28,29,126,31,159,34,35],"65":[28,29,126,31,159,34,35],"67":[28,29,126,31,159,34,35],"68":[28,29,126,31,159,34,35],"72":[28,29,126,31,159,34,35],"81":[28,29,126,31,159,34,35],"87":[28,29,126,31,159,34,35],"110":[28,29,126,31,159,34,35],"124":[28,29,126,31,159,34,35],"139":[28,29,126,31,159,34,35],"160":[28,29,126,31,159,34,35],"172":[28,29,126,31,159,34,35],"174":[28,29,126,31,159,34,35],"175":[28,29,126,31,159,34,35],"225":[28,29,126,31,159,34,35],"235":[28,29,126,31,159,34,35],"239":[28,29,126,31,159,34,35],"241":[28,29,126,31,159,34,35],"258":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/workspace/sandbox-setup.ts":{"75":[28,29,126,31,159,34,35],"84":[28,29,126,31,159,34,35],"97":[28,29,126,31,159,34,35],"142":[28,29,126,31,159,34,35],"182":[28,29,126,31,159,34,35],"198":[28,29,126,31,159,34,35],"239":[28,29,126,31,159,34,35],"246":[28,29,126,31,159,34,35],"253":[28,29,126,31,159,34,35],"277":[28,29,126,31,159,34,35],"296":[28,29,126,31,159,34,35],"338":[28,29,126,31,159,34,35],"355":[28,29,126,31,159,34,35],"366":[28,29,126,31,159,34,35],"369":[28,29,126,31,159,34,35],"375":[28,29,126,31,159,34,35],"381":[28,29,126,31,159,34,35],"394":[28,29,126,31,159,34,35],"410":[28,29,126,31,159,34,35],"431":[28,29,126,31,159,34,35],"444":[28,29,126,31,159,34,35],"454":[28,29,126,31,159,34,35],"471":[28,29,126,31,159,34,35],"477":[28,29,126,31,159,34,35],"497":[28,29,126,31,159,34,35],"504":[28,29,126,31,159,34,35],"505":[28,29,126,31,159,34,35],"508":[28,29,126,31,159,34,35],"515":[28,29,126,31,159,34,35],"534":[28,29,126,31,159,34,35],"543":[28,29,126,31,159,34,35],"548":[28,29,126,31,159,34,35],"552":[28,29,126,31,159,34,35],"583":[28,29,126,31,159,34,35],"589":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/workspace/sandbox-typescript.ts":{"27":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/workspace/snapshot-image-context.ts":{"18":[28,29,31,159,34,35],"30":[28,29,31,159,34,35],"48":[28,29,31,159,34,35],"62":[28,29,31,159,34,35],"68":[28,29,31,159,34,35],"78":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/workspace/snapshot-manager.ts":{"89":[28,29,31,159,34,35],"103":[28,29,31,159,34,35],"114":[28,29,31,159,34,35],"126":[28,29,31,159,34,35],"138":[28,29,31,159,34,35],"148":[28,29,31,159,34,35],"152":[28,29,31,159,34,35],"166":[28,29,31,159,34,35],"176":[28,29,31,159,34,35],"189":[28,29,31,159,34,35],"198":[28,29,31,159,34,35],"203":[28,29,31,159,34,35],"230":[28,29,31,159,34,35],"261":[28,29,31,159,34,35],"323":[28,29,31,159,34,35],"383":[28,29,31,159,34,35],"420":[28,29,31,159,34,35],"457":[28,29,31,159,34,35],"502":[28,29,31,159,34,35],"599":[28,29,31,159,34,35],"624":[28,29,31,159,34,35],"629":[28,29,31,159,34,35],"631":[28,29,31,159,34,35],"633":[28,29,31,159,34,35],"638":[28,29,31,159,34,35],"659":[28,29,31,159,34,35],"663":[28,29,31,159,34,35],"677":[28,29,31,159,34,35],"707":[28,29,31,159,34,35],"712":[28,29,31,159,34,35],"719":[28,29,31,159,34,35],"728":[28,29,31,159,34,35],"730":[28,29,31,159,34,35],"738":[28,29,31,159,34,35],"747":[28,29,31,159,34,35],"752":[28,29,31,159,34,35],"762":[28,29,31,159,34,35],"767":[28,29,31,159,34,35],"785":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/workspace/template-telemetry.ts":{"59":[28,29,126,31,159,34,35],"74":[28,29,126,31,159,34,35],"78":[28,29,126,31,159,34,35],"88":[28,29,126,31,159,34,35],"97":[28,29,126,31,159,34,35],"125":[28,29,126,31,159,34,35],"144":[28,29,126,31,159,34,35],"149":[28,29,126,31,159,34,35],"159":[28,29,126,31,159,34,35],"166":[28,29,126,31,159,34,35],"176":[28,29,126,31,159,34,35],"187":[28,29,126,31,159,34,35],"195":[28,29,126,31,159,34,35],"200":[28,29,126,31,159,34,35],"224":[28,29,126,31,159,34,35],"229":[28,29,126,31,159,34,35],"260":[28,29,126,31,159,34,35],"279":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/workspace/workspace-file-content.ts":{"2":[28,29,31,159,34,35],"7":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/workspace/workspace-files.ts":{"39":[28,29,126,31,159,34,35],"43":[28,29,126,31,159,34,35],"47":[28,29,126,31,159,34,35],"57":[28,29,126,31,159,34,35],"67":[28,29,126,31,159,34,35],"71":[28,29,126,31,159,34,35],"79":[28,29,126,31,159,34,35],"129":[28,29,126,31,159,34,35],"138":[28,29,126,31,159,34,35],"145":[28,29,126,31,159,34,35],"160":[28,29,126,31,159,34,35],"192":[28,29,126,31,159,34,35],"203":[28,29,126,31,159,34,35],"206":[28,29,126,31,159,34,35],"208":[28,29,126,31,159,34,35]},"packages/@n8n/instance-ai/src/workspace/workspace-manifest.ts":{"17":[28,29,31,159,34,35]},"packages/@n8n/instance-ai/src/workspace/workspace-paths.ts":{"12":[28,29,126,31,159,34,35],"21":[28,29,126,31,159,34,35],"31":[28,29,126,31,159,34,35],"39":[28,29,126,31,159,34,35],"50":[28,29,126,31,159,34,35]},"packages/@n8n/telemetry/src/index.ts":{"3":[28,29,30,126,31,32,33,159,34,35],"14":[28,29,30,126,31,32,33,159,34,35],"16":[28,29,30,126,31,32,33,159,34,35]},"packages/@n8n/telemetry/src/redaction.ts":{"57":[86,124,28,29,126,31,159,34,35],"81":[86,124,28,29,126,31,159,34,35],"88":[86,124,28,29,126,31,159,34,35],"92":[86,124,28,29,126,31,159,34,35],"109":[86,124,28,29,126,31,159,34,35],"135":[86,124,28,29,126,31,159,34,35]},"packages/@n8n/telemetry/src/validate.ts":{"19":"b:IAEA8B8AAADAAEQQDgAA0EACAIQLBAEoAAIkAAA=","23":[86,124,28,29,30,126,31,32,33,159,34,35],"27":"b:IAEA8B8AAADAAEQQDgAA0EACAIQLBAEoAAIkAAA=","31":"b:IAEA8B8AAADAAEQQDgAA0EACAIQLBAEoAAIkAAA=","35":"b:IAEA8B8AAADAAEQQDgAA0EACAIQLBAEoAAIkAAA=","39":"b:IAEA8B8AAADAAEQQDgAA0EACAIQLBAEoAAIkAAA=","43":"b:IAEA8B8AAADAAEQQDgAA0EACAIQLBAEoAAIkAAA=","54":"b:IAEA8B8AAADAAEQQDgAA0EACAIQLBAEoAAIkAAA=","58":[86,124,28,29,30,126,31,32,33,159,34,35],"62":"b:IAEA8B8AAADAAEQQDgAA0EACAIQLBAEoAAIkAAA=","74":"b:IAEA8B8AAADAAEQQDgAA0EACAIQLBAEoAAIkAAA=","104":[86,124,28,29,30,126,31,32,33,159,34,35,71],"111":[86,124,28,29,30,126,31,32,33,159,34,35],"117":[86,124,28,29,30,126,31,32,33,159,34,35],"121":[86,124,28,29,30,126,31,32,33,159,34,35],"122":[86,124,28,29,30,126,31,32,33,159,34,35],"130":"b:IAEA8B8AAADAAEQQDgAA0EACAIQLBAEoAAIkAAA="},"packages/@n8n/utils/src/errors/error-chain.ts":{"4":[159,160,35,49],"13":[159,160,35,49]},"packages/@n8n/utils/src/errors/get-error-message.ts":{"2":[86,124,159,160,35,38]},"packages/@n8n/utils/src/json/to-json-value.ts":{"16":[83,28,29,126,34,35],"49":[83,28,29,126,34,35]},"packages/@n8n/utils/src/lazy-import.ts":{"15":[11,28,29,31,159,34,35,110,38]},"packages/@n8n/utils/src/redaction/redact-text.ts":{"40":[83,86,124,125,28,29,126,31,159,34,35,221],"54":[83,86,124,125,28,29,126,31,159,34,35,221],"55":[83,86,124,125,28,29,126,31,159,34,35,221],"64":[83,86,124,125,28,29,31,159,34,35,221],"84":[83,86,124,125,28,29,31,159,34,35,221],"95":[83,86,124,125,28,29,31,159,34,35,221],"101":[83,86,124,125,28,29,31,159,34,35,221],"106":[83,86,124,125,28,29,31,159,34,35,221],"119":[83,125,28,29,31,159,34,35,221],"163":[83,125,28,29,31,159,34,35,221],"171":[83,125,28,29,31,159,34,35,221],"198":[83,125,28,29,31,159,34,35,221]},"packages/@n8n/utils/src/redaction/sensitive-key.ts":{"7":[83,125,28,29,31,159,34,35,221]},"packages/@n8n/utils/src/scrub-secrets.ts":{"123":[83,86,124,28,29,31,159,34,35]},"packages/@n8n/workflow-sdk/src/ast-interpreter/parser.ts":{"20":[126,35]},"packages/@n8n/workflow-sdk/src/codegen/code-generator.ts":{"109":[126,35],"127":[126,35],"136":[126,35],"144":[126,35],"195":[126,35],"224":[126,35],"235":[126,35],"259":[126,35],"263":[126,35],"308":[126,35],"339":[126,35],"390":[126,35],"419":[126,35],"430":[126,35],"454":[126,35],"469":[126,35],"521":[126,35],"527":[126,35],"543":[126,35],"577":[126,35],"592":[126,35],"628":[126,35],"673":[126,35],"719":[126,35],"740":[126,35],"766":[126,35],"781":[126,35],"801":[126,35],"808":[126,35],"816":[126,35],"827":[126,35],"861":[126,35],"874":[126,35],"889":[126,35],"894":[126,35],"909":[126,35],"914":[126,35],"930":[126,35],"949":[126,35],"964":[126,35],"1019":[126,35],"1027":[126,35],"1037":[126,35],"1055":[126,35],"1065":[126,35],"1093":[126,35],"1120":[126,35],"1148":[126,35],"1230":[126,35],"1242":[126,35],"1252":[126,35],"1260":[126,35],"1274":[126,35],"1290":[126,35],"1346":[126,35],"1401":[126,35],"1534":[126,35]},"packages/@n8n/workflow-sdk/src/codegen/composite-builder.ts":{"50":[126,35],"77":[126,35],"144":[126,35],"185":[126,35],"328":[126,35],"355":[126,35],"387":[126,35],"454":[126,35],"491":[126,35],"528":[126,35],"586":[126,35],"701":[126,35],"814":[126,35],"969":[126,35],"1067":[126,35],"1162":[126,35],"1196":[126,35],"1275":[126,35],"1284":[126,35]},"packages/@n8n/workflow-sdk/src/codegen/composite-handlers/build-utils.ts":{"19":[126,35],"42":[126,35],"53":[126,35],"65":[126,35],"75":[126,35],"82":[126,35],"89":[126,35],"103":[126,35],"134":[126,35],"142":[126,35],"146":[126,35],"157":[126,35],"166":[126,35],"171":[126,35]},"packages/@n8n/workflow-sdk/src/codegen/emit-instance-ai.ts":{"21":[126,35],"84":[126,35],"101":[126,35],"110":[126,35],"124":[126,35],"148":[126,35],"149":[126,35],"162":[126,35],"170":[126,35],"186":[126,35],"205":[126,35]},"packages/@n8n/workflow-sdk/src/codegen/execution-status.ts":{"17":[126,35],"46":[126,35],"61":[126,35],"63":[126,35]},"packages/@n8n/workflow-sdk/src/codegen/expression-annotator.ts":{"11":[126,35],"35":[126,35]},"packages/@n8n/workflow-sdk/src/codegen/graph-annotator.ts":{"16":[126,35],"20":[126,35],"79":[126,35],"104":[126,35],"114":[126,35],"141":[126,35],"157":[126,35]},"packages/@n8n/workflow-sdk/src/codegen/index.ts":{"66":[28,29,126,31,159,34,35,127,110,38],"67":[28,29,126,31,159,34,35,127,110,38],"69":[28,29,126,31,159,34,35,127,110,38],"87":[28,29,126,31,159,34,35,127,110,38],"114":[28,29,126,31,159,34,35,127,110,38]},"packages/@n8n/workflow-sdk/src/codegen/locate-node-declarations.ts":{"26":[126,35],"35":[126,35],"51":[126,35],"64":[126,35],"70":[126,35],"83":[126,35]},"packages/@n8n/workflow-sdk/src/codegen/node-type-utils.ts":{"10":[126,35],"17":[126,35],"24":[126,35],"32":[126,35],"39":[126,35]},"packages/@n8n/workflow-sdk/src/codegen/output-utils.ts":{"24":[126,35],"41":[126,35],"62":[126,35],"75":[126,35],"92":[126,35],"107":[126,35],"114":[126,35]},"packages/@n8n/workflow-sdk/src/codegen/semantic-graph.ts":{"20":[126,35],"44":[126,35],"52":[126,35],"60":[126,35],"98":[126,35],"139":[126,35],"148":[126,35],"151":[126,35],"168":[126,35],"206":[126,35],"240":[126,35],"329":[126,35],"352":[126,35],"384":[126,35]},"packages/@n8n/workflow-sdk/src/codegen/semantic-registry.ts":{"42":[126,35],"48":[126,35],"57":[126,35],"60":[126,35],"76":[126,35],"85":[126,35],"105":[126,35],"137":[126,35],"158":[126,35],"169":[126,35],"199":[126,35]},"packages/@n8n/workflow-sdk/src/codegen/string-utils.ts":{"9":[126,35],"27":[126,35],"38":[126,35],"48":[126,35],"62":[126,35],"107":[126,35],"113":[126,35],"124":[126,35],"132":[126,35],"139":[126,35],"147":[126,35],"155":[126,35]},"packages/@n8n/workflow-sdk/src/codegen/subnode-generator.ts":{"33":[126,35],"42":[126,35],"95":[126,35],"113":[126,35],"120":[126,35],"123":[126,35],"133":[126,35],"138":[126,35],"141":[126,35],"150":[126,35],"159":[126,35],"187":[126,35],"192":[126,35],"201":[126,35],"210":[126,35],"218":[126,35],"226":[126,35],"246":[126,35],"255":[126,35],"298":[126,35],"328":[126,35],"347":[126,35],"373":[126,35],"382":[126,35],"403":[126,35],"425":[126,35],"434":[126,35]},"packages/@n8n/workflow-sdk/src/codegen/variable-names.ts":{"102":[126,35],"115":[126,35],"120":[126,35],"151":[126,35],"162":[126,35]},"packages/@n8n/workflow-sdk/src/constants/node-types.ts":{"24":[28,126,34,35],"31":[28,126,34,35],"38":[28,126,34,35],"45":[28,126,34,35],"52":[28,126,34,35],"59":[28,126,34,35],"66":[28,126,34,35],"73":[28,126,34,35]},"packages/@n8n/workflow-sdk/src/generate-types/index.ts":{"82":[126,34,35,127,110,38]},"packages/@n8n/workflow-sdk/src/index.ts":{"114":[28,29,126,31,159,34,35,127,110,38],"127":[28,29,126,31,159,34,35,127,110,38],"194":[28,29,126,31,159,34,35,127,110,38],"199":[28,29,126,31,159,34,35,127,110,38],"276":[28,29,126,31,159,34,35,127,110,38]},"packages/@n8n/workflow-sdk/src/lint/ast-walk.ts":{"5":[126,35],"13":[126,35],"41":[126,35]},"packages/@n8n/workflow-sdk/src/lint/sdk/workflow-sdk-lint.ts":{"65":[126,35],"70":[126,35],"71":[126,35],"106":[126,35],"111":[126,35],"115":[126,35],"124":[126,35],"143":[126,35],"145":[126,35],"160":[126,35],"204":[126,35],"224":[126,35],"238":[126,35],"316":[126,35],"333":[126,35],"341":[126,35],"354":[126,35],"376":[126,35],"544":[126,35],"552":[126,35]},"packages/@n8n/workflow-sdk/src/mock-data/context.ts":{"23":[28,126,34,35],"29":[28,126,34,35],"75":[28,126,34,35],"89":[28,126,34,35],"97":[28,126,34,35],"115":[28,126,34,35],"136":[28,126,34,35],"179":[28,126,34,35],"198":[28,126,34,35],"224":[28,126,34,35],"257":[28,126,34,35]},"packages/@n8n/workflow-sdk/src/mock-data/index.ts":{"40":[28,126,34,35,127,110,38]},"packages/@n8n/workflow-sdk/src/prompts/best-practices/guides/chatbot.ts":{"4":[28,126,34,35],"125":[28,126,34,35]},"packages/@n8n/workflow-sdk/src/prompts/best-practices/guides/content-generation.ts":{"4":[28,126,34,35],"111":[28,126,34,35]},"packages/@n8n/workflow-sdk/src/prompts/best-practices/guides/data-extraction.ts":{"4":[28,126,34,35],"118":[28,126,34,35]},"packages/@n8n/workflow-sdk/src/prompts/best-practices/guides/data-persistence.ts":{"4":[28,126,34,35],"193":[28,126,34,35]},"packages/@n8n/workflow-sdk/src/prompts/best-practices/guides/data-transformation.ts":{"4":[28,126,34,35],"142":[28,126,34,35]},"packages/@n8n/workflow-sdk/src/prompts/best-practices/guides/document-processing.ts":{"4":[28,126,34,35],"328":[28,126,34,35]},"packages/@n8n/workflow-sdk/src/prompts/best-practices/guides/form-input.ts":{"4":[28,126,34,35],"169":[28,126,34,35]},"packages/@n8n/workflow-sdk/src/prompts/best-practices/guides/notification.ts":{"4":[28,126,34,35],"131":[28,126,34,35]},"packages/@n8n/workflow-sdk/src/prompts/best-practices/guides/scheduling.ts":{"4":[28,126,34,35],"148":[28,126,34,35]},"packages/@n8n/workflow-sdk/src/prompts/best-practices/guides/scraping-and-research.ts":{"4":[28,126,34,35],"154":[28,126,34,35]},"packages/@n8n/workflow-sdk/src/prompts/best-practices/guides/triage.ts":{"4":[28,126,34,35],"145":[28,126,34,35]},"packages/@n8n/workflow-sdk/src/prompts/best-practices/guides/web-app.ts":{"4":[28,126,34,35],"200":[28,126,34,35]},"packages/@n8n/workflow-sdk/src/prompts/best-practices/index.ts":{"1":[28,126,34,35],"4":[28,126,34,35],"7":[28,126,34,35],"8":[28,126,34,35],"14":[28,126,34,35],"19":[28,126,34,35],"20":[28,126,34,35]},"packages/@n8n/workflow-sdk/src/prompts/sdk-reference/index.ts":{"3":[28,29,31,159,34,35]},"packages/@n8n/workflow-sdk/src/types/base.ts":{"173":[28,126,34,35],"204":[28,126,34,35],"243":[28,126,34,35],"290":[28,126,34,35],"669":[28,126,34,35],"685":[28,126,34,35],"708":[28,126,34,35],"712":[28,126,34,35]},"packages/@n8n/workflow-sdk/src/utils/trigger-detection.ts":{"30":[28,126,34,35]},"packages/@n8n/workflow-sdk/src/utils/workflow-json-engine-helpers.ts":{"32":[28,126,34,35],"40":[28,126,34,35],"41":[28,126,34,35],"58":[28,126,34,35],"59":[28,126,34,35],"70":[28,126,34,35]},"packages/@n8n/workflow-sdk/src/validation/display-options.ts":{"77":[28,126,34,35],"90":[28,126,34,35],"98":[28,126,34,35],"115":[28,126,34,35],"156":[28,126,34,35],"157":[28,126,34,35],"167":[28,126,34,35],"231":[28,126,34,35],"274":[28,126,34,35],"289":[28,126,34,35],"311":[28,126,34,35],"332":[28,126,34,35],"333":[28,126,34,35],"349":[28,126,34,35]},"packages/@n8n/workflow-sdk/src/validation/issue-severity.ts":{"13":[28,126,34,35],"20":[28,126,34,35]},"packages/@n8n/workflow-sdk/src/validation/node-parameter-schema/resolve-schema.ts":{"17":[28,126,34,35,127],"65":[28,126,34,35,127],"74":[28,126,34,35,127],"86":[28,126,34,35,127],"95":[28,126,34,35,127],"142":[28,126,34,35,127],"150":[28,126,34,35,127],"166":[28,126,34,35,127],"202":[28,126,34,35,127],"220":[28,126,34,35,127],"223":[28,126,34,35,127],"225":[28,126,34,35,127]},"packages/@n8n/workflow-sdk/src/validation/node-parameter-schema/schema-helpers.ts":{"8":[28,126,34,35],"33":[28,126,34,35]},"packages/@n8n/workflow-sdk/src/validation/node-parameter-schema/schema-validator.ts":{"45":[28,29,126,31,159,34,35,127,110,38],"53":[28,29,126,31,159,34,35,127,110,38],"66":[28,29,126,31,159,34,35,127,110,38],"78":[28,29,126,31,159,34,35,127,110,38],"92":[28,29,126,31,159,34,35,127,110,38],"107":[28,29,126,31,159,34,35,127,110,38],"126":[28,29,126,31,159,34,35,127,110,38],"152":[28,29,126,31,159,34,35,127,110,38],"173":[28,29,126,31,159,34,35,127,110,38],"193":[28,29,126,31,159,34,35,127,110,38],"225":[28,29,126,31,159,34,35,127,110,38],"234":[28,29,126,31,159,34,35,127,110,38],"254":[28,29,126,31,159,34,35,127,110,38],"308":[28,29,126,31,159,34,35,127,110,38],"336":[28,29,126,31,159,34,35,127,110,38],"352":[28,29,126,31,159,34,35,127,110,38],"365":[28,29,126,31,159,34,35,127,110,38],"387":[28,29,126,31,159,34,35,127,110,38],"411":[28,29,126,31,159,34,35,127,110,38],"412":[28,29,126,31,159,34,35,127,110,38],"422":[28,29,126,31,159,34,35,127,110,38],"423":[28,29,126,31,159,34,35,127,110,38],"435":[28,29,126,31,159,34,35,127,110,38],"480":[28,29,126,31,159,34,35,127,110,38],"505":[28,29,126,31,159,34,35,127,110,38],"517":[28,29,126,31,159,34,35,127,110,38],"519":[28,29,126,31,159,34,35,127,110,38],"526":[28,29,126,31,159,34,35,127,110,38],"529":[28,29,126,31,159,34,35,127,110,38],"532":[28,29,126,31,159,34,35,127,110,38],"585":[28,29,126,31,159,34,35,127,110,38],"593":[28,29,126,31,159,34,35,127,110,38],"596":[28,29,126,31,159,34,35,127,110,38],"617":[28,29,126,31,159,34,35,127,110,38],"630":[28,29,126,31,159,34,35,127,110,38],"633":[28,29,126,31,159,34,35,127,110,38],"635":[28,29,126,31,159,34,35,127,110,38],"654":[28,29,126,31,159,34,35,127,110,38],"663":[28,29,126,31,159,34,35,127,110,38],"665":[28,29,126,31,159,34,35,127,110,38],"673":[28,29,126,31,159,34,35,127,110,38],"688":[28,29,126,31,159,34,35,127,110,38],"703":[28,29,126,31,159,34,35,127,110,38],"705":[28,29,126,31,159,34,35,127,110,38],"725":[28,29,126,31,159,34,35,127,110,38],"745":[28,29,126,31,159,34,35,127,110,38],"746":[28,29,126,31,159,34,35,127,110,38],"759":[28,29,126,31,159,34,35,127,110,38],"776":[28,29,126,31,159,34,35,127,110,38],"802":[28,29,126,31,159,34,35,127,110,38],"803":[28,29,126,31,159,34,35,127,110,38]},"packages/@n8n/workflow-sdk/src/validation/node-port-resolvers/resolve-main-input-count.ts":{"16":[28,126,34,35],"31":[28,126,34,35]},"packages/@n8n/workflow-sdk/src/validation/node-port-resolvers/resolve-main-output-count.ts":{"16":[28,126,34,35],"31":[28,126,34,35]},"packages/@n8n/workflow-sdk/src/validation/validate-workflow.ts":{"71":[28,126,34,35],"102":[28,126,34,35],"121":[28,126,34,35],"221":[28,126,34,35],"293":[28,126,34,35],"356":[28,126,34,35],"391":[28,126,34,35],"411":[28,126,34,35],"429":[28,126,34,35],"470":[28,126,34,35],"483":[28,126,34,35],"485":[28,126,34,35],"486":[28,126,34,35],"487":[28,126,34,35],"506":[28,126,34,35],"542":[28,126,34,35],"600":[28,126,34,35],"624":[28,126,34,35],"711":[28,126,34,35],"797":[28,126,34,35],"852":[28,126,34,35],"885":[28,126,34,35],"946":[28,126,34,35],"954":[28,126,34,35],"955":[28,126,34,35],"977":[28,126,34,35],"990":[28,126,34,35],"1004":[28,126,34,35],"1026":[28,126,34,35],"1109":[28,126,34,35],"1148":[28,126,34,35],"1183":[28,126,34,35],"1195":[28,126,34,35],"1219":[28,126,34,35],"1251":[28,126,34,35],"1281":[28,126,34,35],"1294":[28,126,34,35],"1301":[28,126,34,35],"1309":[28,126,34,35],"1314":[28,126,34,35],"1321":[28,126,34,35],"1348":[28,126,34,35],"1406":[28,126,34,35],"1450":[28,126,34,35],"1499":[28,126,34,35]},"packages/@n8n/workflow-sdk/src/workflow-builder/layout-utils.ts":{"67":[28,126,34,35],"84":[28,126,34,35],"140":[28,126,34,35],"144":[28,126,34,35],"159":[28,126,34,35],"172":[28,126,34,35],"179":[28,126,34,35],"180":[28,126,34,35],"187":[28,126,34,35],"195":[28,126,34,35],"212":[28,126,34,35],"232":[28,126,34,35],"268":[28,126,34,35],"272":[28,126,34,35],"282":[28,126,34,35],"302":[28,126,34,35],"313":[28,126,34,35],"316":[28,126,34,35],"318":[28,126,34,35],"327":[28,126,34,35],"332":[28,126,34,35],"340":[28,126,34,35],"350":[28,126,34,35],"379":[28,126,34,35],"387":[28,126,34,35],"398":[28,126,34,35],"402":[28,126,34,35],"404":[28,126,34,35],"415":[28,126,34,35],"424":[28,126,34,35],"430":[28,126,34,35],"434":[28,126,34,35],"449":[28,126,34,35],"458":[28,126,34,35],"466":[28,126,34,35],"475":[28,126,34,35],"496":[28,126,34,35],"516":[28,126,34,35],"524":[28,126,34,35],"529":[28,126,34,35],"532":[28,126,34,35],"536":[28,126,34,35],"537":[28,126,34,35],"543":[28,126,34,35],"550":[28,126,34,35],"553":[28,126,34,35],"563":[28,126,34,35],"567":[28,126,34,35],"569":[28,126,34,35],"580":[28,126,34,35],"588":[28,126,34,35],"606":[28,126,34,35],"624":[28,126,34,35],"633":[28,126,34,35],"635":[28,126,34,35],"638":[28,126,34,35],"647":[28,126,34,35],"655":[28,126,34,35],"660":[28,126,34,35],"661":[28,126,34,35],"667":[28,126,34,35],"668":[28,126,34,35],"686":[28,126,34,35],"691":[28,126,34,35],"693":[28,126,34,35],"695":[28,126,34,35],"705":[28,126,34,35],"712":[28,126,34,35],"722":[28,126,34,35],"734":[28,126,34,35],"738":[28,126,34,35],"748":[28,126,34,35],"757":[28,126,34,35],"766":[28,126,34,35],"795":[28,126,34,35],"814":[28,126,34,35],"819":[28,126,34,35],"820":[28,126,34,35],"823":[28,126,34,35],"824":[28,126,34,35],"832":[28,126,34,35],"833":[28,126,34,35],"851":[28,126,34,35],"862":[28,126,34,35],"870":[28,126,34,35],"871":[28,126,34,35],"897":[28,126,34,35],"901":[28,126,34,35],"906":[28,126,34,35],"918":[28,126,34,35],"921":[28,126,34,35],"942":[28,126,34,35],"949":[28,126,34,35],"962":[28,126,34,35],"971":[28,126,34,35],"980":[28,126,34,35],"981":[28,126,34,35],"983":[28,126,34,35],"1010":[28,126,34,35],"1017":[28,126,34,35],"1056":[28,126,34,35],"1083":[28,126,34,35],"1090":[28,126,34,35],"1120":[28,126,34,35],"1122":[28,126,34,35],"1126":[28,126,34,35]},"packages/@n8n/workflow-sdk/src/workflow-builder/workflow-import.ts":{"45":[28,126,34,35],"98":[28,126,34,35],"101":[28,126,34,35],"104":[28,126,34,35],"107":[28,126,34,35],"110":[28,126,34,35],"128":[28,126,34,35],"139":[28,126,34,35],"180":[28,126,34,35],"202":[28,126,34,35],"206":[28,126,34,35]},"packages/cli/src/credentials/instance-credential-broker.ts":{"28":[83,16,28,29,30,31,32,33,34,35],"35":[83,16,28,29,30,31,32,33,34,35],"39":[83,16,28,29,30,31,32,33,34,35],"44":[83,16,28,29,30,31,32,33,34,35],"62":[83,16,28,29,30,31,32,33,34,35],"67":[83,16,28,29,30,31,32,33,34,35],"75":[83,16,28,29,30,31,32,33,34,35],"103":[83,16,28,29,30,31,32,33,34,35]},"packages/cli/src/metrics/prometheus/instance-ai-metrics.service.ts":{"17":[15,28,29,30,92,31,159,34,35],"23":[15,28,29,30,92,31,159,34,35],"28":[15,28,29,30,92,31,159,34,35],"76":[15,28,29,30,92,31,159,34,35],"84":[15,28,29,30,92,31,159,34,35],"146":[15,28,29,30,92,31,159,34,35],"150":[15,28,29,30,92,31,159,34,35],"153":[15,28,29,30,92,31,159,34,35],"156":[15,28,29,30,92,31,159,34,35],"159":[15,28,29,30,92,31,159,34,35],"163":[15,28,29,30,92,31,159,34,35],"166":[15,28,29,30,92,31,159,34,35],"172":[15,28,29,30,92,31,159,34,35]},"packages/cli/src/middlewares/list-query/dtos/base.select.dto.ts":{"7":[28,126,31,34,35,216,81],"12":[28,126,31,34,35,216,81]},"packages/cli/src/middlewares/list-query/dtos/workflow.filter.dto.ts":{"98":"b:AAABkwy4AIgggAIjCAAAQgAAgAAIAAAABAgAAAA="},"packages/cli/src/middlewares/list-query/dtos/workflow.select.dto.ts":{"4":[28,126,31,34,35,216,81],"22":[28,126,31,34,35,216,81]},"packages/cli/src/modules/agents/instance-ai-agent-context.adapter.ts":{"36":[28,29,31,159,34,35],"52":[28,29,31,159,34,35],"54":[28,29,31,159,34,35],"69":[28,29,31,159,34,35],"79":[28,29,31,159,34,35],"91":[28,29,31,159,34,35],"94":[28,29,31,159,34,35],"111":[28,29,31,159,34,35],"119":[28,29,31,159,34,35],"149":[28,29,31,159,34,35],"191":[28,29,31,159,34,35],"213":[28,29,31,159,34,35],"217":[28,29,31,159,34,35]},"packages/cli/src/modules/agents/instance-ai-builder-delegate.adapter.ts":{"46":[28,29,92,31,159,34,35],"55":[28,29,92,31,159,34,35],"60":[28,29,92,31,159,34,35],"64":[28,29,92,31,159,34,35],"69":[28,29,92,31,159,34,35],"97":[28,29,92,31,159,34,35],"108":[28,29,92,31,159,34,35],"128":[28,29,92,31,159,34,35],"143":[28,29,92,31,159,34,35],"150":[28,29,92,31,159,34,35],"165":[28,29,92,31,159,34,35],"179":[28,29,92,31,159,34,35],"187":[28,29,92,31,159,34,35],"202":[28,29,92,31,159,34,35],"210":[28,29,92,31,159,34,35],"218":[28,29,92,31,159,34,35],"219":[28,29,92,31,159,34,35],"222":[28,29,92,31,159,34,35],"227":[28,29,92,31,159,34,35],"231":[28,29,92,31,159,34,35],"236":[28,29,92,31,159,34,35],"259":[28,29,92,31,159,34,35]},"packages/cli/src/modules/agents/model-stream-stall-options.ts":{"16":[83,28,29,31,159,34,35],"29":[83,28,29,31,159,34,35]},"packages/cli/src/modules/instance-ai/browser/composite-local-mcp-server.ts":{"4":[28,29,31,159,34,35],"7":[28,29,31,159,34,35],"25":[28,29,31,159,34,35],"26":[28,29,31,159,34,35],"29":[28,29,31,159,34,35],"33":[28,29,31,159,34,35],"37":[28,29,31,159,34,35],"43":[28,29,31,159,34,35],"58":[28,29,31,159,34,35],"59":[28,29,31,159,34,35],"62":[28,29,31,159,34,35]},"packages/cli/src/modules/instance-ai/browser/instance-ai-browser-session.service.ts":{"66":[16,28,29,30,31,33,159,34,35],"78":[16,28,29,30,31,33,159,34,35],"96":[16,28,29,30,31,33,159,34,35],"105":[16,28,29,30,31,33,159,34,35],"114":[16,28,29,30,31,33,159,34,35],"119":[16,28,29,30,31,33,159,34,35],"123":[16,28,29,30,31,33,159,34,35],"132":[16,28,29,30,31,33,159,34,35],"143":[16,28,29,30,31,33,159,34,35],"158":[16,28,29,30,31,33,159,34,35],"167":[16,28,29,30,31,33,159,34,35],"174":[16,28,29,30,31,33,159,34,35],"175":[16,28,29,30,31,33,159,34,35],"190":[16,28,29,30,31,33,159,34,35],"213":[16,28,29,30,31,33,159,34,35],"226":[16,28,29,30,31,33,159,34,35],"250":[16,28,29,30,31,33,159,34,35],"262":[16,28,29,30,31,33,159,34,35],"277":[16,28,29,30,31,33,159,34,35],"282":[16,28,29,30,31,33,159,34,35],"294":[16,28,29,30,31,33,159,34,35],"305":[16,28,29,30,31,33,159,34,35],"321":[16,28,29,30,31,33,159,34,35],"326":[16,28,29,30,31,33,159,34,35],"330":[16,28,29,30,31,33,159,34,35],"337":[16,28,29,30,31,33,159,34,35],"340":[16,28,29,30,31,33,159,34,35],"345":[16,28,29,30,31,33,159,34,35],"348":[16,28,29,30,31,33,159,34,35]},"packages/cli/src/modules/instance-ai/computer-use-availability.ts":{"8":[28,29,31,159,34,35],"11":[28,29,31,159,34,35],"14":[28,29,31,159,34,35],"35":[28,29,31,159,34,35],"62":[28,29,31,159,34,35]},"packages/cli/src/modules/instance-ai/drop-rejected-attachments.ts":{"12":[160,35],"28":[160,35],"34":[160,35],"74":[160,35]},"packages/cli/src/modules/instance-ai/eval/thread-credential-allowlist.service.ts":{"10":[28,29,92,31,159,34,35],"17":[28,29,92,31,159,34,35],"25":[28,29,92,31,159,34,35],"29":[28,29,92,31,159,34,35],"40":[28,29,92,31,159,34,35],"44":[28,29,92,31,159,34,35]},"packages/cli/src/modules/instance-ai/event-bus/durable-event-log.ts":{"70":[28,29,30,92,31,34,35],"74":[28,29,30,92,31,34,35],"76":[28,29,30,92,31,34,35],"139":[28,29,30,92,31,34,35],"148":[28,29,30,92,31,34,35],"159":[28,29,30,92,31,34,35],"162":[28,29,30,92,31,34,35],"164":[28,29,30,92,31,34,35],"183":[28,29,30,92,31,34,35],"232":[28,29,30,92,31,34,35],"244":[28,29,30,92,31,34,35],"248":[28,29,30,92,31,34,35],"253":[28,29,30,92,31,34,35],"259":[28,29,30,92,31,34,35],"269":[28,29,30,92,31,34,35],"281":[28,29,30,92,31,34,35],"302":[28,29,30,92,31,34,35],"317":[28,29,30,92,31,34,35],"332":[28,29,30,92,31,34,35],"344":[28,29,30,92,31,34,35],"357":[28,29,30,92,31,34,35],"362":[28,29,30,92,31,34,35],"372":[28,29,30,92,31,34,35],"390":[28,29,30,92,31,34,35],"392":[28,29,30,92,31,34,35],"418":[28,29,30,92,31,34,35],"421":[28,29,30,92,31,34,35],"500":[28,29,30,92,31,34,35],"510":[28,29,30,92,31,34,35],"535":[28,29,30,92,31,34,35],"611":[28,29,30,92,31,34,35],"625":[28,29,30,92,31,34,35],"651":[28,29,30,92,31,34,35],"667":[28,29,30,92,31,34,35],"672":[28,29,30,92,31,34,35],"697":[28,29,30,92,31,34,35],"710":[28,29,30,92,31,34,35],"745":[28,29,30,92,31,34,35],"753":[28,29,30,92,31,34,35],"767":[28,29,30,92,31,34,35]},"packages/cli/src/modules/instance-ai/event-bus/durable-log-metrics.ts":{"61":[28,29,30,92,31,34,35],"63":[28,29,30,92,31,34,35],"70":[28,29,30,92,31,34,35],"77":[28,29,30,92,31,34,35],"82":[28,29,30,92,31,34,35],"87":[28,29,30,92,31,34,35],"98":[28,29,30,92,31,34,35],"105":[28,29,30,92,31,34,35],"109":[28,29,30,92,31,34,35],"113":[28,29,30,92,31,34,35]},"packages/cli/src/modules/instance-ai/event-bus/in-process-event-bus.ts":{"24":[28,29,30,92,31,34,35],"44":[28,29,30,92,31,34,35],"51":[28,29,30,92,31,34,35],"59":[28,29,30,92,31,34,35],"73":[28,29,30,92,31,34,35],"89":[28,29,30,92,31,34,35],"104":[28,29,30,92,31,34,35],"111":[28,29,30,92,31,34,35],"113":[28,29,30,92,31,34,35],"117":[28,29,30,92,31,34,35],"122":[28,29,30,92,31,34,35],"128":[28,29,30,92,31,34,35]},"packages/cli/src/modules/instance-ai/filesystem/local-gateway-registry.ts":{"27":[16,28,29,30,31,32,33,159,34,35],"34":[16,28,29,30,31,32,33,159,34,35],"42":[16,28,29,30,31,32,33,159,34,35],"56":[16,28,29,30,31,32,33,159,34,35],"72":[16,28,29,30,31,32,33,159,34,35],"86":[16,28,29,30,31,32,33,159,34,35],"98":[16,28,29,30,31,32,33,159,34,35],"110":[16,28,29,30,31,32,33,159,34,35],"124":[16,28,29,30,31,32,33,159,34,35],"129":[16,28,29,30,31,32,33,159,34,35],"137":[16,28,29,30,31,32,33,159,34,35],"142":[16,28,29,30,31,32,33,159,34,35],"147":[16,28,29,30,31,32,33,159,34,35],"155":[16,28,29,30,31,32,33,159,34,35],"165":[16,28,29,30,31,32,33,159,34,35],"170":[16,28,29,30,31,32,33,159,34,35],"193":[16,28,29,30,31,32,33,159,34,35],"198":[16,28,29,30,31,32,33,159,34,35],"208":[16,28,29,30,31,32,33,159,34,35],"216":[16,28,29,30,31,32,33,159,34,35],"218":[16,28,29,30,31,32,33,159,34,35],"219":[16,28,29,30,31,32,33,159,34,35],"223":[16,28,29,30,31,32,33,159,34,35]},"packages/cli/src/modules/instance-ai/instance-ai-credit-display.ts":{"26":[16,28,29,30,31,33,34,35]},"packages/cli/src/modules/instance-ai/instance-ai-credit.service.ts":{"57":[16,28,29,30,31,33,159,34,35],"71":[16,28,29,30,31,33,159,34,35],"100":[16,28,29,30,31,33,159,34,35],"146":[16,28,29,30,31,33,159,34,35],"178":[16,28,29,30,31,33,159,34,35],"315":[16,28,29,30,31,33,159,34,35],"333":[16,28,29,30,31,33,159,34,35],"349":[16,28,29,30,31,33,159,34,35],"368":[16,28,29,30,31,33,159,34,35],"399":[16,28,29,30,31,33,159,34,35],"406":[16,28,29,30,31,33,159,34,35],"430":[16,28,29,30,31,33,159,34,35]},"packages/cli/src/modules/instance-ai/instance-ai-error-reporter.service.ts":{"25":[28,29,31,159,160,34,35,36],"37":[28,29,31,159,160,34,35,36],"51":[28,29,31,159,160,34,35,36],"58":[28,29,31,159,160,34,35,36],"64":[28,29,31,159,160,34,35,36],"69":[28,29,31,159,160,34,35,36],"73":[28,29,31,159,160,34,35,36],"123":[28,29,31,159,160,34,35,36],"137":[28,29,31,159,160,34,35,36]},"packages/cli/src/modules/instance-ai/instance-ai-gateway.service.ts":{"26":[16,28,29,30,31,32,33,159,34,35],"36":[16,28,29,30,31,32,33,159,34,35],"42":[16,28,29,30,31,32,33,159,34,35],"46":[16,28,29,30,31,32,33,159,34,35],"50":[16,28,29,30,31,32,33,159,34,35],"54":[16,28,29,30,31,32,33,159,34,35],"58":[16,28,29,30,31,32,33,159,34,35],"62":[16,28,29,30,31,32,33,159,34,35],"66":[16,28,29,30,31,32,33,159,34,35],"70":[16,28,29,30,31,32,33,159,34,35],"75":[16,28,29,30,31,32,33,159,34,35],"79":[16,28,29,30,31,32,33,159,34,35],"83":[16,28,29,30,31,32,33,159,34,35],"87":[16,28,29,30,31,32,33,159,34,35],"96":[16,28,29,30,31,32,33,159,34,35],"101":[16,28,29,30,31,32,33,159,34,35],"108":[16,28,29,30,31,32,33,159,34,35],"112":[16,28,29,30,31,32,33,159,34,35],"122":[16,28,29,30,31,32,33,159,34,35],"126":[16,28,29,30,31,32,33,159,34,35]},"packages/cli/src/modules/instance-ai/instance-ai-model.service.ts":{"40":[16,28,29,30,31,33,159,34,35],"47":[16,28,29,30,31,33,159,34,35],"65":[16,28,29,30,31,33,159,34,35],"69":[16,28,29,30,31,33,159,34,35],"90":[16,28,29,30,31,33,159,34,35],"115":[16,28,29,30,31,33,159,34,35],"140":[16,28,29,30,31,33,159,34,35],"147":[16,28,29,30,31,33,159,34,35]},"packages/cli/src/modules/instance-ai/instance-ai-run-pin-data.ts":{"28":[28,126,34,35],"94":[28,126,34,35],"97":[28,126,34,35],"99":[28,126,34,35],"104":[28,126,34,35],"145":[28,126,34,35],"180":[28,126,34,35],"195":[28,126,34,35],"210":[28,126,34,35],"247":[28,126,34,35]},"packages/cli/src/modules/instance-ai/instance-ai-setup-telemetry.service.ts":{"41":[28,29,30,31,32,33,34,35],"63":[28,29,30,31,32,33,34,35],"76":[28,29,30,31,32,33,34,35],"87":[28,29,30,31,32,33,34,35],"91":[28,29,30,31,32,33,34,35],"98":[28,29,30,31,32,33,34,35],"102":[28,29,30,31,32,33,34,35],"110":[28,29,30,31,32,33,34,35],"121":[28,29,30,31,32,33,34,35],"127":[28,29,30,31,32,33,34,35],"148":[28,29,30,31,32,33,34,35],"175":[28,29,30,31,32,33,34,35],"186":[28,29,30,31,32,33,34,35],"209":[28,29,30,31,32,33,34,35],"227":[28,29,30,31,32,33,34,35],"250":[28,29,30,31,32,33,34,35],"278":[28,29,30,31,32,33,34,35]},"packages/cli/src/modules/instance-ai/instance-ai-temporary-workflow.service.ts":{"32":[28,29,92,31,159,35],"48":[28,29,92,31,159,35],"72":[28,29,92,31,159,35],"85":[28,29,92,31,159,35],"142":[28,29,92,31,159,35],"146":[28,29,92,31,159,35]},"packages/cli/src/modules/instance-ai/instance-ai-terminal-outcome.service.ts":{"33":[28,29,30,126,31,159,34,35],"131":[28,29,30,126,31,159,34,35],"143":[28,29,30,126,31,159,34,35],"176":[28,29,30,126,31,159,34,35],"196":[28,29,30,126,31,159,34,35],"209":[28,29,30,126,31,159,34,35],"263":[28,29,30,126,31,159,34,35],"268":[28,29,30,126,31,159,34,35],"298":[28,29,30,126,31,159,34,35],"322":[28,29,30,126,31,159,34,35],"325":[28,29,30,126,31,159,34,35],"333":[28,29,30,126,31,159,34,35],"339":[28,29,30,126,31,159,34,35],"362":[28,29,30,126,31,159,34,35],"393":[28,29,30,126,31,159,34,35],"397":[28,29,30,126,31,159,34,35],"418":[28,29,30,126,31,159,34,35]},"packages/cli/src/modules/instance-ai/instance-ai-test.controller.ts":{"18":[28,29,30,31,32,34,35,228],"28":[28,29,30,31,32,34,35,228],"40":[28,29,30,31,32,34,35,228],"46":[28,29,30,31,32,34,35,228],"52":[28,29,30,31,32,34,35,228],"66":[28,29,30,31,32,34,35,228],"73":[28,29,30,31,32,34,35,228],"92":[28,29,30,31,32,34,35,228],"119":[28,29,30,31,32,34,35,228]},"packages/cli/src/modules/instance-ai/instance-ai-thread-tabs.service.ts":{"18":[28,29,30,126,31,34,35],"27":[28,29,30,126,31,34,35],"31":[28,29,30,126,31,34,35],"46":[28,29,30,126,31,34,35],"59":[28,29,30,126,31,34,35],"61":[28,29,30,126,31,34,35],"65":[28,29,30,126,31,34,35],"68":[28,29,30,126,31,34,35],"84":[28,29,30,126,31,34,35],"91":[28,29,30,126,31,34,35],"96":[28,29,30,126,31,34,35],"109":[28,29,30,126,31,34,35],"115":[28,29,30,126,31,34,35],"121":[28,29,30,126,31,34,35],"137":[28,29,30,126,31,34,35]},"packages/cli/src/modules/instance-ai/instance-ai.adapter.service.ts":{"259":[28,29,126,31,159,34,35,127],"291":[28,29,126,31,159,34,35,127],"304":[28,29,126,31,159,34,35,127],"314":[28,29,126,31,159,34,35,127],"346":[28,29,126,31,159,34,35,127],"359":[28,29,126,31,159,34,35,127],"397":[28,29,126,31,159,34,35,127],"402":[28,29,126,31,159,34,35,127],"406":[28,29,126,31,159,34,35,127],"412":[28,29,126,31,159,34,35,127],"472":[28,29,126,31,159,34,35,127],"477":[28,29,126,31,159,34,35,127],"628":[28,29,126,31,159,34,35,127],"646":[28,29,126,31,159,34,35,127],"671":[28,29,126,31,159,34,35,127],"697":[28,29,126,31,159,34,35,127],"707":[28,29,126,31,159,34,35,127],"776":[28,29,126,31,159,34,35,127],"786":[28,29,126,31,159,34,35,127],"795":[28,29,126,31,159,34,35,127],"800":[28,29,126,31,159,34,35,127],"805":[28,29,126,31,159,34,35,127],"821":[28,29,126,31,159,34,35,127],"835":[28,29,126,31,159,34,35,127],"839":[28,29,126,31,159,34,35,127],"841":[28,29,126,31,159,34,35,127],"842":[28,29,126,31,159,34,35,127],"846":[28,29,126,31,159,34,35,127],"852":[28,29,126,31,159,34,35,127],"857":[28,29,126,31,159,34,35,127],"858":[28,29,126,31,159,34,35,127],"860":[28,29,126,31,159,34,35,127],"863":[28,29,126,31,159,34,35,127],"868":[28,29,126,31,159,34,35,127],"873":[28,29,126,31,159,34,35,127],"876":[28,29,126,31,159,34,35,127],"881":[28,29,126,31,159,34,35,127],"889":[28,29,126,31,159,34,35,127],"913":[28,29,126,31,159,34,35,127],"917":[28,29,126,31,159,34,35,127],"922":[28,29,126,31,159,34,35,127],"939":[28,29,126,31,159,34,35,127],"950":[28,29,126,31,159,34,35,127],"953":[28,29,126,31,159,34,35,127],"960":[28,29,126,31,159,34,35,127],"964":[28,29,126,31,159,34,35,127],"985":[28,29,126,31,159,34,35,127],"994":[28,29,126,31,159,34,35,127],"1002":[28,29,126,31,159,34,35,127],"1006":[28,29,126,31,159,34,35,127],"1009":[28,29,126,31,159,34,35,127],"1013":[28,29,126,31,159,34,35,127],"1020":[28,29,126,31,159,34,35,127],"1026":[28,29,126,31,159,34,35,127],"1039":[28,29,126,31,159,34,35,127],"1080":[28,29,126,31,159,34,35,127],"1091":[28,29,126,31,159,34,35,127],"1103":[28,29,126,31,159,34,35,127],"1116":[28,29,126,31,159,34,35,127],"1138":[28,29,126,31,159,34,35,127],"1159":[28,29,126,31,159,34,35,127],"1202":[28,29,126,31,159,34,35,127],"1204":[28,29,126,31,159,34,35,127],"1208":[28,29,126,31,159,34,35,127],"1223":[28,29,126,31,159,34,35,127],"1258":[28,29,126,31,159,34,35,127],"1271":[28,29,126,31,159,34,35,127],"1283":[28,29,126,31,159,34,35,127],"1305":[28,29,126,31,159,34,35,127],"1326":[28,29,126,31,159,34,35,127],"1401":[28,29,126,31,159,34,35,127],"1409":[28,29,126,31,159,34,35,127],"1414":[28,29,126,31,159,34,35,127],"1422":[28,29,126,31,159,34,35,127],"1430":[28,29,126,31,159,34,35,127],"1431":[28,29,126,31,159,34,35,127],"1433":[28,29,126,31,159,34,35,127],"1446":[28,29,126,31,159,34,35,127],"1464":[28,29,126,31,159,34,35,127],"1492":[28,29,126,31,159,34,35,127],"1504":[28,29,126,31,159,34,35,127],"1514":[28,29,126,31,159,34,35,127],"1522":[28,29,126,31,159,34,35,127],"1533":[28,29,126,31,159,34,35,127],"1552":[28,29,126,31,159,34,35,127],"1582":[28,29,126,31,159,34,35,127],"1590":[28,29,126,31,159,34,35,127],"1600":[28,29,126,31,159,34,35,127],"1605":[28,29,126,31,159,34,35,127],"1611":[28,29,126,31,159,34,35,127],"1623":[28,29,126,31,159,34,35,127],"1635":[28,29,126,31,159,34,35,127],"1660":[28,29,126,31,159,34,35,127],"1687":[28,29,126,31,159,34,35,127],"1738":[28,29,126,31,159,34,35,127],"1824":[28,29,126,31,159,34,35,127],"1835":[28,29,126,31,159,34,35,127],"1932":[28,29,126,31,159,34,35,127],"1945":[28,29,126,31,159,34,35,127],"1958":[28,29,126,31,159,34,35,127],"1978":[28,29,126,31,159,34,35,127],"1990":[28,29,126,31,159,34,35,127],"2013":[28,29,126,31,159,34,35,127],"2025":[28,29,126,31,159,34,35,127],"2044":[28,29,126,31,159,34,35,127],"2053":[28,29,126,31,159,34,35,127],"2075":[28,29,126,31,159,34,35,127],"2114":[28,29,126,31,159,34,35,127],"2127":[28,29,126,31,159,34,35,127],"2258":[28,29,126,31,159,34,35,127],"2278":[28,29,126,31,159,34,35,127],"2347":[28,29,126,31,159,34,35,127],"2368":[28,29,126,31,159,34,35,127],"2434":[28,29,126,31,159,34,35,127],"2461":[28,29,126,31,159,34,35,127],"2569":[28,29,126,31,159,34,35,127],"2589":[28,29,126,31,159,34,35,127],"2592":[28,29,126,31,159,34,35,127],"2597":[28,29,126,31,159,34,35,127],"2611":[28,29,126,31,159,34,35,127],"2669":[28,29,126,31,159,34,35,127],"2678":[28,29,126,31,159,34,35,127],"2687":[28,29,126,31,159,34,35,127],"2711":[28,29,126,31,159,34,35,127],"2716":[28,29,126,31,159,34,35,127],"2731":[28,29,126,31,159,34,35,127],"2756":[28,29,126,31,159,34,35,127],"2768":[28,29,126,31,159,34,35,127],"2771":[28,29,126,31,159,34,35,127],"2780":[28,29,126,31,159,34,35,127],"2782":[28,29,126,31,159,34,35,127],"2803":[28,29,126,31,159,34,35,127],"2806":[28,29,126,31,159,34,35,127],"2823":[28,29,126,31,159,34,35,127],"2832":[28,29,126,31,159,34,35,127],"2842":[28,29,126,31,159,34,35,127],"2846":[28,29,126,31,159,34,35,127],"2891":[28,29,126,31,159,34,35,127],"2895":[28,29,126,31,159,34,35,127],"2906":[28,29,126,31,159,34,35,127],"2930":[28,29,126,31,159,34,35,127],"2946":[28,29,126,31,159,34,35,127],"2948":[28,29,126,31,159,34,35,127],"2950":[28,29,126,31,159,34,35,127],"2965":[28,29,126,31,159,34,35,127],"2974":[28,29,126,31,159,34,35,127],"2977":[28,29,126,31,159,34,35,127],"2990":[28,29,126,31,159,34,35,127],"3004":[28,29,126,31,159,34,35,127],"3009":[28,29,126,31,159,34,35,127],"3016":[28,29,126,31,159,34,35,127],"3028":[28,29,126,31,159,34,35,127],"3072":[28,29,126,31,159,34,35,127],"3091":[28,29,126,31,159,34,35,127],"3105":[28,29,126,31,159,34,35,127],"3116":[28,29,126,31,159,34,35,127],"3162":[28,29,126,31,159,34,35,127],"3169":[28,29,126,31,159,34,35,127],"3178":[28,29,126,31,159,34,35,127],"3183":[28,29,126,31,159,34,35,127],"3205":[28,29,126,31,159,34,35,127],"3209":[28,29,126,31,159,34,35,127],"3214":[28,29,126,31,159,34,35,127],"3219":[28,29,126,31,159,34,35,127],"3221":[28,29,126,31,159,34,35,127],"3236":[28,29,126,31,159,34,35,127],"3244":[28,29,126,31,159,34,35,127],"3249":[28,29,126,31,159,34,35,127],"3254":[28,29,126,31,159,34,35,127],"3259":[28,29,126,31,159,34,35,127],"3271":[28,29,126,31,159,34,35,127],"3284":[28,29,126,31,159,34,35,127],"3292":[28,29,126,31,159,34,35,127],"3294":[28,29,126,31,159,34,35,127],"3311":[28,29,126,31,159,34,35,127],"3319":[28,29,126,31,159,34,35,127],"3325":[28,29,126,31,159,34,35,127],"3343":[28,29,126,31,159,34,35,127],"3353":[28,29,126,31,159,34,35,127],"3371":[28,29,126,31,159,34,35,127],"3378":[28,29,126,31,159,34,35,127],"3382":[28,29,126,31,159,34,35,127],"3389":[28,29,126,31,159,34,35,127],"3398":[28,29,126,31,159,34,35,127],"3404":[28,29,126,31,159,34,35,127],"3414":[28,29,126,31,159,34,35,127],"3423":[28,29,126,31,159,34,35,127],"3431":[28,29,126,31,159,34,35,127],"3440":[28,29,126,31,159,34,35,127],"3456":[28,29,126,31,159,34,35,127],"3466":[28,29,126,31,159,34,35,127],"3478":[28,29,126,31,159,34,35,127],"3491":[28,29,126,31,159,34,35,127],"3512":[28,29,126,31,159,34,35,127],"3533":[28,29,126,31,159,34,35,127],"3563":[28,29,126,31,159,34,35,127],"3579":[28,29,126,31,159,34,35,127],"3598":[28,29,126,31,159,34,35,127],"3631":[28,29,126,31,159,34,35,127],"3660":[28,29,126,31,159,34,35,127],"3675":[28,29,126,31,159,34,35,127],"3684":[28,29,126,31,159,34,35,127],"3699":[28,29,126,31,159,34,35,127],"3711":[28,29,126,31,159,34,35,127],"3728":[28,29,126,31,159,34,35,127],"3738":[28,29,126,31,159,34,35,127],"3742":[28,29,126,31,159,34,35,127],"3745":[28,29,126,31,159,34,35,127],"3747":[28,29,126,31,159,34,35,127],"3750":[28,29,126,31,159,34,35,127],"3752":[28,29,126,31,159,34,35,127],"3754":[28,29,126,31,159,34,35,127],"3755":[28,29,126,31,159,34,35,127],"3759":[28,29,126,31,159,34,35,127],"3765":[28,29,126,31,159,34,35,127],"3772":[28,29,126,31,159,34,35,127],"3776":[28,29,126,31,159,34,35,127],"3786":[28,29,126,31,159,34,35,127],"3793":[28,29,126,31,159,34,35,127],"3808":[28,29,126,31,159,34,35,127],"3811":[28,29,126,31,159,34,35,127],"3814":[28,29,126,31,159,34,35,127],"3818":[28,29,126,31,159,34,35,127],"3821":[28,29,126,31,159,34,35,127],"3875":[28,29,126,31,159,34,35,127],"3882":[28,29,126,31,159,34,35,127],"3890":[28,29,126,31,159,34,35,127],"3908":[28,29,126,31,159,34,35,127],"3917":[28,29,126,31,159,34,35,127],"3920":[28,29,126,31,159,34,35,127],"3926":[28,29,126,31,159,34,35,127],"3943":[28,29,126,31,159,34,35,127],"3948":[28,29,126,31,159,34,35,127],"3965":[28,29,126,31,159,34,35,127],"3971":[28,29,126,31,159,34,35,127],"4013":[28,29,126,31,159,34,35,127],"4030":[28,29,126,31,159,34,35,127],"4087":[28,29,126,31,159,34,35,127],"4088":[28,29,126,31,159,34,35,127],"4122":[28,29,126,31,159,34,35,127],"4125":[28,29,126,31,159,34,35,127],"4130":[28,29,126,31,159,34,35,127],"4141":[28,29,126,31,159,34,35,127],"4146":[28,29,126,31,159,34,35,127],"4152":[28,29,126,31,159,34,35,127],"4154":[28,29,126,31,159,34,35,127],"4165":[28,29,126,31,159,34,35,127],"4170":[28,29,126,31,159,34,35,127],"4175":[28,29,126,31,159,34,35,127],"4182":[28,29,126,31,159,34,35,127],"4200":[28,29,126,31,159,34,35,127],"4212":[28,29,126,31,159,34,35,127],"4228":[28,29,126,31,159,34,35,127],"4242":[28,29,126,31,159,34,35,127],"4263":[28,29,126,31,159,34,35,127],"4268":[28,29,126,31,159,34,35,127],"4271":[28,29,126,31,159,34,35,127],"4280":[28,29,126,31,159,34,35,127],"4309":[28,29,126,31,159,34,35,127],"4390":[28,29,126,31,159,34,35,127],"4396":[28,29,126,31,159,34,35,127],"4429":[28,29,126,31,159,34,35,127],"4436":[28,29,126,31,159,34,35,127],"4458":[28,29,126,31,159,34,35,127],"4471":[28,29,126,31,159,34,35,127],"4484":[28,29,126,31,159,34,35,127],"4516":[28,29,126,31,159,34,35,127],"4560":[28,29,126,31,159,34,35,127],"4569":[28,29,126,31,159,34,35,127],"4580":[28,29,126,31,159,34,35,127],"4602":[28,29,126,31,159,34,35,127],"4615":[28,29,126,31,159,34,35,127],"4629":[28,29,126,31,159,34,35,127],"4637":[28,29,126,31,159,34,35,127],"4645":[28,29,126,31,159,34,35,127],"4652":[28,29,126,31,159,34,35,127],"4677":[28,29,126,31,159,34,35,127],"4686":[28,29,126,31,159,34,35,127],"4687":[28,29,126,31,159,34,35,127],"4691":[28,29,126,31,159,34,35,127],"4694":[28,29,126,31,159,34,35,127],"4710":[28,29,126,31,159,34,35,127],"4736":[28,29,126,31,159,34,35,127],"4789":[28,29,126,31,159,34,35,127],"4792":[28,29,126,31,159,34,35,127],"4793":[28,29,126,31,159,34,35,127],"4803":[28,29,126,31,159,34,35,127],"4859":[28,29,126,31,159,34,35,127],"4896":[28,29,126,31,159,34,35,127],"4910":[28,29,126,31,159,34,35,127],"4933":[28,29,126,31,159,34,35,127],"4968":[28,29,126,31,159,34,35,127],"4994":[28,29,126,31,159,34,35,127],"5007":[28,29,126,31,159,34,35,127],"5031":[28,29,126,31,159,34,35,127],"5039":[28,29,126,31,159,34,35,127],"5053":[28,29,126,31,159,34,35,127],"5102":[28,29,126,31,159,34,35,127],"5105":[28,29,126,31,159,34,35,127],"5107":[28,29,126,31,159,34,35,127],"5121":[28,29,126,31,159,34,35,127],"5176":[28,29,126,31,159,34,35,127],"5178":[28,29,126,31,159,34,35,127],"5179":[28,29,126,31,159,34,35,127],"5183":[28,29,126,31,159,34,35,127],"5190":[28,29,126,31,159,34,35,127],"5202":[28,29,126,31,159,34,35,127],"5203":[28,29,126,31,159,34,35,127],"5206":[28,29,126,31,159,34,35,127],"5220":[28,29,126,31,159,34,35,127],"5224":[28,29,126,31,159,34,35,127],"5229":[28,29,126,31,159,34,35,127],"5230":[28,29,126,31,159,34,35,127],"5239":[28,29,126,31,159,34,35,127],"5254":[28,29,126,31,159,34,35,127],"5282":[28,29,126,31,159,34,35,127],"5315":[28,29,126,31,159,34,35,127],"5319":[28,29,126,31,159,34,35,127],"5321":[28,29,126,31,159,34,35,127],"5367":[28,29,126,31,159,34,35,127],"5379":[28,29,126,31,159,34,35,127],"5394":[28,29,126,31,159,34,35,127],"5409":[28,29,126,31,159,34,35,127],"5426":[28,29,126,31,159,34,35,127],"5441":[28,29,126,31,159,34,35,127],"5452":[28,29,126,31,159,34,35,127],"5453":[28,29,126,31,159,34,35,127],"5459":[28,29,126,31,159,34,35,127],"5482":[28,29,126,31,159,34,35,127],"5495":[28,29,126,31,159,34,35,127],"5525":[28,29,126,31,159,34,35,127],"5539":[28,29,126,31,159,34,35,127],"5553":[28,29,126,31,159,34,35,127]},"packages/cli/src/modules/instance-ai/instance-ai.service.ts":{"286":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","300":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","306":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","317":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","341":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","367":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","378":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","382":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","402":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","405":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","411":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","429":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","449":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","457":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","520":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","534":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","552":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","559":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","564":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","573":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","577":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","584":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","589":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","642":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","710":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","722":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","726":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","742":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","833":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","878":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","881":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","895":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","923":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","926":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","935":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","949":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","961":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","962":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","963":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","972":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","989":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","993":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1002":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1012":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1025":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1032":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1045":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1055":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1071":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1092":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1109":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1120":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1167":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1180":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1197":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1212":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1240":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1244":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1253":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1260":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1274":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1278":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1313":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1314":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1327":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1331":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1367":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1410":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1423":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1435":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1439":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1440":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1450":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1454":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1485":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1523":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1592":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1603":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1611":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1616":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1624":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1644":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1726":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1735":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1766":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1770":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1783":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1799":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1813":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1820":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1824":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1828":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1847":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1859":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1878":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1886":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1958":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1959":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1960":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1962":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","1974":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2002":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2010":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2014":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2018":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2029":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2033":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2041":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2091":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2103":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2223":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2224":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2235":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2240":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2253":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2257":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2261":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2262":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2265":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2281":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2306":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2324":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2327":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2337":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2348":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2372":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2377":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2380":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2385":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2390":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2394":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2399":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2400":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2405":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2414":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2416":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2421":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2454":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2464":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2487":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2488":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2519":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2536":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2549":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2553":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2571":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2593":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2600":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2692":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2693":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2746":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2753":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2755":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2758":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2769":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2787":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2792":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2808":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2873":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2880":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2883":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2890":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2894":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2910":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2916":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2922":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2935":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2952":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2960":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2991":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2992":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2993":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2995":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","2997":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3028":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3038":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3058":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3070":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3089":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3113":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3142":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3154":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3166":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3177":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3228":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3271":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3293":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3303":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3312":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3341":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3345":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3398":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3455":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3459":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3469":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3482":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3495":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3513":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3530":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3593":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3596":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3601":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3620":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3622":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3626":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3628":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3632":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3634":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3648":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3650":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3661":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3676":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3687":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3706":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3720":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3722":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3730":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3747":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3749":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3751":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3758":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3775":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3820":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3854":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3861":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3865":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3869":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3888":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3903":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3924":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3958":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","3967":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","4157":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","4182":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","4263":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","4334":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","4338":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","4354":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","4426":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","4484":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","4509":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","4533":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","4541":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","4552":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","4564":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","5075":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","5084":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","5102":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","5131":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","5140":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","5173":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","5248":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","5267":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","5273":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","5312":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","5337":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","5378":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","5403":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","5502":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","5510":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","5529":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","5573":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","5577":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","5583":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","5601":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","5631":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","5659":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","5669":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","5689":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","5703":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","5713":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","5734":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","5754":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","5759":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","5767":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","5813":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","6002":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","6053":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","6111":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","6114":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","6123":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","6135":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","6679":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","6777":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","6795":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","6806":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","6822":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","6837":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","6866":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","6871":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","6877":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","6927":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","6934":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","6969":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","7018":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","7067":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","7082":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","7086":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","7094":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","7096":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","7109":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","7111":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","7122":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","7127":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","7141":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","7181":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","7222":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","7246":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","7264":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","7266":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","7270":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","7274":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","7312":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","7333":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","7355":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","7415":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","7442":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","7464":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","7467":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","7479":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","7484":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","7487":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA=","7493":"b:AIAB8B8AAAAAAAAQAAAAQAAAAIADAAAAAAAAABA="},"packages/cli/src/modules/instance-ai/instance-context.service.ts":{"169":[28,29,31,159,34,35],"186":[28,29,31,159,34,35],"219":[28,29,31,159,34,35],"238":[28,29,31,159,34,35],"257":[28,29,31,159,34,35],"276":[28,29,31,159,34,35],"340":[28,29,31,159,34,35],"374":[28,29,31,159,34,35],"393":[28,29,31,159,34,35],"457":[28,29,31,159,34,35],"471":[28,29,31,159,34,35],"508":[28,29,31,159,34,35],"509":[28,29,31,159,34,35],"520":[28,29,31,159,34,35],"557":[28,29,31,159,34,35],"581":[28,29,31,159,34,35],"594":[28,29,31,159,34,35],"602":[28,29,31,159,34,35],"609":[28,29,31,159,34,35],"617":[28,29,31,159,34,35],"664":[28,29,31,159,34,35],"767":[28,29,31,159,34,35],"789":[28,29,31,159,34,35],"801":[28,29,31,159,34,35],"823":[28,29,31,159,34,35],"829":[28,29,31,159,34,35],"833":[28,29,31,159,34,35],"842":[28,29,31,159,34,35],"855":[28,29,31,159,34,35],"866":[28,29,31,159,34,35],"886":[28,29,31,159,34,35],"911":[28,29,31,159,34,35],"926":[28,29,31,159,34,35],"934":[28,29,31,159,34,35],"950":[28,29,31,159,34,35],"969":[28,29,31,159,34,35],"972":[28,29,31,159,34,35],"996":[28,29,31,159,34,35],"1035":[28,29,31,159,34,35],"1040":[28,29,31,159,34,35],"1062":[28,29,31,159,34,35],"1085":[28,29,31,159,34,35],"1117":[28,29,31,159,34,35],"1121":[28,29,31,159,34,35],"1135":[28,29,31,159,34,35],"1145":[28,29,31,159,34,35],"1157":[28,29,31,159,34,35],"1178":[28,29,31,159,34,35],"1186":[28,29,31,159,34,35],"1195":[28,29,31,159,34,35],"1206":[28,29,31,159,34,35],"1211":[28,29,31,159,34,35],"1216":[28,29,31,159,34,35],"1219":[28,29,31,159,34,35]},"packages/cli/src/modules/instance-ai/internal-messages.ts":{"73":[28,29,92,31,159,160,34,35],"121":[28,29,92,31,159,160,34,35],"141":[28,29,92,31,159,160,34,35],"159":[28,29,92,31,159,160,34,35],"163":[28,29,92,31,159,160,34,35],"167":[28,29,92,31,159,160,34,35],"171":[28,29,92,31,159,160,34,35],"188":[28,29,92,31,159,160,34,35],"196":[28,29,92,31,159,160,34,35],"198":[28,29,92,31,159,160,34,35],"199":[28,29,92,31,159,160,34,35],"209":[28,29,92,31,159,160,34,35],"217":[28,29,92,31,159,160,34,35],"227":[28,29,92,31,159,160,34,35],"236":[28,29,92,31,159,160,34,35],"253":[28,29,92,31,159,160,34,35],"254":[28,29,92,31,159,160,34,35],"271":[28,29,92,31,159,160,34,35],"272":[28,29,92,31,159,160,34,35],"288":[28,29,92,31,159,160,34,35],"290":[28,29,92,31,159,160,34,35],"308":[28,29,92,31,159,160,34,35],"325":[28,29,92,31,159,160,34,35],"328":[28,29,92,31,159,160,34,35],"334":[28,29,92,31,159,160,34,35],"350":[28,29,92,31,159,160,34,35],"353":[28,29,92,31,159,160,34,35],"363":[28,29,92,31,159,160,34,35],"376":[28,29,92,31,159,160,34,35],"395":[28,29,92,31,159,160,34,35],"406":[28,29,92,31,159,160,34,35],"418":[28,29,92,31,159,160,34,35],"422":[28,29,92,31,159,160,34,35],"439":[28,29,92,31,159,160,34,35],"456":[28,29,92,31,159,160,34,35],"480":[28,29,92,31,159,160,34,35],"481":[28,29,92,31,159,160,34,35],"483":[28,29,92,31,159,160,34,35],"504":[28,29,92,31,159,160,34,35],"518":[28,29,92,31,159,160,34,35],"522":[28,29,92,31,159,160,34,35],"540":[28,29,92,31,159,160,34,35],"545":[28,29,92,31,159,160,34,35],"564":[28,29,92,31,159,160,34,35],"569":[28,29,92,31,159,160,34,35],"579":[28,29,92,31,159,160,34,35],"597":[28,29,92,31,159,160,34,35]},"packages/cli/src/modules/instance-ai/mcp/instance-ai-mcp-connection.controller.ts":{"35":[16,28,29,30,31,33,34,35],"42":[16,28,29,30,31,33,34,35],"50":[16,28,29,30,31,33,34,35],"56":[16,28,29,30,31,33,34,35],"58":[16,28,29,30,31,33,34,35],"59":[16,28,29,30,31,33,34,35],"82":[16,28,29,30,31,33,34,35],"101":[16,28,29,30,31,33,34,35],"107":[16,28,29,30,31,33,34,35],"117":[16,28,29,30,31,33,34,35],"143":[16,28,29,30,31,33,34,35],"148":[16,28,29,30,31,33,34,35]},"packages/cli/src/modules/instance-ai/mcp/instance-ai-mcp-registry.service.ts":{"49":[16,28,29,30,31,33,159,34,35],"61":[16,28,29,30,31,33,159,34,35],"66":[16,28,29,30,31,33,159,34,35],"76":[16,28,29,30,31,33,159,34,35],"87":[16,28,29,30,31,33,159,34,35],"102":[16,28,29,30,31,33,159,34,35],"106":[16,28,29,30,31,33,159,34,35],"177":[16,28,29,30,31,33,159,34,35],"190":[16,28,29,30,31,33,159,34,35],"212":[16,28,29,30,31,33,159,34,35],"221":[16,28,29,30,31,33,159,34,35],"224":[16,28,29,30,31,33,159,34,35],"239":[16,28,29,30,31,33,159,34,35],"266":[16,28,29,30,31,33,159,34,35],"293":[16,28,29,30,31,33,159,34,35],"299":[16,28,29,30,31,33,159,34,35],"309":[16,28,29,30,31,33,159,34,35],"315":[16,28,29,30,31,33,159,34,35],"316":[16,28,29,30,31,33,159,34,35],"318":[16,28,29,30,31,33,159,34,35],"391":[16,28,29,30,31,33,159,34,35],"427":[16,28,29,30,31,33,159,34,35],"484":[16,28,29,30,31,33,159,34,35],"505":[16,28,29,30,31,33,159,34,35],"524":[16,28,29,30,31,33,159,34,35],"529":[16,28,29,30,31,33,159,34,35]},"packages/cli/src/modules/instance-ai/observability.ts":{"17":[28,29,31,159,160,34,35],"46":[28,29,31,159,160,34,35]},"packages/cli/src/modules/instance-ai/onboarding.ts":{"69":[126,35],"71":[126,35],"76":[126,35],"83":[126,35],"96":[126,35],"103":[126,35],"105":[126,35],"110":[126,35],"111":[126,35],"112":[126,35],"113":[126,35],"129":[126,35],"140":[126,35],"161":[126,35],"169":[126,35],"229":[126,35],"249":[126,35],"250":[126,35],"269":[126,35],"272":[126,35],"286":[126,35],"292":[126,35],"306":[126,35],"328":[126,35]},"packages/cli/src/modules/instance-ai/planned-task-action-runner.ts":{"94":[28,29,31,159,35],"96":[28,29,31,159,35],"115":[28,29,31,159,35],"131":[28,29,31,159,35],"157":[28,29,31,159,35],"169":[28,29,31,159,35],"194":[28,29,31,159,35],"212":[28,29,31,159,35],"234":[28,29,31,159,35],"252":[28,29,31,159,35]},"packages/cli/src/modules/instance-ai/repositories/instance-ai-checkpoint.repository.ts":{"11":[30,92,126,31,35],"24":[30,92,126,31,35],"36":[30,92,126,31,35],"40":[30,92,126,31,35],"68":[30,92,126,31,35]},"packages/cli/src/modules/instance-ai/repositories/instance-ai-event-log.repository.ts":{"22":[28,29,30,92,31,34,35],"27":[28,29,30,92,31,34,35],"42":[28,29,30,92,31,34,35],"48":[28,29,30,92,31,34,35],"67":[28,29,30,92,31,34,35],"72":[28,29,30,92,31,34,35],"77":[28,29,30,92,31,34,35],"80":[28,29,30,92,31,34,35],"87":[28,29,30,92,31,34,35],"94":[28,29,30,92,31,34,35],"104":[28,29,30,92,31,34,35],"121":[28,29,30,92,31,34,35],"132":[28,29,30,92,31,34,35],"140":[28,29,30,92,31,34,35],"145":[28,29,30,92,31,34,35],"166":[28,29,30,92,31,34,35],"174":[28,29,30,92,31,34,35],"175":[28,29,30,92,31,34,35],"180":[28,29,30,92,31,34,35],"182":[28,29,30,92,31,34,35],"195":[28,29,30,92,31,34,35],"207":[28,29,30,92,31,34,35],"212":[28,29,30,92,31,34,35],"221":[28,29,30,92,31,34,35],"232":[28,29,30,92,31,34,35],"238":[28,29,30,92,31,34,35],"251":[28,29,30,92,31,34,35],"268":[28,29,30,92,31,34,35],"275":[28,29,30,92,31,34,35],"294":[28,29,30,92,31,34,35]},"packages/cli/src/modules/instance-ai/repositories/instance-ai-pending-confirmation.repository.ts":{"8":[28,92,126,31,35],"21":[28,92,126,31,35],"25":[28,92,126,31,35],"48":[28,92,126,31,35],"53":[28,92,126,31,35],"58":[28,92,126,31,35],"63":[28,92,126,31,35],"76":[28,92,126,31,35],"81":[28,92,126,31,35],"87":[28,92,126,31,35],"96":[28,92,126,31,35]},"packages/cli/src/modules/instance-ai/repositories/instance-ai-thread-grant.repository.ts":{"8":[28,29,31,159,34,35],"16":[28,29,31,159,34,35],"25":[28,29,31,159,34,35],"30":[28,29,31,159,34,35],"35":[28,29,31,159,34,35]},"packages/cli/src/modules/instance-ai/repositories/instance-ai-thread-tabs.repository.ts":{"10":[28,29,30,126,31,34,35],"15":[28,29,30,126,31,34,35],"21":[28,29,30,126,31,34,35],"33":[28,29,30,126,31,34,35],"38":[28,29,30,126,31,34,35]},"packages/cli/src/modules/instance-ai/repositories/instance-ai-thread.repository.ts":{"10":[16,28,29,30,31,33,34,35],"15":[16,28,29,30,31,33,34,35],"21":[16,28,29,30,31,33,34,35],"54":[16,28,29,30,31,33,34,35],"64":[16,28,29,30,31,33,34,35]},"packages/cli/src/modules/instance-ai/run-trace-metadata.ts":{"33":[28,29,31,159,35],"40":[28,29,31,159,35],"48":[28,29,31,159,35],"83":[28,29,31,159,35],"95":[28,29,31,159,35]},"packages/cli/src/modules/instance-ai/sandbox/instance-ai-sandbox.service.ts":{"50":[28,29,30,92,126,31,32,33,159,34,35,228],"54":[28,29,30,92,126,31,32,33,159,34,35,228],"62":[28,29,30,92,126,31,32,33,159,34,35,228],"70":[28,29,30,92,126,31,32,33,159,34,35,228],"74":[28,29,30,92,126,31,32,33,159,34,35,228],"87":[28,29,30,92,126,31,32,33,159,34,35,228],"108":[28,29,30,92,126,31,32,33,159,34,35,228],"117":[28,29,30,92,126,31,32,33,159,34,35,228],"209":[28,29,30,92,126,31,32,33,159,34,35,228],"211":[28,29,30,92,126,31,32,33,159,34,35,228],"215":[28,29,30,92,126,31,32,33,159,34,35,228],"219":[28,29,30,92,126,31,32,33,159,34,35,228],"277":[28,29,30,92,126,31,32,33,159,34,35,228],"286":[28,29,30,92,126,31,32,33,159,34,35,228],"295":[28,29,30,92,126,31,32,33,159,34,35,228],"298":[28,29,30,92,126,31,32,33,159,34,35,228],"334":[28,29,30,92,126,31,32,33,159,34,35,228],"343":[28,29,30,92,126,31,32,33,159,34,35,228],"351":[28,29,30,92,126,31,32,33,159,34,35,228],"356":[28,29,30,92,126,31,32,33,159,34,35,228],"409":[28,29,30,92,126,31,32,33,159,34,35,228],"419":[28,29,30,92,126,31,32,33,159,34,35,228],"428":[28,29,30,92,126,31,32,33,159,34,35,228],"431":[28,29,30,92,126,31,32,33,159,34,35,228],"438":[28,29,30,92,126,31,32,33,159,34,35,228],"460":[28,29,30,92,126,31,32,33,159,34,35,228],"467":[28,29,30,92,126,31,32,33,159,34,35,228],"497":[28,29,30,92,126,31,32,33,159,34,35,228],"511":[28,29,30,92,126,31,32,33,159,34,35,228],"519":[28,29,30,92,126,31,32,33,159,34,35,228],"542":[28,29,30,92,126,31,32,33,159,34,35,228],"544":[28,29,30,92,126,31,32,33,159,34,35,228],"550":[28,29,30,92,126,31,32,33,159,34,35,228],"567":[28,29,30,92,126,31,32,33,159,34,35,228],"586":[28,29,30,92,126,31,32,33,159,34,35,228],"602":[28,29,30,92,126,31,32,33,159,34,35,228],"625":[28,29,30,92,126,31,32,33,159,34,35,228],"639":[28,29,30,92,126,31,32,33,159,34,35,228],"641":[28,29,30,92,126,31,32,33,159,34,35,228],"644":[28,29,30,92,126,31,32,33,159,34,35,228],"648":[28,29,30,92,126,31,32,33,159,34,35,228],"652":[28,29,30,92,126,31,32,33,159,34,35,228],"656":[28,29,30,92,126,31,32,33,159,34,35,228],"662":[28,29,30,92,126,31,32,33,159,34,35,228],"670":[28,29,30,92,126,31,32,33,159,34,35,228],"679":[28,29,30,92,126,31,32,33,159,34,35,228],"691":[28,29,30,92,126,31,32,33,159,34,35,228]},"packages/cli/src/modules/instance-ai/sandbox-provider.ts":{"6":[28,29,31,159,34,35],"14":[28,29,31,159,34,35]},"packages/cli/src/modules/instance-ai/storage/typeorm-agent-checkpoint-store.ts":{"13":[28,29,126,31,159,34,35],"15":[28,29,126,31,159,34,35],"47":[28,29,126,31,159,34,35],"56":[28,29,126,31,159,34,35],"60":[28,29,126,31,159,34,35],"68":[28,29,126,31,159,34,35],"84":[28,29,126,31,159,34,35],"93":[28,29,126,31,159,34,35],"107":[28,29,126,31,159,34,35],"119":[28,29,126,31,159,34,35],"126":[28,29,126,31,159,34,35]},"packages/cli/src/modules/instance-ai/storage/typeorm-agent-memory.ts":{"46":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","62":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","67":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","77":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","88":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","92":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","98":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","103":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","123":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","131":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","138":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","143":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","149":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","155":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","172":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","179":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","198":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","201":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","204":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","207":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","212":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","226":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","241":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","247":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","255":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","260":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","269":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","294":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","295":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","298":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","325":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","343":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","347":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","374":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","380":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","383":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","388":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","392":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","397":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","403":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","404":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","408":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","421":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","430":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","437":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","457":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","470":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","476":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","501":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","509":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","516":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","534":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","539":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","548":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","569":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","575":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","581":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","585":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","592":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","596":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","600":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","607":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","611":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","615":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","627":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","631":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","636":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA=","648":"b:AAAB8A4AAAAAAAAQAAAAQAAAAIADAAAABAAAAAA="},"packages/cli/src/modules/instance-ai/storage/typeorm-observation-log-store.ts":{"30":[28,29,31,159,34,35],"47":[28,29,31,159,34,35],"55":[28,29,31,159,34,35],"61":[28,29,31,159,34,35],"76":[28,29,31,159,34,35],"79":[28,29,31,159,34,35],"85":[28,29,31,159,34,35],"100":[28,29,31,159,34,35],"103":[28,29,31,159,34,35],"127":[28,29,31,159,34,35],"134":[28,29,31,159,34,35],"140":[28,29,31,159,34,35],"146":[28,29,31,159,34,35],"150":[28,29,31,159,34,35],"162":[28,29,31,159,34,35],"169":[28,29,31,159,34,35],"209":[28,29,31,159,34,35],"210":[28,29,31,159,34,35],"215":[28,29,31,159,34,35],"228":[28,29,31,159,34,35],"243":[28,29,31,159,34,35],"294":[28,29,31,159,34,35]},"packages/cli/src/modules/instance-ai/stream-transport-error.ts":{"13":[160,35,36]},"packages/cli/src/modules/instance-ai/suspended-thread-persistence.service.ts":{"47":[28,92,126,31,34,35],"53":[28,92,126,31,34,35],"68":[28,92,126,31,34,35],"81":[28,92,126,31,34,35],"117":[28,92,126,31,34,35],"128":[28,92,126,31,34,35]},"packages/cli/src/modules/instance-ai/trace-replay-state.ts":{"12":[28,29,31,32,159,34,35,228],"19":[28,29,31,32,159,34,35,228],"23":[28,29,31,32,159,34,35,228],"28":[28,29,31,32,159,34,35,228],"32":[28,29,31,32,159,34,35,228],"63":[28,29,31,32,159,34,35,228],"81":[28,29,31,32,159,34,35,228],"85":[28,29,31,32,159,34,35,228],"90":[28,29,31,32,159,34,35,228],"94":[28,29,31,32,159,34,35,228],"98":[28,29,31,32,159,34,35,228],"118":[28,29,31,32,159,34,35,228],"128":[28,29,31,32,159,34,35,228],"154":[28,29,31,32,159,34,35,228],"166":[28,29,31,32,159,34,35,228]},"packages/cli/src/modules/instance-ai/tracing/instance-ai-tracing.service.ts":{"116":[28,29,30,92,126,31,32,159,34,35,228],"124":[28,29,30,92,126,31,32,159,34,35,228],"150":[28,29,30,92,126,31,32,159,34,35,228],"154":[28,29,30,92,126,31,32,159,34,35,228],"158":[28,29,30,92,126,31,32,159,34,35,228],"159":[28,29,30,92,126,31,32,159,34,35,228],"162":[28,29,30,92,126,31,32,159,34,35,228],"166":[28,29,30,92,126,31,32,159,34,35,228],"175":[28,29,30,92,126,31,32,159,34,35,228],"177":[28,29,30,92,126,31,32,159,34,35,228],"180":[28,29,30,92,126,31,32,159,34,35,228],"190":[28,29,30,92,126,31,32,159,34,35,228],"240":[28,29,30,92,126,31,32,159,34,35,228],"244":[28,29,30,92,126,31,32,159,34,35,228],"284":[28,29,30,92,126,31,32,159,34,35,228],"290":[28,29,30,92,126,31,32,159,34,35,228],"329":[28,29,30,92,126,31,32,159,34,35,228],"344":[28,29,30,92,126,31,32,159,34,35,228],"361":[28,29,30,92,126,31,32,159,34,35,228],"370":[28,29,30,92,126,31,32,159,34,35,228],"377":[28,29,30,92,126,31,32,159,34,35,228],"428":[28,29,30,92,126,31,32,159,34,35,228],"464":[28,29,30,92,126,31,32,159,34,35,228],"484":[28,29,30,92,126,31,32,159,34,35,228],"505":[28,29,30,92,126,31,32,159,34,35,228],"510":[28,29,30,92,126,31,32,159,34,35,228],"553":[28,29,30,92,126,31,32,159,34,35,228],"557":[28,29,30,92,126,31,32,159,34,35,228],"561":[28,29,30,92,126,31,32,159,34,35,228],"565":[28,29,30,92,126,31,32,159,34,35,228]},"packages/cli/src/modules/instance-ai/workflow-verification-obligation-service.ts":{"19":[28,126,35],"27":[28,126,35],"29":[28,126,35],"32":[28,126,35],"36":[28,126,35],"42":[28,126,35],"52":[28,126,35],"63":[28,126,35],"77":[28,126,35],"88":[28,126,35]},"packages/cli/src/modules/instance-ai/workflow-verification-task-projector.ts":{"46":[28,29,31,159,34,35],"50":[28,29,31,159,34,35],"58":[28,29,31,159,34,35],"63":[28,29,31,159,34,35],"89":[28,29,31,159,34,35],"104":[28,29,31,159,34,35],"119":[28,29,31,159,34,35],"131":[28,29,31,159,34,35],"149":[28,29,31,159,34,35],"165":[28,29,31,159,34,35],"174":[28,29,31,159,34,35],"182":[28,29,31,159,34,35],"192":[28,29,31,159,34,35],"201":[28,29,31,159,34,35],"218":[28,29,31,159,34,35],"226":[28,29,31,159,34,35],"244":[28,29,31,159,34,35],"285":[28,29,31,159,34,35],"293":[28,29,31,159,34,35],"318":[28,29,31,159,34,35],"340":[28,29,31,159,34,35],"386":[28,29,31,159,34,35],"396":[28,29,31,159,34,35],"402":[28,29,31,159,34,35]},"packages/cli/src/node-catalog/index.ts":{"1":[28,126,34,35]},"packages/cli/src/node-catalog/module-gated-node-types.ts":{"8":[28,126,34,35],"13":[28,126,34,35],"18":[28,126,34,35],"20":[28,126,34,35],"21":[28,126,34,35],"25":[28,126,34,35]},"packages/cli/src/node-catalog/node-catalog.service.ts":{"23":[28,29,31,159,34,35,127,110,38],"29":[28,29,31,159,34,35,127,110,38],"32":[28,29,31,159,34,35,127,110,38],"33":[28,29,31,159,34,35,127,110,38],"35":[28,29,31,159,34,35,127,110,38],"41":[28,29,31,159,34,35,127,110,38],"44":[28,29,31,159,34,35,127,110,38],"52":[28,29,31,159,34,35,127,110,38],"134":[28,29,31,159,34,35,127,110,38],"137":[28,29,31,159,34,35,127,110,38],"222":[28,29,31,159,34,35,127,110,38],"227":[28,29,31,159,34,35,127,110,38],"230":[28,29,31,159,34,35,127,110,38],"235":[28,29,31,159,34,35,127,110,38],"242":[28,29,31,159,34,35,127,110,38],"256":[28,29,31,159,34,35,127,110,38],"266":[28,29,31,159,34,35,127,110,38],"288":[28,29,31,159,34,35,127,110,38],"312":[28,29,31,159,34,35,127,110,38],"322":[28,29,31,159,34,35,127,110,38],"347":[28,29,31,159,34,35,127,110,38],"359":[28,29,31,159,34,35,127,110,38],"375":[28,29,31,159,34,35,127,110,38],"389":[28,29,31,159,34,35,127,110,38],"405":[28,29,31,159,34,35,127,110,38],"421":[28,29,31,159,34,35,127,110,38],"428":[28,29,31,159,34,35,127,110,38],"458":[28,29,31,159,34,35,127,110,38],"485":[28,29,31,159,34,35,127,110,38],"486":[28,29,31,159,34,35,127,110,38],"487":[28,29,31,159,34,35,127,110,38],"488":[28,29,31,159,34,35,127,110,38],"515":[28,29,31,159,34,35,127,110,38],"520":[28,29,31,159,34,35,127,110,38],"567":[28,29,31,159,34,35,127,110,38],"603":[28,29,31,159,34,35,127,110,38],"613":[28,29,31,159,34,35,127,110,38],"636":[28,29,31,159,34,35,127,110,38],"665":[28,29,31,159,34,35,127,110,38],"676":[28,29,31,159,34,35,127,110,38],"695":[28,29,31,159,34,35,127,110,38],"718":[28,29,31,159,34,35,127,110,38],"737":[28,29,31,159,34,35,127,110,38],"746":[28,29,31,159,34,35,127,110,38],"758":[28,29,31,159,34,35,127,110,38],"792":[28,29,31,159,34,35,127,110,38],"839":[28,29,31,159,34,35,127,110,38],"845":[28,29,31,159,34,35,127,110,38],"848":[28,29,31,159,34,35,127,110,38],"853":[28,29,31,159,34,35,127,110,38],"858":[28,29,31,159,34,35,127,110,38],"862":[28,29,31,159,34,35,127,110,38]},"packages/cli/src/services/ai-gateway.service.ts":{"57":[1,2,28,29,31,159,34,35,110,38],"71":[1,2,28,29,31,159,34,35,110,38],"79":[1,2,28,29,31,159,34,35,110,38],"88":[1,2,28,29,31,159,34,35,110,38],"121":[1,2,28,29,31,159,34,35,110,38],"149":[1,2,28,29,31,159,34,35,110,38],"174":[1,2,28,29,31,159,34,35,110,38],"251":[1,2,28,29,31,159,34,35,110,38],"259":[1,2,28,29,31,159,34,35,110,38],"273":[1,2,28,29,31,159,34,35,110,38],"302":[1,2,28,29,31,159,34,35,110,38],"321":[1,2,28,29,31,159,34,35,110,38],"355":[1,2,28,29,31,159,34,35,110,38],"375":[1,2,28,29,31,159,34,35,110,38],"382":[1,2,28,29,31,159,34,35,110,38],"394":[1,2,28,29,31,159,34,35,110,38],"404":[1,2,28,29,31,159,34,35,110,38],"448":[1,2,28,29,31,159,34,35,110,38],"466":[1,2,28,29,31,159,34,35,110,38],"483":[1,2,28,29,31,159,34,35,110,38],"488":[1,2,28,29,31,159,34,35,110,38],"495":[1,2,28,29,31,159,34,35,110,38],"511":[1,2,28,29,31,159,34,35,110,38],"531":[1,2,28,29,31,159,34,35,110,38]},"packages/cli/src/telemetry/index.ts":{"129":[83,28,29,30,31,32,33,34,35,110,38],"141":[83,28,29,30,31,32,33,34,35,110,38],"186":[83,28,29,30,31,32,33,34,35,110,38],"216":[83,28,29,30,31,32,33,34,35,110,38],"227":[83,28,29,30,31,32,33,34,35,110,38],"243":[83,28,29,30,31,32,33,34,35,110,38],"268":[83,28,29,30,31,32,33,34,35,110,38],"284":[83,28,29,30,31,32,33,34,35,110,38],"285":[83,28,29,30,31,32,33,34,35,110,38],"309":[83,28,29,30,31,32,33,34,35,110,38],"317":[83,28,29,30,31,32,33,34,35,110,38],"318":[83,28,29,30,31,32,33,34,35,110,38],"340":[83,28,29,30,31,32,33,34,35,110,38],"350":[83,28,29,30,31,32,33,34,35,110,38],"364":[83,28,29,30,31,32,33,34,35,110,38],"375":[83,28,29,30,31,32,33,34,35,110,38],"379":[83,28,29,30,31,32,33,34,35,110,38],"380":[83,28,29,30,31,32,33,34,35,110,38],"381":[83,28,29,30,31,32,33,34,35,110,38],"382":[83,28,29,30,31,32,33,34,35,110,38],"383":[83,28,29,30,31,32,33,34,35,110,38],"384":[83,28,29,30,31,32,33,34,35,110,38],"388":[83,28,29,30,31,32,33,34,35,110,38],"435":[83,28,29,30,31,32,33,34,35,110,38],"448":[83,28,29,30,31,32,33,34,35,110,38],"490":[83,28,29,30,31,32,33,34,35,110,38],"528":[83,28,29,30,31,32,33,34,35,110,38],"552":[83,28,29,30,31,32,33,34,35,110,38],"557":[83,28,29,30,31,32,33,34,35,110,38],"594":[83,28,29,30,31,32,33,34,35,110,38],"619":[83,28,29,30,31,32,33,34,35,110,38],"625":[83,28,29,30,31,32,33,34,35,110,38],"689":[83,28,29,30,31,32,33,34,35,110,38],"698":[83,28,29,30,31,32,33,34,35,110,38],"702":[83,28,29,30,31,32,33,34,35,110,38],"706":[83,28,29,30,31,32,33,34,35,110,38],"710":[83,28,29,30,31,32,33,34,35,110,38]},"packages/cli/src/utils/ai-proxy-fetch.ts":{"14":[83,146,11,28,29,31,159,34,35],"33":[83,146,11,28,29,31,159,34,35],"51":[83,146,11,28,29,31,159,34,35],"67":[83,146,11,28,29,31,159,34,35]},"packages/cli/src/utils/node-definition-dirs.ts":{"9":[28,29,31,159,34,35]},"packages/cli/src/workflows/execution-timeout-validation.ts":{"6":[28,126,34,35],"20":[28,126,34,35]},"packages/nodes-base/nodes/NoOp/NoOp.node.ts":{"33":"b:ACAAAAgk/gEECABAQoiAAQBRAAAAAAEIAEAABAA="},"packages/workflow/src/schemas.ts":{"89":[20,28,126,34,35],"102":[20,28,126,34,35],"166":[20,28,126,34,35],"240":[20,28,126,34,35],"265":[20,28,126,34,35],"431":[20,28,126,34,35],"508":[20,28,126,34,35],"509":[20,28,126,34,35],"522":[20,28,126,34,35]},"localhost-46623/assets/index-BoK1c_f3.js":{"3":[35]},"localhost-46623/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[35],"9":[35],"10":[35],"19":[35],"23":[35],"29":[35],"33":[35],"34":[35]},"packages/frontend/@n8n/design-system/src/components/N8nAiActivityStepChevron/AiActivityStepChevron.vue":{"16":[86,124,28,29,30,92,126,31,34,161,35,127]},"packages/frontend/@n8n/design-system/src/components/N8nAnimatedCollapsibleContent/AnimatedCollapsibleContent.vue":{"12":[86,124,28,29,30,92,126,31,34,161,35,127],"13":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nApprovalCard/ApprovalCard.vue":{"68":[86,124,126,35],"74":[86,124,126,35],"82":[86,124,126,35],"94":[86,124,126,35],"122":[86,124,126,35],"123":[86,124],"129":[86,124,126,35],"133":[86,124,126,35],"139":[86,124],"155":[86,124,126,35],"162":[86,124,126,35],"193":[86,124],"210":[86,124,126,35],"224":[86,124,126,35],"225":[86,124,126]},"packages/frontend/@n8n/design-system/src/components/N8nCallout/Callout.vue":{"10":"b:ggBFAAoAAAgAeUQAAgAQEABxIrhRAAQEAcQPAAA=","36":"b:ggBFAAoAAAgAeUQAAgAQEABxIrhRAAQEAcQPAAA=","45":"b:AgBFAAoAAAgAOUAAAgAQEABRIphBAAQEAcQNAAA=","49":"b:AgBFAAoAAAgAOUAAAgAQEABRIphBAAQEAcQNAAA=","58":"b:ggBFAAoAAAgAeUQAAgAQEABxIrhRAAQEAcQPAAA=","65":[1,86,22,124],"70":"b:ggBFAAoAAAgAeUQAAgAQEABxIrhRAAQEAcQPAAA="},"packages/frontend/@n8n/design-system/src/components/N8nChatActions/ChatActions.vue":{"21":"b:AAAA8AgAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","39":"b:AAAA8AgAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","42":[86,124,28,29,30,92,126,31,160,161,35,127],"48":[86,124],"54":[86,124],"62":[86,124],"68":[86,124],"78":[86,124],"85":"b:AAAA8AgAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","88":[86,124],"96":"b:AAAA8AgAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","99":[86,124],"104":[86,124,161],"108":"b:AAAA8AgAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","118":[86,124,28,29,30,92,126,31,160,161,35,127],"129":[86,124,28,29,30,92,126,31,160,161,35,127],"134":[86,124,28,29,30,92,126,31,160,161,35,127],"143":[86,124,28,29,30,92,126,31,160,161,35,127],"159":"b:AAAA8AgAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","167":[86,124],"174":"b:AAAA8AgAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","182":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nChatInput/useChatInputAutoFocus.ts":{"16":[86,124],"28":[86,124],"32":[86,124],"36":"b:AAABMB4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","42":[86,124],"43":[86,124],"45":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nChatMessage/ChatMessage.vue":{"9":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","14":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","32":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nHoverCard/HoverCard.vue":{"61":"b:CgAA8BwAAAAAAEAQCAAA0AAAAIAHAAAAAAAAAAA=","89":"b:CgAA8BwAAAAAAEAQCAAA0AAAAIAHAAAAAAAAAAA=","91":"b:CgAA8BwAAAAAAEAQCAAA0AAAAIAHAAAAAAAAAAA=","96":[86,124],"101":[86,124],"105":"b:CgAA8BwAAAAAAEAQCAAA0AAAAIAHAAAAAAAAAAA=","106":[86,124],"115":"b:CgAA8BwAAAAAAEAQCAAA0AAAAIAHAAAAAAAAAAA=","124":"b:CgAA8BwAAAAAAEAQCAAA0AAAAIAHAAAAAAAAAAA=","128":"b:CgAA8BwAAAAAAEAQCAAA0AAAAIAHAAAAAAAAAAA=","133":"b:CgAA8BwAAAAAAEAQCAAA0AAAAIAHAAAAAAAAAAA=","145":[86,124],"152":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/arrows-down-left-up-right--outline-16.svg":{"9":"b:BgAA8BwgAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/calendar--outline-16.svg":{"9":"b:AAAAMx4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/chat-bubble-plus--outline-16.svg":{"9":"b:BgAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/file-text--outline-16.svg":{"9":"b:AAAAMB4gAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/microphone--outline-16.svg":{"9":"b:BAA98B4gAAAAAEAQAAAA0AAAAJgHAAAAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/robot--outline-12.svg":{"9":"b:AAAAMB4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/slash-circle--outline-16.svg":{"9":[86,124,126,35,45]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/speaker-waves--outline-16.svg":{"9":"b:AAA88AggAAAAAEAQAAAA0AAAABgDAAAAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/thumbs-down--outline-16.svg":{"9":"b:AAAA8AggAAAAAEAQAAAA0AAAAYADAAAAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/thumbs-up--outline-16.svg":{"9":"b:AAAA8AggAAAAAEAQAAAA0AAAAYADAAAAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/workflow--outline-16.svg":{"9":"b:CAABkwo4AIiAAEIAAAAA0gAAAAAEwAAADAAgAQA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/filled-square.svg":{"10":"b:4Ak8MBwAAAAAAEAQAAAA0AAAAZgDAAAAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/spinner.svg":{"9":"b:5gkAEAwAAAAAAEAAAAAA0AAAAQABAAAABACAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nMarkdown/Markdown.vue":{"45":"b:AAA88AwAAACAAEQQEAAA0AABABgDAAEIAAEQBAA=","81":"b:AAA88AwAAACAAEQQEAAA0AABABgDAAEIAAEQBAA=","83":"b:AAA88AwAAACAAEQQEAAA0AABABgDAAEIAAEQBAA=","120":"b:AAA88AwAAACAAEQQEAAA0AABABgDAAEIAAEQBAA=","127":[86,124,100],"147":[86,124,176,187,71,200,136,212,218,100],"151":[86,124,176,187,71,200,136,212,218,100],"152":[86,124],"185":[86,124,176,187,71,200,136,212,218,100],"193":[86,18,124,28,126,35,127,200,218,100],"226":"b:AAA88AwAAACAAEQQEAAA0AABABgDAAEIAAEQBAA=","233":[86,124],"251":[86,124],"270":[86,124],"283":[86,124],"292":[86,124],"301":"b:AAA88AwAAACAAEQQEAAA0AABABgDAAEIAAEQBAA=","319":[86,124,82,100]},"packages/frontend/@n8n/design-system/src/components/N8nMarkdown/youtube.ts":{"34":"b:AAA88AwAAACAAEQQEAAA0AABABgDAAEIAAEQBAA=","42":"b:AAA88AgAAAAAAEAQEAAA0AABAAgDAAEAAAEQBAA=","63":[86,124]},"packages/frontend/editor-ui/src/app/components/WorkflowCanvasHost.vue":{"9":[28,126,31,34,35,127],"35":[28,126,31,34,35,127],"45":[28,126,31,34,35,127],"50":[28,126,31,34,35,127],"60":[28,126,31,34,35,127]},"packages/frontend/editor-ui/src/app/components/WorkflowCanvasHostBody.vue":{"20":[28,126,31,34,35,127],"56":[28,126,31,34,35,127],"75":[28,126,31,34,35,127],"93":[28,126,31,34,35,127],"103":[28,126,31,34,35,127],"110":[28,127],"124":[28,126,31,34,35,127],"130":[28,126,31,34,35,127],"131":[28,126,31,34,35,127]},"packages/frontend/editor-ui/src/app/composables/useApprovalCardLabels.ts":{"5":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","7":[126,35]},"packages/frontend/editor-ui/src/app/layouts/InstanceAiLayout.vue":{"21":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","29":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","30":[28,126,35,127],"37":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","49":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/experiments/instanceAiFreeNudge/components/InstanceAiFreeNudge.vue":{"9":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","24":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","25":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","34":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/experiments/instanceAiFreeNudge/stores/instanceAiFreeNudge.store.ts":{"25":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","31":[28,29,92,126,33,159,160,34,161,35,127,36],"34":[28,29,92,126,33,159,160,34,161,35,127,36],"47":[28,29,92,126,33,159,160,34,161,35,127,36],"56":[28,29,92,126,33,159,160,34,161,35,127,36],"59":[28,29,92,126,33,159,160,34,161,35,127,36]},"packages/frontend/editor-ui/src/experiments/instanceAiInspirationFromTaxonomy/metadata.ts":{"47":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","53":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/experiments/instanceAiInspirationFromTaxonomy/useInstanceAiInspirationFromTaxonomyExperiment.ts":{"6":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","9":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","12":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/experiments/instanceAiPersonalizedPromptSuggestions/profileOverride.ts":{"60":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","73":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","106":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","114":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","130":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/experiments/instanceAiPersonalizedPromptSuggestions/useInstanceAiPersonalizedPromptSuggestionsExperiment.ts":{"8":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","11":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","14":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","29":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/experiments/instanceAiProactiveAgent/useInstanceAiProactiveAgentExperiment.ts":{"6":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","9":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/experiments/instanceAiPromptSuggestionsV2/useInstanceAiPromptSuggestionsV2Experiment.ts":{"6":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","9":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/experiments/instanceAiSplitEmptyState/useInstanceAiSplitEmptyStateExperiment.ts":{"5":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","7":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","10":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/experiments/instanceAiWorkflowPreviewSuggestions/components/WorkflowPreviewSuggestions.vue":{"11":"b:AAAAMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","42":[28,29,92,126,159,160,34,161,35,127],"59":[28,29,92,126,159,160,34,161,35,127],"113":"b:AAAAMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","128":"b:AAAAMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/experiments/openWorkflowInAssistant/components/ManualEditorButton.vue":{"11":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","18":[162],"19":[162],"30":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/experiments/openWorkflowInAssistant/components/OpenWorkflowInAssistantNotification.vue":{"10":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","16":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","22":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/experiments/openWorkflowInAssistant/stores/openWorkflowInAssistant.store.ts":{"22":"b:AAAJ8Bw4AAAAAEI7HAAA0gAAAIgHQAAABAgAAAA=","30":[86,124],"33":"b:AAAJ8Bw4AAAAAEI7HAAA0gAAAIgHQAAABAgAAAA=","40":[86,124,162],"42":[86,124],"46":[86,124,162,45,203,99,81],"49":"b:AAAAAAA4AAAAAEIhHAAAEgAAAAAEQAAAAAgAAAA=","53":[86,124],"66":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","75":[86,124,36],"99":[86,124],"107":[86,124],"130":[86,124],"134":[86,124],"141":[86,124],"154":[86,124]},"packages/frontend/editor-ui/src/features/agents/agentEvals.store.ts":{"101":"b:BgAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","221":[1,2]},"packages/frontend/editor-ui/src/features/agents/components/AgentPreviewDock.vue":{"32":"b:DgAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","94":[1,2],"141":[2],"148":[2],"213":[1,2],"244":[1,2],"275":[1,2],"306":[2]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentCapabilitySummary.ts":{"19":[86,124],"33":[86,124],"48":[86,124],"57":[86,124],"63":[86,124],"77":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","88":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/agents/composables/useTestAgentPreviewFlag.ts":{"5":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/agents/n8nChatPage/mergeRecentChats.ts":{"29":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","47":[88,22,25,44,45,63]},"packages/frontend/editor-ui/src/features/agents/n8nChatPage/useMergedChatHistory.ts":{"26":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","34":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","39":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","50":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","105":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/agents/n8nChatPage/usePagedN8nChatThreads.ts":{"87":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","123":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/agents/utils/agentPreviewUrl.ts":{"34":[28,126,35,127]},"packages/frontend/editor-ui/src/features/ai/assistant-at-mentions/assistantAtMentions.telemetry.ts":{"19":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","25":[31],"29":[31]},"packages/frontend/editor-ui/src/features/ai/assistant-at-mentions/composables/useAssistantAtMentions.ts":{"22":[31],"26":[31],"33":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","51":[28,29,92,126,31,159,160,34,161,35,127],"57":[31],"64":[28,29,92,126,159,160,34,161,35,127],"81":[28,29,92,126,31,159,160,34,161,35,127],"90":[31],"115":[28,29,92,126,31,159,160,34,161,35,127],"163":[28,29,92,126,31,159,160,34,161,35,127],"233":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","234":[31],"240":[28,29,92,126,31,159,160,34,161,35,127]},"packages/frontend/editor-ui/src/features/ai/assistant-at-mentions/composables/useAssistantMentionAttachments.ts":{"35":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","213":[28,29,92,126,159,160,34,161,35,127],"217":[28,29,92,126,159,160,34,161,35,127],"226":[28,29,92,126,159,160,34,161,35,127],"230":[28,29,92,126,159,160,34,161,35,127],"244":[28,29,92,126,159,160,34,161,35,127],"249":[28,29,92,126,159,160,34,161,35,127],"267":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","268":[30,92,31,161,36],"276":[28,29,92,126,159,160,34,161,35,127,162]},"packages/frontend/editor-ui/src/features/ai/assistant-at-mentions/composables/useAssistantMentionAvailability.ts":{"8":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","18":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","19":[31],"23":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","56":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","57":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/assistant-at-mentions/composables/useIsAssistantAtMentionsEnabled.ts":{"9":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/chatHub/chat.utils.ts":{"25":"b:AAA88BwAAAAAAEAQAAAA0AAAAJgHAAAAAAAAAAA=","46":[86,18,155,19,156,20,21,124],"64":[86,18,155,19,156,20,21,124],"71":[86,18,155,156,21,124],"82":[86,156,21,124],"110":[86,18,155,19,156,20,21,124],"122":[86,18,155,19,156,20,21,124],"158":[86,156,21,124],"167":[86,124],"171":[86,124],"196":[86,18,155,19,156,20,21,124],"200":[86,155,19,156,124],"215":[86,18,155,19,156,20,21,124],"227":[86,18,155,19,156,20,21,124],"280":[86,18,155,19,156,20,21,124],"331":[86,18,155,19,156,20,21,124],"335":[86,18,155,19,156,20,21,124],"341":[86,18,155,19,156,20,21,124],"348":[86,21,124],"352":[86,18,155,19,156,20,124],"361":[86,18,155,19,156,20,124],"381":[86,18,155,19,156,20,21,124],"412":[86,18,155,19,156,124],"442":[86,18,155,19,156,20,21,124],"446":[86,18,155,19,156,20,21,124],"460":[86,18,155,19,156,20,21,124],"470":[86,18,155,19,156,20,21,124],"563":[86,18,155,19,156,20,21,124],"568":[86,124],"571":[86,124]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useChatHubMarkdownOptions.ts":{"25":[28,126,35,127],"40":"b:AAA88AwAAAAAAAAQAAAAwAAAABgDAAAAAAAAAAA=","56":"b:AAA88AwAAAAAAAAQAAAAwAAAABgDAAAAAAAAAAA=","75":"b:AAA88AwAAAAAAAAQAAAAwAAAABgDAAAAAAAAAAA=","86":[18],"139":"b:AAA88AwAAAAAAAAQAAAAwAAAABgDAAAAAAAAAAA=","140":"b:AAA88AwAAAAAAAAQAAAAwAAAABgDAAAAAAAAAAA=","145":[28,126,35,127],"157":"b:AAA88AwAAAAAAAAQAAAAwAAAABgDAAAAAAAAAAA=","162":[18],"180":"b:AAA88AwAAAAAAAAQAAAAwAAAABgDAAAAAAAAAAA=","200":"b:AAA88AwAAAAAAAAQAAAAwAAAABgDAAAAAAAAAAA=","207":"b:AAA88AwAAAAAAAAQAAAAwAAAABgDAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/composables/useAgentEvalsFlag.ts":{"21":"b:BgAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","24":"b:BgAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/InstanceAiEmptyView.vue":{"135":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","144":[28,29,92,126,159,160,34,161,35,127],"153":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","186":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","203":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","209":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","213":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","224":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","234":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","253":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","261":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","271":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","315":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","350":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","357":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","381":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","402":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","417":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","422":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","427":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","522":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","549":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","553":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","556":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","564":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","574":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","599":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","624":[16,28,29,92,126,159,160,34,161,35,127],"628":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","629":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","643":[28,29,92,126,159,160,34,161,35,127],"913":[28,29,92,126,159,160,34,161,35,127],"926":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/InstanceAiThreadView.vue":{"92":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","113":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","140":[161],"150":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","159":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","160":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","164":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","203":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","242":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","244":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","251":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","257":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","266":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","269":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","270":[28,126,34,35,127],"276":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","285":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","291":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","309":[160,36],"332":[28],"371":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","372":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","377":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIADAAAAAAAAAAA=","380":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIADAAAAAAAAAAA=","385":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","392":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","399":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","403":[28,127],"438":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","443":[30,92,31,161,36],"451":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","454":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","457":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","461":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","467":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","476":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","479":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","482":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","485":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","503":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","511":[28,126,31,34,35,127],"521":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","522":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","523":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","526":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","537":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","540":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","551":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","562":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","586":[28,126,31,34,35,127],"594":[28],"600":[28,126,31,34,35,127],"620":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","643":[30,92,31,161,162,36],"651":[126,160,161,35],"659":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","669":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","670":[30,92,31,161,162,36],"681":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","685":[161,162],"867":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","877":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","882":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","909":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","929":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","968":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","977":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","979":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","989":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","996":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","1012":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","1042":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","1066":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/InstanceAiView.vue":{"30":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","44":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","52":[33],"69":[33],"74":[31],"90":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","116":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIADAAAAAAAAAAA=","118":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIADAAAAAAAAAAA=","131":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","149":[162]},"packages/frontend/editor-ui/src/features/ai/instanceAi/agentTimeline.utils.ts":{"77":[28,29,126,34,35,127],"103":[28,29,30,92,126,31,159,160,34,161,35,127],"117":[28,29,92,126,31,34,161,35,127],"123":[28,29,30,92,126,31,160,34,161,35,127],"134":[28,29,30,92,126,31,160,34,161,35,127],"155":[28,29,30,92,126,31,160,34,161,35,127],"185":[28,29,30,92,126,31,160,34,161,35,127],"190":[28,29,92,126,31,34,161,35,127],"198":[28,29,30,92,126,31,160,34,161,35,127],"305":[28,29,30,92,126,31,160,34,161,35,127],"362":[30]},"packages/frontend/editor-ui/src/features/ai/instanceAi/approvalDetails.ts":{"5":[126,35]},"packages/frontend/editor-ui/src/features/ai/instanceAi/builderAgents.ts":{"18":[30],"30":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIADAAAAAAAAAAA=","39":[30],"47":[30],"48":[30],"56":[30],"71":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIADAAAAAAAAAAA=","82":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIADAAAAAAAAAAA=","145":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","147":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIADAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/canvasPreview.utils.ts":{"65":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","104":[86,124],"108":[86,124],"132":[86,124,28,30,126,31,35,127],"144":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","174":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","204":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","242":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","292":[86,124,28,126,31,34,35,127],"299":[86,124],"313":[86,124,126,35],"369":[86,124],"403":[86,124],"404":[86,124],"405":[86,124],"406":[86,124],"407":[86,124],"408":[86,124],"409":[86,124],"410":[86,124],"413":[86,124],"439":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","463":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","489":[86,124],"520":[86,124],"551":[86,124],"576":[86,124],"594":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","620":[86,124,28,126,31,34,35,127],"628":[86,124,28,126,31,34,35,127],"667":[86,124,28,126,127],"670":[86,124],"673":[86,124]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/AgentActivityTree.vue":{"10":[28,29,30,92,126,31,159,160,34,161,35,127]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/AgentTimeline.vue":{"33":[28,29,30,92,126,31,159,160,34,161,35,127],"120":[28,29,30,92,126,31,159,160,34,161,35,127],"123":[28,29,30,92,126,31,159,160,34,161,35,127],"132":[28,29,30,92,126,31,159,160,34,161,35,127],"146":[28,92,126,127],"154":[28,29,30,92,126,31,159,160,34,161,35,127],"164":[30],"175":[28,29,92,126,31,34,161,35,127],"196":[28,29,30,92,126,31,34,161,35,127],"293":[28,29,30,92,126,31,159,160,34,161,35,127]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/DitherTrailGrid.vue":{"17":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","80":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","100":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","147":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","178":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","193":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","308":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","327":[28,29,92,126,159,160,34,161,35,127],"377":[28,29,92,126,159,160,34,161,35,127],"448":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","517":[28,29,92,126,159,160,34,161,35,127],"530":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","556":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","568":[28,29,92,126,159,160,34,161,35,127],"578":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiArtifactsPanel.vue":{"25":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","30":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","34":[28,29,30,92,126,159,160,34,161,35,127,36],"74":[28],"94":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","95":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","96":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","112":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","128":[28,126,35,127,162],"144":[28,126,35,127,162],"175":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","214":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","224":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","290":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","296":[28,126,35,127,162],"302":[28]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiConfirmationPanel.vue":{"45":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","55":[126,35],"65":[126,35],"121":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","182":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","185":[126,35],"202":[126,35],"238":[126,35],"261":[126,35],"273":[126,35],"289":[126,35],"311":[126],"350":[35],"456":[28,126,31,34,35,127],"525":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","729":[126,35]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiConversation.vue":{"149":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","170":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","175":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","177":[28,126,31,34,35,127,162],"178":[28,126,31,34,35,127,162],"183":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","208":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","216":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","217":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","221":[28,29,92,126,159,160,34,161,35,127,36],"228":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","237":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","241":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","247":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","266":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","267":[28,29,30,92,31,159,160,34,161,36],"278":[161,162],"287":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","299":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","304":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","308":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","392":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","394":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","405":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","416":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","427":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","428":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","434":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","449":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","453":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","470":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","484":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","490":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","498":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","508":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","512":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","524":[30,92,31,161,162,36],"527":[30,92,31,161,36],"544":[36],"567":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","578":[28,29,92,126,159,160,34,161,35,127,162,36],"606":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","611":[161,162],"630":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","636":[160],"733":[160],"748":[160],"901":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","934":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","942":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","997":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","1029":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiEmptyState.vue":{"5":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","22":"b:AAABMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiInput.vue":{"175":[31],"197":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","200":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","209":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","210":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","231":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","263":[28,29,92,126,159,160,34,161,35,127],"285":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","290":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","292":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","295":[31],"329":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","330":[29,160],"332":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","334":[28,29,92,126,31,159,160,34,161,35,127],"335":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","338":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","343":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","348":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","349":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","351":[31],"352":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","359":[28,29,92,126,31,159,160,34,161,35,127],"363":[28,29,92,126,31,159,160,34,161,35,127],"379":[31],"386":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","420":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","426":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","434":"b:AAAAMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","437":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","441":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","443":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","472":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","489":[28,29,92,126,31,159,160,34,161,35,127],"496":[28,29,92,126,159,160,34,161,35,127],"524":[28,29,92,126,159,160,34,161,35,127],"537":[28,29,92,126,159,160,34,161,35,127],"545":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","572":[28,29,92,126,159,160,34,161,35,127],"578":[28,29,92,126,159,160,34,161,35,127],"601":[28,29,92,126,159,160,34,161,35,127],"649":[28,29,92,126,159,160,34,161,35,127],"680":[28,29,92,126,159,160,34,161,35,127],"706":[29,160],"737":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","738":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","766":[31],"784":[29,160],"821":[28,29,92,126,159,160,34,161,35,127],"834":[28,29,92,126,159,160,34,161,35,127],"901":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","911":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","919":[28,29,92,126,159,160,34,161,35,127],"920":[28,29,92,126,159,160,34,161,35,127],"921":[31],"947":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","970":[29,160],"981":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","989":[31],"1009":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","1016":[28,29,92,126,159,160,34,161,35,127],"1020":[28,29,92,126,159,160,34,161,35,127]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiInputMenu.vue":{"21":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","32":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","70":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","84":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiMarkdown.vue":{"12":[28,29,30,92,126,31,160,34,161,35,127],"52":[28,126,31,34,35,127],"88":[28,29,30,92,126,31,160,34,161,35,127],"90":[28,126,35,127],"102":[28,126,34,35,127],"144":[28,126,31,34,35,127],"175":[28,29,30,92,126,31,160,34,161,35,127],"181":[28,126,31,34,35,127],"186":[28,126,31,34,35,127],"207":[28,126,35,127],"217":[28,29,30,92,126,31,160,34,161,35,127],"235":[28,126,35,127],"286":[28,126,35,127],"311":[28,29,30,92,126,31,160,34,161,35,127],"447":[28,92,126,160,35,127],"454":[28,29,30,92,126,31,160,34,161,35,127]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiMessage.vue":{"25":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIADAAAAAAAAAAA=","35":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIADAAAAAAAAAAA=","36":[28,29,30,92,126,31,159,160,34,161,35,127],"37":[28,29,30,92,126,31,159,160,34,161,35,127],"39":[28,29,30,92,126,31,160,34,161,35,127],"45":[28,29,30,92,126,31,159,160,34,161,35,127],"51":[160,35],"54":[28,29,30,92,126,31,159,160,34,161,35,127],"60":[159],"69":[159],"76":[28,29,30,92,126,31,159,160,34,161,35,127],"90":[160,35],"97":[160,35],"107":[28,29,92,126,31,159,160,34,161,35,127,36],"108":[29,31,160],"120":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIADAAAAAAAAAAA=","132":[28,29,30,92,126,31,159,160,34,161,35,127],"139":[28,29,30,92,126,31,159,160,34,161,35,127],"145":[28,29,30,92,126,31,159,160,34,161,35,127],"147":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIADAAAAAAAAAAA=","154":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIADAAAAAAAAAAA=","158":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIADAAAAAAAAAAA=","182":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIADAAAAAAAAAAA=","190":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIADAAAAAAAAAAA=","195":[29,31,160],"217":[159],"223":[159],"231":[160,35],"243":[160,35],"278":[28,29,30,92,126,31,159,160,161,35,127]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiPreviewTabBar.vue":{"35":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","65":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","76":[28,126,31,34,35,127],"82":[28,126,31,34,35,127],"87":[28,126,31,34,35,127],"114":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","115":[28,126,31,34,35,127],"118":[28,126,31,34,35,127],"147":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","150":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","258":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIADAAAAAAAAAAA=","260":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIADAAAAAAAAAAA=","287":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","307":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","308":[28,126,31,34,35,127,162],"310":[28,126,31,34,35,127,162],"332":[28,126,31,34,35,127,162],"392":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIADAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiStatusBar.vue":{"19":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","26":[28,29,159,160,34,161,35,36],"32":[28,29,159,160,34,161,35,36],"57":[35],"66":[28,29,159,160,34,161,35,36],"76":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","80":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIADAAAAAAAAAAA=","84":[28,29,92,126,160,34,161,35,127],"95":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","102":[28,29,159,160,34,161,35,36],"111":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","126":[161,162],"131":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiThreadList.vue":{"72":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","74":[161],"83":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","88":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","101":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","128":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","130":[161],"134":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","147":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","148":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","152":[161],"157":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","160":[161],"164":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","165":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","192":[161],"200":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","207":[161],"219":[161],"229":[31,161],"241":[161],"250":[161],"278":[161],"282":[161],"284":[161],"288":[161],"294":[161],"299":[161],"315":[161],"324":[161],"336":[161],"350":[161],"351":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","376":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","391":[161],"412":[161],"423":[161],"427":[161],"432":[161],"437":[161],"446":[161],"468":[161]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiViewHeader.vue":{"14":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","45":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","60":[161],"62":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","77":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiWorkflowPreview.vue":{"39":[28,126,31,34,35,127],"60":[28,126,31,34,35,127],"117":[28,126,31,34,35,127],"118":[28,126,31,34,35,127],"120":[28,126,35,127],"125":[28,126,31,34,35,127],"157":[28,126,31,35,127],"174":[28,126,31,34,35,127],"191":[28,126,31,34,35,127],"215":[28,126,31,34,35,127]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/LimitedModeNotice.vue":{"14":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/ThinkingBlock.vue":{"19":[28,29,92,126,31,34,161,35,127],"32":[28,29,126,34,35,127],"40":[28,29,92,126,31,34,161,35,127],"44":[28,29,92,126,31,34,161,35,127],"52":[28,29,92,126,31,34,161,35,127],"61":[28,29,92,126,31,34,161,35,127],"62":[28,29,92,126,31,34,161,35,127],"68":[28,29,92,126,31,34,161,35,127],"87":[28,29,92,126,31,34,161,35,127]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/TimelineTextSegment.vue":{"10":[28,29,30,92,126,31,160,34,161,35,127]},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useAgentMutationRefresh.ts":{"12":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","13":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","24":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useBrowserUseConnection.ts":{"24":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useBuildingArtifactIds.ts":{"21":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","24":[28,126,31,34,35,127,162]},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useCreditWarningBanner.ts":{"9":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","12":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","23":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useInstanceAiInputMenuItems.ts":{"29":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","41":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","42":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","50":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","51":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","71":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","136":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","156":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useInstanceAiThreadHistory.ts":{"20":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","22":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","27":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","46":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","54":[28,29,92,126,159,160,34,161,35,127,162]},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useInstanceAiWorkflowPreviewExecution.ts":{"26":[126],"30":[126],"50":[28,126,31,34,35,127],"72":[28,126,35,127],"83":[28,126,35,127],"88":[28,126,35,127],"103":[28,126,35,127],"113":[28,126,35,127],"124":[28,126,31,34,35,127],"125":[28,126,35,127],"134":[126],"149":[28,126,31,34,35,127],"153":[126],"168":[28,126,31,34,35,127],"176":[28,126,31,34,35,127],"208":[28,126,31,34,35,127],"221":[28,126,31,34,35,127],"249":[28,126,31,34,35,127],"261":[28,126,31,34,35,127],"262":[28,126,31,34,35,127],"269":[28,126,31,34,35,127],"276":[28,126,31,34,35,127],"282":[28,127]},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useIsAgentWorking.ts":{"22":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","25":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useOpenArtifactTabs.ts":{"28":[28,126,31,34,35,127],"36":[28,126,34,35,127],"58":[28,126,34,35,127],"67":[31],"78":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","98":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","103":[28,126,31,34,35,127],"125":[28,126,34,35,127],"129":[28,126,35],"131":[28,126,35],"159":[28,126,34,35,127],"167":[126,35],"212":[28,34,35,127],"213":[28,34,35,127],"230":[28,34,161,35,127,162],"242":[28,126,34,35,127],"247":[28,34,35,127],"260":[28,126,31,34,35,127],"268":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","290":[161,162]},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useProjectResourceSearch.ts":{"14":[28,126,31,34,35,127],"23":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","38":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIADAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useTabDragReorder.ts":{"37":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","123":[161,162],"203":[161,162]},"packages/frontend/editor-ui/src/features/ai/instanceAi/confirmationKinds.ts":{"16":[126,34,35]},"packages/frontend/editor-ui/src/features/ai/instanceAi/constants.ts":{"44":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","60":[86,124,162],"66":[86,124]},"packages/frontend/editor-ui/src/features/ai/instanceAi/embed/instanceAiEmbed.types.ts":{"30":[28,126,31,34,35,127]},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAi.api.ts":{"32":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","59":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","77":[86,124],"86":[86,124],"104":[86,124],"117":[86,124,126,35],"135":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","143":[86,124],"163":[86,124],"172":[86,124],"186":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","200":[86,124],"208":[86,16,124,33],"230":[86,124],"250":[86,124]},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAi.handoffContext.ts":{"20":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAi.liveRunState.ts":{"9":[86,124,30,92,126,31,161,35,36],"15":[86,124],"16":[86,124],"19":[86,124,34],"33":[86,124],"44":[86,124,126,35],"61":[86,124,126,35],"73":[86,124,126,35],"89":[86,124,126,35]},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAi.mcp.api.ts":{"19":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAi.reducer.ts":{"53":[86,124,28,29,92,126,159,160,34,161,35,127],"60":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","65":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","110":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","119":[86,124,28,29,30,92,31,161],"127":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","144":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","149":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","179":[86,124,28,29,92,126,159,160,34,161,35,127],"193":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAi.responseTiming.ts":{"2":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAi.settings.api.ts":{"16":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","22":[86,124,33],"29":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","35":[86,124],"42":"b:AAAA8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","48":"b:AAAA8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","54":[86,124],"60":[86,124],"67":[86,124],"74":[86,124,33]},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAi.threadRuntime.ts":{"196":[86,124,28,29,92,126,159,34,161,35,127,36],"203":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","208":"b:AAAAcBwAAAAAAEAQAAAA0AAAAIACAAAAAAAAAAA=","213":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","227":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","232":[86,124],"243":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","253":[86,124],"262":[86,124],"271":[86,124],"292":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","320":[86,124,126,34,35],"330":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","345":[86,124],"348":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","366":[86,124,28,29,30,92,31,161],"391":[86,124],"396":[86,124],"404":[86,124],"464":[86,124,30,92,31,161],"496":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","509":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","511":[86,124,161,162],"561":[86,124],"564":[86,124,28,126,31,34,35,127],"575":[86,124,162],"578":[86,124],"584":[86,124],"587":[86,124],"596":[86,124,35,127],"603":[86,124,28,126,31,34,35,127],"606":[86,124,28,126,127],"638":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","639":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","640":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","641":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","649":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","650":[86,124,28,126,31,34,35,127,162],"651":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","652":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","653":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","657":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","658":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","659":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","668":[86,124],"673":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","681":[86,124],"685":[86,124],"708":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","720":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","721":[86,124,28,126,34,35,127],"739":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","741":[86,124,126,34,35],"752":[86,124,28,29,92,126,160,34,161,35,127],"756":[86,124,28,29,92,126,160,34,161,35,127],"761":[86,124,28,29,92,126,159,160,34,161,35,127],"770":[86,124,28,29,92,126,159,160,34,161,35,127],"778":[86,124,28,29,92,126,160,34,161,35,127],"795":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","815":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","832":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","835":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","842":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","844":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","851":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","854":[86,124],"868":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","871":"b:AAAA8BgAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","877":[86,124,30],"888":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","898":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","915":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","932":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","934":[86,124,126,35],"942":[86,124,34],"951":[86,124,126,35],"973":[86,124,126,35],"990":[86,124,126,35],"1037":[86,124,35],"1050":[86,124,126,35],"1058":[86,124,126,34,35],"1074":[86,124,126,34,35],"1093":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","1143":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","1155":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","1281":[86,124,28,29,92,161],"1301":[86,124,28,29,92,161],"1306":[86,124],"1367":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","1385":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","1390":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","1397":[86,124,28,29,92,161],"1402":[86,124,30,92,31,161],"1414":[86,124,161],"1422":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","1426":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","1431":[86,124,161],"1461":[86,124,161],"1467":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","1478":[86,124,30,92,31,161,162,36],"1501":[86,124,30,92,31,161],"1502":[86,124,30,92,31,161],"1528":[86,124,30,92,126,31,161,35,36],"1560":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","1571":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","1590":[86,124],"1597":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","1616":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","1644":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","1707":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","1733":[86,124,160],"1771":[86,124],"1785":[86,124],"1794":[86,124],"1815":[86,124],"1836":[86,124],"1840":[86,124],"1849":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","1850":[86,124],"1861":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","1869":[86,124,126,35],"1914":[86,124],"1924":[86,124]},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAiBrowserUse.telemetry.ts":{"9":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAiMcp.store.ts":{"34":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","63":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","68":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","73":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","157":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAiMcp.telemetry.ts":{"13":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAiPromptSuggestions.telemetry.ts":{"45":"b:AAAAMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","48":"b:AAAAMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","63":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","68":"b:AAAAMB4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","117":"b:AAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceContextLabels.ts":{"45":[28,29,92,126,31,34,161,35,127]},"packages/frontend/editor-ui/src/features/ai/instanceAi/threadArtifacts.ts":{"18":[86,124],"22":[86,124],"46":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","60":[86,124],"62":[86,124],"72":[86,124]},"packages/frontend/editor-ui/src/features/ai/instanceAi/toolLabels.ts":{"160":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","163":[28,29,126,34,35,127]},"packages/frontend/editor-ui/src/features/ai/instanceAi/useArtifactTabSummaries.ts":{"23":[28,126,31,34,35,127,162],"27":[28,126,31,34,35,127,162],"35":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","40":[28,126,31,34,35,127,162],"47":[28,126,31,34,35,127],"91":[28,126,31,34,35,127,162],"93":[28,126,31,34,35,127,162],"96":[28,126,31,34,35,127],"98":[28,126,31,34,35,127],"99":[28,126,31,34,35,127],"115":[28,126,31,34,35,127,162],"118":[28,126,31,34,35,127,162],"119":[28,126,31,34,35,127,162],"125":[28,126,31,34,35,127,162],"129":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","134":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","136":[28,126,31,34,35,127,162],"145":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","146":[28,126,31,34,35,127,162],"148":[28,126,34,35,127],"149":[28,126,34,127],"160":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","161":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","179":[28,126,31,34,35,127,162]},"packages/frontend/editor-ui/src/features/ai/instanceAi/useCanvasPreview.ts":{"55":[29,31,160],"61":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","68":[28,126,31,34,35,127],"84":"b:AAAA8BgAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","89":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","129":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","131":[28,34,35,127],"136":[28,126,31,34,35,127],"137":[28,126,31,34,35,127],"141":[28,126,31,34,35,127],"142":[28,126,31,34,35,127],"151":[28,126,31,34,35,127],"152":[28,126,31,34,35,127],"166":[28,126,31,34,35,127],"177":[28,126,31,34,35,127],"184":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","188":[28,126,31,34,35,127],"195":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","196":[28,126,31,34,35,127,162],"209":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","210":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","216":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","228":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","238":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","255":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","265":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","269":[31],"280":[28],"310":[28,127],"318":[28,126,34,35,127],"332":[28],"365":[28,126,31,34,35,127,162],"367":[28,126,31,34,35,127],"377":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","397":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","398":[28,126,34,35,127],"420":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","431":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","448":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","459":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","481":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","492":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","512":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","523":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","541":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","552":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","569":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/instanceAi/useResourceRegistry.ts":{"70":[86,124,28,29,126,31,34,35,127,162],"100":[86,124,28,126,31,34,35,127,162],"135":[86,124,126,35],"139":[86,124,126,35],"182":[86,124,28,29,126,34,35,127],"189":[86,124],"208":[86,124,28,29,126,34,35,127],"372":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","390":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","413":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","445":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","474":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","498":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","516":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","543":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","593":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","614":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","661":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","671":"b:AAAAMBwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","692":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","705":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","723":[86,124,28,126,31,34,35,127]},"packages/frontend/editor-ui/src/features/ai/instanceAi/useResponseFeedback.ts":{"12":"b:AAAA8AgAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","14":[86,124,30],"17":"b:AAAA8AgAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","18":[86,124,28,29,126,35,127],"19":[86,124,30],"22":"b:AAAA8AgAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","23":[86,124,28,29,126,35,127],"25":[86,124,30],"48":"b:AAAA8BwAAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","73":"b:AAAA8AwAAAAAAEAQAAAA0AAAAIADAAAAAAAAAAA=","113":[86,124],"157":[86,124],"165":[86,124,161]},"packages/frontend/editor-ui/src/features/ai/instanceAi/useTransitionGate.ts":{"3":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","7":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","9":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","10":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","18":[30,92,31,161,162,36],"23":[30,92,31,161,36]},"packages/frontend/editor-ui/src/features/ai/instanceAi/utils/browserUseSupport.ts":{"6":"b:AAAB8B4AAAAAAEAQAAAA0AAAAIAHAAAAAAAAAAA=","16":[86,124]},"packages/frontend/editor-ui/src/features/ai/instanceAi/utils/buildNodesAttachment.ts":{"29":[86,124],"31":[86,124],"36":[86,124],"41":[86,124],"72":[86,124],"79":[86,124],"80":[86,124],"81":[86,124],"82":[86,124],"86":[86,124],"111":[86,124],"120":[86,124],"121":[86,124],"127":[86,124],"134":[86,124],"136":[86,124],"150":[86,124],"157":[86,124],"158":[86,124],"160":[86,124],"161":[86,124],"171":[86,124],"187":[86,124,28,29,92,126,159,160,34,161,35,127],"189":[86,124,29,160],"190":[86,124]},"packages/frontend/editor-ui/src/features/ai/shared/components/AiThinkingBlock.vue":{"8":[28,29,92,126,31,34,161,35,127],"27":[28,29,92,126,31,34,161,35,127],"29":[28,29,92,126,31,34,161,35,127],"30":[28,29,126,34,161,35,127],"41":[28,29,92,126,31,34,161,35,127],"49":[28,29,92,126,31,34,161,35,127],"52":[28,29,92,126,31,34,161,35,127],"57":[28,126,34,35,127],"73":[161],"77":[28,29,126,34,35,127],"82":[28,29,126,34,161,35,127],"86":[28,29,92,126,31,34,161,35,127],"117":[28,29,92,126,31,34,161,35,127],"124":[28,29,92,126,31,34,161,35,127],"126":[28,29,92,126,31,34,161,35,127],"133":[28,29,92,126,31,34,161,35,127]},"packages/frontend/editor-ui/src/features/ai/shared/components/ChatHistoryDropdown.vue":{"17":"b:BgAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","70":"b:BgAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","85":"b:BgAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","112":"b:AAAA8BwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","119":"b:BgAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","120":[159,160,161,162],"143":[28,29,92,126,159,160,34,161,35,127,162],"148":[161],"155":[161],"172":[31,161],"198":[161],"203":"b:BgAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","221":[161],"226":"b:BgAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","232":[161],"239":[161],"252":[161],"254":[161],"259":[161],"263":[161],"273":[161],"275":[161],"288":[161]},"packages/frontend/editor-ui/src/features/ai/shared/components/ChatHistoryDropdownTrigger.vue":{"10":"b:BgAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","29":"b:BgAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/shared/components/ChatInputBase.vue":{"95":"b:BAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","136":"b:BAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","141":[28,29,92,126,31,159,160,34,161,35,127],"153":[29,160],"154":[29,160],"160":[160],"200":[29,160],"201":[29,160],"204":[29,160],"210":[29,160],"219":[31],"229":[28,29,92,126,159,160,34,161,35,127],"243":"b:BAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","291":[28,29,92,126,31,159,160,34,161,35,127],"294":"b:BAAA8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","295":[2,28,29,92,126,159,160,34,161,35,127],"297":"b:BAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","301":"b:BAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","304":"b:BAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","331":"b:BAAB8B4AAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA="},"packages/frontend/editor-ui/src/features/ai/shared/thinking.utils.ts":{"2":[28,29,126,34,161,35,127]},"packages/frontend/editor-ui/src/features/core/dataTable/components/dataGrid/ColumnHeader.vue":{"27":[24,25],"41":[24,25],"42":[24,25],"44":"b:AAAA8xwAAAAAAAAQAAAAwAAAAIAHAAAAAAAAAAA=","67":[24],"77":[24],"81":[24],"85":[24],"89":[24,25],"99":[24,25],"103":[24,25],"111":[24,25],"116":[24,25],"127":[24,25],"136":[24,25],"138":[24],"144":[24,25],"164":[24,25],"168":[24,25],"186":[24],"196":[24,25],"208":[24,25],"214":[24,25],"268":[24]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/background/CanvasBackgroundStripedPattern.vue":{"14":"b:AAgAEAyAAAAAg0AAGAAA0AADMQAAAAAAQAiAAwA="},"packages/@n8n/ai-utilities/src/json-schema/draft-2020-12.ts":{"30":[110,38,221],"33":[110,38,221],"37":[110,38,221],"58":[110,38,221],"117":[110,38,221]},"packages/@n8n/ai-utilities/src/utils/redact-secrets.ts":{"7":[125,221],"20":[125,221],"28":[125,221],"50":[125,221],"60":[125,221],"74":[125,221],"82":[125,221],"109":[125,221]},"packages/@n8n/db/src/entities/webhook-entity.ts":{"33":"b:ANAgBACAACABAAMAgAmACAAAAAAAEAAAAAAAoAA=","39":"b:ANAgBACAACABAAMAgAmACAAAAAAAEAAAAAAAoAA=","43":"b:ANAgBACAACABAAMAgAmACAAAAAAAEAAAAAAAoAA=","44":"b:ANAgBACAACABAAMAgAmACAAAAAAAEAAAAAAAoAA=","50":"b:ANAgBACAACABAAMAgAmACAAAAAAAEAAAAAAAoAA=","51":"b:ANAgBACAACABAAMAgAmACAAAAAAAEAAAAAAAoAA=","54":"b:ANAgBACAACABAAMAgAmACAAAAAAAEAAAAAAAoAA="},"packages/@n8n/db/src/repositories/workflow-publication-retry-state.repository.ts":{"11":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","15":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","27":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA="},"packages/@n8n/db/src/repositories/workflow-published-version.repository.ts":{"33":"b:APAgBECEviExgANAgImACAAAAAAAEAAAAAAgoAA=","37":"b:APAgBECEviExgANAgImACAAAAAAAEAAAAAAgoAA=","41":"b:APAgBECEviExgANAgImACAAAAAAAEAAAAAAgoAA=","50":"b:APAgBECEviExgANAgImACAAAAAAAEAAAAAAgoAA=","58":"b:APAgBECEviExgANAgImACAAAAAAAEAAAAAAgoAA=","66":"b:APAgBECEviExgANAgImACAAAAAAAEAAAAAAgoAA=","82":"b:APAgBECEviExgANAgImACAAAAAAAEAAAAAAgoAA=","94":"b:APAgBECEviExgANAgImACAAAAAAAEAAAAAAgoAA="},"packages/@n8n/db/src/repositories/workflow-review-request-workflow.repository.ts":{"34":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA=","38":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA=","58":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA=","82":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA=","94":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA=","107":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA=","129":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA=","144":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA=","165":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA=","172":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA=","201":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA="},"packages/@n8n/db/src/services/transaction.ts":{"29":"b:APAcBACEviE3gANAgImACAAAAAAAEAAAAAAgoAA=","32":"b:APAcBACEviE3gANAgImACAAAAAAAEAAAAAAgoAA="},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/CredentialGateTool.ts":{"17":[125,221],"19":[125,221],"20":[125,221],"26":[125,221],"32":[125,221]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/McpServer.ts":{"29":[125,221,205],"46":[125,221,205],"47":[125,221,205],"91":[125,221,205],"103":[125,221,205],"112":[125,221,205],"126":[125,221,205],"136":[125,221,205],"137":[125,221,205],"140":[125,221,205],"155":[125,221,205],"172":[125,221,205],"233":[125,221,205],"240":[125,221,205],"268":[125,221,205],"292":[125,221,205],"296":[125,221,205],"306":[125,221,205],"322":[125,221,205],"326":[125,221,205],"388":[125,221,205],"393":[125,221,205],"398":[125,221,205],"402":[125,221,205],"406":[125,221,205],"410":[125,221,205],"412":[125,221,205],"418":[125,221,205],"425":[125,221,205],"443":[125,221,205],"447":[125,221,205],"450":[125,221,205],"453":[125,221,205],"457":[125,221,205],"461":[125,221,205],"465":[125,221,205],"469":[125,221,205],"476":[125,221,205],"487":[125,221,205],"496":[125,221,205],"512":[125,221,205],"530":[125,221,205],"544":[125,221,205],"557":[125,221,205],"562":[125,221,205],"563":[125,221,205],"603":[125,221,205],"606":[125,221,205],"615":[125,221,205],"634":[125,221,205],"690":[125,221,205],"693":[125,221,205]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/McpTrigger.node.ts":{"34":[125,221],"64":[125,221],"236":[125,221]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/execution/DirectExecutionStrategy.ts":{"6":[125,221]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/execution/ExecutionCoordinator.ts":{"10":[125,221],"14":[125,221],"22":[125,221],"26":[125,221],"30":[125,221]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/execution/PendingCallsManager.ts":{"10":[125,221],"12":[125,221],"15":[125,221],"21":[125,221],"22":[125,221],"38":[125,221],"49":[125,221],"60":[125,221],"64":[125,221],"68":[125,221],"69":[125,221],"72":[125,221],"76":[125,221]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/protocol/MessageFormatter.ts":{"18":[125,221],"52":[125,221],"68":[125,221],"81":[125,221],"82":[125,221],"86":[125,221],"112":[125,221],"113":[125,221],"114":[125,221],"120":[125,221],"126":[125,221]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/protocol/MessageParser.ts":{"11":[125,221],"20":[125,221],"30":[125,221],"40":[125,221],"49":[125,221]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/session/InMemorySessionStore.ts":{"5":[125,221],"11":[125,221],"16":[125,221],"21":[125,221],"26":[125,221],"30":[125,221],"34":[125,221]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/session/SessionManager.ts":{"18":[125,221,205],"20":[125,221,205],"35":[125,221,205],"43":[125,221,205],"45":[125,221,205],"46":[125,221,205],"49":[125,221,205],"53":[125,221,205],"56":[125,221,205],"60":[125,221,205],"64":[125,221,205],"68":[125,221,205],"72":[125,221,205],"76":[125,221,205],"80":[125,221,205],"84":[125,221,205]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/transport/SSETransport.ts":{"10":[221],"17":[221],"22":[221]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/transport/StreamableHttpTransport.ts":{"17":[125,221],"32":[125,221],"37":[125,221],"49":[125,221],"54":[125,221]},"packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/transport/TransportFactory.ts":{"13":[125,221],"17":[125,221],"23":[125,221],"30":[125,221],"35":[125,221]},"packages/@n8n/nodes-langchain/utils/schemaParsing.ts":{"9":[125,221],"10":[125,221],"41":[125,221],"49":[125,221],"53":[125,221],"68":[125,221],"72":[125,221]},"packages/cli/src/activation-errors.service.ts":{"9":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","11":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","15":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","19":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","27":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","35":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA="},"packages/cli/src/errors/response-errors/webhook-not-found.error.ts":{"3":[223,12,14,15,107,221,172,47,61,64,119],"36":[223,12,14,15,107,221,172,47,61,64,119]},"packages/cli/src/modules/workflow-reviews.ee/workflow-review-feature-gate.service.ts":{"17":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA=","22":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA=","26":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA=","33":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA="},"packages/cli/src/modules/workflow-reviews.ee/workflow-review-lifecycle.service.ts":{"51":"b:APAgBAC0viExgANAAImASAAAAAAAEAAAAAAgoAA=","62":"b:APAgBAC0viExgANAAImASAAAAAAAEAAAAAAgoAA=","67":"b:APAgBAC0viExgANAAImASAAAAAAAEAAAAAAgoAA=","73":"b:APAgBAC0viExgANAAImASAAAAAAAEAAAAAAgoAA=","89":"b:APAgBAC0viExgANAAImASAAAAAAAEAAAAAAgoAA=","99":"b:APAgBAC0viExgANAAImASAAAAAAAEAAAAAAgoAA=","130":"b:APAgBAC0viExgANAAImASAAAAAAAEAAAAAAgoAA=","170":"b:APAgBAC0viExgANAAImASAAAAAAAEAAAAAAgoAA=","175":"b:APAgBAC0viExgANAAImASAAAAAAAEAAAAAAgoAA=","202":"b:APAgBAC0viExgANAAImASAAAAAAAEAAAAAAgoAA=","209":"b:APAgBAC0viExgANAAImASAAAAAAAEAAAAAAgoAA=","239":"b:APAgBAC0viExgANAAImASAAAAAAAEAAAAAAgoAA=","245":"b:APAgBAC0viExgANAAImASAAAAAAAEAAAAAAgoAA=","249":"b:APAgBAC0viExgANAAImASAAAAAAAEAAAAAAgoAA=","280":"b:APAgBAC0viExgANAAImASAAAAAAAEAAAAAAgoAA=","285":"b:APAgBAC0viExgANAAImASAAAAAAAEAAAAAAgoAA=","328":"b:APAgBAC0viExgANAAImASAAAAAAAEAAAAAAgoAA="},"packages/cli/src/modules/workflow-reviews.ee/workflow-review-publish-guard.service.ts":{"12":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA=","17":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA="},"packages/cli/src/modules/workflow-reviews.ee/workflow-review-state-notifier.service.ts":{"8":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA=","14":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA=","17":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA=","22":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA="},"packages/cli/src/policy/enforce-workflow-publish.ts":{"20":"b:APAgBACEviE3gANAAImACAAAAAAAEAAAAAAgoAA="},"packages/cli/src/webhooks/live-webhooks.ts":{"44":"b:ANAADACAACABAAAAgAmAAAAAAAAAEAAAAAAAoAA=","56":"b:ANAADACAACABAAAAgAmAAAAAAAAAEAAAAAAAoAA=","60":"b:ANAADACAACABAAAAgAmAAAAAAAAAEAAAAAAAoAA=","68":"b:ANAADACAACABAAAAgAmAAAAAAAAAEAAAAAAAoAA=","73":"b:ANAADACAACABAAAAgAmAAAAAAAAAEAAAAAAAoAA=","88":"b:ANAADACAACABAAAAgAmAAAAAAAAAEAAAAAAAoAA=","109":"b:ANAADACAACABAAAAgAmAAAAAAAAAEAAAAAAAoAA=","137":"b:ANAADACAACABAAAAgAmAAAAAAAAAEAAAAAAAoAA=","160":"b:ANAADACAACABAAAAgAmAAAAAAAAAEAAAAAAAoAA=","184":"b:ANAADACAACABAAAAgAmAAAAAAAAAEAAAAAAAoAA=","197":"b:ANAADACAACABAAAAgAmAAAAAAAAAEAAAAAAAoAA=","223":"b:ANAADACAACABAAAAgAmAAAAAAAAAEAAAAAAAoAA=","243":"b:ANAADACAACABAAAAgAmAAAAAAAAAEAAAAAAAoAA=","255":"b:ANAADACAACABAAAAgAmAAAAAAAAAEAAAAAAAoAA=","269":"b:ANAADACAACABAAAAgAmAAAAAAAAAEAAAAAAAoAA=","285":"b:ANAADACAACABAAAAgAmAAAAAAAAAEAAAAAAAoAA="},"packages/cli/src/webhooks/webhook-request-sanitizer.ts":{"48":"b:ANAABACAACABAAgAgAmACAADAAAAEAAAAAAAoAA=","54":"b:ANAABACAACABAAgAgAmACAADAAAAEAAAAAAAoAA=","60":"b:ANAABACAACABAAgAgAmACAADAAAAEAAAAAAAoAA=","61":"b:ANAABACAACABAAgAgAmACAADAAAAEAAAAAAAoAA=","74":"b:ANAABACAACABAAgAgAmACAADAAAAEAAAAAAAoAA=","82":"b:ANAABACAACABAAgAgAmACAADAAAAEAAAAAAAoAA="},"packages/cli/src/workflows/publication/heal-node-ids.ts":{"54":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA=","64":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA=","92":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA=","95":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA=","105":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA=","116":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA="},"packages/cli/src/workflows/publication/publication-status-reporter.ts":{"43":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","57":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","92":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","109":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","132":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","154":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","159":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","166":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","169":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","185":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","195":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","199":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","209":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","211":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","218":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","236":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","241":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","248":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","262":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","268":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","284":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","289":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","303":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA="},"packages/cli/src/workflows/publication/trigger-diff.ts":{"11":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","48":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg="},"packages/cli/src/workflows/publication/workflow-publication-applier.ts":{"81":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","120":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","148":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","193":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","200":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","231":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","278":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","302":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","309":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","330":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","343":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","348":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","364":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","372":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","379":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","398":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","408":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","409":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","418":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","428":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","444":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","465":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","478":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","492":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","522":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","532":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","565":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","575":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","588":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","593":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","594":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","615":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","621":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","633":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","665":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","670":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","708":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","723":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA="},"packages/cli/src/workflows/publication/workflow-publication-lifecycle-lock.ts":{"35":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","39":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","44":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","53":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","62":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","71":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","72":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","78":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","89":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA="},"packages/cli/src/workflows/publication/workflow-publication-notifier.ts":{"13":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA=","26":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA=","33":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA=","46":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA="},"packages/cli/src/workflows/triggers/enabled-trigger-nodes.ts":{"12":"b:APAgBACEviE3gANAAImACAAAAAAAEAAAAAAgoAA=","28":"b:APAgBACEviE3gANAAImACAAAAAAAEAAAAAAgoAA="},"packages/cli/src/workflows/triggers/non-webhook-trigger-registrar.ts":{"51":"b:APAgBECE/iExgANAgImACAAAAAAAEAAAAAAgoAA=","65":"b:APAgBECE/iExgANAgImACAAAAAAAEAAAAAAgoAA=","66":"b:APAgBECE/iExgANAgImACAAAAAAAEAAAAAAgoAA=","73":"b:APAgBECE/iExgANAgImACAAAAAAAEAAAAAAgoAA=","80":"b:APAgBECE/iExgANAgImACAAAAAAAEAAAAAAgoAA=","123":"b:APAgBECE/iExgANAgImACAAAAAAAEAAAAAAgoAA=","146":"b:APAgBECE/iExgANAgImACAAAAAAAEAAAAAAgoAA=","175":"b:APAgBECE/iExgANAgImACAAAAAAAEAAAAAAgoAA=","189":"b:APAgBECE/iExgANAgImACAAAAAAAEAAAAAAgoAA=","197":"b:APAgBECE/iExgANAgImACAAAAAAAEAAAAAAgoAA=","225":"b:APAgBECE/iExgANAgImACAAAAAAAEAAAAAAgoAA=","231":"b:APAgBECE/iExgANAgImACAAAAAAAEAAAAAAgoAA="},"packages/cli/src/workflows/triggers/trigger-activation-retry.ts":{"10":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","22":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA="},"packages/cli/src/workflows/triggers/trigger-count.service.ts":{"13":"b:APAgBACE/iExgANAgImACAAAAAAAEAAAAAAgoAA=","14":"b:APAgBACE/iExgANAgImACAAAAAAAEAAAAAAgoAA=","17":"b:APAgBACE/iExgANAgImACAAAAAAAEAAAAAAgoAA=","27":"b:APAgBACE/iExgANAgImACAAAAAAAEAAAAAAgoAA="},"packages/cli/src/workflows/triggers/webhook-trigger-registrar.ts":{"20":"b:APAgBACEviE5gANAgImACAAAAAAAEAAAAAAgoQA=","26":"b:APAgBACEviE5gANAgImACAAAAAAAEAAAAAAgoQA=","47":"b:APAgBACEviE5gANAgImACAAAAAAAEAAAAAAgoQA=","67":"b:APAgBACEviE5gANAgImACAAAAAAAEAAAAAAgoQA=","76":"b:APAgBACEviE5gANAgImACAAAAAAAEAAAAAAgoQA=","92":"b:APAgBACEviE5gANAgImACAAAAAAAEAAAAAAgoQA=","104":"b:APAgBACEviE5gANAgImACAAAAAAAEAAAAAAgoQA=","151":"b:APAgBACEviE5gANAgImACAAAAAAAEAAAAAAgoQA=","161":"b:APAgBACEviE5gANAgImACAAAAAAAEAAAAAAgoQA=","178":"b:APAgBACEviE5gANAgImACAAAAAAAEAAAAAAgoQA=","192":"b:APAgBACEviE5gANAgImACAAAAAAAEAAAAAAgoQA=","205":"b:APAgBACEviE5gANAgImACAAAAAAAEAAAAAAgoQA=","212":"b:APAgBACEviE5gANAgImACAAAAAAAEAAAAAAgoQA=","241":"b:APAgBACEviE5gANAgImACAAAAAAAEAAAAAAgoQA=","258":"b:APAgBACEviE5gANAgImACAAAAAAAEAAAAAAgoQA=","262":"b:APAgBACEviE5gANAgImACAAAAAAAEAAAAAAgoQA="},"packages/cli/src/workflows/triggers/workflow-trigger-activator.ts":{"71":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","79":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","80":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","144":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","171":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","185":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","197":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","198":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","220":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","241":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","245":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","268":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","278":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","292":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","321":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","337":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","416":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","446":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","455":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","461":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","471":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","486":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","516":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","523":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","548":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","560":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","581":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","587":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","608":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","619":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","641":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","653":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","677":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","700":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","714":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","715":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","724":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","765":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","814":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","834":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","841":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","851":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","869":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","883":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","889":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","918":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","925":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","934":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","965":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","970":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","973":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","976":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","977":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","981":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","982":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","993":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA=","1030":"b:APAgBECE/iE5gANAgImACAAAAAAAEAAAAAAgoAA="},"packages/cli/src/workflows/workflow-mutation-hooks-proxy.service.ts":{"54":"b:APAgBAC0viExgANAAImASAAAAAAAEAAAAAAgoAA=","57":"b:APAgBAC0viExgANAAImASAAAAAAAEAAAAAAgoAA=","61":"b:APAgBAC0viExgANAAImASAAAAAAAEAAAAAAgoAA=","65":"b:APAgBAC0viExgANAAImASAAAAAAAEAAAAAAgoAA=","69":"b:APAgBAC0viExgANAAImASAAAAAAAEAAAAAAgoAA=","73":"b:APAgBAC0viExgANAAImASAAAAAAAEAAAAAAgoAA=","77":"b:APAgBAC0viExgANAAImASAAAAAAAEAAAAAAgoAA="},"packages/cli/src/workflows/workflow-publish-guard-proxy.service.ts":{"13":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA=","16":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA=","20":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAA="},"packages/cli/src/workflows/workflow-published-data.service.ts":{"22":"b:APAgBACE/iExgANAgImACAAAAAAAEAAAAAAgoAA=","26":"b:APAgBACE/iExgANAgImACAAAAAAAEAAAAAAgoAA=","39":"b:APAgBACE/iExgANAgImACAAAAAAAEAAAAAAgoAA=","50":"b:APAgBACE/iExgANAgImACAAAAAAAEAAAAAAgoAA=","64":"b:APAgBACE/iExgANAgImACAAAAAAAEAAAAAAgoAA=","84":"b:APAgBACE/iExgANAgImACAAAAAAAEAAAAAAgoAA=","93":"b:APAgBACE/iExgANAgImACAAAAAAAEAAAAAAgoAA="},"packages/cli/src/workflows/workflow-push-notifier.service.ts":{"10":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","15":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA="},"packages/core/src/execution-engine/active-workflow-triggers.ts":{"37":"b:APAgBECE/iExgANAAImACAAAAAAAEAAAAAAgoAA=","49":"b:APAgBECE/iExgANAAImACAAAAAAAEAAAAAAgoAA=","68":"b:APAgBECE/iExgANAAImACAAAAAAAEAAAAAAgoAA=","82":"b:APAgBECE/iExgANAAImACAAAAAAAEAAAAAAgoAA=","89":"b:APAgBECE/iExgANAAImACAAAAAAAEAAAAAAgoAA=","94":"b:APAgBECE/iExgANAAImACAAAAAAAEAAAAAAgoAA=","101":"b:APAgBECE/iExgANAAImACAAAAAAAEAAAAAAgoAA=","110":"b:APAgBECE/iExgANAAImACAAAAAAAEAAAAAAgoAA=","126":"b:APAgBECE/iExgANAAImACAAAAAAAEAAAAAAgoAA=","139":"b:APAgBECE/iExgANAAImACAAAAAAAEAAAAAAgoAA=","159":"b:APAgBECE/iExgANAAImACAAAAAAAEAAAAAAgoAA=","172":"b:APAgBECE/iExgANAAImACAAAAAAAEAAAAAAgoAA=","173":"b:APAgBECE/iExgANAAImACAAAAAAAEAAAAAAgoAA=","199":"b:APAgBECE/iExgANAAImACAAAAAAAEAAAAAAgoAA=","300":"b:APAgBECE/iExgANAAImACAAAAAAAEAAAAAAgoAA=","332":"b:APAgBECE/iExgANAAImACAAAAAAAEAAAAAAgoAA=","366":"b:APAgBECE/iExgANAAImACAAAAAAAEAAAAAAgoAA=","393":"b:APAgBECE/iExgANAAImACAAAAAAAEAAAAAAgoAA=","446":"b:APAgBECE/iExgANAAImACAAAAAAAEAAAAAAgoAA=","458":"b:APAgBECE/iExgANAAImACAAAAAAAEAAAAAAgoAA=","513":"b:APAgBECE/iExgANAAImACAAAAAAAEAAAAAAgoAA=","522":"b:APAgBECE/iExgANAAImACAAAAAAAEAAAAAAgoAA=","536":"b:APAgBECE/iExgANAAImACAAAAAAAEAAAAAAgoAA=","559":"b:APAgBECE/iExgANAAImACAAAAAAAEAAAAAAgoAA=","569":"b:APAgBECE/iExgANAAImACAAAAAAAEAAAAAAgoAA=","580":"b:APAgBECE/iExgANAAImACAAAAAAAEAAAAAAgoAA=","597":"b:APAgBECE/iExgANAAImACAAAAAAAEAAAAAAgoAA="},"packages/core/src/execution-engine/scheduled-task-manager.ts":{"34":"b:APAgBACEviExgAtAAImACAAAAAAAEAAAAAAgoAA=","40":"b:APAgBACEviExgAtAAImACAAAAAAAEAAAAAAgoAA=","48":"b:APAgBACEviExgAtAAImACAAAAAAAEAAAAAAgoAA=","57":"b:APAgBACEviExgAtAAImACAAAAAAAEAAAAAAgoAA=","67":"b:APAgBACEviExgAtAAImACAAAAAAAEAAAAAAgoAA=","107":"b:APAgBACEviExgAtAAImACAAAAAAAEAAAAAAgoAA=","110":"b:APAgBACEviExgAtAAImACAAAAAAAEAAAAAAgoAA=","151":"b:APAgBACEviExgAtAAImACAAAAAAAEAAAAAAgoAA=","175":"b:APAgBACEviExgAtAAImACAAAAAAAEAAAAAAgoAA=","180":"b:APAgBACEviExgAtAAImACAAAAAAAEAAAAAAgoAA=","188":"b:APAgBACEviExgAtAAImACAAAAAAAEAAAAAAgoAA=","201":"b:APAgBACEviExgAtAAImACAAAAAAAEAAAAAAgoAA=","228":"b:APAgBACEviExgAtAAImACAAAAAAAEAAAAAAgoAA=","233":"b:APAgBACEviExgAtAAImACAAAAAAAEAAAAAAgoAA=","237":"b:APAgBACEviExgAtAAImACAAAAAAAEAAAAAAgoAA=","243":"b:APAgBACEviExgAtAAImACAAAAAAAEAAAAAAgoAA=","247":"b:APAgBACEviExgAtAAImACAAAAAAAEAAAAAAgoAA=","255":"b:APAgBACEviExgAtAAImACAAAAAAAEAAAAAAgoAA=","270":"b:APAgBACEviExgAtAAImACAAAAAAAEAAAAAAgoAA=","288":"b:APAgBACEviExgAtAAImACAAAAAAAEAAAAAAgoAA="},"packages/core/src/observability/tracing/noop-tracing.ts":{"4":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","11":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","15":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","19":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","23":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","27":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","31":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","35":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","39":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","43":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","47":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","51":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","59":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","62":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA=","66":"b:APAgBACEviExgANAgImACAAAAAAAEAAAAAAgoAA="},"packages/nodes-base/nodes/Webhook/error.ts":{"4":"b:gNCABASBACABAA4AQAkAiAQTAEAAMAAAAAAAIAA="},"packages/nodes-base/nodes/Webhook/utils.ts":{"38":"b:gNCABASBACABAA4AwAmAiAQTAEAAEAAAAAAAoAE=","55":"b:gNCABASBACABAA4AwAmAiAQTAEAAEAAAAAAAoAE=","69":"b:gNCABASBACABAA4AwAmAiAQTAEAAEAAAAAAAoAE=","80":"b:gNCABASBACABAA4AwAmAiAQTAEAAEAAAAAAAoAE=","90":"b:gNCABASBACABAA4AwAmAiAQTAEAAEAAAAAAAoAE=","107":"b:gNCABASBACABAA4AwAmAiAQTAEAAEAAAAAAAoAE=","118":"b:gNCABASBACABAA4AwAmAiAQTAEAAEAAAAAAAoAE=","120":"b:gNCABASBACABAA4AwAmAiAQTAEAAEAAAAAAAoAE=","131":"b:gNCABASBACABAA4AwAmAiAQTAEAAEAAAAAAAoAE=","141":"b:gNCABASBACABAA4AwAmAiAQTAEAAEAAAAAAAoAE=","156":"b:gNCABASBACABAA4AwAmAiAQTAEAAEAAAAAAAoAE=","167":"b:gNCABASBACABAA4AwAmAiAQTAEAAEAAAAAAAoAE=","205":"b:gNCABASBACABAA4AwAmAiAQTAEAAEAAAAAAAoAE=","210":"b:gNCABASBACABAA4AwAmAiAQTAEAAEAAAAAAAoAE=","228":"b:gNCABASBACABAA4AwAmAiAQTAEAAEAAAAAAAoAE=","229":"b:gNCABASBACABAA4AwAmAiAQTAEAAEAAAAAAAoAE=","233":"b:gNCABASBACABAA4AwAmAiAQTAEAAEAAAAAAAoAE=","242":"b:gNCABASBACABAA4AwAmAiAQTAEAAEAAAAAAAoAE=","258":"b:gNCABASBACABAA4AwAmAiAQTAEAAEAAAAAAAoAE=","393":"b:gNCABASBACABAA4AwAmAiAQTAEAAEAAAAAAAoAE=","458":"b:gNCABASBACABAA4AwAmAiAQTAEAAEAAAAAAAoAE=","476":"b:gNCABASBACABAA4AwAmAiAQTAEAAEAAAAAAAoAE="},"packages/workflow/src/auth-redaction.ts":{"8":[125,130,221,173,67],"16":[125,130,221,173,67],"25":[125,130,221,173,67]},"packages/workflow/src/common/get-executable-nodes.ts":{"23":"b:APAgBACEviE3gANAAImACAAAAEAAEAAAAAAAoAA="},"packages/workflow/src/common/get-runnable-nodes.ts":{"14":"b:APAgBACEviE3gANAAImAKAAAAAAAEAAAAAAgoAQ=","40":"b:APAgBACEviE3gANAAImAKAAAAAAAEAAAAAAgoAQ=","79":"b:APAgBACEviE3gANAAImAKAAAAAAAEAAAAAAgoAQ=","87":"b:APAgBACEviE3gANAAImAKAAAAAAAEAAAAAAgoAQ=","92":"b:APAgBACEviE3gANAAImAKAAAAAAAEAAAAAAgoAQ="},"packages/workflow/src/node-validation.ts":{"32":"b:APAgBACEviE3gANAAImACAAAAAAAEAAAAAAgoAA=","59":"b:APAgBACEviE3gANAAImACAAAAAAAEAAAAAAgoAA=","74":"b:APAgBACEviE3gANAAImACAAAAAAAEAAAAAAgoAA=","115":"b:APAgBACEviE3gANAAImACAAAAAAAEAAAAAAgoAA="},"packages/workflow/src/tool-helpers.ts":{"10":[20,125,221]},"packages/workflow/src/workflow-diff.ts":{"28":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","42":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","74":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","79":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","84":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","114":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","118":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","136":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","148":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","161":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","168":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","170":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","186":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","200":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","204":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","217":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","225":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","233":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","247":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","248":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","258":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","259":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","271":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","273":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","274":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","276":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","295":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","324":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","332":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","336":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","342":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","343":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","346":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","397":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","426":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg=","427":"b:APAgBACEviExgANAAImACAAAAAAAEAAAAAAgoAg="},"packages/workflow/src/workflow-validation.ts":{"16":"b:APAgBACEviE3gANAAImACAAAAAAAEAAAAAAgoAA="},"packages/@n8n/backend-network/src/http/parse-incoming-message.ts":{"3":[14,15,154,91,27,130],"5":[14,15,154,91,27,130],"55":[14,15,154,91,27,130],"77":[14,15,154,91,27,130],"108":[14,15,154,91,27,130]},"packages/cli/src/executions/execution.utils.ts":{"13":[83,14,27,130,172,137,225,212,213,119,226],"26":[83,14,27,130,172,137,225,212,213,119,226]},"packages/cli/src/utils/cors.util.ts":{"3":[83,14,27,130,172,137,119,226]},"packages/cli/src/webhooks/waiting-forms.ts":{"17":[14,27,130],"20":[14,27,130],"24":[14,27,130],"30":[14,27,130],"41":[14,27,130],"53":[14,27,130],"73":[14,27,130],"154":[14,27,130]},"packages/cli/src/webhooks/waiting-webhooks.ts":{"47":[83,14,147,27,130,172,137,119,226],"59":[83,14,147,27,130,172,137,119,226],"67":[83,14,147,27,130,172,137,119,226],"71":[83,14,147,27,130,172,137,119,226],"75":[83,14,147,27,130,172,137,119,226],"79":[83,14,147,27,130,172,137,119,226],"89":[83,14,147,27,130,172,137,119,226],"102":[83,14,147,27,130,172,137,119,226],"108":[83,14,147,27,130,172,137,119,226],"127":[83,14,147,27,130,172,137,119,226],"140":[83,14,147,27,130,172,137,119,226],"153":[83,14,147,27,130,172,137,119,226],"164":[83,14,147,27,130,172,137,119,226],"190":[83,14,147,27,130,172,137,119,226],"211":[83,14,147,27,130,172,137,119,226],"236":[83,14,147,27,130,172,137,119,226],"244":[83,14,147,27,130,172,137,119,226],"346":[83,14,147,27,130,172,137,119,226],"359":[83,14,147,27,130,172,137,119,226],"410":[83,14,147,27,130,172,137,119,226],"437":[83,14,147,27,130,172,137,119,226],"440":[83,14,147,27,130,172,137,119,226],"453":[83,14,147,27,130,172,137,119,226]},"packages/cli/src/webhooks/webhook-blank-file-inputs.ts":{"10":[14,15,27,130,172],"23":[14,15,27,130,172],"45":[14,15,27,130,172]},"packages/cli/src/webhooks/webhook-form-data.ts":{"12":[14,15,27,130,172],"18":[14,15,27,130,172],"29":[14,15,27,130,172],"41":[14,15,27,130,172],"42":[14,15,27,130,172],"67":[14,15,27,130,172],"69":[14,15,27,130,172],"71":[14,15,27,130,172]},"packages/cli/src/webhooks/webhook-on-received-response-extractor.ts":{"13":"b:ANAABACAACABAAgAgAGACAQDAAAAEAAAAAAAAAA="},"packages/nodes-base/nodes/Form/Form.node.ts":{"366":"b:gACACAQBAAAAAAQAAAAAAAQRCEBAEAAAAAAAAAA=","454":"b:gACACAQBAAAAAAQAAAAAAAQRCEBAEAAAAAAAAAA=","462":"b:gACACAQBAAAAAAQAAAAAAAQRCEBAEAAAAAAAAAA=","472":"b:gACACAQBAAAAAAQAAAAAAAQRCEBAEAAAAAAAAAA="},"packages/nodes-base/nodes/Form/FormTrigger.node.ts":{"8":[12,147,27,158,130,80]},"packages/nodes-base/nodes/Form/utils/formCompletionUtils.ts":{"27":"b:gACACAQBAAAAAAQAAAAAAAQRCEBAEAAAAAAAAAA=","43":"b:gACACAQBAAAAAAQAAAAAAAQRCEBAEAAAAAAAAAA=","46":"b:gACACAQBAAAAAAQAAAAAAAQRCEBAEAAAAAAAAAA=","52":"b:gACACAQBAAAAAAQAAAAAAAQRCEBAEAAAAAAAAAA=","59":"b:gACACAQBAAAAAAQAAAAAAAQRCEBAEAAAAAAAAAA=","62":"b:gACACAQBAAAAAAQAAAAAAAQRCEBAEAAAAAAAAAA=","83":"b:gACACAQBAAAAAAQAAAAAAAQRCEBAEAAAAAAAAAA="},"packages/nodes-base/nodes/Form/utils/formNodeUtils.ts":{"22":"b:gACACAQBAAAAAAQAAAAAAAQRCEBAEAAAAAAAAAA=","105":"b:gACACAQBAAAAAAQAAAAAAAQRCEBAEAAAAAAAAAA=","108":"b:gACACAQBAAAAAAQAAAAAAAQRCEBAEAAAAAAAAAA="},"packages/nodes-base/nodes/Form/utils/utils.ts":{"54":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","75":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","79":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","94":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","103":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","181":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","182":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","185":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","186":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","198":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","218":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","230":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","241":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","250":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","255":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","344":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","364":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","386":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","392":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","431":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","482":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","511":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","593":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","637":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","698":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","699":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","727":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","743":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","751":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","753":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","765":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","803":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","834":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","847":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","865":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","877":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","892":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","898":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","907":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","919":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","927":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","932":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","947":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","958":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","974":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","989":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","1012":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","1039":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","1064":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","1228":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","1255":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","1316":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","1323":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","1336":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","1340":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","1341":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","1361":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","1376":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","1624":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","1656":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","1659":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA=","1685":"b:gFCACAQBAAAAAAwAQAAAgAQTCEAAEAEAAAAAAAA="},"packages/nodes-base/nodes/Form/v1/FormTriggerV1.node.ts":{"91":[12,147,27,158,130,80],"98":[12,147,27,158,130,80]},"packages/nodes-base/nodes/Form/v2/FormTriggerV2.node.ts":{"166":[12,147,27,158,130,80],"288":[12,147,27,158,130,80],"295":[12,147,27,158,130,80]},"packages/nodes-base/utils/sendAndWait/configureWaitTillDate.util.ts":{"4":"b:gACACAQBAAAAAAQAAAAAAAQRCEBAEAAAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nPulse/Pulse.vue":{"6":[86,147,124,130,173,136]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FixedCollection/FixedCollectionParameter.vue":{"39":[14,147,130,173,206,116,76,77]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterIssues.vue":{"9":"b:AEGQAAAgAAAAZEAIAABQFARICAAAAAQAAAQCAAA=","10":"b:AEGQAAAgAAAAREAIAABQFARICAAAAAQAAAQCAAA=","15":[86,124],"17":"b:AEEQAAAgAAAAZEAAAABQEARICAAAAAQAAAQCAAA="},"packages/@n8n/scheduler/src/core/provisioning/provision.ts":{"36":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","42":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","44":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","45":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","64":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","65":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","69":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","70":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","75":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","81":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","93":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","96":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","103":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","111":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","114":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","116":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","119":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","120":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","121":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","133":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA="},"packages/@n8n/scheduler/src/core/provisioning/provisioner.ts":{"80":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","86":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","89":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","98":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","100":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","114":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA="},"packages/@n8n/scheduler/src/observability/provisioner-tracing.ts":{"23":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","25":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","28":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","43":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","46":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","65":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","67":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","68":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","69":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","82":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/execution-lifecycle/execute-error-workflow.ts":{"23":"b:ANA8BACEviEBAABAgImAAAAAAAAAEAAAAAAwgAI=","42":"b:ANA8BACEviEBAABAgImAAAAAAAAAEAAAAAAwgAI=","121":"b:ANA8BACEviEBAABAgImAAAAAAAAAEAAAAAAwgAI=","129":"b:ANA8BACEviEBAABAgImAAAAAAAAAEAAAAAAwgAI=","145":"b:ANA8BACEviEBAABAgImAAAAAAAAAEAAAAAAwgAI=","150":"b:ANA8BACEviEBAABAgImAAAAAAAAAEAAAAAAwgAI=","158":"b:ANA8BACEviEBAABAgImAAAAAAAAAEAAAAAAwgAI="},"packages/cli/src/scheduling/durable-job-provisioner.ts":{"130":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","143":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","144":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","155":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","160":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","180":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","191":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","199":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","207":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","219":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","228":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","239":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","247":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","254":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","255":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","288":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","290":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","297":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","299":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","311":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","318":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","320":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","323":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","328":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","330":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","332":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","335":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","351":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","390":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","391":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","393":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","395":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","400":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/scheduling/poll-trigger-node/poll-trigger-job-registrar.ts":{"32":"b:ADAgBEAEPgAIgAMAAAAAAAAAAAAAAAAAAAAAAAA=","50":"b:ADAgBEAEPgAIgAMAAAAAAAAAAAAAAAAAAAAAAAA=","93":"b:ADAgBEAEPgAIgAMAAAAAAAAAAAAAAAAAAAAAAAA=","103":"b:ADAgBEAEPgAIgAMAAAAAAAAAAAAAAAAAAAAAAAA=","117":"b:ADAgBEAEPgAIgAMAAAAAAAAAAAAAAAAAAAAAAAA=","126":"b:ADAgBEAEPgAIgAMAAAAAAAAAAAAAAAAAAAAAAAA=","137":"b:ADAgBEAEPgAIgAMAAAAAAAAAAAAAAAAAAAAAAAA=","151":"b:ADAgBEAEPgAIgAMAAAAAAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/scheduling/schedule-trigger-node/schedule-trigger-job-registrar.ts":{"114":"b:ADAgBEAE/gE4gANAAICAAAAAAAAAEAAAAAAgAAA=","144":"b:ADAgBEAE/gE4gANAAICAAAAAAAAAEAAAAAAgAAA=","162":"b:ADAgBEAE/gE4gANAAICAAAAAAAAAEAAAAAAgAAA=","171":"b:ADAgBEAE/gE4gANAAICAAAAAAAAAEAAAAAAgAAA=","182":"b:ADAgBEAE/gE4gANAAICAAAAAAAAAEAAAAAAgAAA=","234":"b:ADAgBEAE/gE4gANAAICAAAAAAAAAEAAAAAAgAAA=","249":"b:ADAgBEAE/gE4gANAAICAAAAAAAAAEAAAAAAgAAA=","276":"b:ADAgBEAE/gE4gANAAICAAAAAAAAAEAAAAAAgAAA=","323":"b:ADAgBEAE/gE4gANAAICAAAAAAAAAEAAAAAAgAAA=","364":"b:ADAgBEAE/gE4gANAAICAAAAAAAAAEAAAAAAgAAA=","379":"b:ADAgBEAE/gE4gANAAICAAAAAAAAAEAAAAAAgAAA=","398":"b:ADAgBEAE/gE4gANAAICAAAAAAAAAEAAAAAAgAAA=","407":"b:ADAgBEAE/gE4gANAAICAAAAAAAAAEAAAAAAgAAA=","409":"b:ADAgBEAE/gE4gANAAICAAAAAAAAAEAAAAAAgAAA=","426":"b:ADAgBEAE/gE4gANAAICAAAAAAAAAEAAAAAAgAAA=","430":"b:ADAgBEAE/gE4gANAAICAAAAAAAAAEAAAAAAgAAA=","443":"b:ADAgBEAE/gE4gANAAICAAAAAAAAAEAAAAAAgAAA=","454":"b:ADAgBEAE/gE4gANAAICAAAAAAAAAEAAAAAAgAAA="},"packages/cli/src/scheduling/workflow-scheduled-job-owner.ts":{"16":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","19":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","24":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA=","28":"b:ADAgBEAE/gE4gAMAAAAAAAAAAAAAAAAAAAAAAAA="},"packages/cli/src/workflows/triggers/engine-v2-active-triggers.ts":{"37":[111,42,49,50,51,94,52],"43":[111,42,49,50,51,94,52],"60":[111,42,49,50,51,94,52]},"packages/cli/src/workflows/triggers/trigger-execution-context.factory.ts":{"54":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","91":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","118":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","123":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","128":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","138":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","154":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","166":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","175":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","178":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","193":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","209":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","210":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","223":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","242":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","261":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","278":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","281":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","285":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","319":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","333":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","342":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","352":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","370":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","380":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","397":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","445":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","450":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","456":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","476":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","510":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","534":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","567":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","580":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","614":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA=","631":"b:ACAgAEAE/gEwgAFAAICBAAAAAAAAEAAAAAAgAAA="},"packages/cli/src/workflows/workflow-publisher.service.ts":{"20":"b:ANAABACEviEBAABAwImAAAAAAAAAEAAAAAAAgAQ=","54":"b:ANAABACEviEBAABAwImAAAAAAAAAEAAAAAAAgAQ=","69":"b:ANAABACEviEBAABAwImAAAAAAAAAEAAAAAAAgAQ="},"packages/core/src/execution-engine/workflow-active-triggers-state.ts":{"14":"b:ACAAAEAE/gEwgAFAAIDBAAAAAAAAEAAAAAAgAAA=","20":"b:ACAAAEAE/gEwgAFAAIDBAAAAAAAAEAAAAAAgAAA=","25":"b:ACAAAEAE/gEwgAFAAIDBAAAAAAAAEAAAAAAgAAA=","30":"b:ACAAAEAE/gEwgAFAAIDBAAAAAAAAEAAAAAAgAAA=","35":"b:ACAAAEAE/gEwgAFAAIDBAAAAAAAAEAAAAAAgAAA=","43":"b:ACAAAEAE/gEwgAFAAIDBAAAAAAAAEAAAAAAgAAA=","48":"b:ACAAAEAE/gEwgAFAAIDBAAAAAAAAEAAAAAAgAAA=","52":"b:ACAAAEAE/gEwgAFAAIDBAAAAAAAAEAAAAAAgAAA=","63":"b:ACAAAEAE/gEwgAFAAIDBAAAAAAAAEAAAAAAgAAA=","68":"b:ACAAAEAE/gEwgAFAAIDBAAAAAAAAEAAAAAAgAAA=","73":"b:ACAAAEAE/gEwgAFAAIDBAAAAAAAAEAAAAAAgAAA=","78":"b:ACAAAEAE/gEwgAFAAIDBAAAAAAAAEAAAAAAgAAA=","83":"b:ACAAAEAE/gEwgAFAAIDBAAAAAAAAEAAAAAAgAAA=","88":"b:ACAAAEAE/gEwgAFAAIDBAAAAAAAAEAAAAAAgAAA=","97":"b:ACAAAEAE/gEwgAFAAIDBAAAAAAAAEAAAAAAgAAA="},"packages/nodes-base/nodes/N8nTrigger/N8nTrigger.node.ts":{"63":[42],"86":[42]},"packages/@n8n/agents/src/sdk/untrusted-content.ts":{"9":[28,126],"13":[28,126],"30":[28,126]},"packages/@n8n/instance-ai/src/utils/agent-tree.ts":{"4":[28,29,30,31],"12":[28,29,30,31]},"packages/cli/src/modules/instance-ai/instance-ai-execution-wait.ts":{"17":[28,126],"29":[28,126],"30":[28,126],"39":[28,126],"40":[28,126]},"packages/cli/src/modules/instance-ai/message-parser.ts":{"47":[28,29,30,92,31],"53":[28,29,30,92,31],"59":[28,29,30,92,31],"61":[28,29,30,92,31],"68":[28,29,30,92,31],"70":[28,29,30,92,31],"82":[28,29,30,92,31],"98":[28,29,30,92,31],"102":[28,29,30,92,31],"106":[28,29,30,92,31],"110":[28,29,30,92,31],"121":[28,29,30,92,31],"147":[28,29,30,92,31],"155":[28,29,30,92,31],"168":[28,29,30,92,31],"176":[28,29,30,92,31],"189":[28,29,30,92,31],"348":[28,29,30,92,31],"358":[28,29,30,92,31],"388":[28,29,30,92,31],"397":[28,29,30,92,31],"403":[28,29,30,92,31],"420":[28,29,30,92,31],"426":[28,29,30,92,31],"438":[28,29,30,92,31]},"packages/cli/src/modules/instance-ai/trigger-run-data.ts":{"10":[28,126],"14":[28,126]},"localhost-35525/assets/index-BoK1c_f3.js":{"3":[28,127]},"localhost-35525/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[28,127],"9":[28,127],"10":[28,127],"19":[28,127],"23":[28,127],"29":[28,127],"33":[28,127],"34":[28,127]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/TimelineActivityIndicator.vue":{"7":[28,92,126,127],"29":[28,92,126,127],"30":[28,92,126,127],"41":[28,126,127],"49":[28,92,126,127],"54":[28,92,126,127]},"packages/@n8n/ai-utilities/src/node-catalog/discriminator-utils.ts":{"44":[34,127,110,38],"55":[34,127,110,38],"70":[34,127,110,38],"81":[34,127,110,38],"117":[34,127,110,38],"128":[34,127,110,38],"139":[34,127,110,38],"151":[34,127,110,38],"161":[34,127,110,38],"178":[34,127,110,38]},"packages/@n8n/ai-utilities/src/node-catalog/dynamic-node-parameters.ts":{"47":[34,127,110,38],"51":[34,127,110,38],"55":[34,127,110,38],"59":[34,127,110,38],"63":[34,127,110,38],"73":[34,127,110,38],"107":[34,127,110,38],"114":[34,127,110,38],"119":[34,127,110,38],"151":[34,127,110,38],"183":[34,127,110,38],"187":[34,127,110,38],"188":[34,127,110,38],"195":[34,127,110,38],"199":[34,127,110,38],"214":[34,127,110,38],"226":[34,127,110,38],"230":[34,127,110,38],"237":[34,127,110,38],"241":[34,127,110,38],"251":[34,127,110,38],"260":[34,127,110,38],"274":[34,127,110,38]},"packages/@n8n/ai-utilities/src/node-catalog/get.ts":{"17":[34,127,110,38],"45":[34,127,110,38],"53":[34,127,110,38],"66":[34,127,110,38],"68":[34,127,110,38],"82":[34,127,110,38],"106":[34,127,110,38],"119":[34,127,110,38],"129":[34,127,110,38],"166":[34,127,110,38],"202":[34,127,110,38],"214":[34,127,110,38],"251":[34,127,110,38],"272":[34,127,110,38],"282":[34,127,110,38],"285":[34,127,110,38],"286":[34,127,110,38],"335":[34,127,110,38],"336":[34,127,110,38],"353":[34,127,110,38],"363":[34,127,110,38],"365":[34,127,110,38],"370":[34,127,110,38],"413":[34,127,110,38],"521":[34,127,110,38],"535":[34,127,110,38],"563":[34,127,110,38],"633":[34,127,110,38]},"packages/@n8n/ai-utilities/src/node-catalog/lean-node-type.ts":{"62":[34,127,110,38],"66":[34,127,110,38],"88":[34,127,110,38]},"packages/@n8n/ai-utilities/src/node-catalog/node-type-parser.ts":{"39":[34,127,110,38],"48":[34,127,110,38],"64":[34,127,110,38],"80":[34,127,110,38],"87":[34,127,110,38],"109":[34,127,110,38],"118":[34,127,110,38],"126":[34,127,110,38],"145":[34,127,110,38]},"packages/@n8n/ai-utilities/src/node-catalog/resource-operation-extractor.ts":{"56":[34,127,110,38],"82":[34,127,110,38],"87":[34,127,110,38],"98":[34,127,110,38],"122":[34,127,110,38],"127":[34,127,110,38],"152":[34,127,110,38],"171":[34,127,110,38],"198":[34,127,110,38],"216":[34,127,110,38],"250":[34,127,110,38],"288":[34,127,110,38],"295":[34,127,110,38],"305":[34,127,110,38]},"packages/@n8n/ai-utilities/src/node-catalog/search-engine.ts":{"69":[34,127,110,38],"80":[34,127,110,38],"103":[34,127,110,38],"107":[34,127,110,38],"112":[34,127,110,38],"115":[34,127,110,38],"122":[34,127,110,38],"140":[34,127,110,38],"142":[34,127,110,38],"169":[34,127,110,38],"189":[34,127,110,38],"194":[34,127,110,38],"202":[34,127,110,38],"217":[34,127,110,38],"232":[34,127,110,38],"238":[34,127,110,38],"265":[34,127,110,38],"286":[34,127,110,38],"292":[34,127,110,38],"299":[34,127,110,38],"303":[34,127,110,38],"311":[34,127,110,38],"315":[34,127,110,38],"332":[34,127,110,38],"342":[34,127,110,38],"346":[34,127,110,38],"355":[34,127,110,38],"368":[34,127,110,38],"379":[34,127,110,38],"383":[34,127,110,38],"390":[34,127,110,38],"392":[34,127,110,38],"398":[34,127,110,38],"402":[34,127,110,38],"404":[34,127,110,38],"418":[34,127,110,38],"476":[34,127,110,38],"489":[34,127,110,38],"503":[34,127,110,38],"530":[34,127,110,38],"531":[34,127,110,38],"540":[34,127,110,38],"566":[34,127,110,38],"574":[34,127,110,38]},"packages/@n8n/ai-utilities/src/node-catalog/search.ts":{"48":[34,127,110,38],"62":[34,127,110,38],"71":[34,127,110,38],"77":[34,127,110,38],"84":[34,127,110,38],"91":[34,127,110,38],"105":[34,127,110,38],"181":[34,127,110,38],"227":[34,127,110,38],"241":[34,127,110,38],"242":[34,127,110,38],"247":[34,127,110,38],"248":[34,127,110,38],"262":[34,127,110,38],"263":[34,127,110,38],"281":[34,127,110,38],"317":[34,127,110,38],"336":[34,127,110,38],"338":[34,127,110,38],"355":[34,127,110,38],"379":[34,127,110,38],"431":[34,127,110,38],"446":[34,127,110,38],"533":[34,127,110,38],"539":[34,127,110,38],"545":[34,127,110,38],"547":[34,127,110,38],"548":[34,127,110,38]},"packages/@n8n/utils/src/sleep.ts":{"3":[86,106,124,127,61,136,137],"4":[86,106,124,127,61,136,137],"10":[86,106,124,127,61,136,137],"15":[86,106,124,127,61,136,137],"28":[86,106,124,127,61,136,137],"30":[86,106,124,127,61,136,137]},"packages/@n8n/workflow-sdk/src/mock-data/ai-root-shapes.ts":{"38":[34,127],"51":[34,127],"70":[34,127],"76":[34,127],"93":[34,127]},"packages/cli/src/services/ai-workflow-builder.service.ts":{"47":[146,11,34,127,37,110,38,58],"65":[146,11,34,127,37,110,38,58],"73":[146,11,34,127,37,110,38,58],"80":[146,11,34,127,37,110,38,58],"88":[146,11,34,127,37,110,38,58],"104":[146,11,34,127,37,110,38,58],"110":[146,11,34,127,37,110,38,58],"124":[146,11,34,127,37,110,38,58],"129":[146,11,34,127,37,110,38,58],"130":[146,11,34,127,37,110,38,58],"191":[146,11,34,127,37,110,38,58],"208":[146,11,34,127,37,110,38,58],"213":[146,11,34,127,37,110,38,58],"219":[146,11,34,127,37,110,38,58],"224":[146,11,34,127,37,110,38,58],"229":[146,11,34,127,37,110,38,58]},"packages/nodes-base/nodes/Wait/Wait.node.ts":{"229":[83,14,102,127,176,136,137,119,226,80],"501":[83,14,102,127,176,136,137,119,226,80],"507":[83,14,102,127,176,136,137,119,226,80],"522":[83,14,102,127,176,136,137,119,226,80],"598":[83,14,102,127,176,136,137,119,226,80],"630":[83,14,102,127,176,136,137,119,226,80]},"packages/nodes-base/nodes/Wait/validation.ts":{"1":[83,14,102,127,176,136,137,119,226,80],"6":[83,14,102,127,176,136,137,119,226,80]},"packages/nodes-base/nodes/Webhook/Webhook.node.ts":{"213":"b:ANAABACAACABAAsAwAmAiAADCAAAEAAAAAAAgAA=","225":"b:ANAABACAACABAAsAwAmAiAADCAAAEAAAAAAAgAA=","367":"b:ANAABACAACABAAsAwAmAiAADCAAAEAAAAAAAgAA=","371":"b:ANAABACAACABAAsAwAmAiAADCAAAEAAAAAAAgAA="},"packages/nodes-base/nodes/Webhook/description.ts":{"58":"b:ANAABACAACABAAsAQAmAiAADAAAAEAAAAAAAgAA=","95":"b:ANAABACAACABAAsAQAmAiAADAAAAEAAAAAAAgAA=","138":"b:ANAABACAACABAAsAQAmAiAADAAAAEAAAAAAAgAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/wait.svg":{"11":[14,148,149,127,176,136,137]},"packages/@n8n/ai-workflow-builder.ee/src/code-builder/index.ts":{"14":[110,38],"21":[110,38],"22":[110,38],"23":[110,38],"25":[110,38]},"packages/@n8n/ai-workflow-builder.ee/src/index.ts":{"7":[146,11,110,38],"44":[146,11,110,38]},"packages/@n8n/api-types/src/agents/agent-json-config.schema.ts":{"125":[1,2,83,86,124,110,38],"242":[1,2,83,86,124,110,38],"443":[1,2,83,86,124,110,38],"481":[1,2,83,86,124,110,38],"482":[1,2,83,86,124,110,38],"497":[1,2,83,86,124,110,38],"514":[86,124],"515":[1,2,83,86,124,110,38],"524":[1,2,83,86,124,110,38],"533":[86,124],"534":[1,2,83,86,124,110,38],"562":[1,2,83,86,124,110,38],"574":[1,2,83,86,124,110,38],"637":[1,2,83,110,38],"656":[1,2,83,110,38],"663":[1,2,83,110,38],"664":[1,2,83,110,38],"677":[1,2,83,110,38],"678":[1,2,83,110,38],"681":[1,2,83,110,38],"682":[1,2,83,110,38],"690":[1,2,83,110,38],"692":[1,2,83,110,38]},"packages/@n8n/api-types/src/schemas/json-value.schema.ts":{"12":[86,124,110,38]},"packages/@n8n/errors/src/response-errors/auth.error.ts":{"4":[90,110,63,67]},"packages/cli/src/eventbus/event-message-classes/event-message-mcp.ts":{"44":[27,163,110,38,67],"52":[27,163,110,38,67]},"packages/cli/src/middlewares/content-security-policy.ts":{"26":[110,38],"34":[110,38],"38":[110,38],"39":[110,38],"42":[110,38],"44":[110,38],"47":[110,38],"49":[110,38],"62":[110,38],"75":[110,38],"108":[110,38],"112":[110,38],"116":[110,38],"131":[110,38]},"packages/cli/src/modules/data-table/data-table-proxy.service.ts":{"46":[110,38],"52":[110,38],"62":[110,38],"70":[110,38],"76":[110,38],"81":[110,38],"92":[110,38],"120":[110,38],"127":[110,38],"130":[110,38],"132":[110,38],"136":[110,38],"141":[110,38],"148":[110,38],"154":[110,38],"164":[110,38],"170":[110,38],"176":[110,38],"188":[110,38],"195":[110,38],"205":[110,38],"216":[110,38],"230":[110,38],"248":[110,38],"256":[110,38],"259":[110,38],"263":[110,38],"271":[110,38],"275":[110,38],"281":[110,38],"289":[110,38],"293":[110,38],"298":[110,38],"302":[110,38],"306":[110,38],"310":[110,38],"315":[110,38],"319":[110,38],"326":[110,38],"336":[110,38],"346":[110,38],"356":[110,38]},"packages/cli/src/modules/mcp/dto/update-mcp-settings.dto.ts":{"12":[27,163,110,38,67],"17":[27,163,110,38,67],"21":[27,163,110,38,67],"25":[27,163,110,38,67]},"packages/cli/src/modules/mcp/mcp-scopes.ts":{"192":[110,38],"201":[110,38]},"packages/cli/src/modules/mcp/mcp-server-middleware.service.ts":{"32":[110,38],"44":[110,38],"72":[110,38],"73":[110,38],"93":[110,38],"94":[110,38],"137":[110,38],"150":[110,38],"163":[110,38]},"packages/cli/src/modules/mcp/mcp.controller.ts":{"32":[110,38],"33":[110,38],"39":[110,38],"48":[110,38],"82":[110,38],"103":[110,38],"123":[110,38],"213":[110,38],"220":[110,38],"223":[110,38],"238":[110,38],"241":[110,38],"252":[110,38]},"packages/cli/src/modules/mcp/mcp.service.ts":{"170":[110,38],"184":[110,38],"219":[110,38],"233":[110,38],"277":[110,38],"294":[110,38],"308":[110,38],"356":[110,38],"362":[110,38],"367":[110,38],"419":[110,38],"420":[110,38],"438":[110,38],"445":[110,38],"495":[110,38],"690":[110,38],"833":[110,38],"861":[110,38],"889":[110,38],"907":[110,38],"973":[110,38],"1088":[110,38],"1110":[110,38],"1118":[110,38],"1133":[110,38],"1147":[110,38],"1158":[110,38],"1181":[110,38],"1196":[110,38]},"packages/cli/src/modules/mcp/mcp.settings.controller.ts":{"21":[27,163,110,38,67],"33":[27,163,110,38,67],"64":[27,163,110,38,67],"70":[27,163,110,38,67],"76":[27,163,110,38,67],"83":[27,163,110,38,67],"94":[27,163,110,38,67],"114":[27,163,110,38,67],"129":[27,163,110,38,67]},"packages/cli/src/modules/mcp/mcp.settings.service.ts":{"54":[27,163,110,38,67],"64":[27,163,110,38,67],"80":[27,163,110,38,67],"89":[27,163,110,38,67],"105":[27,163,110,38,67],"114":[27,163,110,38,67],"134":[27,163,110,38,67],"143":[27,163,110,38,67],"201":[27,163,110,38,67],"230":[27,163,110,38,67],"240":[27,163,110,38,67],"266":[27,163,110,38,67],"290":[27,163,110,38,67],"295":[27,163,110,38,67],"311":[27,163,110,38,67],"314":[27,163,110,38,67],"334":[27,163,110,38,67],"354":[27,163,110,38,67]},"packages/cli/src/modules/mcp/mcp.typeguards.ts":{"22":[110,38],"45":[110,38],"56":[110,38],"74":[110,38]},"packages/cli/src/modules/mcp/mcp.utils.ts":{"19":[110,38],"28":[110,38],"37":[110,38],"57":[110,38],"68":[110,38],"85":[110,38],"103":[110,38],"106":[110,38],"113":[110,38],"120":[110,38],"125":[110,38]},"packages/cli/src/modules/mcp/tool-schema.util.ts":{"12":[110,38],"31":[110,38],"36":[110,38],"43":[110,38],"44":[110,38]},"packages/cli/src/modules/mcp/tools/agents/agent-slack-setup.ts":{"32":[110,38],"43":[110,38],"65":[110,38],"66":[110,38],"69":[110,38],"83":[110,38],"114":[110,38],"134":[110,38],"148":[110,38],"161":[110,38]},"packages/cli/src/modules/mcp/tools/agents/agent-tools.service.ts":{"99":[110,38],"107":[110,38],"113":[110,38],"131":[110,38],"142":[110,38],"208":[110,38],"218":[110,38],"415":[110,38],"426":[110,38],"436":[110,38],"470":[110,38],"477":[110,38],"506":[110,38],"518":[110,38],"533":[110,38],"534":[110,38],"548":[110,38],"561":[110,38],"576":[110,38],"581":[110,38],"593":[110,38],"608":[110,38],"609":[110,38],"666":[110,38],"681":[110,38],"686":[110,38],"732":[110,38],"750":[110,38],"751":[110,38],"776":[110,38],"791":[110,38],"799":[110,38],"809":[110,38],"824":[110,38],"829":[110,38],"863":[110,38],"878":[110,38],"883":[110,38],"913":[110,38],"928":[110,38],"929":[110,38],"943":[110,38],"957":[110,38],"958":[110,38],"978":[110,38],"992":[110,38],"993":[110,38],"1003":[110,38],"1018":[110,38],"1023":[110,38],"1035":[110,38],"1050":[110,38],"1055":[110,38],"1060":[110,38],"1075":[110,38],"1085":[110,38],"1090":[110,38],"1105":[110,38],"1106":[110,38],"1115":[110,38],"1129":[110,38],"1154":[110,38],"1157":[110,38],"1158":[110,38],"1171":[110,38],"1182":[110,38],"1200":[110,38],"1208":[110,38],"1215":[110,38],"1219":[110,38],"1225":[110,38],"1229":[110,38],"1242":[110,38],"1341":[110,38],"1374":[110,38],"1495":[110,38],"1538":[110,38],"1543":[110,38],"1560":[110,38],"1573":[110,38],"1583":[110,38],"1589":[110,38],"1600":[110,38],"1610":[110,38],"1630":[110,38],"1646":[110,38],"1653":[110,38],"1656":[110,38],"1668":[110,38],"1680":[110,38],"1696":[110,38],"1705":[110,38],"1729":[110,38],"1738":[110,38],"1774":[110,38],"1787":[110,38],"1796":[110,38],"1821":[110,38],"1847":[110,38],"1864":[110,38],"1928":[110,38],"1964":[110,38],"1968":[110,38],"1972":[110,38],"1988":[110,38],"1999":[110,38],"2005":[110,38]},"packages/cli/src/modules/mcp/tools/create-folder.tool.ts":{"29":[110,38],"49":[110,38]},"packages/cli/src/modules/mcp/tools/data-table/add-data-table-column.tool.ts":{"30":[110,38],"48":[110,38],"82":[110,38]},"packages/cli/src/modules/mcp/tools/data-table/add-data-table-rows.tool.ts":{"31":[110,38],"50":[110,38],"84":[110,38]},"packages/cli/src/modules/mcp/tools/data-table/create-data-table.tool.ts":{"36":[110,38],"55":[110,38],"73":[110,38]},"packages/cli/src/modules/mcp/tools/data-table/delete-data-table-column.tool.ts":{"20":[110,38],"39":[110,38],"67":[110,38]},"packages/cli/src/modules/mcp/tools/data-table/get-data-table-rows.tool.ts":{"48":[110,38],"82":[110,38],"87":[110,38],"89":[110,38],"95":[110,38],"114":[110,38],"152":[110,38]},"packages/cli/src/modules/mcp/tools/data-table/index.ts":{"1":[110,38],"2":[110,38],"3":[110,38],"5":[110,38],"6":[110,38]},"packages/cli/src/modules/mcp/tools/data-table/rename-data-table-column.tool.ts":{"29":[110,38],"47":[110,38],"83":[110,38]},"packages/cli/src/modules/mcp/tools/data-table/rename-data-table.tool.ts":{"20":[110,38],"38":[110,38],"66":[110,38]},"packages/cli/src/modules/mcp/tools/data-table/search-data-tables.tool.ts":{"29":[110,38],"48":[110,38],"74":[110,38],"80":[110,38],"100":[110,38]},"packages/cli/src/modules/mcp/tools/execute-workflow.tool.ts":{"82":[110,38],"105":[110,38],"184":[110,38],"223":[110,38],"266":[110,38],"335":[110,38],"341":[110,38],"357":[110,38],"387":[110,38],"394":[110,38],"407":[110,38],"426":[110,38],"439":[110,38],"440":[110,38],"446":[110,38],"455":[110,38],"474":[110,38],"554":[110,38],"563":[110,38],"590":[110,38]},"packages/cli/src/modules/mcp/tools/get-execution.tool.ts":{"66":[110,38],"87":[110,38],"215":[110,38],"248":[110,38],"252":[110,38]},"packages/cli/src/modules/mcp/tools/get-workflow-details.tool.ts":{"50":[110,38],"51":[110,38],"53":[110,38],"55":[110,38],"67":[110,38],"85":[110,38],"113":[110,38],"164":[110,38],"201":[110,38]},"packages/cli/src/modules/mcp/tools/get-workflow-history.tool.ts":{"61":[110,38],"81":[110,38],"136":[110,38],"147":[110,38]},"packages/cli/src/modules/mcp/tools/get-workflow-version.tool.ts":{"76":[110,38],"96":[110,38],"158":[110,38]},"packages/cli/src/modules/mcp/tools/get-workflow-versions-diff.tool.ts":{"125":[110,38],"134":[110,38],"144":[110,38],"145":[110,38],"149":[110,38],"152":[110,38],"153":[110,38],"164":[110,38],"193":[110,38],"213":[110,38],"273":[110,38],"294":[110,38],"319":[110,38]},"packages/cli/src/modules/mcp/tools/list-credentials.tool.ts":{"69":[110,38],"121":[110,38],"145":[110,38],"186":[110,38],"195":[110,38],"226":[110,38]},"packages/cli/src/modules/mcp/tools/list-n8n-gateway-services.tool.ts":{"53":[110,38],"72":[110,38]},"packages/cli/src/modules/mcp/tools/list-tags.tool.ts":{"61":[110,38],"79":[110,38],"109":[110,38],"116":[110,38]},"packages/cli/src/modules/mcp/tools/move-workflows-to-folder.tool.ts":{"63":[110,38],"84":[110,38],"108":[110,38]},"packages/cli/src/modules/mcp/tools/prepare-workflow-pin-data.tool.ts":{"57":[110,38],"79":[110,38],"137":[110,38],"147":[110,38],"150":[110,38],"223":[110,38]},"packages/cli/src/modules/mcp/tools/publish-workflow.tool.ts":{"53":[110,38],"61":[110,38],"82":[110,38],"100":[110,38]},"packages/cli/src/modules/mcp/tools/schemas.ts":{"37":[110,38],"40":[110,38],"54":[110,38],"66":[110,38],"71":[110,38],"72":[110,38],"75":[110,38],"79":[110,38],"104":[110,38],"169":[110,38],"173":[110,38],"174":[110,38],"177":[110,38]},"packages/cli/src/modules/mcp/tools/search-executions.tool.ts":{"71":[110,38],"91":[110,38],"140":[110,38]},"packages/cli/src/modules/mcp/tools/search-folders.tool.ts":{"46":[110,38],"66":[110,38],"104":[110,38],"123":[110,38]},"packages/cli/src/modules/mcp/tools/search-projects.tool.ts":{"63":[110,38],"83":[110,38],"115":[110,38],"116":[110,38],"120":[110,38],"128":[110,38],"136":[110,38],"143":[110,38],"175":[110,38]},"packages/cli/src/modules/mcp/tools/search-workflows.tool.ts":{"50":[110,38],"111":[110,38],"132":[110,38],"225":[110,38],"247":[110,38],"262":[110,38],"296":[110,38]},"packages/cli/src/modules/mcp/tools/test-workflow.tool.ts":{"71":[110,38],"94":[110,38],"170":[110,38],"195":[110,38],"215":[110,38],"216":[110,38]},"packages/cli/src/modules/mcp/tools/unpublish-workflow.tool.ts":{"32":[110,38],"53":[110,38],"69":[110,38]},"packages/cli/src/modules/mcp/tools/update-folder.tool.ts":{"32":[110,38],"52":[110,38]},"packages/cli/src/modules/mcp/tools/workflow-builder/create-workflow-from-code.tool.ts":{"72":[110,38],"230":[110,38],"319":[110,38],"348":[110,38],"417":[110,38],"447":[110,38],"522":[110,38],"561":[110,38]},"packages/cli/src/modules/mcp/tools/workflow-builder/delete-workflow.tool.ts":{"27":[110,38],"47":[110,38],"65":[110,38]},"packages/cli/src/modules/mcp/tools/workflow-builder/explore-node-resources.tool.ts":{"99":[110,38],"121":[110,38],"142":[110,38]},"packages/cli/src/modules/mcp/tools/workflow-builder/get-workflow-best-practices.tool.ts":{"53":[110,38],"54":[110,38],"60":[110,38],"67":[110,38],"85":[110,38],"110":[110,38],"128":[110,38]},"packages/cli/src/modules/mcp/tools/workflow-builder/get-workflow-node-types.tool.ts":{"63":[110,38],"85":[110,38]},"packages/cli/src/modules/mcp/tools/workflow-builder/get-workflow-sdk-reference.tool.ts":{"41":[110,38],"59":[110,38]},"packages/cli/src/modules/mcp/tools/workflow-builder/install-community-node.tool.ts":{"58":[110],"87":[110],"112":[110],"125":[110],"220":[110]},"packages/cli/src/modules/mcp/tools/workflow-builder/mcp-instructions.ts":{"61":[110,38]},"packages/cli/src/modules/mcp/tools/workflow-builder/restore-workflow-version.tool.ts":{"49":[110,38],"71":[110,38],"111":[110,38]},"packages/cli/src/modules/mcp/tools/workflow-builder/search-workflow-nodes.tool.ts":{"76":[110,38],"102":[110,38]},"packages/cli/src/modules/mcp/tools/workflow-builder/update-workflow.tool.ts":{"80":[110,38],"127":[110,38],"249":[110,38],"255":[110,38],"383":[110,38],"447":[110,38],"454":[110,38],"455":[110,38],"488":[110,38],"509":[110,38],"527":[110,38],"537":[110,38],"557":[110,38],"599":[110,38],"622":[110,38],"636":[110,38],"643":[110,38],"645":[110,38],"684":[110,38],"711":[110,38],"714":[110,38],"734":[110,38],"740":[110,38],"759":[110,38],"783":[110,38],"818":[110,38],"866":[110,38],"890":[110,38],"905":[110,38],"932":[110,38],"959":[110,38],"970":[110,38],"997":[110,38],"1012":[110,38],"1026":[110,38],"1030":[110,38],"1031":[110,38],"1039":[110,38],"1052":[110,38],"1103":[110,38],"1140":[110,38],"1142":[110,38],"1209":[110,38],"1284":[110,38],"1344":[110,38],"1383":[110,38],"1394":[110,38]},"packages/cli/src/modules/mcp/tools/workflow-builder/validate-node.tool.ts":{"80":[110,38],"98":[110,38],"108":[110,38],"125":[110,38],"126":[110,38],"127":[110,38]},"packages/cli/src/modules/mcp/tools/workflow-builder/validate-workflow-code.tool.ts":{"55":[110,38],"74":[110,38],"95":[110,38],"112":[110,38],"121":[110,38]},"packages/cli/src/modules/oauth-server/database/repositories/oauth-access-token.repository.ts":{"15":[27,158,110,67],"19":[27,158,110,67]},"packages/cli/src/modules/oauth-server/database/repositories/oauth-refresh-token.repository.ts":{"18":[27,158,110,67],"22":[27,158,110,67],"31":[27,158,110,67],"45":[27,158,110,67]},"packages/cli/src/modules/oauth-server/oauth-authorization-code.service.ts":{"17":[27,158,110,67],"23":[27,158,110,67],"55":[27,158,110,67],"83":[27,158,110,67],"111":[27,158,110,67],"138":[27,158,110,67],"151":[27,158,110,67],"157":[27,158,110,67]},"packages/cli/src/modules/oauth-server/oauth-consent.controller.ts":{"14":[27,158,110,67],"21":[27,158,110,67],"81":[27,158,110,67],"122":[27,158,110,67],"129":[27,158,110,67],"136":[27,158,110,67]},"packages/cli/src/modules/oauth-server/oauth-consent.service.ts":{"58":[27,158,110,67],"72":[27,158,110,67],"170":[27,158,110,67],"178":[27,158,110,67],"180":[27,158,110,67],"188":[27,158,110,67],"198":[27,158,110,67],"206":[27,158,110,67],"263":[27,158,110,67],"279":[27,158,110,67],"328":[27,158,110,67],"349":[27,158,110,67],"361":[27,158,110,67],"390":[27,158,110,67],"400":[27,158,110,67]},"packages/cli/src/modules/oauth-server/oauth-server.service.ts":{"71":[27,158,125,163,110,67],"120":[27,158,125,163,110,67],"126":[27,158,125,163,110,67],"127":[27,158,125,163,110,67],"143":[27,158,125,163,110,67],"159":[27,158,125,163,110,67],"161":[27,158,125,163,110,67],"195":[27,158,125,163,110,67],"219":[27,158,125,163,110,67],"224":[27,158,125,163,110,67],"242":[27,158,125,163,110,67],"262":[27,158,125,163,110,67],"314":[27,158,125,163,110,67],"316":[27,158,125,163,110,67],"317":[27,158,125,163,110,67],"320":[27,158,125,163,110,67],"376":[27,158,125,163,110,67],"392":[27,158,125,163,110,67],"409":[27,158,125,163,110,67],"413":[27,158,125,163,110,67],"461":[27,158,125,163,110,67],"503":[27,158,125,163,110,67],"513":[27,158,125,163,110,67],"600":[27,158,125,163,110,67],"614":[27,158,125,163,110,67],"618":[27,158,125,163,110,67],"648":[27,158,125,163,110,67],"655":[27,158,125,163,110,67],"667":[27,158,125,163,110,67],"682":[27,158,125,163,110,67],"687":[27,158,125,163,110,67],"722":[27,158,125,163,110,67],"748":[27,158,125,163,110,67],"749":[27,158,125,163,110,67],"767":[27,158,125,163,110,67],"805":[27,158,125,163,110,67],"817":[27,158,125,163,110,67],"871":[27,158,125,163,110,67],"886":[27,158,125,163,110,67]},"packages/cli/src/modules/oauth-server/oauth-session.service.ts":{"29":[27,158,110,67],"34":[27,158,110,67],"54":[27,158,110,67],"62":[27,158,110,67],"69":[27,158,110,67]},"packages/cli/src/modules/oauth-server/oauth-token.service.ts":{"48":[27,158,110,67],"61":[27,158,110,67],"70":[27,158,110,67],"109":[27,158,110,67],"117":[27,158,110,67],"138":[27,158,110,67],"143":[27,158,110,67],"228":[27,158,110,67],"235":[27,158,110,67],"278":[27,158,110,67],"291":[27,158,110,67],"370":[27,158,110,67],"377":[27,158,110,67],"392":[27,158,110,67],"416":[27,158,110,67],"428":[27,158,110,67],"446":[27,158,110,67],"458":[27,158,110,67],"472":[27,158,110,67],"492":[27,158,110,67],"509":[27,158,110,67]},"packages/cli/src/modules/oauth-server/oauth.controller.ts":{"46":[27,158,125,110,67],"73":[27,158,125,110,67],"75":[27,158,125,110,67],"97":[27,158,125,110,67],"138":[27,158,125,110,67],"148":[27,158,125,110,67],"155":[27,158,125,110,67],"172":[27,158,125,110,67],"183":[27,158,125,110,67],"193":[27,158,125,110,67],"208":[27,158,125,110,67],"218":[27,158,125,110,67],"233":[27,158,125,110,67],"263":[27,158,125,110,67],"291":[27,158,125,110,67],"303":[27,158,125,110,67]},"packages/cli/src/modules/oauth-server/oauth.errors.ts":{"8":[110,67],"20":[110,67],"28":[110,67],"35":[110,67]},"packages/cli/src/modules/oauth-server/oauth.helpers.ts":{"13":[27,158,110,67],"34":[27,158,110,67],"58":[27,158,110,67]},"packages/cli/src/modules/oauth-server/protected-resource-resolvers/chat-trigger-resource.base.ts":{"40":[27,220,110,67],"60":[27,220,110,67],"66":[27,220,110,67],"105":[27,220,110,67],"106":[27,220,110,67],"107":[27,220,110,67]},"packages/cli/src/modules/oauth-server/protected-resource-resolvers/chat-trigger-resource.resolver.ts":{"14":[27,220,110,67],"27":[27,220,110,67],"31":[27,220,110,67],"40":[27,220,110,67],"54":[27,220,110,67]},"packages/cli/src/modules/oauth-server/protected-resource-resolvers/chat-trigger-test-resource.resolver.ts":{"13":[27,220,110,67],"25":[27,220,110,67],"29":[27,220,110,67],"39":[27,220,110,67],"50":[27,220,110,67]},"packages/cli/src/modules/oauth-server/protected-resource-resolvers/form-trigger-resource.resolver.ts":{"23":[27,158,110,67],"35":[27,158,110,67],"45":[27,158,110,67],"67":[27,158,110,67],"87":[27,158,110,67],"88":[27,158,110,67],"89":[27,158,110,67]},"packages/cli/src/modules/oauth-server/protected-resource-resolvers/form-trigger-test-resource.resolver.ts":{"22":[27,158,220,110,67],"33":[27,158,220,110,67],"43":[27,158,220,110,67],"65":[27,158,220,110,67],"89":[27,158,220,110,67],"90":[27,158,220,110,67],"91":[27,158,220,110,67]},"packages/cli/src/modules/oauth-server/protected-resource-resolvers/utils.ts":{"41":[27,158,220,110,67],"54":[27,158,220,110,67],"61":[27,158,220,110,67],"84":[27,158,220,110,67],"109":[27,158,220,110,67],"127":[27,158,220,110,67],"138":[27,158,220,110,67],"143":[27,158,220,110,67],"157":[27,158,220,110,67]},"packages/cli/src/modules/oauth-server/protected-resource-resolvers/workflow-mcp-test-trigger-resource.resolver.ts":{"20":[27,158,110,67],"31":[27,158,110,67],"41":[27,158,110,67],"66":[27,158,110,67],"86":[27,158,110,67],"87":[27,158,110,67]},"packages/cli/src/modules/oauth-server/protected-resource-resolvers/workflow-mcp-trigger-resource.resolver.ts":{"21":[27,158,125,110,67],"33":[27,158,125,110,67],"43":[27,158,125,110,67],"86":[27,158,125,110,67],"106":[27,158,125,110,67],"107":[27,158,125,110,67]},"packages/cli/src/modules/oauth-server/protected-resource-resolvers/workflow-webhook-test-trigger-resource.resolver.ts":{"42":[27,110,67],"53":[27,110,67],"64":[27,110,67],"89":[27,110,67],"105":[27,110,67],"109":[27,110,67],"120":[27,110,67],"126":[27,110,67],"141":[27,110,67],"142":[27,110,67],"150":[27,110,67],"151":[27,110,67]},"packages/cli/src/modules/oauth-server/protected-resource-resolvers/workflow-webhook-trigger-resource.resolver.ts":{"58":[27,220,110,67],"70":[27,220,110,67],"81":[27,220,110,67],"100":[27,220,110,67],"113":[27,220,110,67],"124":[27,220,110,67],"141":[27,220,110,67],"156":[27,220,110,67],"157":[27,220,110,67],"171":[27,220,110,67],"175":[27,220,110,67]},"packages/cli/src/services/oauth-token-verifier-proxy.service.ts":{"95":[27,158,110,67],"98":[27,158,110,67],"102":[27,158,110,67]},"packages/@n8n/api-types/src/dto/api-keys/create-api-key-request.dto.ts":{"5":[87,143,220,175,47,117,195,132,133,65,68]},"packages/@n8n/api-types/src/dto/api-keys/update-api-key-request.dto.ts":{"7":[87,143,220,175,47,117,195,132,133,65,68]},"packages/@n8n/api-types/src/dto/workflow-reviews/workflow-review-activity.dto.ts":{"33":[86,124,68]},"packages/@n8n/api-types/src/schemas/scopes.schema.ts":{"14":"b:AAAAAACAAAASAMAAAAAgEDCAAAAAgAAACAAAEAA="},"packages/@n8n/db/src/repositories/workflow-review-activity-comment.repository.ts":{"10":[68],"14":[68]},"packages/@n8n/db/src/repositories/workflow-review-activity.repository.ts":{"46":[68],"50":[68],"65":[68],"87":[68],"99":[68],"114":[68]},"packages/@n8n/db/src/repositories/workflow-review-inbox.repository.ts":{"54":[68],"69":[68],"81":[68],"99":[68],"150":[68],"181":[68],"185":[68],"207":[68],"220":[68],"221":[68]},"packages/@n8n/db/src/repositories/workflow-review-request-author.repository.ts":{"10":[68],"14":[68],"30":[68],"42":[68],"55":[68],"67":[68],"77":[68]},"packages/@n8n/db/src/repositories/workflow-review-request-reviewer.repository.ts":{"10":[68],"15":[68],"27":[68],"37":[68],"50":[68],"62":[68],"72":[68]},"packages/@n8n/db/src/repositories/workflow-review-request.repository.ts":{"31":[13,21,126,44,45,68,79,81],"35":[13,21,126,44,45,68,79,81],"65":[13,21,126,44,45,68,79,81],"73":[13,21,126,44,45,68,79,81],"85":[13,21,126,44,45,68,79,81],"89":[13,21,126,44,45,68,79,81],"138":[13,21,126,44,45,68,79,81],"153":[13,21,126,44,45,68,79,81]},"packages/@n8n/permissions/src/public-api-permissions.ee.ts":{"251":"b:AAAAAACAAAASAIAEAAAgADCAAAAAgAAADAAAEAA=","258":"b:AAAAAACAAAASAIAEAAAgADCAAAAAgAAADAAAEAA=","265":"b:AAAAAACAAAASAIAEAAAgADCAAAAAgAAADAAAEAA=","268":"b:AAAAAACAAAASAIAEAAAgADCAAAAAgAAADAAAEAA="},"packages/@n8n/permissions/src/types.ee.ts":{"75":[87,90,143,220,175,47,117,195,132,133,65,68],"129":[87,90,143,220,175,47,117,195,132,133,65,68]},"packages/@n8n/scheduler/src/core/index.ts":{"18":"b:ACAAAEAA/gEwgAEAAAABAAAAAAAAAAAAAAAAAAA=","86":"b:ACAAAEAA/gEwgAEAAAABAAAAAAAAAAAAAAAAAAA=","120":"b:ACAAAEAA/gEwgAEAAAABAAAAAAAAAAAAAAAAAAA=","122":"b:ACAAAEAA/gEwgAEAAAABAAAAAAAAAAAAAAAAAAA="},"packages/@n8n/scheduler/src/core/materializer/coalesce-group.ts":{"15":[13,49,50,51,52,53,54,55,56,68,69,79,80],"17":[13,49,50,51,52,53,54,55,56,68,69,79,80],"19":[13,49,50,51,52,53,54,55,56,68,69,79,80],"26":[13,49,50,51,52,53,54,55,56,68,69,79,80],"36":[13,49,50,51,52,53,54,55,56,68,69,79,80],"40":[13,49,50,51,52,53,54,55,56,68,69,79,80],"46":[13,49,50,51,52,53,54,55,56,68,69,79,80],"54":[13,49,50,51,52,53,54,55,56,68,69,79,80],"68":[13,49,50,51,52,53,54,55,56,68,69,79,80]},"packages/@n8n/scheduler/src/core/materializer/misfire.ts":{"29":[13,49,50,51,52,53,54,55,56,68,69,79,80],"37":[13,49,50,51,52,53,54,55,56,68,69,79,80],"64":[13,49,50,51,52,53,54,55,56,68,69,79,80],"66":[13,49,50,51,52,53,54,55,56,68,69,79,80],"67":[13,49,50,51,52,53,54,55,56,68,69,79,80]},"packages/@n8n/scheduler/src/core/materializer/owner-key.ts":{"23":[13,49,50,51,52,53,54,55,56,68,69,79,80],"27":[13,49,50,51,52,53,54,55,56,68,69,79,80],"31":[13,49,50,51,52,53,54,55,56,68,69,79,80],"37":[13,49,50,51,52,53,54,55,56,68,69,79,80]},"packages/@n8n/scheduler/src/core/materializer/plan.ts":{"51":[13,49,50,51,52,53,54,55,56,68,69,79,80]},"packages/@n8n/scheduler/src/core/provisioning/index.ts":{"1":[13,38,49,50,51,52,53,54,55,56,68,69,79,80]},"packages/@n8n/scheduler/src/core/provisioning/run-options.ts":{"77":[13,38,49,50,51,52,53,54,55,56,68,69,79,80],"98":[13,38,49,50,51,52,53,54,55,56,68,69,79,80],"103":[13,38,49,50,51,52,53,54,55,56,68,69,79,80],"104":[13,38,49,50,51,52,53,54,55,56,68,69,79,80],"105":[13,38,49,50,51,52,53,54,55,56,68,69,79,80],"107":[13,38,49,50,51,52,53,54,55,56,68,69,79,80],"110":[13,38,49,50,51,52,53,54,55,56,68,69,79,80],"119":[13,38,49,50,51,52,53,54,55,56,68,69,79,80],"123":[13,38,49,50,51,52,53,54,55,56,68,69,79,80],"170":[13,38,49,50,51,52,53,54,55,56,68,69,79,80],"190":[13,38,49,50,51,52,53,54,55,56,68,69,79,80]},"packages/@n8n/scheduler/src/core/provisioning/schedule-identity.ts":{"14":[13,38,49,50,51,52,53,54,55,56,68,69,79,80],"49":[13,38,49,50,51,52,53,54,55,56,68,69,79,80],"68":[13,38,49,50,51,52,53,54,55,56,68,69,79,80]},"packages/@n8n/scheduler/src/core/reconciliation/owner.ts":{"32":"b:ACAAAEAC/gEwgAEAAAAAAAAAAAAAAAAAAAAAAAA=","44":"b:ACAAAEAC/gEwgAEAAAAAAAAAAAAAAAAAAAAAAAA=","61":"b:ACAAAEAC/gEwgAEAAAAAAAAAAAAAAAAAAAAAAAA=","66":"b:ACAAAEAC/gEwgAEAAAAAAAAAAAAAAAAAAAAAAAA=","71":"b:ACAAAEAC/gEwgAEAAAAAAAAAAAAAAAAAAAAAAAA="},"packages/@n8n/scheduler/src/core/recurrence/field.ts":{"14":[13,49,50,51,52,53,54,55,56,68,69,79,80]},"packages/@n8n/scheduler/src/core/recurrence/kinds/cron.ts":{"25":[13,49,50,51,52,53,68,69,79,80],"62":[13,49,50,51,52,53,68,69,79,80],"82":[13,49,50,51,52,53,68,69,79,80],"103":[13,49,50,51,52,53,68,69,79,80],"112":[13,49,50,51,52,53,68,69,79,80],"127":[13,49,50,51,52,53,68,69,79,80]},"packages/@n8n/scheduler/src/core/recurrence/next-run.ts":{"33":[13,49,50,51,52,53,54,55,56,68,69,79,80],"68":[13,49,50,51,52,53,54,55,56,68,69,79,80],"92":[13,49,50,51,52,53,54,55,56,68,69,79,80]},"packages/@n8n/scheduler/src/core/recurrence/resolve.ts":{"24":[13,49,50,51,52,53,54,55,56,68,69,79,80],"50":[13,49,50,51,52,53,54,55,56,68,69,79,80]},"packages/cli/src/controllers/api-keys.controller.ts":{"26":[87,143,220,175,47,117,195,132,133,65,68],"36":[87,143,220,175,47,117,195,132,133,65,68],"43":[87,143,220,175,47,117,195,132,133,65,68],"68":[87,143,220,175,47,117,195,132,133,65,68],"82":[87,143,220,175,47,117,195,132,133,65,68],"97":[87,143,220,175,47,117,195,132,133,65,68],"115":[87,143,220,175,47,117,195,132,133,65,68],"131":[87,143,220,175,47,117,195,132,133,65,68]},"packages/cli/src/controllers/invitation.controller.ts":{"21":[87,143,220,175,47,194,195,132,133,68],"38":[87,143,220,175,47,194,195,132,133,68],"49":[87,143,220,175,47,194,195,132,133,68],"74":[87,143,220,175,47,194,195,132,133,68],"118":[87,143,220,175,47,194,195,132,133,68]},"packages/cli/src/controllers/security-settings.controller.ts":{"14":[47,68],"24":[47,68],"40":[47,68],"82":[47,68],"86":[47,68],"91":[47,68]},"packages/cli/src/modules/workflow-reviews.ee/workflow-review-activity.service.ts":{"29":[68],"41":[68],"64":[68],"84":[68],"123":[68],"127":[68],"129":[68],"133":[68],"138":[68],"141":[68],"147":[68],"150":[68],"158":[68]},"packages/cli/src/modules/workflow-reviews.ee/workflow-review-authorization.service.ts":{"50":[68],"68":[68],"76":[68],"80":[68],"95":[68],"122":[68],"145":[68],"175":[68],"199":[68],"209":[68],"216":[68],"217":[68],"220":[68],"239":[68],"244":[68],"253":[68],"269":[68]},"packages/cli/src/modules/workflow-reviews.ee/workflow-review-decision-policy.ts":{"32":[68]},"packages/cli/src/modules/workflow-reviews.ee/workflow-review-inbox.service.ts":{"40":[68],"49":[68],"72":[68],"78":[68],"90":[68],"97":[68],"110":[68],"138":[68],"173":[68],"185":[68],"201":[68],"205":[68],"222":[68],"240":[68]},"packages/cli/src/modules/workflow-reviews.ee/workflow-review-participant.resolver.ts":{"31":[68],"42":[68],"43":[68],"53":[68],"54":[68],"55":[68],"65":[68],"66":[68],"69":[68],"80":[68],"87":[68]},"packages/cli/src/modules/workflow-reviews.ee/workflow-review-request-decision.service.ts":{"42":[68],"61":[68],"89":[68],"95":[68],"141":[68],"173":[68],"216":[68],"281":[68],"317":[68],"347":[68],"358":[68]},"packages/cli/src/modules/workflow-reviews.ee/workflow-review-request-mutation-guard.service.ts":{"19":[68],"27":[68],"33":[68]},"packages/cli/src/modules/workflow-reviews.ee/workflow-review-request-status.service.ts":{"24":[68],"32":[68],"53":[68],"62":[68],"72":[68],"86":[68],"91":[68],"103":[68],"106":[68]},"packages/cli/src/modules/workflow-reviews.ee/workflow-review-request-submission.service.ts":{"39":[68],"46":[68],"65":[68],"78":[68],"79":[68],"82":[68],"110":[68],"129":[68],"144":[68],"190":[68],"193":[68],"202":[68],"285":[68],"304":[68],"337":[68],"362":[68],"378":[68]},"packages/cli/src/modules/workflow-reviews.ee/workflow-review-requests.controller.ts":{"28":[68],"38":[68],"49":[68],"59":[68],"71":[68],"86":[68],"102":[68],"112":[68],"121":[68],"136":[68],"157":[68]},"packages/cli/src/modules/workflow-reviews.ee/workflow-review.mapper.ts":{"26":[68],"40":[68],"58":[68],"79":[68],"99":[68]},"packages/cli/src/public-api/media-types/content-type.ts":{"8":[87,90,143,220,175,47,195,132,133,65,68],"31":[87,90,143,220,175,47,195,132,133,65,68],"32":[87,90,143,220,175,47,195,132,133,65,68],"40":[87,90,143,220,175,47,195,132,133,65,68]},"packages/cli/src/public-api/media-types/request-body/json.request-body.ts":{"15":[87,90,143,220,175,47,195,132,133,65,68],"19":[87,90,143,220,175,47,195,132,133,65,68]},"packages/cli/src/public-api/public-api-controller.registry.ts":{"42":[87,90,143,220,175,47,195,132,133,65,68],"53":[87,90,143,220,175,47,195,132,133,65,68],"60":[87,90,143,220,175,47,195,132,133,65,68],"67":[87,90,143,220,175,47,195,132,133,65,68],"75":[87,90,143,220,175,47,195,132,133,65,68],"83":[87,90,143,220,175,47,195,132,133,65,68],"100":[87,90,143,220,175,47,195,132,133,65,68],"189":[87,90,143,220,175,47,195,132,133,65,68],"208":[87,90,143,220,175,47,195,132,133,65,68],"209":[87,90,143,220,175,47,195,132,133,65,68],"221":[87,90,143,220,175,47,195,132,133,65,68],"235":[87,90,143,220,175,47,195,132,133,65,68],"236":[87,90,143,220,175,47,195,132,133,65,68],"248":[87,90,143,220,175,47,195,132,133,65,68],"249":[87,90,143,220,175,47,195,132,133,65,68],"259":[87,90,143,220,175,47,195,132,133,65,68],"260":[87,90,143,220,175,47,195,132,133,65,68],"270":[87,90,143,220,175,47,195,132,133,65,68],"275":[87,90,143,220,175,47,195,132,133,65,68],"311":[87,90,143,220,175,47,195,132,133,65,68],"312":[87,90,143,220,175,47,195,132,133,65,68],"326":[87,90,143,220,175,47,195,132,133,65,68],"327":[87,90,143,220,175,47,195,132,133,65,68]},"packages/cli/src/public-api/public-api-route-resolver.ts":{"56":[87,90,143,220,175,47,195,132,133,65,68],"57":[87,90,143,220,175,47,195,132,133,65,68],"60":[87,90,143,220,175,47,195,132,133,65,68],"61":[87,90,143,220,175,47,195,132,133,65,68],"64":[87,90,143,220,175,47,195,132,133,65,68],"66":[87,90,143,220,175,47,195,132,133,65,68],"106":[87,90,143,220,175,47,195,132,133,65,68],"172":[87,90,143,220,175,47,195,132,133,65,68],"177":[87,90,143,220,175,47,195,132,133,65,68],"197":[87,90,143,220,175,47,195,132,133,65,68],"208":[87,90,143,220,175,47,195,132,133,65,68],"211":[87,90,143,220,175,47,195,132,133,65,68],"215":[87,90,143,220,175,47,195,132,133,65,68],"226":[87,90,143,220,175,47,195,132,133,65,68],"229":[87,90,143,220,175,47,195,132,133,65,68],"241":[87,90,143,220,175,47,195,132,133,65,68],"256":[87,90,143,220,175,47,195,132,133,65,68],"265":[87,90,143,220,175,47,195,132,133,65,68]},"packages/cli/src/public-api/v1/controllers/users.public.controller.ts":{"48":[87,90,143,220,175,47,195,132,133,68],"60":[87,90,143,220,175,47,195,132,133,68],"74":[87,90,143,220,175,47,195,132,133,68],"100":[87,90,143,220,175,47,195,132,133,68],"113":[87,90,143,220,175,47,195,132,133,68],"140":[87,90,143,220,175,47,195,132,133,68],"155":[87,90,143,220,175,47,195,132,133,68],"172":[87,90,143,220,175,47,195,132,133,68]},"packages/cli/src/scheduling/desired-job-name.ts":{"11":[13,38,49,50,51,52,53,54,55,56,68,69,79,80],"17":[13,38,49,50,51,52,53,54,55,56,68,69,79,80]},"packages/cli/src/scheduling/schedule-columns.ts":{"23":[13,38,49,50,51,52,53,54,55,56,68,69,79,80],"64":[13,38,49,50,51,52,53,54,55,56,68,69,79,80]},"packages/cli/src/services/api-key-auth.strategy.ts":{"20":[87,143,220,38,175,47,195,132,133,65,68],"26":[87,143,220,38,175,47,195,132,133,65,68],"66":[87,143,220,38,175,47,195,132,133,65,68],"73":[87,143,220,38,175,47,195,132,133,65,68],"80":[87,143,220,38,175,47,195,132,133,65,68],"85":[87,143,220,38,175,47,195,132,133,65,68]},"packages/cli/src/services/auth-strategy.registry.ts":{"24":[87,90,143,220,38,175,47,195,132,133,65,68],"27":[87,90,143,220,38,175,47,195,132,133,65,68],"31":[87,90,143,220,38,175,47,195,132,133,65,68],"49":[87,90,143,220,38,175,47,195,132,133,65,68]},"packages/cli/src/services/public-api-key.service.ts":{"37":"b:AAAAAACAAAASAIAAAAAgADCAAAAAgAAADAAAEAA=","44":"b:AAAAAACAAAASAIAAAAAgADCAAAAAgAAADAAAEAA=","62":"b:AAAAAACAAAASAIAAAAAgADCAAAAAgAAADAAAEAA=","78":"b:AAAAAACAAAASAIAAAAAgADCAAAAAgAAADAAAEAA=","126":"b:AAAAAACAAAASAIAAAAAgADCAAAAAgAAADAAAEAA=","137":"b:AAAAAACAAAASAIAAAAAgADCAAAAAgAAADAAAEAA=","162":"b:AAAAAACAAAASAIAAAAAgADCAAAAAgAAADAAAEAA=","173":"b:AAAAAACAAAASAIAAAAAgADCAAAAAgAAADAAAEAA=","201":"b:AAAAAACAAAASAIAAAAAgADCAAAAAgAAADAAAEAA=","229":"b:AAAAAACAAAASAIAAAAAgADCAAAAAgAAADAAAEAA=","247":"b:AAAAAACAAAASAIAAAAAgADCAAAAAgAAADAAAEAA=","259":"b:AAAAAACAAAASAIAAAAAgADCAAAAAgAAADAAAEAA=","261":"b:AAAAAACAAAASAIAAAAAgADCAAAAAgAAADAAAEAA=","267":"b:AAAAAACAAAASAIAAAAAgADCAAAAAgAAADAAAEAA=","272":"b:AAAAAACAAAASAIAAAAAgADCAAAAAgAAADAAAEAA=","283":"b:AAAAAACAAAASAIAAAAAgADCAAAAAgAAADAAAEAA=","305":"b:AAAAAACAAAASAIAAAAAgADCAAAAAgAAADAAAEAA=","329":"b:AAAAAACAAAASAIAAAAAgADCAAAAAgAAADAAAEAA=","338":"b:AAAAAACAAAASAIAAAAAgADCAAAAAgAAADAAAEAA=","348":"b:AAAAAACAAAASAIAAAAAgADCAAAAAgAAADAAAEAA=","353":"b:AAAAAACAAAASAIAAAAAgADCAAAAAgAAADAAAEAA=","355":"b:AAAAAACAAAASAIAAAAAgADCAAAAAgAAADAAAEAA=","358":"b:AAAAAACAAAASAIAAAAAgADCAAAAAgAAADAAAEAA=","368":"b:AAAAAACAAAASAIAAAAAgADCAAAAAgAAADAAAEAA=","377":"b:AAAAAACAAAASAIAAAAAgADCAAAAAgAAADAAAEAA=","378":"b:AAAAAACAAAASAIAAAAAgADCAAAAAgAAADAAAEAA=","383":"b:AAAAAACAAAASAIAAAAAgADCAAAAAgAAADAAAEAA=","385":"b:AAAAAACAAAASAIAAAAAgADCAAAAAgAAADAAAEAA="},"packages/cli/src/services/security-settings.service.ts":{"53":[47,68],"68":[47,68],"98":[47,68],"148":[47,68],"156":[47,68],"176":[47,68],"183":[47,68],"186":[47,68],"195":[47,68],"199":[47,68],"203":[47,68],"208":[47,68]},"packages/cli/src/services/workflow-review-policy.service.ts":{"12":[68],"14":[68],"30":[68]},"packages/cli/src/user-management/email/user-management-mailer.ts":{"33":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","37":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","72":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","89":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","100":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","111":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","121":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","131":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","159":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","188":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","212":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","234":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","243":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","269":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","290":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","300":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","317":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","331":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","345":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","349":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","354":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","370":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","374":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","379":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","395":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","399":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","404":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","413":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","418":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","419":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","432":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","437":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","442":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA=","458":"b:AAAgAACgAAAQAIAACAQAADGAAAAAgAAAHAAAEAA="},"packages/@n8n/scheduler/src/core/reconciliation/reconcile.ts":{"85":[8,16,36,39,41,45,70,71,72,78,81],"125":[8,16,36,39,41,45,70,71,72,78,81],"164":[8,16,36,39,41,45,70,71,72,78,81],"168":[8,16,36,39,41,45,70,71,72,78,81],"223":[8,16,36,39,41,45,70,71,72,78,81],"257":[8,16,36,39,41,45,70,71,72,78,81],"316":[8,16,36,39,41,45,70,71,72,78,81],"321":[8,16,36,39,41,45,70,71,72,78,81],"325":[8,16,36,39,41,45,70,71,72,78,81],"326":[8,16,36,39,41,45,70,71,72,78,81],"330":[8,16,36,39,41,45,70,71,72,78,81],"334":[8,16,36,39,41,45,70,71,72,78,81],"347":[8,16,36,39,41,45,70,71,72,78,81],"365":[8,16,36,39,41,45,70,71,72,78,81],"370":[8,16,36,39,41,45,70,71,72,78,81],"383":[8,16,36,39,41,45,70,71,72,78,81],"410":[8,16,36,39,41,45,70,71,72,78,81],"448":[8,16,36,39,41,45,70,71,72,78,81],"461":[8,16,36,39,41,45,70,71,72,78,81],"470":[8,16,36,39,41,45,70,71,72,78,81],"476":[8,16,36,39,41,45,70,71,72,78,81],"484":[8,16,36,39,41,45,70,71,72,78,81]},"packages/cli/src/modules/external-secrets.ee/external-secrets-manager.ee.ts":{"34":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","55":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","58":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","75":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","85":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","89":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","97":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","101":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","105":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","112":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","118":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","131":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","158":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","182":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","186":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","190":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","194":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","202":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","213":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","225":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","276":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","285":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","294":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","329":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","343":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","361":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","369":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","373":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","392":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA="},"packages/cli/src/modules/external-secrets.ee/external-secrets-refresh.task.ts":{"19":"b:AAAAAAAAAACAgAAABgBAAABAAAAE4AAIAFYEAAA=","26":"b:AAAAAAAAAACAgAAABgBAAABAAAAE4AAIAFYEAAA="},"packages/cli/src/modules/external-secrets.ee/secrets-cache.service.ts":{"25":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","38":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","41":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","46":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","50":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","51":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","54":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","63":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","91":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","94":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","95":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","107":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","115":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","123":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA=","131":"b:AAAAAAAAABCAgACABgBCAABAAAAE4AAIAFYEAAA="},"packages/cli/src/workflows/node-group-rules-flag-gate.ts":{"16":[31,71],"19":[31,71]},"packages/nodes-base/nodes/If/If.node.ts":{"8":[120,31,169,71,203,136,137,140,119,100]},"packages/nodes-base/nodes/If/V1/IfV1.node.ts":{"18":"b:AAAAgAAAAACAAAAAEACAAQATAAAAAgAAAAgFAAA=","26":"b:AAAAgAAAAACAAAAAEACAAQATAAAAAgAAAAgFAAA=","320":"b:AAAAgAAAAACAAAAAEACAAQATAAAAAgAAAAgFAAA=","329":"b:AAAAgAAAAACAAAAAEACAAQATAAAAAgAAAAgFAAA=","331":"b:AAAAgAAAAACAAAAAEACAAQATAAAAAgAAAAgFAAA=","337":"b:AAAAgAAAAACAAAAAEACAAQATAAAAAgAAAAgFAAA=","339":"b:AAAAgAAAAACAAAAAEACAAQATAAAAAgAAAAgFAAA=","341":"b:AAAAgAAAAACAAAAAEACAAQATAAAAAgAAAAgFAAA=","343":"b:AAAAgAAAAACAAAAAEACAAQATAAAAAgAAAAgFAAA=","345":"b:AAAAgAAAAACAAAAAEACAAQATAAAAAgAAAAgFAAA=","347":"b:AAAAgAAAAACAAAAAEACAAQATAAAAAgAAAAgFAAA=","349":"b:AAAAgAAAAACAAAAAEACAAQATAAAAAgAAAAgFAAA=","350":"b:AAAAgAAAAACAAAAAEACAAQATAAAAAgAAAAgFAAA=","351":"b:AAAAgAAAAACAAAAAEACAAQATAAAAAgAAAAgFAAA=","353":"b:AAAAgAAAAACAAAAAEACAAQATAAAAAgAAAAgFAAA=","355":"b:AAAAgAAAAACAAAAAEACAAQATAAAAAgAAAAgFAAA=","357":"b:AAAAgAAAAACAAAAAEACAAQATAAAAAgAAAAgFAAA=","359":"b:AAAAgAAAAACAAAAAEACAAQATAAAAAgAAAAgFAAA=","361":"b:AAAAgAAAAACAAAAAEACAAQATAAAAAgAAAAgFAAA=","363":"b:AAAAgAAAAACAAAAAEACAAQATAAAAAgAAAAgFAAA=","369":"b:AAAAgAAAAACAAAAAEACAAQATAAAAAgAAAAgFAAA=","378":"b:AAAAgAAAAACAAAAAEACAAQATAAAAAgAAAAgFAAA=","383":"b:AAAAgAAAAACAAAAAEACAAQATAAAAAgAAAAgFAAA="},"packages/nodes-base/nodes/If/V2/IfV2.node.ts":{"20":[120,31,169,71,203,136,137,140,119,100],"96":[120,31,169,71,203,136,137,140,119,100],"100":[120,31,169,71,203,136,137,140,119,100]},"packages/nodes-base/nodes/If/V2/utils.ts":{"3":"b:AAAAgAAAAACAAAAAEQCAAQATAAAAAgEAAAgAAAA=","7":"b:AAAAgAAAAACAAAAAEQCAAQATAAAAAgEAAAgAAAA=","8":"b:AAAAgAAAAACAAAAAEQCAAQATAAAAAgEAAAgAAAA="},"packages/nodes-base/nodes/StickyNote/StickyNote.node.ts":{"57":[176,187,71,200,136,212,80,100]},"packages/workflow/src/graph/graph-utils.ts":{"41":[31,71],"62":[31,71],"80":[31,71],"88":[31,71],"95":[31,71],"103":[31,71],"114":[31,71],"115":[31,71],"123":[31,71],"133":[31,71],"134":[31,71],"145":[31,71],"157":[31,71],"170":[31,71],"174":[31,71],"199":[31,71],"203":[31,71],"213":[31,71],"217":[31,71],"239":[31,71],"249":[31,71],"264":[31,71]},"packages/@n8n/db/src/repositories/poller-state.repository.ts":{"32":[49,112,50,51,94,52],"42":[49,112,50,51,94,52],"59":[49,112,50,51,94,52],"104":[49,112,50,51,94,52],"119":[49,112,50,51,94,52],"150":[49,112,50,51,94,52],"159":[49,112,50,51,94,52],"183":[49,112,50,51,94,52],"196":[49,112,50,51,94,52],"197":[49,112,50,51,94,52],"199":[49,112,50,51,94,52],"212":[49,112,50,51,94,52],"223":[49,112,50,51,94,52],"232":[49,112,50,51,94,52]},"packages/cli/src/workflows/triggers/poll-cursor.service.ts":{"17":[49,50,51,94,52],"21":[49,50,51,94,52],"42":[49,50,51,94,52],"51":[49,50,51,94,52],"56":[49,50,51,94,52],"78":[49,50,51,94,52],"102":[49,50,51,94,52],"122":[49,50,51,94,52],"146":[49,50,51,94,52],"155":[49,50,51,94,52],"157":[49,50,51,94,52],"192":[49,50,51,94,52],"199":[49,50,51,94,52]},"packages/core/src/execution-engine/node-execution-context/poll-context.ts":{"21":[49,50,51,94,52],"25":[49,50,51,94,52],"32":[49,50,51,94,52],"42":[49,50,51,94,52],"43":[49,50,51,94,52],"46":[49,50,51,94,52],"51":[49,50,51,94,52],"65":[49,50,51,94,52],"70":[49,50,51,94,52],"74":[49,50,51,94,52],"79":[49,50,51,94,52]},"packages/core/src/execution-engine/poll-cursor-hooks.ts":{"8":[49,112,50,51,94,52],"14":[49,112,50,51,94,52]},"packages/core/src/execution-engine/poll-trigger-executor.ts":{"21":[49,50,51,94,52],"39":[49,50,51,94,52],"45":[49,50,51,94,52],"62":[49,50,51,94,52],"94":[49,50,51,94,52]},"packages/nodes-base/nodes/E2eTest/E2eTestPollingTrigger.node.ts":{"15":[49,50,51,94,52],"16":[49,50,51,94,52],"48":[49,50,51,94,52],"69":[49,50,51,94,52]},"packages/workflow/src/cron.ts":{"52":[49,50,51,94,52],"80":[49,50,51,94,52]},"localhost-36257/assets/index-BoK1c_f3.js":{"3":[71]},"localhost-36257/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[71],"9":[71],"10":[71],"19":[71],"23":[71],"29":[71],"33":[71],"34":[71]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/blocks--solid-16.svg":{"9":[86,124,31,71]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/group--outline-16.svg":{"9":[86,124,31,45,187,71,213]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/palette--outline-16.svg":{"9":[86,124,176,187,71,200,136,212,218,100]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/workflow--solid-16.svg":{"9":[86,124,31,71]},"packages/frontend/@n8n/design-system/src/components/N8nSticky/Sticky.vue":{"16":[86,124,176,187,71,200,136,212,218,100],"28":[86,124,176,187,71,200,136,212,218,100],"32":[86,124,176,187,71,200,136,212,218,100],"36":[86,124,176,187,71,200,136,212,218,100],"38":[86,124,176,187,71,200,136,212,218,100],"43":[86,124,176,187,71,200,136,212,218,100],"45":[86,124],"58":[86,124,176,187,71,200,136,212,218,100],"65":[86,124,176,187,71,200,136,212,218,100],"66":[86,124],"68":[86,124],"79":[86,124],"83":[86,124],"87":[86,124],"91":[86,124],"95":[86,124],"99":[86,124,176,187,71,200,136,212,218,100],"113":[86,124],"127":[86,124],"128":[86,124],"129":[86,124],"130":[86,124],"146":[86,124]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/edges/CanvasEdgeToolbar.vue":{"12":[86,124,45,186,187,188,70,134,71,201,137],"27":[86,124,45,186,187,188,70,134,71,201,137],"31":[86,124,45,186,187,188,70,134,71,201,137],"41":[86,124,186,187,70],"45":[86,124,70,71,201],"47":[86,124,45,186,187,188,70,134,71,201,137],"55":[86,124,45,186,187,188,70,134,71,201,137],"72":[86,124,45,186,187,188,70,134,71,201,137]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/edges/CanvasEdgeTooltip.vue":{"9":[86,124,45,186,187,188,70,134,71,201,137],"10":[86,124,45,186,187,188,70,134,71,201,137],"20":[86,124,45,186,187,188,70,134,71,201,137]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/groups/CanvasNodeGroupTitleBar.vue":{"38":[86,124,31,71],"84":[86,124,31,71],"85":[86,124,31,71],"88":[86,124,31,71],"89":[86,124,31,71],"90":[86,124,31,71],"91":[86,124,31,71],"92":[86,124,31,71],"93":[86,124,31,71],"105":[86,124,31,71],"107":[86,124,31,71],"122":[86,124,71],"133":[86,124,71],"140":[86,124,31,71],"154":[86,124,31,71],"156":[86,124,31,71],"163":[86,124,71],"167":[86,124],"171":[86,124,71],"175":[86,124],"179":[86,124],"185":[86,124,31,71],"192":[86,124,71],"196":[86,124],"211":[86,124,71],"218":[86,124,31,71],"233":[86,124,31,71],"237":[86,124,31,71],"238":[86,124,31,71],"244":[86,124,31,71],"267":[86,124,31,71],"268":[86,124,31,71],"271":[86,124,31,71],"275":[86,124,31,71],"278":[86,124,31,71],"285":[86,124,31,71],"292":[86,124,71],"297":[86,124,71],"298":[86,124],"304":[86,124],"306":[86,124],"313":[86,124],"319":[86,124,71],"323":[86,124,71],"327":[86,124],"334":[86,124],"338":[86,124],"345":[86,124],"354":[86,124],"358":[86,124],"363":[86,124],"372":[86,124],"385":[86,124],"399":[86,124,71],"412":[86,124],"416":[86,124,31,71],"431":[86,124],"446":[86,124,31,71],"458":[86,124,31,71],"472":[86,124,31,71],"487":[86,124,31,71],"501":[86,124],"535":[86,124,31,71],"664":[86,124],"685":[86,124],"692":[86,124],"699":[86,124],"715":[86,124],"733":[86,124]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/CanvasNodeStickyNote.vue":{"15":[86,124,176,187,71,200,136,212,218,100],"27":[86,124,176,187,71,200,136,212,218,100],"29":[86,124,176,187,71,200,136,212,218,100],"39":[86,124],"57":[86,124],"63":[86,124],"75":[86,124],"83":[86,124,200],"91":[86,124,176,187,71,200,136,212,218,100],"95":[86,124,71],"98":[86,124,176,187,71,200,136,212,218,100]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/toolbar/CanvasNodeStickyColorSelector.vue":{"10":[86,124,176,187,71,200,136,212,218,100],"17":[86,124,200],"21":[86,124,200],"27":[86,124],"31":[86,124,200],"35":[86,124],"40":[86,124],"44":[86,124],"49":[86,124],"53":[86,124,200],"60":[86,124],"61":[86,124],"66":[86,124,176,187,71,200,136,212,218,100],"70":[86,124,71],"73":[86,124,176,187,71,200,136,212,218,100],"86":[86,124,176,187,71,200,136,212,218,100],"95":[86,124,200],"98":[86,124,200],"106":[86,124],"135":[86,124]},"packages/frontend/editor-ui/src/features/workflows/canvas/nodeGroups.utils.ts":{"7":[86,124,71],"12":[86,124],"17":[86,124],"18":[86,124],"24":[86,124],"32":[86,124,71]},"localhost-41355/assets/index-BoK1c_f3.js":{"3":[76]},"localhost-41355/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[76],"9":[76],"10":[76],"19":[76],"23":[76],"29":[76],"33":[76],"34":[76]},"packages/@n8n/expression-runtime/src/bridge/quickjs-bridge.ts":{"41":[86,124,76],"43":[86,124,76],"67":[86,124,76],"76":[86,124,76],"84":[86,124,76],"97":[86,124,76],"107":[86,124,76],"115":[86,124,76],"132":[86,124],"137":[86,124],"154":[86,124,76],"196":[86,124],"203":[86,124],"205":[86,124],"233":[86,124,76],"244":[86,124],"277":[86,124],"305":[86,124,76],"328":[86,124,76],"343":[86,124],"363":[86,124,76],"365":[86,124],"367":[86,124,76],"368":[86,124,76],"369":[86,124,76],"373":[86,124,76],"375":[86,124],"377":[86,124,76],"378":[86,124],"379":[86,124],"383":[86,124],"385":[86,124],"387":[86,124],"392":[86,124],"397":[86,124],"401":[86,124],"403":[86,124],"405":[86,124],"406":[86,124],"407":[86,124],"411":[86,124],"413":[86,124],"415":[86,124],"416":[86,124],"420":[86,124],"422":[86,124],"424":[86,124],"425":[86,124],"429":[86,124],"431":[86,124],"433":[86,124],"434":[86,124],"438":[86,124],"441":[86,124],"483":[86,124,76],"491":[86,124,76],"517":[86,124],"535":[86,124,76],"545":[86,124,76],"574":[86,124,76],"602":[86,124,76],"607":[86,124,76],"608":[86,124,76],"804":[86,124,76],"848":[86,124,76],"1021":[86,124,76],"1045":[86,124,76],"1083":[86,124,76],"1090":[86,124,76],"1100":[86,124],"1111":[86,124],"1130":[86,124,76],"1175":[86,124,76],"1311":[86,124],"1320":[86,124,76],"1334":[86,124],"1357":[86,124,76]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/chevron-left--outline-16.svg":{"9":"b:AAAAAwA4ABAAfEIhHgAQEgAwASAEQAJAIMwFAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/node-pin.svg":{"11":"b:AAAAAAAAAAAAOUAAEgAQEAARIAAAAAEAgOYnAAA="},"packages/frontend/editor-ui/src/app/utils/telemetryUtils.ts":{"5":[86,124,60,206,116,75,76,207,77,78,141],"13":[86,124,60,206,116,75,76,207,77,141],"14":[86,124,60,206,116,75,76,207,141],"21":[86,124,60,206,116,75,76,207,141],"27":[86,124,206,75,141],"28":[86,124,206,75,141],"71":[86,124,60,206,116,75,76,207,141],"78":[86,124],"79":[86,124]},"packages/frontend/editor-ui/src/features/shared/editors/components/InlineExpressionEditor/ExpressionOutput.vue":{"20":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMQAAAA=","33":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMQAAAA=","34":"b:AAAAAAAAABAAPEAAAgAQEAAwAAAAAAAAAMQAAAA=","37":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMQAAAA=","46":"b:AAAAAAAAABAAPEAAAgAQEAAwAAAAAAAAAMQAAAA=","60":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMQAAAA=","62":"b:AAAAAAAAABAAPEAAAgAQEAAwAAAAAAAAAMQAAAA=","65":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMQAAAA=","88":"b:AAAAAAAAABAAPEAAAgAQEAAwAAAAAAAAAMQAAAA=","99":"b:AAAAAAAAABAAPEAAAgAQEAAwAAAAAAAAAMQAAAA=","102":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMQAAAA=","112":[86,124,75],"122":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMQAAAA=","123":"b:AAAAAAAAABAAPEAAAgAQEAAwAAAAAAAAAMQAAAA=","136":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMQAAAA=","138":[86,124],"149":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMQAAAA=","154":[86,124,60,202,206,116,75,76,207,77,78,141],"158":[86,124,75],"159":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMQAAAA="},"packages/frontend/editor-ui/src/features/shared/editors/components/InlineExpressionEditor/OutputItemSelect.vue":{"7":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMQAAAA=","10":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMQAAAA=","11":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMQAAAA=","12":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMQAAAA=","13":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMQAAAA=","14":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMQAAAA=","17":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMQAAAA=","18":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMQAAAA=","19":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMQAAAA=","20":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMQAAAA=","21":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMQAAAA=","25":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMQAAAA=","26":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMQAAAA=","28":[86,124],"32":[86,124,77,140],"36":[86,124,77],"38":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMQAAAA=","44":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMQAAAA=","69":[86,124],"71":"b:AAAAAAAAABAAfEAAAgAQEAAwAAAAAABAAMQAAAA="},"packages/frontend/editor-ui/src/features/shared/editors/components/JsonEditor/JsonEditor.vue":{"33":"b:AAQAAAAAAAAAOEAAAgAwFEAQAAAAAQAAANQQAAA=","43":"b:AAQAAAAAAAAAOEAAAgAwFEAQAAAAAQAAANQQAAA=","71":"b:AAQAAAAAAAAAOEAAAgAwEEAQAAAAAQAAANQQAAA=","80":"b:AAQAAAAAAAAAOEAAAgAwFEAQAAAAAQAAANQQAAA=","84":"b:AAQAAAAAAAAAOEAAAgAQEAAQAAAAAQAAAMQAAAA=","89":"b:AAQAAAAAAAAAOEAAAgAwFEAQAAAAAQAAANQQAAA=","90":[86,124,202,206,116,75,76,207,140,97],"102":"b:AAQAAAAAAAAAOEAAAgAwFEAQAAAAAQAAANQQAAA=","110":[86,124],"114":[86,124],"124":"b:AAQAAAAAAAAAOEAAAgAwFEAQAAAAAQAAANQQAAA="},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/blank.completions.ts":{"8":"b:AAAAAAAAABAAfEAAAgAQEAAgAAAAAAAAAMQAAAA="},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/bracketAccess.completions.ts":{"17":"b:AAAAAAAAABAAfEAAAgAQEAAgAAAAAAAAAMQAAAA=","53":[86,124,206,116,75,77],"62":[86,124,116],"70":[86,124,206,116,75,77],"74":[86,124,206,116,75,77],"75":[86,124,206,116,75,77]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/dollar.completions.ts":{"29":"b:AAAAAAAAABAAfEAAAgAQEAAgAAAAAAAAAMQAAAA=","43":"b:AAAAAAAAABAAPEAAAgAQEAAgAAAAAAAAAMQAAAA=","52":[86,124],"60":"b:AAAAAAAAABAAPEAAAgAQEAAgAAAAAAAAAMQAAAA=","138":[86,124,202,74,206,116,75,76,207,77,97,141],"153":[86,124,202,74,206,116,75,76,207,77,97,141],"155":[86,124,202,74,206,116,75,76,207,77,97,141]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/completions/nonDollar.completions.ts":{"9":"b:AAAAAAAAABAAfEAAAgAQEAAgAAAAAAAAAMQAAAA=","56":[86,124]},"packages/nodes-base/nodes/Google/Gmail/GenericFunctions.ts":{"30":[7,23,140,211],"146":[7,23,140,211],"209":[7,23,140,211],"233":[7,23,140,211],"258":[7,23,140,211],"281":[7,23,140,211],"289":[7,23,140,211],"343":[7,23,140,211],"400":[7,23,140,211],"408":[7,23,140,211],"428":[7,23,140,211],"468":[7,23,140,211],"501":[7,23,140,211],"502":[7,23,140,211],"512":[7,23,140,211],"517":[7,23,140,211],"521":[7,23,140,211],"523":[7,23,140,211],"530":[7,23,140,211],"542":[7,23,140,211],"559":[7,23,140,211]},"packages/nodes-base/nodes/Google/Gmail/Gmail.node.ts":{"8":[7,23,140]},"packages/nodes-base/nodes/Google/Gmail/utils/descriptions.ts":{"3":[7,23,140,211]},"packages/nodes-base/nodes/Google/Gmail/utils/replyToEmail.ts":{"16":[7,23,140],"71":[7,23,140],"76":[7,23,140],"95":[7,23,140],"98":[7,23,140],"107":[7,23,140]},"packages/nodes-base/nodes/Google/Gmail/v1/GmailV1.node.ts":{"134":[7,23,140],"147":[7,23,140],"260":[7,23,140],"267":[7,23,140],"275":[7,23,140],"347":[7,23,140],"354":[7,23,140],"362":[7,23,140],"417":[7,23,140],"421":[7,23,140],"587":[7,23,140],"595":[7,23,140],"603":[7,23,140]},"packages/nodes-base/nodes/Google/Gmail/v2/GmailV2.node.ts":{"157":[7,23,140],"174":[7,23,140]},"packages/nodes-base/nodes/Google/Gmail/v2/loadOptions.ts":{"5":[7,23,140],"29":[7,23,140]},"packages/nodes-base/nodes/Google/Gmail/v2/utils/draft.ts":{"7":[7,23,140],"14":[7,23,140],"21":[7,23,140],"32":[7,23,140]},"packages/nodes-base/nodes/Microsoft/GenericFunctions.ts":{"10":[7],"65":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/MicrosoftOutlook.node.ts":{"8":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v1/GenericFunctions.ts":{"12":[7],"57":[7],"90":[7],"123":[7],"131":[7],"155":[7],"157":[7],"161":[7],"165":[7],"176":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v1/MicrosoftOutlookV1.node.ts":{"108":[7],"119":[7],"138":[7],"264":[7],"312":[7],"315":[7],"372":[7],"589":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/MicrosoftOutlookV2.node.ts":{"16":[7],"27":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/calendar/create.operation.ts":{"94":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/calendar/delete.operation.ts":{"19":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/calendar/get.operation.ts":{"19":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/calendar/getAll.operation.ts":{"38":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/calendar/update.operation.ts":{"89":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/contact/create.operation.ts":{"42":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/contact/delete.operation.ts":{"19":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/contact/get.operation.ts":{"55":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/contact/getAll.operation.ts":{"81":[7],"106":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/contact/update.operation.ts":{"30":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/draft/create.operation.ts":{"206":[7],"223":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/draft/delete.operation.ts":{"19":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/draft/get.operation.ts":{"85":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/draft/send.operation.ts":{"29":[7],"36":[7],"37":[7],"41":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/draft/update.operation.ts":{"184":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/event/create.operation.ts":{"180":[7],"222":[7],"225":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/event/delete.operation.ts":{"20":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/event/get.operation.ts":{"56":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/event/getAll.operation.ts":{"125":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/event/update.operation.ts":{"217":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/folder/create.operation.ts":{"38":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/folder/delete.operation.ts":{"20":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/folder/get.operation.ts":{"39":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/folder/getAll.operation.ts":{"68":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/folder/update.operation.ts":{"30":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/folderMessage/getAll.operation.ts":{"228":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/message/delete.operation.ts":{"19":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/message/get.operation.ts":{"115":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/message/getAll.operation.ts":{"244":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/message/move.operation.ts":{"22":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/message/reply.operation.ts":{"222":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/message/send.operation.ts":{"209":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/message/sendAndWait.operation.ts":{"31":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/message/update.operation.ts":{"173":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/messageAttachment/add.operation.ts":{"54":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/messageAttachment/download.operation.ts":{"30":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/messageAttachment/get.operation.ts":{"62":[7],"79":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/messageAttachment/getAll.operation.ts":{"62":[7],"77":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/actions/router.ts":{"16":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/helpers/utils.ts":{"65":[7],"107":[7],"147":[7],"149":[7],"157":[7],"183":[7],"185":[7],"207":[7],"208":[7],"216":[7],"224":[7],"242":[7],"258":[7],"267":[7],"279":[7],"285":[7],"286":[7],"345":[7],"370":[7],"374":[7],"378":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/methods/listSearch.ts":{"11":[7],"45":[7],"55":[7],"63":[7],"71":[7],"104":[7],"115":[7],"147":[7],"158":[7],"201":[7],"212":[7],"241":[7],"247":[7],"258":[7],"295":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/methods/loadOptions.ts":{"8":[7],"28":[7],"48":[7]},"packages/nodes-base/nodes/Microsoft/Outlook/v2/transport/index.ts":{"27":[7],"48":[7],"72":[7],"150":[7],"184":[7],"237":[7],"273":[7],"291":[7]},"packages/nodes-base/nodes/Slack/Slack.node.ts":{"8":[7,34,166,172,178]},"packages/nodes-base/nodes/Slack/SlackTriggerHelpers.ts":{"8":[7,34,166,172,178],"22":[7,34,166,172,178],"39":[7,34,166,172,178],"50":[7,34,166,172,178],"104":[7,34,166,172,178],"119":[7,34,166,172,178],"139":[7,34,166,172,178],"143":[7,34,166,172,178]},"packages/nodes-base/nodes/Slack/V1/GenericFunctions.ts":{"16":[7,34,166,172,178],"19":[7,34,166,172,178],"20":[7,34,166,172,178],"26":[7,34,166,172,178],"27":[7,34,166,172,178],"33":[7,34,166,172,178],"104":[7,34,166,172,178],"140":[7,34,166,172,178]},"packages/nodes-base/nodes/Slack/V1/SlackV1.node.ts":{"76":[7,34,166,172,178],"190":[7,34,166,172,178],"202":[7,34,166,172,178],"216":[7,34,166,172,178],"236":[7,34,166,172,178],"250":[7,34,166,172,178],"268":[7,34,166,172,178],"476":[7,34,166,172,178],"486":[7,34,166,172,178]},"packages/nodes-base/nodes/Slack/V2/GenericFunctions.ts":{"41":[7,34,166,172,178],"48":[7,34,166,172,178],"51":[7,34,166,172,178],"52":[7,34,166,172,178],"58":[7,34,166,172,178],"59":[7,34,166,172,178],"70":[7,34,166,172,178],"136":[7,34,166,172,178],"140":[7,34,166,172,178],"200":[7,34,166,172,178],"213":[7,34,166,172,178],"249":[7,34,166,172,178],"314":[7,34,166,172,178],"354":[7,34,166,172,178],"398":[7,34,166,172,178],"473":[7,34,166,172,178],"483":[7,34,166,172,178],"510":[7,34,166,172,178],"526":[7,34,166,172,178],"570":[7,34,166,172,178]},"packages/nodes-base/nodes/Slack/V2/SlackHitlWebhook.ts":{"23":[7,34,166,172,178],"60":[7,34,166,172,178],"80":[7,34,166,172,178],"91":[7,34,166,172,178],"141":[7,34,166,172,178],"213":[7,34,166,172,178]},"packages/nodes-base/nodes/Slack/V2/SlackV2.node.ts":{"66":[7,34,166,172,178],"187":[7,34,166,172,178],"204":[7,34,166,172,178],"224":[7,34,166,172,178],"229":[7,34,166,172,178],"234":[7,34,166,172,178],"241":[7,34,166,172,178],"257":[7,34,166,172,178],"263":[7,34,166,172,178],"268":[7,34,166,172,178],"279":[7,34,166,172,178],"296":[7,34,166,172,178],"310":[7,34,166,172,178],"330":[7,34,166,172,178],"344":[7,34,166,172,178],"363":[7,34,166,172,178],"377":[7,34,166,172,178],"397":[7,34,166,172,178],"621":[7,34,166,172,178],"684":[7,34,166,172,178],"694":[7,34,166,172,178],"1644":[7,34,166,172,178],"1689":[7,34,166,172,178],"1717":[7,34,166,172,178]},"packages/nodes-base/utils/query-escaping.ts":{"19":[7,78,218,100],"27":[7,78,218,100],"38":[7,78,218,100],"52":[7,78,218,100],"67":[7,78,218,100],"77":[7,78,218,100],"94":[7,78,218,100],"117":[7,78,218,100],"142":[7,78,218,100],"150":[7,78,218,100]},"packages/nodes-base/utils/sendAndWait/email-templates.ts":{"82":[7,23,34,166,40,172,178,136,140,82],"147":[7,23,34,166,40,172,178,136,140,82]},"packages/nodes-base/utils/sendAndWait/utils.ts":{"59":[7,23,34,166,40,172,178,136,140,82],"155":[7,23,34,166,40,172,178,136,140,82],"311":[7,23,34,166,40,172,178,136,140,82],"341":[7,23,34,166,40,172,178,136,140,82],"351":[7,23,34,166,40,172,178,136,140,82],"354":[7,23,34,166,40,172,178,136,140,82],"501":[7,23,34,166,40,172,178,136,140,82],"506":[7,23,34,166,40,172,178,136,140,82],"513":[7,23,34,166,40,172,178,136,140,82],"584":[7,23,34,166,40,172,178,136,140,82],"592":[7,23,34,166,40,172,178,136,140,82],"626":[7,23,34,166,40,172,178,136,140,82]},"packages/nodes-base/utils/webhook-signature-verification.ts":{"64":[7,34,166,172,178],"106":[7,34,166,172,178]},"localhost-41281/assets/index-BoK1c_f3.js":{"3":[7,144,146,163,97]},"localhost-41281/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[7,144,146,163,97],"9":[7,144,146,163,97],"10":[7,144,146,163,97],"19":[7,144,146,163,97],"23":[7,144,146,163,97],"29":[7,144,146,163,97],"33":[7,144,146,163,97],"34":[7,144,146,163,97]},"packages/frontend/@n8n/design-system/src/components/AskAssistantButton/AskAssistantButton.vue":{"8":[5,6,7,86,124],"18":[86,124],"20":[86,124],"24":[86,124],"26":[5,6,7,86,124]},"packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/BaseMessage.vue":{"16":[5,6,7,8,144,86,11,124],"22":[86,124],"23":[86,124],"29":[86,124],"31":[5,6,7,8,144,86,11,124]},"packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/MessageWrapper.vue":{"22":[5,6,7,8,144,86,11,124],"30":[5,6,7,8,144,86,11,124],"33":[5,6,7,8,144,86,11,124],"47":[6,86,124],"48":[6,86,124],"49":[86,124],"51":[86,124]},"packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/TextMessage.vue":{"31":[8,86,124],"40":[5,6,7,8,144,86,11,124],"42":[5,6,7,8,144,86,11,124],"48":[86,124],"52":[5,6,7,8,144,86,11,124],"53":[5,6,7,8,144,86,11,124],"58":[5,6,7,8,144,86,11,124],"59":[86,124],"61":[86,124],"67":[86,124],"70":[86,124],"73":[86,124],"77":[86,124],"80":[5,6,7,8,144,86,11,124],"88":[86,124],"89":[5,6,7,8,144,86,11,124],"112":[86,124],"136":[86,124],"137":[8,86,124]},"packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/ThinkingMessage.vue":{"14":[5,6,7,8,144,86,11,124],"21":[5,6,7,8,144,86,11,124],"23":[5,6,7,8,144,86,11,124],"24":[86,124],"32":[5,6,7,8,144,86,11,124],"34":[86,124],"38":[5,6,7,8,144,86,11,124],"48":[5,6,7,8,144,86,11,124],"64":[5,6,7,8,144,86,11,124],"65":[5,6,7,8,144,86,11,124]},"packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/helpers.ts":{"9":[5,6,7,8,144,86,11,124]},"packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/useMarkdown.ts":{"6":[5,6,7,8,144,86,11,124],"22":[86,124],"29":[5,6,7,8,144,86,11,124]},"packages/frontend/@n8n/design-system/src/components/BlinkingCursor/BlinkingCursor.vue":{"2":[5,6,7,8,144,86,124]},"packages/frontend/@n8n/design-system/src/types/assistant.ts":{"165":[5,6,7,8,144,86,11,124],"221":[5,6,7,8,144,86,11,124],"227":[5,6,7,8,144,86,11,124],"239":[5,6,7,8,144,86,11,124]},"packages/frontend/editor-ui/src/app/components/CopyInput.vue":{"21":[7,86,23,124,173,59,136],"39":[86,124,136],"50":[7,86,23,124,173,59,136],"56":[7,86,23,124,173,59,136]},"packages/frontend/editor-ui/src/features/ai/assistant/assistant.api.ts":{"19":[144,86,11,124],"46":[5,6,7,8,86,124],"75":[6,86,124],"88":[86,124],"100":[86,124],"110":[86,124],"130":[144,86,146,11,124],"137":[86,124],"141":[86,124],"145":[86,124],"153":[86,124],"162":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Chat/AskAssistantChat.vue":{"13":[5,6,7,8,86,124,131],"27":[5,6,7,8,86,124,131],"32":[5,6,7,8,86,124,131],"34":[5,6,7,8,86,124,131],"39":[5,8,86,124],"50":[5,8,86,124],"65":[6,86,124],"72":[6,86,124],"80":[5,6,7,8,86,124,131],"84":[5,6,7,8,86,124,131],"87":[5,8,86,124],"96":[5,86,124],"103":[86,124],"105":[86,124],"108":[5,6,7,8,86,124,131]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Chat/AskAssistantFloatingButton.vue":{"14":[5,6,7],"25":[5,6,7],"63":[5,6,7],"80":[5,6,7]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Chat/AskModeEmptyState.vue":{"5":[5,6,7,8,86,124,131],"6":[5,6,7,8,86,124,131]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/GoogleAuthButton.vue":{"2":[7,86,23,124]},"packages/cli/src/credentials/credentials.service.ee.ts":{"30":"b:AACoAAAQAAACAAQIACAAADAAASAAAAAACAAAQAA=","44":"b:AACoAAAQAAACAAQIACAAADAAASAAAAAACAAAQAA=","83":"b:AACoAAAQAAACAAQIACAAADAAASAAAAAACAAAQAA=","85":"b:AACoAAAQAAACAAQIACAAADAAASAAAAAACAAAQAA=","89":"b:AACoAAAQAAACAAQIACAAADAAASAAAAAACAAAQAA=","100":"b:AACoAAAQAAACAAQIACAAADAAASAAAAAACAAAQAA=","104":"b:AACoAAAQAAACAAQIACAAADAAASAAAAAACAAAQAA=","196":"b:AACoAAAQAAACAAQIACAAADAAASAAAAAACAAAQAA=","209":"b:AACoAAAQAAACAAQIACAAADAAASAAAAAACAAAQAA=","266":"b:AACoAAAQAAACAAQIACAAADAAASAAAAAACAAAQAA=","268":"b:AACoAAAQAAACAAQIACAAADAAASAAAAAACAAAQAA="},"packages/nodes-base/nodes/Telegram/GenericFunctions.ts":{"84":[144,136,82],"146":[144,136,82],"220":[144,136,82],"260":[144,136,82],"273":[144,136,82],"277":[144,136,82],"283":[144,136,82],"304":[144,136,82]},"packages/nodes-base/nodes/Telegram/Telegram.node.ts":{"2043":[144,136,82],"2049":[144,136,82]},"packages/nodes-base/nodes/Telegram/TelegramTrigger.node.ts":{"26":[144],"237":[144],"252":[144],"286":[144],"301":[144],"358":[144],"376":[144],"394":[144]},"packages/nodes-base/nodes/Telegram/hitl/setup.ts":{"11":[144,136,82],"24":[144,136,82],"41":[144,136,82],"67":[144,136,82]},"packages/nodes-base/nodes/Telegram/hitl/tokens.ts":{"17":[144,136,82]},"packages/nodes-base/nodes/Telegram/hitl/webhook.ts":{"12":[144,136,82],"21":[144,136,82],"25":[144,136,82],"36":[144,136,82],"51":[144,136,82],"88":[144,136,82],"133":[144,136,82]},"packages/nodes-base/nodes/Telegram/util/triggerUtils.ts":{"11":[144]},"packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/MessageRating.vue":{"15":[144,86,124],"32":[86,124],"39":[86,124],"49":[86,124],"57":[86,124],"62":[144,86,124],"78":[86,124],"86":[86,124],"97":[86,124],"106":[86,124]},"packages/frontend/@n8n/design-system/src/components/CanvasPill/CanvasPill.vue":{"8":[144,86,11,124],"9":[144,86,11,124]},"packages/frontend/@n8n/design-system/src/components/CanvasThinkingPill/CanvasThinkingPill.vue":{"17":[144,86,11,124],"23":[144,86,11,124],"27":[144,86,11,124],"30":[144,86,11,124],"40":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/currency-dollar-circle--outline-16.svg":{"9":[3,144,86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/sparkle-rays--outline-16.svg":{"9":"b:AAiRAAIAAAAAAEAAEAAAEAAIBQAAACBAAAAAAQA="},"packages/frontend/editor-ui/src/features/ai/assistant/assistant.types.ts":{"422":[144,86,11,124],"439":[144,86,124],"445":[86,124],"458":[144,86,11,124],"464":[144,86,11,124],"468":[144,86,124],"492":[144,86,124],"499":[86,124],"505":[144,86,124],"511":[144,86,124],"523":[144,86,124],"529":[144,86,124],"535":[144,86,124],"545":[144,86,124],"551":[144,86,124],"555":[144,86,124],"561":[144,86,124],"573":[144,86,11,124],"579":[144,86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/builder.utils.ts":{"19":[144,86,11,124],"23":[144,86,11,124],"27":[144,86,11,124],"121":[86,124],"122":[86,124],"130":[144,86,11,124],"141":[144,86,11,124],"152":[86,124],"161":[86,124],"165":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/BuilderSetupCard.vue":{"30":[144,86,124],"55":[144,86,124],"59":[144,86,124],"61":[144,86,124],"84":[144,86,124],"86":[86,124],"91":[144,86,124],"97":[144,86,124],"101":[144,86,124],"105":[144,86,124],"106":[144,86,124],"107":[144,86,124],"111":[144,86,124],"112":[144,86,124],"113":[144,86,124],"114":[144,86,124],"116":[144,86,124],"120":[86,124],"122":[144,86,124],"129":[86,124],"140":[144,86,124],"153":[144,86,124],"161":[86,124],"173":[86,124],"186":[144,86,124],"191":[144,86,124],"192":[86,124],"193":[144,86,124],"209":[144,86,124],"210":[144,86,124],"213":[144,86,124],"222":[144,86,124],"223":[144,86,124],"236":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/BuilderSetupWizard.vue":{"14":[144,86,124],"22":[86,124],"39":[144,86,124],"43":[144,86,124],"47":[144,86,124],"51":[144,86,124],"55":[144,86,124],"59":[144,86,124],"68":[86,124],"75":[144,86,124],"86":[144,86,124],"91":[144,86,124],"96":[144,86,124],"102":[144,86,124],"104":[144,86,124],"107":[144,86,124],"115":[144,86,124],"122":[144,86,124],"131":[144,86,124],"140":[144,86,124],"148":[86,124],"152":[86,124],"162":[144,86,124],"175":[144,86,124],"187":[144,86,124],"204":[86,124],"210":[144,86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/CreditsSettingsDropdown.vue":{"11":[144,86,124],"37":[144,86,124],"44":[86,124],"51":[86,124],"53":[86,124],"61":[86,124],"65":[86,124],"72":[86,124],"83":[86,124],"90":[86,124],"97":[86,124],"102":[86,124],"105":[144,86,124],"121":[144,86,124],"127":[86,124],"151":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/ExecuteMessage.vue":{"34":[144,86,124],"37":[86,124],"40":[86,124],"51":[144,86,124],"58":[144,86,124],"59":[86,124],"72":[86,124],"87":[144,86,124],"101":[86,124],"122":[86,124],"129":[86,124],"136":[144,86,124],"138":[86,124],"142":[86,124],"146":[144,86,124],"150":[86,124],"153":[86,124],"156":[86,124],"161":[86,124],"164":[86,124],"168":[86,124],"173":[86,124],"181":[86,124],"186":[86,124],"188":[86,124],"191":[144,86,124],"199":[86,124],"206":[86,124],"218":[86,124],"223":[144,86,124],"234":[86,124],"235":[86,124],"258":[86,124],"260":[86,124],"265":[86,124],"283":[86,124],"285":[86,124],"297":[86,124],"326":[86,124],"328":[86,124],"344":[86,124],"346":[86,124],"370":[86,124],"406":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/components/HubSwitcher.vue":{"11":[144,86,146,11,124],"19":[144,86,146,11,124],"24":[86,124],"26":[144,86,146,11,124]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useBuilderExecution.ts":{"21":[144,86,124],"25":[86,124],"34":[86,124],"35":[86,124],"39":[86,124],"41":[86,124],"45":[86,124],"46":[86,124],"53":[144,86,124],"60":[86,124],"63":[86,124],"65":[86,124],"81":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useBuilderSetupCards.ts":{"10":[144,86,124],"21":[144,86,124],"26":[144,86,124],"30":[144,86,124],"45":[144,86,124],"59":[144,86,124],"60":[144,86,124],"65":[144,86,124],"67":[144,86,124],"71":[144,86,124],"74":[144,86,124],"77":[144,86,124],"80":[86,124],"89":[144,86,124],"90":[144,86,124],"104":[144,86,124],"110":[144,86,124],"116":[86,124],"120":[86,124],"135":[86,124],"145":[86,124],"157":[144,86,124]},"packages/frontend/editor-ui/src/features/credentials/composables/useCredentialTestInBackground.ts":{"4":[144,86,16,124,33,34],"11":[144,86,124],"20":[144,86,124],"84":[86,124,34]},"packages/frontend/editor-ui/src/features/setupPanel/components/TriggerExecuteButton.vue":{"6":[144,86,124],"18":[144,86,124],"20":[86,124],"22":[144,86,124],"27":[86,124],"28":[86,124],"30":[144,86,124]},"packages/frontend/editor-ui/src/features/setupPanel/components/cards/SetupCardBody.vue":{"22":[144,86,124],"57":[144,86,124],"61":[144,86,124],"63":[144,86,124],"70":[144,86,124],"77":[144,86,124],"94":[144,86,124],"97":[144,86,124],"106":[144,86,124],"110":[144,86,124],"111":[144,86,124],"113":[144,86,124],"114":[86,124],"116":[86,124],"124":[144,86,124],"135":[144,86,124],"136":[144,86,124],"139":[86,124],"143":[144,86,124],"164":[86,124],"183":[144,86,124],"197":[144,86,124],"198":[86,124],"200":[144,86,124],"206":[144,86,124],"247":[86,124]},"packages/frontend/editor-ui/src/features/setupPanel/components/cards/SetupCardSection.vue":{"9":[144,86,124],"13":[144,86,124],"16":[144,86,124]},"packages/frontend/editor-ui/src/features/setupPanel/composables/groupSetupCards.ts":{"20":[144,86,124],"51":[86,124],"81":[144,86,124],"111":[86,124],"116":[86,124],"178":[86,124]},"packages/frontend/editor-ui/src/features/setupPanel/composables/useTriggerExecution.ts":{"18":[144,86,124],"38":[144,86,124],"40":[144,86,124],"46":[144,86,124],"57":[86,124],"70":[144,86,124],"77":[144,86,124],"81":[144,86,124],"87":[144,86,124],"91":[144,86,124]},"packages/frontend/editor-ui/src/features/setupPanel/composables/useWebhookUrls.ts":{"21":[144,86,124],"25":[144,86,124],"27":[144,86,124],"33":[144,86,124],"35":[144,86,124],"38":[86,124],"54":[86,124],"83":[144,86,124]},"packages/frontend/editor-ui/src/features/setupPanel/composables/useWorkflowSetupState.ts":{"50":[144,86,124],"67":[144,86,124],"74":[144,86,124],"92":[86,124],"121":[144,86,124],"124":[144,86,124],"160":[144,86,124],"168":[86,124],"173":[86,124],"198":[144,86,124],"226":[144,86,124],"231":[144,86,124],"235":[86,124],"254":[86,124],"297":[144,86,124],"299":[144,86,124],"300":[144,86,124],"306":[144,86,124],"330":[144,86,124],"353":[144,86,124],"354":[144,86,124],"361":[144,86,124],"362":[144,86,124],"365":[144,86,124],"366":[144,86,124],"376":[144,86,124],"390":[144,86,124],"404":[144,86,124],"417":[144,86,124],"420":[86,124],"434":[144,86,124],"435":[144,86,124],"437":[144,86,124],"441":[144,86,124],"449":[144,86,124],"468":[144,86,124],"471":[144,86,124],"477":[144,86,124],"478":[144,86,124],"486":[86,124],"513":[144,86,124],"554":[86,124],"622":[144,86,124],"638":[144,86,124],"641":[144,86,124],"656":[86,124],"664":[144,86,124],"665":[144,86,124],"667":[144,86,124],"669":[144,86,124],"682":[86,124],"683":[86,124],"686":[86,124],"690":[86,124],"691":[86,124],"700":[144,86,124],"703":[144,86,124],"705":[86,124],"707":[86,124],"709":[86,124],"714":[144,86,124],"718":[144,86,124],"730":[144,86,124],"775":[86,124],"800":[144,86,124],"803":[86,124],"811":[144,86,124],"837":[144,86,124],"868":[86,124],"882":[86,124]},"packages/frontend/editor-ui/src/features/setupPanel/setupPanel.utils.ts":{"8":[144,86,124,34],"27":[144,86,124],"65":[144,86,124],"118":[144,86,124],"151":[144,86,124],"242":[144,86,124],"282":[144,86,124],"298":[86,124],"301":[86,124],"308":[86,124],"314":[86,124],"315":[86,124],"325":[144,86,124],"328":[86,124],"333":[144,86,124]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/CanvasNodeChoicePrompt.vue":{"21":[144,86,146,11,124],"30":[144,86,146,11,124],"41":[144,86,146,11,124],"44":[144,86,146,11,124],"46":[144,86,146,11,124],"50":[86,124],"61":[86,124],"65":[144,86,146,11,124],"75":[86,124],"83":[144,86,146,11,124],"87":[144,86,146,11,124],"112":[86,124]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/useCanvasLayout.guards.ts":{"12":[144,86,124,185,197],"18":[144,86,124,185,197],"22":[144,86,124,185,197],"26":[144,86,124,185,197],"35":[86,124]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/components/ExperimentalEmbeddedNdvMapper.vue":{"19":[144,86,124,188,199],"39":[144,86,124,188,199],"43":[144,86,124,188,199],"45":[86,124,199],"54":[86,124,199],"67":[86,124],"80":[144,86,124,188,199],"87":[86,124,188,199],"96":[144,86,124,188,199],"111":[86,124,199]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/composables/useExpressionResolveCtx.ts":{"7":[144,86,124,188,199],"12":[144,86,124,188,199],"21":[144,86,124,188,199]},"packages/frontend/editor-ui/src/features/workflows/canvas/iconLuma.utils.ts":{"17":"b:AACAAAAAAQAAQEQAEAAAEAAAAQEQAAAAAAAKBAA=","25":"b:AACAAAAAAQAAQEQAEAAAEAAAAQEQAAAAAAAKBAA=","26":"b:AACAAAAAAQAAQEQAEAAAEAAAAQEQAAAAAAAKBAA=","34":"b:AACAAAAAAQAAQEQAEAAAEAAAAQEQAAAAAAAKBAA=","47":"b:AACAAAAAAQAAQEQAEAAAEAAAAQEQAAAAAAAKBAA=","68":"b:AACAAAAAAQAAQEQAEAAAEAAAAQEQAAAAAAAKBAA="},"packages/@n8n/ai-workflow-builder.ee/src/ai-workflow-builder-agent.service.ts":{"39":[146,11],"64":[146,11],"69":[146,11],"90":[146,11],"106":[146,11],"163":[146,11],"171":[146,11],"175":[146,11],"184":[146,11],"190":[146,11],"200":[146,11],"237":[146,11],"248":[146,11],"271":[146,11],"330":[146,11],"367":[146,11],"369":[146,11],"376":[146,11],"378":[146,11],"383":[146,11],"384":[146,11],"389":[146,11],"404":[146,11],"427":[146,11],"433":[146,11],"451":[146,11],"470":[146,11],"486":[146,11],"505":[146,11],"545":[146,11]},"packages/@n8n/ai-workflow-builder.ee/src/session-manager.service.ts":{"36":[146,11],"54":[146,11],"62":[146,11],"72":[146,11],"83":[146,11],"87":[146,11],"96":[146,11],"104":[146,11],"118":[146,11],"132":[146,11],"160":[146,11],"166":[146,11],"174":[146,11],"180":[146,11],"185":[146,11],"200":[146,11],"222":[146,11],"270":[146,11],"275":[146,11],"279":[146,11],"283":[146,11],"300":[146,11],"312":[146,11],"335":[146,11],"363":[146,11],"378":[146,11],"427":[146,11],"440":[146,11],"532":[146,11],"564":[146,11],"583":[146,11],"666":[146,11],"674":[146,11]},"packages/@n8n/ai-workflow-builder.ee/src/tools/utils/ssrf-guard.ts":{"27":[146,11],"37":[146,11],"39":[146,11],"40":[146,11],"42":[146,11],"52":[146,11],"62":[146,11]},"packages/cli/src/controllers/ai.controller.ts":{"45":[146,11],"54":[146,11],"70":[146,11],"87":[146,11],"96":[146,11],"170":[146,11],"175":[146,11],"184":[146,11],"205":[146,11],"224":[146,11],"238":[146,11],"248":[146,11],"267":[146,11],"278":[146,11],"289":[146,11],"304":[146,11],"317":[146,11],"337":[146,11],"352":[146,11]},"packages/@n8n/blob-storage/src/fs-byte-store.ts":{"20":[4,101,223,103,18,21,136,138],"22":[4,101,223,103,18,21,136,138],"26":[4,101,223,103,18,21,136,138],"41":[4,101,223,103,18,21,136,138],"46":[4,101,223,103,18,21,136,138],"56":[4,101,223,103,18,21,136,138],"69":[4,101,223,103,18,21,136,138],"74":[4,101,223,103,18,21,136,138],"80":[4,101,223,103,18,21,136,138],"87":[4,101,223,103,18,21,136,138],"95":[4,101,223,103,18,21,136,138],"96":[4,101,223,103,18,21,136,138],"97":[4,101,223,103,18,21,136,138],"98":[4,101,223,103,18,21,136,138],"99":[4,101,223,103,18,21,136,138],"103":[4,101,223,103,18,21,136,138],"119":[4,101,223,103,18,21,136,138],"132":[4,101,223,103,18,21,136,138]},"packages/core/src/binary-data/binary-data.service.ts":{"26":"b:EAAkAAAAAAAAAAAAoACAAAAFAAAAAAAAAAAwgAI=","32":"b:EAAkAAAAAAAAAAAAoACAAAAFAAAAAAAAAAAwgAI=","36":"b:EAAkAAAAAAAAAAAAoACAAAAFAAAAAAAAAAAwgAI=","43":"b:EAAkAAAAAAAAAAAAoACAAAAFAAAAAAAAAAAwgAI=","52":"b:EAAkAAAAAAAAAAAAoACAAAAFAAAAAAAAAAAwgAI=","65":"b:EAAkAAAAAAAAAAAAoACAAAAFAAAAAAAAAAAwgAI=","71":"b:EAAkAAAAAAAAAAAAoACAAAAFAAAAAAAAAAAwgAI=","102":"b:EAAkAAAAAAAAAAAAoACAAAAFAAAAAAAAAAAwgAI=","133":"b:EAAkAAAAAAAAAAAAoACAAAAFAAAAAAAAAAAwgAI=","139":"b:EAAkAAAAAAAAAAAAoACAAAAFAAAAAAAAAAAwgAI=","149":"b:EAAkAAAAAAAAAAAAoACAAAAFAAAAAAAAAAAwgAI=","155":"b:EAAkAAAAAAAAAAAAoACAAAAFAAAAAAAAAAAwgAI=","161":"b:EAAkAAAAAAAAAAAAoACAAAAFAAAAAAAAAAAwgAI=","169":"b:EAAkAAAAAAAAAAAAoACAAAAFAAAAAAAAAAAwgAI=","198":"b:EAAkAAAAAAAAAAAAoACAAAAFAAAAAAAAAAAwgAI=","204":"b:EAAkAAAAAAAAAAAAoACAAAAFAAAAAAAAAAAwgAI=","207":"b:EAAkAAAAAAAAAAAAoACAAAAFAAAAAAAAAAAwgAI=","227":"b:EAAkAAAAAAAAAAAAoACAAAAFAAAAAAAAAAAwgAI=","239":"b:EAAkAAAAAAAAAAAAoACAAAAFAAAAAAAAAAAwgAI=","243":"b:EAAkAAAAAAAAAAAAoACAAAAFAAAAAAAAAAAwgAI=","251":"b:EAAkAAAAAAAAAAAAoACAAAAFAAAAAAAAAAAwgAI=","263":"b:EAAkAAAAAAAAAAAAoACAAAAFAAAAAAAAAAAwgAI=","269":"b:EAAkAAAAAAAAAAAAoACAAAAFAAAAAAAAAAAwgAI=","270":"b:EAAkAAAAAAAAAAAAoACAAAAFAAAAAAAAAAAwgAI=","283":"b:EAAkAAAAAAAAAAAAoACAAAAFAAAAAAAAAAAwgAI="},"packages/core/src/binary-data/blob.manager.ts":{"21":[4,101,223,103,18,21,136,138],"39":[4,101,223,103,18,21,136,138],"44":[4,101,223,103,18,21,136,138],"48":[4,101,223,103,18,21,136,138],"59":[4,101,223,103,18,21,136,138],"63":[4,101,223,103,18,21,136,138],"69":[4,101,223,103,18,21,136,138],"75":[4,101,223,103,18,21,136,138],"87":[4,101,223,103,18,21,136,138],"93":[4,101,223,103,18,21,136,138],"94":[4,101,223,103,18,21,136,138],"112":[4,101,223,103,18,21,136,138],"130":[4,101,223,103,18,21,136,138],"142":[4,101,223,103,18,21,136,138],"151":[4,101,223,103,18,21,136,138],"155":[4,101,223,103,18,21,136,138],"168":[4,101,223,103,18,21,136,138],"185":[4,101,223,103,18,21,136,138],"186":[4,101,223,103,18,21,136,138],"191":[4,101,223,103,18,21,136,138],"196":[4,101,223,103,18,21,136,138],"199":[4,101,223,103,18,21,136,138],"204":[4,101,223,103,18,21,136,138],"214":[4,101,223,103,18,21,136,138],"219":[4,101,223,103,18,21,136,138]},"packages/core/src/execution-engine/node-execution-context/utils/webhook-helper-functions.ts":{"13":"b:ANAABACAACABAAgAkAmACAADAEAAEAAAAAAAgAA=","33":"b:ANAABACAACABAAgAkAmACAADAEAAEAAAAAAAgAA="},"packages/nodes-base/nodes/Files/ConvertToFile/ConvertToFile.node.ts":{"107":[223,173,138]},"packages/nodes-base/nodes/Files/ConvertToFile/actions/iCall.operation.ts":{"16":[223,173,138]},"packages/nodes-base/nodes/Files/ConvertToFile/actions/spreadsheet.operation.ts":{"94":[223,173,138]},"packages/nodes-base/nodes/Files/ConvertToFile/actions/toBinary.operation.ts":{"105":[223,173,138]},"packages/nodes-base/nodes/Files/ConvertToFile/actions/toJson.operation.ts":{"90":[223,173,138],"102":[223,173,138]},"packages/nodes-base/nodes/Files/ConvertToFile/actions/toText.operation.ts":{"78":[223,173,138]},"packages/nodes-base/nodes/Files/ExtractFromFile/ExtractFromFile.node.ts":{"117":[223,170]},"packages/nodes-base/nodes/Files/ExtractFromFile/actions/moveTo.operation.ts":{"106":[223,170]},"packages/nodes-base/nodes/Files/ExtractFromFile/actions/parseIcsCalendar.ts":{"4":[223,170]},"packages/nodes-base/nodes/Files/ExtractFromFile/actions/pdf.operation.ts":{"83":[223,170]},"packages/nodes-base/nodes/Files/ExtractFromFile/actions/spreadsheet.operation.ts":{"8":[223,170],"9":[223,170],"18":[223,170],"58":[223,170]},"packages/nodes-base/nodes/ICalendar/createEvent.operation.ts":{"275":[223,173,138]},"packages/nodes-base/nodes/RespondToWebhook/RespondToWebhook.node.ts":{"359":[223,224,103,173,227,80],"367":[223,224,103,173,227,80],"391":[223,224,103,173,227,80],"471":[223,224,103,173,227,80],"537":[223,224,103,173,227,80]},"packages/nodes-base/nodes/RespondToWebhook/utils/binary.ts":{"5":[223,224,227,80],"16":[223,224,227,80]},"packages/nodes-base/nodes/RespondToWebhook/utils/outputs.ts":{"1":[223,224,227,80]},"packages/nodes-base/nodes/SpreadsheetFile/v2/fromFile.operation.ts":{"86":[223,170],"127":[223,170],"130":[223,170],"137":[223,170],"145":[223,170],"155":[223,170]},"packages/nodes-base/utils/binary.ts":{"37":[223,40,170,173,138],"87":[223,40,170,173,138],"139":[223,40,170,173,138],"155":[223,40,170,173,138],"189":[223,40,170,173,138],"218":[223,40,170,173,138],"221":[223,40,170,173,138],"230":[223,40,170,173,138],"233":[223,40,170,173,138]},"packages/@n8n/api-types/src/dto/project/list-projects-query.dto.ts":{"13":"b:AAAAAgAwABAAAEIICABAEjAAACAAAAAADAAAAAA=","14":"b:AAAAAgAwABAAAEIICABAEjAAACAAAAAADAAAAAA=","17":"b:AAAAAgAwABAAAEIICABAEjAAACAAAAAADAAAAAA=","26":"b:AAAAAgAwABAAAEIICABAEjAAACAAAAAADAAAAAA=","34":"b:AAAAAgAwABAAAEIICABAEjAAACAAAAAADAAAAAA=","35":"b:AAAAAgAwABAAAEIICABAEjAAACAAAAAADAAAAAA=","38":"b:AAAAAgAwABAAAEIICABAEjAAACAAAAAADAAAAAA=","41":"b:AAAAAgAwABAAAEIICABAEjAAACAAAAAADAAAAAA="},"packages/@n8n/db/src/entities/credentials-entity.ts":{"88":[222,23,132]},"packages/cli/src/modules/agents/repositories/agent-credential-dependency.repository.ts":{"17":[1,83,23,91,44,45,195,132,133],"24":[1,83,23,91,44,45,195,132,133],"25":[1,83,23,91,44,45,195,132,133],"70":[1,83,23,91,44,45,195,132,133],"71":[1,83,23,91,44,45,195,132,133],"79":[1,83,23,91,44,45,195,132,133],"83":[1,83,23,91,44,45,195,132,133],"94":[1,83,23,91,44,45,195,132,133],"108":[1,83,23,91,44,45,195,132,133]},"packages/@n8n/agents/src/runtime/loop/generate-sink.ts":{"27":[34],"30":[34],"32":[34],"46":[34],"67":[34],"74":[34],"81":[34],"89":[34],"93":[34],"104":[34]},"packages/@n8n/ai-utilities/src/llm-output/extract-json.ts":{"4":[34],"10":[34],"30":[34],"42":[34],"64":[34]},"packages/@n8n/instance-ai/src/tools/workflows/credential-utils.ts":{"35":[34],"46":[34],"62":[34],"95":[34],"109":[34],"114":[34],"118":[34],"136":[34]},"packages/@n8n/instance-ai/src/utils/parse-model-headers.ts":{"5":[34]},"packages/@n8n/workflow-sdk/src/mock-data/data-table-read.ts":{"39":[34],"48":[34],"69":[34],"76":[34]},"packages/@n8n/workflow-sdk/src/mock-data/date-anchors.ts":{"15":[34],"25":[34]},"packages/@n8n/workflow-sdk/src/mock-data/parse.ts":{"10":[34],"31":[34],"43":[34],"50":[34],"54":[34],"58":[34],"84":[34],"90":[34],"116":[34]},"packages/@n8n/workflow-sdk/src/mock-data/prompt.ts":{"29":[34],"76":[34],"112":[34]},"packages/core/src/nodes-loader/output-schema-resolver.ts":{"53":"b:AAAAAAQAAAAACAAAAgAAAAAQAAAAEAUIADQEAAA=","61":"b:AAAAAAQAAAAACAAAAgAAAAAQAAAAEAUIADQEAAA=","65":"b:AAAAAAQAAAAACAAAAgAAAAAQAAAAEAUIADQEAAA=","81":"b:AAAAAAQAAAAACAAAAgAAAAAQAAAAEAUIADQEAAA=","82":"b:AAAAAAQAAAAACAAAAgAAAAAQAAAAEAUIADQEAAA=","83":"b:AAAAAAQAAAAACAAAAgAAAAAQAAAAEAUIADQEAAA=","85":"b:AAAAAAQAAAAACAAAAgAAAAAQAAAAEAUIADQEAAA=","88":"b:AAAAAAQAAAAACAAAAgAAAAAQAAAAEAUIADQEAAA=","90":"b:AAAAAAQAAAAACAAAAgAAAAAQAAAAEAUIADQEAAA=","91":"b:AAAAAAQAAAAACAAAAgAAAAAQAAAAEAUIADQEAAA=","92":"b:AAAAAAQAAAAACAAAAgAAAAAQAAAAEAUIADQEAAA=","93":"b:AAAAAAQAAAAACAAAAgAAAAAQAAAAEAUIADQEAAA=","94":"b:AAAAAAQAAAAACAAAAgAAAAAQAAAAEAUIADQEAAA=","109":"b:AAAAAAQAAAAACAAAAgAAAAAQAAAAEAUIADQEAAA=","114":"b:AAAAAAQAAAAACAAAAgAAAAAQAAAAEAUIADQEAAA=","116":"b:AAAAAAQAAAAACAAAAgAAAAAQAAAAEAUIADQEAAA=","127":"b:AAAAAAQAAAAACAAAAgAAAAAQAAAAEAUIADQEAAA=","160":"b:AAAAAAQAAAAACAAAAgAAAAAQAAAAEAUIADQEAAA="},"localhost-36439/assets/index-BoK1c_f3.js":{"3":[34]},"localhost-36439/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[34],"9":[34],"10":[34],"19":[34],"23":[34],"29":[34],"33":[34],"34":[34]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/ConfirmationFooter.vue":{"15":[34]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/InstanceAiWorkflowSetup.vue":{"9":[34]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/components/WorkflowSetupCard.vue":{"14":[34],"23":[34],"25":[34],"26":[34],"28":[34],"32":[34],"36":[34],"55":[34],"67":[34]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/components/WorkflowSetupSectionBody.vue":{"29":[34],"38":[34],"40":[34],"46":[34],"61":[34],"68":[34],"79":[34],"83":[34],"102":[34],"106":[34],"109":[34],"112":[34],"136":[34],"143":[34],"145":[34],"157":[34],"166":[34],"170":[34],"173":[34],"198":[34],"221":[34]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/components/WorkflowSetupWizard.vue":{"6":[34],"15":[34]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/components/WorkflowSetupWizardFooter.vue":{"8":[34],"11":[34],"12":[34],"17":[34],"22":[34],"29":[34],"39":[34],"41":[34],"43":[34],"49":[34],"59":[34],"72":[34],"89":[34],"118":[34]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/composables/useWorkflowSetupActions.ts":{"31":[34],"61":[34],"74":[34]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/composables/useWorkflowSetupApply.ts":{"13":[34]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/composables/useWorkflowSetupBootstrap.ts":{"5":[34],"14":[34]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/composables/useWorkflowSetupContext.ts":{"62":[34],"67":[34],"83":[34],"87":[34],"88":[34],"89":[34],"133":[34],"142":[34],"179":[34]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/composables/useWorkflowSetupInputs.ts":{"15":[34],"77":[34],"89":[34],"96":[34],"102":[34],"128":[34],"141":[34],"145":[34],"149":[34],"220":[34],"245":[34],"254":[34],"257":[34],"268":[34],"271":[34]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/composables/useWorkflowSetupSections.ts":{"11":[34],"16":[34],"21":[34],"75":[34],"98":[34],"123":[34]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/composables/useWorkflowSetupTelemetry.ts":{"46":[34],"62":[34],"75":[34],"79":[34],"85":[34],"91":[34],"190":[34],"204":[34],"211":[34],"229":[34],"234":[34]},"packages/frontend/editor-ui/src/features/ai/instanceAi/workflowSetup/workflowSetup.helpers.ts":{"2":[34]},"packages/@n8n/backend-services/src/services/project-scope.service.ts":{"13":[163],"18":[163],"24":[163]},"packages/@n8n/db/src/utils/apply-workflow-boolean-setting-filter.ts":{"12":[163]},"packages/@n8n/db/src/utils/list-query-sort.ts":{"8":"b:AAABgwA4AIgAgAInCAAAAgBAgAAMAAAABAgAAAA="},"packages/cli/src/middlewares/list-query/dtos/pagination.dto.ts":{"6":"b:AAABgwA4AIgAgAIjCAAAAgBAgAAMAAAABAgAAAA=","15":"b:AAABgwA4AIgAgAIjCAAAAgBAgAAMAAAABAgAAAA="},"packages/cli/src/middlewares/list-query/dtos/workflow.sort-by.dto.ts":{"6":"b:AAABgwA4AIgAgAIjCAAAAgBAgAAMAAAABAgAAAA=","13":"b:AAABgwA4AIgAgAIjCAAAAgBAgAAMAAAABAgAAAA="},"packages/cli/src/modules/agents/agent-mcp-access.controller.ts":{"19":[163],"22":[163],"27":[163]},"packages/cli/src/modules/agents/agent-mcp-access.service.ts":{"29":[163],"39":[163],"54":[163],"60":[163],"76":[163],"78":[163],"80":[163],"110":[163],"111":[163],"117":[163]},"packages/cli/src/modules/oauth-server/database/repositories/oauth-user-consent.repository.ts":{"42":[163],"53":[163],"96":[163],"114":[163]},"packages/cli/src/modules/oauth-server/oauth-clients.controller.ts":{"21":[163],"32":[163],"49":[163],"78":[163],"90":[163]},"packages/frontend/@n8n/design-system/src/components/N8nAlertDialog/AlertDialog.vue":{"74":[86,22,124,163,47],"83":[86,124],"87":[86,124,47],"91":[86,124],"94":[86,22,124,163,47],"99":[86,22,124,163,47],"102":[86,124,47],"103":[86,124,47]},"packages/frontend/@n8n/design-system/src/components/N8nDialog/DialogDescription.vue":{"15":[86,124,163,47,63],"16":[86,124,163,47,63]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/arrow-to-bracket-right--outline-16.svg":{"9":"b:AABAAACAANwAAEAAAAAsEACAACAIAACABgAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/binoculars--outline-16.svg":{"9":"b:AABAAACgANwAAEAAAAAsEACAACAIAACABgAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/clipboard--outline-16.svg":{"9":"b:AABAAACAANwAAEAAAAAsEACAACAIAACABgAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/people--outline-16.svg":{"9":"b:AABQAACAANwAAEAAAAAsEACAACAIAACABgAAAQA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/plug--outline-16.svg":{"9":"b:AAAAAACAANwAAEAAAAAsEACAACAIAACABgAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/shield--outline-16.svg":{"9":"b:AABAAACgANwAAEAAAAAsEACAACAIAACABgAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/vault--outline-16.svg":{"9":"b:AABAAACAANwAAEAAAAAsEACAACAIAACABgAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nSettingsLayout/SettingsLayout.vue":{"28":[86,143,22,124,163,47,193,63],"29":[86,143,22,124,163,47,193,63],"33":[86,143,22,124,163,47,193,63],"40":[86,124],"42":[86,124],"44":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nSettingsPageHeader/SettingsPageHeader.vue":{"29":[86,143,22,124,163,47,193,63],"40":[86,143,22,124,163,47,193,63],"41":[86,143,22,124,163,47,193,63],"60":[86,124],"65":[86,143,22,124,163,47,193,63],"69":[86,143,124,163,47,193,63]},"packages/frontend/@n8n/design-system/src/components/N8nSettingsRow/SettingsRow.vue":{"67":[86,143,124,33,163,47,193,63],"107":[86,143,124,33,163,47,193,63],"112":[86,124],"116":[86,124],"120":[86,124],"125":[86,143,124,33,163,47,193,63],"133":[86,143,124,33,163,47,193,63],"138":[86,143,124,33,163,47,193,63],"151":[86,143,124,33,163,47,193,63],"157":[86,143,124,33,163,47,193,63],"159":[86,143,124,33,163,47,193,63],"166":[86,143,124,33,163,47,193,63],"174":[86,124],"183":[86,124,163,47,63],"189":[86,124,193,63],"201":[86,143,124,33,163,47,193,63],"236":[86,143,124,33,163,47,193,63],"244":[86,143,124,33,163,193,63],"251":[86,143,124,163,193,63],"268":[86,124,163,47,63],"279":[86,124],"285":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nSettingsRowConfigure/SettingsRowConfigure.vue":{"22":[86,124,33,163],"23":[86,124,33,163]},"packages/frontend/@n8n/design-system/src/components/N8nSettingsRowGroup/SettingsRowGroup.vue":{"15":[86,143,124,33,163,47,193,63],"16":[86,143,124,163,47,193,63]},"packages/frontend/@n8n/design-system/src/components/N8nSettingsSection/SettingsSection.vue":{"18":[86,143,124,163,47,193,63],"26":[86,143,124,163,47,193,63],"29":[86,143,124,163,47,193,63],"36":[86,143,124,163,47,193,63],"41":[86,124]},"packages/frontend/editor-ui/src/app/components/SettingsSidebar.vue":{"23":"b:AABAAACAANwAAAAAAAAsAACAACAIAACABgAAAAA=","26":"b:AABAAACAANwAAAAAAAAsAACAACAIAACABgAAAAA=","38":"b:AABAAACAANwAAAAAAAAsAACAACAIAACABgAAAAA=","46":"b:AABAAACAANwAAAAAAAAsAACAACAIAACABgAAAAA="},"packages/frontend/editor-ui/src/app/layouts/SettingsLayout.vue":{"27":"b:AABAAACAANwAAAAAAAAsAACAACAIAACABgAAAAA=","34":"b:AABAAACAANwAAAAAAAAsAACAACAIAACABgAAAAA=","36":"b:AABAAACAANwAAAAAAAAsAACAACAIAACABgAAAAA="},"packages/frontend/editor-ui/src/experiments/exposeAllWorkflowsToMcp/stores/exposeAllWorkflowsToMcp.store.ts":{"10":[86,124,163],"15":[86,124],"18":[86,124,163],"25":[86,124],"28":[86,124],"32":[86,124],"36":[86,124]},"packages/modules/mcp/frontend/src/SettingsMCPView.vue":{"56":[163],"58":[163],"64":[163],"65":[163],"88":[163],"100":[163],"111":[163],"120":[163],"129":[163],"138":[163],"185":[163],"195":[163],"198":[163],"205":[163],"210":[163],"242":[163],"266":[163],"318":[163],"324":[163],"337":[163],"352":[163],"360":[163],"388":[163],"401":[163],"409":[163],"434":[163]},"packages/modules/mcp/frontend/src/assets/client-icons/claude.svgcomponent":{"9":[86,124,163]},"packages/modules/mcp/frontend/src/components/ConnectionParameter.vue":{"16":[163],"33":[163],"72":[163]},"packages/modules/mcp/frontend/src/components/McpAllowedCallbackUrlsDialog.vue":{"24":[163],"44":[163],"60":[163],"111":[163]},"packages/modules/mcp/frontend/src/components/McpConnectClientDialog.vue":{"24":[163],"31":[163],"32":[163],"33":[163],"36":[163],"42":[163],"49":[163],"55":[163],"123":[163],"132":[163],"147":[163],"152":[163],"178":[163],"187":[163],"288":[163],"295":[163],"311":[163]},"packages/modules/mcp/frontend/src/components/McpStatusControl.vue":{"6":[163],"20":[163],"28":[163],"37":[163],"49":[163]},"packages/modules/mcp/frontend/src/components/OAuthClientDetailsModal.vue":{"22":[163],"61":[163]},"packages/modules/mcp/frontend/src/components/RevokeOAuthClientConfirmModal.vue":{"7":[163],"23":[163],"31":[163],"43":[163]},"packages/modules/mcp/frontend/src/composables/useMcp.ts":{"5":"b:BgAAAAC4AAAgAEIhHAAAEgAAAAAMQAAAAAgAAAA=","8":[86,124],"14":[86,124],"18":[86,124],"22":[86,124],"29":[86,124,163],"33":[86,124],"39":[86,124]},"packages/modules/mcp/frontend/src/mcp.api.ts":{"45":[86,124],"52":[86,124],"56":[86,124],"60":[86,124,163],"66":[86,124],"78":[86,124],"99":[86,124,163],"104":[86,124,163],"114":[86,124,163],"120":[86,124],"133":[86,124],"156":[86,124,163],"173":[86,124],"184":[86,124,163]},"packages/modules/mcp/frontend/src/mcp.clients.catalog.ts":{"44":[163]},"packages/@n8n/errors/src/unexpected.error.ts":{"15":"b:UAQAAADAAAgAAkAAoRAAMMETAAAAAAAAAAAEAAA="},"packages/cli/src/eventbus/event-message-classes/event-message-runner.ts":{"23":"b:UAQAAADAAAAAAgAAoRAAIMETAAAAAAAAAAAEAAA=","31":"b:UAQAAADAAAAAAgAAoRAAIMETAAAAAAAAAAAEAAA="},"packages/cli/src/task-runners/default-task-runner-disconnect-analyzer.ts":{"18":"b:UAQAAADAAAAAAgAAoRAAIMETAAAAAAAAAAAEAAA=","22":"b:UAQAAADAAAAAAgAAoRAAIMETAAAAAAAAAAAEAAA="},"packages/cli/src/task-runners/errors/task-runner-disconnected-error.ts":{"7":"b:UAQAAADAAAAAAgAAoRAAIMETAAAAAAAAAAAEAAA=","27":"b:UAQAAADAAAAAAgAAoRAAIMETAAAAAAAAAAAEAAA="},"packages/cli/src/task-runners/task-broker/errors/task-deferred.error.ts":{"4":"b:UAQAAADAAAAAAgAAoRAAIMETAAAAAAAAAAAEAAA="},"packages/cli/src/task-runners/task-broker/task-broker.service.ts":{"135":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","152":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","158":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","174":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","175":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","184":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","185":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","204":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","212":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","214":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","217":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","218":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","226":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","228":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","238":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","241":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","247":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","266":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","268":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","269":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","272":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","278":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","282":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","286":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","290":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","294":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","348":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","367":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","376":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","385":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","394":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","411":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","428":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","445":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","482":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","499":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","511":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","527":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","538":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","551":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","562":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","574":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","587":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","608":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","617":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","628":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","667":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","679":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","691":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","696":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","703":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","761":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","776":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","782":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","824":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","837":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","868":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","874":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","875":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","876":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","910":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","928":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","932":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","933":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","936":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","950":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","958":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","973":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","977":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","984":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","998":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","1003":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","1007":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","1017":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","1029":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","1046":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","1061":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","1065":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","1069":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","1073":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","1077":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","1081":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","1085":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","1089":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","1093":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","1097":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","1101":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI=","1105":"b:UAQAAADAAAAAAwAAoRAAIMETAAAAABAAAACEAAI="},"packages/cli/src/task-runners/task-managers/data-request-response-builder.ts":{"17":"b:UAQAAADAAAAAAgAAoRAAIMETAAAAAAAAAAAEAAA=","37":"b:UAQAAADAAAAAAgAAoRAAIMETAAAAAAAAAAAEAAA=","57":"b:UAQAAADAAAAAAgAAoRAAIMETAAAAAAAAAAAEAAA=","70":"b:UAQAAADAAAAAAgAAoRAAIMETAAAAAAAAAAAEAAA="},"packages/cli/src/task-runners/task-managers/data-request-response-stripper.ts":{"18":"b:UAQAAADAAAAAAwAAoRAAIMMTAAAAAAAAAAAEAAA=","32":"b:UAQAAADAAAAAAwAAoRAAIMMTAAAAAAAAAAAEAAA=","43":"b:UAQAAADAAAAAAwAAoRAAIMMTAAAAAAAAAAAEAAA=","64":"b:UAQAAADAAAAAAwAAoRAAIMMTAAAAAAAAAAAEAAA=","68":"b:UAQAAADAAAAAAwAAoRAAIMMTAAAAAAAAAAAEAAA=","72":"b:UAQAAADAAAAAAwAAoRAAIMMTAAAAAAAAAAAEAAA=","86":"b:UAQAAADAAAAAAwAAoRAAIMMTAAAAAAAAAAAEAAA=","94":"b:UAQAAADAAAAAAwAAoRAAIMMTAAAAAAAAAAAEAAA=","118":"b:UAQAAADAAAAAAwAAoRAAIMMTAAAAAAAAAAAEAAA=","138":"b:UAQAAADAAAAAAwAAoRAAIMMTAAAAAAAAAAAEAAA="},"packages/cli/src/task-runners/task-managers/local-task-requester.ts":{"18":"b:UAQAAADAAAAAAgAAoRAAIMETAAAAAAAAAAAEAAA=","29":"b:UAQAAADAAAAAAgAAoRAAIMETAAAAAAAAAAAEAAA=","35":"b:UAQAAADAAAAAAgAAoRAAIMETAAAAAAAAAAAEAAA=","36":"b:UAQAAADAAAAAAgAAoRAAIMETAAAAAAAAAAAEAAA="},"packages/cli/src/task-runners/task-managers/task-requester.ts":{"73":"b:UAQAAADAAAAAAwgAoRAAIMETAAAAABAAAACEAAI=","81":"b:UAQAAADAAAAAAwgAoRAAIMETAAAAABAAAACEAAI=","85":"b:UAQAAADAAAAAAwgAoRAAIMETAAAAABAAAACEAAI=","90":"b:UAQAAADAAAAAAwgAoRAAIMETAAAAABAAAACEAAI=","138":"b:UAQAAADAAAAAAwgAoRAAIMETAAAAABAAAACEAAI=","175":"b:UAQAAADAAAAAAwgAoRAAIMETAAAAABAAAACEAAI=","199":"b:UAQAAADAAAAAAwgAoRAAIMETAAAAABAAAACEAAI=","221":"b:UAQAAADAAAAAAwgAoRAAIMETAAAAABAAAACEAAI=","227":"b:UAQAAADAAAAAAwgAoRAAIMETAAAAABAAAACEAAI=","231":"b:UAQAAADAAAAAAwgAoRAAIMETAAAAABAAAACEAAI=","250":"b:UAQAAADAAAAAAwgAoRAAIMETAAAAABAAAACEAAI=","262":"b:UAQAAADAAAAAAwgAoRAAIMETAAAAABAAAACEAAI=","264":"b:UAQAAADAAAAAAwgAoRAAIMETAAAAABAAAACEAAI=","290":"b:UAQAAADAAAAAAwgAoRAAIMETAAAAABAAAACEAAI=","304":"b:UAQAAADAAAAAAwgAoRAAIMETAAAAABAAAACEAAI=","331":"b:UAQAAADAAAAAAwgAoRAAIMETAAAAABAAAACEAAI=","339":"b:UAQAAADAAAAAAwgAoRAAIMETAAAAABAAAACEAAI=","347":"b:UAQAAADAAAAAAwgAoRAAIMETAAAAABAAAACEAAI=","355":"b:UAQAAADAAAAAAwgAoRAAIMETAAAAABAAAACEAAI=","381":"b:UAQAAADAAAAAAwgAoRAAIMETAAAAABAAAACEAAI=","396":"b:UAQAAADAAAAAAwgAoRAAIMETAAAAABAAAACEAAI="},"packages/core/src/execution-engine/node-execution-context/utils/normalize-items.ts":{"10":"b:EAQAAADAAAAAAwAAoRAAAMETAAAAAgAAAAAGAAA=","17":"b:EAQAAADAAAAAAwAAoRAAAMETAAAAAgAAAAAGAAA=","20":"b:EAQAAADAAAAAAwAAoRAAAMETAAAAAgAAAAAGAAA=","24":"b:EAQAAADAAAAAAwAAoRAAAMETAAAAAgAAAAAGAAA=","26":"b:EAQAAADAAAAAAwAAoRAAAMETAAAAAgAAAAAGAAA=","27":"b:EAQAAADAAAAAAwAAoRAAAMETAAAAAgAAAAAGAAA=","40":"b:EAQAAADAAAAAAwAAoRAAAMETAAAAAgAAAAAGAAA=","44":"b:EAQAAADAAAAAAwAAoRAAAMETAAAAAgAAAAAGAAA="},"packages/nodes-base/nodes/Code/Code.node.ts":{"24":"b:cAQAAADAAABEAgQAoRAAAMETAAAAAAAIAAgEAAA=","196":"b:cAQAAADAAABEAgQAoRAAAMETAAAAAAAIAAgEAAA="},"packages/nodes-base/nodes/Code/python-runner-unavailable.error.ts":{"11":"b:cAQAAADAAABEAgQAIRAAAMETAAAAAAAIAAgAAAA="},"localhost-44031/assets/index-BoK1c_f3.js":{"3":[73]},"localhost-44031/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[73],"9":[73],"10":[73],"19":[73],"23":[73],"29":[73],"33":[73],"34":[73]},"packages/@n8n/api-types/src/dto/executions/compare-execution-list-items.ts":{"3":[86,124,72,73,137,215,216,217],"26":[86,124,72,73,137,215,216,217]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/composables/useAddExecutionToDataset.ts":{"15":[47,72,136,73,137,215,216,217]},"packages/frontend/editor-ui/src/features/execution/executions/components/workflow/ExecutionPreviewHost.vue":{"18":[47,72,136,73,137,215,216,217],"33":[47,72,136,73,137,215,216,217],"36":[47,72,136,73,137,215,216,217],"44":[47,72,136,73,137,215,216,217],"56":[47,72,136,73,137,215,216,217],"57":[47,72,136,73,137,215,216,217],"58":[47,72,136,73,137,215,216,217],"60":[47,72,136,73,137,215,216,217],"71":[47,72,136,73,137,215,216,217],"110":[47,72,136,73,137,215,216,217],"111":[47,72,136,73,137,215,216,217],"113":[72,136,216,217],"116":[47,72,136,73,137,215,216,217]},"packages/frontend/editor-ui/src/features/execution/executions/components/workflow/WorkflowExecutionsCard.vue":{"41":[47,72,136,73,137,215,216,217],"44":[47,72,136,73,137,215,216,217],"48":[47,72,136,73,137,215,216,217],"49":[72,215,216],"61":[47,72,136,73,137,215,216,217],"64":[47,72,136,73,137,215,216,217],"65":[47,72,136,73,137,215,216,217],"67":[47,72,136,73,137,215,216,217],"73":[47,72,136,73,137,215,216,217],"108":[47,72,136,73,137,215,216,217],"141":[47,72,136,73,137,215,216,217],"193":[47,72,136,73,137,215,216,217]},"packages/frontend/editor-ui/src/features/execution/executions/components/workflow/WorkflowExecutionsPreview.vue":{"55":[47,72,136,73,137,215,216,217],"59":[47,72,136,73,137,215,216,217],"63":[47,72,136,73,137,215,216,217],"64":[47,72,136,73,137,215,216,217],"65":[47,72,136,73,137,215,216,217],"68":[47,72,136,73,137,215,216,217],"79":[47,72,136,73,137,215,216,217],"85":[47,72,136,73,137,215,216,217],"93":[47,72,136,73,137,215,216,217],"102":[47,72,136,73,137,215,216,217],"126":[47,72,136,73,137,215,216,217],"130":[136],"141":[47,72,136,73,137,215,216,217],"147":[47,72,136,73,137,215,216,217],"157":[47,72,136,73,137,215,216,217],"169":[47,72,136,73,137,215,216,217],"191":[47,72,136,73,137,215,216,217],"197":[47,72,136,73,137,215,216,217],"199":[47,72,136,73,137,215,216,217],"226":[136],"317":[47,72,136,73,137,215,216,217],"337":[47,72,136,73,137,215,216,217],"368":[47,72,136,73,137,215,216,217],"380":[47,72,136,73,137,215,216,217],"415":[47,72,136,73,137,215,216,217],"430":[47,72,136,73,137,215,216,217],"433":[72],"459":[72,215],"462":[72,215],"465":[72,215]},"packages/frontend/editor-ui/src/features/execution/executions/composables/useExecutionPreviewDocument.ts":{"59":[47,72,136,73,137,215,216,217],"106":[47,72,136,73,137,215,216,217],"118":[47,72,136,73,137,215,216,217],"147":[47,72,136,73,137,215,216,217],"175":[72,215,216],"187":[72],"193":[47,72,136,73,137,215,216,217],"232":[216],"233":[216],"323":[47,72,136,73,137,215,216,217],"339":[72,136,216,217]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/parts/CanvasNodeDisabledStrikeThrough.vue":{"6":"b:AAAAAAAAAABgA0EAAAAAEEACAAAAAAAAAAKAAwA=","10":"b:AAAAAAAAAABgA0EAAAAAEEACAAAAAAAAAAKAAwA=","19":"b:AAAAAAAAAABgA0EAAAAAEEACAAAAAAAAAAKAAwA="},"packages/nodes-base/nodes/HttpRequest/GenericFunctions.ts":{"31":[8,122,154,23,91,109,26,41,70,72,74,139,97],"42":[8,122,154,23,91,109,26,41,70,72,74,139,97],"56":[8,122,154,23,91,109,26,41,70,72,74,139,97],"71":[8,122,154,23,91,109,26,41,70,72,74,139,97],"80":[8,122,154,23,91,109,26,41,70,72,74,139,97],"81":[8,122,154,23,91,109,26,41,70,72,74,139,97],"84":[8,122,154,23,91,109,26,41,70,72,74,139,97],"90":[8,122,154,23,91,109,26,41,70,72,74,139,97],"103":[8,122,154,23,91,109,26,41,70,72,74,139,97],"154":[8,122,154,23,91,109,26,41,70,72,74,139,97],"156":[8,122,154,23,91,109,26,41,70,72,74,139,97],"167":[8,122,154,23,91,109,26,41,70,72,74,139,97],"260":[8,122,154,23,91,109,26,41,70,72,74,139,97],"265":[8,122,154,23,91,109,26,41,70,72,74,139,97],"270":[8,122,154,23,91,109,26,41,70,72,74,139,97],"277":[8,122,154,23,91,109,26,41,70,72,74,139,97],"303":[8,122,154,23,91,109,26,41,70,72,74,139,97],"317":[8,122,154,23,91,109,26,41,70,72,74,139,97],"319":[8,122,154,23,91,109,26,41,70,72,74,139,97],"321":[8,122,154,23,91,109,26,41,70,72,74,139,97],"333":[8,122,154,23,91,109,26,41,70,72,74,139,97]},"packages/nodes-base/nodes/HttpRequest/HttpRequest.node.ts":{"9":[8,122,154,23,91,109,41,70,72,74,139,97]},"packages/nodes-base/nodes/HttpRequest/V1/HttpRequestV1.node.ts":{"43":[8,122,154,23,91,109,41,70,72,74,139,97],"617":[8,122,154,23,91,109,41,70,72,74,139,97],"811":[8,122,154,23,91,109,41,70,72,74,139,97],"888":[8,122,154,23,91,109,41,70,72,74,139,97],"1002":[8,122,154,23,91,109,41,70,72,74,139,97],"1009":[8,122,154,23,91,109,41,70,72,74,139,97],"1014":[8,122,154,23,91,109,41,70,72,74,139,97],"1158":[8,122,154,23,91,109,41,70,72,74,139,97]},"packages/nodes-base/nodes/HttpRequest/V2/HttpRequestV2.node.ts":{"47":[8,122,154,23,91,109,41,70,72,74,139,97],"632":[8,122,154,23,91,109,41,70,72,74,139,97],"883":[8,122,154,23,91,109,41,70,72,74,139,97],"960":[8,122,154,23,91,109,41,70,72,74,139,97],"1083":[8,122,154,23,91,109,41,70,72,74,139,97],"1089":[8,122,154,23,91,109,41,70,72,74,139,97],"1094":[8,122,154,23,91,109,41,70,72,74,139,97],"1107":[8,122,154,23,91,109,41,70,72,74,139,97],"1250":[8,122,154,23,91,109,41,70,72,74,139,97]},"packages/nodes-base/nodes/HttpRequest/V3/Description.ts":{"11":[8,122,154,23,91,109,41,70,72,74,139,97],"1268":[8,122,154,23,91,109,41,70,72,74,139,97]},"packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts":{"55":[8,122,154,23,91,109,26,41,70,72,74,139,97],"62":[8,122,154,23,91,109,26,41,70,72,74,139,97],"66":[8,122,154,23,91,109,26,41,70,72,74,139,97],"75":[8,122,154,23,91,109,26,41,70,72,74,139,97],"110":[8,122,154,23,91,109,26,41,70,72,74,139,97],"400":[8,122,154,23,91,109,26,41,70,72,74,139,97],"517":[8,122,154,23,91,109,26,41,70,72,74,139,97],"653":[8,122,154,23,91,109,26,41,70,72,74,139,97],"695":[8,122,154,23,91,109,26,41,70,72,74,139,97],"755":[8,122,154,23,91,109,26,41,70,72,74,139,97],"774":[8,122,154,23,91,109,26,41,70,72,74,139,97],"785":[8,122,154,23,91,109,26,41,70,72,74,139,97],"790":[8,122,154,23,91,109,26,41,70,72,74,139,97],"805":[8,122,154,23,91,109,26,41,70,72,74,139,97],"811":[8,122,154,23,91,109,26,41,70,72,74,139,97],"834":[8,122,154,23,91,109,26,41,70,72,74,139,97],"836":[8,122,154,23,91,109,26,41,70,72,74,139,97],"837":[8,122,154,23,91,109,26,41,70,72,74,139,97],"981":[8,122,154,23,91,109,26,41,70,72,74,139,97],"1143":[8,122,154,23,91,109,26,41,70,72,74,139,97],"1206":[8,122,154,23,91,109,26,41,70,72,74,139,97]},"packages/nodes-base/nodes/HttpRequest/V3/utils/binaryData.ts":{"3":[8,122,154,23,91,109,41,70,72,74,139,97]},"packages/nodes-base/nodes/HttpRequest/V3/utils/buffer-decoding.ts":{"13":[8,122,154,23,91,109,26,41,70,72,74,139,97],"36":[8,122,154,23,91,109,26,41,70,72,74,139,97]},"packages/nodes-base/nodes/HttpRequest/V3/utils/error-details.ts":{"13":[8,122,154,23,91,109,41,70,72,74,139,97],"35":[8,122,154,23,91,109,41,70,72,74,139,97],"48":[8,122,154,23,91,109,41,70,72,74,139,97]},"packages/nodes-base/nodes/HttpRequest/V3/utils/parse.ts":{"1":[8,122,154,23,91,109,41,70,72,74,139,97]},"packages/nodes-base/nodes/HttpRequest/shared/optimizeResponse.ts":{"20":[8,122,154,23,91,109,26,41,70,72,74,139,97],"37":[8,122,154,23,91,109,26,41,70,72,74,139,97],"38":[8,122,154,23,91,109,26,41,70,72,74,139,97],"42":[8,122,154,23,91,109,26,41,70,72,74,139,97],"55":[8,122,154,23,91,109,26,41,70,72,74,139,97],"63":[8,122,154,23,91,109,26,41,70,72,74,139,97],"92":[8,122,154,23,91,109,26,41,70,72,74,139,97],"97":[8,122,154,23,91,109,26,41,70,72,74,139,97],"127":[8,122,154,23,91,109,26,41,70,72,74,139,97],"128":[8,122,154,23,91,109,26,41,70,72,74,139,97],"179":[8,122,154,23,91,109,26,41,70,72,74,139,97],"194":[8,122,154,23,91,109,26,41,70,72,74,139,97],"226":[8,122,154,23,91,109,26,41,70,72,74,139,97],"255":[8,122,154,23,91,109,26,41,70,72,74,139,97]},"localhost-42219/assets/index-BoK1c_f3.js":{"3":[74]},"localhost-42219/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[74],"9":[74],"10":[74],"19":[74],"23":[74],"29":[74],"33":[74],"34":[74]},"packages/@n8n/scheduler/src/core/retention/prune.ts":{"24":[97,98,79,100],"58":[97,98,79,100],"90":[97,98,79,100],"117":[97,98,79,100]},"packages/nodes-base/nodes/Pipedrive/Pipedrive.node.ts":{"8":[97]},"packages/nodes-base/nodes/Pipedrive/v1/GenericFunctions.ts":{"31":[23,97],"103":[23,97],"142":[23,97],"187":[23,97],"195":[23,97],"210":[23,97],"230":[23,97],"278":[23,97],"292":[23,97],"293":[23,97],"302":[23,97],"305":[23,97]},"packages/nodes-base/nodes/Pipedrive/v1/PipedriveV1.node.ts":{"37":[97],"2256":[97],"2393":[97],"3809":[97],"3820":[97],"3834":[97],"3862":[97],"3876":[97],"3900":[97],"3904":[97],"3908":[97],"3912":[97],"3916":[97],"3926":[97],"3930":[97],"3944":[97],"3962":[97],"3978":[97],"3994":[97],"4023":[97],"4053":[97],"4058":[97],"4063":[97],"4068":[97],"4073":[97],"4103":[97],"4949":[97]},"packages/nodes-base/nodes/Pipedrive/v2/PipedriveV2.node.ts":{"16":[97],"28":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/activity/create.operation.ts":{"119":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/activity/delete.operation.ts":{"31":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/activity/get.operation.ts":{"34":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/activity/getAll.operation.ts":{"126":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/activity/update.operation.ts":{"140":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/deal/create.operation.ts":{"222":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/deal/delete.operation.ts":{"31":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/deal/duplicate.operation.ts":{"31":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/deal/get.operation.ts":{"34":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/deal/getAll.operation.ts":{"124":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/deal/search.operation.ts":{"138":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/deal/update.operation.ts":{"179":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/dealProduct/add.operation.ts":{"117":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/dealProduct/getAll.operation.ts":{"54":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/dealProduct/remove.operation.ts":{"40":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/dealProduct/update.operation.ts":{"116":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/file/create.operation.ts":{"87":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/file/delete.operation.ts":{"31":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/file/download.operation.ts":{"34":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/file/get.operation.ts":{"31":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/file/update.operation.ts":{"54":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/lead/create.operation.ts":{"148":[97],"175":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/lead/delete.operation.ts":{"31":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/lead/get.operation.ts":{"31":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/lead/getAll.operation.ts":{"100":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/lead/update.operation.ts":{"105":[97],"132":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/note/create.operation.ts":{"96":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/note/delete.operation.ts":{"31":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/note/get.operation.ts":{"31":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/note/getAll.operation.ts":{"143":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/note/update.operation.ts":{"103":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/organization/create.operation.ts":{"71":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/organization/delete.operation.ts":{"31":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/organization/get.operation.ts":{"34":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/organization/getAll.operation.ts":{"81":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/organization/search.operation.ts":{"98":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/organization/update.operation.ts":{"78":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/person/create.operation.ts":{"164":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/person/delete.operation.ts":{"31":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/person/get.operation.ts":{"34":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/person/getAll.operation.ts":{"80":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/person/search.operation.ts":{"117":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/person/update.operation.ts":{"171":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/product/create.operation.ts":{"126":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/product/delete.operation.ts":{"31":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/product/get.operation.ts":{"34":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/product/getAll.operation.ts":{"53":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/product/search.operation.ts":{"101":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/product/update.operation.ts":{"133":[97]},"packages/nodes-base/nodes/Pipedrive/v2/actions/router.ts":{"15":[97]},"packages/nodes-base/nodes/Pipedrive/v2/helpers/customFields.ts":{"24":[97],"36":[97],"58":[97],"59":[97],"61":[97],"69":[97],"97":[97],"130":[97],"142":[97],"143":[97]},"packages/nodes-base/nodes/Pipedrive/v2/helpers/fields.ts":{"10":[97]},"packages/nodes-base/nodes/Pipedrive/v2/helpers/index.ts":{"3":[97],"7":[97]},"packages/nodes-base/nodes/Pipedrive/v2/helpers/searchResponse.ts":{"9":[97],"14":[97],"25":[97]},"packages/nodes-base/nodes/Pipedrive/v2/helpers/typeCoercion.ts":{"4":[97],"18":[97],"32":[97],"55":[97]},"packages/nodes-base/nodes/Pipedrive/v2/methods/loadOptions.ts":{"9":[97],"34":[97],"65":[97],"83":[97],"117":[97],"120":[97],"127":[97],"130":[97],"137":[97],"143":[97],"150":[97],"162":[97],"187":[97],"193":[97],"203":[97],"206":[97],"213":[97],"223":[97],"226":[97]},"packages/nodes-base/nodes/Pipedrive/v2/transport/pipedrive.api.ts":{"30":[97],"96":[97],"126":[97],"170":[97],"229":[97],"232":[97]},"localhost-41281/assets/verified-Pt0guxqN.js":{"8":[97]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/link--outline-16.svg":{"9":"b:ZgUAAAAgAAAAIEAIFgBAEDACAAQABAk4AAIGBAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/node-dirty.svg":{"11":[86,124,173,177,186,135,205,97,141,213]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/triangle.svg":{"8":[6,86,124,173,45,177,135,205,97,141,213]},"packages/frontend/editor-ui/src/app/utils/json-schema.ts":{"5":[86,124,97],"9":[86,124,97],"12":[86,124,97],"25":[86,124],"32":[86,124,97],"35":[86,124,97]},"packages/frontend/editor-ui/src/experiments/mcpJsonNudge/composables/useMcpJsonNudgeEligibility.ts":{"22":"b:YAEAAAAAAABAIAQADgAAAEACAAQABAk4AAIGBAA=","32":"b:YAEAAAAAAABAIAQADgAAAEACAAQABAk4AAIGBAA="},"packages/frontend/editor-ui/src/experiments/mcpJsonNudge/composables/useMcpJsonNudgeTrigger.ts":{"26":"b:YAEAAAAAAABAIAQADgAAAEACAAQABAk4AAIGBAA="},"packages/frontend/editor-ui/src/features/ndv/panel/components/WireMeUp.vue":{"8":"b:AACAAAAAAAAAIGAABgAAECAAAAEAIJAAAAACAAA="},"packages/frontend/editor-ui/src/features/ndv/runData/schemaPreview.api.ts":{"13":"b:AAAAAAAAAAAACEAAAgAAEAAQAAAAEAUMADQcAgA=","17":[86,124,187,205,97,211],"27":"b:AAAAAAAAAAAACEAAAgAAEAAQAAAAEAUMADQcAgA="},"packages/frontend/editor-ui/src/features/workflows/canvas/emptyGroup.utils.ts":{"13":[86,124],"17":[86,124],"20":[86,124],"31":[86,124],"42":[86,124],"96":"b:YAEAAAAAAABAIEQADgAAEEACAAQABAk4AAIGBAA=","114":[86,124],"115":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nAvatar/Avatar.vue":{"16":"b:AgAgAAAwAIAAAEIICABAEDCAACAAgAAAHgAAAAA=","29":"b:AgAgAAAwAIAAAEIICABAEDCAACAAgAAAHgAAAAA=","30":"b:AgAgAAAwAIAAAEIICABAEDCAACAAgAAAHgAAAAA=","32":"b:AgAgAAAwAIAAAEIICABAEDCAACAAgAAAHgAAAAA=","34":"b:AgAgAAAwAIAAAEIICABAEDCAACAAgAAAHgAAAAA=","37":"b:AgAgAAAwAIAAAEIICABAEDCAACAAgAAAHgAAAAA=","38":"b:AgAgAAAwAIAAAEIICABAEDCAACAAgAAAHgAAAAA="},"packages/frontend/@n8n/design-system/src/utils/labelUtil.ts":{"1":"b:AgAgAAAwAIAAAEIICABAEDCAACAAgAAAHgAAAAA=","4":"b:AgAgAAAwAIAAAEIICABAEDCAACAAgAAAHgAAAAA=","6":"b:AgAgAAAwAIAAAEIICABAEDCAACAAgAAAHgAAAAA=","11":"b:AgAgAAAwAIAAAEIICABAEDCAACAAgAAAHgAAAAA=","12":[86,124]},"packages/frontend/editor-ui/src/app/components/DependencyPill.vue":{"31":[91,45,132,133,100],"33":[91,45,132,133,100],"39":[91,45,132,133,100],"41":[91,45,132,133,100],"45":[91,45,132,133,100],"51":[91,45,132,133,100],"109":[91,45,132,133,100],"112":[91,45,132,133,100]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectSharing.vue":{"24":"b:AAAAAAAQAAAAAEIIAABAEDAAACAAAAAAHAAAAAA=","99":"b:AAAAAAAQAAAAAEIIAABAEDAAACAAAAAAHAAAAAA=","105":[86,124,132,133,196],"106":[86,124],"111":[86,124],"117":[86,157,91,124,44,194,118,132,133,196,81],"120":[86,157,91,124,44,194,118,132,133,196,81],"129":[86,157,91,124,44,194,118,132,133,196,81],"139":[86,157,91,124,44,132,133,196,81],"145":[86,157,91,124,132,133,196,81],"151":[86,157,91,124,44,194,118,132,133,196,81],"152":[86,157,91,124,44,194,118,132,133,196,81],"161":[86,157,91,124,44,194,118,132,133,196,81],"164":[86,157,91,124,44,194,118,132,133,196,81],"168":[86,157,91,124,44,194,118,132,133,196,81],"170":[86,157,91,124,44,194,118,132,133,196,81],"184":"b:AAAAAAAQAAAAAEIIAABAEDAAACAAAAAAHAAAAAA=","200":[86,157,91,124,44,194,132,133,196],"206":"b:AAAAAAAQAAAAAEIIAABAEDAAACAAAAAAHAAAAAA=","210":[86,157,91,124,44,194,132,133,196],"216":[86,124,44,194,132,133,196],"230":[86,157,91,124,195,132,133,196,81],"231":[86,157,91,124,132,133,196],"232":[86,124],"236":[86,157,91,124,132,133,196],"239":[86,91,124],"267":[86,124],"272":"b:AAAAAAAQAAAAAEIIAABAEDAAACAAAAAAHAAAAAA=","273":"b:AAAAAAAQAAAAAEIIAABAEDAAACAAAAAAHAAAAAA=","283":"b:AAAAAAAQAAAAAEIIAABAEDAAACAAAAAAHAAAAAA=","287":[86,124],"288":"b:AAAAAAAQAAAAAEIIAABAEDAAACAAAAAAHAAAAAA=","306":[86,124],"308":[86,157,91,124,44,194,118,132,133,196,81],"314":[86,124],"316":[86,157,91,124,44,194,118,132,133,196,81],"319":[86,157,91,124,44,194,118,132,133,196,81],"323":[86,157,91,124,44,194,118,132,133,196,81],"333":[86,124],"335":[86,124],"351":[86,157,91,124,195,132,133,196,81],"355":[86,157,91,124,195,132,133,196,81],"359":[86,157,91,124,132,133,196],"366":[86,124],"371":[86,157,91,124,132,133,196],"376":[86,124],"383":[86,124],"392":[86,124],"409":[86,124],"410":[86,157,91,124,132,133,196],"412":[86,157,91,124,132,133,196],"422":[86,157,91,124,132,133,196],"431":[86,91,124]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectSharingInfo.vue":{"13":"b:AAAAAAAQAAAAAEIIAABAEDAAACAAAAAAHAAAAAA=","15":"b:AAAAAAAQAAAAAEIIAABAEDAAACAAAAAAHAAAAAA=","26":"b:AAAAAAAQAAAAAEIIAABAEDAAACAAAAAAHAAAAAA=","32":"b:AAAAAAAQAAAAAEIIAABAEDAAACAAAAAAHAAAAAA="},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialSharing.ee.vue":{"39":[86,157,91,124,132,133],"60":[86,157,91,124,132,133],"64":[86,157,91,124,132,133],"67":[86,124],"72":[86,124],"74":[86,157,91,124,132,133],"75":[86,157,91,124,132,133],"87":[86,157,91,124,132,133],"91":[86,157,91,124,132,133],"94":[86,124],"95":[86,124],"100":[86,157,91,124,132,133],"106":[86,157,91,124,132,133],"114":[86,157,91,124,132,133],"123":[86,157,91,124,132,133],"124":[86,157,91,124,132,133],"137":[86,157,91,124,132,133],"139":[86,124],"158":[86,157,91,124,132,133],"164":[86,157,91,124,132,133],"170":[86,124],"186":[86,124],"204":[86,124],"213":[86,124],"217":[86,124],"233":[86,124],"245":[86,124],"254":[86,124],"262":[86,124],"263":[86,124],"268":[86,157,91,124,132,133],"274":[86,157,91,124,132,133],"280":[86,124,132,133],"289":[86,124],"291":[86,157,91,124,132,133],"317":[86,157,91,124,132,133],"321":[86,124],"324":[86,124],"352":[86,157,91,124],"354":[86,124],"357":[86,124],"360":[86,124],"368":[86,124],"373":[86,124],"374":[86,124],"381":[86,124],"385":[86,124],"386":[86,124]},"packages/frontend/editor-ui/src/features/credentials/credentials.ee.api.ts":{"6":[86,124,132,133],"19":[86,124,44]},"packages/@n8n/ai-utilities/src/utils/embeddings-input-validation.ts":{"13":[4,10],"32":[4,10],"40":[4,10]},"packages/@n8n/ai-utilities/src/utils/loaders/n8n-pdf-loader.ts":{"21":[4],"26":[4],"43":[4],"57":[4],"73":[4],"82":[4]},"packages/@n8n/ai-utilities/src/utils/log-wrapper.ts":{"38":[4,10,18,19,20],"80":[4,10,18,19,20],"109":[4,10,18,19,20],"127":[4,10,18,19,20],"132":[4,10,18,19,20],"155":[4,10,18,19,20],"184":[4,10,18,19,20],"205":[4,10,18,19,20],"227":[4,10,18,19,20],"271":[4,10,18,19,20],"298":[4,10,18,19,20],"325":[4,10,18,19,20],"355":[4,10,18,19,20],"374":[4,10,18,19,20],"398":[4,10,18,19,20],"422":[4,10,18,19,20],"456":[4,10,18,19,20]},"packages/@n8n/ai-utilities/src/utils/n8n-binary-loader.ts":{"33":[4],"40":[4],"54":[4],"60":[4],"86":[4],"104":[4],"151":[4],"158":[4],"166":[4],"174":[4],"198":[4],"227":[4]},"packages/@n8n/ai-utilities/src/utils/vector-store/MemoryManager/MemoryCalculator.ts":{"21":[4,10],"61":[4,10]},"packages/@n8n/ai-utilities/src/utils/vector-store/MemoryManager/MemoryVectorStoreManager.ts":{"40":[4,10],"69":[4,10],"80":[4,10],"91":[4,10],"106":[4,10],"114":[4,10],"131":[4,10],"138":[4,10],"163":[4,10],"175":[4,10],"182":[4,10],"190":[4,10],"211":[4,10],"268":[4,10]},"packages/@n8n/ai-utilities/src/utils/vector-store/MemoryManager/StoreCleanupService.ts":{"16":[4,10],"31":[4,10],"45":[4,10],"79":[4,10],"117":[4,10],"120":[4,10],"153":[4,10]},"packages/@n8n/ai-utilities/src/utils/vector-store/MemoryManager/config.ts":{"10":[4,10],"38":[4,10],"47":[4,10]},"packages/@n8n/ai-utilities/src/utils/vector-store/createVectorStoreNode/createVectorStoreNode.ts":{"50":[4,10,86,13,77],"53":[4,10,86,13,77],"417":[4,10,86,13,77],"479":[4,10,86,13,77]},"packages/@n8n/ai-utilities/src/utils/vector-store/createVectorStoreNode/operations/insertOperation.ts":{"17":[4,10]},"packages/@n8n/ai-utilities/src/utils/vector-store/createVectorStoreNode/utils.ts":{"12":[4,10,86,13,77],"16":[4,10,86,13,77],"26":[4,10,86,13,77],"36":[4,10,86,13,77],"41":[4,10,86,13,77],"47":[4,10,86,13,77]},"packages/@n8n/ai-utilities/src/utils/vector-store/processDocuments.ts":{"7":[4,10],"19":[4,10],"28":[4,10],"41":[4,10]},"packages/@n8n/backend-network/src/http/binary-buffer.ts":{"16":[4,8,154,18,91,26,41,72],"20":[4,8,154,18,91,26,41,72],"25":[4,8,154,18,91,26,41,72],"29":[4,8,154,18,91,26,41,72],"32":[4,8,154,18,91,26,41,72],"34":[4,8,154,18,91,26,41,72],"42":[4,8,154,18,91,26,41,72],"46":[4,8,154,18,91,26,41,72],"47":[4,8,154,18,91,26,41,72],"48":[4,8,154,18,91,26,41,72],"58":[4,8,154,18,91,26,41,72],"59":[4,8,154,18,91,26,41,72],"61":[4,8,154,18,91,26,41,72],"81":[4,8,154,18,91,26,41,72]},"packages/@n8n/nodes-langchain/nodes/code/Code.node.ts":{"72":[4,10,13],"127":[4,10,13],"131":[4,10,13],"141":[4,10,13],"151":[4,10,13],"155":[4,10,13],"156":[4,10,13],"157":[4,10,13],"163":[4,10,13],"168":[4,10,13]},"packages/@n8n/nodes-langchain/nodes/document_loaders/DocumentDefaultDataLoader/DocumentDefaultDataLoader.node.ts":{"21":[4,10],"38":[4,10],"329":[4,10]},"packages/@n8n/nodes-langchain/nodes/text_splitters/TextSplitterCharacterTextSplitter/TextSplitterCharacterTextSplitter.node.ts":{"13":[4,10],"68":[4,10]},"packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreInMemory/VectorStoreInMemory.node.ts":{"37":[4,10,13],"132":[4,10,13],"143":[4,10,13],"152":[4,10,13],"161":[4,10,13],"186":[4,10,13],"192":[4,10,13]},"packages/core/src/utils/serialized-buffer.ts":{"10":[4,101,103,47],"14":[4,101,103,47]},"packages/nodes-base/nodes/Code/ExecutionError.ts":{"14":[4,10,13],"30":[4,10,13],"38":[4,10,13],"39":[4,10,13],"59":[4,10,13],"75":[4,10,13]},"packages/nodes-base/nodes/Code/JavaScriptSandbox.ts":{"30":[4,10,13],"52":[4,10,13],"55":[4,10,13],"65":[4,10,13],"85":[4,10,13],"93":[4,10,13],"103":[4,10,13]},"packages/nodes-base/nodes/Code/Sandbox.ts":{"24":[4,10,13],"46":[4,10,13],"59":[4,10,13],"71":[4,10,13]},"localhost-33539/assets/index-BoK1c_f3.js":{"3":[4]},"localhost-33539/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[4],"9":[4],"10":[4],"19":[4],"23":[4],"29":[4],"33":[4],"34":[4]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/character-text-splitter.svg":{"11":[4,10]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/default-data-loader.svg":{"11":[4,10,77]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/simple-vector-store.svg":{"11":[4,10,167,116,77]},"packages/@n8n/ai-utilities/src/utils/n8n-json-loader.ts":{"15":[10],"21":[10],"35":[10],"45":[10],"81":[10]},"packages/@n8n/nodes-langchain/nodes/chains/ChainRetrievalQA/ChainRetrievalQa.node.ts":{"21":[10],"186":[10],"202":[10],"208":[10]},"packages/@n8n/nodes-langchain/nodes/chains/ChainRetrievalQA/processItem.ts":{"19":[10]},"packages/@n8n/nodes-langchain/nodes/retrievers/RetrieverVectorStore/RetrieverVectorStore.node.ts":{"14":[10],"73":[10]},"packages/workflow/src/workflow-data-proxy-paired-item-memo.ts":{"18":[9,10,120,18,19,20,136,140,213,119,226],"39":[9,10,120,18,19,20,136,140,213,119,226]},"localhost-32885/assets/index-BoK1c_f3.js":{"3":[10]},"localhost-32885/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[10],"9":[10],"10":[10],"19":[10],"23":[10],"29":[10],"33":[10],"34":[10]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/link-slash--outline-16.svg":{"9":[10,86,124,210,140]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/question-and-answer-chain.svg":{"11":[10,77]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/vector-store-retriever.svg":{"11":[10,77]},"packages/frontend/editor-ui/src/features/execution/executions/components/ViewSubExecution.vue":{"9":[10,86,14,124,137,212,213],"23":[10,86,14,124,137,212,213],"27":[86,124,212,213],"41":[10,86,14,124,137,212,213],"55":[86,124]},"packages/cli/src/tool-generation/index.ts":{"7":[20,23,125,181,139]},"packages/nodes-base/nodes/Pipedrive/PipedriveTrigger.node.ts":{"16":[23],"280":[23],"314":[23],"362":[23],"386":[23]},"packages/nodes-base/nodes/Trello/GenericFunctions.ts":{"14":[23],"46":[23]},"packages/nodes-base/nodes/Trello/Trello.node.ts":{"138":[23],"161":[23],"169":[23],"192":[23],"203":[23]},"localhost-41503/assets/index-BoK1c_f3.js":{"3":[23,131,190,138]},"localhost-41503/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[23,131,190,138],"9":[23,131,190,138],"10":[23,131,190,138],"19":[23,131,190,138],"23":[23,131,190,138],"29":[23,131,190,138],"33":[23,131,190,138],"34":[23,131,190,138]},"localhost-41503/assets/verified-Pt0guxqN.js":{"8":[23,190]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialTypeSelector.vue":{"15":[86,23,124],"42":[86,23,124],"44":[86,23,124],"59":[86,124],"63":[86,23,124],"70":[86,23,124],"74":[86,124],"78":[86,124],"79":[86,23,124],"87":[86,124],"89":[86,23,124],"99":[86,23,124],"100":[86,23,124],"101":[86,23,124],"103":[86,23,124],"108":[86,23,124],"112":[86,23,124],"115":[86,23,124]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialsSelect.vue":{"21":[86,122,23,91,124],"36":[86,122,23,91,124],"37":[86,122,23,91,124],"43":[86,122,23,91,124],"44":[86,122,23,91,124],"47":[86,23,91,124],"57":[86,122,23,91,124],"87":[86,122,23,91,124],"95":[86,122,23,124],"104":[86,122,23,91,124],"105":[86,122,23,91,124],"128":[86,122,23,91,124],"142":[86,23,91,124],"143":[86,124],"144":[86,23,91,124],"145":[86,23,91,124],"146":[86,122,23,91,124],"148":[86,122,23,91,124],"154":[86,122,23,91,124],"176":[86,23,91,124]},"packages/frontend/editor-ui/src/features/ndv/panel/components/InputNodeSelect.vue":{"18":"b:AACAAAAAAAAAIGAAAAAQEAASAAAAAKAAAAAHAAA=","29":"b:AACAAAAAAAAAIGAAAAAQEAASAAAAAKAAAAAHAAA=","33":"b:AACAAAAAAAAAIGAAAAAQEAASAAAAAKAAAAAHAAA=","40":"b:AACAAAAAAAAAIGAAAAAQEAASAAAAAKAAAAAHAAA=","43":[86,124,181,137,116,208,209,210,140],"56":[86,124,181,137,116,208,209,210,140],"58":[86,124,181,137,116,208,209,210,140],"65":[86,124,181,137,116,208,209,210,140],"70":[86,124,181,137,116,208,209,210,140],"79":[86,124,181,137,116,208,209,210,140],"91":[86,124],"97":[86,124],"106":[86,124,181,137,116,208,209,210,140],"110":[86,124,181,137,116,208,209,210,140],"116":[86,124,116,140],"118":"b:AACAAAAAAAAAIGAAAAAQEAASAAAAAKAAAAAHAAA=","133":"b:AACAAAAAAAAAIGAAAAAQEAASAAAAAKAAAAAHAAA=","139":"b:AACAAAAAAAAAIGAAAAAQEAASAAAAAKAAAAAHAAA=","143":[86,124,181,137,116,208,209,210,140],"149":[86,124,181,137,116,208,209,210,140]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputOverrides/FromAiOverrideButton.vue":{"5":[86,20,23,124,181,190,139],"16":[86,20,23,124,181,190,139],"22":[86,124],"24":[86,20,23,124,181,190,139],"34":[86,20,124]},"packages/cli/src/modules/instance-registry/instance-registry.controller.ts":{"9":[201],"16":[201],"24":[201],"39":[201]},"packages/cli/src/modules/instance-registry/instance-registry.service.ts":{"27":[201],"36":[201],"50":[201],"68":[201],"73":[201],"82":[201],"87":[201],"97":[201],"106":[201],"110":[201],"114":[201],"118":[201],"137":[201]},"packages/nodes-base/nodes/Notion/NotionTrigger.node.ts":{"31":[201],"39":[201],"50":[201],"281":[201],"354":[201],"363":[201],"366":[201]},"packages/@n8n/syslog-client/src/client.ts":{"78":[61],"129":[61],"147":[61],"148":[61],"162":[61],"185":[61],"197":[61],"205":[61],"214":[61],"233":[61],"253":[61],"279":[61],"293":[61],"310":[61],"322":[61],"337":[61],"342":[61],"350":[61],"365":[61],"377":[61],"391":[61],"420":[61],"438":[61],"453":[61],"468":[61],"475":[61],"483":[61],"501":[61]},"packages/@n8n/syslog-client/src/factory.ts":{"25":[61]},"packages/@n8n/syslog-client/src/index.ts":{"13":[61]},"packages/@n8n/syslog-client/src/schemas.ts":{"9":[61],"10":[61],"11":[61]},"packages/@n8n/syslog-client/src/utils.ts":{"7":[61],"15":[61],"37":[61],"69":[61]},"packages/cli/src/eventbus/event-message-classes/event-message-generic.ts":{"22":[117,61,62],"30":[117,61,62]},"packages/cli/src/modules/log-streaming.ee/create-message-event-bus-destination.ts":{"17":[117,61,62]},"packages/cli/src/modules/log-streaming.ee/destinations/destination-credentials-access.ts":{"14":[117,61,62]},"packages/cli/src/modules/log-streaming.ee/destinations/message-event-bus-destination-syslog.ee.ts":{"20":[61],"48":[61],"80":[61],"85":[61],"102":[61],"122":[61],"136":[61],"150":[61],"154":[61]},"packages/cli/src/modules/log-streaming.ee/destinations/message-event-bus-destination.ee.ts":{"49":[117,61,62],"84":[117,61,62],"88":[117,61,62],"98":[117,61,62],"117":[117,61,62],"125":[117,61,62],"130":[117,61,62],"134":[117,61,62]},"packages/cli/src/modules/log-streaming.ee/log-streaming-destination.service.ts":{"38":[117,61,62],"51":[117,61,62],"75":[117,61,62],"90":[117,61,62],"97":[117,61,62],"122":[117,61,62],"142":[117,61,62],"161":[117,61,62],"188":[117,61,62],"193":[117,61,62],"194":[117,61,62],"201":[117,61,62],"209":[117,61,62],"220":[117,61,62],"221":[117,61,62],"229":[117,61,62],"238":[117,61,62],"263":[117,61,62]},"packages/cli/src/modules/log-streaming.ee/log-streaming.controller.ts":{"24":[117,61,114,62],"32":[117,61,114,62],"41":[117,61,114,62],"48":[117,61,114,62],"59":[117,61,114,62],"82":[117,61,114,62],"103":[117,61,114,62]},"packages/cli/src/utils/circuit-breaker.ts":{"15":[117,61,62],"147":[117,61,62],"172":[117,61,62],"176":[117,61,62],"180":[117,61,62],"184":[117,61,62],"191":[117,61,62],"197":[117,61,62],"206":[117,61,62],"234":[117,61,62],"269":[117,61,62],"270":[117,61,62]},"packages/cli/src/utils/sliding-window.ts":{"31":[117,61,62],"42":[117,61,62],"57":[117,61,62],"60":[117,61,62],"67":[117,61,62]},"localhost-38823/assets/index-BoK1c_f3.js":{"3":[114]},"localhost-38823/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[114],"9":[114],"10":[114],"19":[114],"23":[114],"29":[114],"33":[114],"34":[114]},"packages/frontend/@n8n/rest-api-client/src/api/eventbus.ee.ts":{"10":[86,124,117,114,62],"16":[86,124,117,114],"28":[86,124,62],"32":[86,124,117,114,62],"42":[86,124,117,114,62],"46":[86,124,117,114,62]},"packages/frontend/editor-ui/src/app/utils/rbac/middleware/rbac.ts":{"11":"b:AAAAAACAAFwAAEAAAAAsEAAAACAAAACABAAAAAA="},"packages/frontend/editor-ui/src/app/utils/rbacUtils.ts":{"4":"b:AAAAAACAAFwAAEAAAAAsEAAAACAAAACABAAAAAA=","12":"b:AAAAAACAAFwAAEAAAAAsEAAAACAAAACABAAAAAA=","23":"b:AAAAAACAAFwAAEAAAAAsEAAAACAAAACABAAAAAA=","34":[86,124,60,194]},"packages/frontend/editor-ui/src/features/integrations/logStreaming.ee/components/EventDestinationCard.vue":{"44":[117,114,62],"52":[117,114,62],"56":[117,114,62],"72":[117,114,62],"76":[114],"87":[117,62],"100":[117],"106":[117],"110":[62],"135":[117,114,62],"141":[117,114,62],"144":[117,114,62],"148":[117,114,62],"153":[117,114,62],"157":[117,114,62],"160":[117,114,62],"176":[117]},"packages/frontend/editor-ui/src/features/integrations/logStreaming.ee/components/EventDestinationSettingsModal.vue":{"78":[117,114,62],"89":[117,114,62],"109":[114,62],"123":[117,114,62],"127":[117,114,62],"131":[114,62],"135":[114,62],"139":[117,114,62],"141":[117,114,62],"145":[117,114,62],"163":[117,114,62],"167":[114],"187":[117,114,62],"191":[117,114,62],"206":[117,114,62],"210":[114],"219":[114],"225":[117,114,62],"233":[114,62],"237":[114],"263":[114],"302":[117,114,62],"307":[62],"331":[62],"343":[114],"372":[114,62],"380":[117,114,62],"396":[117,114,62],"413":[117,114,62],"455":[117,114,62],"465":[114,62],"473":[114,62],"475":[114,62],"487":[114,62],"496":[117,114,62]},"packages/frontend/editor-ui/src/features/integrations/logStreaming.ee/logStreaming.store.ts":{"44":[117,114,62],"53":[117,114,62],"81":[117,114,62],"99":[117,114,62],"105":[117,114,62],"128":[117,114,62],"136":[117,114,62],"151":[117,114,62],"155":[117,114,62],"163":[117,114,62],"220":[117,114],"226":[62],"231":[117,114],"248":[117,114],"265":[117,114,62],"276":[117,114,62],"280":[117,114,62],"284":[62]},"packages/frontend/editor-ui/src/features/integrations/logStreaming.ee/logStreaming.utils.ts":{"13":[117,114,62],"33":[114]},"packages/frontend/editor-ui/src/features/integrations/logStreaming.ee/modals.ts":{"8":[86,124,117,114,62]},"packages/frontend/editor-ui/src/features/integrations/logStreaming.ee/views/SettingsLogStreamingView.vue":{"36":[117,114,62],"44":[117,114,62],"49":[117,114,62],"53":[117,114,62],"57":[117,114,62],"59":[117,114,62],"72":[117,114,62],"74":[62],"87":[117,114,62],"93":[114],"97":[117,114,62],"102":[62],"107":[117,114,62],"128":[117,114,62],"132":[114,62],"147":[62],"156":[117,62],"177":[117,114,62],"199":[117,114,62],"203":[117,114,62],"209":[62],"210":[117,62],"225":[117,114,62]},"packages/@n8n/api-types/src/dto/binary-data/binary-data-query.dto.ts":{"8":[101,138],"12":[101,138]},"packages/cli/src/binary-data/binary-data-access.service.ts":{"27":[101,138],"35":[101,138],"55":[101,138],"95":[101,138]},"packages/cli/src/controllers/binary-data.controller.ts":{"18":[101,138],"24":[101,138],"44":[101,138],"58":[101,138],"89":[101,138]},"packages/core/src/binary-data/utils.ts":{"3":[101,18,225,138,212,213,119],"13":[101,18,225,138,212,213,119],"18":[101,18,225,138,212,213,119],"28":[101,18,225,138,212,213,119]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/convert-to-file.svg":{"11":"b:AAAAAAAAAABEAAAAARAAAMAEAAEAIBAAAAYCAAA="},"packages/frontend/editor-ui/src/app/utils/fileUtils.ts":{"4":[86,18,124,29,160],"10":[86,124,138],"19":[86,18,124,29,160],"26":[86,124],"27":[86,124],"31":[86,18,124,29,160],"33":[86,18,124,29,160],"34":[86,18,124,29,160],"46":[86,124]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataBinary.vue":{"18":[86,124,138],"26":[86,124,138],"33":[86,124,138],"37":[86,124,138],"42":[86,124,138],"47":[86,124,138],"58":[86,124],"63":[86,124],"65":[86,124,138],"71":[86,124],"72":[86,124],"75":[86,124],"77":[86,124,138],"86":[86,124,138],"97":[86,124,138],"105":[86,124],"117":[86,124,138],"125":[86,124,138],"133":[86,124,138],"145":[86,124],"153":[86,124,138]},"packages/@n8n/expression-runtime/src/evaluator/error-classification.ts":{"5":[86,124,209,119]},"packages/cli/src/executions/pre-execution-checks/subworkflow-policy-checker.ts":{"18":[83,225,212,213,119],"29":[83,225,212,213,119],"68":[83,225,212,213,119],"97":[83,225,212,213,119],"115":[83,225,212,213,119],"124":[83,225,212,213,119],"142":[83,225,212,213,119],"146":[83,225,212,213,119],"147":[83,225,212,213,119],"158":[83,225,212,213,119]},"packages/cli/src/modules/otel/otel.service.ts":{"43":[83,209,119],"55":[83,209,119],"62":[83,209,119],"67":[83,209,119],"73":[83,209,119],"87":[83,209,119],"96":[83,209,119],"98":[83,209,119],"99":[83,209,119],"100":[83,209,119],"107":[83,209,119],"108":[83,209,119],"126":[83,209,119],"127":[83,209,119],"134":[83,209,119],"152":[83,209,119],"166":[83,209,119],"178":[83,209,119],"187":[83,209,119],"210":[83,209,119],"219":[83,209,119],"230":[83,209,119],"240":[83,209,119],"259":[83,209,119],"267":[83,209,119],"276":[83,209,119],"289":[83,209,119],"316":[83,209,119],"320":[83,209,119],"321":[83,209,119],"322":[83,209,119],"323":[83,209,119],"324":[83,209,119],"331":[83,209,119],"336":[83,209,119],"360":[83,209,119],"369":[83,209,119],"379":[83,209,119],"380":[83,209,119]},"packages/core/src/execution-engine/node-execution-context/utils/extract-value.ts":{"21":[120,169,172,136,137,210,77,78,119],"40":[120,169,172,136,137,210,77,78,119],"61":[120,169,172,136,137,210,77,78,119],"69":[120,169,172,136,137,210,77,78,119],"78":[120,169,172,136,137,210,77,78,119],"111":[120,169,172,136,137,210,77,78,119],"131":[120,169,172,136,137,210,77,78,119],"165":[120,169,172,136,137,210,77,78,119]},"packages/nodes-base/nodes/ExecuteWorkflow/ExecuteWorkflow/ExecuteWorkflow.node.ts":{"22":[45,225,212,213,119,142],"365":[45,225,212,213,119,142]},"packages/nodes-base/nodes/ExecuteWorkflow/ExecuteWorkflow/GenericFunctions.ts":{"10":[45,225,212,213,119,142],"29":[45,225,212,213,119,142]},"packages/nodes-base/nodes/ExecuteWorkflow/ExecuteWorkflow/methods/localResourceMapping.ts":{"5":[45,225,212,213,119,142]},"packages/nodes-base/nodes/Filter/Filter.node.ts":{"8":[176,136,119]},"packages/nodes-base/nodes/Filter/V1/FilterV1.node.ts":{"17":[176,136,119],"310":[176,136,119]},"packages/nodes-base/nodes/Filter/V1/GenericFunctions.ts":{"5":[176,136,119],"8":[176,136,119],"10":[176,136,119],"18":[176,136,119],"19":[176,136,119],"20":[176,136,119],"22":[176,136,119],"24":[176,136,119],"26":[176,136,119],"28":[176,136,119],"29":[176,136,119],"30":[176,136,119],"31":[176,136,119],"33":[176,136,119],"35":[176,136,119],"37":[176,136,119],"39":[176,136,119],"41":[176,136,119],"47":[176,136,119],"56":[176,136,119],"61":[176,136,119]},"packages/nodes-base/nodes/Filter/V2/FilterV2.node.ts":{"20":[176,136,119],"96":[176,136,119],"100":[176,136,119]},"packages/nodes-base/nodes/Switch/Switch.node.ts":{"9":[96,116,210,140,119]},"packages/nodes-base/nodes/Switch/V1/SwitchV1.node.ts":{"17":[96,116,210,140,119],"25":[96,116,210,140,119],"533":[96,116,210,140,119],"548":[96,116,210,140,119],"550":[96,116,210,140,119],"552":[96,116,210,140,119],"554":[96,116,210,140,119],"556":[96,116,210,140,119],"558":[96,116,210,140,119],"560":[96,116,210,140,119],"561":[96,116,210,140,119],"562":[96,116,210,140,119],"564":[96,116,210,140,119],"566":[96,116,210,140,119],"568":[96,116,210,140,119],"570":[96,116,210,140,119],"572":[96,116,210,140,119],"575":[96,116,210,140,119],"580":[96,116,210,140,119],"601":[96,116,210,140,119]},"packages/nodes-base/nodes/Switch/V2/SwitchV2.node.ts":{"19":[96,116,210,140,119],"27":[96,116,210,140,119],"531":[96,116,210,140,119],"533":[96,116,210,140,119],"548":[96,116,210,140,119],"563":[96,116,210,140,119],"565":[96,116,210,140,119],"567":[96,116,210,140,119],"569":[96,116,210,140,119],"571":[96,116,210,140,119],"573":[96,116,210,140,119],"575":[96,116,210,140,119],"576":[96,116,210,140,119],"577":[96,116,210,140,119],"579":[96,116,210,140,119],"581":[96,116,210,140,119],"583":[96,116,210,140,119],"585":[96,116,210,140,119],"587":[96,116,210,140,119],"590":[96,116,210,140,119],"595":[96,116,210,140,119],"616":[96,116,210,140,119],"637":[96,116,210,140,119],"647":[96,116,210,140,119]},"packages/nodes-base/nodes/Switch/V3/SwitchV3.node.ts":{"21":[96,116,210,140,119],"25":[96,116,210,140,119],"31":[96,116,210,140,119],"51":[96,116,210,140,119],"348":[96,116,210,140,119],"378":[96,116,210,140,119],"384":[96,116,210,140,119],"410":[96,116,210,140,119],"423":[96,116,210,140,119]},"packages/nodes-base/nodes/Transform/SplitOut/SplitOut.node.ts":{"134":[119],"144":[119],"152":[119],"153":[119],"175":[119],"188":[119],"190":[119],"208":[119]},"packages/nodes-base/nodes/Transform/SplitOut/utils.ts":{"8":[119],"14":[119],"20":[119]},"packages/nodes-base/nodes/Transform/utils/utils.ts":{"8":[119],"18":[119],"22":[119],"23":[119]},"packages/nodes-base/utils/workflow-backtracking.ts":{"24":[45,225,212,213,119,227,142],"44":[45,225,212,213,119,227,142]},"packages/workflow/src/errors/expression.error.ts":{"33":[5,209,119],"57":[5,209,119]},"packages/workflow/src/node-parameters/filter-parameter.ts":{"28":[120,169,136,137,210,119],"36":[120,169,136,137,210,119],"70":[120,169,136,137,210,119],"75":[120,169,136,137,210,119],"110":[120,169,136,137,210,119],"122":[120,169,136,137,210,119],"128":[120,169,136,137,210,119],"200":[120,169,136,137,210,119],"202":[120,169,136,137,210,119],"219":[120,169,136,137,210,119],"237":[120,169,136,137,210,119],"250":[120,169,136,137,210,119],"256":[120,169,136,137,210,119],"265":[120,169,136,137,210,119],"292":[120,169,136,137,210,119],"468":[120,169,136,137,210,119],"477":[120,169,136,137,210,119],"485":[120,169,136,137,210,119],"498":[120,169,136,137,210,119],"538":[120,169,136,137,210,119],"542":[120,169,136,137,210,119],"556":[120,169,136,137,210,119],"561":[120,169,136,137,210,119]},"packages/@n8n/agents/src/sdk/guardrails/patterns.ts":{"21":[1,2,83],"37":[1,2,83],"51":[1,2,83]},"packages/@n8n/api-types/src/agents/agent-config-lifecycle.ts":{"8":[1,2,83,86,124],"13":[1,2,83,86,124]},"packages/@n8n/api-types/src/agents/agent-personalisation.ts":{"9":[1,2,83,86,124],"11":[1,2,83,86,124],"15":[1,2,83,86,124],"17":[1,2,83,86,124],"20":[1,2,83,86,124],"27":[1,2,83,86,124],"31":[1,2,83,86,124],"51":[1,2,83,86,124],"66":[1,2,83,86,124],"74":[1,2,83,86,124],"86":[1,2,83,86,124]},"packages/cli/src/modules/agents/adapters/agents-credential-provider.ts":{"14":[1,2,83],"32":[1,2,83],"46":[1,2,83],"61":[1,2,83],"66":[1,2,83],"82":[1,2,83],"99":[1,2,83],"103":[1,2,83],"113":[1,2,83],"120":[1,2,83],"125":[1,2,83],"129":[1,2,83],"132":[1,2,83],"143":[1,2,83],"153":[1,2,83]},"packages/cli/src/modules/agents/agent-chat.controller.ts":{"72":[2,83],"88":[2,83],"91":[2,83],"97":[2,83],"102":[2,83],"110":[2,83],"154":[2,83],"160":[2,83],"166":[2,83],"186":[2,83],"205":[2,83],"222":[2,83],"239":[2,83],"240":[2,83],"247":[2,83],"253":[2,83],"261":[2,83],"297":[2,83],"320":[2,83],"344":[2,83],"361":[2,83],"413":[2,83],"435":[2,83],"454":[2,83],"474":[2,83],"494":[2,83],"517":[2,83],"541":[2,83],"575":[2,83],"602":[2,83],"615":[2,83],"637":[2,83],"660":[2,83],"682":[2,83],"698":[2,83],"716":[2,83],"735":[2,83],"759":[2,83],"780":[2,83],"794":[2,83],"817":[2,83],"841":[2,83],"858":[2,83],"881":[2,83],"903":[2,83],"909":[2,83],"915":[2,83],"916":[2,83],"940":[2,83],"959":[2,83],"981":[2,83],"1034":[2,83],"1065":[2,83],"1085":[2,83],"1133":[2,83]},"packages/cli/src/modules/agents/agent-default-model-resolver.service.ts":{"26":[1,2],"40":[1,2],"46":[1,2],"64":[1,2],"78":[1,2],"90":[1,2],"94":[1,2],"105":[1,2],"127":[1,2],"152":[1,2]},"packages/cli/src/modules/agents/agent-definition.service.ts":{"23":[1,2],"31":[1,2],"46":[1,2],"50":[1,2],"55":[1,2],"66":[1,2],"77":[1,2]},"packages/cli/src/modules/agents/agent-execution-orchestrator.service.ts":{"334":[2,83],"354":[2,83],"365":[2,83],"382":[2,83],"386":[2,83],"390":[2,83],"396":[2,83],"429":[2,83],"434":[2,83],"494":[2,83],"519":[2,83],"534":[2,83],"535":[2,83],"539":[2,83],"618":[2,83],"671":[2,83],"684":[2,83],"685":[2,83],"694":[2,83],"714":[2,83],"739":[2,83],"754":[2,83],"786":[2,83],"809":[2,83],"831":[2,83],"837":[2,83],"870":[2,83],"879":[2,83],"899":[2,83],"926":[2,83],"939":[2,83],"957":[2,83],"980":[2,83],"1030":[2,83],"1031":[2,83],"1044":[2,83],"1069":[2,83],"1101":[2,83],"1126":[2,83],"1127":[2,83],"1131":[2,83],"1147":[2,83],"1157":[2,83],"1240":[2,83],"1281":[2,83],"1296":[2,83],"1299":[2,83],"1303":[2,83],"1333":[2,83],"1357":[2,83],"1373":[2,83],"1393":[2,83],"1420":[2,83],"1441":[2,83],"1455":[2,83],"1484":[2,83],"1513":[2,83],"1542":[2,83],"1578":[2,83],"1597":[2,83],"1627":[2,83],"1640":[2,83],"1696":[2,83],"1728":[2,83],"1771":[2,83],"1804":[2,83]},"packages/cli/src/modules/agents/agent-execution.service.ts":{"184":[1,2,83],"201":[1,2,83],"207":[1,2,83],"217":[1,2,83],"277":[1,2,83],"316":[1,2,83],"332":[1,2,83],"357":[1,2,83],"372":[1,2,83],"376":[1,2,83],"383":[1,2,83],"397":[1,2,83],"435":[1,2,83],"451":[1,2,83],"461":[1,2,83],"488":[1,2,83],"509":[1,2,83],"510":[1,2,83],"513":[1,2,83],"516":[1,2,83],"527":[1,2,83],"534":[1,2,83],"541":[1,2,83],"549":[1,2,83],"556":[1,2,83],"565":[1,2,83],"585":[1,2,83],"611":[1,2,83],"620":[1,2,83],"624":[1,2,83],"634":[1,2,83],"657":[1,2,83],"663":[1,2,83],"686":[1,2,83],"701":[1,2,83],"707":[1,2,83],"722":[1,2,83],"748":[1,2,83],"768":[1,2,83],"782":[1,2,83],"789":[1,2,83],"794":[1,2,83],"802":[1,2,83],"820":[1,2,83],"836":[1,2,83],"840":[1,2,83],"845":[1,2,83],"855":[1,2,83],"858":[1,2,83],"859":[1,2,83],"862":[1,2,83],"876":[1,2,83],"881":[1,2,83],"898":[1,2,83],"906":[1,2,83],"922":[1,2,83],"939":[1,2,83],"943":[1,2,83],"962":[1,2,83],"990":[1,2,83],"1004":[1,2,83],"1009":[1,2,83],"1010":[1,2,83],"1013":[1,2,83],"1062":[1,2,83],"1089":[1,2,83],"1096":[1,2,83],"1115":[1,2,83],"1144":[1,2,83],"1152":[1,2,83],"1199":[1,2,83],"1218":[1,2,83],"1231":[1,2,83],"1237":[1,2,83],"1259":[1,2,83],"1283":[1,2,83],"1291":[1,2,83],"1300":[1,2,83],"1308":[1,2,83]},"packages/cli/src/modules/agents/agent-integration-persistence.service.ts":{"62":[1,2],"70":[1,2],"75":[1,2],"84":[1,2],"86":[1,2],"87":[1,2],"92":[1,2],"107":[1,2],"108":[1,2],"113":[1,2],"134":[1,2],"171":[1,2],"182":[1,2],"205":[1,2],"218":[1,2],"249":[1,2]},"packages/cli/src/modules/agents/agent-integrations.controller.ts":{"29":[1,2],"42":[1,2],"73":[1,2],"103":[1,2],"119":[1,2],"124":[1,2],"128":[1,2],"139":[1,2],"160":[1,2],"175":[1,2],"283":[1,2],"285":[1,2],"297":[1,2]},"packages/cli/src/modules/agents/agent-message-queue.service.ts":{"66":[2,83],"82":[2,83],"100":[2,83],"138":[2,83],"184":[2,83],"195":[2,83],"198":[2,83],"202":[2,83],"211":[2,83],"212":[2,83],"227":[2,83],"236":[2,83],"239":[2,83],"259":[2,83],"269":[2,83],"288":[2,83],"297":[2,83],"319":[2,83],"341":[2,83],"350":[2,83],"397":[2,83],"398":[2,83],"410":[2,83],"430":[2,83],"437":[2,83],"460":[2,83]},"packages/cli/src/modules/agents/agent-policy.service.ts":{"13":[1,2,83],"31":[1,2,83],"34":[1,2,83],"51":[1,2,83]},"packages/cli/src/modules/agents/agent-publish.service.ts":{"73":[1,2,83],"78":[1,2,83],"79":[1,2,83],"89":[1,2,83],"112":[1,2,83],"134":[1,2,83],"159":[1,2,83],"200":[1,2,83],"258":[1,2,83],"267":[1,2,83],"299":[1,2,83],"313":[1,2,83],"355":[1,2,83],"379":[1,2,83],"403":[1,2,83],"426":[1,2,83],"435":[1,2,83],"451":[1,2,83],"491":[1,2,83],"499":[1,2,83],"515":[1,2,83],"525":[1,2,83],"542":[1,2,83],"552":[1,2,83],"558":[1,2,83],"577":[1,2,83],"594":[1,2,83],"600":[1,2,83],"611":[1,2,83],"616":[1,2,83],"617":[1,2,83],"640":[1,2,83],"650":[1,2,83],"657":[1,2,83],"675":[1,2,83],"695":[1,2,83],"712":[1,2,83]},"packages/cli/src/modules/agents/agent-runnable-state.service.ts":{"20":[1,2,83],"36":[1,2,83],"56":[1,2,83]},"packages/cli/src/modules/agents/agent-skill-refs.service.ts":{"52":[1,2,83],"59":[1,2,83],"64":[1,2,83],"71":[1,2,83],"79":[1,2,83],"85":[1,2,83],"89":[1,2,83],"98":[1,2,83],"107":[1,2,83],"109":[1,2,83],"118":[1,2,83],"128":[1,2,83],"134":[1,2,83],"137":[1,2,83],"140":[1,2,83],"156":[1,2,83],"162":[1,2,83],"164":[1,2,83],"181":[1,2,83],"191":[1,2,83],"193":[1,2,83],"211":[1,2,83],"240":[1,2,83],"248":[1,2,83],"264":[1,2,83],"274":[1,2,83],"281":[1,2,83],"284":[1,2,83],"289":[1,2,83],"294":[1,2,83],"302":[1,2,83],"335":[1,2,83],"344":[1,2,83],"378":[1,2,83],"409":[1,2,83],"415":[1,2,83],"425":[1,2,83],"434":[1,2,83],"444":[1,2,83],"453":[1,2,83],"463":[1,2,83],"469":[1,2,83],"476":[1,2,83],"482":[1,2,83],"489":[1,2,83],"492":[1,2,83],"499":[1,2,83],"504":[1,2,83],"508":[1,2,83],"509":[1,2,83],"512":[1,2,83],"513":[1,2,83]},"packages/cli/src/modules/agents/agent-task.service.ts":{"51":[1,2,83],"70":[1,2,83],"90":[1,2,83],"92":[1,2,83],"100":[1,2,83],"116":[1,2,83],"138":[1,2,83],"159":[1,2,83],"162":[1,2,83],"177":[1,2,83],"188":[1,2,83],"190":[1,2,83],"200":[1,2,83],"211":[1,2,83],"230":[1,2,83],"245":[1,2,83],"258":[1,2,83],"262":[1,2,83],"274":[1,2,83],"277":[1,2,83],"291":[1,2,83],"309":[1,2,83],"332":[1,2,83],"337":[1,2,83],"342":[1,2,83],"353":[1,2,83],"377":[1,2,83],"382":[1,2,83],"397":[1,2,83],"412":[1,2,83],"430":[1,2,83],"431":[1,2,83],"450":[1,2,83],"472":[1,2,83],"510":[1,2,83],"511":[1,2,83],"514":[1,2,83],"522":[1,2,83],"532":[1,2,83],"568":[1,2,83],"591":[1,2,83],"621":[1,2,83],"631":[1,2,83],"656":[1,2,83],"664":[1,2,83],"670":[1,2,83],"677":[1,2,83],"683":[1,2,83],"695":[1,2,83],"726":[1,2,83],"744":[1,2,83]},"packages/cli/src/modules/agents/agent-tasks.controller.ts":{"23":[1,2],"31":[1,2],"42":[1,2],"67":[1,2],"93":[1,2],"119":[1,2]},"packages/cli/src/modules/agents/agent-threads.controller.ts":{"15":[1,2],"22":[1,2],"42":[1,2],"60":[1,2],"69":[1,2],"83":[1,2]},"packages/cli/src/modules/agents/agent-validation.service.ts":{"76":[1,2,83],"85":[1,2,83],"94":[1,2,83],"110":[1,2,83],"124":[1,2,83],"135":[1,2,83],"146":[1,2,83],"166":[1,2,83],"203":[1,2,83],"228":[1,2,83],"246":[1,2,83],"269":[1,2,83],"287":[1,2,83],"291":[1,2,83],"294":[1,2,83],"301":[1,2,83],"309":[1,2,83],"317":[1,2,83],"319":[1,2,83],"351":[1,2,83],"357":[1,2,83],"373":[1,2,83],"378":[1,2,83],"390":[1,2,83],"402":[1,2,83],"449":[1,2,83],"457":[1,2,83],"491":[1,2,83],"519":[1,2,83],"529":[1,2,83],"558":[1,2,83],"574":[1,2,83],"607":[1,2,83],"635":[1,2,83],"671":[1,2,83],"726":[1,2,83],"747":[1,2,83],"783":[1,2,83],"798":[1,2,83],"810":[1,2,83],"821":[1,2,83],"845":[1,2,83],"862":[1,2,83],"904":[1,2,83],"909":[1,2,83],"911":[1,2,83]},"packages/cli/src/modules/agents/agents-catalog.controller.ts":{"19":[1,2],"26":[1,2],"33":[1,2],"52":[1,2]},"packages/cli/src/modules/agents/agents-settings.service.ts":{"18":[1,2,83],"29":[1,2,83],"39":[1,2,83],"40":[1,2,83],"44":[1,2,83],"49":[1,2,83],"50":[1,2,83],"60":[1,2,83],"74":[1,2,83]},"packages/cli/src/modules/agents/builder/agents-builder.service.ts":{"89":[2,83],"104":[2,83],"147":[2,83],"198":[2,83],"215":[2,83],"230":[2,83],"265":[2,83],"290":[2,83],"304":[2,83],"311":[2,83],"339":[2,83],"346":[2,83],"353":[2,83],"360":[2,83],"369":[2,83],"381":[2,83],"400":[2,83],"409":[2,83]},"packages/cli/src/modules/agents/integrations/agent-chat-integration.ts":{"111":[1,2,83],"117":[1,2,83],"133":[1,2,83],"225":[1,2,83],"278":[1,2,83],"279":[1,2,83],"283":[1,2,83],"284":[1,2,83],"362":[1,2,83],"639":[1,2,83],"642":[1,2,83],"646":[1,2,83],"650":[1,2,83],"656":[1,2,83],"661":[1,2,83],"662":[1,2,83]},"packages/cli/src/modules/agents/integrations/channel-status-report.ts":{"35":[1,2],"55":[1,2],"56":[1,2],"70":[1,2],"73":[1,2],"81":[1,2],"85":[1,2],"93":[1,2],"105":[1,2],"107":[1,2],"109":[1,2],"113":[1,2],"116":[1,2],"117":[1,2],"118":[1,2],"121":[1,2],"123":[1,2]},"packages/cli/src/modules/agents/integrations/n8n-checkpoint-storage.ts":{"25":[2,83],"52":[2,83],"64":[2,83],"66":[2,83],"67":[2,83],"68":[2,83],"70":[2,83],"72":[2,83],"79":[2,83],"106":[2,83],"108":[2,83],"132":[2,83],"138":[2,83],"156":[2,83],"162":[2,83],"183":[2,83],"198":[2,83],"211":[2,83],"215":[2,83],"231":[2,83],"249":[2,83],"268":[2,83],"297":[2,83],"305":[2,83],"324":[2,83],"340":[2,83],"356":[2,83],"374":[2,83],"379":[2,83]},"packages/cli/src/modules/agents/json-config/agent-config-composition.ts":{"13":[1,2,83],"29":[1,2,83]},"packages/cli/src/modules/agents/json-config/agent-document.ts":{"14":[1,2,83],"20":[1,2,83],"32":[1,2,83]},"packages/cli/src/modules/agents/model-catalog.ts":{"3":[1,2]},"packages/cli/src/modules/agents/repositories/agent-channel-status.repository.ts":{"42":[1,2],"56":[1,2],"69":[1,2],"78":[1,2],"83":[1,2],"87":[1,2],"92":[1,2],"97":[1,2],"107":[1,2],"112":[1,2]},"packages/cli/src/modules/agents/repositories/agent-checkpoint.repository.ts":{"9":[2,83],"13":[2,83],"17":[2,83],"25":[2,83],"37":[2,83],"41":[2,83],"45":[2,83],"53":[2,83],"68":[2,83],"83":[2,83],"97":[2,83],"109":[2,83]},"packages/cli/src/modules/agents/repositories/agent-execution-thread.repository.ts":{"51":[1,2,83],"55":[1,2,83],"68":[1,2,83],"97":[1,2,83],"151":[1,2,83],"182":[1,2,83],"198":[1,2,83],"212":[1,2,83],"252":[1,2,83],"274":[1,2,83],"278":[1,2,83],"285":[1,2,83],"304":[1,2,83],"332":[1,2,83],"344":[1,2,83],"354":[1,2,83],"366":[1,2,83],"380":[1,2,83],"407":[1,2,83],"418":[1,2,83],"425":[1,2,83],"434":[1,2,83],"435":[1,2,83],"438":[1,2,83],"441":[1,2,83],"453":[1,2,83],"487":[1,2,83],"495":[1,2,83],"500":[1,2,83],"509":[1,2,83],"510":[1,2,83],"517":[1,2,83],"523":[1,2,83],"526":[1,2,83],"542":[1,2,83],"562":[1,2,83],"574":[1,2,83],"590":[1,2,83]},"packages/cli/src/modules/agents/repositories/agent-history.repository.ts":{"17":[1,2,83],"24":[1,2,83],"37":[1,2,83],"70":[1,2,83],"83":[1,2,83],"104":[1,2,83]},"packages/cli/src/modules/agents/repositories/agent-task.repository.ts":{"12":[1,2],"16":[1,2],"23":[1,2],"27":[1,2],"31":[1,2],"37":[1,2],"44":[1,2],"45":[1,2],"50":[1,2]},"packages/cli/src/modules/agents/skills/skill-names.ts":{"5":[1,2,83],"17":[1,2,83],"29":[1,2,83],"36":[1,2,83],"40":[1,2,83],"46":[1,2,83]},"packages/cli/src/modules/agents/tools/workflow-tool-workflow-resolver.ts":{"6":[1,2,83],"14":[1,2,83],"17":[1,2,83],"36":[1,2,83],"53":[1,2,83],"59":[1,2,83],"63":[1,2,83],"69":[1,2,83],"70":[1,2,83]},"packages/cli/src/modules/agents/utils/agent-config-hash.ts":{"5":[1,2,83],"6":[1,2,83],"14":[1,2,83],"23":[1,2,83],"28":[1,2,83],"32":[1,2,83]},"packages/cli/src/modules/agents/utils/agent-credential-provider.ts":{"7":[1,2,83]},"packages/cli/src/modules/agents/utils/agent-definition.ts":{"25":[1,2,83],"37":[1,2,83]},"packages/cli/src/modules/agents/utils/agent-missing-skill-ids.ts":{"5":[1,2,83]},"packages/cli/src/modules/agents/utils/extract-agent-workflow-refs.ts":{"8":[1,2,83],"12":[1,2,83]},"packages/cli/src/modules/agents/utils/node-tool-validation.ts":{"20":[1,2],"23":[1,2],"55":[1,2],"67":[1,2],"71":[1,2],"112":[1,2]},"packages/cli/src/modules/agents/utils/parse-thread-list-limit.ts":{"2":[1,2]},"localhost-36611/assets/index-BoK1c_f3.js":{"3":[2]},"localhost-36611/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[2],"9":[2],"10":[2],"19":[2],"23":[2],"29":[2],"33":[2],"34":[2]},"packages/frontend/@n8n/design-system/src/components/N8nAiModelSelectorDropdown/AiModelSelectorDropdown.vue":{"29":[1,2,86,18,155,19,156,20,21,124],"90":[86,124],"93":[1,2,86,18,155,19,156,20,21,124],"95":[1,2,86,18,155,19,156,20,21,124],"97":[86,124],"101":[86,155,19,156,124],"107":[86,124],"110":[86,124],"112":[1,2,86,18,155,19,156,20,21,124],"127":[1,2,86,18,155,19,156,20,21,124],"133":[1,2,86,18,155,19,156,20,21,124],"138":[1,2,86,18,155,19,156,20,21,124],"147":[86,124],"155":[86,124],"163":[86,18,155,19,156,20,124],"172":[86,155,19,156,124],"186":[86,155,19,156,124],"189":[86,124],"191":[86,124],"196":[86,124],"205":[86,155,19,156,124],"212":[86,124],"219":[86,124],"228":[86,124],"233":[86,155,19,156,124],"236":[86,124],"238":[86,124],"253":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nBreadcrumbs/Breadcrumbs.vue":{"34":[1,2,3,86,124,24,25,43,174,98],"60":[1,2,3,86,124,24,25,43,174,98],"66":[1,2,3,86,124,24,25,43,174,98],"70":[86,124,43],"74":[86,124,43],"75":[86,124,43],"82":[86,124,43],"108":[1,2,3,86,124,24,25,43,174,98],"109":[86,124,43],"115":[86,124,43],"124":[86,124,43],"125":[86,124,43],"143":[86,124,43],"144":[86,124,43],"151":[86,124],"152":[86,124],"159":[86,124,43],"166":[86,124],"171":[86,124],"173":[1,2,3,86,124,24,25,43,174,98],"212":[86,124,43],"219":[86,124,43],"234":[86,124],"246":[86,124],"247":[86,124,43],"254":[1,2,3,86,124,24,25,43,174,98],"266":[86,124,43],"267":[86,124,43],"268":[86,124,43],"270":[1,2,3,86,124,24,25,43,174,98],"271":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nDropdownMenu/composables/useDropdownSearch.ts":{"43":[86,124],"47":[86,124],"55":[86,124],"66":[86,124],"72":[86,124],"75":[86,124],"79":[86,124],"87":[86,124],"116":[86,124],"125":[86,124],"145":[1,2,86,124],"153":[86,124],"158":[1,2,86,124],"169":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/arrows-in--outline-16.svg":{"9":[2,86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/file-code--outline-16.svg":{"9":[1,2,86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/quotes--outline-16.svg":{"9":[1,2,86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/text-b--outline-16.svg":{"9":[1,2,86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/text-italics--outline-16.svg":{"9":[1,2,86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/text-strikethrough--outline-16.svg":{"9":[1,2,86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/text-underline--outline-16.svg":{"9":[1,2,86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIconPicker/IconPicker.vue":{"54":[1,2,86,156,21,124,175,45],"102":[86,124,45],"104":[86,124,45],"106":[86,124,45],"108":[86,124,45],"111":[1,2,86,156,21,124,175,45],"114":[86,124,45],"119":[1,2,86,156,21,124,175,45],"126":[86,124,45],"130":[86,124,45],"138":[86,124,45],"143":[86,124,45],"151":[86,124,45],"160":[1,2,86,156,21,124,175,45],"183":[1,2,86,156,21,124,175,45],"184":[1,2,86,156,21,124,175,45],"189":[86,124,45],"194":[1,2,86,156,21,124,175,45],"197":[86,124,45],"200":[86,124,45],"204":[86,124,45],"208":[86,124,45],"212":[86,124,45],"225":[86,124,45],"234":[86,124,45],"242":[86,124,45],"251":[86,124,45],"256":[86,124,45],"269":[86,124,45],"274":[86,124,45],"280":[86,124,45],"285":[86,124],"291":[86,124,45],"300":[86,124,45],"308":[86,124,45],"316":[86,124],"320":[86,124,45],"326":[86,124,45],"333":[86,156,124,45],"338":[86,124],"346":[86,124],"347":[86,124],"355":[86,124,45],"364":[86,124],"371":[86,124],"389":[86,124],"402":[86,124],"443":[86,124],"451":[1,2,86,156,21,124,175,45],"462":[1,2,86,156,21,124,175,45],"475":[86,124],"477":[1,2,86,156,21,124,175,45],"493":[86,124,45],"506":[86,124],"507":[86,124,45],"513":[86,124,45],"552":[86,124,45],"561":[86,124],"563":[86,124,45],"575":[86,124],"577":[86,124,45],"581":[86,124],"584":[86,124,45],"595":[86,124],"596":[86,124,45],"620":[86,124,45],"623":[86,124,45],"628":[86,124,45],"641":[86,124],"643":[86,124],"645":[86,124],"646":[86,124,45],"669":[86,124,45],"672":[86,124,45],"677":[86,124,45],"689":[86,124,45],"691":[86,124,45],"693":[86,124,45],"694":[86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nIconPicker/useIconPickerSearch.ts":{"24":[1,2,86,156,21,124,175,45],"32":[86,124],"39":[86,124],"47":[86,124],"48":[86,124],"49":[86,124],"63":[1,2,86,156,21,124,175,45],"101":[86,124,45],"107":[86,124,45],"112":[86,124],"113":[86,124],"117":[86,124,45],"123":[86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nIconPicker/useIconPickerVirtualRows.ts":{"30":[86,124,45],"40":[1,2,86,156,21,124,175,45],"60":[86,124,45],"68":[86,124],"72":[86,124],"75":[86,124],"79":[86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nMarkdownEditor/MarkdownEditor.vue":{"19":[1,2,86,124],"40":[1,2,86,124],"46":[1,2,86,124],"50":[1,2,86,124],"53":[86,124],"56":[86,124],"58":[1,2,86,124],"64":[1,2,86,124],"68":[1,2,86,124],"77":[86,124],"83":[1,2,86,124],"84":[86,124],"92":[86,124],"98":[1,2,86,124],"109":[1,2,86,124],"112":[1,2,86,124],"115":[1,2,86,124],"119":[1,2,86,124],"126":[86,124],"148":[86,124],"166":[86,124],"175":[1,2,86,124],"186":[86,124],"188":[86,124],"191":[86,124],"196":[86,124],"202":[86,124],"229":[86,124],"235":[1,2,86,124],"245":[86,124],"246":[86,124],"271":[86,124],"279":[86,124],"283":[86,124],"287":[86,124],"293":[86,124],"302":[86,124],"311":[86,124],"315":[86,124],"325":[1,2,86,124],"381":[86,124],"389":[1,2,86,124],"399":[86,124],"414":[86,124],"422":[86,124],"445":[86,124],"449":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nMarkdownEditor/MarkdownEditorExpandedViewButton.vue":{"10":[1,2,86,124],"27":[1,2,86,124],"33":[1,2,86,124],"37":[1,2,86,124],"43":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nMarkdownEditor/MarkdownEditorToolbar.vue":{"21":[1,2,86,124],"51":[1,2,86,124],"53":[86,124],"62":[1,2,86,124],"67":[86,124],"73":[86,124],"79":[86,124],"85":[86,124],"89":[1,2,86,124],"94":[86,124],"100":[86,124],"104":[1,2,86,124],"109":[86,124],"115":[86,124],"121":[86,124],"125":[1,2,86,124],"130":[86,124],"136":[86,124],"140":[1,2,86,124],"163":[1,2,86,124],"167":[1,2,86,124],"168":[86,124],"171":[1,2,86,124],"176":[1,2,86,124],"177":[86,124],"182":[1,2,86,124],"186":[1,2,86,124],"187":[86,124],"190":[1,2,86,124],"199":[1,2,86,124],"201":[1,2,86,124],"205":[1,2,86,124],"213":[86,124],"219":[86,124],"227":[86,124],"237":[86,124],"242":[86,124],"247":[86,124],"278":[86,124],"297":[1,2,86,124],"314":[1,2,86,124],"321":[1,2,86,124],"328":[1,2,86,124],"343":[1,2,86,124],"345":[1,2,86,124],"351":[86,124],"365":[1,2,86,124],"367":[1,2,86,124],"373":[86,124],"380":[86,124],"382":[1,2,86,124],"392":[86,124],"395":[86,124],"419":[86,124],"425":[86,124],"434":[86,124],"457":[1,2,86,124],"459":[1,2,86,124],"465":[86,124],"478":[1,2,86,124],"480":[1,2,86,124],"486":[86,124],"503":[86,124],"509":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nMarkdownEditor/composables/useMarkdownEditor.ts":{"31":[1,2,86,124],"37":[1,2,86,124],"39":[86,124],"45":[1,2,86,124],"55":[1,2,86,124],"87":[86,124],"90":[86,124],"95":[1,2,86,124],"98":[86,124],"104":[86,124],"107":[86,124],"112":[1,2,86,124],"113":[86,124],"125":[1,2,86,124],"126":[1,86,124]},"packages/frontend/@n8n/design-system/src/components/N8nMarkdownEditor/markdownEditorUtils.ts":{"8":[1,2,86,124],"10":[86,124],"25":[86,124],"35":[86,124],"45":[86,124],"48":[86,124],"51":[86,124],"62":[86,124],"71":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nSwitch/Switch.vue":{"10":[1,2,86,157,124],"14":[1,2,86,157,124],"21":[1,2,86,157,124],"26":[1,2,86,157,124],"30":[1,2,86,157,124],"38":[1,2,86,157,124],"48":[1,2,86,157,124],"56":[86,124],"57":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nToggle/Toggle.vue":{"22":[1,2,86,124],"36":[1,2,86,124],"41":[1,2,86,124],"47":[1,2,86,124],"52":[1,2,86,124],"67":[1,2,86,124],"69":[86,124],"74":[1,2,86,124],"78":[1,2,86,124],"86":[1,2,86,124],"103":[1,2,86,124],"119":[86,124],"136":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nToggleGroup/ToggleGroup.vue":{"30":[1,2,86,124],"31":[1,2,86,124],"47":[86,124],"48":[1,2,86,124]},"packages/frontend/@n8n/design-system/src/components/N8nVisuallyHidden/VisuallyHidden.vue":{"10":[1,2,86,124],"11":[1,2,86,124]},"packages/frontend/editor-ui/src/features/agents/agentSessions.store.ts":{"18":[1,2,3],"39":[1,2,3],"44":[1,2,3],"55":[1,2,3],"74":[1,2,3],"182":[2,3],"226":[1,2,3],"237":[1,2,3],"244":[1,2,3],"252":[1,2]},"packages/frontend/editor-ui/src/features/agents/agentTemplates.ts":{"59":[1,2]},"packages/frontend/editor-ui/src/features/agents/channels/n8nChat/useN8nChatChannel.ts":{"12":[1,2],"22":[1,2]},"packages/frontend/editor-ui/src/features/agents/channels/registry.ts":{"29":[1,2],"173":[1,2],"177":[1,2],"181":[1,2]},"packages/frontend/editor-ui/src/features/agents/channels/slack/useSlackChannelRuntime.ts":{"66":[1,2]},"packages/frontend/editor-ui/src/features/agents/channels/teams/useTeamsChannelRuntime.ts":{"71":[1,2],"77":[1,2]},"packages/frontend/editor-ui/src/features/agents/components/AgentBuilderEditorColumn.vue":{"36":[1,2],"70":[1,2],"79":[1,2],"80":[1,2],"149":[1,2],"179":[1,2],"192":[1,2],"209":[1,2],"216":[1,2],"248":[1,2]},"packages/frontend/editor-ui/src/features/agents/components/AgentBuilderHeader.vue":{"34":[1,2],"72":[1,2],"73":[1,2],"78":[1,2],"83":[1,2],"92":[1,2],"100":[1,2],"102":[1,2],"135":[1,2],"152":[1,2],"158":[1,2],"170":[1,2],"173":[1,2],"181":[1,2],"214":[1,2],"262":[1,2]},"packages/frontend/editor-ui/src/features/agents/components/AgentBuilderTabPanel.vue":{"2":[1,2]},"packages/frontend/editor-ui/src/features/agents/components/AgentCapabilitiesSection.utils.ts":{"29":[86,124],"56":[86,124],"61":[86,124],"66":[86,124],"67":[86,124],"68":[86,124],"69":[86,124],"71":[86,124],"83":[1,2,86,124],"117":[86,124]},"packages/frontend/editor-ui/src/features/agents/components/AgentCapabilitiesSection.vue":{"46":[1,2,86,124],"79":[1,2,86,124],"80":[1,2,86,124],"103":[1,2,86,124],"111":[1,2,86,124],"112":[1,2,86,124],"113":[1,2,86,124],"114":[86,124],"116":[86,124],"117":[86,124],"118":[86,124],"120":[1,2,86,124],"121":[86,124],"122":[86,124],"139":[86,124],"143":[86,124],"145":[86,124],"146":[86,124],"150":[86,124],"151":[86,124],"153":[86,124],"154":[86,124],"156":[86,124],"157":[86,124],"160":[1,2,86,124],"162":[1,2,86,124],"163":[86,124],"168":[1,2,86,124],"169":[86,124],"172":[1,2,86,124],"173":[86,124],"190":[86,124],"202":[1,2,86,124],"203":[86,124],"209":[86,124],"217":[86,124],"238":[86,124],"246":[86,124],"262":[86,124],"277":[86,124],"283":[1,2,86,124],"285":[86,124],"310":[1,2,86,124],"312":[86,124],"318":[1,2,86,124],"320":[86,124],"323":[86,124],"326":[1,2,86,124],"333":[1,2,86,124],"334":[1,2,86,124],"341":[1,2,86,124],"342":[1,2,86,124],"346":[86,124],"351":[86,124],"370":[86,124],"373":[86,124],"387":[86,124],"395":[86,124],"401":[86,124],"405":[86,124],"409":[86,124],"412":[86,124],"416":[86,124],"419":[86,124],"420":[86,124],"423":[86,124],"425":[86,124],"428":[86,124],"437":[86,124],"438":[86,124],"446":[86,124],"457":[86,124],"458":[86,124],"468":[86,124],"471":[86,124],"475":[86,124],"487":[86,124],"503":[86,124],"505":[86,124],"513":[1,2,86,124],"519":[1,2,86,124],"527":[86,124],"528":[1,2,86,124],"529":[86,124],"537":[86,124],"539":[86,124],"540":[86,124],"541":[86,124],"551":[86,124],"553":[86,124],"561":[86,124],"566":[86,124],"567":[86,124],"568":[86,124],"575":[86,124],"583":[86,124],"599":[86,124],"600":[86,124],"619":[86,124],"620":[86,124],"621":[86,124],"632":[86,124],"634":[86,124],"636":[86,124],"650":[86,124],"651":[86,124],"665":[86,124],"666":[1,2,86,124],"668":[86,124],"675":[86,124],"676":[86,124],"677":[86,124],"688":[86,124],"689":[86,124],"701":[86,124],"702":[86,124],"703":[86,124],"714":[1,2,86,124],"715":[86,124],"719":[86,124],"720":[86,124],"721":[86,124],"730":[86,124],"731":[86,124],"743":[86,124]},"packages/frontend/editor-ui/src/features/agents/components/AgentChatEmptyState.vue":{"8":[2],"24":[2]},"packages/frontend/editor-ui/src/features/agents/components/AgentChatMessageList.vue":{"174":[2],"259":[2],"432":[2],"476":[2],"484":[2],"499":[2],"504":[2],"516":[2]},"packages/frontend/editor-ui/src/features/agents/components/AgentChatPanel.vue":{"261":[2],"277":[2],"295":[2],"298":[2],"305":[2],"463":[2],"464":[2],"465":[2],"466":[2],"467":[2],"468":[2],"470":[2],"473":[2],"509":[2],"512":[2],"577":[2],"586":[2],"601":[2],"667":[2],"671":[2],"699":[2],"703":[2],"712":[2],"713":[2],"714":[2],"715":[2],"757":[2],"762":[2],"766":[2],"821":[2],"830":[2],"882":[2],"883":[2],"888":[2],"906":[2],"912":[2],"917":[2],"920":[2],"929":[2],"933":[2],"974":[2],"982":[2],"993":[2],"1040":[2],"1043":[2],"1048":[2],"1052":[2],"1060":[2],"1061":[2],"1062":[2],"1066":[2],"1069":[2],"1076":[2],"1272":[2],"1393":[2],"1655":[2],"1714":[2]},"packages/frontend/editor-ui/src/features/agents/components/AgentChipRow.vue":{"4":[1,2,86,124],"26":[1,2,86,124],"33":[86,124],"41":[86,124],"48":[86,124],"50":[86,124],"63":[86,124],"64":[1,2,86,124]},"packages/frontend/editor-ui/src/features/agents/components/AgentCollaborationBanner.vue":{"10":[1,2],"14":[1,2],"39":[1],"52":[1],"65":[1],"66":[1],"67":[1],"73":[1],"78":[1,2],"91":[1],"98":[1],"102":[1]},"packages/frontend/editor-ui/src/features/agents/components/AgentIdentityHeader.vue":{"12":[1,2],"32":[1,2],"33":[1,2],"43":[1,2],"58":[1,2],"66":[1,2]},"packages/frontend/editor-ui/src/features/agents/components/AgentInfoPanel.vue":{"45":[1,2,86,124],"81":[1,2,86,124],"89":[1,2,86,124],"96":[1,2,86,124],"105":[1,2,86,124],"119":[1,2,86,124],"123":[1,2,86,124],"129":[86,124],"155":[1,2,86,124],"156":[1,2,86,124],"177":[1,2,86,124],"189":[1,2,86,124],"190":[86,124],"206":[86,124],"214":[86,124],"216":[86,124],"222":[86,124],"233":[86,124],"238":[86,124],"243":[86,124],"301":[1,2,86,124],"305":[86,124],"331":[1,2,86,124],"337":[1,2,86,124],"348":[86,124],"361":[1,2,86,124],"362":[86,124],"368":[86,124],"372":[86,124],"376":[86,124],"380":[86,124],"390":[1,2,86,124],"397":[1,2,86,124],"403":[1,2,86,124],"404":[1,2,86,124],"407":[1,2,86,124],"430":[86,124],"444":[86,124],"457":[86,124],"465":[86,124],"466":[86,124],"470":[86,124],"486":[1,2,86,124],"487":[1,2,86,124],"490":[1,2,86,124]},"packages/frontend/editor-ui/src/features/agents/components/AgentMemoryPanel.vue":{"22":[1,2],"35":[1,2],"36":[1,2],"92":[1,2],"100":[1,2],"102":[1,2],"103":[1,2],"109":[1,2],"112":[1,2]},"packages/frontend/editor-ui/src/features/agents/components/AgentModelSelector.vue":{"45":[1,2,86,124],"108":[1,2,86,124],"112":[86,124],"126":[1,2,86,124],"132":[1,2,86,124],"136":[86,124],"143":[1,2,86,124],"153":[1,2,86,124],"155":[1,2,86,124],"161":[1,2,86,124],"170":[1,2,86,124],"174":[1,2,86,124],"178":[1,2,86,124],"182":[86,124],"188":[86,124],"192":[1,2,86,124],"196":[1,2,86,124],"200":[1,2,86,124],"214":[86,124],"217":[1,2,86,124],"221":[86,124],"227":[1,2,86,124],"228":[1,2,86,124],"232":[1,2,86,124],"235":[1,2,86,124],"241":[86,124],"247":[86,124],"252":[1,2,86,124],"278":[86,124],"281":[86,124],"306":[1,2,86,124],"319":[86,124],"369":[86,124],"471":[1,2,86,124],"475":[1,2,86,124],"478":[86,124],"488":[1,2,86,124],"525":[1,2,86,124],"533":[86,124],"544":[86,124],"545":[86,124],"551":[86,124],"558":[1,2,86,124],"561":[86,124],"562":[86,124],"584":[86,124],"593":[1,2,86,124],"606":[86,124],"630":[86,124],"642":[86,124],"665":[86,124],"710":[86,124],"714":[86,124],"722":[1,2,86,124],"741":[1,2,86,124],"748":[86,124],"752":[86,124],"756":[86,124],"764":[86,124]},"packages/frontend/editor-ui/src/features/agents/components/AgentPanel.vue":{"13":[1,2,86,124],"19":[1,2,86,124],"32":[1,2,86,124]},"packages/frontend/editor-ui/src/features/agents/components/AgentPanelHeader.vue":{"18":[1,2,86,124],"24":[1,2,86,124],"27":[1,2,86,124],"28":[1,2,86,124]},"packages/frontend/editor-ui/src/features/agents/components/AgentPersonalisationIcon.vue":{"8":[2,86,124],"16":[2,86,124],"24":[2,86,124],"34":[2,86,124],"35":[2,86,124]},"packages/frontend/editor-ui/src/features/agents/components/AgentPreviewButton.vue":{"33":[1,2],"34":[1,2],"39":[1,2]},"packages/frontend/editor-ui/src/features/agents/components/AgentPreviewChatPage.vue":{"14":[1,2],"55":[2],"68":[1,2],"77":[1,2],"106":[2]},"packages/frontend/editor-ui/src/features/agents/components/AgentPreviewMoreMenu.vue":{"34":[1,2],"63":[1,2],"67":[1,2],"120":[2],"130":[2],"209":[2],"250":[1,2],"272":[2],"278":[1,2],"284":[1,2],"298":[1,2],"308":[2],"318":[2]},"packages/frontend/editor-ui/src/features/agents/components/AgentPublishButton.vue":{"14":[1,2],"53":[1,2],"62":[1,2],"65":[1,2],"69":[1,2],"96":[1,2],"105":[1,2],"107":[1,2],"172":[1,2],"182":[1,2],"190":[1,2],"214":[1,2]},"packages/frontend/editor-ui/src/features/agents/components/AgentSchedulesRow.vue":{"15":[1,2],"57":[1,2],"91":[1,2],"105":[1,2],"202":[1,2],"262":[1,2]},"packages/frontend/editor-ui/src/features/agents/components/AgentSessionHistoryDropdown.vue":{"19":[1,2],"45":[1,2],"61":[1,2],"72":[1,2],"89":[1,2]},"packages/frontend/editor-ui/src/features/agents/components/AgentSetupTasks/AgentSetupTasks.vue":{"10":[1,2],"25":[1,2],"40":[1,2],"42":[1,2],"43":[1,2],"46":[1,2],"47":[1,2],"50":[1,2],"56":[1,2],"57":[1,2],"60":[1,2],"100":[1,2],"115":[1,2],"122":[2],"150":[1,2],"153":[1,2]},"packages/frontend/editor-ui/src/features/agents/components/AgentSetupTasks/agentSetupTasks.registry.ts":{"55":[1,2],"61":[1,2],"67":[1,2],"73":[1,2],"81":[1,2],"85":[1,2],"100":[1,2],"109":[1,2],"119":[1,2],"137":[1,2],"146":[1,2]},"packages/frontend/editor-ui/src/features/agents/components/AgentSetupTasks/useAgentSetupTasks.ts":{"15":[1,2],"16":[1,2],"17":[1,2],"31":[1,2],"32":[1,2],"34":[1,2],"37":[1,2]},"packages/frontend/editor-ui/src/features/agents/components/AgentSkillsSection.vue":{"13":[1,2,86,124],"37":[86,124],"38":[86,124],"39":[86,124],"41":[86,124],"42":[86,124],"49":[86,124],"59":[1,2,86,124],"70":[86,124],"71":[1,2,86,124],"72":[86,124],"73":[86,124],"74":[86,124],"83":[86,124],"84":[86,124]},"packages/frontend/editor-ui/src/features/agents/components/AgentTriggersSection.vue":{"28":[1,2],"86":[1,2],"90":[1,2],"105":[1,2],"106":[1,2],"108":[1,2],"165":[1,2],"191":[1,2],"197":[1,2],"213":[1,2],"269":[1,2],"284":[1,2]},"packages/frontend/editor-ui/src/features/agents/components/AgentTypingIndicator.vue":{"2":[2]},"packages/frontend/editor-ui/src/features/agents/components/AgentValidationTooltip.vue":{"23":[1,2],"245":[1,2],"258":[1,2]},"packages/frontend/editor-ui/src/features/agents/components/AgentWebSearchSection.vue":{"57":[1,2,86,124],"64":[1,2,86,124],"70":[86,124],"87":[1,2,86,124],"88":[1,2,86,124],"89":[86,124],"90":[86,124],"96":[1,2,86,124],"123":[1,2,86,124],"124":[1,2,86,124],"142":[1,2,86,124],"159":[1,2,86,124],"160":[86,124],"175":[86,124],"180":[86,124],"197":[86,124],"211":[86,124],"212":[86,124],"220":[86,124],"223":[86,124],"226":[86,124],"231":[86,124],"252":[86,124],"268":[86,124],"272":[86,124],"277":[86,124],"301":[86,124],"316":[86,124],"328":[86,124],"345":[1,2,86,124],"354":[1,2,86,124],"357":[1,2,86,124],"370":[1,2,86,124],"372":[1,2,86,124],"391":[86,124],"394":[86,124],"420":[86,124],"423":[86,124],"446":[86,124],"449":[86,124],"466":[86,124],"469":[86,124]},"packages/frontend/editor-ui/src/features/agents/components/model-selector/ModelSelectorTriggerIcon.vue":{"12":[1,2,86,124]},"packages/frontend/editor-ui/src/features/agents/components/model-selector/menuItemId.ts":{"5":[1,2,86,124],"15":[86,124]},"packages/frontend/editor-ui/src/features/agents/composables/agentTelemetry.utils.ts":{"102":[2]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentApi.ts":{"44":[86,124],"48":[86,124],"68":[2,86,124],"80":[86,124],"108":[1,2,86,124],"121":[86,124],"129":[86,124],"155":[86,124],"180":[86,124],"194":[86,124],"217":[86,124],"229":[86,124],"242":[1,2,86,124],"263":[1,2,3,86,124],"275":[86,124],"303":[86,124],"320":[86,124],"330":[86,124],"338":[86,124],"350":[86,124],"369":[86,124],"382":[86,124],"401":[86,124],"424":[86,124],"440":[1,2,86,124],"452":[86,124],"464":[1,2,86,124],"476":[86,124],"490":[86,124],"505":[86,124],"541":[1,2,86,124],"552":[86,124],"566":[86,124],"580":[86,124],"592":[86,124],"604":[86,124],"618":[86,124],"632":[86,124],"644":[1,2,3,86,124],"662":[1,2,86,124],"674":[86,124],"686":[86,124],"701":[86,124],"715":[86,124],"731":[2,86,124],"745":[86,124],"761":[86,124],"775":[2,86,124],"789":[86,124],"806":[86,124],"823":[86,124],"838":[86,124],"855":[2,86,124],"870":[86,124],"879":[86,124],"891":[86,124],"903":[86,124],"917":[86,124],"945":[86,124],"958":[1,2,86,124],"969":[1,2,86,124]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentBackgroundJobs.ts":{"32":[2],"38":[2],"49":[2],"58":[2],"63":[2],"76":[2],"121":[2],"128":[2],"185":[2],"197":[2],"198":[2],"199":[2],"213":[2],"224":[2]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentBuilderMainTabs.ts":{"21":[1,2],"43":[1,2],"65":[1,2],"77":[1,2],"100":[1,2],"110":[1,2],"111":[1,2]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentBuilderSession.ts":{"46":[1,2,3],"55":[1,2,3],"67":[1,2],"73":[1,2],"77":[1,2,3],"83":[2],"98":[2],"109":[2],"131":[1,2,3],"139":[1,2,3],"149":[1,2,3],"170":[2,3],"188":[1,2,3],"195":[1,2],"203":[1,2],"208":[1,2],"214":[1,2],"215":[1,2],"220":[1,2],"237":[1,2,3]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentBuilderTelemetry.ts":{"39":[1,2],"65":[1,2],"128":[1,2]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentCapabilityIssueMessages.ts":{"9":[1,2,86,124],"14":[86,124],"20":[86,124],"24":[86,124],"27":[86,124],"38":[86,124]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentChannelRemoval.ts":{"14":[1,2],"38":[1]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentChatStream.ts":{"119":[2],"163":[2],"191":[2],"220":[2],"227":[2],"240":[2],"322":[2],"363":[2],"522":[2],"547":[2]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentConfigAutosave.ts":{"51":[1,2],"84":[1,2],"219":[1,2],"232":[1,2],"273":[1,2],"295":[1,2]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentConfigValidation.ts":{"13":[1,2],"20":[1,2],"29":[1,2],"45":[1,2]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentExecutionUpdates.ts":{"20":[2,3],"27":[2],"61":[2]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentIntegrationStatus.ts":{"61":[1,2],"101":[1,2],"156":[1,2],"166":[1,2],"170":[1,2],"177":[1,2]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentIntegrationsCatalog.ts":{"9":[1,2],"12":[1,2],"15":[1,2],"28":[1,2]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentModelCredentials.ts":{"16":[86,124],"34":[1,2,86,124],"41":[1,2,86,124],"43":[86,124],"56":[1,2,86,124],"61":[1,2,86,124],"68":[1,2,86,124],"84":[86,124],"89":[1,2,86,124],"104":[86,124],"116":[86,124],"120":[1,2,86,124],"122":[1,2,86,124]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentProjectBreadcrumb.ts":{"7":[1,2,3],"11":[1,2,3],"18":[1,2,3],"23":[1,2,3]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentProjectId.ts":{"14":[1,2,86,124],"20":[1,2,86,124]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentPublish.ts":{"16":[1,2]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentSessionLangSmithExport.ts":{"18":[1,2,3],"26":[1,2,3]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentThreadsApi.ts":{"49":[1,2,3],"122":[1,2,3],"125":[1,2,3],"150":[2,3]},"packages/frontend/editor-ui/src/features/agents/composables/useFixWithAssistantCalloutDismissal.ts":{"18":[2],"26":[2],"43":[2],"60":[1,2],"64":[1,2]},"packages/frontend/editor-ui/src/features/agents/composables/useModelCatalog.ts":{"39":[1,2,86,124],"47":[86,124],"61":[1,2,86,124],"65":[86,124],"71":[1,2,86,124],"75":[1,2,86,124],"83":[1,2,86,124],"86":[86,124],"89":[1,2,86,124],"98":[86,124],"101":[86,124],"110":[86,124],"121":[86,124],"136":[86,124],"143":[86,124],"148":[86,124],"156":[1,2,86,124],"183":[86,124],"185":[86,124],"193":[86,124],"207":[86,124]},"packages/frontend/editor-ui/src/features/agents/composables/useProjectAgentsList.ts":{"19":[1,2,86,124],"28":[1,2,3,86,124],"30":[1,2,86,124],"35":[1,2,86,124],"42":[1,2,86,124],"47":[86,124],"55":[86,124],"66":[1,2,86,124],"72":[86,124],"78":[86,124],"81":[86,124],"87":[86,124]},"packages/frontend/editor-ui/src/features/agents/model-providers.ts":{"66":[1,2,86,124]},"packages/frontend/editor-ui/src/features/agents/stores/agentCollaboration.store.ts":{"25":[1,2],"50":[1,2],"55":[1],"63":[1,2],"68":[1,2],"70":[1,2],"85":[1,2],"99":[1,2],"106":[1,2],"111":[1],"138":[1],"168":[1],"193":[1,2],"200":[1,2],"264":[1,2],"267":[1],"276":[1,2],"311":[1,2]},"packages/frontend/editor-ui/src/features/agents/utils/agent-plan.ts":{"95":[2],"182":[2]},"packages/frontend/editor-ui/src/features/agents/utils/agentSectionEditor.utils.ts":{"7":[1,2],"8":[1,2]},"packages/frontend/editor-ui/src/features/agents/utils/errors.ts":{"10":[2]},"packages/frontend/editor-ui/src/features/agents/utils/model-string.ts":{"15":[1,2,86,124],"22":[1,2,86,124],"31":[1,2,86,124],"44":[86,124]},"packages/frontend/editor-ui/src/features/agents/utils/nativeWebSearch.ts":{"17":[86,124],"23":[86,124],"34":[86,124],"43":[1,2,86,124],"49":[86,124],"58":[86,124],"59":[86,124],"65":[86,124],"94":[86,124],"138":[86,124]},"packages/frontend/editor-ui/src/features/agents/utils/relative-time.ts":{"102":[2]},"packages/frontend/editor-ui/src/features/agents/utils/validationIssues.ts":{"7":[1,2,86,124],"12":[1,2,86,124],"13":[1,2,86,124]},"packages/frontend/editor-ui/src/features/agents/views/AgentBuilderView.vue":{"248":[1,2],"256":[1,2],"257":[1,2],"260":[1,2],"267":[1,2],"271":[1,2],"275":[1,2],"285":[1,2],"289":[1,2],"293":[1,2],"305":[1,2],"319":[1,2],"320":[1,2],"330":[1,2],"334":[1,2],"342":[1,2],"373":[1,2],"378":[1,2],"489":[1,2],"535":[1,2],"552":[2],"594":[1,2],"609":[1,2],"619":[1,2],"620":[1,2],"637":[1,2],"644":[1,2],"645":[1,2],"774":[1,2],"796":[1,2],"803":[1,2],"806":[1,2],"825":[1,2],"887":[1,2],"890":[1,2],"896":[1,2],"920":[1,2],"923":[1,2],"933":[1,2],"949":[1,2],"977":[1,2],"991":[1,2],"1272":[2],"1277":[2],"1286":[1,2],"1613":[1,2],"1662":[1,2],"1693":[1],"1787":[2],"1877":[1],"2157":[1,2],"2241":[1,2],"2285":[1],"2304":[1,2],"2324":[1,2],"2341":[1,2],"2361":[1,2],"2617":[1,2],"2624":[1,2],"2630":[1,2],"2771":[1,2],"2778":[1,2],"2782":[1,2],"2847":[1,2],"2909":[1,2],"2917":[1,2],"2926":[2],"2972":[1,2],"2981":[1,2],"2989":[2],"3047":[2],"3119":[1,2],"3139":[1,2],"3149":[1,2]},"packages/frontend/editor-ui/src/features/agents/views/AgentView.vue":{"22":[1,2,3],"26":[1,2,3]},"packages/frontend/editor-ui/src/features/ai/shared/agentsChat/displayGroups.ts":{"94":[2],"98":[2],"219":[2]},"packages/frontend/editor-ui/src/features/ai/shared/agentsChat/messageMappers.ts":{"104":[2]},"packages/modules/type-availability-policies/frontend/src/components/ContactInstanceAdminModal.vue":{"18":[1,2,86,124,66],"26":[1,2,86,124,66],"31":[86,124],"37":[86,124],"38":[86,124],"45":[1,2,86,124,66],"51":[86,124],"57":[86,124],"59":[1,2,86,124,66],"70":[86,124],"77":[86,124],"80":[86,124],"82":[86,124],"94":[86,124]},"packages/@n8n/ai-utilities/src/model-discovery/providers/anthropic.ts":{"5":[18,19,20],"15":[18,19,20],"16":[18,19,20]},"packages/@n8n/chat-hub/src/artifact.ts":{"3":[86,18,155,19,156,20,21,124],"19":[86,18,19,20,124]},"packages/@n8n/chat-hub/src/parser.ts":{"12":[86,18,155,19,156,20,21,124],"117":[86,18,155,19,156,20,21,124],"134":[86,18,155,19,156,20,21,124],"159":[86,18,19,20,124],"187":[86,18,19,20,124],"217":[86,18,19,20,124],"250":[86,18,155,19,156,20,21,124],"275":[18,19,20]},"packages/@n8n/db/src/repositories/project-secrets-provider-access.repository.ee.ts":{"9":[18,20,60],"12":[18,20,60],"21":[18,20,60],"28":[18,20,60],"35":[18,20,60],"43":[18,20,60],"54":[18,20,60]},"packages/@n8n/db/src/utils/transaction.ts":{"15":[18,19,20,24,25,194]},"packages/@n8n/nodes-langchain/nodes/llms/LMChatAnthropic/LmChatAnthropic.node.ts":{"100":[13,18,19,20,21,139],"126":[13,18,19,20,21,139],"194":[13,18,19,20,21,139],"557":[13,18,19,20,21,139],"673":[13,18,19,20,21,139],"691":[13,18,19,20,21,139],"709":[13,18,19,20,21,139],"745":[13,18,19,20,21,139]},"packages/@n8n/nodes-langchain/nodes/llms/LMChatAnthropic/methods/searchModels.ts":{"7":[13,18,19,20,139],"23":[13,18,19,20,139],"28":[13,18,19,20,139],"29":[13,18,19,20,139]},"packages/@n8n/nodes-langchain/nodes/memory/MemoryBufferWindow/MemoryBufferWindow.node.ts":{"30":[18,19,20],"34":[18,19,20],"41":[18,19,20],"63":[18,19,20],"75":[18,19,20],"158":[18,19,20]},"packages/@n8n/nodes-langchain/nodes/memory/MemoryManager/MemoryManager.node.ts":{"20":[18,19,20],"47":[18,19,20],"50":[18,19,20],"53":[18,19,20],"63":[18,19,20],"73":[18,19,20],"302":[18,19,20],"400":[18,19,20]},"packages/@n8n/utils/src/files/sanitize-filename.ts":{"55":[18,43]},"packages/cli/src/credentials/credential-connection-status-proxy.ts":{"19":[18,20,21,222,44],"23":[18,20,21,222,44],"31":[18,20,21,222,44],"36":[18,20,21,222,44],"41":[18,20,21,222,44],"50":[18,20,21,222,44]},"packages/cli/src/modules/chat-hub/chat-hub-agent.repository.ts":{"9":[18,19,156,20],"13":[18,19,156,20],"24":[18,19,156,20],"32":[18,19,156,20],"37":[18,19,156,20],"44":[18,19,156,20],"53":[18,19,156,20]},"packages/cli/src/modules/chat-hub/chat-hub-agent.service.ts":{"35":[18,19,156,20,194],"50":[18,19,156,20,194],"53":[18,19,156,20,194],"56":[18,19,156,20,194],"57":[18,19,156,20,194],"76":[18,19,156,20,194],"80":[18,19,156,20,194],"88":[18,19,156,20,194],"95":[18,19,156,20,194],"123":[18,19,156,20,194],"163":[18,19,156,20,194],"182":[18,19,156,20,194],"203":[18,19,156,20,194],"215":[18,19,156,20,194],"230":[18,19,156,20,194],"264":[18,19,156,20,194],"287":[18,19,156,20,194],"309":[18,19,156,20,194],"334":[18,19,156,20,194],"349":[18,19,156,20,194],"360":[18,19,156,20,194],"375":[18,19,156,20,194],"384":[18,19,156,20,194],"394":[18,19,156,20,194],"400":[18,19,156,20,194],"403":[18,19,156,20,194],"418":[18,19,156,20,194],"426":[18,19,156,20,194],"451":[18,19,156,20,194]},"packages/cli/src/modules/chat-hub/chat-hub-credentials.service.ts":{"17":[18,19,156,20,21],"24":[18,19,156,20,21],"37":[18,19,156,20,21],"48":[18,19,156,20,21],"61":[18,19,156,20,21],"70":[18,19,156,20,21],"90":[18,19,156,20,21]},"packages/cli/src/modules/chat-hub/chat-hub-execution.service.ts":{"50":[18,19,20,21],"67":[18,19,20,21],"78":[18,19,20,21],"90":[18,19,20,21],"155":[18,19,20,21],"206":[18,19,20,21],"227":[18,19,20,21],"250":[18,19,20,21],"253":[18,19,20,21],"263":[18,19,20,21],"273":[18,19,20,21],"302":[18,19,20,21],"367":[18,19,20,21],"446":[18,19,20,21],"488":[18,19,20,21],"496":[18,19,20,21],"497":[18,19,20,21],"498":[18,19,20,21],"540":[18,19,20,21],"569":[18,19,20,21],"609":[18,19,20,21],"623":[18,19,20,21],"628":[18,19,20,21],"630":[18,19,20,21],"634":[18,19,20,21],"640":[18,19,20,21],"652":[18,19,20,21],"658":[18,19,20,21],"660":[18,19,20,21],"661":[18,19,20,21],"662":[18,19,20,21],"663":[18,19,20,21],"666":[18,19,20,21],"673":[18,19,20,21],"692":[18,19,20,21],"713":[18,19,20,21],"733":[18,19,20,21],"746":[18,19,20,21]},"packages/cli/src/modules/chat-hub/chat-hub-extractor.ts":{"33":[18,19,20],"53":[18,19,20],"67":[18,19,20],"73":[18,19,20]},"packages/cli/src/modules/chat-hub/chat-hub-title.service.ts":{"39":[18,19,156,20,21],"53":[18,19,156,20,21],"80":[18,19,156,20,21],"88":[18,19,156,20,21],"124":[18,19,156,20,21],"152":[18,19,156,20,21],"186":[18,19,156,20,21],"259":[18,19,156,20,21],"260":[18,19,156,20,21],"262":[18,19,156,20,21],"272":[18,19,156,20,21]},"packages/cli/src/modules/chat-hub/chat-hub-tool.repository.ts":{"10":[18,19,156,20],"14":[18,19,156,20],"22":[18,19,156,20],"30":[18,19,156,20],"35":[18,19,156,20],"42":[18,19,156,20],"50":[18,19,156,20],"57":[18,19,156,20],"68":[18,19,156,20],"79":[18,19,156,20],"90":[18,19,156,20],"98":[18,19,156,20],"101":[18,19,156,20],"109":[18,19,156,20],"112":[18,19,156,20],"122":[18,19,156,20]},"packages/cli/src/modules/chat-hub/chat-hub-tool.service.ts":{"21":[18,19,156,20],"30":[18,19,156,20],"34":[18,19,156,20],"38":[18,19,156,20],"40":[18,19,156,20],"43":[18,19,156,20],"45":[18,19,156,20],"48":[18,19,156,20],"52":[18,19,156,20],"56":[18,19,156,20],"60":[18,19,156,20],"64":[18,19,156,20],"80":[18,19,156,20],"87":[18,19,156,20],"106":[18,19,156,20],"113":[18,19,156,20],"148":[18,19,156,20],"150":[18,19,156,20],"162":[18,19,156,20]},"packages/cli/src/modules/chat-hub/chat-hub-workflow.service.ts":{"88":[18,19,156,20,21],"105":[18,19,156,20,21],"111":[18,19,156,20,21],"172":[18,19,156,20,21],"196":[18,19,156,20,21],"213":[18,19,156,20,21],"262":[18,19,156,20,21],"285":[18,19,156,20,21],"300":[18,19,156,20,21],"314":[18,19,156,20,21],"330":[18,19,156,20,21],"333":[18,19,156,20,21],"340":[18,19,156,20,21],"341":[18,19,156,20,21],"355":[18,19,156,20,21],"402":[18,19,156,20,21],"418":[18,19,156,20,21],"468":[18,19,156,20,21],"469":[18,19,156,20,21],"532":[18,19,156,20,21],"602":[18,19,156,20,21],"667":[18,19,156,20,21],"679":[18,19,156,20,21],"760":[18,19,156,20,21],"768":[18,19,156,20,21],"794":[18,19,156,20,21],"956":[18,19,156,20,21],"971":[18,19,156,20,21],"993":[18,19,156,20,21],"1063":[18,19,156,20,21],"1123":[18,19,156,20,21],"1134":[18,19,156,20,21],"1148":[18,19,156,20,21],"1164":[18,19,156,20,21],"1165":[18,19,156,20,21],"1172":[18,19,156,20,21],"1197":[18,19,156,20,21],"1210":[18,19,156,20,21],"1245":[18,19,156,20,21],"1248":[18,19,156,20,21],"1259":[18,19,156,20,21],"1270":[18,19,156,20,21],"1328":[18,19,156,20,21],"1345":[18,19,156,20,21],"1374":[18,19,156,20,21],"1385":[18,19,156,20,21],"1401":[18,19,156,20,21],"1472":[18,19,156,20,21],"1486":[18,19,156,20,21],"1500":[18,19,156,20,21],"1530":[18,19,156,20,21],"1560":[18,19,156,20,21],"1568":[18,19,156,20,21],"1571":[18,19,156,20,21],"1625":[18,19,156,20,21],"1634":[18,19,156,20,21],"1638":[18,19,156,20,21],"1643":[18,19,156,20,21],"1656":[18,19,156,20,21],"1665":[18,19,156,20,21],"1683":[18,19,156,20,21],"1690":[18,19,156,20,21],"1719":[18,19,156,20,21],"1745":[18,19,156,20,21],"1866":[18,19,156,20,21],"1911":[18,19,156,20,21]},"packages/cli/src/modules/chat-hub/chat-hub.attachment.service.ts":{"18":[18,19,20],"27":[18,19,20],"54":[18,19,20],"84":[18,19,20],"128":[18,19,20],"131":[18,19,20],"137":[18,19,20],"145":[18,19,20],"151":[18,19,20],"153":[18,19,20],"157":[18,19,20],"169":[18,19,20],"173":[18,19,20],"195":[18,19,20],"196":[18,19,20],"211":[18,19,20]},"packages/cli/src/modules/chat-hub/chat-hub.constants.ts":{"694":[18,19,20],"719":[18,19,20]},"packages/cli/src/modules/chat-hub/chat-hub.controller.ts":{"62":[18,19,156,20],"72":[18,19,156,20],"86":[18,19,156,20],"96":[18,19,156,20],"111":[18,19,156,20],"121":[18,19,156,20],"159":[18,19,156,20],"168":[18,19,156,20],"194":[18,19,156,20],"224":[18,19,156,20],"249":[18,19,156,20],"283":[18,19,156,20],"308":[18,19,156,20],"342":[18,19,156,20],"358":[18,19,156,20],"374":[18,19,156,20],"389":[18,19,156,20],"401":[18,19,156,20],"403":[18,19,156,20],"408":[18,19,156,20],"420":[18,19,156,20],"435":[18,19,156,20],"446":[18,19,156,20],"452":[18,19,156,20],"462":[18,19,156,20],"473":[18,19,156,20],"487":[18,19,156,20],"510":[18,19,156,20],"520":[18,19,156,20]},"packages/cli/src/modules/chat-hub/chat-hub.models.service.ts":{"32":[18,19,20,21],"41":[18,19,20,21],"54":[18,19,20,21],"64":[18,19,20,21],"90":[18,19,20,21],"98":[18,19,20,21],"172":[18,19,20,21],"188":[18,19,20,21],"204":[18,19,20,21],"256":[18,19,20,21],"301":[18,19,20,21],"311":[18,19,20,21],"318":[18,19,20,21],"335":[18,19,20,21],"384":[18,19,20,21],"433":[18,19,20,21],"477":[18,19,20,21],"520":[18,19,20,21],"563":[18,19,20,21],"606":[18,19,20,21],"649":[18,19,20,21],"692":[18,19,20,21],"704":[18,19,20,21],"706":[18,19,20,21],"726":[18,19,20,21],"735":[18,19,20,21],"736":[18,19,20,21],"743":[18,19,20,21],"751":[18,19,20,21],"797":[18,19,20,21],"802":[18,19,20,21],"803":[18,19,20,21],"807":[18,19,20,21],"808":[18,19,20,21],"817":[18,19,20,21],"823":[18,19,20,21]},"packages/cli/src/modules/chat-hub/chat-hub.service.ts":{"56":[18,19,20,21],"77":[18,19,20,21],"88":[18,19,20,21],"114":[18,19,20,21],"179":[18,19,20,21],"203":[18,19,20,21],"210":[18,19,20,21],"214":[18,19,20,21],"241":[18,19,20,21],"249":[18,19,20,21],"265":[18,19,20,21],"278":[18,19,20,21],"287":[18,19,20,21],"297":[18,19,20,21],"309":[18,19,20,21],"317":[18,19,20,21],"334":[18,19,20,21],"338":[18,19,20,21],"347":[18,19,20,21],"391":[18,19,20,21],"392":[18,19,20,21],"399":[18,19,20,21],"438":[18,19,20,21],"452":[18,19,20,21],"476":[18,19,20,21],"490":[18,19,20,21],"522":[18,19,20,21],"566":[18,19,20,21],"603":[18,19,20,21],"631":[18,19,20,21],"644":[18,19,20,21],"723":[18,19,20,21],"761":[18,19,20,21],"776":[18,19,20,21],"789":[18,19,20,21],"795":[18,19,20,21],"868":[18,19,20,21],"894":[18,19,20,21],"914":[18,19,20,21],"927":[18,19,20,21],"933":[18,19,20,21],"1022":[18,19,20,21],"1049":[18,19,20,21],"1058":[18,19,20,21],"1070":[18,19,20,21],"1073":[18,19,20,21],"1129":[18,19,20,21],"1143":[18,19,20,21],"1155":[18,19,20,21],"1158":[18,19,20,21],"1217":[18,19,20,21],"1244":[18,19,20,21],"1287":[18,19,20,21],"1307":[18,19,20,21],"1314":[18,19,20,21]},"packages/cli/src/modules/chat-hub/chat-hub.settings.controller.ts":{"18":[18,19,157,20],"27":[18,19,157,20],"39":[18,19,157,20],"46":[18,19,157,20],"61":[18,19,157,20],"75":[18,19,157,20],"88":[18,19,157,20]},"packages/cli/src/modules/chat-hub/chat-hub.settings.service.ts":{"21":[18,19,156,157,20,194],"26":[18,19,156,157,20,194],"37":[18,19,156,157,20,194],"39":[18,19,156,157,20,194],"48":[18,19,156,157,20,194],"55":[18,19,156,157,20,194],"68":[18,19,156,157,20,194],"76":[18,19,156,157,20,194],"93":[18,19,156,157,20,194],"115":[18,19,156,157,20,194],"125":[18,19,156,157,20,194],"141":[18,19,156,157,20,194],"152":[18,19,156,157,20,194]},"packages/cli/src/modules/chat-hub/chat-message.repository.ts":{"19":[18,19,20],"27":[18,19,20],"40":[18,19,20],"50":[18,19,20],"76":[18,19,20],"110":[18,19,20],"119":[18,19,20],"124":[18,19,20],"132":[18,19,20]},"packages/cli/src/modules/chat-hub/chat-session.repository.ts":{"11":[18,19,20],"15":[18,19,20],"27":[18,19,20],"32":[18,19,20],"37":[18,19,20],"73":[18,19,20],"78":[18,19,20],"92":[18,19,20]},"packages/cli/src/modules/chat-hub/chat-stream-state.service.ts":{"68":[18,19,20],"89":[18,19,20],"115":[18,19,20],"131":[18,19,20],"151":[18,19,20],"177":[18,19,20],"187":[18,19,20],"205":[18,19,20],"233":[18,19,20],"245":[18,19,20],"251":[18,19,20],"268":[18,19,20],"283":[18,19,20],"287":[18,19,20],"291":[18,19,20],"304":[18,19,20],"319":[18,19,20],"329":[18,19,20],"342":[18,19,20],"357":[18,19,20],"367":[18,19,20],"370":[18,19,20],"380":[18,19,20]},"packages/cli/src/modules/chat-hub/chat-stream.service.ts":{"52":[18,19,20,21],"66":[18,19,20,21],"100":[18,19,20,21],"137":[18,19,20,21],"162":[18,19,20,21],"198":[18,19,20,21],"235":[18,19,20,21],"272":[18,19,20,21],"308":[18,19,20,21],"318":[18,19,20,21],"326":[18,19,20,21],"335":[18,19,20,21],"435":[18,19,20,21],"454":[18,19,20,21],"461":[18,19,20,21],"501":[18,19,20,21],"531":[18,19,20,21],"561":[18,19,20,21],"588":[18,19,20,21],"616":[18,19,20,21],"643":[18,19,20,21]},"packages/cli/src/modules/chat-hub/context-limits.ts":{"223":[18,19,20]},"packages/cli/src/modules/chat-hub/stream-capturer.ts":{"13":[18,19,20],"23":[18,19,20],"32":[18,19,20],"43":[18,19,20],"44":[18,19,20],"53":[18,19,20],"67":[18,19,20],"72":[18,19,20],"96":[18,19,20],"112":[18,19,20],"124":[18,19,20],"142":[18,19,20],"151":[18,19,20],"204":[18,19,20]},"packages/cli/src/modules/dynamic-credentials.ee/services/credential-connection-status.service.ts":{"34":[18,20,21,222,44],"50":[18,20,21,222,44],"61":[18,20,21,222,44],"79":[18,20,21,222,44],"101":[18,20,21,222,44],"126":[18,20,21,222,44],"136":[18,20,21,222,44],"140":[18,20,21,222,44],"145":[18,20,21,222,44],"163":[18,20,21,222,44],"172":[18,20,21,222,44],"183":[18,20,21,222,44],"193":[18,20,21,222,44],"196":[18,20,21,222,44],"201":[18,20,21,222,44],"204":[18,20,21,222,44],"206":[18,20,21,222,44],"211":[18,20,21,222,44],"215":[18,20,21,222,44],"219":[18,20,21,222,44],"241":[18,20,21,222,44],"260":[18,20,21,222,44],"266":[18,20,21,222,44]},"packages/cli/src/modules/favorites/favorites.event-relay.ts":{"10":[83,13,18,20,21,25,174,79,81],"17":[83,13,18,20,21,25,174,79,81],"19":[83,13,18,20,21,25,174,79,81],"21":[83,13,18,20,21,25,174,79,81],"23":[83,13,18,20,21,25,174,79,81],"25":[83,13,18,20,21,25,174,79,81],"27":[83,13,18,20,21,25,174,79,81]},"packages/cli/src/webhooks/streaming-webhook-response-heartbeat.ts":{"21":[18,19,20],"22":[18,19,20],"34":[18,19,20]},"packages/nodes-base/nodes/Merge/Merge.node.ts":{"9":[18,19,20,96,136,139]},"packages/nodes-base/nodes/Merge/v1/MergeV1.node.ts":{"20":[18,19,20,96,136,139],"205":[18,19,20,96,136,139]},"packages/nodes-base/nodes/Merge/v2/MergeV2.node.ts":{"35":[18,19,20,96,136,139],"293":[18,19,20,96,136,139],"459":[18,19,20,96,136,139],"467":[18,19,20,96,136,139],"520":[18,19,20,96,136,139],"603":[18,19,20,96,136,139],"604":[18,19,20,96,136,139]},"packages/nodes-base/nodes/Merge/v2/utils.ts":{"31":[18,19,20,96,136,139],"32":[18,19,20,96,136,139],"34":[18,19,20,96,136,139],"41":[18,19,20,96,136,139],"47":[18,19,20,96,136,139],"72":[18,19,20,96,136,139],"78":[18,19,20,96,136,139],"103":[18,19,20,96,136,139],"128":[18,19,20,96,136,139],"150":[18,19,20,96,136,139],"151":[18,19,20,96,136,139],"159":[18,19,20,96,136,139],"176":[18,19,20,96,136,139],"187":[18,19,20,96,136,139],"191":[18,19,20,96,136,139],"197":[18,19,20,96,136,139],"203":[18,19,20,96,136,139],"210":[18,19,20,96,136,139],"213":[18,19,20,96,136,139],"216":[18,19,20,96,136,139],"219":[18,19,20,96,136,139],"243":[18,19,20,96,136,139],"246":[18,19,20,96,136,139],"250":[18,19,20,96,136,139],"268":[18,19,20,96,136,139],"273":[18,19,20,96,136,139],"279":[18,19,20,96,136,139],"285":[18,19,20,96,136,139],"288":[18,19,20,96,136,139],"292":[18,19,20,96,136,139],"307":[18,19,20,96,136,139],"327":[18,19,20,96,136,139],"334":[18,19,20,96,136,139],"349":[18,19,20,96,136,139],"350":[18,19,20,96,136,139]},"packages/nodes-base/nodes/Merge/v3/MergeV3.node.ts":{"15":[18,19,20,96,136,139],"26":[18,19,20,96,136,139]},"packages/nodes-base/nodes/Merge/v3/actions/mode/append.ts":{"21":[18,19,20,96,136,139]},"packages/nodes-base/nodes/Merge/v3/actions/mode/chooseBranch.ts":{"73":[18,19,20,96,136,139],"98":[18,19,20,96,136,139],"99":[18,19,20,96,136,139]},"packages/nodes-base/nodes/Merge/v3/actions/mode/combineAll.ts":{"35":[18,19,20,96,136,139]},"packages/nodes-base/nodes/Merge/v3/actions/mode/combineByFields.ts":{"261":[18,19,20,96,136,139],"274":[18,19,20,96,136,139],"297":[18,19,20,96,136,139],"305":[18,19,20,96,136,139],"358":[18,19,20,96,136,139]},"packages/nodes-base/nodes/Merge/v3/actions/mode/combineByPosition.ts":{"49":[18,19,20,96,136,139],"80":[18,19,20,96,136,139],"82":[18,19,20,96,136,139],"95":[18,19,20,96,136,139],"100":[18,19,20,96,136,139],"106":[18,19,20,96,136,139],"110":[18,19,20,96,136,139],"112":[18,19,20,96,136,139]},"packages/nodes-base/nodes/Merge/v3/actions/mode/combineBySql.ts":{"104":[18,19,20,96,136,139],"125":[18,19,20,96,136,139],"131":[18,19,20,96,136,139],"152":[18,19,20,96,136,139],"158":[18,19,20,96,136,139],"167":[18,19,20,96,136,139],"170":[18,19,20,96,136,139],"179":[18,19,20,96,136,139],"180":[18,19,20,96,136,139],"208":[18,19,20,96,136,139],"255":[18,19,20,96,136,139],"270":[18,19,20,96,136,139],"271":[18,19,20,96,136,139],"272":[18,19,20,96,136,139],"289":[18,19,20,96,136,139],"290":[18,19,20,96,136,139],"300":[18,19,20,96,136,139]},"packages/nodes-base/nodes/Merge/v3/actions/router.ts":{"7":[18,19,20,96,136,139]},"packages/nodes-base/nodes/Merge/v3/helpers/sandbox-utils.ts":{"13":[18,19,20,96,136,139],"29":[18,19,20,96,136,139],"41":[18,19,20,96,136,139],"49":[18,19,20,96,136,139],"100":[18,19,20,96,136,139],"120":[18,19,20,96,136,139],"135":[18,19,20,96,136,139],"156":[18,19,20,96,136,139],"181":[18,19,20,96,136,139]},"packages/nodes-base/nodes/Merge/v3/helpers/utils.ts":{"33":[18,19,20,96,136,139],"34":[18,19,20,96,136,139],"36":[18,19,20,96,136,139],"43":[18,19,20,96,136,139],"49":[18,19,20,96,136,139],"74":[18,19,20,96,136,139],"80":[18,19,20,96,136,139],"105":[18,19,20,96,136,139],"130":[18,19,20,96,136,139],"152":[18,19,20,96,136,139],"153":[18,19,20,96,136,139],"161":[18,19,20,96,136,139],"178":[18,19,20,96,136,139],"189":[18,19,20,96,136,139],"193":[18,19,20,96,136,139],"199":[18,19,20,96,136,139],"205":[18,19,20,96,136,139],"212":[18,19,20,96,136,139],"215":[18,19,20,96,136,139],"218":[18,19,20,96,136,139],"221":[18,19,20,96,136,139],"245":[18,19,20,96,136,139],"248":[18,19,20,96,136,139],"252":[18,19,20,96,136,139],"270":[18,19,20,96,136,139],"275":[18,19,20,96,136,139],"281":[18,19,20,96,136,139],"287":[18,19,20,96,136,139],"290":[18,19,20,96,136,139],"294":[18,19,20,96,136,139],"309":[18,19,20,96,136,139],"329":[18,19,20,96,136,139],"336":[18,19,20,96,136,139],"351":[18,19,20,96,136,139],"352":[18,19,20,96,136,139],"364":[18,19,20,96,136,139],"365":[18,19,20,96,136,139],"371":[18,19,20,96,136,139],"375":[18,19,20,96,136,139],"389":[18,19,20,96,136,139],"406":[18,19,20,96,136,139]},"packages/nodes-base/nodes/Merge/v3/methods/loadOptions.ts":{"3":[18,19,20,96,136,139],"36":[18,19,20,96,136,139]},"localhost-41851/assets/index-BoK1c_f3.js":{"3":[18,155,156,157,21]},"localhost-41851/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[18,155,156,157,21],"9":[18,155,156,157,21],"10":[18,155,156,157,21],"19":[18,155,156,157,21],"23":[18,155,156,157,21],"29":[18,155,156,157,21],"33":[18,155,156,157,21],"34":[18,155,156,157,21]},"packages/@n8n/utils/src/retry.ts":{"15":[86,18,155,19,156,20,21,124,136,137],"46":[86,18,155,19,156,20,21,124]},"packages/frontend/@n8n/chat/src/components/ChatFile.vue":{"28":[18,29,160],"33":[18]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/arrow-down--outline-16.svg":{"9":[86,18,124,59]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/dots-vertical--outline-16.svg":{"9":"b:AAA8AAA4AAAAAEIgCAAAEAAAABgCQAAAgAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/paperclip--outline-16.svg":{"9":[86,18,155,19,156,20,21,124]},"packages/frontend/@n8n/design-system/src/components/N8nLogo/Logo.vue":{"8":"b:AAB9AgAwAIAAAEADCAAAEAAAgBgAAAAAAAAAAAA=","24":"b:AAB9AgAwAIAAAEADCAAAEAAAgBgAAAAAAAAAAAA=","30":"b:AAB9AgAwAIAAAEADCAAAEAAAgBgAAAAAAAAAAAA=","42":"b:AAB9AgAwAIAAAEADCAAAEAAAgBgAAAAAAAAAAAA=","55":"b:AAB9AgAwAIAAAEADCAAAEAAAgBgAAAAAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nLogo/logo-icon.svg":{"8":"b:AAB9AgAwAIAAAEADCAAAEAAAgBgAAAAAAAAAAAA="},"packages/frontend/@n8n/design-system/src/components/N8nLogo/logo-text.svg":{"8":"b:AAB9AgAwAIAAAEADCAAAEAAAgBgAAAAAAAAAAAA="},"packages/frontend/editor-ui/src/app/layouts/ChatLayout.vue":{"8":[18,155,19,156,20,21],"10":[18,155,19,156,20,21]},"packages/frontend/editor-ui/src/app/utils/rbac/checks/hasRole.ts":{"5":[86,18,155,19,156,157,20,21,124]},"packages/frontend/editor-ui/src/features/ai/chatHub/ChatView.vue":{"76":[18,155,19,156,20,21],"84":[18,155,19,156,20,21],"91":[18,155,19,156,20,21],"94":[18,155,19,156,20,21],"96":[18,155,19,156,20,21],"99":[18,155,19,156,20,21],"101":[18,155,19,156,20,21],"106":[18,155,19,156,20,21],"108":[18,155,19,156,20,21],"134":[18],"141":[18,155,19,156,20,21],"146":[18,155,19,156,20,21],"150":[18,155,19,156,20,21],"182":[18,155,19,156,20,21],"214":[18,155,19,156,20,21],"218":[18,155,19,156,20,21],"225":[18,155,19,156,20],"236":[20],"245":[18,155,19,156,20,21],"253":[18,155,19,156,20,21],"258":[18,155,19,156,20,21],"267":[18,155,19,156,20,21],"293":[18,155,19,156,20,21],"308":[18,155,19,156,20,21],"323":[18,155,19,156,20,21],"335":[18,155,19,156,20,21],"363":[18,155,19,156,20,21],"364":[18,155,19,156,20,21],"382":[18,155,19,156,20,21],"400":[18,155,19,156,20,21],"408":[18,155,19,156,20,21],"417":[18,155,19,156,20,21],"428":[18,155,19,156,20,21],"448":[18,155,19,156,20,21],"464":[18,155,19,156,20,21],"472":[18,155,19,156,20,21],"483":[18,155,19,156,20,21],"576":[18,155,19,156,20],"600":[18,155,19,156,20],"628":[156],"706":[18,155,19,156,20,21],"735":[18,155,19,156,20,21],"747":[18,155,19,156,20,21]},"packages/frontend/editor-ui/src/features/ai/chatHub/chat.api.ts":{"32":[86,18,155,19,156,157,20,21,124],"44":[86,18,155,19,156,20,21,124],"62":[86,124],"79":[86,124],"99":[86,124],"120":[86,124],"140":[86,124],"160":[86,18,155,19,156,20,21,124],"174":[86,124],"183":[86,18,155,19,156,20,21,124],"202":[86,124],"216":[86,124],"224":[86,124],"232":[86,18,155,19,156,20,21,124],"240":[86,156,124],"248":[86,156,124],"256":[86,156,124],"265":[86,156,124],"270":[86,124],"287":[86,124],"299":[86,157,124],"309":[86,157,124],"322":[86,157,124],"333":[86,124],"342":[86,124],"349":[86,18,124],"362":[86,21,124],"377":[86,124],"392":[86,124],"404":[86,18,155,19,156,20,21,124],"408":[86,20,124],"415":[86,124],"428":[86,124]},"packages/frontend/editor-ui/src/features/ai/chatHub/chat.types.ts":{"114":[18]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatAgentAvatar.vue":{"22":[18,155,19,156,20]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatConversationHeader.vue":{"47":[18,155,19,156,20,21],"65":[18,155,19,156,20,21],"67":[18,155,19,156,20,21],"85":[18,155,19,156,20,21]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatGreetings.vue":{"22":[18,155,19,156,20,21],"38":[156,21]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatMessage.vue":{"68":[18,155,19,156,20,21],"96":[18,155,19,156,20,21],"116":[18,155,19,156,20,21],"117":[18,155,19,156,20,21],"144":[18,155,19,156,20,21],"149":[18,155,19,156,20,21],"150":[18,155,19,156,20,21],"159":[18,155,19,156,20,21],"169":[18,155,19,156,20,21],"170":[18],"188":[18,155,19,156,20,21],"190":[18,155,19,156,20,21],"198":[18,155,19,156,20,21],"295":[18,155,19,156,20,21],"296":[18,155,19,156,20,21],"307":[18,155,19,156,20,21],"317":[18,155,19,156,20,21],"320":[18,155,19,156,20,21],"410":[18],"422":[18,155,19,156,20,21]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatMessageActions.vue":{"13":[18,155,19,156,20,21],"35":[18,155,19,156,20,21],"37":[18,155,19,156,20,21],"52":[18,155,19,156,20,21],"53":[18,155,19,156,20,21],"65":[18,155,19,156,20,21]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatPrompt.vue":{"18":[18,155,19,156,20,21],"59":[18,155,19,156,20,21],"71":[18,155,19,156,20,21],"75":[18,155,19,156,20,21],"79":[18,155,19,156,20,21],"81":[18,155,19,156,20,21],"82":[18,155,19,156,20,21],"104":[18],"150":[18,155,19,156,20,21],"211":[18,155,19,156,20,21],"212":[18,155,19,156,20,21],"228":[18,155,19,156,20,21],"289":[18,155,19,156,20,21]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatPromptCallouts.vue":{"19":[18,155,19,156,20,21],"35":[18,155,156],"45":[18,155,156]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatPromptFull.vue":{"10":[18,155,19,156,20,21],"55":[18],"71":[18,155,19,156,20,21],"75":[18,155,19,156,20,21],"87":[18,155,19,156,20,21],"103":[18,155,19,156,20,21],"112":[18,155,19,156,20,21],"125":[18,155,19,156,20,21]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatSessionMenuItem.vue":{"20":[18,155,19,156,20,21],"34":[18,155,19,156,20,21],"44":[18,155,19,156,20,21],"87":[18,155,19,156,20,21],"89":[18,155,19,156,20,21],"101":[18,155,19,156,20,21],"122":[18,155,19,156,20,21]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatSidebar.vue":{"19":[18,155,19,156,20,21],"49":[18,155,19,156,20,21],"59":[18,155,19,156,20,21],"60":[18,155,19,156,20,21],"69":[18,155,19,156,20,21]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatSidebarContent.vue":{"25":[18,155,19,156,20,21],"32":[18,155,19,156,20,21],"39":[18,155,19,156,20,21],"43":[18,155,19,156,20,21],"45":[18,155,19,156,20,21],"57":[18,155,19,156,20,21],"69":[18,155,19,156,20,21],"80":[18,155,19,156,20,21],"138":[18,155,19,156,20,21],"141":[18,155,19,156,20,21],"156":[18,155,19,156,20,21],"176":[18,155,19,156,20,21],"181":[18,155,19,156,20,21],"184":[18,155,19,156,20,21],"195":[18,155,19,156,20,21],"199":[18,155,19,156,20,21]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatSidebarLink.vue":{"25":[18,155,19,156,20,21],"44":[18,155,19,156,20,21],"61":[18,155,19,156,20,21]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatStarter.vue":{"36":[18,155,19,156,20,21],"38":[20],"42":[155,20],"46":[155,20],"47":[20],"49":[155,20],"59":[18,155,19,156,20,21],"67":[155,20],"80":[155,20],"97":[155,20],"111":[155,20],"133":[155,20],"148":[20],"159":[20]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatTypingIndicator.vue":{"2":[18,155,19,156,20,21]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/CopyButton.vue":{"9":[18,155,19,156,20,21],"12":[18,155,19,156,20,21],"22":[18,155,19,156,20,21]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ModelSelector.vue":{"54":[18,155,19,156,20,21],"78":[18,155,19,156,20,21],"84":[18,155,19,156,20,21],"85":[18,155,19,156,20,21],"93":[18,155,19,156,20,21],"103":[18,155,19,156,20,21],"105":[18,155,19,156,20,21],"109":[155],"113":[155,19],"144":[155,19,156],"184":[18,155,19,156,20,21],"201":[18,155,19,156,20,21],"209":[155,19,156]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/SkeletonMenuItem.vue":{"2":[18,155,19,156,20,21]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ToolsSelector.vue":{"32":[20],"34":[18,155,19,156,20,21],"36":[20],"39":[20],"41":[20],"45":[20],"50":[18,155,19,156,20,21],"53":[20],"62":[20],"104":[20],"108":[20],"116":[20],"153":[18,155,19,156,20,21],"166":[18,155,19,156,20,21],"175":[18,155,19,156,20,21],"197":[20],"204":[20],"207":[20]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useChatArtifacts.ts":{"6":[18,155,19,156,20,21],"12":[18,155,19,156,20,21],"13":[18,155,19,156,20,21],"21":[18,155,19,156,20,21],"26":[18,155,19,156,20,21],"30":[18,155,19,156,20,21],"39":[18,155,19,156,20,21]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useChatCredentials.ts":{"18":[18,155,19,156,20,21],"38":[18,155,19,156,20,21],"43":[18,155,19,156,20,21],"47":[18,155,19,156,20,21],"49":[18,155,19,156,20,21],"66":[21],"72":[156,21],"81":[18,155,19,156,20,21],"83":[18,155,19,156,20,21],"100":[18,155,19,156,20,21],"102":[18,155,19,156,20,21]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useChatInputFocus.ts":{"13":[18,155,19,156,20,21]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useChatPushHandler.ts":{"31":[18,155,19,156,20,21],"42":[18,155,19,156,20,21],"50":[18,155,19,156,20,21],"62":[18,155,19,156,20,21],"93":[18,155,19,156],"118":[18,155,19,156,20,21],"133":[20,21],"148":[18,155,19,156,20,21],"162":[18,155,19,156,20,21],"179":[18,155,19,156,20,21],"211":[18,155,19,156,20,21],"220":[18,155,19,156,20,21],"222":[18,155,19,156,20,21],"233":[156],"268":[18,155,156,21]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useChatSession.ts":{"29":[18,155,19,156,20,21],"37":[18,155,19,156,20,21],"41":[156],"46":[18,155,19,156,20,21],"47":[18,155,19,156,20,21],"51":[18,155,19,156,20,21],"71":[18,155,19,156,20,21],"78":[18],"85":[18,155,19,156,20,21],"95":[18,155,19,156,20,21],"111":[18,155,19,156,20,21],"112":[18,155,19,156,20,21]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useCustomAgent.ts":{"7":[18,155,19,156,20,21],"8":[18,155,19,156,20],"18":[18,155,19,156,20,21]},"packages/frontend/editor-ui/src/features/ai/chatHub/composables/useDynamicCredentialsStatus.ts":{"33":[18,155,19,156,20,21],"39":[18,155,19,156,20,21],"40":[18,155,19,156,20,21],"50":[21],"196":[18,155,19,156,20,21]},"packages/frontend/editor-ui/src/features/ai/chatHub/model-selector.utils.ts":{"118":[18,155,19,156,20,21],"132":[18,155,19,156,20,21],"142":[156],"170":[21],"182":[21],"199":[18,155,19,156,20,21],"223":[18,155,19,156,20,21],"260":[21],"267":[18,155,19,156,20,21],"274":[18,155,19,156,20,21],"284":[18,155,19,156,20,21],"334":[18,155,19,156,20,21],"376":[18,155,19,156,20,21],"393":[18,155,19,156,20,21]},"packages/frontend/editor-ui/src/features/ai/shared/utils/fileAccept.ts":{"4":[86,18,155,19,156,20,21,124],"5":[86,18,155,19,156,20,21,124],"6":[86,18,155,19,156,20,21,124],"18":[86,18,124,29,160],"26":[86,18,124],"28":[86,18,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/book--outline-16.svg":{"9":[86,88,124,201,216]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/book-open--outline-16.svg":{"9":[86,88,124,201]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/bug--outline-16.svg":{"9":[86,88,124,201,216]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/graduation-cap--outline-16.svg":{"9":[86,88,124,201,216]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/video-camera--outline-16.svg":{"9":[86,88,124,201,216]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/compare-datasets.svg":{"11":[152,108,180,66,70,96,134,201,135,209]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/extract-from-file.svg":{"11":"b:AAAAAAAAAABEAAAAARAAAMAAAAEABBAAAAYCAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/loop-over-items.svg":{"11":[166,176,186,187,201,137,116,218]},"packages/frontend/@n8n/design-system/src/types/menu.ts":{"56":[86,88,124,201]},"packages/frontend/@n8n/rest-api-client/src/api/instance-registry.ts":{"6":[86,124,201]},"packages/frontend/editor-ui/src/app/components/AboutModal.vue":{"16":[86,124,201],"24":[86,124,201],"28":[86,124,201],"32":[86,124],"49":[86,124],"57":[86,124,201],"68":[86,124,201],"72":[86,124,201],"75":[86,124,201],"80":[86,124,201],"83":[86,124,201],"88":[86,124,201],"91":[86,124,201],"92":[86,124,201],"98":[86,124,201],"101":[86,124,201],"102":[86,124,201],"108":[86,124,201],"111":[86,124,201],"116":[86,124,201],"119":[86,124,201],"120":[86,124,201],"127":[86,124,201]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/CodeNodeEditor.vue":{"34":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","54":[86,124,135,209],"55":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","56":[6,86,124,135,209],"59":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","60":"b:AAAAAAAAAABEAEAAARAAEMAAAAEAABAAAAICAAA=","61":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","68":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","69":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","70":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","73":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","80":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","83":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","92":"b:AAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","97":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","103":[6,86,124,188,135,209],"108":[6,86,124],"110":[6,86,124],"115":[6,86,124,188,135,209],"116":[6,86,124,188,135,209],"149":[86,124],"167":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","181":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA="},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/linter.ts":{"23":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","29":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","38":[6,86,124,135,209],"62":[86,124,135],"68":[86,124,135],"79":[86,124],"95":[86,124,135,209],"98":[86,124],"118":[86,124],"136":[86,124,135,209],"138":[86,124,135,209],"142":[86,124,135,209],"144":[86,124,135,209],"146":[86,124,135,209],"151":[86,124,135],"162":[86,124],"180":[86,124,135],"183":[86,124],"194":[86,124],"222":[86,124,135],"230":[86,124,135],"257":[86,124,135,209],"264":[86,124,135],"288":[86,124,135,209],"298":[86,124,135],"321":[86,124,135,209],"328":[86,124,135],"329":[86,124,135],"346":[86,124,135],"352":[86,124,135],"377":[86,124,135,209],"399":[86,124,135,209],"415":[86,124,135,209],"422":[86,124,135],"442":[86,124],"466":[86,124,135],"474":[86,124],"493":[86,124],"513":[86,124,135,209],"523":[86,124],"538":[86,124],"554":[86,124,135,209],"567":[86,124],"588":[86,124,135,209],"599":[86,124,135],"610":[86,124],"626":[86,124,135],"632":[86,124,135],"633":[86,124,135]},"packages/frontend/editor-ui/src/features/shared/editors/composables/useCodeEditor.ts":{"70":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","80":[86,124],"113":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","114":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","125":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","134":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","166":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAAA=","170":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","181":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","185":[6,86,108,124,188,135,209],"195":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAAA=","203":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAAA=","210":[86,124],"224":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","232":[86,124],"239":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","253":[6,86,124,188,135,209],"262":[86,124,209],"267":[86,124,209],"275":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","350":[86,124],"362":[86,124],"370":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAAAAICAAA=","382":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","386":"b:AAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","403":[86,124],"408":[86,124],"417":[6,86,124,135,209],"431":[86,124],"443":[6,86,124,135,209],"453":[86,124],"455":[86,124]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/typescript/client/useTypescript.ts":{"28":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","37":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","44":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","57":[86,124],"68":[6,86,124,135],"85":[86,124],"89":[86,124],"117":[6,86,124,135],"125":[6,86,124,135],"135":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","136":"b:QAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA=","142":[86,124,135],"150":"b:AAAAAAAAAABEAEAAARAAEMAAAAEAABAQAAICAgA="},"packages/frontend/editor-ui/src/features/workflows/components/ImportWorkflowUrlModal.vue":{"10":[86,124,201,218],"16":[86,124,201,218],"20":[86,124,201,218],"24":[86,124,218],"29":[86,124,201,218],"32":[86,124,201,218],"45":[86,124,201,218],"60":[86,124,201,218],"68":[86,124,201,218],"76":[86,124,201,218]},"packages/frontend/@n8n/design-system/src/components/N8nDropdownMenu/DropdownMenu.utils.ts":{"6":[86,124],"11":[86,155,19,156,124,31,161],"17":[86,124,31],"35":[86,155,19,156,124,31,161],"39":[86,124],"56":[86,124],"63":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nDropdownMenu/DropdownMenuSearch.vue":{"18":[86,155,19,156,124,161],"33":[86,124],"39":[86,124],"43":[86,155,19,156,124,161],"48":[86,155,19,156,124,161]},"packages/frontend/@n8n/design-system/src/components/N8nDropdownMenu/DropdownMenuSearchableContent.vue":{"25":[86,155,19,156,124,31,161],"83":[86,155,19,156,124,31,161],"91":[86,124],"95":[86,124],"101":[86,124],"115":[86,124],"127":[86,155,19,156,124,161],"131":[86,124,31,161],"138":[86,124,31,161],"142":[86,124],"148":[86,124],"154":[86,155,19,156,124,161],"163":[86,155,19,156,124,161],"169":[86,124,31],"173":[86,124],"178":[86,155,19,156,124],"189":[86,124],"196":[86,124],"212":[86,124],"218":[86,155,19,156,124,161],"226":[86,155,19,156,124,161],"231":[86,155,19,156,124,31,161],"233":[86,155,19,156,124,31,161],"237":[86,124],"283":[86,124,31],"324":[86,124,31],"327":[86,124,31],"332":[86,155,19,156,124,161],"337":[86,155,19,156,124,31,161],"338":[86,155,19,156,124,31,161],"342":[86,155,19,156,124,31,161],"354":[86,155,19,156,124,31,161],"365":[86,155,19,156,124,31,161],"371":[86,155,19,156,124,31,161],"372":[86,124,31,161],"382":[86,155,19,156,124,31,161],"395":[86,124],"398":[86,124]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatProviderAvatar.vue":{"13":[155,19,156],"23":[155,19,156]},"packages/frontend/editor-ui/src/features/ai/chatHub/ChatPersonalAgentsView.vue":{"38":[156],"39":[156],"40":[156],"42":[156],"51":[156],"66":[156],"78":[156],"79":[156],"87":[156],"110":[156],"129":[156],"133":[156],"140":[156],"145":[156],"158":[156],"159":[156]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/AgentEditorModal.vue":{"116":[156],"119":[156],"125":[156],"126":[156],"127":[156],"132":[156],"138":[156],"145":[156],"152":[156],"156":[156],"162":[156],"172":[156],"195":[156],"197":[156],"210":[156],"238":[156],"243":[156],"426":[156],"435":[156],"449":[156],"471":[156],"485":[156],"520":[156],"540":[156],"555":[156],"571":[156],"581":[156],"600":[156],"686":[156],"689":[156]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatAgentCard.vue":{"24":[156,21],"30":[156,21],"36":[156],"43":[156,21],"53":[156,21],"56":[156,21],"74":[156],"76":[156]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatAgentSearchSort.vue":{"19":[156,21],"28":[156,21],"63":[156,21]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/SuggestedPromptsEditor.vue":{"9":[156],"51":[156],"92":[156]},"packages/frontend/@n8n/design-system/src/components/N8nDataTableServer/N8nDataTableServer.vue":{"54":[86,157,21,124,175,45,194],"97":[86,157,21,124,175,45,194],"98":[86,157,21,124,175,45,194],"106":[86,157,21,124,175,45,194],"113":[86,157,21,124,175,45,194],"117":[86,157,21,124,175,45,194],"123":[86,157,21,124,175,45,194],"135":[86,157,21,124,175,45,194],"139":[86,157,21,124,175,45,194],"148":[86,157,21,124,175,45,194],"153":[86,157,21,124,175,45,194],"168":[86,124],"182":[86,157,21,124,175,45,194],"183":[86,157,21,124,175,45,194],"194":[86,21,124,175,45,194],"209":[86,124],"220":[86,157,21,124,175,45,194],"225":[86,124],"228":[86,124],"231":[86,124],"237":[86,124],"243":[86,157,21,124,175,45,194],"247":[86,124],"267":[86,124],"271":[86,124],"276":[86,124],"280":[86,124],"292":[86,157,21,124,175,45,194],"300":[86,124],"305":[86,124],"315":[86,124],"316":[86,124],"324":[86,124],"329":[86,124],"343":[86,157,21,124,175,45,194],"346":[86,157,21,124,175,45,194],"350":[86,124,194],"353":[86,124],"356":[86,124],"362":[86,124],"379":[86,124],"395":[86,157,21,124,175,45,194],"412":[86,157,21,124,175,45,194],"413":[86,157,21,124,175,45,194],"422":[86,124],"437":[86,124],"438":[86,124],"439":[86,124],"461":[86,124],"463":[86,124],"472":[86,157,21,124,175,45,194],"473":[86,157,21,124,175,45,194],"476":[86,124],"478":[86,157,21,124,175,45,194],"507":[86,124],"516":[86,157,124],"518":[86,157,124]},"packages/frontend/@n8n/design-system/src/components/N8nPagination/Pagination.vue":{"24":"b:AAAAAwA4AAAAAEIhHAAAEgAAACAEQAIAAAgFAAA=","25":"b:AAAAAwA4AAAAAEIhHAAAEgAAACAEQAIAAAgFAAA=","26":"b:AAAAAwA4AAAAAEIhHAAAEgAAACAEQAIAAAgFAAA=","51":"b:AAAAAwA4AAAAAEIhHAAAEgAAACAEQAIAAAgFAAA=","56":[86,124,25,177],"58":"b:AAAAAwA4AAAAAEIhHAAAEgAAACAEQAIAAAgFAAA=","63":[86,124,25],"65":"b:AAAAAwA4AAAAAEIhHAAAEgAAACAEQAIAAAgFAAA=","73":[86,124,24,25,177],"77":[86,124,24,25,177],"85":[86,124,24,25,177],"96":"b:AAAAAwA4AAAAAEIhHAAAEgAAACAEQAIAAAgFAAA=","98":"b:AAAAAwA4AAAAAEIhHAAAEgAAACAEQAIAAAgFAAA=","106":[86,124,177,208,210],"111":"b:AAAAAwA4AAAAAEIhHAAAEgAAACAEQAIAAAgFAAA=","115":"b:AAAAAwA4AAAAAEIhHAAAEgAAACAEQAIAAAgFAAA=","119":"b:AAAAAwA4AAAAAEIhHAAAEgAAACAEQAIAAAgFAAA=","123":"b:AAAAAwA4AAAAAEIhHAAAEgAAAAAEQAAAAAgAAAA=","124":"b:AAAAAwA4AAAAAEIhHAAAEgAAAAAEQAAAAAgAAAA=","130":[86,124,25,177],"138":[86,124,25],"150":[86,124],"173":[86,124],"179":[86,124],"186":[86,124],"192":[86,124],"201":[86,124],"212":[86,124],"224":"b:AAAAAwA4AAAAAEIhHAAAEgAAACAEQAIAAAgFAAA=","251":"b:AAAAAwA4AAAAAEIhHAAAEgAAACAEQAIAAAgFAAA=","257":"b:AAAAAwA4AAAAAEIhHAAAEgAAACAEQAIAAAgFAAA=","261":"b:AAAAAwA4AAAAAEIhHAAAEgAAACAEQAIAAAgFAAA=","263":"b:AAAAAwA4AAAAAEIhHAAAEgAAACAEQAIAAAgFAAA=","278":"b:AAAAAwA4AAAAAEIhHAAAEgAAACAEQAIAAAgFAAA=","286":[86,124],"294":"b:AAAAAwA4AAAAAEIhHAAAEgAAACAEQAIAAAgFAAA=","302":"b:AAAAAwA4AAAAAEIhHAAAEgAAACAEQAIAAAgFAAA=","304":"b:AAAAAwA4AAAAAEIhHAAAEgAAACAEQAIAAAgFAAA=","336":[86,124]},"packages/frontend/editor-ui/src/features/ai/chatHub/SettingsChatHubView.vue":{"26":[157],"41":[157],"43":[157],"60":[157],"68":[157],"76":[157],"94":[157],"115":[157],"126":[157],"133":[157],"141":[157]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ChatProvidersTable.vue":{"25":[157],"47":[157],"56":[157],"65":[157],"75":[157],"81":[157],"89":[157],"93":[157],"116":[157],"123":[157],"136":[157],"140":[157],"163":[157],"172":[157],"176":[157],"190":[157],"193":[157],"199":[157],"204":[157]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ProviderSettingsModal.vue":{"123":[157],"127":[157],"141":[157],"156":[157],"164":[157],"184":[157],"217":[157],"227":[157],"229":[157],"240":[157],"243":[157],"250":[157],"254":[157],"265":[157],"279":[157],"308":[157],"319":[157],"372":[157],"375":[157],"398":[157],"401":[157]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialPicker/CredentialPicker.vue":{"19":[86,19,157,124,48,82],"52":[86,19,157,124,48,82],"57":[86,124],"65":[86,19,157,124,48,82],"66":[86,19,157,124,82],"74":[86,19,157,124,48,82],"103":[86,19,157,124,48,82],"108":[86,19,157,124,48,82],"114":[86,157,124],"117":[86,124,82],"134":[86,157,124],"144":[86,124],"181":[86,124,82],"188":[86,124],"198":[86,124],"199":[86,124],"210":[86,19,157,124,82],"220":[86,19,157,124,48,82],"221":[86,19,157,124,48,82],"227":[86,19,157,124,48,82],"249":[86,19,157,124,82],"260":[86,157,124],"269":[86,19,124],"278":[86,124]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialPicker/CredentialsDropdown.vue":{"36":[86,19,157,124,82],"58":[86,124],"62":[86,19,157,124,82],"64":[86,124],"71":[86,19,157,124,82],"75":[86,19,157,124,82],"81":[86,19,157,124,82],"87":[86,19,157,124],"93":[86,19,157,124],"97":[86,157,124],"102":[86,157,124],"107":[86,124],"111":[86,19,157,124,82],"132":[86,19,157,124,82],"141":[86,124],"144":[86,124],"149":[86,124],"160":[86,19,157,124,82],"166":[86,19,157,124,82],"171":[86,19,157,124,82],"173":[86,19,157,124,82],"177":[86,19,157,124,82],"188":[86,19,157,124,82],"189":[86,19,157,124,82],"194":[86,19,157,124,82],"200":[86,124],"219":[86,124]},"packages/@n8n/blob-storage/src/json-store.ts":{"19":[21,136],"23":[21,136],"27":[21,136],"31":[21,136],"47":[21,136],"55":[21,136],"60":[21,136],"64":[21,136],"66":[21,136],"76":[21,136],"80":[21,136],"86":[21,136],"93":[21,136],"103":[21,136],"117":[21,136],"129":[21,136],"134":[21,136]},"packages/@n8n/db/src/repositories/workflow-review-lifecycle.repository.ts":{"29":[13,21,126,44,45,79,81],"39":[13,21,126,44,45,79,81],"47":[13,21,126,44,45,79,81],"84":[13,21,126,44,45,79,81],"101":[13,21,126,44,45,79,81]},"packages/@n8n/errors/src/response-errors/forbidden.error.ts":{"4":[21]},"packages/cli/src/active-workflow-manager.ts":{"78":[21],"103":[21],"114":[21],"121":[21],"143":[21],"150":[21],"160":[21],"238":[21],"283":[21],"319":[21],"339":[21],"353":[21],"381":[21],"395":[21],"414":[21],"427":[21],"496":[21],"503":[21],"512":[21],"540":[21],"669":[21],"671":[21],"708":[21],"719":[21],"727":[21],"748":[21],"845":[21],"851":[21],"852":[21],"855":[21],"865":[21],"882":[21],"890":[21],"962":[21],"972":[21],"985":[21],"1029":[21],"1051":[21],"1071":[21],"1104":[21],"1141":[21],"1144":[21],"1187":[21],"1194":[21],"1210":[21]},"packages/cli/src/events/relays/workflow-failure-notification.event-relay.ts":{"15":[21,64,225],"24":[21,64,225],"26":[21,64,225],"35":[21,64,225]},"packages/cli/src/modules/dynamic-credentials.ee/services/credential-resolver-workflow.service.ts":{"33":[21,109,158,67],"49":[21,109,158,67],"59":[21,109,158,67],"100":[21,109,158,67],"139":[21,109,158,67],"143":[21,109,158,67],"147":[21,109,158,67],"170":[21,109,158,67],"212":[21,109,158,67],"239":[21,109,158,67],"265":[21,109,158,67],"280":[21,109,158,67],"293":[21,109,158,67]},"packages/cli/src/modules/dynamic-credentials.ee/services/dynamic-credential-cors.service.ts":{"12":[21,109],"30":[21,109],"31":[21,109],"53":[21,109],"61":[21,109]},"packages/cli/src/modules/dynamic-credentials.ee/services/dynamic-credential-web.service.ts":{"17":[21,109],"36":[21,109],"41":[21,109],"53":[21,109]},"packages/cli/src/modules/dynamic-credentials.ee/workflow-status.controller.ts":{"23":[21,109],"38":[21,109],"59":[21,109],"85":[21,109],"93":[21,109]},"packages/cli/src/modules/external-secrets.ee/external-secrets-providers.ee.ts":{"13":[121,21,25,45,113,60,95,99,81],"23":[121,21,25,45,113,60,95,99,81],"27":[121,21,25,45,113,60,95,99,81],"31":[121,21,25,45,113,60,95,99,81],"35":[121,21,25,45,113,60,95,99,81]},"packages/cli/src/modules/external-secrets.ee/providers/aws-secrets-manager.ts":{"114":[121,21,25,45,113,60,99,81],"122":[121,21,25,45,113,60,99,81],"162":[121,21,25,45,113,60,99,81],"177":[121,21,25,45,113,60,99,81],"192":[121,21,25,45,113,60,99,81],"196":[121,21,25,45,113,60,99,81],"203":[121,21,25,45,113,60,99,81],"217":[121,21,25,45,113,60,99,81],"221":[121,21,25,45,113,60,99,81],"225":[121,21,25,45,113,60,99,81],"229":[121,21,25,45,113,60,99,81],"235":[121,21,25,45,113,60,99,81],"245":[121,21,25,45,113,60,99,81],"254":[121,21,25,45,113,60,99,81],"281":[121,21,25,45,113,60,99,81],"282":[121,21,25,45,113,60,99,81],"287":[121,21,25,45,113,60,99,81],"291":[121,21,25,45,113,60,99,81],"295":[121,21,25,45,113,60,99,81],"320":[121,21,25,45,113,60,99,81],"338":[121,21,25,45,113,60,99,81]},"packages/cli/src/modules/external-secrets.ee/providers/azure-key-vault/azure-key-vault.ts":{"169":[121,21,25,45,60,99,81],"174":[121,21,25,45,60,99,81],"180":[121,21,25,45,60,99,81],"205":[121,21,25,45,60,99,81],"223":[121,21,25,45,60,99,81],"239":[121,21,25,45,60,99,81],"243":[121,21,25,45,60,99,81],"252":[121,21,25,45,60,99,81],"331":[121,21,25,45,60,99,81],"335":[121,21,25,45,60,99,81],"339":[121,21,25,45,60,99,81],"343":[121,21,25,45,60,99,81],"354":[121,21,25,45,60,99,81],"376":[121,21,25,45,60,99,81]},"packages/cli/src/modules/external-secrets.ee/providers/gcp-secrets-manager/gcp-secrets-manager.ts":{"47":[121,21,25,45,60,99,81],"52":[121,21,25,45,60,99,81],"64":[121,21,25,45,60,99,81],"89":[121,21,25,45,60,99,81],"104":[121,21,25,45,60,99,81],"108":[121,21,25,45,60,99,81],"116":[121,21,25,45,60,99,81],"129":[121,21,25,45,60,99,81],"182":[121,21,25,45,60,99,81],"209":[121,21,25,45,60,99,81],"213":[121,21,25,45,60,99,81],"217":[121,21,25,45,60,99,81],"221":[121,21,25,45,60,99,81],"245":[121,21,25,45,60,99,81],"256":[121,21,25,45,60,99,81]},"packages/cli/src/modules/external-secrets.ee/providers/infisical.ts":{"166":[121,21,25,45,60,99,81],"174":[121,21,25,45,60,99,81],"180":[121,21,25,45,60,99,81],"190":[121,21,25,45,60,99,81],"216":[121,21,25,45,60,99,81],"227":[121,21,25,45,60,99,81],"248":[121,21,25,45,60,99,81],"282":[121,21,25,45,60,99,81],"295":[121,21,25,45,60,99,81],"297":[121,21,25,45,60,99,81],"300":[121,21,25,45,60,99,81],"301":[121,21,25,45,60,99,81],"310":[121,21,25,45,60,99,81],"313":[121,21,25,45,60,99,81],"320":[121,21,25,45,60,99,81],"326":[121,21,25,45,60,99,81],"342":[121,21,25,45,60,99,81],"354":[121,21,25,45,60,99,81],"370":[121,21,25,45,60,99,81],"374":[121,21,25,45,60,99,81],"378":[121,21,25,45,60,99,81],"382":[121,21,25,45,60,99,81],"392":[121,21,25,45,60,99,81],"417":[121,21,25,45,60,99,81]},"packages/cli/src/modules/external-secrets.ee/providers/one-password.ts":{"61":[121,21,25,45,60,99,81],"66":[121,21,25,45,60,99,81],"92":[121,21,25,45,60,99,81],"118":[121,21,25,45,60,99,81],"137":[121,21,25,45,60,99,81],"141":[121,21,25,45,60,99,81],"188":[121,21,25,45,60,99,81],"192":[121,21,25,45,60,99,81],"196":[121,21,25,45,60,99,81],"197":[121,21,25,45,60,99,81],"198":[121,21,25,45,60,99,81],"202":[121,21,25,45,60,99,81],"206":[121,21,25,45,60,99,81]},"packages/cli/src/modules/external-secrets.ee/providers/vault.ts":{"306":[121,21,25,45,60,95,99,81],"316":[121,21,25,45,60,95,99,81],"322":[121,21,25,45,60,95,99,81],"332":[121,21,25,45,60,95,99,81],"381":[121,21,25,45,60,95,99,81],"387":[121,21,25,45,60,95,99,81],"394":[121,21,25,45,60,95,99,81],"412":[121,21,25,45,60,95,99,81],"417":[121,21,25,45,60,95,99,81],"429":[121,21,25,45,60,95,99,81],"463":[121,21,25,45,60,95,99,81],"489":[121,21,25,45,60,95,99,81],"512":[121,21,25,45,60,95,99,81],"526":[121,21,25,45,60,95,99,81],"537":[121,21,25,45,60,95,99,81],"557":[121,21,25,45,60,95,99,81],"566":[121,21,25,45,60,95,99,81],"593":[121,21,25,45,60,95,99,81],"598":[121,21,25,45,60,95,99,81],"604":[121,21,25,45,60,95,99,81],"607":[121,21,25,45,60,95,99,81],"612":[121,21,25,45,60,95,99,81],"621":[121,21,25,45,60,95,99,81],"630":[121,21,25,45,60,95,99,81],"639":[121,21,25,45,60,95,99,81],"649":[121,21,25,45,60,95,99,81],"652":[121,21,25,45,60,95,99,81],"660":[121,21,25,45,60,95,99,81],"663":[121,21,25,45,60,95,99,81],"679":[121,21,25,45,60,95,99,81],"687":[121,21,25,45,60,95,99,81],"712":[121,21,25,45,60,95,99,81],"720":[121,21,25,45,60,95,99,81],"728":[121,21,25,45,60,95,99,81],"733":[121,21,25,45,60,95,99,81],"739":[121,21,25,45,60,95,99,81],"754":[121,21,25,45,60,95,99,81],"787":[121,21,25,45,60,95,99,81],"791":[121,21,25,45,60,95,99,81],"795":[121,21,25,45,60,95,99,81],"796":[121,21,25,45,60,95,99,81],"802":[121,21,25,45,60,95,99,81],"814":[121,21,25,45,60,95,99,81],"825":[121,21,25,45,60,95,99,81],"833":[121,21,25,45,60,95,99,81],"841":[121,21,25,45,60,95,99,81]},"packages/cli/src/modules/external-secrets.ee/secrets-providers-connections.controller.ee.ts":{"32":[121,21,25,45,60,99,81],"41":[121,21,25,45,60,99,81],"81":[121,21,25,45,60,99,81],"104":[121,21,25,45,60,99,81],"122":[121,21,25,45,60,99,81],"135":[121,21,25,45,60,99,81],"138":[121,21,25,45,60,99,81],"145":[121,21,25,45,60,99,81],"157":[121,21,25,45,60,99,81],"172":[121,21,25,45,60,99,81]},"packages/cli/src/modules/external-secrets.ee/secrets-providers-project.controller.ee.ts":{"32":[121,21,25,45,60,99,81],"42":[121,21,25,45,60,99,81],"56":[121,21,25,45,60,99,81],"89":[121,21,25,45,60,99,81],"96":[121,21,25,45,60,99,81],"101":[121,21,25,45,60,99,81],"125":[121,21,25,45,60,99,81],"160":[121,21,25,45,60,99,81],"181":[121,21,25,45,60,99,81]},"packages/cli/src/modules/external-secrets.ee/secrets-providers-types.controller.ee.ts":{"15":[121,21,25,45,60,99,81],"24":[121,21,25,45,60,99,81],"40":[121,21,25,45,60,99,81],"43":[121,21,25,45,60,99,81],"50":[121,21,25,45,60,99,81]},"packages/cli/src/modules/external-secrets.ee/types.ts":{"34":[121,21,25,45,113,95,99,81],"60":[121,21,25,45,113,95,99,81],"87":[121,21,25,45,113,95,99,81],"105":[121,21,25,45,113,95,99,81],"106":[121,21,25,45,113,95,99,81],"112":[121,21,25,45,113,95,99,81]},"packages/workflow/src/errors/policy-refusal.ts":{"5":[152,20,21,49,64]},"packages/frontend/@n8n/design-system/src/components/N8nFormInput/FormInput.vue":{"56":[86,16,151,21,124,175,45,59,192,63,213],"82":[86,16,151,21,124,175,45,59,192,63,213],"122":[86,151,124,175,45,59,192,63,213],"128":[86,151,124,175,45,59,192,63],"133":[86,16,151,124,175,45,59,192,63,213],"137":[86,124],"143":[86,16,151,21,124,175,45,59,192,63,213],"161":[86,16,151,21,124,175,45,59,192,63,213],"167":[86,16,151,21,124,175,45,59,192,63,213],"173":[86,151,124,175,192,63],"176":[86,16,151,21,124,175,45,59,192,63,213],"196":[86,124],"198":[86,124],"214":[86,16,151,21,124,175,45,59,192,63,213],"215":[86,124,175],"232":[86,124,59],"234":[86,124,59],"268":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/arrow-up-right--outline-16.svg":{"9":[86,21,124,175,45,60]},"packages/frontend/@n8n/design-system/src/components/N8nUserInfo/UserInfo.vue":{"22":[86,21,124,175,45,194],"29":[86,21,124,175,45,194],"35":[86,21,124,175,45,194],"44":[86,124],"45":[86,124],"50":[86,21,124,175,45,194],"54":[86,124],"58":[86,21,124,175,45,194]},"packages/frontend/@n8n/design-system/src/components/N8nUserSelect/UserSelect.vue":{"31":[86,21,124,175,45],"53":[86,21,124,175,45],"56":[86,21,124,175,45],"60":[86,124],"76":[86,21,124,175,45],"77":[86,21,124,175,45],"93":[86,21,124,175],"101":[86,21,124],"102":[86,21,124,175],"104":[86,124],"107":[86,124],"116":[86,21,124,175,45],"119":[86,21,124,175,45],"140":[86,21,124,175,45],"142":[86,21,124,175,45],"152":[86,21,124,175,45],"159":[86,21,124,175,45]},"packages/frontend/@n8n/rest-api-client/src/api/secretsProvider.ee.ts":{"11":[86,21,124,175,45,60],"17":[86,21,124,175,45,60],"23":[86,124],"30":[86,124],"43":[86,124],"60":[86,124],"74":[86,124],"85":[86,124],"96":[86,124,60],"107":[86,21,124,175,45],"118":[86,124],"130":[86,124],"148":[86,124],"164":[86,124],"176":[86,124]},"packages/frontend/editor-ui/src/features/ai/chatHub/ChatWorkflowAgentsView.vue":{"30":[21],"31":[21],"32":[21],"49":[21],"68":[21],"76":[21]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectDeleteDialog.vue":{"62":[21,175,45]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectExternalSecrets.vue":{"27":[21,175,45],"53":[21,175,45],"58":[21,175,45],"66":[21,175,45],"70":[21,175,45],"77":[21,175,45],"90":[21,175,45],"117":[21,175,45],"121":[21,175,45],"132":[21,175,45],"180":[21,175,45],"188":[21,175,45],"264":[21,175,45],"265":[21,175,45],"275":[21,175,45],"291":[21,175,45],"307":[21,175,45],"309":[21,175,45],"312":[21,175,45],"315":[21,175,45],"324":[21,175,45],"332":[21,175,45]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectMembersAccessCell.vue":{"8":[21,175,45],"15":[21,175,45],"19":[21,175,45],"20":[21,175,45],"23":[21,175,45],"41":[21,175,45]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectMembersActionsCell.vue":{"6":[21,175,45],"17":[21,175,45]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectMembersRoleCell.vue":{"10":[21,175],"23":[21,175],"25":[21,175],"26":[21,175],"28":[21,175],"29":[21,175],"31":[21],"33":[21,175]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectMembersTable.vue":{"12":[21,175,45],"38":[21,175,45],"45":[21,175,45],"59":[21,175,45],"67":[21,175,45],"70":[21],"74":[21,175,45],"82":[21,175],"83":[21,175,45],"99":[21,175,45],"104":[21,175,45],"121":[21,175,45]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectRoleUpgradeDialog.vue":{"14":[21,175,45],"22":[21,175,45]},"packages/frontend/editor-ui/src/features/collaboration/projects/views/ProjectSettings.vue":{"63":[21,175,45],"68":[21,175,45],"83":[21,175,45],"121":[21,175,45],"127":[21,175,45],"130":[21,175,45],"134":[21,175,45],"135":[21,175,45],"136":[21,175,45],"144":[21,175],"145":[21,175],"148":[21,175,45],"158":[21,175],"164":[21,175],"173":[21,175],"196":[21],"201":[21],"232":[175,45],"281":[21,175,45],"301":[175],"306":[175,45],"329":[175,45],"330":[175,45],"337":[175,45],"368":[175,45],"402":[175,45],"449":[21,175,45],"456":[45],"471":[21,175,45],"480":[21,175,45],"482":[21,175,45],"509":[21,175,45],"513":[21,175,45],"536":[21,175,45],"555":[21,175,45],"566":[21,175],"571":[21,175,45],"574":[21,175,45],"580":[21,175,45],"587":[21,175,45],"597":[21,175,45],"598":[21,175,45],"608":[21,175,45],"630":[21,175,45],"652":[175],"670":[21,175,45],"675":[21,175,45],"677":[21,175,45],"693":[21,175,45],"703":[21,175,45],"710":[21,175,45],"738":[21,175,45],"758":[21,175,45],"787":[21,175,45],"864":[21,175,45]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/composables/useSecretsProviderConnection.ee.ts":{"26":[86,21,124,175,45,60],"34":[86,124],"39":[86,124],"62":[86,124],"79":[86,124],"100":[86,124],"120":[86,124],"126":[86,124]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/composables/useSecretsProvidersList.ee.ts":{"21":[60],"22":[60],"24":[21,175,45,60],"35":[21,175,45,60],"64":[60],"68":[60],"72":[21,175,45,60],"77":[60]},"packages/frontend/editor-ui/src/features/roles/components/CustomRolesUpgradeModal.vue":{"16":[21,175,194]},"packages/frontend/editor-ui/src/features/roles/components/RoleContactAdminModal.vue":{"9":[21,175,194],"32":[21,175,194]},"packages/frontend/editor-ui/src/features/roles/components/RoleHoverPopover.vue":{"16":[21,175,194],"76":[21,175,194]},"packages/frontend/editor-ui/src/features/roles/components/RoleSelectDropdown.vue":{"18":[21,175,194],"21":[21,175,194],"81":[21,194],"84":[21,194],"96":[21,175,194],"97":[21,175,194],"101":[21,175,194],"109":[21,175,194],"138":[21,194],"140":[21,194],"165":[21,175,194],"182":[21,175,194],"196":[21,175,194],"205":[21,175,194],"211":[21,175,194],"220":[21,175,194],"226":[21,175],"231":[21,175,194],"242":[21,175,194],"252":[21,175,194],"260":[21,175,194]},"packages/frontend/editor-ui/src/features/roles/project/projectRoleScopes.ts":{"37":[21,175,45,194],"39":[21,175,45,194]},"packages/cli/src/modules/mcp-registry/mcp-registry-connection.ts":{"22":[37],"28":[37],"41":[37],"58":[37],"63":[37],"64":[37],"69":[37],"105":[37],"111":[37],"181":[37],"190":[37]},"packages/cli/src/modules/mcp-registry/mcp-registry-node-loader.ts":{"41":[37],"71":[37],"76":[37],"80":[37],"91":[37],"108":[37],"112":[37],"144":[37],"150":[37],"158":[37],"162":[37],"168":[37],"174":[37],"183":[37],"188":[37],"192":[37],"196":[37],"215":[37],"217":[37],"219":[37],"220":[37],"222":[37],"226":[37],"231":[37]},"packages/cli/src/modules/mcp-registry/mcp-registry-test.controller.ts":{"17":[37],"23":[37],"29":[37],"38":[37]},"packages/cli/src/modules/mcp-registry/node-description-transform.ts":{"45":[37],"52":[37],"65":[37],"88":[37],"122":[37],"135":[37],"144":[37],"152":[37],"165":[37],"182":[37],"216":[37],"234":[37],"245":[37],"257":[37],"273":[37],"275":[37],"285":[37],"286":[37],"287":[37],"292":[37],"297":[37],"307":[37],"326":[37]},"packages/cli/src/modules/mcp-registry/registry/mcp-registry-capabilities.ts":{"13":[37],"19":[37],"21":[37]},"packages/cli/src/modules/mcp-registry/registry/mcp-registry.service.ts":{"27":[37],"40":[37],"45":[37],"52":[37],"56":[37],"61":[37],"69":[37],"74":[37],"77":[37],"85":[37],"89":[37],"93":[37],"95":[37],"98":[37],"112":[37],"137":[37],"144":[37],"150":[37],"151":[37],"153":[37],"154":[37],"156":[37],"157":[37],"171":[37],"182":[37],"194":[37],"218":[37],"222":[37],"226":[37]},"packages/cli/src/modules/mcp-registry/registry/mcp-registry.types.ts":{"12":[37],"13":[37],"47":[37],"126":[37],"150":[37],"155":[37],"172":[37]},"packages/workflow/src/mcp-helpers.ts":{"57":[37],"105":[37],"116":[37],"134":[37],"168":[37]},"localhost-33191/assets/index-BoK1c_f3.js":{"3":[37]},"localhost-33191/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[37],"9":[37],"10":[37],"19":[37],"23":[37],"29":[37],"33":[37],"34":[37]},"packages/frontend/editor-ui/src/app/components/McpRegistrySuggestionFooter.vue":{"15":[37]},"packages/frontend/editor-ui/src/app/components/SuggestionFooter.vue":{"11":[37,165],"20":[37,165],"25":[165]},"packages/@n8n/backend-network/src/http/axios/legacy.ts":{"36":[8,154,91,26,41,172,72,205],"56":[8,154,91,26,41,172,72,205],"77":[8,154,91,26,41,172,72,205],"142":[8,154,91,26,41,172,72,205],"188":[8,154,91,26,41,172,72,205],"208":[8,154,91,26,41,172,72,205],"212":[8,154,91,26,41,172,72,205],"221":[8,154,91,26,41,172,72,205],"251":[8,154,91,26,41,172,72,205],"262":[8,154,91,26,41,172,72,205],"306":[8,154,91,26,41,172,72,205],"314":[8,154,91,26,41,172,72,205],"327":[8,154,91,26,41,172,72,205]},"packages/@n8n/backend-network/src/http/legacy-request.ts":{"48":[8,154,91,26,41,72,205]},"packages/core/src/execution-engine/node-execution-context/utils/construct-execution-metadata.ts":{"8":[205,210],"13":[205,210]},"packages/core/src/execution-engine/node-execution-context/utils/request-helpers/legacy-request-adapter.ts":{"16":[8,154,91,26,41,72,205],"29":[8,154,91,26,41,72,205]},"packages/core/src/execution-engine/partial-execution-utils/clean-run-data.ts":{"12":[5,6,177,135,136,137,205,210,140,141]},"packages/core/src/execution-engine/partial-execution-utils/directed-graph.ts":{"40":[5,6,177,135,136,137,205,210,140,141],"45":[5,6,177,135,136,137,205,210,140,141],"49":[5,6,177,135,136,137,205,210,140,141],"58":[5,6,177,135,136,137,205,210,140,141],"72":[5,6,177,135,136,137,205,210,140,141],"86":[5,6,177,135,136,137,205,210,140,141],"91":[5,6,177,135,136,137,205,210,140,141],"116":[5,6,177,135,136,137,205,210,140,141],"172":[5,6,177,135,136,137,205,210,140,141],"201":[5,6,177,135,136,137,205,210,140,141],"216":[5,6,177,135,136,137,205,210,140,141],"233":[5,6,177,135,136,137,205,210,140,141],"255":[5,6,177,135,136,137,205,210,140,141],"259":[5,6,177,135,136,137,205,210,140,141],"276":[5,6,177,135,136,137,205,210,140,141],"293":[5,6,177,135,136,137,205,210,140,141],"297":[5,6,177,135,136,137,205,210,140,141],"347":[5,6,177,135,136,137,205,210,140,141],"355":[5,6,177,135,136,137,205,210,140,141],"366":[5,6,177,135,136,137,205,210,140,141],"414":[5,6,177,135,136,137,205,210,140,141],"454":[5,6,177,135,136,137,205,210,140,141],"458":[5,6,177,135,136,137,205,210,140,141],"466":[5,6,177,135,136,137,205,210,140,141],"499":[5,6,177,135,136,137,205,210,140,141],"537":[5,6,177,135,136,137,205,210,140,141],"543":[5,6,177,135,136,137,205,210,140,141],"566":[5,6,177,135,136,137,205,210,140,141]},"packages/core/src/execution-engine/partial-execution-utils/filter-disabled-nodes.ts":{"5":[5,6,177,135,136,137,205,210,140,141],"12":[5,6,177,135,136,137,205,210,140,141]},"packages/core/src/execution-engine/partial-execution-utils/find-start-nodes.ts":{"13":[5,6,177,135,136,137,205,210,140,141],"29":[5,6,177,135,136,137,205,210,140,141],"50":[5,6,177,135,136,137,205,210,140,141],"137":[5,6,177,135,136,137,205,210,140,141],"159":[5,6,177,135,136,137,205,210,140,141]},"packages/core/src/execution-engine/partial-execution-utils/find-subgraph.ts":{"6":[5,6,177,135,136,137,205,210,140,141],"39":[5,6,177,135,136,137,205,210,140,141],"45":[5,6,177,135,136,137,205,210,140,141],"88":[5,6,177,135,136,137,205,210,140,141]},"packages/core/src/execution-engine/partial-execution-utils/find-trigger-for-partial-execution.ts":{"12":[5,6,177,135,136,137,205,210,140,141],"14":[5,6,177,135,136,137,205,210,140,141],"17":[5,6,177,135,136,137,205,210,140,141],"29":[5,6,177,135,136,137,205,210,140,141],"30":[5,6,177,135,136,137,205,210,140,141],"31":[5,6,177,135,136,137,205,210,140,141],"36":[5,6,177,135,136,137,205,210,140,141],"61":[5,6,177,135,136,137,205,210,140,141],"78":[5,6,177,135,136,137,205,210,140,141],"98":[5,6,177,135,136,137,205,210,140,141],"112":[5,6,177,135,136,137,205,210,140,141],"115":[5,6,177,135,136,137,205,210,140,141],"121":[5,6,177,135,136,137,205,210,140,141]},"packages/core/src/execution-engine/partial-execution-utils/get-incoming-data.ts":{"3":[5,6,177,135,136,137,205,210,140,141],"13":[5,6,177,135,136,137,205,210,140,141],"17":[5,6,177,135,136,137,205,210,140,141]},"packages/core/src/execution-engine/partial-execution-utils/get-source-data-groups.ts":{"5":[5,6,177,135,136,137,205,210,140,141],"28":[5,6,177,135,136,137,205,210,140,141],"86":[5,6,177,135,136,137,205,210,140,141],"118":[5,6,177,135,136,137,205,210,140,141],"119":[5,6,177,135,136,137,205,210,140,141],"126":[5,6,177,135,136,137,205,210,140,141],"139":[5,6,177,135,136,137,205,210,140,141],"156":[5,6,177,135,136,137,205,210,140,141],"157":[5,6,177,135,136,137,205,210,140,141]},"packages/core/src/execution-engine/partial-execution-utils/handle-cycles.ts":{"15":[5,6,177,135,136,137,205,210,140,141],"26":[5,6,177,135,136,137,205,210,140,141],"41":[5,6,177,135,136,137,205,210,140,141]},"packages/core/src/execution-engine/partial-execution-utils/recreate-node-execution-stack.ts":{"20":[5,6,177,135,136,137,205,210,140,141],"39":[5,6,177,135,136,137,205,210,140,141],"72":[5,6,177,135,136,137,205,210,140,141],"103":[5,6,177,135,136,137,205,210,140,141]},"packages/core/src/execution-engine/partial-execution-utils/run-data-utils.ts":{"11":[5,6,177,135,136,137,205,210,140,141],"17":[5,6,177,135,136,137,205,210,140,141],"20":[5,6,177,135,136,137,205,210,140,141]},"packages/nodes-base/nodes/HackerNews/GenericFunctions.ts":{"16":[181,205,206,75],"42":[181,205,206,75]},"packages/nodes-base/nodes/HackerNews/HackerNews.node.ts":{"264":[181,205,206,75]},"packages/@n8n/utils/src/nodes-api-level.ts":{"6":[58],"17":[58]},"packages/cli/src/errors/response-errors/incompatible-nodes-api-version.error.ts":{"8":[58]},"packages/community-packages.controller.ts":{"11":[39,58],"15":[39,58],"25":[39,58],"31":[39,58],"39":[39,58]},"packages/community-packages.lifecycle.service.ts":{"35":[39,58],"37":[39,58],"49":[39,58],"60":[39,58],"71":[39,58],"94":[39,58],"132":[39,58],"229":[39,58],"245":[39,58],"253":[39,58],"303":[39,58],"313":[39,58],"328":[39,58],"339":[39,58],"358":[39,58],"395":[39,58],"409":[39,58]},"packages/community-packages.service.ts":{"45":[58],"82":[58],"98":[58],"103":[58],"110":[58],"114":[58],"118":[58],"133":[58],"154":[58],"196":[58],"202":[58],"221":[58],"224":[58],"228":[58],"229":[58],"235":[58],"254":[58],"263":[58],"264":[58],"277":[58],"300":[58],"324":[58],"333":[58],"340":[58],"348":[58],"357":[58],"399":[58],"425":[58],"436":[58],"463":[58],"471":[58],"480":[58],"488":[58],"496":[58],"505":[58],"509":[58],"515":[58],"536":[58],"542":[58],"629":[58],"651":[58],"667":[58],"727":[58],"754":[58],"755":[58],"804":[58],"805":[58],"835":[58],"857":[58],"871":[58],"881":[58],"896":[58],"907":[58],"925":[58],"954":[58],"979":[58],"992":[58],"1059":[58],"1066":[58],"1067":[58],"1072":[58],"1073":[58],"1078":[58]},"packages/core/src/nodes-loader/package-directory-loader.ts":{"17":[58],"27":[58],"57":[58],"86":[58],"94":[58],"100":[58]},"packages/installed-packages.repository.ts":{"10":[58],"17":[58],"21":[58],"28":[58],"37":[58]},"packages/npm-utils.ts":{"46":[58],"55":[58],"61":[58],"71":[58],"75":[58],"76":[58],"79":[58],"88":[58],"93":[58],"104":[58],"128":[58],"149":[58],"164":[58],"168":[58],"181":[58],"196":[58],"253":[58],"287":[58],"335":[58]},"packages/workflow/src/nodes-api-version.ts":{"28":[58],"37":[58]},"localhost-42967/assets/index-BoK1c_f3.js":{"3":[58]},"localhost-42967/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[58],"9":[58],"10":[58],"19":[58],"23":[58],"29":[58],"33":[58],"34":[58]},"packages/frontend/@n8n/rest-api-client/src/api/communityNodes.ts":{"7":[86,124,39,191,58],"14":[86,124,191,58],"22":[86,124,191],"26":[86,124,191,58],"34":[86,124,191,58]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/removeNodeType.ts":{"10":[58]},"packages/frontend/editor-ui/src/features/settings/communityNodes/communityNodes.utils.ts":{"4":[86,124,191,58],"25":[86,124,191,58],"53":[86,124,58]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/CommunityPackageCard.vue":{"44":[191,58],"47":[191,58],"60":[191,58],"77":[191],"95":[191,58],"100":[191,58],"101":[191,58],"102":[191,58],"111":[191,58],"126":[191,58],"133":[191,58],"142":[191,58],"156":[191,58]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/CommunityPackageInstallModal.vue":{"32":[86,124,191,58],"39":[86,124,191,58],"47":[86,124,191,58],"49":[86,124],"54":[86,124,191,58],"78":[86,124,191,58],"82":[86,124,191],"86":[86,124,191,58],"90":[86,124],"94":[86,124],"98":[86,124,191,58],"111":[86,124,191,58],"119":[86,124,191,58],"134":[86,124,191,58],"167":[86,124,191,58],"172":[86,124,191,58],"178":[86,124,191,58]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/CommunityPackageManageConfirmModal.vue":{"33":[86,124,191,58],"55":[86,124,191,58],"58":[86,124,191],"69":[86,124,191,58],"70":[86,124,191,58],"73":[86,124,191,58],"109":[86,124,191,58],"113":[86,124,191,58],"121":[86,124,191],"125":[86,124,191],"148":[86,124,191,58],"152":[86,124,191,58],"194":[86,124,191,58],"195":[86,124,191,58],"203":[86,124,191,58],"216":[86,124,191,58],"222":[86,124],"226":[86,124,191,58],"232":[86,124,191,58],"240":[86,124,191,58],"252":[86,124,191,58],"253":[86,124,191,58],"261":[86,124,191,58],"270":[86,124,191,58]},"packages/frontend/editor-ui/src/features/settings/communityNodes/composables/useInstallNode.ts":{"40":[86,20,124,39,191,58],"53":[86,124],"63":[86,124,191,58],"103":[86,124]},"packages/frontend/editor-ui/src/features/settings/communityNodes/views/SettingsCommunityNodesView.vue":{"40":[191,58],"44":[191,58],"48":[191,58],"56":[191,58],"77":[191,58],"82":[191,58],"90":[58],"94":[191,58],"104":[191,58],"110":[191,58],"117":[191,58],"122":[191,58],"126":[191,58],"130":[191,58],"178":[191,58]},"localhost-42773/assets/index-BoK1c_f3.js":{"3":[70]},"localhost-42773/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[70],"9":[70],"10":[70],"19":[70],"23":[70],"29":[70],"33":[70],"34":[70]},"localhost-42773/assets/verified-Pt0guxqN.js":{"8":[70]},"packages/@n8n/agents/src/runtime/memory/memory-lifecycle.ts":{"8":[83],"12":[83],"16":[83],"23":[83],"28":[83],"33":[83],"38":[83],"49":[83],"64":[83],"76":[83]},"packages/@n8n/agents/src/runtime/tools/sdk-owned-tool.ts":{"5":[83],"9":[83]},"packages/@n8n/agents/src/runtime/tools/todos-core.ts":{"12":[83],"19":[83],"35":[83],"44":[83]},"packages/@n8n/agents/src/runtime/tools/write-todos-tool.ts":{"21":[83],"48":[83],"52":[83],"90":[83]},"packages/@n8n/agents/src/sdk/metadata-enriched-tracer.ts":{"6":[83],"11":[83],"34":[83],"59":[83],"66":[83]},"packages/@n8n/agents/src/workspace/sandbox/daytona-auth-manager.ts":{"54":[83],"71":[83],"82":[83],"86":[83],"91":[83],"97":[83]},"packages/@n8n/agents/src/workspace/sandbox/daytona-sandbox.ts":{"165":[83],"170":[83],"182":[83],"196":[83],"226":[83],"243":[83],"250":[83],"271":[83],"293":[83],"338":[83],"350":[83],"374":[83],"388":[83],"394":[83],"399":[83],"400":[83],"433":[83],"437":[83],"438":[83],"452":[83],"456":[83],"478":[83],"496":[83],"511":[83],"533":[83],"556":[83],"572":[83],"573":[83],"576":[83],"582":[83],"587":[83],"595":[83],"635":[83],"675":[83],"691":[83],"717":[83],"726":[83],"738":[83],"754":[83],"761":[83],"764":[83],"770":[83],"776":[83],"835":[83],"850":[83],"858":[83],"864":[83]},"packages/@n8n/ai-utilities/src/agent-config/native-web-search-provider-tools.ts":{"12":[1,83],"16":[1,83],"20":[1,83],"34":[1,83],"59":[1,83]},"packages/@n8n/api-types/src/agents/model-providers.ts":{"28":[83,86,124],"60":[83]},"packages/@n8n/api-types/src/agents/sanitize-agent-json-config.ts":{"13":[1,83],"17":[1,83],"21":[1,83],"25":[1,83],"29":[1,83],"33":[1,83],"37":[1,83],"41":[1,83],"45":[1,83],"49":[1,83],"55":[1,83],"61":[1,83],"75":[1,83],"79":[1,83],"94":[1,83],"102":[1,83],"103":[1,83],"109":[1,83],"119":[1,83],"124":[1,83],"144":[1,83],"153":[1,83],"162":[1,83],"169":[1,83],"197":[1,83],"213":[1,83],"243":[1,83],"247":[1,83]},"packages/@n8n/api-types/src/agents/sanitize-agent-tool-name.ts":{"4":[83,86,124]},"packages/@n8n/api-types/src/agents/types.ts":{"63":[83,86,124],"73":[83,86,124],"84":[83,86,124],"89":[83,86,124],"90":[83,86,124],"93":[83,86,124],"108":[83,86,124]},"packages/@n8n/backend-common/src/locking/in-process-lock.service.ts":{"24":[83],"27":[83],"36":[83],"37":[83],"52":[83],"69":[83],"72":[83],"80":[83],"97":[83],"101":[83]},"packages/@n8n/backend-common/src/locking/lock.service.ts":{"10":[83],"14":[83],"18":[83]},"packages/@n8n/errors/src/response-errors/conflict.error.ts":{"4":[83,80]},"packages/cli/src/modules/agents/agent-change-publisher.service.ts":{"23":[1,83],"29":[1,83]},"packages/cli/src/modules/agents/agent-chat-attachment.service.ts":{"43":[83],"60":[83],"67":[83],"103":[83],"114":[83],"133":[83],"141":[83],"149":[83],"159":[83],"163":[83],"168":[83],"176":[83],"182":[83],"184":[83],"196":[83],"198":[83],"232":[83]},"packages/cli/src/modules/agents/agent-chat-execution.service.ts":{"61":[83],"73":[83],"83":[83],"95":[83],"103":[83],"120":[83],"124":[83],"155":[83],"165":[83],"175":[83],"185":[83],"189":[83],"196":[83],"210":[83],"229":[83],"237":[83],"247":[83],"293":[83]},"packages/cli/src/modules/agents/agent-conversation-state.service.ts":{"9":[83],"15":[83],"31":[83]},"packages/cli/src/modules/agents/agent-execution-update-broadcaster.ts":{"20":[83],"31":[83],"32":[83],"41":[83],"57":[83],"58":[83],"63":[83],"80":[83],"81":[83],"86":[83],"102":[83],"106":[83],"110":[83],"114":[83],"122":[83]},"packages/cli/src/modules/agents/agent-knowledge.service.ts":{"33":[83],"42":[83],"64":[83],"70":[83],"73":[83],"76":[83],"83":[83],"94":[83],"108":[83],"114":[83],"119":[83],"129":[83],"134":[83],"147":[83],"155":[83],"174":[83],"188":[83],"192":[83],"193":[83],"197":[83],"201":[83],"215":[83],"222":[83],"225":[83],"228":[83],"235":[83],"237":[83],"265":[83],"271":[83],"279":[83],"280":[83],"283":[83],"286":[83]},"packages/cli/src/modules/agents/agent-message-mapper.ts":{"4":[83],"26":[83],"41":[83]},"packages/cli/src/modules/agents/agent-message-steering.service.ts":{"31":[83],"42":[83],"49":[83],"50":[83],"58":[83],"63":[83],"86":[83],"102":[83],"106":[83],"124":[83],"134":[83],"156":[83],"186":[83],"192":[83],"229":[83],"235":[83],"242":[83],"245":[83]},"packages/cli/src/modules/agents/agent-push-recipients.service.ts":{"8":[1,83],"13":[1,83],"17":[1,83]},"packages/cli/src/modules/agents/agent-queued-preview-stream.service.ts":{"36":[83],"44":[83],"47":[83],"53":[83],"55":[83],"68":[83],"75":[83],"81":[83],"91":[83],"97":[83],"101":[83],"108":[83],"114":[83],"115":[83],"127":[83],"141":[83]},"packages/cli/src/modules/agents/agent-run-tracing.service.ts":{"46":[83],"59":[83],"65":[83],"77":[83],"114":[83]},"packages/cli/src/modules/agents/agent-runtime-cache.service.ts":{"107":[1,83],"118":[1,83],"128":[1,83],"149":[1,83],"161":[1,83],"187":[1,83],"196":[1,83],"202":[1,83],"210":[1,83],"216":[1,83],"236":[1,83],"262":[1,83],"274":[1,83],"305":[1,83],"376":[1,83],"398":[1,83],"402":[1,83],"415":[1,83]},"packages/cli/src/modules/agents/agent-runtime-reconstruction.service.ts":{"217":[83],"236":[83],"266":[83],"273":[83],"296":[83],"388":[83],"400":[83],"441":[83],"451":[83],"454":[83],"461":[83],"471":[83],"472":[83],"475":[83],"481":[83],"485":[83],"511":[83],"520":[83],"524":[83],"527":[83],"532":[83],"536":[83],"550":[83],"574":[83],"608":[83],"639":[83],"647":[83],"659":[83],"708":[83],"715":[83],"723":[83],"730":[83],"738":[83],"747":[83],"752":[83],"781":[83],"782":[83],"790":[83],"797":[83],"805":[83],"823":[83],"829":[83],"850":[83],"905":[83],"926":[83],"946":[83],"986":[83],"1010":[83],"1018":[83],"1032":[83],"1055":[83],"1114":[83],"1124":[83],"1181":[83],"1188":[83],"1209":[83],"1214":[83],"1266":[83]},"packages/cli/src/modules/agents/agent-sandbox-principal.ts":{"38":[83],"42":[83],"51":[83],"74":[83]},"packages/cli/src/modules/agents/agent-sandbox-runtime.service.ts":{"71":[83],"83":[83],"94":[83],"107":[83],"116":[83],"122":[83],"130":[83],"139":[83],"144":[83],"164":[83],"179":[83],"215":[83],"243":[83],"267":[83],"276":[83],"287":[83],"291":[83],"298":[83],"315":[83],"345":[83],"365":[83],"401":[83],"442":[83],"445":[83],"454":[83],"477":[83]},"packages/cli/src/modules/agents/agent-sse-stream.ts":{"21":[83],"31":[83],"35":[83],"45":[83],"51":[83],"59":[83],"63":[83],"77":[83],"88":[83],"104":[83],"111":[83],"149":[83],"231":[83],"305":[83],"317":[83],"328":[83]},"packages/cli/src/modules/agents/agent-telemetry.ts":{"16":[83],"21":[83],"25":[83],"35":[83],"45":[83],"50":[83],"51":[83],"58":[83],"79":[83],"92":[83]},"packages/cli/src/modules/agents/agent-test-chat.service.ts":{"10":[83],"17":[83],"26":[83],"33":[83],"38":[83],"49":[83],"56":[83]},"packages/cli/src/modules/agents/agent-test-run.service.ts":{"135":[83],"140":[83],"153":[83],"175":[83],"182":[83],"221":[83],"235":[83],"241":[83],"244":[83],"256":[83],"262":[83],"268":[83],"283":[83],"311":[83],"339":[83],"348":[83],"352":[83],"366":[83],"403":[83],"437":[83],"451":[83]},"packages/cli/src/modules/agents/agent-tool-approval.service.ts":{"15":[83],"20":[83],"32":[83],"33":[83]},"packages/cli/src/modules/agents/agent-turn-execution.service.ts":{"86":[83],"101":[83],"110":[83],"114":[83],"125":[83],"158":[83],"168":[83],"175":[83],"179":[83],"199":[83],"208":[83],"247":[83],"255":[83],"264":[83],"292":[83],"294":[83],"301":[83],"318":[83],"331":[83],"355":[83],"377":[83],"386":[83],"396":[83],"413":[83],"427":[83],"453":[83],"479":[83],"512":[83],"518":[83]},"packages/cli/src/modules/agents/background/agent-background-job.service.ts":{"74":[83],"83":[83],"86":[83],"90":[83],"117":[83],"132":[83],"136":[83],"137":[83],"138":[83],"150":[83],"169":[83],"189":[83],"210":[83],"227":[83],"252":[83],"279":[83],"284":[83],"296":[83],"311":[83],"318":[83],"324":[83],"328":[83],"333":[83],"347":[83],"363":[83],"370":[83],"381":[83],"382":[83],"388":[83],"394":[83],"402":[83],"411":[83],"434":[83],"451":[83],"470":[83],"480":[83],"487":[83],"517":[83],"551":[83],"564":[83],"570":[83],"580":[83],"593":[83],"608":[83],"612":[83],"619":[83],"629":[83],"632":[83],"654":[83],"662":[83],"667":[83],"670":[83],"673":[83],"693":[83],"698":[83],"722":[83],"763":[83],"781":[83],"790":[83],"798":[83],"803":[83],"818":[83],"832":[83],"868":[83],"894":[83],"926":[83],"943":[83],"948":[83],"956":[83],"958":[83],"978":[83],"1003":[83],"1054":[83],"1058":[83],"1069":[83],"1093":[83],"1121":[83]},"packages/cli/src/modules/agents/background/agent-wake.service.ts":{"54":[83],"71":[83],"84":[83],"89":[83],"95":[83],"99":[83],"109":[83],"118":[83],"126":[83],"143":[83],"145":[83],"153":[83],"160":[83],"168":[83],"170":[83],"177":[83],"182":[83],"189":[83],"194":[83],"214":[83],"229":[83],"260":[83],"299":[83],"307":[83],"318":[83],"329":[83],"345":[83]},"packages/cli/src/modules/agents/background/background-job-messages.ts":{"12":[83],"15":[83],"17":[83],"20":[83],"24":[83],"25":[83],"31":[83],"36":[83],"46":[83]},"packages/cli/src/modules/agents/background/background-job-tools.ts":{"43":[83],"47":[83],"50":[83],"78":[83],"133":[83],"155":[83],"166":[83],"168":[83],"171":[83],"183":[83],"190":[83],"204":[83],"242":[83],"256":[83],"270":[83],"275":[83],"284":[83]},"packages/cli/src/modules/agents/background/sub-agent-background-runner.ts":{"68":[83],"78":[83],"110":[83],"141":[83],"156":[83],"163":[83],"196":[83],"210":[83],"215":[83],"226":[83],"243":[83],"245":[83],"249":[83],"256":[83],"304":[83],"322":[83],"323":[83],"333":[83],"356":[83],"358":[83],"361":[83],"368":[83],"373":[83],"375":[83],"389":[83],"392":[83],"422":[83]},"packages/cli/src/modules/agents/budget-guardrail.ts":{"33":[83],"38":[83],"52":[83],"71":[83],"82":[83],"96":[83],"97":[83],"103":[83],"144":[83],"149":[83],"184":[83],"193":[83],"207":[83],"213":[83],"227":[83],"232":[83]},"packages/cli/src/modules/agents/execution-recorder.ts":{"33":[83],"35":[83],"46":[83],"52":[83],"77":[83],"104":[83],"114":[83],"124":[83],"127":[83],"128":[83],"146":[83],"156":[83],"173":[83],"179":[83],"198":[83],"203":[83],"288":[83],"301":[83],"347":[83],"351":[83],"358":[83],"370":[83],"475":[83],"479":[83],"484":[83],"503":[83],"526":[83],"549":[83],"551":[83],"579":[83],"623":[83],"638":[83],"650":[83],"656":[83],"671":[83],"684":[83],"742":[83],"747":[83]},"packages/cli/src/modules/agents/integrations/integration-action-executor.ts":{"70":[83],"76":[83],"85":[83],"169":[83],"184":[83],"235":[83],"273":[83],"297":[83],"335":[83],"360":[83],"393":[83],"408":[83],"424":[83],"436":[83],"440":[83],"444":[83],"458":[83]},"packages/cli/src/modules/agents/integrations/integration-context-query-executor.ts":{"21":[83],"27":[83],"95":[83]},"packages/cli/src/modules/agents/integrations/integration-message-context.service.ts":{"25":[83],"31":[83],"37":[83],"44":[83],"56":[83],"75":[83],"85":[83],"93":[83],"99":[83],"105":[83],"120":[83],"144":[83],"148":[83],"168":[83],"196":[83],"207":[83]},"packages/cli/src/modules/agents/integrations/integration-message-context.ts":{"15":[83],"22":[83],"31":[83],"41":[83],"53":[83],"75":[83],"88":[83],"100":[83],"112":[83],"118":[83],"124":[83]},"packages/cli/src/modules/agents/integrations/integration-tool-descriptions.ts":{"4":[83],"12":[83],"18":[83],"26":[83],"47":[83]},"packages/cli/src/modules/agents/integrations/integration-tool-factory.ts":{"75":[83],"82":[83],"90":[83],"106":[83],"107":[83],"119":[83],"125":[83],"134":[83],"138":[83],"164":[83],"178":[83],"239":[83],"253":[83],"262":[83]},"packages/cli/src/modules/agents/integrations/integration-tool-schema.ts":{"35":[83],"37":[83],"52":[83],"60":[83],"87":[83],"89":[83],"104":[83],"112":[83],"139":[83],"146":[83],"153":[83],"179":[83],"183":[83],"197":[83],"204":[83]},"packages/cli/src/modules/agents/integrations/n8n-memory.ts":{"83":[83],"96":[83],"121":[83],"136":[83],"138":[83],"140":[83],"141":[83],"143":[83],"145":[83],"147":[83],"149":[83],"152":[83],"153":[83],"159":[83],"165":[83],"176":[83],"210":[83],"221":[83],"234":[83],"235":[83],"245":[83],"247":[83],"257":[83],"267":[83],"279":[83],"280":[83],"291":[83],"304":[83],"307":[83],"317":[83],"323":[83],"329":[83],"344":[83],"347":[83],"353":[83],"369":[83],"372":[83],"380":[83],"383":[83],"388":[83],"396":[83],"400":[83],"411":[83],"417":[83],"460":[83],"461":[83],"468":[83],"482":[83],"500":[83],"556":[83],"560":[83],"571":[83],"584":[83],"593":[83],"596":[83],"600":[83],"611":[83],"657":[83],"665":[83],"675":[83],"745":[83],"770":[83],"781":[83],"795":[83],"803":[83],"806":[83],"812":[83],"817":[83],"829":[83],"834":[83],"840":[83],"853":[83],"913":[83],"914":[83],"941":[83],"944":[83],"962":[83],"980":[83],"987":[83],"993":[83],"1001":[83],"1015":[83],"1032":[83],"1052":[83],"1067":[83],"1077":[83],"1088":[83]},"packages/cli/src/modules/agents/json-config/credential-field-mapping.ts":{"18":[83],"20":[83],"22":[83],"23":[83],"30":[83],"32":[83],"34":[83],"36":[83],"38":[83],"40":[83],"49":[83],"51":[83],"53":[83],"55":[83],"57":[83],"65":[83],"91":[83],"106":[83],"114":[83],"123":[83]},"packages/cli/src/modules/agents/json-config/from-json-config.ts":{"156":[83],"268":[83],"273":[83],"277":[83],"286":[83],"302":[83],"306":[83],"309":[83],"325":[83],"341":[83],"380":[83],"400":[83],"411":[83],"414":[83],"415":[83],"429":[83],"431":[83],"444":[83],"461":[83],"469":[83],"520":[83],"590":[83],"625":[83],"639":[83]},"packages/cli/src/modules/agents/json-config/model-config.ts":{"18":[83],"32":[83]},"packages/cli/src/modules/agents/json-config/sanitize-unknown-agent-credentials.ts":{"7":[1,83],"14":[1,83]},"packages/cli/src/modules/agents/repositories/agent-background-job.repository.ts":{"56":[83],"64":[83],"65":[83],"80":[83],"100":[83],"109":[83],"116":[83],"136":[83],"141":[83],"152":[83],"168":[83],"186":[83],"195":[83],"208":[83],"215":[83],"218":[83],"226":[83],"230":[83],"241":[83],"249":[83],"263":[83],"285":[83],"291":[83],"306":[83],"314":[83],"320":[83],"333":[83],"363":[83],"383":[83],"390":[83],"396":[83],"405":[83],"407":[83],"428":[83],"436":[83],"442":[83],"461":[83],"469":[83],"475":[83],"494":[83],"515":[83],"524":[83]},"packages/cli/src/modules/agents/repositories/agent-execution.repository.ts":{"30":[83],"34":[83],"39":[83],"43":[83],"50":[83],"54":[83],"58":[83],"65":[83],"69":[83],"77":[83],"93":[83],"104":[83],"114":[83],"126":[83],"130":[83],"143":[83],"160":[83],"167":[83],"178":[83],"212":[83],"221":[83],"245":[83],"246":[83],"260":[83],"276":[83],"279":[83],"314":[83],"326":[83],"334":[83],"353":[83],"362":[83],"369":[83],"374":[83]},"packages/cli/src/modules/agents/repositories/agent-file.repository.ts":{"8":[83],"12":[83],"21":[83],"25":[83]},"packages/cli/src/modules/agents/repositories/agent-message-queue.repository.ts":{"12":[83],"16":[83],"37":[83],"45":[83],"52":[83],"67":[83],"71":[83],"72":[83],"77":[83],"90":[83],"100":[83],"108":[83],"121":[83],"133":[83],"141":[83],"148":[83],"153":[83],"162":[83],"177":[83],"184":[83],"190":[83],"193":[83],"207":[83],"212":[83],"216":[83],"229":[83]},"packages/cli/src/modules/agents/repositories/agent-message.repository.ts":{"29":[83],"36":[83],"40":[83],"96":[83],"117":[83],"126":[83],"134":[83],"143":[83],"160":[83],"167":[83],"170":[83],"187":[83],"196":[83],"207":[83],"209":[83],"218":[83],"219":[83],"240":[83],"241":[83],"242":[83],"262":[83],"295":[83],"297":[83],"302":[83],"310":[83],"315":[83],"343":[83],"358":[83]},"packages/cli/src/modules/agents/repositories/agent-thread-grant.repository.ts":{"9":[83],"13":[83],"17":[83],"19":[83]},"packages/cli/src/modules/agents/runtime/agent-secure-runtime.ts":{"37":[83],"60":[83],"62":[83],"92":[83],"135":[83],"156":[83],"164":[83],"205":[83],"212":[83],"223":[83],"251":[83],"256":[83],"288":[83],"291":[83],"350":[83],"356":[83],"388":[83],"390":[83],"397":[83],"410":[83],"417":[83]},"packages/cli/src/modules/agents/sub-agents/delegate-sub-agent-tool.ts":{"31":[83],"53":[83],"109":[83],"145":[83],"161":[83],"168":[83],"174":[83],"194":[83],"206":[83]},"packages/cli/src/modules/agents/sub-agents/sub-agent-cleanup.service.ts":{"11":[83],"22":[83],"36":[83],"42":[83],"48":[83]},"packages/cli/src/modules/agents/sub-agents/sub-agent-runner.ts":{"165":[83],"174":[83],"186":[83],"208":[83],"228":[83],"240":[83],"306":[83],"397":[83],"408":[83],"464":[83],"474":[83],"506":[83],"514":[83],"556":[83],"562":[83],"590":[83],"597":[83],"605":[83],"615":[83],"637":[83],"667":[83]},"packages/cli/src/modules/agents/sub-agents/sub-agent-source-resolver.ts":{"38":[83],"49":[83],"140":[83]},"packages/cli/src/modules/agents/tool-registry.ts":{"28":[83]},"packages/cli/src/modules/agents/tools/environment-tool.ts":{"13":[83],"19":[83]},"packages/cli/src/modules/agents/tools/mark-session-failed.tool.ts":{"12":[83],"18":[83]},"packages/cli/src/modules/agents/tools/workflow-tool-factory.ts":{"144":[83],"198":[83],"211":[83],"222":[83],"232":[83],"233":[83],"260":[83],"261":[83],"291":[83],"297":[83],"313":[83],"325":[83],"330":[83],"338":[83],"364":[83],"378":[83],"401":[83],"415":[83],"455":[83],"506":[83],"514":[83],"517":[83],"533":[83],"534":[83],"588":[83],"596":[83],"616":[83],"646":[83],"666":[83],"690":[83],"701":[83],"727":[83],"830":[83],"846":[83],"868":[83],"878":[83],"909":[83],"952":[83],"962":[83],"967":[83],"987":[83],"1001":[83],"1011":[83],"1020":[83],"1050":[83],"1089":[83],"1167":[83]},"packages/cli/src/modules/agents/tools/workflow-tool-workflow-loader.service.ts":{"26":[83],"32":[83],"63":[83]},"packages/cli/src/modules/agents/types/agent-queued-message.ts":{"26":[83],"66":[83]},"packages/cli/src/modules/agents/utils/agent-execution-counter.ts":{"6":[83],"17":[83],"25":[83],"33":[83]},"packages/cli/src/modules/agents/utils/agent-memory-scope.ts":{"6":[83],"14":[83],"23":[83],"27":[83],"31":[83],"37":[83],"43":[83],"51":[83],"58":[83],"64":[83],"68":[83]},"packages/cli/src/modules/agents/utils/agent-published-snapshot.ts":{"19":[83],"29":[83],"42":[83]},"packages/cli/src/modules/agents/utils/agent-runtime-assets.ts":{"10":[83]},"packages/cli/src/modules/agents/utils/agent-stream.ts":{"3":[83]},"packages/cli/src/modules/agents/utils/agent-thread-access.ts":{"13":[83],"19":[83],"33":[83],"42":[83],"47":[83],"59":[83]},"packages/cli/src/modules/agents/utils/decrypt-agent-credential.ts":{"6":[83]},"packages/cli/src/modules/agents/utils/execution-failure-summary.ts":{"26":[83],"32":[83],"36":[83],"44":[83],"58":[83]},"packages/cli/src/modules/agents/utils/execution-input.ts":{"5":[83],"17":[83]},"packages/cli/src/modules/agents/utils/execution-to-message-mapper.ts":{"27":[83],"32":[83],"37":[83],"41":[83],"51":[83],"66":[83],"86":[83],"114":[83],"139":[83],"151":[83],"152":[83],"157":[83],"161":[83],"165":[83],"177":[83],"194":[83],"228":[83],"258":[83],"294":[83],"298":[83]},"packages/cli/src/modules/agents/utils/extract-agent-credential-ids.ts":{"7":[1,83],"9":[1,83]},"packages/cli/src/modules/agents/utils/fatal-session-outcome.ts":{"11":[83],"33":[83],"48":[83]},"packages/cli/src/modules/agents/utils/inbound-attachments.ts":{"8":[83],"26":[83],"52":[83],"75":[83],"84":[83],"85":[83],"87":[83]},"packages/cli/src/modules/agents/utils/mcp-attribution.ts":{"14":[83],"22":[83],"35":[83]},"packages/cli/src/modules/agents/utils/messages-envelope.ts":{"13":[83],"24":[83],"41":[83],"58":[83],"88":[83],"96":[83],"97":[83],"105":[83],"107":[83],"116":[83],"117":[83],"126":[83]},"packages/cli/src/modules/agents/utils/queued-message-id.ts":{"8":[83]},"packages/cli/src/modules/agents/utils/sub-agent-resolver.ts":{"8":[83]},"packages/cli/src/modules/agents/utils/visit-agent-credential-references.ts":{"37":[1,83],"49":[1,83],"79":[1,83],"86":[1,83]},"packages/cli/src/services/sandbox-settings.service.ts":{"25":[83],"39":[83],"50":[83],"60":[83],"92":[83],"103":[83],"107":[83],"111":[83],"118":[83],"141":[83],"169":[83],"178":[83],"184":[83]},"packages/cli/src/task-runners/task-runner-module.ts":{"43":[83,136,137,225],"52":[83,136,137,225],"60":[83,136,137,225],"68":[83,136,137,225],"77":[83,136,137,225],"84":[83,136,137,225],"94":[83,136,137,225],"103":[83,136,137,225],"113":[83,136,137,225],"156":[83,136,137,225]},"packages/cli/src/utils/ttl-map.ts":{"24":[1,83],"30":[1,83],"34":[1,83],"44":[1,83],"49":[1,83],"56":[1,83],"65":[1,83],"73":[1,83],"78":[1,83],"84":[1,83],"94":[1,83],"99":[1,83],"104":[1,83],"109":[1,83],"117":[1,83]},"packages/workflow/src/constants.ts":{"21":[83]},"packages/workflow/src/errors/execution-cancelled.error.ts":{"9":[83,136,137,225],"19":[83,136,137,225],"26":[83,136,137,225],"33":[83,136,137,225]},"packages/nodes-base/nodes/StopAndError/StopAndError.node.ts":{"82":[5,6,226]},"packages/nodes-base/nodes/StopAndError/utils.ts":{"14":[5,6,226],"18":[5,6,226]},"localhost-45811/assets/index-BoK1c_f3.js":{"3":[5,133,206,77]},"localhost-45811/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[5,133,206,77],"9":[5,133,206,77],"10":[5,133,206,77],"19":[5,133,206,77],"23":[5,133,206,77],"29":[5,133,206,77],"33":[5,133,206,77],"34":[5,133,206,77]},"packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/EventMessage.vue":{"24":[5,86,124],"40":[5,86,124],"44":[5,86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/stop-and-error.svg":{"11":[5,6]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Chat/NewAssistantSessionModal.vue":{"14":[5,86,124],"27":[5,86,124],"31":[5,86,124],"44":[5,86,124],"56":[5,86,124],"62":[5,86,124],"65":[5,86,124],"68":[5,86,124],"72":[5,86,124]},"packages/@n8n/scheduler/src/core/executor/lease-heartbeat.ts":{"43":[49,50,51,53,54,55,56],"45":[49,50,51,53,54,55,56],"51":[49,50,51,53,54,55,56],"68":[49,50,51,53,54,55,56],"74":[49,50,51,53,54,55,56],"79":[49,50,51,53,54,55,56],"80":[49,50,51,53,54,55,56],"85":[49,50,51,53,54,55,56],"86":[49,50,51,53,54,55,56],"87":[49,50,51,53,54,55,56],"91":[49,50,51,53,54,55,56]},"packages/@n8n/scheduler/src/core/executor/precision-timer.ts":{"14":[49,50,51,53,54,55,56],"15":[49,50,51,53,54,55,56],"16":[49,50,51,53,54,55,56],"35":[49,50,51,53,54,55,56],"38":[49,50,51,53,54,55,56],"43":[49,50,51,53,54,55,56],"50":[49,50,51,53,54,55,56],"58":[49,50,51,53,54,55,56],"66":[49,50,51,53,54,55,56]},"packages/@n8n/scheduler/src/observability/attributes.ts":{"77":[49,50,51,53,54,55,56],"92":[49,50,51,53,54,55,56]},"packages/@n8n/scheduler/src/observability/executor-tracing.ts":{"22":[49,50,51,53,54,55,56],"24":[49,50,51,53,54,55,56],"36":[49,50,51,53,54,55,56],"67":[49,50,51,53,54,55,56],"71":[49,50,51,53,54,55,56],"78":[49,50,51,53,54,55,56],"91":[49,50,51,53,54,55,56]},"packages/cli/src/scheduling/poll-trigger-node/poll-trigger-task-handler.ts":{"39":[49,50,51],"53":[49,50,51],"65":[49,50,51],"76":[49,50,51],"129":[49,50,51],"233":[49,50,51],"244":[49,50,51],"251":[49,50,51],"265":[49,50,51],"266":[49,50,51],"270":[49,50,51]},"packages/cli/src/scheduling/resolve-task-trigger-node.ts":{"24":[49,50,51,53,54,55,56],"30":[49,50,51,53,54,55,56]},"packages/cli/src/scheduling/seeded-cron.ts":{"10":[49,50,51,52],"19":[49,50,51,52]},"packages/cli/src/scheduling/workflow-node-task-payload.ts":{"1":[49,50,51,53,54,55,56],"11":[49,50,51,53,54,55,56]},"packages/cli/src/workflows/triggers/poll-backoff.service.ts":{"17":[49,112,50,51,52],"32":[49,112,50,51,52],"44":[49,112,50,51,52],"61":[49,112,50,51,52],"75":[49,112,50,51,52],"121":[49,112,50,51,52],"134":[49,112,50,51,52],"145":[49,112,50,51,52]},"localhost-45811/assets/verified-Pt0guxqN.js":{"8":[133,77]},"packages/cli/src/modules/policy-infrastructure/policy-decision-audit.ts":{"68":[64,65,66],"84":[64,65,66],"90":[64,65,66],"150":[64,65,66],"166":[64,65,66],"180":[64,65,66]},"packages/cli/src/modules/type-availability-policies/credential-type-policy-instance.controller.ts":{"36":[64,65,66],"41":[64,65,66],"55":[64,65,66],"80":[64,65,66],"97":[64,65,66],"104":[64,65,66],"116":[64,65,66],"136":[64,65,66],"149":[64,65,66]},"packages/cli/src/modules/type-availability-policies/credential-type-policy.check.ts":{"48":[64,65,66],"60":[64,65,66],"72":[64,65,66],"79":[64,65,66],"84":[64,65,66],"99":[64,65,66],"112":[64,65,66],"124":[64,65,66],"139":[64,65,66],"156":[64,65,66],"174":[64,65,66],"175":[64,65,66],"176":[64,65,66],"190":[64,65,66],"193":[64,65,66],"199":[64,65,66],"209":[64,65,66],"225":[64,65,66],"226":[64,65,66]},"packages/cli/src/modules/type-availability-policies/database/repositories/type-availability-policy-attachment.repository.ts":{"19":[64,65,66],"30":[64,65,66],"39":[64,65,66],"53":[64,65,66],"82":[64,65,66],"87":[64,65,66],"95":[64,65,66],"118":[64,65,66],"133":[64,65,66],"138":[64,65,66],"156":[64,65,66],"161":[64,65,66]},"packages/cli/src/modules/type-availability-policies/database/repositories/type-availability-policy-scope.repository.ts":{"24":[64,65,66],"29":[64,65,66],"39":[64,65,66],"56":[64,65,66],"70":[64,65,66],"88":[64,65,66],"115":[64,65,66],"127":[64,65,66],"138":[64,65,66],"147":[64,65,66],"153":[64,65,66],"167":[64,65,66],"193":[64,65,66],"197":[64,65,66],"223":[64,65,66],"229":[64,65,66],"251":[64,65,66],"263":[64,65,66],"277":[64,65,66]},"packages/cli/src/modules/type-availability-policies/database/repositories/type-availability-policy.repository.ts":{"21":[64,65,66],"27":[64,65,66],"32":[64,65,66],"46":[64,65,66],"69":[64,65,66],"91":[64,65,66],"100":[64,65,66],"116":[64,65,66],"139":[64,65,66],"145":[64,65,66],"162":[64,65,66]},"packages/cli/src/modules/type-availability-policies/node-type-policy.check.ts":{"25":[64,65,66],"27":[64,65,66],"40":[64,65,66],"50":[64,65,66],"62":[64,65,66],"69":[64,65,66],"74":[64,65,66],"89":[64,65,66],"100":[64,65,66],"111":[64,65,66],"116":[64,65,66],"125":[64,65,66],"141":[64,65,66],"142":[64,65,66]},"packages/cli/src/modules/type-availability-policies/package-resolver.ts":{"25":[64,65,66],"28":[64,65,66],"45":[64,65,66],"58":[64,65,66],"63":[64,65,66],"80":[64,65,66],"86":[64,65,66],"89":[64,65,66],"97":[64,65,66],"112":[64,65,66]},"packages/cli/src/modules/type-availability-policies/policy-evaluator.ts":{"51":[64,65,66],"60":[64,65,66],"83":[64,65,66],"84":[64,65,66],"86":[64,65,66],"87":[64,65,66],"101":[64,65,66],"116":[64,65,66],"134":[64,65,66],"147":[64,65,66],"177":[64,65,66]},"packages/cli/src/modules/type-availability-policies/policy-shadow-lint.ts":{"24":[64,65,66],"38":[64,65,66],"72":[64,65,66],"75":[64,65,66],"86":[64,65,66],"88":[64,65,66]},"packages/cli/src/modules/type-availability-policies/type-availability-policy-instance.controller.ts":{"36":[64,65,66],"41":[64,65,66],"55":[64,65,66],"80":[64,65,66],"97":[64,65,66],"104":[64,65,66],"116":[64,65,66],"136":[64,65,66],"149":[64,65,66]},"packages/cli/src/modules/type-availability-policies/type-availability-policy.service.ts":{"97":[64,65,66],"105":[64,65,66],"107":[64,65,66],"114":[64,65,66],"116":[64,65,66],"159":[64,65,66],"193":[64,65,66],"194":[64,65,66],"197":[64,65,66],"198":[64,65,66],"214":[64,65,66],"234":[64,65,66],"262":[64,65,66],"279":[64,65,66],"284":[64,65,66],"294":[64,65,66],"304":[64,65,66],"331":[64,65,66],"377":[64,65,66],"409":[64,65,66],"418":[64,65,66],"474":[64,65,66],"493":[64,65,66],"531":[64,65,66],"547":[64,65,66],"594":[64,65,66],"633":[64,65,66],"634":[64,65,66],"663":[64,65,66],"667":[64,65,66],"672":[64,65,66],"700":[64,65,66],"708":[64,65,66],"722":[64,65,66],"726":[64,65,66],"735":[64,65,66],"780":[64,65,66],"804":[64,65,66],"861":[64,65,66],"1006":[64,65,66],"1026":[64,65,66],"1045":[64,65,66],"1062":[64,65,66],"1074":[64,65,66],"1081":[64,65,66],"1091":[64,65,66],"1095":[64,65,66],"1096":[64,65,66],"1109":[64,65,66],"1142":[64,65,66],"1156":[64,65,66],"1169":[64,65,66],"1207":[64,65,66],"1217":[64,65,66],"1240":[64,65,66],"1243":[64,65,66],"1251":[64,65,66],"1264":[64,65,66]},"packages/cli/src/modules/type-availability-policies/type-violation.ts":{"25":[64,65,66]},"packages/nodes-base/nodes/Postgres/Postgres.node.ts":{"8":[64,65,66,202]},"packages/nodes-base/nodes/Postgres/transport/index.ts":{"27":[64,65,66,202],"47":[64,65,66,202],"50":[64,65,66,202],"56":[64,65,66,202],"91":[64,65,66,202],"92":[64,65,66,202],"96":[64,65,66,202],"100":[64,65,66,202],"106":[64,65,66,202],"114":[64,65,66,202],"121":[64,65,66,202],"138":[64,65,66,202],"156":[64,65,66,202],"157":[64,65,66,202],"162":[64,65,66,202],"168":[64,65,66,202],"186":[64,65,66,202],"208":[64,65,66,202]},"packages/nodes-base/nodes/Postgres/v1/PostgresV1.node.ts":{"288":[64,65,66,202],"297":[64,65,66,202],"331":[64,65,66,202]},"packages/nodes-base/nodes/Postgres/v1/genericFunctions.ts":{"13":[64,65,66,202],"27":[64,65,66,202],"33":[64,65,66,202],"36":[64,65,66,202],"55":[64,65,66,202],"62":[64,65,66,202],"78":[64,65,66,202],"83":[64,65,66,202],"88":[64,65,66,202],"92":[64,65,66,202],"105":[64,65,66,202],"119":[64,65,66,202],"121":[64,65,66,202],"136":[64,65,66,202],"157":[64,65,66,202],"182":[64,65,66,202],"198":[64,65,66,202],"200":[64,65,66,202],"224":[64,65,66,202],"231":[64,65,66,202],"255":[64,65,66,202],"291":[64,65,66,202],"307":[64,65,66,202],"308":[64,65,66,202],"314":[64,65,66,202],"327":[64,65,66,202],"346":[64,65,66,202],"383":[64,65,66,202],"398":[64,65,66,202],"399":[64,65,66,202],"405":[64,65,66,202],"418":[64,65,66,202],"425":[64,65,66,202],"450":[64,65,66,202],"494":[64,65,66,202],"510":[64,65,66,202],"511":[64,65,66,202],"517":[64,65,66,202],"520":[64,65,66,202],"537":[64,65,66,202],"546":[64,65,66,202],"558":[64,65,66,202],"561":[64,65,66,202],"587":[64,65,66,202],"626":[64,65,66,202],"641":[64,65,66,202],"642":[64,65,66,202],"648":[64,65,66,202],"651":[64,65,66,202],"668":[64,65,66,202],"677":[64,65,66,202],"690":[64,65,66,202],"693":[64,65,66,202],"721":[64,65,66,202]},"packages/nodes-base/nodes/Postgres/v2/PostgresV2.node.ts":{"16":[64,65,66,202],"25":[64,65,66,202]},"packages/nodes-base/nodes/Postgres/v2/actions/database/deleteTable.operation.ts":{"88":[64,65,66,202]},"packages/nodes-base/nodes/Postgres/v2/actions/database/executeQuery.operation.ts":{"55":[64,65,66,202],"65":[64,65,66,202],"119":[64,65,66,202],"120":[64,65,66,202]},"packages/nodes-base/nodes/Postgres/v2/actions/database/insert.operation.ts":{"161":[64,65,66,202]},"packages/nodes-base/nodes/Postgres/v2/actions/database/select.operation.ts":{"79":[64,65,66,202]},"packages/nodes-base/nodes/Postgres/v2/actions/database/update.operation.ts":{"195":[64,65,66,202],"279":[64,65,66,202],"286":[64,65,66,202],"333":[64,65,66,202]},"packages/nodes-base/nodes/Postgres/v2/actions/database/upsert.operation.ts":{"194":[64,65,66,202],"286":[64,65,66,202],"298":[64,65,66,202]},"packages/nodes-base/nodes/Postgres/v2/actions/router.ts":{"15":[64,65,66,202]},"packages/nodes-base/nodes/Postgres/v2/helpers/utils.ts":{"27":[64,65,66,202],"36":[64,65,66,202],"46":[64,65,66,202],"50":[64,65,66,202],"51":[64,65,66,202],"54":[64,65,66,202],"58":[64,65,66,202],"63":[64,65,66,202],"70":[64,65,66,202],"79":[64,65,66,202],"87":[64,65,66,202],"138":[64,65,66,202],"144":[64,65,66,202],"165":[64,65,66,202],"194":[64,65,66,202],"206":[64,65,66,202],"221":[64,65,66,202],"240":[64,65,66,202],"248":[64,65,66,202],"325":[64,65,66,202],"328":[64,65,66,202],"329":[64,65,66,202],"336":[64,65,66,202],"367":[64,65,66,202],"370":[64,65,66,202],"373":[64,65,66,202],"380":[64,65,66,202],"390":[64,65,66,202],"406":[64,65,66,202],"427":[64,65,66,202],"467":[64,65,66,202],"509":[64,65,66,202],"515":[64,65,66,202],"531":[64,65,66,202],"532":[64,65,66,202],"540":[64,65,66,202],"541":[64,65,66,202],"544":[64,65,66,202],"551":[64,65,66,202],"554":[64,65,66,202],"561":[64,65,66,202],"576":[64,65,66,202],"606":[64,65,66,202],"622":[64,65,66,202],"627":[64,65,66,202],"634":[64,65,66,202],"639":[64,65,66,202],"642":[64,65,66,202],"659":[64,65,66,202],"666":[64,65,66,202],"687":[64,65,66,202],"690":[64,65,66,202],"708":[64,65,66,202],"725":[64,65,66,202],"766":[64,65,66,202],"768":[64,65,66,202],"780":[64,65,66,202],"786":[64,65,66,202],"795":[64,65,66,202]},"packages/nodes-base/nodes/Postgres/v2/methods/credentialTest.ts":{"10":[64,65,66,202]},"packages/nodes-base/nodes/Postgres/v2/methods/listSearch.ts":{"7":[64,65,66,202],"19":[64,65,66,202],"29":[64,65,66,202],"46":[64,65,66,202]},"packages/nodes-base/nodes/Postgres/v2/methods/loadOptions.ts":{"7":[64,65,66,202],"24":[64,65,66,202],"34":[64,65,66,202],"42":[64,65,66,202],"47":[64,65,66,202]},"packages/nodes-base/nodes/Postgres/v2/methods/resourceMapping.ts":{"67":[64,65,66,202],"82":[64,65,66,202],"105":[64,65,66,202],"107":[64,65,66,202]},"packages/nodes-base/utils/connection-pool-manager.ts":{"53":[64,65,66,202],"66":[64,65,66,202],"68":[64,65,66,202],"74":[64,65,66,202],"81":[64,65,66,202],"104":[64,65,66,202],"131":[64,65,66,202],"139":[64,65,66,202],"152":[64,65,66,202],"172":[64,65,66,202]},"packages/nodes-base/utils/postgres.ts":{"12":[64,65,66,202],"32":[64,65,66,202],"34":[64,65,66,202],"38":[64,65,66,202],"41":[64,65,66,202],"47":[64,65,66,202],"55":[64,65,66,202]},"packages/@n8n/nodes-langchain/nodes/embeddings/EmbeddingsHuggingFaceInference/EmbeddingsHuggingFaceInference.node.ts":{"16":[77],"86":[77],"94":[77],"132":[77],"142":[77]},"packages/@n8n/nodes-langchain/nodes/memory/MemoryXata/MemoryXata.node.ts":{"23":[77],"105":[77]},"packages/@n8n/nodes-langchain/nodes/output_parser/OutputParserStructured/OutputParserStructured.node.ts":{"32":[13,77],"198":[13,77]},"packages/@n8n/nodes-langchain/nodes/text_splitters/TextSplitterTokenSplitter/TextSplitterTokenSplitter.node.ts":{"13":[77],"62":[77]},"packages/@n8n/nodes-langchain/nodes/text_splitters/TextSplitterTokenSplitter/TokenTextSplitter.ts":{"16":[77],"28":[77],"36":[77]},"packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreQdrant/Qdrant.utils.ts":{"9":[77],"28":[77]},"packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreSupabase/VectorStoreSupabase.node.ts":{"67":[77],"84":[77]},"packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreWeaviate/Weaviate.utils.ts":{"22":[77],"68":[77],"127":[77]},"packages/@n8n/nodes-langchain/nodes/vector_store/shared/methods/listSearch.ts":{"10":[77],"19":[77],"27":[77],"58":[77],"65":[77],"73":[77],"87":[77],"95":[77],"102":[77]},"packages/@n8n/nodes-langchain/nodes/vector_store/shared/supabase.ts":{"7":[77]},"localhost-39517/assets/index-BoK1c_f3.js":{"3":[77]},"localhost-39517/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[77],"9":[77],"10":[77],"19":[77],"23":[77],"29":[77],"33":[77],"34":[77]},"localhost-39517/assets/verified-Pt0guxqN.js":{"8":[77]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/package--outline-16.svg":{"9":[86,124,48,77,216,82,100]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/basic-llm-chain.svg":{"11":[85,139,77]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/contextual-compression-retriever.svg":{"11":[77]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/guardrails.svg":{"11":[77]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/multiquery-retriever.svg":{"11":[77]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/sentiment-analysis.svg":{"11":[77]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/summarization-chain.svg":{"11":[77]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/token-splitter.svg":{"11":[77]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/workflow-retriever.svg":{"11":[77]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/LinkItem.vue":{"13":[77]},"packages/@n8n/nodes-langchain/nodes/tools/ToolVectorStore/ToolVectorStore.node.ts":{"17":[13],"51":[13],"140":[13],"148":[13]},"packages/cli/src/errors/response-errors/workflow-activation-bad-request.error.ts":{"8":[13,227]},"packages/cli/src/errors/response-errors/workflow-validation.error.ts":{"9":[13,227]},"packages/core/src/execution-engine/node-execution-context/utils/create-node-as-tool.ts":{"43":[20,125],"89":[20,125],"97":[20,125],"109":[20,125],"115":[20,125],"126":[20,125],"142":[20,125]},"packages/workflow/src/from-ai-parse-utils.ts":{"27":[20,125],"59":[20,125],"110":[20,125],"120":[20,125],"148":[20,125],"199":[20,125],"251":[20,125],"327":[20,125],"330":[20,125],"332":[20,125],"334":[20,125],"338":[20,125],"345":[20,125],"347":[20,125],"365":[20,125],"463":[20,125],"494":[20,125],"514":[20,125],"530":[20,125]},"localhost-36491/assets/index-BoK1c_f3.js":{"3":[20,137]},"localhost-36491/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[20,137],"9":[20,137],"10":[20,137],"19":[20,137],"23":[20,137],"29":[20,137],"33":[20,137],"34":[20,137]},"packages/@n8n/api-types/src/push/heartbeat.ts":{"9":[86,20,124]},"packages/frontend/@n8n/design-system/src/components/N8nSelectableList/SelectableList.vue":{"7":[86,20,124,181],"35":[86,124],"37":[86,20,124,181],"39":[86,20,124,181],"43":[86,20,124,181],"45":[86,124],"52":[86,124],"56":[86,124],"61":[86,124],"63":[86,20,124,181],"70":[86,20,124,181],"74":[86,124],"76":[86,20,124,181],"84":[86,124],"95":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nTag/Tag.vue":{"15":[86,20,124,181,81,82]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ToolListItem.vue":{"32":[20],"39":[20],"46":[20],"52":[20],"57":[20],"58":[20],"75":[20],"92":[20],"106":[20],"116":[20],"127":[20],"168":[20]},"packages/frontend/editor-ui/src/features/ai/chatHub/components/ToolsManagerModal.vue":{"55":[20],"56":[20],"60":[20],"67":[20],"87":[20],"90":[20],"91":[20],"98":[20],"122":[20],"124":[20],"132":[20],"140":[20],"154":[20],"159":[20],"160":[20],"166":[20],"173":[20],"177":[20],"191":[20],"227":[20],"228":[20],"231":[20],"235":[20],"292":[20],"315":[20],"328":[20],"357":[20],"366":[20],"386":[20],"389":[20],"411":[20],"424":[20],"433":[20],"441":[20],"456":[20],"464":[20],"471":[20],"492":[20],"493":[20]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputOverrides/FromAiOverrideField.vue":{"11":[86,20,124,181],"12":[86,20,124,181],"22":[86,20,124,181],"25":[86,20,124,181],"34":[86,124]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputOverrides/ParameterOverrideSelectableList.vue":{"16":[86,20,124,181],"22":[86,20,124,181],"23":[86,20,124,181],"29":[86,124],"37":[86,124],"41":[86,124],"47":[86,20,124,181],"58":[86,124]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/composables/useRestrictedNodeWarning.ts":{"13":[20]},"packages/frontend/editor-ui/src/features/shared/toolConfig/NodeToolSettingsContent.vue":{"91":[20],"96":[20],"98":[20],"122":[20],"126":[20],"130":[20],"140":[20],"145":[20],"148":[20],"156":[20],"157":[20],"160":[20],"174":[20],"192":[20],"195":[20],"207":[20],"222":[20],"229":[20],"243":[20],"252":[20],"332":[20],"352":[20],"353":[20],"414":[20],"415":[20],"430":[20],"435":[20],"444":[20],"445":[20],"453":[20],"491":[20],"529":[20]},"packages/@n8n/api-types/src/schemas/folder.schema.ts":{"10":[86,124,93,43,174]},"packages/@n8n/db/src/repositories/folder.repository.ts":{"16":"b:AAABAwA4AIgAgAIjGABAAgAAgAAEQAAABAgAAAA=","20":"b:AAABAwA4AIgAgAIjGABAAgAAgAAEQAAABAgAAAA=","31":"b:AAABAwA4AIgAgAIjGABAAgAAgAAEQAAABAgAAAA=","45":"b:AAABAwA4AIgAgAIjGABAAgAAgAAEQAAABAgAAAA=","53":"b:AAABAwA4AIgAgAIjGABAAgAAgAAEQAAABAgAAAA=","58":"b:AAABAwA4AIgAgAIjGABAAgAAgAAEQAAABAgAAAA=","69":"b:AAABAwA4AIgAgAIjGABAAgAAgAAEQAAABAgAAAA=","81":"b:AAABAwA4AIgAgAIjGABAAgAAgAAEQAAABAgAAAA=","86":"b:AAABAwA4AIgAgAIjGABAAgAAgAAEQAAABAgAAAA=","96":"b:AAABAwA4AIgAgAIjGABAAgAAgAAEQAAABAgAAAA=","115":"b:AAABAwA4AIgAgAIjGABAAgAAgAAEQAAABAgAAAA=","128":"b:AAABAwA4AIgAgAIjGABAAgAAgAAEQAAABAgAAAA=","134":"b:AAABAwA4AIgAgAIjGABAAgAAgAAEQAAABAgAAAA=","166":"b:AAABAwA4AIgAgAIjGABAAgAAgAAEQAAABAgAAAA=","170":"b:AAABAwA4AIgAgAIjGABAAgAAgAAEQAAABAgAAAA=","174":"b:AAABAwA4AIgAgAIjGABAAgAAgAAEQAAABAgAAAA=","178":"b:AAABAwA4AIgAgAIjGABAAgAAgAAEQAAABAgAAAA=","195":"b:AAABAwA4AIgAgAIjGABAAgAAgAAEQAAABAgAAAA=","228":"b:AAABAwA4AIgAgAIjGABAAgAAgAAEQAAABAgAAAA=","239":"b:AAABAwA4AIgAgAIjGABAAgAAgAAEQAAABAgAAAA=","255":"b:AAABAwA4AIgAgAIjGABAAgAAgAAEQAAABAgAAAA=","265":"b:AAABAwA4AIgAgAIjGABAAgAAgAAEQAAABAgAAAA=","279":"b:AAABAwA4AIgAgAIjGABAAgAAgAAEQAAABAgAAAA=","294":"b:AAABAwA4AIgAgAIjGABAAgAAgAAEQAAABAgAAAA=","304":"b:AAABAwA4AIgAgAIjGABAAgAAgAAEQAAABAgAAAA=","320":"b:AAABAwA4AIgAgAIjGABAAgAAgAAEQAAABAgAAAA=","339":"b:AAABAwA4AIgAgAIjGABAAgAAgAAEQAAABAgAAAA=","356":"b:AAABAwA4AIgAgAIjGABAAgAAgAAEQAAABAgAAAA=","396":"b:AAABAwA4AIgAgAIjGABAAgAAgAAEQAAABAgAAAA=","430":"b:AAABAwA4AIgAgAIjGABAAgAAgAAEQAAABAgAAAA=","439":"b:AAABAwA4AIgAgAIjGABAAgAAgAAEQAAABAgAAAA=","473":"b:AAABAwA4AIgAgAIjGABAAgAAgAAEQAAABAgAAAA="},"packages/@n8n/decorators/src/timed.ts":{"16":"b:AAABAwA4AIgAgAIjGAAAAgAAgAAEAAAABAgAAAA=","17":"b:AAABAwA4AIgAgAIjGAAAAgAAgAAEAAAABAgAAAA=","18":"b:AAABAwA4AIgAgAIjGAAAAgAAgAAEAAAABAgAAAA=","23":"b:AAABAwA4AIgAgAIjGAAAAgAAgAAEAAAABAgAAAA="},"packages/cli/src/controllers/folder.controller.ts":{"34":[93,43,174,44,45,118],"41":[93,43,174,44,45,118],"59":[93,43,174,44,45,118],"80":[93,43,174,44,45,118],"100":[93,43,174,44,45,118],"124":[93,43,174,44,45,118],"146":[93,43,174,44,45,118],"168":[93,43,174,44,45,118],"183":[93,43,174,44,45,118],"205":[93,43,174,44,45,118]},"packages/cli/src/services/folder.service.ts":{"31":[93,43,174,44,45,194,118],"39":[93,43,174,44,45,194,118],"57":[93,43,174,44,45,194,118],"62":[93,43,174,44,45,194,118],"70":[93,43,174,44,45,194,118],"73":[93,43,174,44,45,194,118],"112":[93,43,174,44,45,194,118],"120":[93,43,174,44,45,194,118],"149":[93,43,174,44,45,194,118],"168":[93,43,174,44,45,194,118],"181":[93,43,174,44,45,194,118],"204":[93,43,174,44,45,194,118],"212":[93,43,174,44,45,194,118],"220":[93,43,174,44,45,194,118],"228":[93,43,174,44,45,194,118],"239":[93,43,174,44,45,194,118],"253":[93,43,174,44,45,194,118],"254":[93,43,174,44,45,194,118],"262":[93,43,174,44,45,194,118],"287":[93,43,174,44,45,194,118],"300":[93,43,174,44,45,194,118],"326":[93,43,174,44,45,194,118],"339":[93,43,174,44,45,194,118],"342":[93,43,174,44,45,194,118],"347":[93,43,174,44,45,194,118]},"localhost-41201/assets/index-BoK1c_f3.js":{"3":[43,135,98]},"localhost-41201/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[43,135,98],"9":[43,135,98],"10":[43,135,98],"19":[43,135,98],"23":[43,135,98],"29":[43,135,98],"33":[43,135,98],"34":[43,135,98]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/folder--outline-16.svg":{"9":[86,124,93,43,174,45]},"packages/frontend/editor-ui/src/app/components/WorkflowCard.vue":{"61":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","141":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","144":[121,88,162,44,45,203,98,99,81,100],"145":[81],"146":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","148":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","151":[45,99],"154":[45,99],"158":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","162":[121,88,162,44,45,203,98,99,81,100],"173":[121,88,162,44,45,203,98,99,81,100],"193":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","309":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","333":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","337":[121,88,162,44,45,203,98,99,81,100],"343":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","368":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","380":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","384":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","386":[162,45,203,99,81],"415":[44,81],"501":[81],"511":[81],"547":[81],"551":[81],"589":[81],"638":[81],"678":[81],"680":[81],"682":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","694":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","706":[99],"726":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","756":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","773":[121,88,162,44,45,203,98,99,81,100],"799":[81]},"packages/frontend/editor-ui/src/app/composables/useAutoScrollOnDrag.ts":{"13":"b:AAABAwA4AIgAgAIjHAAAAgAAgAAEwAAADAgAAAA=","20":"b:AAABAwA4AIgAgAIjHAAAAgAAgAAEwAAADAgAAAA=","99":[93],"103":"b:AAABAwA4AIgAgAIjHAAAAgAAgAAEwAAADAgAAAA=","108":"b:AAABAwA4AIgAgAIjHAAAAgAAgAAEwAAADAgAAAA=","117":"b:AAAAAwA4AIAAgAIhHAAAAgAAgAAEwAAACAgAAAA=","125":"b:AAAAAwAgAIAAgAIADAAAAAAAgAAEgAAACAgAAAA="},"packages/frontend/editor-ui/src/app/views/WorkflowsView.vue":{"187":"b:AAABAwA4AIgAgAIjHAAAAgAAgAAEwAAADAgAAAA=","239":[93,43,174],"284":[93,43,174],"286":[93,43,174],"291":[93,43,174],"293":[93,43,174],"298":"b:AAAAAwA4AAAAgAIhHAAAAgAAAAAEwAAACAgAAAA=","302":"b:AAABAwA4AIgAgAIjHAAAAgAAgAAEwAAADAgAAAA=","306":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","308":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","312":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","316":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","323":"b:AAABAwA4AIgAgAIjHAAAAgAAgAAEwAAADAgAAAA=","327":[93,43,174,44,99,81],"331":[93,43,174,44,99,81],"337":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","341":"b:AAABAwA4AIgAgAIjHAAAAgAAgAAEwAAADAgAAAA=","345":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","349":"b:AAABAwA4AIgAgAIjHAAAAgAAgAAEwAAADAgAAAA=","354":"b:AAABAwA4AIgAgAIjHAAAAgAAgAAEwAAADAgAAAA=","361":[93,43,174,44,99,81],"367":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","373":[93,43,174],"379":[93,43,174],"384":[93,43,174,44,99,81],"390":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","392":[93,43,174,44,99,81],"396":[93,43,174,44,99,81],"405":[93,43,174,44,99,81],"430":[93,43,174,44,99,81],"453":[93,43,174,44,99,81],"465":[93,43,174,44,99,81],"493":[93,43,174,44,99,81],"502":[93,43,174],"506":"b:AAAAAwA4AAAAgAIhHAAAAgAAAAAEwAAACAgAAAA=","507":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","546":[81],"561":"b:AAAAAwA4AAAAgAIhHAAAAgAAAAAEwAAACAgAAAA=","575":[43,174,44,81],"586":[43,174,44],"595":[43,174,44],"601":[43,174,44],"605":"b:AAAAAwA4AAAAgAIhHAAAAgAAAAAEwAAACAgAAAA=","618":"b:AAAAAwA4AAAAgAIhHAAAAgAAAAAEwAAACAgAAAA=","622":"b:AAABAwA4AIgAgAIhHAAAAgAAAAAEwAAADAgAAAA=","627":"b:AAAAAwA4AAAAgAIhHAAAAgAAAAAEwAAACAgAAAA=","639":"b:AAABAwA4AIgAgAIjHAAAAgAAgAAEwAAADAgAAAA=","649":"b:AAABAwA4AIgAgAIjHAAAAgAAgAAEwAAADAgAAAA=","651":[93,43,174],"675":[44,81],"690":[174],"723":"b:AAAAAwA4AAAAgAIhHAAAAgAAAAAEwAAACAgAAAA=","733":[121,24,25,43,174,175,44,195,81],"737":[121,24,25,43,174,175,44,195,81],"745":"b:AAABAwA4AIgAgAIjHAAAAgAAgAAEwAAADAgAAAA=","767":"b:AAAAAwAgAIAAgAIADAAAAAAAgAAEgAAACAgAAAA=","787":"b:AAABAQAwAIgAAAIDHAAAAgAAgAAEgAAABAAAAAA=","803":"b:AAABAwA4AIgAgAIjHAAAAgAAgAAEwAAADAgAAAA=","860":"b:AAABAwA4AIgAgAIjHAAAAgAAgAAEwAAADAgAAAA=","874":[81],"908":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","909":[93,43,174],"927":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","928":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","961":"b:AAABAwA4AIgAgAIjHAAAAgAAgAAEwAAADAgAAAA=","982":[24,93,43,174,44,99,81],"990":[43,81],"1001":"b:AAAAAwA4AAAAgAIhHAAAAgAAAAAEwAAACAgAAAA=","1031":[24,93,43,174,44,99,81],"1071":"b:AAABAwA4AIgAgAIjHAAAAgAAgAAEwAAADAgAAAA=","1076":"b:AAABAwA4AIgAgAIjHAAAAgAAgAAEwAAADAgAAAA=","1105":[81],"1286":[81],"1287":[81],"1311":[93,174],"1312":[93,174],"1318":[174],"1342":[93,43,174],"1387":[93],"1395":[93],"1414":[93],"1446":[43,174],"1677":[43,174],"1738":[43,174],"1776":[43],"1822":[174],"1857":[43,174],"1876":[174],"1892":[93],"2019":[44],"2046":[44],"2093":[93],"2106":[93],"2164":[174],"2247":"b:AAAAAwA4AAAAgAIhHAAAAgAAAAAEwAAACAgAAAA=","2260":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","2327":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","2363":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","2373":[93,43,174],"2376":[93,43,174],"2377":[93,43,174],"2417":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","2420":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","2421":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","2460":[121,24,25,43,174,175,44,195,81],"2479":[81],"2492":[81],"2507":[81],"2523":[81],"2535":[43,44],"2537":[43,44]},"packages/frontend/editor-ui/src/experiments/credentialsAppSelection/stores/credentialsAppSelection.store.ts":{"14":"b:AAABAwA4AIgAgAIjHAAAAgAAgAAEwAAADAgAAAA=","23":[16,24,45,59,63,194],"25":[16,24,45,59,63,194],"29":[16,24,45,59,63,194],"35":[16,24,45,59,63,194]},"packages/frontend/editor-ui/src/experiments/openWorkflowInAssistant/components/OpenInAssistantCardButton.vue":{"13":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","23":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","32":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA="},"packages/frontend/editor-ui/src/experiments/openWorkflowInAssistant/composables/useOpenInAssistantCard.ts":{"10":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","24":"b:AAAAAAA4AAAAAAIhHAAAAgAAAAAEQAAAAAgAAAA=","28":[162,45,203,99,81]},"packages/frontend/editor-ui/src/experiments/personalizedTemplates/stores/personalizedTemplates.store.ts":{"66":"b:AAABAwA4AIgAgAIjHAAAAgAAgAAEwAAADAgAAAA=","91":"b:AAAAAwA4AAAAAAIhHAAAAgAAAAAEwAAACAgAAAA=","164":"b:AAABAwA4AIgAgAIjHAAAAgAAgAAEwAAADAgAAAA="},"packages/frontend/editor-ui/src/experiments/personalizedTemplatesV3/stores/personalizedTemplatesV3.store.ts":{"13":"b:AAABAwA4AIgAgEIjHAAAEgAAgAAEwAAADAgAAAA=","27":"b:AAAAAwAYAAAAAEIBFAAAEgAAAAAAwAAACAgAAAA=","36":"b:AAABAwA4AIgAgEIjHAAAEgAAgAAEwAAADAgAAAA=","49":[86,124],"60":[86,124],"66":[86,124],"70":[86,124],"74":[86,124],"78":[86,124],"82":[86,124],"86":[86,124],"90":[86,124],"96":[86,124],"100":[86,124],"105":[86,124],"130":"b:AAABAwA4AIgAgEIjHAAAEgAAgAAEwAAADAgAAAA="},"packages/frontend/editor-ui/src/experiments/templateRecoV2/stores/templateRecoV2.store.ts":{"14":"b:AAABAwA4AIgAgEIjHAAAEgAAgAAEwAAADAgAAAA=","21":"b:AAAAAwAYAAAAAEIBFAAAEgAAAAAAwAAACAgAAAA=","28":[86,124],"40":[86,124],"44":[86,124],"48":[86,124],"55":[86,124],"58":[86,124],"64":[86,124],"70":[86,124],"76":[86,124],"82":[86,124]},"packages/frontend/editor-ui/src/features/core/folders/components/FolderCard.vue":{"68":[93,43,174],"72":[43],"74":[93,43,174],"98":[93,43,174],"106":[93,43,174],"119":[93,43,174],"130":[93,43,174],"134":[93,43,174],"145":[43],"165":[43],"169":[93,43,174],"180":[93,43,174],"213":[93,43,174],"220":[93,43,174],"221":[93,43,174],"229":[93,43,174],"232":[93,43,174],"239":[93,43,174],"247":[93,174],"258":[93,43],"270":[93,43,174],"279":[93,43,174],"285":[93,43,174],"286":[93,43,174],"298":[43],"328":[93,43,174],"338":[93,43,174],"359":[93,43,174]},"packages/frontend/editor-ui/src/features/core/folders/folders.api.ts":{"11":[86,124,43,174],"23":[86,124,43,174],"35":[86,124,174],"46":[86,124,174],"57":[86,124,44,118],"87":[86,124],"100":[86,124,93],"111":[86,124,174]},"packages/frontend/editor-ui/src/features/workflow-reviews/components/WorkflowPublishChoiceDialog.vue":{"17":[43],"26":[43],"31":[43],"34":[43],"42":[43],"43":[43],"45":[43],"48":[43],"53":[43],"60":[43],"64":[43]},"packages/frontend/editor-ui/src/features/workflow-reviews/components/WorkflowReviewRequiredToggle.vue":{"9":[43],"17":[43],"20":[43],"21":[43],"26":[43],"39":[43],"41":[43],"46":[43],"58":[43]},"packages/frontend/editor-ui/src/features/workflow-reviews/components/WorkflowReviewStatusBanner.vue":{"29":[43],"54":[43],"63":[43],"74":[43],"80":[43],"138":[43],"140":[43],"149":[43],"152":[43],"157":[43],"160":[43],"173":[43],"182":[43],"194":[43],"202":[43],"208":[43]},"packages/frontend/editor-ui/src/features/workflow-reviews/components/WorkflowReviewSubmittedDialog.vue":{"21":[43],"34":[43],"35":[43],"39":[43],"44":[43],"54":[43],"59":[43],"64":[43]},"packages/frontend/editor-ui/src/features/workflow-reviews/components/WorkflowSubmitForReviewDialog.vue":{"35":[43],"71":[43],"77":[43],"79":[43],"86":[43],"87":[43],"95":[43],"113":[43],"114":[43],"132":[43],"137":[43],"139":[43],"142":[43],"145":[43],"148":[43],"153":[43],"161":[43],"239":[43],"259":[43],"283":[43],"301":[43],"321":[43],"333":[43],"347":[43],"354":[43],"365":[43],"373":[43]},"packages/frontend/editor-ui/src/features/workflow-reviews/components/WorkflowUpdateReviewDialog.vue":{"30":[43],"64":[43],"68":[43],"74":[43],"77":[43],"79":[43],"81":[43],"87":[43],"98":[43],"119":[43],"120":[43],"138":[43],"143":[43],"148":[43],"153":[43],"158":[43],"232":[43],"246":[43],"252":[43],"255":[43],"259":[43],"289":[43],"313":[43],"321":[43],"332":[43],"340":[43]},"packages/frontend/editor-ui/src/features/workflow-reviews/composables/useReviewVersionName.ts":{"11":[43],"22":[43],"30":[43],"39":[43]},"packages/frontend/editor-ui/src/features/workflows/composables/useWorkflowsEmptyState.ts":{"19":"b:AAABAQAwAIgAAAIBHAAAAgAAAAAEwAAABAgAAAA=","20":"b:AAABAwA4AIgAgAIhHAAAAgAAAAAEwAAADAgAAAA=","22":"b:AAABAwA4AIgAgAIhHAAAAgAAAAAEwAAADAgAAAA=","28":[16,24,45,59,63,194],"32":[16,24,45,59,63,194],"40":[16,24,45,59,63,194]},"packages/cli/src/modules/type-availability-policies/available-credential-types.controller.ts":{"18":[65,66],"41":[65,66],"49":[65,66]},"packages/cli/src/public-api/v1/controllers/credential-type-policies.public.controller.ts":{"53":[65],"73":[65],"75":[65],"96":[65],"119":[65],"152":[65],"182":[65],"216":[65],"246":[65],"270":[65],"296":[65],"326":[65],"346":[65],"360":[65]},"localhost-41201/assets/verified-Pt0guxqN.js":{"8":[135]},"packages/frontend/editor-ui/src/app/utils/forceParse.ts":{"9":[6,86,124,135,75]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/utils.ts":{"10":[86,124,135,209],"19":[86,124,135,209],"30":[86,124,135,209],"40":[86,124],"50":[86,124],"53":[86,124],"66":[86,124],"67":[86,124],"70":[86,124],"82":[86,124],"91":[86,124],"94":[86,124]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/typescript/client/completions.ts":{"19":[86,124,135],"30":[86,124,135],"53":[86,124],"54":[86,124],"97":[86,124],"101":[86,124],"131":[86,124],"135":[86,124],"137":[86,124]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/typescript/client/linter.ts":{"4":[86,124,135],"8":[86,124,135]},"packages/@n8n/db/src/repositories/activity-event.repository.ts":{"36":[86,137,209],"83":[86,137,209],"88":[86,137,209],"103":[86,137,209],"112":[86,137,209],"132":[86,137,209],"168":[86,137,209],"184":[86,137,209],"211":[86,137,209],"250":[86,137,209],"259":[86,137,209],"291":[86,137,209],"323":[86,137,209],"334":[86,137,209]},"packages/cli/src/modules/breaking-changes/owners/migration-owner-suggestion.service.ts":{"44":[86,137,209],"53":[86,137,209],"59":[86,137,209],"71":[86,137,209],"89":[86,137,209],"105":[86,137,209],"111":[86,137,209],"112":[86,137,209],"122":[86,137,209],"131":[86,137,209],"137":[86,137,209],"145":[86,137,209],"161":[86,137,209]},"packages/nodes-base/nodes/SplitInBatches/SplitInBatches.node.ts":{"9":[166,176,187,137]},"packages/nodes-base/nodes/SplitInBatches/v1/SplitInBatchesV1.node.ts":{"62":[166,176,187,137],"97":[166,176,187,137],"111":[166,176,187,137],"128":[166,176,187,137]},"packages/nodes-base/nodes/SplitInBatches/v2/SplitInBatchesV2.node.ts":{"64":[166,176,187,137],"102":[166,176,187,137],"116":[166,176,187,137],"135":[166,176,187,137],"147":[166,176,187,137]},"packages/nodes-base/nodes/SplitInBatches/v3/SplitInBatchesV3.node.ts":{"88":[166,176,187,137],"126":[166,176,187,137],"140":[166,176,187,137],"159":[166,176,187,137],"171":[166,176,187,137]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/status-waiting.svg":{"8":[86,124,137]},"packages/frontend/editor-ui/src/features/execution/logs/components/LogsViewConsumedTokenCountText.vue":{"8":[137]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataJson.vue":{"22":[181,136,137,116,210],"59":[181,136,137,116,210],"61":[181,136,137,116,210],"63":[116],"71":[181,136,137,116,210],"82":[181,136,137,116,210],"83":[181,136,137,116,210],"85":[116],"98":[116],"122":[181,136,137,116,210],"126":[181,136,137,116,210],"130":[181,136,137,116,210],"166":[181,136,137,116,210],"181":[181,136,137,116,210]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataJsonActions.vue":{"64":[181,136,137,116]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataParsedAiContent.vue":{"31":[137],"33":[137],"54":[137],"63":[137],"72":[137],"76":[137]},"packages/frontend/editor-ui/src/features/ndv/runData/components/ai/utils.ts":{"38":[137],"51":[137],"52":[137],"53":[137]},"packages/cli/src/modules/data-table/data-table-aggregate.service.ts":{"13":"b:AAABAwAwAIgAAAIjHAAAAgAAgAAEAAAABAAAAAA=","21":"b:AAABAwAwAIgAAAIjHAAAAgAAgAAEAAAABAAAAAA=","22":"b:AAABAwAwAIgAAAIjHAAAAgAAgAAEAAAABAAAAAA=","24":"b:AAABAwAwAIgAAAIjHAAAAgAAgAAEAAAABAAAAAA=","37":"b:AAABAwAwAIgAAAIjHAAAAgAAgAAEAAAABAAAAAA="},"localhost-40985/assets/index-BoK1c_f3.js":{"3":[6,121,158,174,197,72,213]},"localhost-40985/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[6,121,158,174,197,72,213],"9":[6,121,158,174,197,72,213],"10":[6,121,158,174,197,72,213],"19":[6,121,158,174,197,72,213],"23":[6,121,158,174,197,72,213],"29":[6,121,158,174,197,72,213],"33":[6,121,158,174,197,72,213],"34":[6,121,158,174,197,72,213]},"packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/CodeDiffMessage.vue":{"19":[6,86,124],"20":[6,86,124],"31":[86,124],"32":[6,86,124],"40":[6,86,124],"41":[6,86,124]},"packages/frontend/@n8n/design-system/src/components/CodeDiff/CodeDiff.vue":{"10":[6,86,124],"43":[6,86,124],"48":[6,86,124],"49":[86,124],"85":[6,86,124],"93":[6,86,124],"120":[6,86,124],"121":[6,86,124],"137":[6,86,124],"138":[6,86,124]},"localhost-46835/assets/index-BoK1c_f3.js":{"3":[3]},"localhost-46835/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[3],"9":[3],"10":[3],"19":[3],"23":[3],"29":[3],"33":[3],"34":[3]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/clock--outline-16.svg":{"9":[3,86,124,209,100]},"packages/frontend/@n8n/design-system/src/components/TableBase/TableBase.vue":{"8":[3,86,124,192],"22":[86,124],"23":[86,124],"26":[3,86,124,192],"31":[3,86,124,192]},"packages/frontend/editor-ui/src/features/agents/components/AgentSessionTimelineHeader.vue":{"55":[3],"65":[3],"68":[3],"77":[3],"145":[3]},"packages/frontend/editor-ui/src/features/agents/components/AgentSessionTimelinePanel.vue":{"38":[3],"59":[3],"72":[3],"79":[3],"83":[3],"84":[3],"90":[3],"91":[3],"93":[3],"146":[3],"159":[3],"168":[3],"184":[3],"213":[3],"269":[3],"280":[3],"284":[3],"315":[3],"319":[3],"329":[3],"352":[3],"353":[3],"359":[3],"374":[3],"386":[3],"426":[3]},"packages/frontend/editor-ui/src/features/agents/components/AgentSessionsFilter.vue":{"15":[3],"49":[3],"65":[3],"77":[3]},"packages/frontend/editor-ui/src/features/agents/components/SessionDetailPanel.vue":{"47":[3],"66":[3],"90":[3],"163":[3],"166":[3],"180":[3],"202":[3],"225":[3],"241":[3],"251":[3],"269":[3],"277":[3]},"packages/frontend/editor-ui/src/features/agents/components/SessionEventFilter.vue":{"24":[3],"28":[3],"29":[3],"30":[3],"62":[3],"96":[3],"101":[3]},"packages/frontend/editor-ui/src/features/agents/components/SessionTimelineChart.vue":{"58":[3],"65":[3],"85":[3],"89":[3],"95":[3],"108":[3],"136":[3],"165":[3],"192":[3],"194":[3],"224":[3],"246":[3],"290":[3],"291":[3],"297":[3],"301":[3],"317":[3],"381":[3]},"packages/frontend/editor-ui/src/features/agents/components/SessionTimelinePill.vue":{"7":[3],"19":[3],"48":[3],"49":[3]},"packages/frontend/editor-ui/src/features/agents/components/SessionTimelineRow.vue":{"25":[3],"36":[3],"43":[3],"44":[3],"46":[3],"51":[3],"57":[3],"85":[3],"87":[3],"97":[3],"124":[3],"129":[3]},"packages/frontend/editor-ui/src/features/agents/components/SessionTimelineTable.vue":{"13":[3],"78":[3],"84":[3],"99":[3],"102":[3],"103":[3],"104":[3],"109":[3],"113":[3],"124":[3],"136":[3],"139":[3],"142":[3],"150":[3],"168":[3],"192":[3],"202":[3],"210":[3],"211":[3],"220":[3],"229":[3],"248":[3],"257":[3]},"packages/frontend/editor-ui/src/features/agents/components/ToolIoView.vue":{"45":[3],"47":[3],"60":[3],"183":[3],"184":[3],"186":[3]},"packages/frontend/editor-ui/src/features/agents/components/WorkflowExecutionLogViewer.vue":{"24":[3],"40":[3],"52":[3],"57":[3],"59":[3],"68":[3],"69":[3],"72":[3],"84":[3],"92":[3],"94":[3],"98":[3],"109":[3],"130":[3],"138":[3],"161":[3],"175":[3],"187":[3],"195":[3]},"packages/frontend/editor-ui/src/features/agents/composables/useBackOrFallback.ts":{"9":[3]},"packages/frontend/editor-ui/src/features/agents/composables/useSubAgentNames.ts":{"12":[3],"25":[3]},"packages/frontend/editor-ui/src/features/agents/session-timeline.styles.ts":{"6":[3],"41":[3]},"packages/frontend/editor-ui/src/features/agents/session-timeline.utils.ts":{"33":[3],"38":[3],"81":[3],"109":[3],"196":[3],"220":[3],"242":[3],"253":[3],"326":[3],"335":[3],"342":[3],"343":[3],"348":[3],"351":[3],"394":[3],"494":[3],"498":[3],"514":[3],"519":[3],"589":[3],"689":[3],"719":[3]},"packages/frontend/editor-ui/src/features/agents/utils/background-job-labels.ts":{"10":[3]},"packages/frontend/editor-ui/src/features/agents/utils/thread-title.ts":{"27":[3],"38":[3]},"packages/frontend/editor-ui/src/features/agents/views/AgentSessionTimelineView.vue":{"50":[3],"51":[3],"52":[3],"76":[3],"84":[3],"91":[3],"96":[3],"112":[3],"128":[3],"135":[3],"140":[3],"150":[3],"168":[3],"179":[3],"190":[3],"195":[3],"196":[3],"201":[3],"202":[3],"203":[3],"222":[3],"228":[3],"244":[3],"268":[3],"301":[3],"307":[3]},"packages/frontend/editor-ui/src/features/agents/views/AgentSessionsListView.vue":{"58":[3],"59":[3],"60":[3],"75":[3],"100":[3],"133":[3],"178":[3],"283":[3],"324":[3],"346":[3]},"packages/frontend/editor-ui/src/features/ndv/runData/components/StandaloneRunData.vue":{"26":[3]},"packages/frontend/editor-ui/src/features/ndv/runData/components/StandaloneRunDataHost.vue":{"38":[3],"59":[3],"86":[3],"99":[3],"132":[3],"155":[3],"156":[3],"161":[3],"169":[3],"172":[3]},"packages/frontend/editor-ui/src/app/utils/stringUtils.ts":{"8":[86,124,208,210],"16":[86,124,208,210],"21":[86,124,208,210],"22":[86,124,208,210]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataPaginationBar.vue":{"11":[86,124,177,208,210],"15":[86,124,177,208,210],"26":[86,124,177],"34":[86,124],"36":[86,124,177,208,210],"37":[86,124,177,208,210]},"packages/frontend/editor-ui/src/app/components/VersionCard.vue":{"14":[86,121,124],"16":[86,124],"18":[86,121,124],"42":[86,121,124],"46":[86,124],"65":[86,124]},"localhost-36399/assets/index-BoK1c_f3.js":{"3":[22]},"localhost-36399/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[22],"9":[22],"10":[22],"19":[22],"23":[22],"29":[22],"33":[22],"34":[22]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/cloud--outline-16.svg":{"9":[86,22,124]},"packages/frontend/@n8n/rest-api-client/src/api/cloudPlans.ts":{"90":[86,22,124],"94":[86,22,124],"98":[86,22,124],"102":[86,124],"108":[86,124],"112":[86,124],"121":[86,124]},"packages/frontend/editor-ui/src/app/utils/rbac/checks/isInstanceOwner.ts":{"4":[86,143,22,124,193,63]},"packages/frontend/editor-ui/src/features/settings/apiKeys/apiKeys.store.ts":{"18":[86,22,124],"24":[86,22,124],"40":[86,124],"43":[86,124],"46":[86,124],"50":[86,124],"51":[86,124],"60":[86,124],"65":[86,124],"87":[86,124],"97":[86,124],"107":[86,124],"114":[86,124],"122":[86,124],"126":[86,124],"135":[86,124],"144":[86,124],"150":[86,124],"157":[86,124]},"packages/frontend/editor-ui/src/features/settings/apiKeys/components/ApiKeyScopesModal.vue":{"7":[22],"18":[22],"27":[22]},"packages/frontend/editor-ui/src/features/settings/apiKeys/components/RevokeApiKeyConfirmModal.vue":{"9":[86,22,124],"25":[86,22,124],"33":[86,22,124],"44":[86,22,124],"57":[86,124],"58":[86,124],"59":[86,124]},"packages/frontend/editor-ui/src/features/settings/apiKeys/components/RotateApiKeyConfirmModal.vue":{"7":[22],"21":[22],"28":[22]},"packages/frontend/editor-ui/src/features/settings/apiKeys/views/SettingsApiView.vue":{"136":[22],"206":[22],"306":[22],"308":[22],"309":[22],"318":[22],"327":[22]},"packages/frontend/editor-ui/src/features/shared/banners/components/banners/BaseBanner.vue":{"19":[86,22,124],"36":[86,22,124],"40":[86,124],"46":[86,22,124],"62":[86,22,124]},"packages/frontend/editor-ui/src/features/shared/banners/components/banners/TrialBanner.vue":{"77":[86,22,124],"92":[86,22,124],"93":[86,22,124],"100":[86,22,124],"107":[86,22,124],"108":[86,22,124],"109":[86,22,124],"117":[86,22,124],"120":[86,22,124],"126":[86,22,124],"131":[86,22,124],"133":[86,22,124],"147":[86,22,124],"157":[86,22,124],"162":[86,22,124],"170":[86,22,124],"175":[86,22,124],"182":[86,124],"193":[86,22,124],"207":[86,22,124],"223":[86,22,124],"227":[86,22,124],"233":[86,22,124],"241":[86,22,124]},"packages/cli/src/modules/dynamic-credentials.ee/services/credential-check-proxy.service.ts":{"24":[27,158,67],"29":[27,158,67],"41":[27,158,67],"70":[27,158,67],"96":[27,158,67],"117":[27,158,67],"148":[27,158,67],"159":[27,158,67],"165":[27,158,67],"171":[27,158,67]},"packages/cli/src/modules/inbound-auth-core/grant-authorization.ts":{"11":[27,158,67]},"packages/cli/src/modules/oauth-server/oauth-flow.service.ts":{"25":[27,158],"42":[27,158],"73":[27,158],"145":[27,158]},"packages/cli/src/modules/oauth-server/resource-gate.ts":{"16":[27,158,67],"21":[27,158,67],"22":[27,158,67]},"packages/cli/src/modules/oauth-server/resource-identity.ts":{"14":[27,158,67]},"packages/cli/src/services/oauth2-flow-proxy.service.ts":{"24":[27,158],"27":[27,158],"31":[27,158],"36":[27,158],"41":[27,158]},"packages/@n8n/api-types/src/dto/folders/list-folder-query.dto.ts":{"46":[86,124,174,44,45,118],"72":[86,124,174,44,45,118],"73":[86,124,174,44,45,118],"81":[86,124,174,44,45,118],"82":[86,124,174,44,45,118],"91":[86,124,174,44,45,118],"99":[86,124],"100":[174,44,45,118]},"packages/frontend/editor-ui/src/features/core/folders/components/DeleteFolderModal.vue":{"16":[86,124,174],"41":[86,124,174],"46":[86,124,174],"50":[86,124,174],"55":[86,124,174],"74":[86,124,174],"82":[86,124,174],"105":[86,124],"141":[86,124],"143":[86,124,174],"155":[86,124,174],"158":[86,124],"162":[86,124,174],"165":[86,124],"168":[86,124,174],"176":[86,124],"181":[86,124],"194":[86,124],"197":[86,124,174],"199":[86,124,174],"208":[86,124],"227":[86,124,174]},"packages/cli/src/modules/promotions.ee/promotions-git.utils.ts":{"20":[59],"25":[59],"33":[59],"54":[59],"55":[59],"61":[59],"91":[59],"96":[59],"106":[59]},"packages/cli/src/modules/source-control.ee/source-control-export.service.ee.ts":{"73":[59],"98":[59],"102":[59],"106":[59],"110":[59],"118":[59],"120":[59],"127":[59],"129":[59],"130":[59],"134":[59],"146":[59],"151":[59],"173":[59],"176":[59],"198":[59],"216":[59],"229":[59],"254":[59],"270":[59],"299":[59],"314":[59],"315":[59],"348":[59],"382":[59],"387":[59],"423":[59],"451":[59],"457":[59],"465":[59],"483":[59],"489":[59],"525":[59],"528":[59],"556":[59],"578":[59],"582":[59],"589":[59],"603":[59],"619":[59]},"packages/cli/src/modules/source-control.ee/source-control-git.service.ee.ts":{"48":[59],"58":[59],"81":[59],"118":[59],"168":[59],"172":[59],"187":[59],"194":[59],"209":[59],"265":[59],"280":[59],"291":[59],"322":[59],"330":[59],"339":[59],"340":[59],"354":[59],"365":[59],"376":[59],"388":[59],"400":[59],"414":[59],"468":[59],"471":[59],"472":[59],"490":[59],"504":[59],"514":[59],"535":[59],"545":[59],"562":[59],"576":[59],"600":[59],"607":[59],"615":[59]},"packages/cli/src/modules/source-control.ee/source-control-helper.ee.ts":{"42":[59],"66":[59],"74":[59],"97":[59],"124":[59],"158":[59],"162":[59],"166":[59],"173":[59],"177":[59],"181":[59],"185":[59],"189":[59],"207":[59],"213":[59],"226":[59],"246":[59],"258":[59],"264":[59],"281":[59],"287":[59],"291":[59],"300":[59],"304":[59],"305":[59],"309":[59],"317":[59],"321":[59],"323":[59],"327":[59],"334":[59],"336":[59],"338":[59],"340":[59],"342":[59],"346":[59],"353":[59],"354":[59],"356":[59],"358":[59],"368":[59],"385":[59],"422":[59],"426":[59],"448":[59],"456":[59],"457":[59],"459":[59],"476":[59],"496":[59],"505":[59],"509":[59],"524":[59]},"packages/cli/src/modules/source-control.ee/source-control-preferences.service.ee.ts":{"35":[59],"48":[59],"56":[59],"66":[59],"74":[59],"84":[59],"92":[59],"100":[59],"112":[59],"121":[59],"136":[59],"144":[59],"170":[59],"184":[59],"198":[59],"211":[59],"239":[59],"243":[59],"247":[59],"251":[59],"255":[59],"259":[59],"278":[59],"330":[59],"338":[59]},"packages/cli/src/modules/source-control.ee/source-control.controller.ee.ts":{"31":[59],"40":[59],"67":[59],"132":[59],"177":[59],"187":[59],"196":[59],"227":[59],"243":[59],"252":[59],"269":[59],"286":[59],"300":[59]},"packages/cli/src/modules/source-control.ee/source-control.service.ee.ts":{"72":[59],"89":[59],"104":[59],"113":[59],"126":[59],"149":[59],"158":[59],"188":[59],"219":[59],"268":[59],"277":[59],"290":[59],"291":[59],"294":[59],"310":[59],"320":[59],"331":[59],"348":[59],"362":[59],"370":[59],"376":[59],"398":[59],"417":[59],"418":[59],"437":[59],"440":[59],"507":[59],"532":[59],"537":[59],"541":[59],"555":[59],"570":[59],"594":[59],"623":[59],"728":[59],"729":[59],"735":[59]},"localhost-41479/assets/index-BoK1c_f3.js":{"3":[59]},"localhost-41479/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[59],"9":[59],"10":[59],"19":[59],"23":[59],"29":[59],"33":[59],"34":[59]},"packages/frontend/@n8n/design-system/src/components/N8nColorPicker/ColorPicker.vue":{"21":[86,124,59],"34":[86,124,59],"45":[86,124],"49":[86,124],"53":[86,124],"57":[86,124],"59":[86,124,59]},"packages/frontend/editor-ui/src/app/components/layouts/EmptyStateLayout.vue":{"19":[16,24,45,59,63,194],"46":[16,24,45,59,63,194],"50":[16,45,194],"57":[16,24,45,59,63,194],"77":[16,24,45,59,63,194],"85":[16,24,45,59,63,194],"111":[16,24,45,59,63,194],"165":[16,24,45,59,63,194],"174":[16,24,45,59,63,194],"185":[16,24,45,59,63,194],"194":[16,24,45,59,63,194]},"packages/frontend/editor-ui/src/experiments/surfaceMcpToNewCloudUsers/composables/useSurfaceMcpEmptyState.ts":{"15":[16,24,45,59,63,194],"25":[16,24,45,59,63,194],"43":[16,24,45,59,63,194],"48":[16,24,45,59,63,194],"65":[16,24,45,59,63,194]},"packages/frontend/editor-ui/src/experiments/surfaceMcpToNewCloudUsers/composables/useSurfaceMcpToNewCloudUsersEligibility.ts":{"7":[16,24,45,59,63,194],"13":[16,24,45,59,63,194]},"packages/frontend/editor-ui/src/experiments/surfaceMcpToNewCloudUsers/stores/surfaceMcpToNewCloudUsers.store.ts":{"22":[16,24,45,59,63,194]},"packages/frontend/editor-ui/src/features/integrations/sourceControl.ee/views/SettingsSourceControl.vue":{"47":[59],"48":[59],"119":[59],"137":[59],"148":[59],"157":[59],"178":[59],"182":[59],"287":[59],"288":[59],"338":[59],"348":[59],"352":[59],"429":[59],"447":[59],"452":[59],"453":[59],"470":[59],"492":[59],"499":[59],"518":[59],"520":[59],"539":[59]},"packages/frontend/editor-ui/src/app/composables/useReportWorkflowFailuresToParent.ts":{"33":[148,149,197,198]},"packages/frontend/editor-ui/src/app/layouts/DemoLayout.vue":{"18":[148,149,197,198],"62":[148,149,197,198],"89":[148,149,197,198]},"packages/frontend/editor-ui/src/app/views/DemoDiffView.vue":{"20":[197],"27":[197],"36":[197],"64":[197]},"packages/frontend/editor-ui/src/features/execution/logs/components/DemoFooter.vue":{"9":[148,149,197,198],"10":[148,149,197,198],"11":[148,149,197,198]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/HighlightedEdge.vue":{"6":[86,124,197],"7":[86,124,197],"11":[86,124,197],"13":[86,124,197]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/SyncedWorkflowCanvas.vue":{"16":[86,124,197],"39":[86,124,197],"49":[86,124,197],"68":[86,124,197],"71":[86,124,197],"76":[86,124],"90":[86,124,197],"98":[86,124,197],"102":[86,124,197],"105":[86,124],"107":[86,124],"108":[86,124],"119":[86,124],"131":[86,124,197],"146":[86,124,197],"149":[86,124,197],"152":[86,124,197]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/WorkflowDiffContent.vue":{"15":[86,124,197],"41":[86,124,197],"46":[86,124,197],"48":[86,124,197],"59":[86,124,197],"70":[86,124,197],"75":[86,124,197],"87":[86,124,197],"102":[86,124,197],"113":[86,124,197],"118":[86,124,197],"130":[86,124,197],"138":[86,124],"139":[86,124]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/WorkflowDiffView.vue":{"32":[86,124,197],"62":[86,124],"66":[86,124],"80":[86,124,197],"81":[86,124,197],"100":[86,124,197],"101":[86,124,197],"107":[86,124],"118":[86,124,197],"126":[86,124],"137":[86,124],"147":[86,124,197],"165":[86,124],"168":[86,124,197],"189":[86,124,197],"194":[86,124,197],"196":[86,124,197],"203":[86,124,197],"214":[86,124],"220":[86,124],"230":[86,124],"241":[86,124],"249":[86,124],"262":[86,124],"264":[86,124],"335":[86,124],"338":[86,124],"341":[86,124],"344":[86,124],"347":[86,124]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/useViewportSync.ts":{"30":[86,124,197],"47":[86,124,197],"53":[86,124,197],"72":[86,124,197]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/useWorkflowDiff.ts":{"37":[86,124,197],"38":[86,124,197],"48":[86,124,197],"49":[86,124,197],"53":[86,124,197],"58":[86,124,197],"77":[86,124,197],"89":[86,124,197],"100":[86,124,197],"106":[86,124,197],"123":[86,124,197],"136":[86,124,197],"152":[86,124,197],"168":[86,124,197],"173":[86,124,197],"183":[86,124,197],"217":[86,124],"226":[86,124,197],"248":[86,124,197],"276":[86,124,197]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/useWorkflowDiffUI.ts":{"25":[86,124,197],"40":[86,124,197],"45":[86,124],"50":[86,124],"75":[86,124],"78":[86,124],"94":[86,124,197],"97":[86,124,197],"98":[86,124,197],"105":[86,124],"106":[86,124],"116":[86,124],"117":[86,124],"130":[86,124,197],"157":[86,124],"167":[86,124,197],"175":[86,124],"176":[86,124],"182":[86,124,197],"189":[86,124],"192":[86,124],"196":[86,124],"211":[86,124],"221":[86,124,197],"225":[86,124,197],"248":[86,124]},"packages/@n8n/backend-network/src/http/binary-string.ts":{"12":[8,154,91,26,41,72]},"packages/workflow/src/redaction-channels.ts":{"23":[8,154,91,41,47,72],"37":[8,154,91,41,47,72],"52":[8,154,91,41,47,72],"77":[8,154,91,41,47,72]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/sendConsoleMessage.ts":{"7":[8,154,91,41,47,72]},"packages/frontend/editor-ui/src/app/utils/rbac/checks/isEnterpriseFeatureEnabled.ts":{"4":[86,124,72],"15":[86,124,72],"17":[86,124]},"packages/frontend/editor-ui/src/app/utils/rbac/middleware/enterprise.ts":{"6":[86,124,72]},"packages/frontend/editor-ui/src/features/execution/executions/composables/useExecutionDebugging.ts":{"41":[72],"45":[72],"86":[72],"87":[72],"94":[72],"104":[72],"121":[72],"140":[72],"146":[72],"156":[72],"160":[72],"204":[72]},"packages/@n8n/db/src/utils/escape-like.ts":{"5":[45,213,142]},"packages/cli/src/services/workflow-loader.service.ts":{"7":[45,213,142],"9":[45,213,142]},"packages/core/src/execution-engine/node-execution-context/local-load-options-context.ts":{"16":[45,213,142],"23":[45,213,142],"42":[45,213,142],"69":[45,213,142]},"packages/core/src/execution-engine/node-execution-context/workflow-node-context.ts":{"16":[45,213,142],"22":[45,213,142]},"packages/workflow/src/node-parameters/path-utils.ts":{"10":[45,213,142]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/execute-sub-workflow.svg":{"11":[168,212,213,142]},"packages/frontend/editor-ui/src/app/composables/usePushConnection/handlers/workflowActivated.ts":{"12":[172,69,213,142,79,80]},"packages/frontend/editor-ui/src/app/composables/workflowPublicationConfirmation.ts":{"43":[86,124,172,69,79,80],"46":[86,124],"59":[86,124,172,69,213,142,79,80],"77":[86,124,172,69,79,80]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ResourceMapper/ResourceMapper.vue":{"55":[86,124,78,141,213,142],"99":[86,124,141],"119":[86,124,78,141,213,142],"121":[86,124,141],"146":[86,124],"150":[86,124,141],"171":[86,124,78,141,213,142],"173":[86,124,141],"185":[86,124,78,141,213,142],"221":[86,124,141],"262":[86,124,141],"266":[86,124,78,141,213,142],"273":[86,124,78,141,213,142],"277":[86,124,78,141,213,142],"281":[86,124,78,141,213,142],"285":[86,124,78,141,213,142],"293":[86,124,78,141,213,142],"303":[86,124,141],"313":[86,124,141],"320":[86,124],"329":[86,124,78,141,213,142],"332":[86,124,141],"340":[86,124,213,142],"347":[86,124,78,141,213,142],"375":[86,124,78,141,213,142],"400":[86,124,78,141,213,142],"423":[86,124,78,141,213,142],"433":[86,124,141],"434":[86,124,141],"457":[86,124],"467":[86,124,78,141,213,142],"470":[86,124,141],"490":[86,124,78,141,213,142],"503":[86,124,78,141,213,142],"509":[86,124,141],"520":[86,124,141],"540":[86,124,141],"546":[86,124,141],"554":[86,124,141],"555":[86,124,141],"572":[86,124,141],"580":[86,124],"588":[86,124],"603":[86,124],"605":[86,124],"619":[86,124,78,141,213,142],"631":[86,124,78,141,213,142],"637":[86,124,141],"648":[86,124,78,141,213,142],"681":[86,124,141],"684":[86,124,213,142],"711":[86,124],"717":[86,124,213,142],"722":[86,124],"728":[86,124],"729":[86,124]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/WorkflowSelectorParameterInput/WorkflowSelectorParameterInput.vue":{"60":[86,124,213,142],"111":[86,124,213,142],"122":[86,124,213,142],"132":[86,124,213,142],"146":[86,124,213,142],"154":[86,124,213,142],"162":[86,124,213,142],"170":[86,124,213,142],"177":[86,124,213,142],"195":[86,124,142],"205":[86,124,142],"210":[86,124,142],"214":[86,124],"218":[86,124,142],"221":[86,124],"227":[86,124],"231":[86,124,213,142],"252":[86,124,213,142],"259":[86,124,213,142],"263":[86,124,213,142],"264":[86,124,142],"273":[86,124,213,142],"274":[86,124,213,142],"286":[86,124,213,142],"293":[86,124,142],"298":[86,124,142],"331":[86,124,213,142],"358":[86,124],"363":[86,124],"366":[86,124],"370":[86,124,142],"375":[86,124],"378":[86,124,213,142],"396":[86,124,213,142],"398":[86,124,213,142],"404":[86,124,213,142],"421":[86,124,213,142],"438":[86,124],"457":[86,124,213,142],"480":[86,124],"481":[86,124,213,142]},"packages/frontend/editor-ui/src/features/ndv/parameters/composables/useResourceLocatorDropdown.ts":{"8":[86,124,213,142],"15":[86,124,142],"23":[86,124,142],"27":[86,124,142]},"packages/frontend/editor-ui/src/features/ndv/parameters/composables/useResourceLocatorModes.ts":{"15":[86,124,213,142],"21":[86,124,213,142],"34":[86,124,213,142],"35":[86,124,213,142],"37":[86,124,142],"51":[86,124,213,142]},"packages/frontend/editor-ui/src/features/ndv/parameters/composables/useWorkflowResourcesLocator.ts":{"13":[86,124,213,142],"17":[86,124,142],"29":[86,124,213,142],"31":[86,124,213,142],"40":[86,124,213,142],"48":[86,124,142],"56":[86,124,213,142],"61":[86,124,213,142],"71":[86,124,213,142],"107":[86,124,213,142],"113":[86,124,142],"118":[86,124,142]},"packages/frontend/editor-ui/src/features/workflows/components/WorkflowExtractionNameModal.vue":{"21":[86,124,213],"31":[86,124,213],"37":[86,124,213],"57":[86,124,213],"59":[86,124,213],"64":[86,124,213],"79":[86,124,213],"90":[86,124,213]},"packages/cli/src/services/heap-diagnostics.service.ts":{"18":[107],"23":[107],"40":[107],"64":[107]},"packages/cli/src/services/process-internals.service.ts":{"19":[107],"24":[107],"27":[107]},"packages/@n8n/instance-ai/src/parsers/docx-parser.ts":{"17":[29]},"packages/@n8n/instance-ai/src/parsers/html-parser.ts":{"35":[29]},"packages/@n8n/instance-ai/src/parsers/ooxml-guard.ts":{"24":[29],"35":[29],"76":[29]},"packages/@n8n/instance-ai/src/parsers/pdf-parser.ts":{"19":[29]},"packages/@n8n/instance-ai/src/parsers/structured-file-parser.ts":{"18":[29],"31":[29],"35":[29],"66":[29],"150":[29],"155":[29],"177":[29],"179":[29],"216":[29],"217":[29],"220":[29],"221":[29],"225":[29],"229":[29],"232":[29],"240":[29],"261":[29],"268":[29],"299":[29],"313":[29],"366":[29],"412":[29],"416":[29],"425":[29],"452":[29],"455":[29],"460":[29],"527":[29],"528":[29],"553":[29],"583":[29],"593":[29]},"packages/@n8n/instance-ai/src/parsers/validate-attachments.ts":{"31":[29],"39":[29],"43":[29],"68":[29],"69":[29],"81":[29],"83":[29],"84":[29],"121":[29],"133":[29],"151":[29],"161":[29],"184":[29],"185":[29],"188":[29],"189":[29]},"packages/@n8n/instance-ai/src/parsers/xlsx-parser.ts":{"18":[29]},"packages/@n8n/instance-ai/src/tools/attachments/parse-file.tool.ts":{"62":[29],"111":[29],"112":[29],"115":[29],"119":[29],"129":[29],"138":[29],"156":[29],"171":[29]},"localhost-44855/assets/index-BoK1c_f3.js":{"3":[29,92,126,160,161,162]},"localhost-44855/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[29,92,126,160,161,162],"9":[29,92,126,160,161,162],"10":[29,92,126,160,161,162],"19":[29,92,126,160,161,162],"23":[29,92,126,160,161,162],"29":[29,92,126,160,161,162],"33":[29,92,126,160,161,162],"34":[29,92,126,160,161,162]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/AttachmentPreview.vue":{"10":[29,31,160],"25":[29,31,160],"30":[29,31,160],"33":[29,160],"36":[29,160],"40":[29,160],"41":[160],"42":[29,160],"44":[29,160],"51":[160],"59":[29,160],"77":[29,160],"82":[29,31,160]},"packages/@n8n/instance-ai/src/tools/orchestration/agent-persistence.ts":{"3":[161]},"packages/frontend/editor-ui/src/experiments/openWorkflowInAssistant/launchWorkflowThread.ts":{"24":[86,124,162,36]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/InstanceAiResourceChip.vue":{"10":[31,162],"30":[31,162]},"packages/cli/src/modules/type-availability-policies/available-types.controller.ts":{"18":[66],"40":[66],"48":[66]},"packages/cli/src/modules/type-availability-policies/type-availability-policy-project.controller.ts":{"22":[66],"27":[66],"41":[66]},"packages/workflow/src/credential-only-nodes.ts":{"14":[66],"18":[66],"23":[66]},"localhost-40907/assets/index-BoK1c_f3.js":{"3":[66]},"localhost-40907/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[66],"9":[66],"10":[66],"19":[66],"23":[66],"29":[66],"33":[66],"34":[66]},"localhost-40907/assets/verified-Pt0guxqN.js":{"8":[66]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/envelope--outline-16.svg":{"9":[86,124,66]},"packages/modules/type-availability-policies/frontend/src/components/RestrictedNodePanel.vue":{"20":[86,124,66],"26":[86,124,66],"29":[86,124,66],"35":[86,124,66],"37":[86,124,66],"44":[86,124],"45":[86,124,66],"54":[86,124],"55":[86,124,66]},"packages/modules/type-availability-policies/frontend/src/components/RestrictedNodePopover.vue":{"47":[86,124,66],"51":[86,124,66],"55":[86,124],"60":[86,124,66],"63":[86,124,66],"66":[86,124,66],"77":[86,124],"78":[86,124],"82":[86,124],"85":[86,124,66],"102":[86,124,66],"112":[86,124],"118":[86,124],"120":[86,124],"121":[86,124],"123":[86,124],"131":[86,124]},"packages/modules/type-availability-policies/frontend/src/composables/useExclusiveOpen.ts":{"5":[86,124,66],"8":[86,124,66],"13":[86,124,66],"22":[86,124,66]},"packages/modules/type-availability-policies/frontend/src/type-availability-policies.api.ts":{"5":[86,124,66],"12":[86,124,66]},"localhost-34799/assets/index-BoK1c_f3.js":{"3":[75,207,79]},"localhost-34799/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[75,207,79],"9":[75,207,79],"10":[75,207,79],"19":[75,207,79],"23":[75,207,79],"29":[75,207,79],"33":[75,207,79],"34":[75,207,79]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ExpressionEditorModal/ExpressionEditorModalInput.vue":{"29":[86,124,75],"42":[86,124,75],"52":[86,124,75],"60":[86,124,75],"66":[86,124,75],"69":[86,124,75],"70":[86,124,75],"76":[86,124,75],"83":[86,124,75],"89":[86,124,75],"94":[86,124,75],"97":[86,124,75]},"packages/frontend/editor-ui/src/app/components/CharacterCount.vue":{"11":[86,124,172,69,79,80],"12":[86,124,172,69,79,80],"20":[86,124,172,69,79,80]},"packages/frontend/editor-ui/src/app/components/WorkflowVersionForm.vue":{"18":[86,124,172,69,79,80],"28":[86,124,172,69,79,80],"32":[86,124],"39":[86,124,172,69,79,80],"48":[86,124,172,69,79,80],"68":[86,124,172,69,79,80]},"packages/frontend/editor-ui/src/features/workflows/components/ActivationModal.vue":{"22":[86,124,172,69,79,80],"31":[86,124,172,69,79,80],"33":[86,124,172,69,79,80],"71":[86,124],"81":[86,124],"85":[86,124],"90":[86,124],"94":[86,124,69],"98":[86,124,172,69,79,80],"103":[86,124,172,69,79,80],"105":[86,124,172,69,79,80],"110":[86,124,172,69,79,80],"122":[86,124,172,69,79,80],"125":[86,124,172,69,79,80]},"packages/frontend/editor-ui/src/features/workflows/components/WorkflowPublishModal.vue":{"31":[86,124,172,69,79,80],"46":[86,124,172,69,79,80],"50":[86,124,172,69,79,80],"54":[86,124,172,69,79,80],"60":[86,124,172,69,79,80],"68":[86,124],"70":[86,124,172,69,79,80],"72":[86,124,172,69,79,80],"81":[86,124,172,69,79,80],"87":[86,124,172,69,79,80],"109":[86,124,172,69,79,80],"113":[86,124,172,69,79,80],"131":[86,124,172,69,79,80],"135":[86,124,172,69,79,80],"138":[86,124,172],"144":[86,124],"145":[86,124],"160":[86,124,172,69,79,80],"173":[86,124],"203":[86,124,172,69,79,80],"230":[86,124,172,69,79,80],"264":[86,124,172,69,79,80],"278":[86,124,172,69,79,80],"279":[86,124,172,69,79,80],"281":[86,124,172,69,79,80],"288":[86,124],"296":[86,124],"304":[86,124],"308":[86,124],"309":[86,124],"318":[86,124],"325":[86,124],"343":[86,124]},"packages/frontend/editor-ui/src/features/workflows/workflowHistory/utils.ts":{"9":[86,124,203],"12":[86,124],"15":[86,124,172,69,79,80],"19":[86,124,203],"37":[86,124,203],"69":[86,124,203],"74":[86,124,203],"114":[86,124,203]},"packages/@n8n/api-types/src/dto/data-table/list-data-table-content-query.dto.ts":{"15":[86,124,24,25],"42":[86,124,24,25]},"packages/cli/src/modules/data-table/data-table-column.repository.ts":{"23":[24,25],"34":[24,25],"36":[24,25],"47":[24,25],"66":[24,25],"76":[24,25],"80":[24,25],"86":[24,25],"98":[24,25],"108":[24,25],"115":[24,25],"143":[24,25],"145":[24,25],"163":[24,25],"172":[24,25],"179":[24,25],"187":[24,25],"196":[24,25],"220":[24,25],"227":[24,25],"246":[24,25],"253":[24,25],"273":[24,25],"275":[24,25],"280":[24,25]},"packages/cli/src/modules/data-table/data-table-ddl.service.ts":{"23":[24,25],"25":[24,25],"31":[24,25],"45":[24,25],"47":[24,25],"55":[24,25],"67":[24,25],"74":[24,25],"76":[24,25],"84":[24,25],"91":[24,25],"96":[24,25],"103":[24,25],"108":[24,25],"116":[24,25]},"packages/cli/src/modules/data-table/data-table-rows.repository.ts":{"56":[24,25],"147":[24,25],"149":[24,25],"156":[24,25],"177":[24,25],"218":[24,25],"226":[24,25],"232":[24,25],"233":[24,25],"272":[24,25],"284":[24,25],"305":[24,25],"314":[24,25],"319":[24,25],"320":[24,25],"354":[24,25],"359":[24,25],"378":[24,25],"384":[24,25],"421":[24,25],"430":[24,25],"462":[24,25],"468":[24,25],"469":[24,25],"490":[24,25],"492":[24,25],"499":[24,25],"507":[24,25],"522":[24,25],"536":[24,25],"557":[24,25],"569":[24,25],"587":[24,25],"596":[24,25],"597":[24,25],"616":[24,25],"641":[24,25],"652":[24,25],"678":[24,25],"687":[24,25],"706":[24,25],"721":[24,25],"729":[24,25]},"packages/cli/src/modules/data-table/data-table.controller.ts":{"54":[24,25],"60":[24,25],"80":[24,25],"89":[24,25],"106":[24,25],"134":[24,25],"148":[24,25],"172":[24,25],"193":[24,25],"213":[24,25],"229":[24,25],"245":[24,25],"267":[24,25],"289":[24,25],"314":[24,25],"355":[24,25],"384":[24,25],"414":[24,25],"445":[24,25],"476":[24,25]},"localhost-33511/assets/index-BoK1c_f3.js":{"3":[25,175,134]},"localhost-33511/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[25,175,134],"9":[25,175,134],"10":[25,175,134],"19":[25,175,134],"23":[25,175,134],"29":[25,175,134],"33":[25,175,134],"34":[25,175,134]},"packages/frontend/@n8n/design-system/src/components/N8nSelectedItemsInfo/SelectedItemsInfo.vue":{"11":[86,124,24,25],"20":[86,124,24],"27":[86,124,24],"31":[86,124,24],"33":[86,124,24,25]},"packages/frontend/editor-ui/src/features/core/dataTable/DataTableDetailsView.vue":{"49":[24,25],"51":[24,25],"69":[24,25],"88":[24],"96":[24],"103":[24],"111":[24],"143":[24,25],"150":[24,25],"157":[25],"200":[24,25],"203":[24,25],"207":[24,25],"218":[24,25]},"packages/frontend/editor-ui/src/features/core/dataTable/DataTableView.vue":{"64":[24,25],"65":[24,25],"73":[24,25],"82":[24,25],"84":[24,25],"110":[24,25],"130":[24,25],"135":[24,25],"171":[24,25],"176":[24,25],"180":[24,25],"181":[24,25],"216":[24,25],"226":[24,25]},"packages/frontend/editor-ui/src/features/core/dataTable/components/AddDataTableModal.vue":{"120":[24,25],"140":[24,25],"141":[24,25],"149":[24,25],"188":[24,25],"267":[24,25],"334":[24,25],"339":[24,25],"345":[24,25],"357":[24,25],"358":[24,25],"361":[24,25]},"packages/frontend/editor-ui/src/features/core/dataTable/components/DataTableActions.vue":{"54":[24,25],"55":[24,25],"57":[24,25],"92":[25],"154":[25]},"packages/frontend/editor-ui/src/features/core/dataTable/components/DataTableBreadcrumbs.vue":{"16":[24,25],"38":[24,25],"42":[24,25],"46":[24,25],"81":[24],"103":[24,25],"109":[24,25],"119":[24,25],"122":[24,25]},"packages/frontend/editor-ui/src/features/core/dataTable/components/DataTableCard.vue":{"34":[24,25],"44":[24,25],"49":[24,25],"50":[24,25],"55":[24,25],"64":[24,25],"67":[24,25],"74":[24,25],"81":[24,25],"93":[24,25],"105":[24,25],"114":[24,25],"120":[24,25]},"packages/frontend/editor-ui/src/features/core/dataTable/components/DownloadDataTableModal.vue":{"25":[24,25]},"packages/frontend/editor-ui/src/features/core/dataTable/components/ImportCsvModal.vue":{"22":[24,25],"158":[24,25],"171":[24,25],"174":[24,25]},"packages/frontend/editor-ui/src/features/core/dataTable/components/dataGrid/AddColumnButton.vue":{"31":[24,25],"48":[24,25],"74":[24,25],"76":[24],"79":[24],"85":[24],"122":[24],"131":[24],"137":[24],"150":[24,25],"162":[24,25],"168":[24,25],"182":[24],"192":[24],"225":[24],"229":[24],"230":[24],"251":[24]},"packages/frontend/editor-ui/src/features/core/dataTable/components/dataGrid/AddRowButton.vue":{"6":[24,25],"15":[24,25],"16":[24,25]},"packages/frontend/editor-ui/src/features/core/dataTable/components/dataGrid/DataTableLoadingIndicator.vue":{"8":[24,25],"15":[24,25]},"packages/frontend/editor-ui/src/features/core/dataTable/components/dataGrid/DataTableTable.vue":{"54":[24,25],"57":[24,25],"75":[24,25],"96":[24,25],"114":[24],"123":[24,25],"124":[24],"127":[24],"135":[24],"139":[24],"143":[24],"147":[24,25],"170":[24,25],"191":[24],"196":[24,25],"197":[24],"229":[24,25]},"packages/frontend/editor-ui/src/features/core/dataTable/components/dataGrid/registerAgGridModulesOnce.ts":{"27":[24,25]},"packages/frontend/editor-ui/src/features/core/dataTable/composables/useAgGrid.ts":{"23":[24,25],"34":[24,25],"86":[24,25],"98":[24,25],"118":[24],"124":[24],"133":[24],"135":[24],"145":[24],"153":[24],"173":[24],"212":[24,25],"231":[24,25]},"packages/frontend/editor-ui/src/features/core/dataTable/composables/useDataTableColumnFilters.ts":{"19":[24,25]},"packages/frontend/editor-ui/src/features/core/dataTable/composables/useDataTableColumns.ts":{"40":[24,25],"59":[24,25],"66":[24],"77":[24],"97":[24],"123":[24,25],"132":[24,25],"159":[24,25],"161":[24,25],"165":[24,25],"208":[24,25],"214":[24,25],"218":[24],"219":[24],"226":[24],"234":[24],"242":[24],"244":[24],"245":[24]},"packages/frontend/editor-ui/src/features/core/dataTable/composables/useDataTableOperations.ts":{"59":[24,25],"116":[24],"118":[24],"136":[24],"139":[24],"209":[24],"234":[24],"245":[24],"261":[24],"284":[24],"337":[24,25],"363":[24],"399":[24]},"packages/frontend/editor-ui/src/features/core/dataTable/composables/useDataTablePagination.ts":{"11":[24,25],"17":[24,25],"21":[24],"32":[24]},"packages/frontend/editor-ui/src/features/core/dataTable/composables/useDataTableSelection.ts":{"5":[24,25],"13":[24,25],"15":[24,25],"21":[24],"22":[24,25],"27":[24],"31":[24],"40":[24,25]},"packages/frontend/editor-ui/src/features/core/dataTable/composables/useDataTableTypes.ts":{"8":[24,25],"9":[24,25],"18":[24,25],"25":[24,25]},"packages/frontend/editor-ui/src/features/core/dataTable/modals.ts":{"12":[86,124,24,25]},"packages/frontend/editor-ui/src/features/core/dataTable/module.descriptor.ts":{"15":[86,124,24,25],"16":[86,124,24,25],"17":[86,124,24,25],"34":[86,124,25],"38":[86,124,25],"39":[86,124,25],"45":[86,124]},"packages/frontend/editor-ui/src/features/core/dataTable/typeGuards.ts":{"11":[24],"21":[24,25]},"packages/frontend/editor-ui/src/features/core/dataTable/utils/columnUtils.ts":{"26":[24],"29":[24],"35":[24,25],"36":[24,25],"51":[24,25],"52":[24,25],"65":[24,25],"66":[24,25],"94":[24,25],"95":[24],"119":[24],"126":[24,25],"135":[24],"141":[24],"149":[24,25],"156":[24,25],"163":[24,25],"170":[24,25],"177":[24],"184":[24,25],"191":[24,25],"198":[24,25],"205":[24,25],"212":[24,25],"219":[24,25],"229":[24,25],"241":[24],"253":[24]},"packages/@n8n/imap/src/connection-options.ts":{"34":[82]},"packages/@n8n/imap/src/errors.ts":{"2":[82],"8":[82],"14":[82]},"packages/@n8n/imap/src/headers.ts":{"3":[82],"7":[82],"9":[82]},"packages/@n8n/imap/src/imap-simple.ts":{"68":[82],"72":[82],"76":[82],"77":[82],"103":[82],"107":[82],"157":[82],"166":[82],"178":[82],"184":[82],"190":[82],"195":[82],"201":[82],"207":[82],"216":[82],"218":[82],"221":[82],"226":[82],"229":[82],"233":[82],"237":[82],"244":[82],"257":[82],"262":[82],"263":[82],"278":[82],"283":[82],"286":[82],"289":[82],"304":[82],"321":[82],"325":[82],"334":[82],"363":[82],"373":[82],"387":[82],"392":[82],"396":[82],"405":[82],"406":[82],"407":[82],"414":[82],"425":[82],"444":[82],"457":[82],"484":[82],"499":[82],"513":[82],"528":[82],"554":[82],"564":[82],"569":[82],"576":[82],"585":[82],"586":[82],"588":[82],"593":[82],"594":[82]},"packages/@n8n/imap/src/message.ts":{"4":[82],"6":[82],"24":[82],"25":[82],"34":[82],"38":[82],"40":[82],"45":[82],"47":[82]},"packages/cli/src/controllers/oauth/oauth1-credential.controller.ts":{"13":[82],"22":[82],"37":[82]},"packages/cli/src/oauth/oauth-browser-binding.service.ts":{"16":[124,109,78,82],"19":[124,109,78,82],"31":[124,109,78,82],"48":[124,109,78,82],"58":[124,109,78,82],"72":[124,109,78,82]},"packages/cli/src/oauth/oauth.service.ts":{"109":[124,109,78,82],"119":[124,109,78,82],"123":[124,109,78,82],"130":[124,109,78,82],"140":[124,109,78,82],"176":[124,109,78,82],"180":[124,109,78,82],"184":[124,109,78,82],"193":[124,109,78,82],"221":[124,109,78,82],"225":[124,109,78,82],"234":[124,109,78,82],"248":[124,109,78,82],"287":[124,109,78,82],"292":[124,109,78,82],"329":[124,109,78,82],"357":[124,109,78,82],"364":[124,109,78,82],"374":[124,109,78,82],"381":[124,109,78,82],"396":[124,109,78,82],"411":[124,109,78,82],"437":[124,109,78,82],"453":[124,109,78,82],"472":[124,109,78,82],"481":[124,109,78,82],"489":[124,109,78,82],"497":[124,109,78,82],"591":[124,109,78,82],"604":[124,109,78,82],"643":[124,109,78,82],"658":[124,109,78,82],"674":[124,109,78,82],"705":[124,109,78,82],"706":[124,109,78,82],"709":[124,109,78,82],"719":[124,109,78,82],"728":[124,109,78,82],"743":[124,109,78,82],"762":[124,109,78,82],"768":[124,109,78,82],"777":[124,109,78,82],"788":[124,109,78,82],"803":[124,109,78,82],"812":[124,109,78,82],"830":[124,109,78,82],"903":[124,109,78,82],"917":[124,109,78,82],"920":[124,109,78,82],"927":[124,109,78,82],"1006":[124,109,78,82],"1017":[124,109,78,82],"1106":[124,109,78,82],"1167":[124,109,78,82],"1219":[124,109,78,82],"1237":[124,109,78,82],"1256":[124,109,78,82],"1282":[124,109,78,82],"1355":[124,109,78,82],"1367":[124,109,78,82],"1411":[124,109,78,82],"1439":[124,109,78,82],"1452":[124,109,78,82],"1470":[124,109,78,82],"1515":[124,109,78,82],"1534":[124,109,78,82],"1590":[124,109,78,82],"1601":[124,109,78,82],"1627":[124,109,78,82]},"packages/cli/src/oauth/validate-oauth-url.ts":{"12":[124,109,78,82]},"packages/nodes-base/nodes/EmailReadImap/EmailReadImap.node.ts":{"8":[82]},"packages/nodes-base/nodes/EmailReadImap/connection-events.ts":{"6":[82],"7":[82]},"packages/nodes-base/nodes/EmailReadImap/credentials.ts":{"6":[82]},"packages/nodes-base/nodes/EmailReadImap/search-criteria.ts":{"27":[82],"28":[82],"29":[82],"30":[82],"31":[82],"32":[82],"33":[82],"37":[82],"38":[82],"39":[82],"40":[82],"41":[82],"42":[82],"46":[82],"47":[82],"51":[82],"52":[82],"57":[82],"67":[82],"75":[82],"92":[82],"106":[82],"107":[82],"108":[82],"112":[82],"115":[82],"228":[82],"242":[82],"248":[82],"249":[82],"251":[82],"252":[82],"257":[82],"268":[82],"271":[82],"277":[82],"284":[82]},"packages/nodes-base/nodes/EmailReadImap/v1/EmailReadImapV1.node.ts":{"31":[82],"63":[82],"68":[82],"74":[82],"86":[82],"106":[82],"112":[82],"121":[82],"130":[82],"302":[82],"311":[82],"339":[82],"353":[82],"385":[82],"410":[82],"458":[82],"462":[82],"468":[82],"471":[82],"475":[82]},"packages/nodes-base/nodes/EmailReadImap/v2/EmailReadImapV2.node.ts":{"193":[82],"202":[82],"234":[82],"276":[82],"319":[82],"343":[82],"347":[82],"351":[82],"357":[82],"362":[82],"366":[82]},"packages/nodes-base/nodes/EmailReadImap/v2/utils.ts":{"30":[82],"68":[82],"95":[82],"137":[82],"142":[82],"148":[82],"163":[82],"189":[82],"195":[82],"204":[82],"214":[82]},"packages/nodes-base/nodes/NextCloud/GenericFunctions.ts":{"14":[82]},"packages/nodes-base/nodes/NextCloud/NextCloud.node.ts":{"872":[82],"1103":[82],"1190":[82],"1198":[82],"1284":[82],"1292":[82],"1326":[82],"1334":[82],"1364":[82],"1372":[82],"1392":[82],"1397":[82],"1405":[82]},"packages/nodes-base/nodes/Shopify/GenericFunctions.ts":{"12":[82],"85":[82],"124":[82]},"packages/nodes-base/nodes/Shopify/ShopifyTrigger.node.ts":{"335":[82],"350":[82],"373":[82],"389":[82]},"packages/nodes-base/nodes/Twitter/Twitter.node.ts":{"8":[82]},"packages/nodes-base/nodes/Twitter/V1/GenericFunctions.ts":{"14":[82],"46":[82],"69":[82],"81":[82]},"packages/nodes-base/nodes/Twitter/V1/TwitterV1.node.ts":{"27":[82],"76":[82],"92":[82],"123":[82],"164":[82],"171":[82]},"packages/nodes-base/nodes/Twitter/V2/GenericFunctions.ts":{"13":[82],"60":[82],"83":[82],"105":[82]},"packages/nodes-base/nodes/Twitter/V2/TwitterV2.node.ts":{"31":[82],"100":[82],"116":[82]},"localhost-41341/assets/index-BoK1c_f3.js":{"3":[33]},"localhost-41341/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[33],"9":[33],"10":[33],"19":[33],"23":[33],"29":[33],"33":[33],"34":[33]},"localhost-45737/assets/index-BoK1c_f3.js":{"3":[33]},"localhost-45737/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[33],"9":[33],"10":[33],"19":[33],"23":[33],"29":[33],"33":[33],"34":[33]},"packages/frontend/@n8n/design-system/src/components/N8nDialog/DialogFooter.vue":{"6":[86,124,33,47,63]},"packages/frontend/@n8n/design-system/src/components/N8nRadioGroup/RadioGroup.vue":{"11":[86,124,33],"12":[86,124,33],"13":[86,124,33],"37":[86,124],"43":[86,124],"45":[86,124,33],"55":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nRadioGroup/RadioGroupItem.vue":{"15":[86,124,33],"19":[86,124,33],"22":[86,124,33],"25":[86,124],"31":[86,124,33],"43":[86,124,33],"51":[86,124],"53":[86,124]},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useInstanceAiConfiguration.ts":{"11":[16,33],"21":[16,33],"23":[16,33],"24":[33],"25":[16,33],"26":[33],"27":[16,33]},"packages/frontend/editor-ui/src/features/ai/instanceAi/composables/useInstanceCredentialTest.ts":{"13":[16,33]},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAiConfiguration.ts":{"17":[86,16,124,33],"23":[86,124],"26":[86,124,33]},"packages/frontend/editor-ui/src/features/ai/instanceAi/instanceAiSetup.telemetry.ts":{"24":[33],"74":[16,33],"75":[16,33]},"packages/frontend/editor-ui/src/features/ai/instanceAi/onboarding/InstanceAiOnboardingIntro.vue":{"31":[16,33],"41":[16,33],"46":[33],"65":[33],"93":[33]},"packages/frontend/editor-ui/src/features/ai/instanceAi/onboarding/InstanceAiOnboardingView.vue":{"23":[16,33],"33":[16,33],"34":[16,33],"35":[33],"43":[16,33],"44":[16,33],"57":[16,33],"64":[16,33],"74":[33],"78":[16,33],"81":[16,33],"82":[33],"99":[33],"136":[16,33],"142":[16,33]},"packages/frontend/editor-ui/src/features/ai/instanceAi/onboarding/InstanceAiOnboardingWizard.vue":{"53":[16,33],"129":[33],"130":[33],"191":[33],"199":[33],"216":[33],"246":[33],"255":[33],"259":[33],"260":[33],"269":[16,33],"272":[33],"278":[33],"281":[33],"396":[33],"415":[33],"428":[16,33],"430":[16,33],"453":[33],"488":[33],"494":[33],"521":[33],"522":[33],"559":[33],"611":[33],"642":[33],"681":[33],"706":[33],"711":[33],"712":[33],"732":[16,33],"1102":[33],"1138":[33],"1150":[33],"1165":[33],"1170":[33],"1199":[33],"1201":[33],"1213":[33],"1236":[33],"1266":[33],"1272":[33],"1286":[33],"1291":[33],"1297":[33],"1302":[33],"1328":[33],"1354":[33]},"packages/frontend/editor-ui/src/features/ai/instanceAi/onboarding/useInstanceAiOnboarding.ts":{"12":[16,33],"17":[16,33],"24":[33],"33":[33],"39":[33],"44":[33]},"packages/frontend/editor-ui/src/app/utils/formatters/textFormatter.ts":{"8":[175]},"localhost-37735/assets/index-BoK1c_f3.js":{"3":[48]},"localhost-37735/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[48],"9":[48],"10":[48],"19":[48],"23":[48],"29":[48],"33":[48],"34":[48]},"packages/frontend/@n8n/rest-api-client/src/api/templates.ts":{"131":[86,124,100],"135":[86,124,100],"139":[86,124,100],"146":[86,124,100],"159":[86,124,100],"190":[86,124,82],"198":[86,124,82,100],"206":[86,124,48,82,100]},"packages/frontend/editor-ui/src/app/utils/formatters/listFormatter.ts":{"15":[86,124,48,82]},"packages/frontend/editor-ui/src/features/workflows/templates/components/AppsRequiringCredsNotice.vue":{"10":[86,124,48,82],"17":[86,124,48,82],"24":[86,124,48,82],"27":[86,124,48,82],"33":[86,124,48,82],"37":[86,124,48,82],"38":[86,124,48,82]},"packages/frontend/editor-ui/src/features/workflows/templates/components/IconSuccess.vue":{"2":[86,124,48,82]},"packages/frontend/editor-ui/src/features/workflows/templates/components/SetupTemplateFormStep.vue":{"18":[86,124,48,82],"42":[86,124,48,82],"44":[86,124,48,82],"48":[86,124,48,82],"52":[86,124,48,82],"53":[86,124,48,82],"60":[86,124,48,82],"71":[86,124,82],"77":[86,124,48,82],"85":[86,124,48,82],"98":[86,124,48,82]},"packages/frontend/editor-ui/src/features/workflows/templates/components/SetupWorkflowCredentialsModal.vue":{"13":[86,124,48],"29":[86,124,48],"46":[86,124,48],"52":[86,124,82],"61":[86,124,48],"65":[86,124,48,82],"67":[86,124,48,82],"71":[86,124,48,82],"83":[86,124,48],"90":[86,124,82],"91":[86,124],"98":[86,124,48,82],"105":[86,124,82]},"packages/frontend/editor-ui/src/features/workflows/templates/composables/useCredentialSetupState.ts":{"29":[86,124,48,82],"34":[86,124,48,82],"38":[86,124,48,82],"43":[86,124,48,82],"77":[86,124,48,82],"103":[86,124,48,82],"115":[86,124,48,82],"123":[86,124,48,82],"126":[86,124,48,82],"132":[86,124,48,82],"136":[86,124,48,82],"140":[86,124,48,82],"144":[86,124,82],"163":[86,124,48,82],"171":[86,124,82],"175":[86,124]},"packages/frontend/editor-ui/src/features/workflows/templates/composables/useSetupWorkflowCredentialsModalState.ts":{"9":[86,124,48],"15":[86,124,48],"34":[86,124,48,82],"40":[86,124],"52":[86,124,82],"66":[86,124],"89":[86,124],"97":[86,124]},"packages/frontend/editor-ui/src/features/workflows/templates/utils/templateTransforms.ts":{"38":[86,124,48,82],"47":[86,124,48,82],"55":[86,124,82],"73":[86,124,82],"99":[86,124,82],"122":[86,124,82],"127":[86,124,82],"150":[86,124],"165":[86,124],"168":[86,124]},"packages/@n8n/backend-network/src/http/retryability.ts":{"30":[49],"49":[49],"66":[49],"81":[49],"82":[49],"85":[49],"89":[49],"96":[49],"116":[49],"130":[49],"142":[49],"166":[49]},"packages/@n8n/scheduler/src/core/executor/backoff.ts":{"24":[49]},"packages/cli/src/workflows/triggers/poll-backoff-policy.ts":{"28":[49],"35":[49],"38":[49],"41":[49],"60":[49],"74":[49],"114":[49]},"packages/nodes-base/nodes/N8n/GenericFunctions.ts":{"21":[134],"56":[134],"93":[134],"94":[134],"107":[134],"111":[134],"146":[134],"150":[134],"186":[134],"210":[134]},"packages/nodes-base/nodes/N8n/WorkflowLocator.ts":{"18":[134],"32":[134],"37":[134],"42":[134]},"localhost-33511/assets/verified-Pt0guxqN.js":{"8":[134]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/n8n.svg":{"11":[168,134]},"localhost-34597/assets/index-BoK1c_f3.js":{"3":[82]},"localhost-34597/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[82],"9":[82],"10":[82],"19":[82],"23":[82],"29":[82],"33":[82],"34":[82]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/eyes--outline-16.svg":{"9":[86,124,45,82,100]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/email-trigger.svg":{"11":[82]},"packages/frontend/@n8n/design-system/src/components/N8nTags/Tags.vue":{"21":[86,124,81,82],"37":[86,124,81,82],"45":[86,124,81],"47":[86,124],"50":[86,124,81,82],"56":[86,124,81,82],"60":[86,124],"68":[86,124]},"packages/frontend/editor-ui/src/app/components/GoBackButton.vue":{"11":[82]},"packages/frontend/editor-ui/src/app/components/NodeList.vue":{"19":[82,100],"23":[100],"27":[82,100],"31":[82,100],"36":[82,100],"42":[82,100]},"packages/frontend/editor-ui/src/features/workflows/templates/components/TemplateCard.vue":{"12":[82,100],"37":[82],"41":[100],"43":[82,100],"65":[82,100],"71":[82,100],"75":[82,100]},"packages/frontend/editor-ui/src/features/workflows/templates/components/TemplateDetails.vue":{"21":[82],"32":[82],"34":[82],"49":[82],"59":[82],"62":[82],"79":[82],"86":[82],"89":[82]},"packages/frontend/editor-ui/src/features/workflows/templates/components/TemplateList.vue":{"38":[82,100],"47":[82,100],"71":[100],"74":[82],"83":[82,100],"90":[82,100],"97":[100],"98":[82]},"packages/frontend/editor-ui/src/features/workflows/templates/setupTemplate.store.ts":{"39":[82],"56":[82],"60":[82],"80":[82],"98":[82],"115":[82],"128":[82],"149":[82],"176":[82]},"packages/frontend/editor-ui/src/features/workflows/templates/utils/templateActions.ts":{"30":[82],"72":[82],"100":[100],"128":[82,100],"132":[82,100],"137":[82,100]},"packages/frontend/editor-ui/src/features/workflows/templates/views/SetupWorkflowFromTemplateView.vue":{"22":[82],"25":[82],"26":[82],"28":[82],"49":[82],"57":[82],"79":[82],"89":[82],"109":[82],"135":[82],"143":[82],"151":[82]},"packages/frontend/editor-ui/src/features/workflows/templates/views/TemplatesCollectionView.vue":{"32":[82],"37":[82],"39":[82],"44":[82],"45":[82],"48":[82],"49":[82],"64":[82],"87":[82],"88":[82],"98":[82],"117":[82],"121":[82],"124":[82]},"localhost-40517/assets/index-BoK1c_f3.js":{"3":"b:AEAAAAACAAAAAAAAAAAIAAAAiAAAJSSVAAEKAAA="},"localhost-40517/assets/rolldown-runtime-Bq5D3eIA.js":{"8":"b:AEAAAAACAAAAAAAAAAAIAAAAiAAAJSSVAAEKAAA=","9":"b:AEAAAAACAAAAAAAAAAAIAAAAiAAAJSSVAAEKAAA=","10":"b:AEAAAAACAAAAAAAAAAAIAAAAiAAAJSSVAAEKAAA=","19":"b:AEAAAAACAAAAAAAAAAAIAAAAiAAAJSSVAAEKAAA=","23":"b:AEAAAAACAAAAAAAAAAAIAAAAiAAAJSSVAAEKAAA=","29":"b:AEAAAAACAAAAAAAAAAAIAAAAiAAAJSSVAAEKAAA=","33":"b:AEAAAAACAAAAAAAAAAAIAAAAiAAAJSSVAAEKAAA=","34":"b:AEAAAAACAAAAAAAAAAAIAAAAiAAAJSSVAAEKAAA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/merge.svg":{"11":[14,96,136,139]},"packages/frontend/@n8n/design-system/src/components/N8nFormBox/FormBox.vue":{"30":[86,16,151,124,63],"37":[86,151,124,63],"38":[86,151,124,63],"39":[86,151,124,63],"40":[86,124],"41":[86,16,151,124,63],"47":[86,16,151,124,63],"62":[86,124],"77":[86,16,151,124,63]},"packages/frontend/@n8n/design-system/src/components/N8nFormInputs/FormInputs.vue":{"20":[86,16,151,124,63],"38":[86,16,151,124,63],"39":[86,16,151,124,63],"44":[86,151,124,63],"45":[86,151,124,63],"56":[86,16,151,124,63],"57":[86,16,151,124,63],"60":[86,16,151,124,63],"64":[86,16,151,124,63],"65":[86,124,63],"68":[86,124,63],"69":[86,124,63],"70":[86,124,63],"75":[86,151,124,63],"81":[86,16,151,124,63],"88":[86,124],"92":[86,124],"96":[86,124],"108":[86,124,63],"117":[86,151,124,63],"124":[86,151,124,63],"137":[86,16,151,124,63],"151":[86,151,124,63],"154":[86,16,151,124,63],"158":[86,16,151,124,63],"161":[86,16,151,124,63],"172":[86,124],"185":[86,151,124,63],"186":[86,16,151,124,63]},"packages/frontend/@n8n/design-system/src/components/ResizeObserver/ResizeObserver.vue":{"6":[86,16,151,124,63],"21":[86,16,151,124,63],"23":[86,16,151,124,63],"25":[86,16,151,124,63],"30":[86,16,151,124,63],"36":[86,151,124,63],"37":[86,151,124,63],"38":[86,151,124,63],"47":[86,151,124,63],"52":[86,16,151,124,63]},"packages/frontend/editor-ui/src/app/stores/sessionExpiry.store.ts":{"5":[86,16,151,124,63],"8":[86,124]},"packages/frontend/editor-ui/src/app/utils/handleSessionExpired.ts":{"12":[86,16,151,124,63]},"packages/frontend/editor-ui/src/app/utils/rbac/checks/isGuest.ts":{"4":[86,16,151,124,63]},"packages/frontend/editor-ui/src/app/utils/rbac/middleware/guest.ts":{"6":[86,16,151,124,63]},"packages/frontend/editor-ui/src/features/core/auth/views/AuthView.vue":{"28":[151,63],"32":[151,63]},"packages/frontend/editor-ui/src/features/core/auth/views/SigninView.vue":{"60":[16,151,63],"75":[16,151,63],"113":[151,63],"118":[16,151,63],"119":[16,151,63],"162":[63],"171":[151,63],"190":[151,63],"207":[151,63],"215":[151,63],"292":[63],"297":[63]},"packages/cli/src/modules/mcp/mcp-api-key.service.ts":{"24":[38],"30":[38],"52":[38],"67":[38],"104":[38],"113":[38],"126":[38],"142":[38],"143":[38]},"packages/cli/src/modules/mcp/mcp.errors.ts":{"13":[38],"30":[38]},"packages/cli/src/modules/mcp/tools/tool-error.utils.ts":{"8":[38],"12":[38],"26":[38]},"packages/cli/src/modules/mcp/tools/webhook-utils.ts":{"48":[38],"56":[38],"64":[38],"70":[38],"83":[38],"140":[38],"145":[38],"154":[38],"159":[38],"169":[38],"174":[38],"188":[38],"200":[38],"217":[38],"257":[38],"260":[38],"266":[38],"276":[38],"292":[38],"324":[38],"339":[38],"359":[38]},"packages/cli/src/modules/mcp/tools/workflow-inputs.ts":{"55":[38],"60":[38],"77":[38]},"packages/cli/src/modules/mcp/tools/workflow-validation.utils.ts":{"22":[38],"50":[38],"61":[38],"94":[38]},"packages/@n8n/api-types/src/schemas/credential-description.schema.ts":{"14":[86,87,124]},"packages/cli/src/public-api/v1/controllers/discover.public.controller.ts":{"26":[87]},"packages/cli/src/public-api/v1/handlers/discover/discover.service.ts":{"53":[87],"65":[87],"70":[87],"74":[87],"135":[87],"136":[87],"150":[87],"159":[87],"163":[87],"167":[87],"168":[87],"211":[87],"213":[87],"218":[87],"223":[87],"231":[87],"255":[87]},"packages/cli/src/public-api/v1/openapi-gen/decorator-routes.ts":{"51":[87],"76":[87],"89":[87],"95":[87],"124":[87],"153":[87],"161":[87],"186":[87],"203":[87],"227":[87],"253":[87],"329":[87],"334":[87]},"packages/cli/src/public-api/v1/openapi-gen/object-union-type.ts":{"13":[87],"15":[87],"28":[87],"35":[87]},"packages/cli/src/public-api/v1/openapi-gen/schema-modifiers.ts":{"6":[87]},"packages/cli/src/public-api/v1/openapi-gen/untyped-nullable.ts":{"14":[87],"16":[87],"26":[87]},"localhost-40517/assets/verified-Pt0guxqN.js":{"8":[168,173,209,211]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/n8n-trigger.svg":{"11":[168]},"packages/@n8n/backend-common/src/utils/path-util.ts":{"9":[170],"27":[170],"40":[170],"46":[170],"55":[170],"63":[170]},"packages/nodes-base/nodes/Files/ReadWriteFile/ReadWriteFile.node.ts":{"60":[170]},"packages/nodes-base/nodes/Files/ReadWriteFile/actions/read.operation.ts":{"96":[170]},"packages/nodes-base/nodes/Files/ReadWriteFile/actions/write.operation.ts":{"72":[170]},"packages/nodes-base/nodes/Files/ReadWriteFile/helpers/utils.ts":{"5":[170],"44":[170],"56":[170]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataHints.vue":{"18":[86,124,166,178,186,211,142],"35":[86,124,166,178,186,211,142],"39":[86,124,166,178,186,211,142],"83":[86,124,166,178,186,211,142],"102":[86,124,166,178,186,211,142],"106":[86,124],"110":[86,124],"114":[86,124],"120":[86,124],"121":[86,124],"124":[86,124],"128":[86,124],"138":[86,124,166,178,186,211,142],"144":[86,124,166,178,186,211,142],"149":[86,124,166,178,186,211,142],"156":[86,124],"159":[86,124],"168":[86,124],"169":[86,124],"182":[86,124]},"packages/cli/src/metrics/prometheus/active-workflow-metrics.service.ts":{"17":[15],"22":[15],"26":[15],"33":[15],"34":[15]},"packages/cli/src/metrics/prometheus/cached-metric-query.ts":{"19":[15],"37":[15],"51":[15],"57":[15],"69":[15],"83":[15],"91":[15],"96":[15],"102":[15]},"packages/cli/src/metrics/prometheus/database-metric-query.service.ts":{"33":[15],"42":[15],"46":[15],"50":[15],"54":[15],"58":[15],"62":[15],"66":[15],"70":[15],"81":[15],"85":[15],"89":[15],"93":[15],"97":[15]},"packages/cli/src/metrics/prometheus/prometheus.service.ts":{"42":[15],"101":[15],"113":[15],"115":[15],"116":[15],"124":[15],"126":[15]},"packages/cli/src/metrics/prometheus/pss-metrics.service.ts":{"15":[15],"17":[15],"21":[15],"25":[15],"41":[15]},"packages/cli/src/modules/instance-ai/instance-ai-run-probe.ts":{"12":[15],"13":[15],"15":[15],"19":[15]},"packages/workflow/src/n8n-oauth2-auth.ts":{"25":[15,125,220],"32":[15,125,220],"36":[15,125,220],"45":[15,125,220],"80":[15,125,220]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/AgentTool.node.ts":{"8":[181]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/V2/AgentToolV2.node.ts":{"19":[181],"99":[181]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/V2/utils.ts":{"11":[181],"23":[181],"26":[181],"86":[181],"89":[181]},"packages/@n8n/nodes-langchain/nodes/agents/Agent/V3/AgentToolV3.node.ts":{"22":[181],"101":[181]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/arrows-out--outline-16.svg":{"9":[86,124,45,188,199]},"packages/frontend/editor-ui/src/app/components/FocusPanel.vue":{"57":[188,199],"89":[188,199],"93":[188,199],"113":[188,199],"129":[188,199],"137":[188,199],"140":[188,199],"142":[188,199],"196":[188,199],"202":[188,199],"213":[188,199],"215":[188,199],"233":[188,199],"235":[199],"241":[199],"369":[188,199],"373":[188,199],"374":[188,199],"395":[188,199],"600":[199],"603":[199]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/components/ExperimentalCanvasNodeSettings.vue":{"21":[86,124,188,199],"31":[86,124,188,199],"32":[86,124,188,199],"35":[86,124,188,199],"36":[86,124,188,199],"41":[86,124,188,199],"43":[86,124],"49":[86,124],"70":[86,124,188,199],"91":[86,124],"93":[86,124]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/components/ExperimentalFocusPanelHeader.vue":{"18":[188,199],"27":[188,199],"28":[188,199],"32":[188,199]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/components/ExperimentalNodeDetailsDrawer.vue":{"21":[188,199],"26":[188,199],"27":[188],"33":[188,199],"36":[188,199],"37":[188],"46":[188,199],"51":[188],"53":[188],"58":[188]},"packages/@n8n/scheduler/src/core/recurrence/kinds/interval.ts":{"12":[53,54,55,56],"27":[53,54,55,56],"36":[53,54,55,56],"51":[53,54,55,56]},"packages/cli/src/scheduling/schedule-trigger-node/schedule-trigger-task-handler.ts":{"37":[53,54,55,56],"51":[53,54,55,56],"149":[53,54,55,56],"164":[53,54,55,56]},"packages/cli/src/scheduling/schedule-trigger-node/schedule-trigger-task.ts":{"14":[53,54,55,56],"24":[53,54,55,56]},"packages/cli/src/controllers/orchestration.controller.ts":{"9":[115],"20":[115]},"packages/cli/src/scaling/worker-status.service.ee.ts":{"18":[115],"26":[115],"36":[115],"51":[115],"62":[115],"94":[115],"95":[115],"110":[115]},"packages/frontend/editor-ui/src/features/settings/orchestration.ee/components/WorkerList.vue":{"25":[115],"35":[115],"39":[115],"41":[115],"49":[115],"60":[115]},"packages/frontend/editor-ui/src/features/settings/orchestration.ee/orchestration.store.ts":{"26":[115],"56":[115]},"packages/frontend/editor-ui/src/features/settings/orchestration.ee/views/WorkerView.vue":{"30":[115],"33":[115]},"packages/core/src/execution-engine/node-execution-context/utils/request-helpers/authentication.ts":{"44":[152,26,172,209],"56":[152,26,172,209],"203":[152,26,172,209]},"packages/nodes-base/nodes/Airtable/Airtable.node.ts":{"8":[209]},"packages/nodes-base/nodes/Airtable/v1/AirtableV1.node.ts":{"558":[209],"565":[209],"833":[209],"834":[209],"838":[209],"839":[209]},"packages/nodes-base/nodes/Airtable/v1/GenericFunctions.ts":{"29":[209],"72":[209],"100":[209]},"packages/nodes-base/nodes/Airtable/v2/AirtableV2.node.ts":{"15":[209],"29":[209]},"packages/nodes-base/nodes/Airtable/v2/actions/base/getMany.operation.ts":{"88":[209],"112":[209]},"packages/nodes-base/nodes/Airtable/v2/actions/base/getSchema.operation.ts":{"30":[209]},"packages/nodes-base/nodes/Airtable/v2/actions/record/create.operation.ts":{"51":[209]},"packages/nodes-base/nodes/Airtable/v2/actions/record/deleteRecord.operation.ts":{"36":[209]},"packages/nodes-base/nodes/Airtable/v2/actions/record/get.operation.ts":{"60":[209],"85":[209]},"packages/nodes-base/nodes/Airtable/v2/actions/record/search.operation.ts":{"147":[209],"183":[209],"214":[209],"224":[209]},"packages/nodes-base/nodes/Airtable/v2/actions/record/update.operation.ts":{"57":[209]},"packages/nodes-base/nodes/Airtable/v2/actions/record/upsert.operation.ts":{"52":[209],"120":[209],"125":[209],"142":[209]},"packages/nodes-base/nodes/Airtable/v2/actions/router.ts":{"8":[209]},"packages/nodes-base/nodes/Airtable/v2/helpers/utils.ts":{"11":[209],"16":[209],"41":[209],"50":[209],"56":[209],"63":[209],"78":[209],"97":[209],"112":[209],"121":[209],"131":[209]},"packages/nodes-base/nodes/Airtable/v2/methods/listSearch.ts":{"11":[209],"44":[209],"54":[209],"91":[209],"101":[209],"117":[209],"145":[209]},"packages/nodes-base/nodes/Airtable/v2/methods/loadOptions.ts":{"6":[209],"19":[209],"42":[209],"57":[209],"62":[209],"65":[209],"80":[209]},"packages/nodes-base/nodes/Airtable/v2/methods/resourceMapping.ts":{"48":[209],"63":[209],"76":[209],"88":[209],"90":[209],"120":[209]},"packages/nodes-base/nodes/Airtable/v2/transport/index.ts":{"20":[209],"59":[209],"87":[209],"94":[209],"131":[209]},"packages/nodes-base/nodes/Cron/Cron.node.ts":{"53":[209],"59":[209],"66":[209],"71":[209],"74":[209]},"packages/nodes-base/nodes/DebugHelper/DebugHelper.node.ts":{"255":[177,136,204,209,212],"346":[177,136,204,209,212]},"packages/nodes-base/nodes/DebugHelper/functions.ts":{"4":[177,136,204,209,212],"14":[177,136,204,209,212]},"packages/nodes-base/nodes/DebugHelper/randomData.ts":{"26":[177,136,204,209,212],"36":[177,136,204,209,212],"48":[177,136,204,209,212],"55":[177,136,204,209,212],"59":[177,136,204,209,212],"63":[177,136,204,209,212],"79":[177,136,204,209,212],"83":[177,136,204,209,212],"87":[177,136,204,209,212],"91":[177,136,204,209,212],"95":[177,136,204,209,212],"99":[177,136,204,209,212]},"packages/nodes-base/nodes/Typeform/GenericFunctions.ts":{"40":[209],"77":[209],"113":[209]},"packages/nodes-base/nodes/Typeform/TypeformTrigger.node.ts":{"122":[209],"160":[209],"179":[209],"205":[209],"230":[209],"305":[209]},"packages/nodes-base/nodes/Typeform/TypeformTriggerHelpers.ts":{"18":[209],"24":[209],"36":[209]},"packages/workflow/src/workflow-data-proxy-helpers.ts":{"3":[209]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/empty-output.svg":{"9":[86,124,209]},"packages/nodes-base/nodes/Google/Gmail/GmailTrigger.node.ts":{"295":[211],"312":[211],"325":[211],"366":[211],"384":[211],"402":[211],"454":[211],"461":[211],"495":[211],"496":[211],"606":[211],"663":[211],"678":[211],"682":[211],"685":[211],"735":[211],"745":[211],"777":[211],"815":[211],"819":[211],"826":[211]},"localhost-42409/assets/index-BoK1c_f3.js":{"3":[9,145,149,123,39,193,194,204]},"localhost-42409/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[9,145,149,123,39,193,194,204],"9":[9,145,149,123,39,193,194,204],"10":[9,145,149,123,39,193,194,204],"19":[9,145,149,123,39,193,194,204],"23":[9,145,149,123,39,193,194,204],"29":[9,145,149,123,39,193,194,204],"33":[9,145,149,123,39,193,194,204],"34":[9,145,149,123,39,193,194,204]},"packages/@n8n/db/src/repositories/evaluation-config.repository.ts":{"9":[145],"13":[145],"17":[145],"21":[145],"36":[145],"47":[145],"52":[145],"56":[145]},"packages/cli/src/evaluation.ee/evaluation-config.controller.ts":{"16":[145],"22":[145],"35":[145],"41":[145],"49":[145],"60":[145],"77":[145],"84":[145],"99":[145]},"packages/cli/src/evaluation.ee/evaluation-config.service.ts":{"13":[145],"19":[145],"23":[145],"27":[145],"55":[145],"71":[145],"75":[145],"79":[145]},"packages/@n8n/api-types/src/schemas/eval-collections.schema.ts":{"74":[145,86,124],"107":[145,86,124],"123":[145,86,124],"129":[145,86,124]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/components/Compare/AiInsightsCard.vue":{"9":[145],"24":[145],"25":[145],"30":[145],"36":[145],"40":[145],"48":[145],"50":[145],"64":[145],"71":[145],"77":[145],"83":[145],"94":[145],"104":[145],"126":[145],"139":[145],"146":[145],"159":[145]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/components/Compare/CasesTable.vue":{"27":[145],"44":[145],"49":[145],"56":[145],"57":[145],"62":[145],"65":[145],"70":[145],"73":[145],"81":[145],"87":[145],"91":[145],"92":[145],"97":[145],"116":[145],"144":[145],"149":[145],"162":[145],"166":[145],"173":[145],"184":[145],"188":[145]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/components/Compare/CompareHeader.vue":{"27":[145],"28":[145],"34":[145],"51":[145],"63":[145],"64":[145],"72":[145],"95":[145],"104":[145],"124":[145],"127":[145]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/components/Compare/CompareTabs.vue":{"16":[145],"36":[145],"43":[145],"46":[145],"49":[145],"52":[145],"68":[145]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/components/Compare/DatasetMismatchBanner.vue":{"8":[145],"14":[145],"15":[145],"19":[145]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/components/Compare/MetricCriteria.vue":{"19":[145],"21":[145],"44":[145],"49":[145]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/components/Compare/OutputsTab.vue":{"20":[145],"47":[145],"48":[145],"51":[145],"56":[145],"65":[145],"75":[145],"82":[145],"84":[145],"92":[145],"99":[145],"107":[145],"125":[145],"134":[145]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/components/Compare/ScoreChart.vue":{"21":[145],"25":[145],"36":[145],"37":[145],"43":[145],"50":[145],"57":[145],"63":[145]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/components/shared/GroupedMetricChart.vue":{"48":[145],"54":[145],"59":[145],"81":[145],"91":[145],"125":[145],"126":[145]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/components/shared/VersionAvatar.vue":{"10":[145],"22":[145],"24":[145],"25":[145]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/components/shared/versionPalette.ts":{"15":[145],"21":[145]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/composables/useCompareCases.ts":{"42":[145],"45":[145],"46":[145],"56":[145],"79":[145],"103":[145],"114":[145],"124":[145],"127":[145],"133":[145],"136":[145],"142":[145],"148":[145],"149":[145],"154":[145],"158":[145],"162":[145],"164":[145],"168":[145],"172":[145],"173":[145],"191":[145],"197":[145],"202":[145],"213":[145],"214":[145],"215":[145],"227":[145],"239":[145],"241":[145]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/composables/useCompareData.ts":{"47":[145],"50":[145],"52":[145],"67":[145],"68":[145],"78":[145],"79":[145],"82":[145]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/composables/useEvalCollectionsFlag.ts":{"24":[145]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/evalCollections.api.ts":{"16":[145],"34":[145],"141":[145]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/evalCollections.store.ts":{"24":[145],"27":[145],"28":[145],"30":[145],"49":[145],"64":[145],"66":[145],"85":[145],"261":[145],"339":[145]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/evaluation.api.ts":{"70":[145,86,124],"74":[145,86,124],"79":[86,124],"92":[86,124],"119":[86,124],"135":[86,124],"143":[145,86,124],"147":[145,86,124],"162":[86,124],"178":[145,86,124],"186":[86,124],"200":[86,124],"213":[86,124],"228":[86,124],"243":[86,124]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/evaluation.utils.ts":{"21":[145,86,124],"42":[86,124],"90":[145,86,124],"94":[145,86,124],"99":[86,124],"104":[86,124],"105":[86,124],"108":[145,86,124],"115":[145,86,124],"118":[145,86,124],"130":[145,86,124],"133":[145,86,124],"136":[145,86,124],"145":[86,124],"146":[86,124],"155":[145,86,124],"165":[145,86,124],"178":[145,86,124],"180":[145,86,124],"181":[145,86,124],"187":[145,86,124],"189":[145,86,124],"203":[145,86,124],"213":[86,124],"220":[86,124],"230":[145,86,124],"244":[145,86,124],"251":[145,86,124],"272":[86,124],"282":[145,86,124],"304":[145,86,124],"309":[86,124],"336":[145,86,124],"341":[86,124],"347":[86,124],"371":[86,124],"375":[86,124],"379":[86,124],"388":[145,86,124],"405":[86,124],"424":[86,124],"440":[86,124]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/views/CompareCollectionView.vue":{"38":[145],"42":[145],"58":[145],"69":[145],"70":[145],"86":[145],"89":[145],"92":[145],"98":[145],"112":[145],"137":[145],"151":[145],"187":[145]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/views/EvaluationsRootView.vue":{"44":[145,69],"46":[145],"47":[145],"52":[145],"56":[145],"91":[145],"101":[145,69],"118":[145,69]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/circle--outline-16.svg":{"9":[86,123,124,45,47,69]},"packages/@n8n/client-oauth2/src/client-oauth2-token.ts":{"28":[109,26,78],"43":[109,26,78],"75":[109,26,78],"132":[109,26,78]},"packages/@n8n/client-oauth2/src/client-oauth2.ts":{"70":[124,109,78],"88":[124,109,78],"96":[124,109,78],"109":[124,109,78],"122":[124,109,78],"125":[124,109,78],"145":[124,109,78],"197":[124,109,78]},"packages/@n8n/client-oauth2/src/code-flow.ts":{"40":[124,109,78],"45":[124,109,78],"89":[124,109,78]},"packages/@n8n/client-oauth2/src/credential-options.ts":{"22":[109,78]},"packages/@n8n/client-oauth2/src/credentials-flow.ts":{"25":[124,109,78],"30":[124,109,78]},"packages/@n8n/client-oauth2/src/index.ts":{"2":[124,109,78],"5":[124,109,78]},"packages/@n8n/client-oauth2/src/utils.ts":{"8":[124,109,78],"22":[124,109,78],"34":[124,109,78],"51":[124,109,78],"62":[124,109,78],"69":[124,109,78],"76":[124,109,78]},"packages/@n8n/decorators/src/credential-resolver/errors.ts":{"5":[109],"16":[109],"27":[109]},"packages/cli/src/controllers/oauth/oauth2-credential.controller.ts":{"22":[124,109,78],"33":[124,109,78],"41":[124,109,78],"210":[124,109,78]},"packages/cli/src/modules/dynamic-credentials.ee/config-redaction.ts":{"5":[109],"13":[109],"32":[109],"34":[109],"49":[109],"60":[109],"62":[109],"88":[109]},"packages/cli/src/modules/dynamic-credentials.ee/credential-resolvers/identifiers/n8n-identifier.ts":{"50":[109,27,125],"52":[109,27,125],"79":[109,27,125],"100":[109,27,125],"108":[109,27,125],"112":[109,27,125],"196":[109,27,125],"236":[109,27,125],"246":[109,27,125],"261":[109,27,125]},"packages/cli/src/modules/dynamic-credentials.ee/credential-resolvers/identifiers/oauth2-metadata-http-client.ts":{"36":[109],"53":[109],"66":[109]},"packages/cli/src/modules/dynamic-credentials.ee/credential-resolvers/identifiers/oauth2-userinfo-identifier.ts":{"37":[109],"46":[109],"70":[109],"76":[109],"108":[109],"139":[109],"150":[109],"161":[109],"170":[109],"221":[109],"240":[109],"291":[109],"312":[109],"329":[109],"338":[109],"361":[109],"380":[109],"389":[109]},"packages/cli/src/modules/dynamic-credentials.ee/credential-resolvers/identifiers/oauth2-utils.ts":{"20":[109],"25":[109],"39":[109],"46":[109],"66":[109]},"packages/cli/src/modules/dynamic-credentials.ee/credential-resolvers/oauth-credential-resolver.ts":{"40":[109],"135":[109],"164":[109],"185":[109],"195":[109],"199":[109],"212":[109],"217":[109],"228":[109],"236":[109]},"packages/cli/src/modules/dynamic-credentials.ee/credential-resolvers/storage/dynamic-credential-entry-storage.ts":{"10":[109],"14":[109],"31":[109],"53":[109],"66":[109]},"packages/cli/src/modules/dynamic-credentials.ee/credential-resolvers.controller.ts":{"38":[109,219],"47":[109,219],"48":[109,219],"68":[109,219],"78":[109,219],"89":[109,219],"92":[109,219],"103":[109,219],"135":[109,219],"156":[109,219],"176":[109,219],"216":[109,219]},"packages/cli/src/modules/dynamic-credentials.ee/dynamic-credentials.controller.ts":{"35":[109,27],"51":[109,27],"74":[109,27],"115":[109,27],"127":[109,27],"160":[109,27],"172":[109,27],"243":[109,27],"324":[109,27]},"packages/cli/src/modules/dynamic-credentials.ee/services/credential-resolver-registry.service.ts":{"14":[109],"24":[109],"68":[109],"75":[109]},"packages/cli/src/modules/dynamic-credentials.ee/services/credential-resolver.service.ts":{"49":[109,219],"65":[109,219],"90":[109,219],"93":[109,219],"98":[109,219],"101":[109,219],"108":[109,219],"113":[109,219],"114":[109,219],"122":[109,219],"135":[109,219],"194":[109,219],"208":[109,219],"222":[109,219],"264":[109,219],"295":[109,219],"313":[109,219],"320":[109,219],"334":[109,219]},"packages/cli/src/modules/dynamic-credentials.ee/services/dynamic-credential-storage.service.ts":{"27":[109],"36":[109],"132":[109],"138":[109]},"packages/cli/src/modules/dynamic-credentials.ee/services/resolver-config-expression.service.ts":{"16":[109],"23":[109]},"packages/cli/src/modules/dynamic-credentials.ee/services/shared-fields.ts":{"19":[109],"38":[109],"60":[109],"67":[109]},"packages/workflow/src/node-parameters/node-parameter-value-type-guard.ts":{"13":[109],"27":[109],"38":[109],"54":[109],"66":[109],"84":[109],"120":[109]},"packages/cli/src/modules/dynamic-credentials.ee/context-establishment-hooks/bearer-token-extractor.ts":{"29":[26],"37":[26],"41":[26]},"packages/cli/src/modules/dynamic-credentials.ee/context-establishment-hooks/http-header-extractor.ts":{"24":[26],"32":[26],"53":[26],"75":[26],"101":[26],"105":[26]},"packages/core/src/execution-engine/node-execution-context/utils/request-helpers/oauth.ts":{"48":[26,78],"55":[26,78],"77":[26,78],"94":[26,78],"118":[26,78],"129":[26,78],"135":[26,78],"152":[26,78],"163":[26,78],"302":[26,78],"311":[26,78],"321":[26,78],"328":[26,78],"344":[26,78],"349":[26,78],"353":[26,78],"356":[26,78],"364":[26,78],"366":[26,78],"369":[26,78],"381":[26,78],"395":[26,78],"503":[26,78],"522":[26,78],"547":[26,78],"550":[26,78],"551":[26,78],"562":[26,78],"573":[26,78],"576":[26,78],"577":[26,78],"596":[26,78],"620":[26,78],"662":[26,78],"668":[26,78]},"packages/cli/src/credentials/executing-user-identifier-proxy.ts":{"16":[27],"20":[27]},"packages/cli/src/modules/dynamic-credentials.ee/credential-resolvers/n8n-credential-resolver.ts":{"22":[27],"40":[27],"69":[27],"90":[27],"105":[27],"109":[27],"113":[27],"125":[27],"133":[27]},"packages/cli/src/modules/dynamic-credentials.ee/credential-resolvers/storage/dynamic-credential-user-entry-storage.ts":{"14":[27],"26":[27],"52":[27],"81":[27],"100":[27]},"packages/cli/src/modules/dynamic-credentials.ee/services/authorize-intent.service.ts":{"37":[27],"39":[27],"48":[27],"52":[27]},"packages/cli/src/utils/handlebars.util.ts":{"6":[27],"10":[27],"11":[27],"22":[27]},"packages/@n8n/db/src/utils/separate.ts":{"1":[102,216],"5":[102,216]},"localhost-45803/assets/index-BoK1c_f3.js":{"3":"b:AAAAAAAAAAAAAAABAABQAAAAQAEACNsiwAAAAQA="},"localhost-45803/assets/rolldown-runtime-Bq5D3eIA.js":{"8":"b:AAAAAAAAAAAAAAABAABQAAAAQAEACNsiwAAAAQA=","9":"b:AAAAAAAAAAAAAAABAABQAAAAQAEACNsiwAAAAQA=","10":"b:AAAAAAAAAAAAAAABAABQAAAAQAEACNsiwAAAAQA=","19":"b:AAAAAAAAAAAAAAABAABQAAAAQAEACNsiwAAAAQA=","23":"b:AAAAAAAAAAAAAAABAABQAAAAQAEACNsiwAAAAQA=","29":"b:AAAAAAAAAAAAAAABAABQAAAAQAEACNsiwAAAAQA=","33":"b:AAAAAAAAAAAAAAABAABQAAAAQAEACNsiwAAAAQA=","34":"b:AAAAAAAAAAAAAAABAABQAAAAQAEACNsiwAAAAQA="},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/status-warning.svg":{"8":[86,88,124]},"packages/frontend/@n8n/design-system/src/components/N8nStatusDot/StatusDot.vue":{"13":[86,88,124,81,100]},"packages/frontend/editor-ui/src/app/components/PublicationIndicator.vue":{"35":[88,81,100],"37":[88,81,100]},"packages/frontend/editor-ui/src/app/components/VersionUpdateCTA.vue":{"30":[88]},"packages/cli/src/modules/inbound-auth-core/trusted-source.gate.ts":{"18":[125],"27":[125]},"packages/@n8n/db/src/repositories/webhook.repository.ts":{"8":[220,67],"16":[220,67],"25":[220,67],"36":[220,67]},"packages/core/src/errors/unrecognized-node-type.error.ts":{"4":[39]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/nodeCreator/CommunityNodeDetails.vue":{"20":[39],"40":[39],"103":[39]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/nodeCreator/CommunityNodeDocsLink.vue":{"9":[39],"14":[39],"23":[39]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/nodeCreator/CommunityNodeFooter.vue":{"16":[86,124,39],"21":[86,124,39],"25":[86,124],"29":[86,124],"35":[86,124,39],"55":[86,124,39],"60":[86,124,39],"67":[86,124],"75":[86,124,39],"76":[86,124,39],"79":[86,124,39],"82":[86,124,39],"83":[86,124,39]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/nodeCreator/CommunityNodeInfo.vue":{"18":[39],"30":[39],"31":[39],"35":[39],"44":[39],"51":[39],"112":[39],"117":[39],"122":[39],"148":[39],"151":[39]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/CommunityNodeItem.vue":{"11":[39]},"packages/cli/src/modules/external-secrets.ee/external-secrets-provider-connection-manager.ee.ts":{"49":[113,60,95],"64":[113,60,95],"68":[113,60,95],"71":[113,60,95],"74":[113,60,95],"88":[113,60,95],"103":[113,60,95],"120":[113,60,95],"131":[113,60,95],"158":[113,60,95],"168":[113,60,95],"193":[113,60,95],"225":[113,60,95],"233":[113,60,95],"246":[113,60,95],"272":[113,60,95],"305":[113,60,95],"314":[113,60,95],"315":[113,60,95],"327":[113,60,95],"347":[113,60,95],"427":[113,60,95],"466":[113,60,95],"486":[113,60,95],"491":[113,60,95],"500":[113,60,95]},"packages/cli/src/modules/external-secrets.ee/external-secrets.controller.ee.ts":{"13":[113,95],"22":[113,95],"34":[113,95],"40":[113,95],"47":[113,95],"60":[113,95],"68":[113,95],"76":[113,95],"90":[113,95]},"packages/cli/src/modules/external-secrets.ee/external-secrets.service.ee.ts":{"10":[113,95],"15":[113,95],"30":[113,95],"31":[113,95],"44":[113,95],"50":[113,95],"54":[113,95],"61":[113,95],"66":[113,95],"70":[113,95],"77":[113,95]},"packages/cli/src/modules/external-secrets.ee/provider-lifecycle.service.ts":{"25":[113,95],"36":[113,95],"78":[113,95],"112":[113,95],"127":[113,95]},"packages/cli/src/modules/external-secrets.ee/redaction.service.ee.ts":{"15":[113,95],"19":[113,95],"20":[113,95],"42":[113,95],"53":[113,95],"62":[113,95]},"packages/cli/src/modules/external-secrets.ee/retry-manager.service.ts":{"28":[113,60,95],"31":[113,60,95],"32":[113,60,95],"43":[113,60,95],"63":[113,60,95],"76":[113,60,95],"113":[113,60,95],"128":[113,60,95],"139":[113,60,95],"146":[113,60,95]},"packages/cli/src/modules/external-secrets.ee/settings-store.service.ts":{"18":[113,95],"26":[113,95],"38":[113,95],"54":[113,95],"61":[113,95],"80":[113,95],"108":[113,95],"116":[113,95],"127":[113,95],"142":[113,95]},"packages/cli/src/modules/external-secrets.ee/with-timeout.ts":{"12":[113,95],"14":[113,95],"15":[113,95]},"packages/cli/src/modules/external-secrets.ee/errors/secrets-provider-errors.ts":{"24":[60,95],"59":[60,95],"79":[60,95],"96":[60,95]},"packages/cli/src/modules/external-secrets.ee/secret-provider-access-check.service.ee.ts":{"16":[60],"23":[60],"33":[60],"76":[60],"97":[60],"99":[60]},"localhost-44083/assets/index-BoK1c_f3.js":{"3":[60]},"localhost-44083/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[60],"9":[60],"10":[60],"19":[60],"23":[60],"29":[60],"33":[60],"34":[60]},"packages/frontend/editor-ui/src/features/integrations/externalSecrets.ee/assets/images/aws-secrets-manager.svg":{"8":[86,124,60]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/components/DeleteSecretsProviderModal.ee.vue":{"28":[86,124,60],"41":[86,124,60],"43":[86,124,60],"47":[86,124,60],"54":[86,124,60],"64":[86,124,60],"74":[86,124,60],"90":[86,124,60],"126":[86,124],"128":[86,124,60],"142":[86,124,60],"145":[86,124,60],"157":[86,124,60],"162":[86,124,60],"163":[86,124,60],"179":[86,124,60],"190":[86,124,60],"195":[86,124,60],"198":[86,124,60],"206":[86,124,60]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/components/SecretsProviderConnectionCard.ee.vue":{"49":[60],"57":[60],"61":[60],"63":[60],"74":[60],"85":[60],"95":[60],"115":[60],"156":[60],"167":[60],"180":[60],"183":[60],"198":[60],"224":[60],"230":[60]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/components/SecretsProviderImage.ee.vue":{"17":[86,124,60],"21":[86,124,60]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/components/SecretsProvidersEmptyState.ee.vue":{"8":[60],"16":[60],"45":[60],"56":[60],"64":[60],"73":[60],"95":[60],"101":[60],"108":[60],"112":[60]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/views/SettingsSecretsProviders.ee.vue":{"47":[60],"49":[60],"52":[60],"97":[60],"101":[60],"137":[60],"138":[60],"193":[60],"194":[60],"205":[60],"212":[60],"237":[60],"243":[60],"251":[60],"266":[60],"269":[60],"285":[60],"298":[60],"310":[60]},"packages/@n8n/api-types/src/dto/user/user-update-request.dto.ts":{"6":[193,63],"13":[193,63],"15":[193,63]},"packages/frontend/@n8n/design-system/src/components/N8nExternalLink/ExternalLink.vue":{"20":[86,143,124,193,63],"27":[86,143,124,193,63]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/sun--outline-16.svg":{"9":[86,143,124,45,193,63]},"packages/frontend/editor-ui/src/features/core/auth/views/SettingsPersonalView.vue":{"66":[143,193,63],"69":[143,193,63],"71":[143,193,63],"75":[143,193,63],"85":[143,193,63],"89":[143,193,63],"90":[143,193,63],"100":[143,193,63],"101":[143,193,63],"102":[143,193,63],"106":[143,193,63],"112":[143,193,63],"116":[143,193,63],"175":[143,193,63],"188":[143,193,63],"215":[193,63],"234":[143,193,63],"238":[143,193,63],"255":[143,193,63],"264":[193,63],"274":[193,63],"283":[193,63],"290":[193,63],"291":[193,63],"295":[193,63],"317":[63],"330":[63],"341":[63],"351":[63],"393":[63],"404":[63],"412":[63],"439":[143,193,63],"446":[143,193,63],"456":[143,193,63],"480":[193,63],"511":[143,193,63],"514":[143,193,63],"515":[143,193,63],"526":[143,193,63],"538":[143,193,63],"549":[143,193,63],"564":[143,193,63],"569":[143,193,63]},"packages/@n8n/api-types/src/dto/invitation/invite-users-request.dto.ts":{"12":[143,194]},"packages/@n8n/backend-services/src/services/ownership-transfer-handler.registry.ts":{"20":[194],"23":[194],"27":[194]},"packages/cli/src/modules/chat-hub/chat-hub-event-relay.service.ts":{"9":[194],"18":[194],"26":[194]},"packages/cli/src/modules/data-table/data-table.module.ts":{"8":[194],"22":[194],"29":[194],"41":[194],"47":[194],"55":[194],"62":[194]},"packages/cli/src/modules/instance-ai/instance-ai-event-relay.service.ts":{"20":[194],"30":[194],"38":[194]},"packages/cli/src/modules/provisioning.ee/provisioning.controller.ee.ts":{"13":[89,194],"21":[89,194],"31":[89,194]},"packages/cli/src/services/ownership-transfer/ownership-transfer.service.ts":{"27":[194],"42":[194],"53":[194],"83":[194],"86":[194],"111":[194]},"packages/frontend/@n8n/rest-api-client/src/api/provisioning.ts":{"22":[86,124,194],"28":[86,124]},"packages/frontend/editor-ui/src/app/utils/rbac/checks/isDefaultUser.ts":{"4":[86,124,194]},"packages/frontend/editor-ui/src/features/roles/instance/instanceRoleScopes.ts":{"153":[194],"163":[194],"168":[194],"186":[194],"240":[194],"249":[194],"264":[194],"270":[194],"282":[194],"297":[194],"301":[194],"307":[194],"311":[194],"322":[194],"326":[194],"347":[194],"359":[194],"360":[194],"364":[194],"365":[194],"448":[194],"488":[194]},"packages/frontend/editor-ui/src/features/settings/sso/provisioning/composables/userRoleProvisioning.store.ts":{"13":[194],"18":[194]},"packages/frontend/editor-ui/src/features/settings/users/components/DeleteUserModal.vue":{"15":[86,124,194],"32":[86,124,194],"35":[86,124,194],"38":[86,124,194],"40":[86,124,194],"49":[86,124,194],"65":[86,124,194],"71":[86,124,194],"105":[86,124,194],"118":[86,124,194],"122":[86,124,194],"128":[86,124,194],"132":[86,124,194],"134":[86,124,194],"137":[86,124,194],"142":[86,124,194],"154":[86,124,194],"155":[86,124,194],"156":[86,124,194],"165":[86,124,194],"174":[86,124,194]},"packages/frontend/editor-ui/src/features/settings/users/components/SettingsUsersActionsCell.vue":{"7":[194],"16":[194],"21":[194]},"packages/frontend/editor-ui/src/features/settings/users/components/SettingsUsersLastActiveCell.vue":{"7":[194],"10":[194],"13":[194]},"packages/frontend/editor-ui/src/features/settings/users/components/SettingsUsersProjectsCell.vue":{"8":[194],"20":[194],"26":[194],"33":[194],"34":[194],"38":[194],"51":[194],"52":[194]},"packages/frontend/editor-ui/src/features/settings/users/components/SettingsUsersProjectsModal.vue":{"17":[194],"52":[194]},"packages/frontend/editor-ui/src/features/settings/users/components/SettingsUsersRoleCell.vue":{"31":[194],"33":[194],"34":[194],"36":[194],"40":[194],"41":[194],"45":[194],"48":[194],"49":[194],"50":[194],"52":[194],"56":[194],"58":[194]},"packages/frontend/editor-ui/src/features/settings/users/components/SettingsUsersTable.vue":{"19":[194],"41":[194],"47":[194],"63":[194],"74":[194],"85":[194],"96":[194],"127":[194],"135":[194],"138":[194],"143":[194],"145":[194],"160":[194],"165":[194],"176":[194],"179":[194],"182":[194],"186":[194]},"packages/frontend/editor-ui/src/features/settings/users/views/SettingsUsersView.vue":{"71":[194],"73":[194],"77":[194],"81":[194],"83":[194],"98":[194],"103":[194],"112":[194],"118":[194],"125":[194],"134":[194],"139":[194],"143":[194],"147":[194],"171":[194],"206":[194],"211":[194],"328":[194],"329":[194],"338":[194],"350":[194],"373":[194],"378":[194],"425":[194],"428":[194],"433":[194],"442":[194],"502":[194],"509":[194]},"localhost-39957/assets/index-BoK1c_f3.js":{"3":[8,143,165,192,203,210,212,218]},"localhost-39957/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[8,143,165,192,203,210,212,218],"9":[8,143,165,192,203,210,212,218],"10":[8,143,165,192,203,210,212,218],"19":[8,143,165,192,203,210,212,218],"23":[8,143,165,192,203,210,212,218],"29":[8,143,165,192,203,210,212,218],"33":[8,143,165,192,203,210,212,218],"34":[8,143,165,192,203,210,212,218]},"packages/cli/src/public-api/v1/shared/services/pagination.service.ts":{"12":[90,143],"20":[90,143],"48":[90,143],"60":[90,143],"72":[90,143],"81":[90,143]},"localhost-39957/assets/verified-Pt0guxqN.js":{"8":[165]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/edit-image.svg":{"11":[164,165,100]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/Panel/NoResults.vue":{"8":[165],"24":[165],"27":[165],"32":[165],"47":[165],"59":[165]},"packages/cli/src/push/origin-validator.ts":{"16":[46],"26":[46],"43":[46],"111":[46],"145":[46],"166":[46],"177":[46],"187":[46],"199":[46],"239":[46]},"packages/cli/src/push/sse.push.ts":{"11":[46],"32":[46],"42":[46],"46":[46],"52":[46]},"packages/cli/src/services/rate-limit.service.ts":{"31":[46],"45":[46],"56":[46],"58":[46],"65":[46],"69":[46],"70":[46],"77":[46],"95":[46]},"localhost-37417/assets/index-BoK1c_f3.js":{"3":[46]},"localhost-37417/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[46],"9":[46],"10":[46],"19":[46],"23":[46],"29":[46],"33":[46],"34":[46]},"packages/cli/src/environments.ee/variables/variables.controller.ee.ts":{"18":[192],"21":[192],"31":[192],"49":[192],"59":[192],"79":[192]},"packages/frontend/@n8n/design-system/src/components/N8nDatatable/Datatable.vue":{"16":[86,124,192],"30":[86,124,192],"34":[86,124],"38":[86,124,192],"47":[86,124],"51":[86,124],"65":[86,124],"69":[86,124,192],"73":[86,124,192],"82":[86,124,192],"92":[86,124,192],"94":[86,124],"95":[86,124],"125":[86,124,192],"126":[86,124,192],"127":[86,124,192]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/variable--outline-16.svg":{"9":[86,124,45,192,216]},"packages/frontend/editor-ui/src/features/collaboration/projects/views/ProjectVariables.vue":{"67":[192],"77":[192],"81":[192],"86":[192],"90":[192],"92":[192],"93":[192],"108":[192],"113":[192],"149":[192],"183":[192],"192":[192],"196":[192],"215":[192],"221":[192],"268":[192],"280":[192],"289":[192],"313":[192],"399":[192],"433":[192],"434":[192],"450":[192],"451":[192],"462":[192]},"packages/frontend/editor-ui/src/features/settings/environments.ee/components/VariableModal.vue":{"58":[86,124,192],"63":[86,124,192],"89":[86,124,192],"94":[86,124,192],"101":[86,124,192],"105":[86,124],"108":[86,124,192],"109":[86,124,192],"112":[86,124,192],"125":[86,124,192],"151":[86,124,192],"152":[86,124],"169":[86,124,192],"170":[86,124,192],"174":[86,124,192],"184":[86,124,192],"188":[86,124,192],"197":[86,124],"202":[86,124],"207":[86,124,192],"243":[86,124,192],"248":[86,124,192],"265":[86,124,192],"275":[86,124,192],"278":[86,124,192],"280":[86,124],"281":[86,124],"294":[86,124,192],"301":[86,124,192],"309":[86,124],"325":[86,124,192],"330":[86,124,192],"336":[86,124,192],"340":[86,124],"343":[86,124,192],"345":[86,124,192],"351":[86,124,192],"354":[86,124],"365":[86,124,192]},"packages/frontend/editor-ui/src/features/settings/environments.ee/environments.api.ts":{"10":[86,124,192,203,210,212,218],"21":[86,124,192],"29":[86,124,192],"41":[86,124,192]},"packages/frontend/editor-ui/src/app/components/WorkflowPreviewHost.vue":{"45":[203,100],"50":[203,100],"61":[203,100],"76":[203,100],"90":[203,100],"122":[203,100],"124":[203,100],"128":[203,100]},"packages/frontend/editor-ui/src/features/workflows/workflowHistory/components/WorkflowHistoryContent.vue":{"40":[203],"55":[203],"70":[203],"81":[203],"84":[203],"97":[203],"101":[203],"107":[203],"129":[203],"130":[203],"135":[203],"150":[203],"152":[203],"172":[203]},"packages/frontend/editor-ui/src/features/workflows/workflowHistory/components/WorkflowHistoryList.vue":{"22":[203],"49":[203],"61":[203],"73":[203],"82":[203],"86":[203],"92":[203],"119":[203],"151":[203],"179":[203],"184":[203]},"packages/frontend/editor-ui/src/features/workflows/workflowHistory/components/WorkflowHistoryListItem.vue":{"26":[203],"58":[203],"63":[203],"74":[203],"83":[203],"99":[203],"165":[203],"172":[203],"203":[203],"211":[203],"214":[203]},"packages/frontend/editor-ui/src/features/workflows/workflowHistory/views/WorkflowHistory.vue":{"61":[203],"78":[203],"81":[203],"92":[203],"93":[203],"100":[203],"101":[203],"106":[203],"112":[203],"117":[203],"127":[203],"128":[203],"143":[203],"154":[203],"169":[203],"177":[203],"181":[203],"199":[203],"228":[203],"573":[203],"588":[203],"625":[203],"644":[203]},"packages/nodes-base/nodes/N8nTrainingCustomerDatastore/N8nTrainingCustomerDatastore.node.ts":{"119":[210]},"packages/nodes-base/nodes/Transform/Sort/Sort.node.ts":{"164":[210,140],"221":[210,140],"226":[210,140]},"packages/nodes-base/nodes/Transform/Sort/utils.ts":{"8":[210,140]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/sort.svg":{"11":[116,210,140]},"packages/nodes-base/nodes/Linear/GenericFunctions.ts":{"16":[152],"66":[152],"70":[152],"100":[152],"126":[152]},"packages/nodes-base/nodes/Linear/Linear.node.ts":{"109":[152],"119":[152],"136":[152],"154":[152],"172":[152],"220":[152]},"packages/nodes-base/nodes/Linear/Queries.ts":{"2":[152],"15":[152],"28":[152],"41":[152],"95":[152],"102":[152],"138":[152],"147":[152],"189":[152],"245":[152],"255":[152]},"packages/nodes-base/nodes/Google/Sheet/GoogleSheets.node.ts":{"8":[78,218,100]},"packages/nodes-base/nodes/Google/Sheet/v1/GenericFunctions.ts":{"20":[78,218,100],"72":[78,218,100],"96":[78,218,100],"99":[78,218,100]},"packages/nodes-base/nodes/Google/Sheet/v1/GoogleSheet.ts":{"48":[78,218,100],"66":[78,218,100],"78":[78,218,100],"97":[78,218,100],"119":[78,218,100],"138":[78,218,100],"156":[78,218,100],"175":[78,218,100],"194":[78,218,100],"218":[78,218,100],"250":[78,218,100],"270":[78,218,100],"286":[78,218,100],"300":[78,218,100],"386":[78,218,100],"470":[78,218,100],"542":[78,218,100],"574":[78,218,100],"576":[78,218,100]},"packages/nodes-base/nodes/Google/Sheet/v1/GoogleSheetsV1.node.ts":{"32":[78,218,100],"42":[78,218,100],"68":[78,218,100],"96":[78,218,100],"125":[78,218,100],"227":[78,218,100],"299":[78,218,100],"413":[78,218,100]},"packages/nodes-base/nodes/Google/Sheet/v2/GoogleSheetsV2.node.ts":{"15":[78,218,100],"29":[78,218,100]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/router.ts":{"9":[78,218,100]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/append.operation.ts":{"213":[78,218,100],"326":[78,218,100]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/appendOrUpdate.operation.ts":{"264":[78,218,100],"365":[78,218,100],"374":[78,218,100],"392":[78,218,100],"424":[78,218,100],"447":[78,218,100],"521":[78,218,100]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/clear.operation.ts":{"160":[78,218,100]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/create.operation.ts":{"77":[78,218,100]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/delete.operation.ts":{"114":[78,218,100]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/read.operation.ts":{"170":[78,218,100]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/remove.operation.ts":{"7":[78,218,100]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/update.operation.ts":{"253":[78,218,100],"345":[78,218,100],"354":[78,218,100],"371":[78,218,100],"403":[78,218,100],"430":[78,218,100],"496":[78,218,100]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/spreadsheet/create.operation.ts":{"118":[78,218,100]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/spreadsheet/delete.operation.ts":{"68":[78,218,100]},"packages/nodes-base/nodes/Google/Sheet/v2/actions/utils/readOperation.ts":{"12":[78,218,100],"110":[78,218,100]},"packages/nodes-base/nodes/Google/Sheet/v2/helpers/GoogleSheet.ts":{"39":[78,218,100],"47":[78,218,100],"58":[78,218,100],"74":[78,218,100],"93":[78,218,100],"117":[78,218,100],"136":[78,218,100],"149":[78,218,100],"165":[78,218,100],"178":[78,218,100],"186":[78,218,100],"204":[78,218,100],"220":[78,218,100],"264":[78,218,100],"287":[78,218,100],"333":[78,218,100],"367":[78,218,100],"380":[78,218,100],"394":[78,218,100],"411":[78,218,100],"441":[78,218,100],"446":[78,218,100],"461":[78,218,100],"480":[78,218,100],"494":[78,218,100],"545":[78,218,100],"627":[78,218,100],"675":[78,218,100],"803":[78,218,100],"833":[78,218,100],"835":[78,218,100],"857":[78,218,100],"880":[78,218,100]},"packages/nodes-base/nodes/Google/Sheet/v2/helpers/GoogleSheets.utils.ts":{"24":[78,218,100],"50":[78,218,100],"56":[78,218,100],"69":[78,218,100],"79":[78,218,100],"82":[78,218,100],"99":[78,218,100],"101":[78,218,100],"106":[78,218,100],"108":[78,218,100],"115":[78,218,100],"117":[78,218,100],"120":[78,218,100],"128":[78,218,100],"134":[78,218,100],"135":[78,218,100],"146":[78,218,100],"149":[78,218,100],"151":[78,218,100],"156":[78,218,100],"161":[78,218,100],"162":[78,218,100],"166":[78,218,100],"199":[78,218,100],"206":[78,218,100],"208":[78,218,100],"211":[78,218,100],"238":[78,218,100],"272":[78,218,100],"281":[78,218,100],"282":[78,218,100],"305":[78,218,100],"310":[78,218,100],"311":[78,218,100],"326":[78,218,100],"334":[78,218,100],"336":[78,218,100],"351":[78,218,100],"358":[78,218,100],"364":[78,218,100],"368":[78,218,100],"369":[78,218,100],"371":[78,218,100]},"packages/nodes-base/nodes/Google/Sheet/v2/methods/credentialTest.ts":{"9":[78,218,100]},"packages/nodes-base/nodes/Google/Sheet/v2/methods/listSearch.ts":{"15":[78,218,100],"44":[78,218,100],"53":[78,218,100]},"packages/nodes-base/nodes/Google/Sheet/v2/methods/loadOptions.ts":{"8":[78,218,100],"39":[78,218,100],"87":[78,218,100],"96":[78,218,100],"99":[78,218,100],"103":[78,218,100],"113":[78,218,100],"117":[78,218,100]},"packages/nodes-base/nodes/Google/Sheet/v2/methods/resourceMapping.ts":{"12":[78,218,100],"58":[78,218,100],"60":[78,218,100]},"packages/nodes-base/nodes/Google/Sheet/v2/transport/index.ts":{"16":[78,218,100],"84":[78,218,100]},"packages/nodes-base/nodes/Hubspot/HubspotTrigger.node.ts":{"17":[218,100],"320":[218,100],"323":[218,100],"326":[218,100],"329":[218,100],"337":[218,100],"384":[218,100],"418":[218,100],"447":[218,100]},"packages/nodes-base/nodes/Hubspot/V1/GenericFunctions.ts":{"15":[218,100],"78":[218,100],"123":[218,100],"144":[218,100],"155":[218,100],"1953":[218,100],"1955":[218,100],"1960":[218,100],"1963":[218,100],"1978":[218,100],"1987":[218,100],"1997":[218,100],"2008":[218,100],"2024":[218,100]},"packages/nodes-base/nodes/Kafka/KafkaTrigger.node.ts":{"8":[111]},"packages/nodes-base/nodes/Kafka/utils.ts":{"42":[111],"59":[111],"133":[111],"149":[111],"162":[111],"197":[111],"204":[111],"237":[111],"288":[111],"294":[111],"330":[111],"360":[111],"384":[111],"389":[111],"392":[111],"395":[111],"400":[111],"404":[111],"407":[111],"410":[111],"413":[111],"416":[111],"445":[111],"448":[111],"463":[111],"496":[111],"500":[111],"544":[111],"595":[111],"622":[111],"645":[111],"655":[111],"683":[111],"686":[111],"695":[111],"697":[111],"706":[111],"707":[111],"730":[111],"746":[111],"768":[111],"773":[111],"774":[111],"793":[111],"804":[111],"805":[111],"815":[111],"816":[111],"817":[111],"844":[111],"852":[111]},"packages/nodes-base/nodes/Kafka/v1/KafkaTriggerV1.node.ts":{"400":[111],"407":[111],"428":[111],"444":[111],"453":[111],"487":[111],"523":[111],"531":[111],"559":[111]},"packages/nodes-base/nodes/Kafka/v2/KafkaTriggerV2.node.ts":{"21":[111],"28":[111],"58":[111],"63":[111],"70":[111],"72":[111],"84":[111],"105":[111],"108":[111],"116":[111],"122":[111]},"packages/nodes-base/nodes/Kafka/v2/TriggerSettings.ts":{"93":[111],"124":[111],"150":[111],"209":[111],"214":[111],"235":[111],"264":[111],"367":[111]},"packages/nodes-base/nodes/Kafka/v2/consumer/ConsumeTopic.ts":{"114":[111],"130":[111],"133":[111],"137":[111],"161":[111],"184":[111],"208":[111],"214":[111],"242":[111],"263":[111],"296":[111],"326":[111]},"packages/nodes-base/nodes/Kafka/v2/consumer/DataEmitter.ts":{"75":[111],"90":[111],"91":[111],"100":[111],"115":[111],"117":[111],"151":[111],"168":[111],"169":[111],"170":[111],"188":[111],"210":[111],"212":[111]},"packages/nodes-base/nodes/Kafka/v2/consumer/MessageParser.ts":{"37":[111],"42":[111],"58":[111],"64":[111],"114":[111]},"packages/nodes-base/nodes/Kafka/v2/consumer/index.ts":{"15":[111]},"localhost-39061/assets/index-BoK1c_f3.js":{"3":[111]},"localhost-39061/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[111],"9":[111],"10":[111],"19":[111],"23":[111],"29":[111],"33":[111],"34":[111]},"packages/cli/src/eventbus/event-message-classes/abstract-event-message.ts":{"10":[117,62],"12":[117,62],"16":[117,62],"28":[117,62],"48":[117,62],"59":[117,62],"72":[117,62],"101":[117,62],"107":[117,62],"115":[117,62],"120":[117,62],"131":[117,62],"142":[117,62],"146":[117,62]},"packages/cli/src/modules/log-streaming.ee/destinations/message-event-bus-destination-sentry.ee.ts":{"16":[62],"36":[62],"56":[62],"95":[62],"105":[62],"119":[62],"123":[62]},"packages/cli/src/modules/log-streaming.ee/destinations/message-event-bus-destination-webhook.ee.ts":{"31":[117,62],"81":[117,62],"116":[117,62],"125":[117,62],"130":[117,62],"142":[117,62],"170":[117,62],"171":[117,62],"190":[117,62],"208":[117,62],"267":[117,62],"301":[117,62],"317":[117,62]},"localhost-45845/assets/index-BoK1c_f3.js":{"3":[62,69,141,142,100]},"localhost-45845/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[62,69,141,142,100],"9":[62,69,141,142,100],"10":[62,69,141,142,100],"19":[62,69,141,142,100],"23":[62,69,141,142,100],"29":[62,69,141,142,100],"33":[62,69,141,142,100],"34":[62,69,141,142,100]},"packages/frontend/editor-ui/src/features/integrations/logStreaming.ee/components/LogStreamingPaywall.vue":{"27":[62]},"packages/cli/src/controllers/change-email.controller.ts":{"30":[63],"49":[63],"118":[63],"134":[63],"165":[63],"173":[63]},"packages/cli/src/controllers/mfa.controller.ts":{"21":[63],"32":[63],"67":[63],"75":[63],"118":[63],"159":[63],"203":[63]},"packages/cli/src/mfa/mfa.service.ts":{"17":[63],"27":[63],"35":[63],"36":[63],"39":[63],"45":[63],"60":[63],"68":[63],"80":[63],"83":[63],"91":[63],"95":[63],"100":[63],"107":[63],"120":[63],"127":[63],"136":[63],"145":[63],"155":[63],"165":[63]},"packages/cli/src/mfa/totp.service.ts":{"6":[63],"10":[63],"26":[63],"38":[63]},"packages/cli/src/services/email-change.service.ts":{"20":[63],"29":[63],"43":[63],"74":[63],"112":[63]},"localhost-37935/assets/index-BoK1c_f3.js":{"3":[63]},"localhost-37935/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[63],"9":[63],"10":[63],"19":[63],"23":[63],"29":[63],"33":[63],"34":[63]},"packages/frontend/@n8n/rest-api-client/src/api/mfa.ts":{"4":[86,124],"8":[86,124],"14":[86,124],"21":[86,124],"33":[86,124,63],"37":[86,124]},"packages/frontend/editor-ui/src/features/core/auth/components/PromptMfaCodeModal.vue":{"42":[63],"43":[63],"46":[63],"53":[63],"82":[63],"92":[63],"99":[63],"110":[63],"123":[63],"157":[63],"170":[63],"192":[63],"201":[63]},"packages/frontend/editor-ui/src/features/core/auth/modals.ts":{"14":[86,124],"19":[86,124],"24":[86,124],"29":[86,124,63]},"packages/frontend/editor-ui/src/features/core/auth/views/MfaView.vue":{"63":[63],"86":[63],"107":[63],"116":[63],"117":[63],"129":[63],"155":[63],"164":[63],"189":[63],"194":[63],"204":[63],"225":[63]},"localhost-45803/assets/verified-Pt0guxqN.js":{"8":[152,180,183,116]},"packages/@n8n/db/src/repositories/test-run.repository.ee.ts":{"18":[69],"22":[69],"45":[69],"53":[69],"57":[69],"62":[69],"71":[69],"82":[69],"89":[69],"97":[69],"105":[69],"117":[69],"140":[69],"153":[69],"165":[69],"173":[69],"185":[69],"200":[69],"210":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/OpenAi.node.ts":{"12":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/helpers/binary-data.ts":{"11":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/helpers/description.ts":{"3":[69],"20":[69],"38":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/helpers/polling.ts":{"4":[69],"34":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/helpers/utils.ts":{"17":[69],"27":[69],"39":[69],"50":[69],"58":[69],"66":[69],"88":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/methods/listSearch.ts":{"16":[69],"39":[69],"48":[69],"49":[69],"52":[69],"66":[69],"72":[69],"78":[69],"85":[69],"91":[69],"95":[69],"98":[69],"102":[69],"127":[69],"132":[69],"136":[69],"179":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/methods/loadOptions.ts":{"5":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/transport/index.ts":{"15":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/OpenAiV1.node.ts":{"22":[69],"82":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/assistant/create.operation.ts":{"176":[69],"185":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/assistant/deleteAssistant.operation.ts":{"18":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/assistant/list.operation.ts":{"25":[69],"62":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/assistant/message.operation.ts":{"158":[69],"165":[69],"224":[69],"231":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/assistant/update.operation.ts":{"120":[69],"126":[69],"132":[69],"207":[69],"213":[69],"214":[69],"217":[69],"223":[69],"224":[69],"228":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/audio/generate.operation.ts":{"134":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/audio/transcribe.operation.ts":{"58":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/audio/translate.operation.ts":{"50":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/descriptions.ts":{"5":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/file/deleteFile.operation.ts":{"51":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/file/list.operation.ts":{"53":[69],"63":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/file/upload.operation.ts":{"57":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/image/analyze.operation.ts":{"131":[69],"158":[69],"172":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/image/generate.operation.ts":{"255":[69],"291":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/router.ts":{"16":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/text/classify.operation.ts":{"53":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/text/message.operation.ts":{"240":[69],"244":[69],"360":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/OpenAiV2.node.ts":{"23":[69],"92":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/audio/generate.operation.ts":{"134":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/audio/transcribe.operation.ts":{"58":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/audio/translate.operation.ts":{"50":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/conversation/create.operation.ts":{"84":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/conversation/get.operation.ts":{"27":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/conversation/remove.operation.ts":{"27":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/conversation/update.operation.ts":{"36":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/descriptions.ts":{"5":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/file/deleteFile.operation.ts":{"51":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/file/list.operation.ts":{"62":[69],"72":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/file/upload.operation.ts":{"65":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/image/analyze.operation.ts":{"133":[69],"157":[69],"169":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/image/edit.operation.ts":{"584":[69],"618":[69],"695":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/image/generate.operation.ts":{"73":[69],"118":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/router.ts":{"17":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/text/classify.operation.ts":{"58":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/text/helpers/responses.ts":{"16":[69],"18":[69],"21":[69],"24":[69],"27":[69],"33":[69],"108":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/text/response.operation.ts":{"584":[69],"588":[69],"630":[69],"633":[69],"653":[69],"660":[69],"728":[69],"730":[69],"747":[69]},"packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/video/generate.operation.ts":{"92":[69],"132":[69],"135":[69]},"packages/cli/src/evaluation.ee/test-runs.controller.ee.ts":{"24":[69],"33":[69],"56":[69],"80":[69],"86":[69],"87":[69],"98":[69],"111":[69],"124":[69],"139":[69],"148":[69],"162":[69],"181":[69],"203":[69]},"localhost-45845/assets/verified-Pt0guxqN.js":{"8":[69]},"packages/frontend/editor-ui/src/app/stores/workflows.ee.store.ts":{"13":[86,124,47,195,196,69,81],"18":[86,124,47,69],"19":[86,124,47,69],"34":[86,124,196],"43":[86,124,196],"49":[86,124,196]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/composables/useWorkflowEvaluationState.ts":{"25":[69],"26":[69],"51":[69]},"packages/frontend/editor-ui/src/features/resolvers/composables/useCredentialResolvers.ts":{"26":[86,124,47,69],"38":[86,124],"51":[86,124],"59":[86,124],"109":[86,124],"111":[86,124],"120":[86,124]},"packages/frontend/editor-ui/src/features/workflows/components/WorkflowSettings/RedactionMembersModal.vue":{"9":[86,124,47,69],"24":[86,124,47,69],"26":[86,124,47,69],"41":[86,124,47,69],"48":[86,124],"49":[86,124],"56":[86,124],"59":[86,124],"65":[86,124],"69":[86,124]},"packages/frontend/editor-ui/src/features/workflows/components/WorkflowSettings/WorkflowSettings.vue":{"74":[86,124,47,69],"160":[86,124],"164":[86,124],"167":[86,124],"175":[86,124],"178":[86,124],"182":[86,124],"190":[86,124],"216":[86,124,47,69],"223":[86,124,47,69],"226":[86,124,47,69],"229":[86,124,47,69],"230":[86,124,47,69],"231":[86,124,47,69],"232":[86,124,47,69],"235":[86,124,47,69],"240":[86,124,47,69],"242":[86,124,47],"244":[86,124,47],"250":[86,124,47,69],"254":[86,124,47,69],"256":[86,124,47,69],"260":[86,124,47,69],"265":[86,124,47,69],"280":[86,124,47,69],"284":[86,124,47,69],"288":[86,124,47,69],"289":[86,124,47,69],"293":[86,124],"297":[86,124,47,69],"301":[86,124],"316":[86,124,47,69],"321":[86,124],"332":[86,124,47,69],"336":[86,124,47],"348":[86,124,47,69],"352":[86,124,47],"363":[86,124,47],"374":[86,124],"378":[86,124],"382":[86,124,47,69],"384":[86,124,47,69],"389":[86,124,47,69],"393":[86,124,47,69],"404":[86,124,47,69],"418":[86,124,47,69],"421":[86,124],"427":[86,124,47],"434":[86,124],"443":[86,124,47,69],"473":[86,124,47,69],"497":[86,124,47,69],"521":[86,124,47,69],"544":[86,124,47,69],"567":[86,124,47,69],"594":[86,124,47,69],"600":[86,124],"618":[86,124],"624":[86,124],"631":[86,124],"635":[86,124],"638":[86,124],"650":[86,124,47,69],"661":[86,124],"674":[86,124,47],"760":[86,124,47],"799":[86,124],"809":[86,124],"813":[86,124],"817":[86,124],"826":[86,124],"838":[86,124,47,69],"877":[86,124],"965":[86,124],"983":[86,124],"995":[86,124,47],"999":[86,124,47,69],"1014":[86,124,47,69],"1022":[86,124,47,69],"1025":[86,124,47,69],"1033":[86,124,47,69],"1036":[86,124,47,69],"1040":[86,124,47,69],"1051":[86,124,47,69],"1052":[86,124,47,69],"1054":[86,124],"1056":[86,124,47,69],"1061":[86,124,47,69],"1071":[86,124,47,69],"1073":[86,124,47,69],"1078":[86,124,47,69],"1085":[86,124],"1094":[86,124],"1095":[86,124],"1097":[86,124],"1099":[86,124],"1104":[86,124],"1116":[86,124],"1118":[86,124],"1125":[86,124],"1152":[86,124,47,69],"1153":[86,124,47,69],"1155":[86,124],"1157":[86,124,47,69],"1163":[86,124,47,69],"1174":[86,124,47,69],"1176":[86,124,47,69],"1187":[86,124],"1192":[86,124],"1194":[86,124],"1199":[86,124],"1212":[86,124,47,69],"1214":[86,124],"1216":[86,124,47,69],"1221":[86,124,47,69],"1228":[86,124,47,69],"1230":[86,124,47,69],"1241":[86,124,47,69],"1243":[86,124],"1245":[86,124,47,69],"1250":[86,124,47,69],"1257":[86,124,47,69],"1259":[86,124,47,69],"1270":[86,124,47,69],"1272":[86,124],"1274":[86,124,47,69],"1279":[86,124,47,69],"1286":[86,124,47,69],"1288":[86,124,47,69],"1299":[86,124,47,69],"1301":[86,124],"1303":[86,124,47,69],"1308":[86,124,47,69],"1315":[86,124,47,69],"1317":[86,124,47,69],"1328":[86,124,47,69],"1330":[86,124],"1332":[86,124,47,69],"1337":[86,124,47,69],"1344":[86,124,47,69],"1346":[86,124,47,69],"1357":[86,124,47,69],"1360":[86,124,47,69],"1383":[86,124,69],"1387":[86,124],"1395":[86,124],"1397":[86,124,47,69],"1407":[86,124,47,69],"1413":[86,124,47],"1421":[86,124],"1424":[86,124,47,69],"1440":[86,124,47,69],"1442":[86,124,47,69],"1453":[86,124],"1455":[86,124],"1456":[86,124],"1464":[86,124,47,69],"1489":[86,124,69],"1493":[86,124],"1501":[86,124],"1503":[86,124,47,69],"1513":[86,124,47,69],"1522":[86,124,47],"1530":[86,124],"1538":[86,124,47,69],"1552":[86,124,47,69],"1554":[86,124,47,69],"1567":[86,124,47,69],"1569":[86,124],"1571":[86,124,47,69],"1576":[86,124,47,69],"1592":[86,124],"1593":[86,124],"1595":[86,124],"1597":[86,124],"1602":[86,124],"1606":[86,124],"1608":[86,124],"1612":[86,124],"1617":[86,124],"1619":[86,124],"1623":[86,124],"1628":[86,124],"1630":[86,124],"1636":[86,124],"1637":[86,124],"1640":[86,124],"1642":[86,124],"1648":[86,124],"1650":[86,124],"1652":[86,124],"1666":[86,124,47,69],"1669":[86,124],"1671":[86,124,47,69],"1677":[86,124,47,69],"1685":[86,124,47,69],"1687":[86,124,47,69],"1698":[86,124,47,69],"1718":[86,124],"1737":[86,124],"1768":[86,124],"1785":[86,124],"1789":[86,124,47,69],"1803":[86,124]},"packages/nodes-base/nodes/E2eTest/E2eTest.node.ts":{"175":[78,141],"180":[78,141],"188":[78,141],"201":[78,141],"207":[78,141]},"packages/nodes-base/nodes/E2eTest/mock.ts":{"66":[78,141]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ResourceMapper/MappingFields.vue":{"49":[86,124,141],"74":[86,124,141],"83":[86,124,141],"85":[86,124,141],"86":[86,124,141],"101":[86,124,141],"104":[86,124,141],"117":[86,124,141],"118":[86,124,141],"121":[86,124,141],"122":[86,124,141],"131":[86,124,141],"132":[86,124,141],"134":[86,124,141],"161":[86,124,141],"164":[86,124,141],"178":[86,124,141],"182":[86,124,141],"186":[86,124,141],"196":[86,124,141],"204":[86,124,141],"214":[86,124,141],"238":[86,124,141],"252":[86,124,141],"267":[86,124,141],"280":[86,124,141],"284":[86,124,141],"288":[86,124,141],"292":[86,124],"296":[86,124,141],"315":[86,124,141],"328":[86,124,141],"331":[86,124],"334":[86,124],"346":[86,124],"362":[86,124],"366":[86,124,141],"397":[86,124,141],"433":[86,124],"442":[86,124,141]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ResourceMapper/MappingModeSelect.vue":{"20":[86,124,78,141],"54":[86,124,78,141],"55":[86,124],"61":[86,124,78,141],"89":[86,124],"94":[86,124],"103":[86,124,78,141],"113":[86,124,78,141],"121":[86,124,78,141],"123":[86,124,78,141],"128":[86,124,78,141],"140":[86,124,78,141],"150":[86,124,78,141],"153":[86,124,78,141]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ResourceMapper/MatchingColumnsSelect.vue":{"27":[86,124,141],"39":[86,124,141],"50":[86,124,141],"51":[86,124,141],"62":[86,124,141],"63":[86,124,141],"69":[86,124,141],"84":[86,124,141],"103":[86,124,141],"117":[86,124,141],"130":[86,124,141],"138":[86,124],"147":[86,124],"156":[86,124,141],"169":[86,124,141],"182":[86,124,141],"191":[86,124,141],"200":[86,124,141],"202":[86,124,141],"206":[86,124,141],"211":[86,124,141]},"packages/frontend/editor-ui/src/features/ndv/parameters/composables/useNodeSpecificationValues.ts":{"5":[86,124,78,141],"6":[86,124,78,141],"10":[86,124,78,141],"16":[86,124,141],"20":[86,124,78,141],"24":[86,124,141]},"packages/@n8n/permissions/src/schemas.ee.ts":{"23":[86,124,99],"50":[86,124,99],"73":[86,124,99]},"localhost-37575/assets/index-BoK1c_f3.js":{"3":[99]},"localhost-37575/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[99],"9":[99],"10":[99],"19":[99],"23":[99],"29":[99],"33":[99],"34":[99]},"packages/frontend/@n8n/design-system/src/components/N8nUserStack/UserStack.vue":{"11":[1,86,124,99],"26":[86,124],"28":[86,124],"40":[86,124],"44":[1,86,124,99],"54":[1,86,124,99],"60":[1,86,124,99],"64":[86,124],"67":[1,86,124,99],"72":[1,86,124,99],"75":[1,86,124,99],"92":[86,124],"94":[86,124],"96":[86,124],"103":[86,124]},"packages/core/src/execution-engine/node-execution-context/hook-context.ts":{"21":[100],"34":[100],"38":[100],"42":[100],"54":[100],"61":[100]},"packages/frontend/@n8n/design-system/src/utils/markdown.ts":{"20":[86,124],"43":[86,124,100],"44":[86,124]},"packages/frontend/editor-ui/src/app/components/CollectionWorkflowCard.vue":{"12":[100],"13":[100],"17":[100]},"packages/frontend/editor-ui/src/app/views/WorkflowOnboardingView.vue":{"17":[100],"55":[100]},"packages/frontend/editor-ui/src/features/workflows/templates/components/TemplateFilters.vue":{"15":[100],"34":[100],"38":[100],"43":[100],"44":[100],"52":[100],"60":[100],"68":[100],"69":[100],"80":[100],"81":[100],"91":[100],"108":[100],"118":[100]},"packages/frontend/editor-ui/src/features/workflows/templates/components/TemplatesInfoCard.vue":{"21":[100],"29":[100]},"packages/frontend/editor-ui/src/features/workflows/templates/components/TemplatesInfoCarousel.vue":{"11":[100],"37":[100],"64":[100],"65":[100],"67":[100],"73":[100],"74":[100],"76":[100],"82":[100],"95":[100],"101":[100],"112":[100],"113":[100],"115":[100]},"packages/frontend/editor-ui/src/features/workflows/templates/recommendations/components/RecommendedTemplateCard.vue":{"17":[100],"35":[100],"38":[100],"43":[100],"46":[100],"71":[100],"82":[100],"101":[100],"109":[100],"121":[100],"127":[100],"137":[100],"148":[100],"177":[100],"187":[100]},"packages/frontend/editor-ui/src/features/workflows/templates/recommendations/recommendedTemplates.store.ts":{"5":[100]},"packages/frontend/editor-ui/src/features/workflows/templates/views/TemplatesSearchView.vue":{"51":[100],"54":[100],"61":[100],"65":[100],"69":[100],"73":[100],"87":[100],"105":[100],"106":[100],"110":[100],"115":[100],"125":[100],"129":[100],"137":[100],"149":[100],"156":[100],"166":[100],"173":[100],"178":[100],"192":[100],"196":[100],"220":[100],"258":[100],"277":[100],"285":[100],"297":[100],"310":[100],"319":[100],"330":[100],"379":[100],"386":[100],"410":[100]},"packages/frontend/editor-ui/src/features/workflows/templates/views/TemplatesWorkflowView.vue":{"43":[100],"47":[100],"49":[100],"81":[100],"91":[100],"92":[100],"103":[100],"125":[100],"149":[100],"156":[100],"169":[100],"195":[100],"201":[100]},"packages/@n8n/nodes-langchain/nodes/chains/ChainLLM/ChainLlm.node.ts":{"27":[85,139],"71":[85,139],"91":[85,139],"97":[85,139],"128":[85,139],"146":[85,139]},"packages/@n8n/nodes-langchain/nodes/chains/ChainLLM/methods/chainExecutor.ts":{"20":[85,139],"35":[85,139],"46":[85,139],"61":[85,139],"70":[85,139],"96":[85,139],"119":[85,139],"127":[85,139],"141":[85,139]},"packages/@n8n/nodes-langchain/nodes/chains/ChainLLM/methods/config.ts":{"21":[85,139]},"packages/@n8n/nodes-langchain/nodes/chains/ChainLLM/methods/imageUtils.ts":{"15":[85,139],"27":[85,139],"82":[85,139]},"packages/@n8n/nodes-langchain/nodes/chains/ChainLLM/methods/index.ts":{"1":[85,139]},"packages/@n8n/nodes-langchain/nodes/chains/ChainLLM/methods/processItem.ts":{"11":[85,139],"33":[85,139]},"packages/@n8n/nodes-langchain/nodes/chains/ChainLLM/methods/promptUtils.ts":{"23":[85,139],"34":[85,139],"44":[85,139],"50":[85,139],"66":[85,139],"75":[85,139],"120":[85,139],"149":[85,139],"153":[85,139],"158":[85,139],"159":[85,139],"168":[85,139]},"packages/@n8n/nodes-langchain/nodes/chains/ChainLLM/methods/responseFormatter.ts":{"6":[85,139]},"packages/@n8n/nodes-langchain/utils/output_parsers/parserInput.ts":{"10":[85,139]},"localhost-44893/assets/index-BoK1c_f3.js":{"3":[85,154,172,117]},"localhost-44893/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[85,154,172,117],"9":[85,154,172,117],"10":[85,154,172,117],"19":[85,154,172,117],"23":[85,154,172,117],"29":[85,154,172,117],"33":[85,154,172,117],"34":[85,154,172,117]},"localhost-44893/assets/verified-Pt0guxqN.js":{"8":[85]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/chat-memory-manager.svg":{"11":[85]},"packages/@n8n/api-types/src/dto/workflows/base-workflow-public.dto.ts":{"60":[86,90,124],"110":[86,124],"111":[90],"136":[86,124],"137":[90],"166":[86,124],"168":[90]},"packages/@n8n/api-types/src/dto/workflows/workflow-public.dto.ts":{"29":[86,124],"30":[90],"37":[86,124],"38":[90]},"packages/cli/src/metrics/prometheus/token-exchange-metrics.service.ts":{"21":[90],"26":[90],"30":[90],"71":[90],"75":[90],"80":[90],"84":[90],"89":[90],"93":[90]},"packages/cli/src/modules/token-exchange/controllers/embed-auth.controller.ts":{"21":[90],"36":[90],"54":[90],"65":[90]},"packages/cli/src/modules/token-exchange/controllers/token-exchange.controller.ts":{"21":[90],"42":[90]},"packages/cli/src/modules/token-exchange/database/repositories/token-exchange-jti.repository.ts":{"14":[90],"18":[90],"31":[90],"32":[90],"80":[90],"81":[90]},"packages/cli/src/modules/token-exchange/database/repositories/trusted-key.repository.ts":{"8":[90],"12":[90],"16":[90]},"packages/cli/src/modules/token-exchange/services/identity-resolution.service.ts":{"32":[90],"36":[90],"44":[90],"57":[90],"72":[90],"96":[90],"158":[90],"176":[90],"209":[90],"223":[90],"266":[90],"320":[90],"366":[90]},"packages/cli/src/modules/token-exchange/services/jti-store.service.ts":{"25":[90],"34":[90]},"packages/cli/src/modules/token-exchange/services/scoped-jwt.strategy.ts":{"17":[90],"22":[90],"67":[90],"74":[90],"97":[90],"104":[90]},"packages/cli/src/modules/token-exchange/services/token-exchange.service.ts":{"34":[90],"56":[90],"142":[90],"156":[90]},"packages/cli/src/modules/token-exchange/services/trusted-key.service.ts":{"72":[90],"95":[90],"102":[90],"117":[90],"169":[90],"177":[90],"181":[90],"187":[90],"213":[90],"217":[90],"242":[90],"251":[90],"252":[90],"254":[90],"255":[90],"300":[90],"325":[90],"340":[90],"366":[90],"370":[90],"373":[90],"395":[90],"412":[90],"431":[90],"447":[90],"459":[90],"468":[90],"508":[90],"553":[90]},"packages/cli/src/modules/token-exchange/token-exchange.errors.ts":{"10":[90],"23":[90]},"packages/cli/src/modules/token-exchange/token-exchange.schemas.ts":{"29":[90]},"packages/cli/src/public-api/v1/controllers/workflows.public.controller.ts":{"96":[90],"102":[90],"103":[90],"106":[90],"115":[90],"125":[90],"137":[90],"147":[90],"163":[90],"178":[90],"189":[90],"199":[90],"207":[90],"219":[90],"223":[90],"235":[90],"278":[90],"314":[90],"348":[90],"401":[90],"450":[90],"476":[90],"499":[90],"521":[90],"535":[90],"564":[90],"574":[90],"583":[90],"594":[90],"616":[90],"642":[90],"670":[90],"688":[90],"706":[90],"725":[90],"752":[90],"795":[90],"823":[90],"831":[90],"852":[90]},"packages/cli/src/public-api/v1/shared/project.mapper.ts":{"5":[90],"9":[90]},"packages/cli/src/utils/validate-redirect-url.ts":{"8":[89,90]},"packages/@n8n/api-types/src/dto/data-table/delete-data-table-rows.dto.ts":{"7":[86,124,24],"52":[86,124,24]},"packages/@n8n/api-types/src/dto/data-table/update-data-table-row.dto.ts":{"10":[86,124,24],"18":[86,124,24]},"packages/cli/src/modules/data-table/data-table-permissions.ts":{"12":[24]},"localhost-43789/assets/index-BoK1c_f3.js":{"3":[24,139,140,78,80]},"localhost-43789/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[24,139,140,78,80],"9":[24,139,140,78,80],"10":[24,139,140,78,80],"19":[24,139,140,78,80],"23":[24,139,140,78,80],"29":[24,139,140,78,80],"33":[24,139,140,78,80],"34":[24,139,140,78,80]},"packages/frontend/editor-ui/src/features/core/dataTable/components/dataGrid/ElDatePickerCellEditor.vue":{"7":[24],"24":[24],"30":[24],"36":[24],"43":[24],"45":[24]},"packages/frontend/editor-ui/src/features/core/dataTable/components/dataGrid/NullEmptyCellRenderer.vue":{"2":[24]},"packages/frontend/editor-ui/src/features/core/dataTable/composables/useDatePickerCommon.ts":{"11":[24],"17":[24],"22":[24],"35":[24],"60":[24],"67":[24],"84":[24]},"packages/frontend/editor-ui/src/features/core/dataTable/utils/typeUtils.ts":{"13":[24],"49":[24]},"packages/frontend/editor-ui/src/features/core/dataTable/utils.ts":{"1":[86,124,24],"6":[86,124,24]},"packages/core/src/utils/hitl-callback-reference.ts":{"31":[172],"40":[172],"52":[172],"61":[172],"73":[172],"77":[172],"91":[172],"110":[172],"124":[172]},"packages/core/src/utils/signature-helpers.ts":{"9":[172],"21":[172],"28":[172],"43":[172]},"packages/workflow/src/safe-regex.ts":{"49":[172],"62":[172],"66":[172],"76":[172],"89":[172],"97":[172],"104":[172],"105":[172],"106":[172],"108":[172],"110":[172],"115":[172],"132":[172],"143":[172],"150":[172],"157":[172],"165":[172],"172":[172],"182":[172],"187":[172],"191":[172],"198":[172],"199":[172],"200":[172],"202":[172],"203":[172]},"localhost-43789/assets/verified-Pt0guxqN.js":{"8":[139,80]},"packages/frontend/editor-ui/src/features/credentials/composables/oauthCallback.ts":{"32":[86,124,78],"47":[86,124],"62":[86,124,78],"69":[86,124],"81":[86,124],"133":[86,124,78],"141":[86,124],"147":[86,124],"160":[86,124],"165":[86,124],"171":[86],"175":[86],"192":[86],"197":[86],"205":[86]},"packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreZep/VectorStoreZep.node.ts":{"81":[86],"108":[86]},"localhost-44717/assets/index-BoK1c_f3.js":{"3":[31]},"localhost-44717/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[31],"9":[31],"10":[31],"19":[31],"23":[31],"29":[31],"33":[31],"34":[31]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/at--outline-16.svg":{"9":[86,124,31]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/crosshair--outline-16.svg":{"9":[86,124,31,45]},"packages/frontend/editor-ui/src/features/ai/assistant-at-mentions/AssistantAtMentionPicker.vue":{"46":[31],"87":[31],"89":[31],"92":[31],"94":[31],"95":[31],"98":[31],"103":[31],"104":[31],"105":[31],"112":[31],"116":[31],"119":[31],"161":[31],"163":[31],"166":[31],"169":[31],"171":[31],"174":[31],"215":[31],"219":[31],"223":[31],"260":[31],"269":[31],"270":[31],"280":[31],"301":[31],"302":[31],"315":[31],"333":[31],"349":[31],"367":[31],"370":[31],"422":[31],"446":[31],"479":[31],"496":[31],"516":[31],"522":[31],"530":[31],"536":[31]},"packages/frontend/editor-ui/src/features/ai/assistant-at-mentions/AssistantMentionBreadcrumbs.vue":{"6":[31],"20":[31],"21":[31],"22":[31]},"packages/frontend/editor-ui/src/features/ai/assistant-at-mentions/composables/useArtifactMentionIndex.ts":{"52":[31],"56":[31],"57":[31],"63":[31],"65":[31],"68":[31],"70":[31],"71":[31],"91":[31],"94":[31],"95":[31],"105":[31],"107":[31],"120":[31],"129":[31],"135":[31],"143":[31],"149":[31],"187":[31],"197":[31],"215":[31],"252":[31],"257":[31],"263":[31],"270":[31],"273":[31],"277":[31],"295":[31],"296":[31],"305":[31],"327":[31],"333":[31]},"packages/frontend/editor-ui/src/features/ai/assistant-at-mentions/composables/useAssistantMentionSources.ts":{"24":[31],"32":[31],"39":[31],"54":[31],"62":[31],"73":[31],"85":[31],"100":[31],"105":[31],"134":[31],"162":[31],"179":[31],"181":[31],"184":[31],"189":[31],"193":[31],"194":[31],"200":[31],"210":[31],"221":[31],"227":[31],"258":[31],"269":[31],"274":[31],"308":[31],"325":[31],"333":[31]},"packages/frontend/editor-ui/src/features/ai/assistant-at-mentions/utils/buildMentionItems.ts":{"17":[31],"42":[31],"102":[31],"116":[31],"117":[31],"118":[31],"141":[31],"156":[31]},"packages/frontend/editor-ui/src/features/ai/assistant-at-mentions/utils/searchMentionItems.ts":{"14":[31],"24":[31],"37":[31],"47":[31]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/NodeChip.vue":{"10":[31],"59":[31]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/NodesAttachmentChips.vue":{"33":[31],"46":[31],"75":[31],"79":[31],"87":[31],"90":[31],"242":[31],"247":[31],"284":[31],"286":[31],"291":[31],"309":[31],"311":[31],"316":[31]},"packages/@n8n/api-types/src/agents/agent-skill.schema.ts":{"16":[86,124],"23":[86,124],"39":[86,124]},"packages/@n8n/api-types/src/agents/child-trace.ts":{"4":[86,124],"10":[86,124],"23":[86,124],"32":[86,124],"37":[86,124],"47":[86,124],"60":[86,124]},"packages/@n8n/api-types/src/agents/inline-agent-config.schema.ts":{"34":[86,124],"58":[86,124],"60":[86,124],"88":[86,124],"139":[86,124]},"packages/@n8n/api-types/src/agents/provider-capabilities.ts":{"186":[86,124],"210":[86,124],"218":[86,124],"246":[86,124]},"packages/@n8n/api-types/src/agents/rich-card.schema.ts":{"74":[86,124],"137":[86,124]},"packages/@n8n/api-types/src/agents/skills.schema.ts":{"20":[86,124],"21":[86,124],"24":[86,124]},"packages/@n8n/api-types/src/agents/slack/manager-credential.ts":{"4":[86,124]},"packages/@n8n/api-types/src/dto/ai/ai-ask-request.dto.ts":{"15":[86,124],"30":[86,124]},"packages/@n8n/api-types/src/dto/data-table/download-data-table-csv-query.dto.ts":{"8":[86,124]},"packages/@n8n/api-types/src/dto/data-table/upsert-data-table-row.dto.ts":{"10":[86,124],"18":[86,124]},"packages/@n8n/api-types/src/dto/evaluations/evaluation-config.dto.ts":{"37":[86,124]},"packages/@n8n/api-types/src/dto/insights/insights-summary-public.dto.ts":{"28":[86,124]},"packages/@n8n/api-types/src/dto/promotions/promotable-resource.dto.ts":{"82":[86,124]},"packages/@n8n/api-types/src/dto/promotions/promotion-binding-preflight.dto.ts":{"45":[86,124],"49":[86,124]},"packages/@n8n/api-types/src/dto/trusted-source/create-trusted-source.dto.ts":{"12":[86,124],"17":[86,124],"40":[86,124]},"packages/@n8n/api-types/src/dto/type-availability-policies/replace-attachments.dto.ts":{"21":[86,124],"23":[86,124],"28":[86,124],"30":[86,124]},"packages/@n8n/api-types/src/model-priority.ts":{"6":[86,124],"7":[86,124],"15":[86,124],"18":[86,124],"20":[86,124],"21":[86,124]},"packages/@n8n/api-types/src/schemas/ai-preference.schema.ts":{"39":[86,124],"48":[86,124]},"packages/@n8n/api-types/src/schemas/data-table.schema.ts":{"63":[86,124]},"packages/@n8n/api-types/src/schemas/insights.schema.ts":{"75":[86,124],"93":[86,124]},"packages/@n8n/api-types/src/schemas/instance-ai-setup-credential-selection.ts":{"16":[86,124],"21":[86,124],"25":[86,124],"44":[86,124]},"packages/@n8n/api-types/src/schemas/llm-step-display.ts":{"101":[86,124],"105":[86,124],"113":[86,124],"121":[86,124],"128":[86,124],"166":[86,124],"176":[86,124],"235":[86,124],"250":[86,124],"267":[86,124],"269":[86,124],"283":[86,124],"287":[86,124],"300":[86,124],"320":[86,124],"335":[86,124],"350":[86,124],"382":[86,124],"400":[86,124],"410":[86,124],"419":[86,124],"437":[86,124],"443":[86,124],"491":[86,124],"495":[86,124],"516":[86,124],"525":[86,124],"534":[86,124],"549":[86,124],"579":[86,124],"594":[86,124],"624":[86,124],"677":[86,124],"687":[86,124],"689":[86,124],"698":[86,124],"700":[86,124],"707":[86,124],"712":[86,124],"716":[86,124],"728":[86,124],"737":[86,124],"745":[86,124],"750":[86,124],"763":[86,124],"767":[86,124],"777":[86,124],"793":[86,124],"825":[86,124],"829":[86,124],"862":[86,124],"865":[86,124],"895":[86,124],"897":[86,124],"907":[86,124],"925":[86,124],"948":[86,124],"987":[86,124],"1024":[86,124],"1058":[86,124],"1068":[86,124],"1098":[86,124],"1107":[86,124],"1114":[86,124],"1123":[86,124],"1127":[86,124],"1132":[86,124],"1156":[86,124],"1157":[86,124]},"packages/@n8n/api-types/src/schemas/mcp.schema.ts":{"66":[86,124],"67":[86,124],"70":[86,124],"71":[86,124]},"packages/@n8n/api-types/src/schemas/project.schema.ts":{"25":[86,124],"29":[86,124],"31":[86,124]},"packages/@n8n/api-types/src/schemas/source-controlled-file.schema.ts":{"33":[86,124]},"packages/@n8n/api-types/src/schemas/thread-title-search.schema.ts":{"12":[86,124]},"packages/@n8n/api-types/src/workflow-publish-blocked-details.ts":{"19":[86,124]},"packages/@n8n/codemirror-lang-sql/src/complete.ts":{"192":[86,124,202],"193":[86,124,202]},"packages/@n8n/errors/src/application.error.ts":{"21":[86,124]},"packages/@n8n/expression-runtime/src/extensions/array-extensions.ts":{"14":[86,124],"19":[86,124],"25":[86,124],"29":[86,124],"33":[86,124],"37":[86,124],"47":[86,124],"51":[86,124],"58":[86,124],"61":[86,124],"62":[86,124],"77":[86,124],"82":[86,124],"83":[86,124],"85":[86,124],"93":[86,124],"96":[86,124],"97":[86,124],"102":[86,124],"105":[86,124],"116":[86,124],"120":[86,124],"132":[86,124],"136":[86,124],"148":[86,124],"159":[86,124],"161":[86,124],"166":[86,124],"174":[86,124],"181":[86,124],"195":[86,124],"207":[86,124],"213":[86,124],"219":[86,124],"229":[86,124],"249":[86,124],"254":[86,124],"286":[86,124],"317":[86,124],"324":[86,124],"331":[86,124],"340":[86,124],"347":[86,124],"356":[86,124],"361":[86,124],"368":[86,124],"372":[86,124],"376":[86,124],"380":[86,124],"384":[86,124],"388":[86,124]},"packages/@n8n/expression-runtime/src/extensions/boolean-extensions.ts":{"3":[86,124],"7":[86,124],"11":[86,124]},"packages/@n8n/expression-runtime/src/extensions/date-extensions.ts":{"78":[86,124],"82":[86,124],"92":[86,124],"97":[86,124],"107":[86,124],"113":[86,124],"138":[86,124],"146":[86,124],"169":[86,124],"176":[86,124],"188":[86,124],"193":[86,124],"214":[86,124],"235":[86,124],"244":[86,124],"249":[86,124],"263":[86,124],"268":[86,124],"277":[86,124],"282":[86,124],"286":[86,124]},"packages/@n8n/expression-runtime/src/extensions/expression-extension-error.ts":{"4":[86,124]},"packages/@n8n/expression-runtime/src/extensions/extend.ts":{"13":[86,124],"17":[86,124],"36":[86,124],"79":[86,124],"138":[86,124],"146":[86,124],"154":[86,124],"174":[86,124],"190":[86,124]},"packages/@n8n/expression-runtime/src/extensions/number-extensions.ts":{"10":[86,124],"23":[86,124],"30":[86,124],"37":[86,124],"41":[86,124],"45":[86,124],"49":[86,124],"53":[86,124],"58":[86,124],"62":[86,124],"66":[86,124],"71":[86,124]},"packages/@n8n/expression-runtime/src/extensions/object-extensions.ts":{"5":[86,124],"9":[86,124],"13":[86,124],"17":[86,124],"21":[86,124],"26":[86,124],"37":[86,124],"52":[86,124],"69":[86,124],"89":[86,124],"92":[86,124],"95":[86,124],"97":[86,124],"101":[86,124],"105":[86,124],"109":[86,124],"113":[86,124],"117":[86,124]},"packages/@n8n/expression-runtime/src/extensions/string-extensions.ts":{"48":[86,124],"87":[86,124],"118":[86,124],"122":[86,124],"126":[86,124],"130":[86,124],"134":[86,124],"176":[86,124],"180":[86,124],"193":[86,124],"215":[86,124],"223":[86,124],"231":[86,124],"242":[86,124],"256":[86,124],"266":[86,124],"273":[86,124],"279":[86,124],"283":[86,124],"287":[86,124],"298":[86,124],"302":[86,124],"306":[86,124],"329":[86,124],"336":[86,124],"344":[86,124],"362":[86,124],"370":[86,124],"374":[86,124],"383":[86,124],"423":[86,124],"434":[86,124],"440":[86,124],"444":[86,124]},"packages/@n8n/expression-runtime/src/extensions/utils.ts":{"7":[86,124],"24":[86,124],"37":[86,124]},"packages/@n8n/expression-runtime/src/observability/noop-provider.ts":{"4":[86,124],"5":[86,124],"6":[86,124],"7":[86,124],"11":[86,124],"12":[86,124],"13":[86,124],"17":[86,124],"21":[86,124],"22":[86,124],"23":[86,124],"24":[86,124]},"packages/@n8n/expression-runtime/src/pool/idle-scaling-pool.ts":{"20":[86,124],"29":[86,124],"35":[86,124],"45":[86,124],"56":[86,124],"60":[86,124],"74":[86,124],"79":[86,124],"83":[86,124],"84":[86,124],"89":[86,124],"93":[86,124],"96":[86,124],"101":[86,124],"109":[86,124],"117":[86,124],"119":[86,124],"121":[86,124],"126":[86,124],"137":[86,124],"140":[86,124]},"packages/@n8n/expression-runtime/src/types/bridge.ts":{"111":[86,124],"112":[86,124],"113":[86,124],"114":[86,124]},"packages/@n8n/expression-runtime/src/types/evaluator.ts":{"357":[86,124]},"packages/@n8n/expression-runtime/src/types/runtime.ts":{"16":[86,124]},"packages/@n8n/utils/src/is-unknown-array.ts":{"3":[86,124]},"packages/frontend/@n8n/chat/src/components/Button.vue":{"6":[86,124],"19":[86,124],"22":[86,124],"27":[86,124]},"packages/frontend/@n8n/chat/src/components/MessageWithButtons.vue":{"18":[86,124],"21":[86,124],"34":[86,124],"42":[86,124],"50":[86,124],"56":[86,124],"57":[86,124]},"packages/frontend/@n8n/chat/src/utils/utils.ts":{"33":[86,124],"49":[86,124],"82":[86,124]},"packages/frontend/@n8n/design-system/src/components/AskAssistantAvatar/AssistantAvatar.vue":{"10":[86,124]},"packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/BlockMessage.vue":{"19":[86,124],"23":[86,124],"30":[86,124],"31":[86,124]},"packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/ErrorMessage.vue":{"18":[86,124],"19":[86,124],"23":[86,124],"34":[86,124],"35":[86,124]},"packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/RestoreVersionConfirm.vue":{"13":[86,124],"29":[86,124],"49":[86,124],"58":[86,124],"62":[86,124],"64":[86,124],"83":[86,124]},"packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/ToolMessage.vue":{"21":[86,124],"24":[86,124],"31":[86,124],"36":[86,124],"47":[86,124],"57":[86,124],"61":[86,124],"66":[86,124],"69":[86,124],"87":[86,124]},"packages/frontend/@n8n/design-system/src/components/CanvasCollaborationPill/CanvasCollaborationPill.vue":{"13":[86,124],"25":[86,124],"29":[86,124],"35":[86,124],"37":[86,124],"42":[86,124],"44":[86,124],"48":[86,124]},"packages/frontend/@n8n/design-system/src/components/DateRangePicker/DateRangePicker.vue":{"27":[86,124],"42":[86,124],"45":[86,124],"49":[86,124],"50":[86,124],"56":[86,124],"57":[86,124],"65":[86,124],"66":[86,124],"70":[86,124],"75":[86,124],"78":[86,124],"81":[86,124],"82":[86,124],"85":[86,124],"92":[86,124],"95":[86,124],"97":[86,124],"101":[86,124],"117":[86,124]},"packages/frontend/@n8n/design-system/src/components/DateRangePicker/DateRangePickerField.vue":{"15":[86,124],"16":[86,124],"19":[86,124],"24":[86,124],"25":[86,124],"27":[86,124],"33":[86,124],"41":[86,124],"46":[86,124],"48":[86,124],"54":[86,124],"62":[86,124],"69":[86,124],"75":[86,124],"83":[86,124],"88":[86,124],"94":[86,124],"98":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nAiActivityStep/AiActivityStep.vue":{"45":[86,124],"49":[86,124],"52":[86,124],"61":[86,124],"63":[86,124],"65":[86,124],"67":[86,124],"76":[86,124],"90":[86,124],"91":[86,124],"97":[86,124],"99":[86,124],"101":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nAiActivityStepButton/AiActivityStepButton.vue":{"4":[86,124,30],"27":[86,124],"31":[86,124,30],"45":[86,124,30]},"packages/frontend/@n8n/design-system/src/components/N8nAiActivityStepGroup/AiActivityStepGroup.vue":{"37":[86,124],"38":[86,124],"44":[86,124],"46":[86,124],"52":[86,124],"54":[86,124],"64":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nAiActivityStepResultSection/AiActivityStepResultSection.vue":{"2":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nAlert/Alert.vue":{"16":[86,124],"23":[86,124],"37":[86,124],"53":[86,124],"64":[86,124],"70":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nCodeBlock/CodeBlock.vue":{"15":[86,124],"33":[86,124],"44":[86,124],"50":[86,124],"53":[86,124],"60":[86,124],"66":[86,124],"71":[86,124],"89":[86,124],"111":[86,124],"114":[86,124],"132":[86,124],"146":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nCollapsiblePanel/CollapsiblePanel.vue":{"31":[86,124],"44":[86,124],"45":[86,124],"47":[86,124],"55":[86,124],"58":[86,124],"64":[86,124],"77":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nCommandBar/CommandBarItem.vue":{"9":[86,124,216],"21":[86,124,216],"35":[86,124],"42":[86,124,216],"56":[86,124],"58":[86,124],"59":[86,124,216]},"packages/frontend/@n8n/design-system/src/components/N8nContextMenu/ContextMenu.utils.ts":{"3":[86,124],"19":[86,124],"24":[86,124],"27":[86,124],"28":[86,124],"31":[86,124],"35":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nContextMenu/ContextMenu.vue":{"24":[86,124],"36":[86,124],"38":[86,124],"43":[86,124],"47":[86,124],"51":[86,124],"53":[86,124],"57":[86,124],"63":[86,124],"71":[86,124],"74":[86,124],"75":[86,124],"76":[86,124],"85":[86,124],"86":[86,124],"89":[86,124],"92":[86,124],"94":[86,124],"97":[86,124],"100":[86,124],"103":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nContextMenu/ContextMenuBody.vue":{"23":[86,124],"27":[86,124],"35":[86,124],"51":[86,124],"54":[86,124],"57":[86,124],"60":[86,124],"64":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nContextMenu/ContextMenuItem.vue":{"33":[86,124],"53":[86,124],"55":[86,124],"58":[86,124],"60":[86,124],"61":[86,124],"66":[86,124],"69":[86,124],"71":[86,124],"77":[86,124],"84":[86,124],"91":[86,124],"97":[86,124],"101":[86,124],"109":[86,124],"114":[86,124],"121":[86,124],"124":[86,124],"127":[86,124],"142":[86,124],"148":[86,124],"151":[86,124],"154":[86,124],"157":[86,124],"161":[86,124],"175":[86,124],"182":[86,124],"185":[86,124],"188":[86,124],"193":[86,124],"204":[86,124],"211":[86,124],"214":[86,124],"217":[86,124],"222":[86,124],"232":[86,124],"239":[86,124],"242":[86,124],"245":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nContextMenu/ContextMenuItemContent.vue":{"13":[86,124],"24":[86,124],"25":[86,124],"26":[86,124],"28":[86,124],"35":[86,124],"40":[86,124],"52":[86,124],"53":[86,124],"57":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nContextMenu/ContextMenuNodes.vue":{"18":[86,124],"27":[86,124],"29":[86,124],"33":[86,124],"37":[86,124],"38":[86,124],"41":[86,124],"46":[86,124],"52":[86,124],"55":[86,124],"58":[86,124],"61":[86,124],"64":[86,124],"68":[86,124],"78":[86,124],"82":[86,124],"83":[86,124],"84":[86,124],"86":[86,124],"87":[86,124],"90":[86,124],"93":[86,124],"103":[86,124],"105":[86,124],"108":[86,124],"111":[86,124],"114":[86,124],"118":[86,124],"125":[86,124],"126":[86,124],"129":[86,124],"132":[86,124],"136":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nCopyInput/CopyInput.vue":{"31":[86,124],"50":[86,124],"52":[86,124],"57":[86,124],"62":[86,124],"75":[86,124],"80":[86,124],"84":[86,124],"86":[86,124],"95":[86,124],"100":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nEmptyState/EmptyStateIconCards.vue":{"21":[86,124],"23":[86,124],"29":[86,124],"32":[86,124],"36":[86,124],"41":[86,124],"51":[86,124],"53":[86,124],"58":[86,124],"60":[86,124],"66":[86,124],"75":[86,124],"77":[86,124],"84":[86,124],"91":[86,124],"93":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nFloatingWindow/FloatingWindow.vue":{"14":[86,124],"59":[86,124],"68":[86,124],"79":[86,124],"94":[86,124],"99":[86,124],"111":[86,124],"124":[86,124],"133":[86,124],"151":[86,124],"208":[86,124],"218":[86,124],"236":[86,124],"244":[86,124],"262":[86,124],"266":[86,124],"270":[86,124],"274":[86,124],"278":[86,124],"282":[86,124],"286":[86,124],"290":[86,124],"298":[86,124],"306":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nHeaderAction/HeaderAction.vue":{"36":[86,124],"37":[86,124],"43":[86,124],"44":[86,124],"53":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/anthropic.svg":{"13":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/azure.svg":{"9":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/binary.svg":{"8":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/bot-fail.svg":{"12":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/bot-idle.svg":{"12":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/bot-pass.svg":{"12":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/bot-waiting.svg":{"5":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/bot-warning.svg":{"12":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/arrow-corner-down-right--outline-16.svg":{"9":[86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/arrow-from-bracket-right--outline-16.svg":{"9":[86,124,45,216]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/arrows-split--outline-16.svg":{"9":[86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/bell--outline-16.svg":{"9":[86,124,216]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/blocks--outline-16.svg":{"9":[86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/chat-bubbles--outline-16.svg":{"9":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/chevrons-left--outline-16.svg":{"9":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/chevrons-right--outline-16.svg":{"9":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/chevrons-up-down--outline-16.svg":{"9":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/crosshair--solid-16.svg":{"9":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/dots-horizontal-circle--outline-16.svg":{"9":[86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/exclamation-circle--outline-16.svg":{"9":[86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/eyes-slash--outline-16.svg":{"9":[86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/file-arrow-down--outline-16.svg":{"9":[86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/file-diff--outline-16.svg":{"9":[86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/folder-plus--outline-16.svg":{"9":[86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/gauge--outline-16.svg":{"9":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/gift--outline-16.svg":{"9":[86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/hard-drive--outline-16.svg":{"9":[86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/hourglass--outline-16.svg":{"9":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/list-plus--outline-16.svg":{"9":[86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/minus--outline-16.svg":{"9":[86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/minus-circle--outline-16.svg":{"9":[86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/mouse-pointer--outline-16.svg":{"9":[86,124,45,199]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/paperplane--outline-16.svg":{"9":[86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/pencil-slash--outline-16.svg":{"9":[86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/person-check--outline-16.svg":{"9":[86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/person-circle--outline-16.svg":{"9":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/person-pencil--outline-16.svg":{"9":[86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/play-circle--outline-16.svg":{"9":[86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/power--outline-16.svg":{"9":[86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/rss--outline-16.svg":{"9":[86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/smiley-square--outline-16.svg":{"9":[86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/sparkle--outline-16.svg":{"9":[86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/sparkle--solid-16.svg":{"9":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/speaker-x--outline-16.svg":{"9":[86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/squares--outline-16.svg":{"9":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/star--solid-16.svg":{"9":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/template--outline-16.svg":{"9":[86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/brand/terminal--outline-16.svg":{"9":[86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/continue.svg":{"9":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/discord.svg":{"8":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/entra.svg":{"9":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/form.svg":{"9":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/linear.svg":{"8":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/lovable.svg":{"11":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/resolver.svg":{"11":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/retry.svg":{"8":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/run-once.svg":{"9":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/slack.svg":{"14":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/status-canceled.svg":{"8":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/status-completed.svg":{"8":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/status-error.svg":{"8":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/status-new.svg":{"8":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/status-unknown.svg":{"8":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/teams.svg":{"9":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/telegram.svg":{"8":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/toolbox.svg":{"10":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/webhook.svg":{"8":[86,124,45]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/custom/whatsapp.svg":{"8":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIconPicker/IconColorPicker.vue":{"15":[86,124,45],"63":[86,124,45],"65":[86,124,45],"67":[86,124],"71":[86,124],"76":[86,124],"81":[86,124,45],"92":[86,124,45],"100":[86,124,45],"104":[86,124],"112":[86,124],"121":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIconPicker/IconPicker.utils.ts":{"10":[86,124],"18":[86,124,45],"22":[86,124],"29":[86,124,45],"30":[86,124,45],"35":[86,124],"41":[86,124],"42":[86,124],"43":[86,124],"49":[86,124],"71":[86,124],"81":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nIconPicker/SkinTonePicker.vue":{"12":[86,124,45],"31":[86,124,45],"33":[86,124],"41":[86,124,45],"51":[86,124,45],"59":[86,124,45],"63":[86,124],"70":[86,124],"72":[86,124],"79":[86,124],"80":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nSectionHeader/SectionHeader.vue":{"21":[86,124,166],"28":[86,124,166]},"packages/frontend/@n8n/design-system/src/components/N8nSettingsRowButton/SettingsRowButton.vue":{"25":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nSettingsSaveBar/SettingsSaveBar.vue":{"42":[86,124],"68":[86,124],"86":[86,124],"91":[86,124],"98":[86,124],"108":[86,124],"117":[86,124],"121":[86,124],"136":[86,124],"147":[86,124],"155":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nSetupConnection/SetupConnection.vue":{"9":[86,124],"14":[86,124],"30":[86,124],"32":[86,124],"39":[86,124],"61":[86,124],"63":[86,124],"70":[86,124],"80":[86,124],"81":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nSetupPanel/SetupPanel.vue":{"10":[86,124],"18":[86,124],"21":[86,124],"28":[86,124],"33":[86,124],"35":[86,124],"41":[86,124],"45":[86,124],"51":[86,124],"52":[86,124],"56":[86,124],"57":[86,124],"65":[86,124],"73":[86,124],"75":[86,124],"92":[86,124],"99":[86,124],"129":[86,124],"136":[86,124],"137":[86,124],"146":[86,124],"155":[86,124],"165":[86,124],"166":[86,124],"206":[86,124],"215":[86,124],"225":[86,124],"226":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nStepper/Stepper.vue":{"30":[86,124],"31":[86,124],"42":[86,124],"44":[86,124]},"packages/frontend/@n8n/design-system/src/components/N8nUsersList/UsersList.vue":{"12":[86,124],"22":[86,124],"23":[86,124],"60":[86,124],"61":[86,124],"65":[86,124],"66":[86,124],"77":[86,124],"82":[86,124],"87":[86,124],"99":[86,124],"113":[86,124]},"packages/frontend/@n8n/design-system/src/locale/lang/en.ts":{"45":[86,124],"49":[86,124],"55":[86,124],"117":[86,124]},"packages/frontend/@n8n/design-system/src/utils/colorUtils.ts":{"16":[86,124],"23":[86,124],"37":[86,124],"40":[86,124],"51":[86,124],"62":[86,124],"74":[86,124],"84":[86,124]},"packages/frontend/@n8n/design-system/src/utils/valueByPath.ts":{"10":[86,124],"11":[86,124]},"packages/frontend/@n8n/design-system/src/v2/components/Loading/Loading.vue":{"7":[86,124],"16":[86,124],"18":[86,124],"19":[86,124],"20":[86,124],"21":[86,124],"22":[86,124],"27":[86,124],"29":[86,124],"38":[86,124],"42":[86,124],"52":[86,124],"65":[86,124]},"packages/frontend/@n8n/frontend-module-sdk/src/registries/commandRegistry.ts":{"6":[86,124],"10":[86,124],"12":[86,124],"15":[86,124]},"packages/frontend/@n8n/rest-api-client/src/api/ai-usage.ts":{"6":[86,124]},"packages/frontend/@n8n/rest-api-client/src/api/api-keys.ts":{"13":[86,124],"33":[86,124],"37":[86,124],"44":[86,124],"51":[86,124],"59":[86,124]},"packages/frontend/@n8n/rest-api-client/src/api/breaking-changes.ts":{"18":[86,124],"25":[86,124],"36":[86,124],"43":[86,124],"56":[86,124],"67":[86,124],"79":[86,124],"93":[86,124],"105":[86,124]},"packages/frontend/@n8n/rest-api-client/src/api/credentialResolvers.ts":{"10":[86,124],"18":[86,124],"24":[86,124],"31":[86,124],"38":[86,124],"51":[86,124],"58":[86,124]},"packages/frontend/@n8n/rest-api-client/src/api/dynamic-banners.ts":{"26":[86,124]},"packages/frontend/@n8n/rest-api-client/src/api/events.ts":{"4":[86,124]},"packages/frontend/@n8n/rest-api-client/src/api/instance-version-history.ts":{"4":[86,124]},"packages/frontend/@n8n/rest-api-client/src/api/ldap.ts":{"50":[86,124],"54":[86,124],"58":[86,124],"70":[86,124],"74":[86,124]},"packages/frontend/@n8n/rest-api-client/src/api/npsSurvey.ts":{"6":[86,124]},"packages/frontend/@n8n/rest-api-client/src/api/orchestration.ts":{"8":[86,124],"12":[86,124],"19":[86,124]},"packages/frontend/@n8n/rest-api-client/src/api/roleMappingRule.ts":{"41":[86,124],"65":[86,124],"72":[86,124],"80":[86,124],"87":[86,124]},"packages/frontend/@n8n/rest-api-client/src/api/security-settings.ts":{"6":[86,124,47],"10":[86,124,47]},"packages/frontend/@n8n/rest-api-client/src/api/sso.ts":{"16":[86,124],"21":[86,124],"25":[86,124],"31":[86,124],"45":[86,124],"52":[86,124],"56":[86,124],"63":[86,124],"82":[86,124]},"packages/frontend/@n8n/rest-api-client/src/api/third-party-licenses.ts":{"4":[86,124]},"packages/frontend/@n8n/rest-api-client/src/api/ui.ts":{"6":[86,124]},"packages/frontend/@n8n/rest-api-client/src/api/webhooks.ts":{"13":[86,124]},"packages/frontend/@n8n/stores/src/invitation.api.ts":{"26":[86,124],"33":[86,124]},"packages/frontend/@n8n/stores/src/onboarding.api.ts":{"7":[86,124]},"packages/frontend/editor-ui/src/app/api/workflows.ee.ts":{"7":[86,124,196],"20":[86,124,44],"28":[86,124]},"packages/frontend/editor-ui/src/app/components/AiUpdatedCodeMessage.vue":{"3":[86,124],"4":[86,124]},"packages/frontend/editor-ui/src/app/components/ChatEmbedModal.vue":{"53":[86,124],"55":[86,124],"72":[86,124],"80":[86,124],"83":[86,124],"87":[86,124],"88":[86,124],"97":[86,124],"106":[86,124],"117":[86,124],"132":[86,124],"138":[86,124],"140":[86,124],"151":[86,124],"167":[86,124],"182":[86,124],"187":[86,124],"192":[86,124]},"packages/frontend/editor-ui/src/app/components/NodeActionsList.vue":{"17":[86,124],"28":[86,124],"29":[86,124],"33":[86,124],"35":[86,124],"36":[86,124],"45":[86,124],"61":[86,124],"69":[86,124],"76":[86,124],"82":[86,124],"86":[86,124],"94":[86,124],"105":[86,124],"109":[86,124]},"packages/frontend/editor-ui/src/app/components/NodeExecutionErrorMessage.vue":{"4":[86,124],"5":[86,124]},"packages/frontend/editor-ui/src/app/components/TitledList.vue":{"9":[86,124],"12":[86,124]},"packages/frontend/editor-ui/src/app/components/WarningTooltip.vue":{"6":[86,124],"8":[86,124],"10":[86,124]},"packages/frontend/editor-ui/src/app/components/WhatsNewModal.vue":{"24":[86,124],"41":[86,124],"43":[86,124],"47":[86,124],"55":[86,124],"56":[86,124],"68":[86,124],"82":[86,124],"92":[86,124],"98":[86,124],"104":[86,124],"107":[86,124],"113":[86,124],"131":[86,124],"142":[86,124],"148":[86,124],"151":[86,124],"166":[86,124],"173":[86,124],"184":[86,124]},"packages/frontend/editor-ui/src/app/components/scopes/ScopesSelector.vue":{"31":[86,124],"80":[86,124],"81":[86,124],"92":[86,124],"96":[86,124],"98":[86,124],"100":[86,124],"102":[86,124],"106":[86,124],"110":[86,124],"112":[86,124],"114":[86,124],"117":[86,124],"128":[86,124],"135":[86,124],"141":[86,124],"152":[86,124],"173":[86,124],"179":[86,124],"195":[86,124],"199":[86,124],"212":[86,124],"229":[86,124],"233":[86,124],"237":[86,124],"238":[86,124],"241":[86,124],"242":[86,124],"245":[86,124],"254":[86,124],"257":[86,124],"264":[86,124],"265":[86,124],"271":[86,124],"278":[86,124],"281":[86,124],"284":[86,124],"298":[86,124],"299":[86,124],"313":[86,124],"322":[86,124],"328":[86,124],"338":[86,124],"346":[86,124],"358":[86,124],"372":[86,124],"389":[86,124],"413":[86,124],"414":[86,124],"415":[86,124],"421":[86,124],"425":[86,124]},"packages/frontend/editor-ui/src/app/components/scopes/scopes.utils.ts":{"22":[86,124],"30":[86,124],"34":[86,124],"37":[86,124],"53":[86,124],"72":[86,124],"79":[86,124],"80":[86,124]},"packages/frontend/editor-ui/src/app/composables/useToolParameters.ts":{"28":[86,124],"40":[86,124],"73":[86,124],"78":[86,124],"81":[86,124],"85":[86,124],"99":[86,124],"116":[86,124],"140":[86,124],"169":[86,124],"195":[86,124],"203":[86,124],"204":[86,124],"210":[86,124],"211":[86,124],"219":[86,124],"242":[86,124],"246":[86,124],"256":[86,124],"264":[86,124],"325":[86,124],"331":[86,124]},"packages/frontend/editor-ui/src/app/moduleInitializer/placeholderPage.ts":{"5":[86,124]},"packages/frontend/editor-ui/src/app/stores/webhooks.store.ts":{"16":[86,124],"21":[86,124],"24":[86,124]},"packages/frontend/editor-ui/src/app/utils/rbac/middleware/defaultUser.ts":{"6":[86,124]},"packages/frontend/editor-ui/src/app/utils/rbac/middleware/role.ts":{"6":[86,124]},"packages/frontend/editor-ui/src/app/utils/retryUtils.ts":{"18":[86,124]},"packages/frontend/editor-ui/src/app/utils/safeRegex.ts":{"25":[86,124],"33":[86,124],"37":[86,124],"41":[86,124],"42":[86,124],"46":[86,124],"52":[86,124],"58":[86,124],"69":[86,124],"75":[86,124],"81":[86,124],"93":[86,124],"94":[86,124],"99":[86,124],"113":[86,124]},"packages/frontend/editor-ui/src/experiments/exposeAllWorkflowsToMcp/modals.ts":{"7":[86,124]},"packages/frontend/editor-ui/src/experiments/mcpJsonNudge/modals.ts":{"7":[86,124]},"packages/frontend/editor-ui/src/experiments/personalizedTemplatesV3/components/NodeRecommendationModal.vue":{"13":[86,124],"23":[86,124],"27":[86,124],"35":[86,124],"42":[86,124],"47":[86,124],"51":[86,124],"58":[86,124],"69":[86,124],"72":[86,124],"76":[86,124],"85":[86,124],"88":[86,124],"91":[86,124],"94":[86,124]},"packages/frontend/editor-ui/src/experiments/personalizedTemplatesV3/components/TemplateCard.vue":{"12":[86,124],"21":[86,124],"24":[86,124],"34":[86,124],"45":[86,124],"57":[86,124],"84":[86,124],"88":[86,124],"93":[86,124],"95":[86,124],"98":[86,124],"102":[86,124]},"packages/frontend/editor-ui/src/experiments/surfaceAssistantOnWorkflowError/workflowErrorNudge.telemetry.ts":{"9":[86,124],"16":[86,124]},"packages/frontend/editor-ui/src/experiments/surfaceAssistantOnWorkflowError/workflowErrorNudgeOutline.ts":{"21":[86,124],"26":[86,124],"38":[86,124],"57":[86,124]},"packages/frontend/editor-ui/src/experiments/surfaceAssistantOnWorkflowError/workflowErrorNudgePosition.ts":{"5":[86,124],"7":[86,124],"8":[86,124]},"packages/frontend/editor-ui/src/experiments/surfaceMcpToNewCloudUsers/modals.ts":{"7":[86,124]},"packages/frontend/editor-ui/src/experiments/templateRecoV2/components/NodeRecommendationModal.vue":{"16":[86,124],"35":[86,124],"45":[86,124],"46":[86,124],"55":[86,124],"57":[86,124],"60":[86,124],"64":[86,124],"68":[86,124],"76":[86,124],"83":[86,124],"87":[86,124],"90":[86,124],"98":[86,124],"99":[86,124],"107":[86,124],"111":[86,124],"114":[86,124],"118":[86,124],"125":[86,124],"135":[86,124],"142":[86,124],"155":[86,124],"160":[86,124],"161":[86,124],"168":[86,124],"172":[86,124],"181":[86,124],"183":[86,124],"184":[86,124],"191":[86,124],"195":[86,124],"203":[86,124],"207":[86,124]},"packages/frontend/editor-ui/src/experiments/templateRecoV2/components/TemplateCard.vue":{"13":[86,124],"25":[86,124],"28":[86,124],"32":[86,124],"39":[86,124],"44":[86,124],"48":[86,124],"52":[86,124],"57":[86,124],"59":[86,124],"64":[86,124]},"packages/frontend/editor-ui/src/experiments/templateRecoV2/components/YoutubeCard.vue":{"5":[86,124],"13":[86,124],"16":[86,124],"21":[86,124],"28":[86,124],"29":[86,124]},"packages/frontend/editor-ui/src/features/agents/components/AgentChipButton.vue":{"7":[86,124],"38":[86,124],"46":[86,124],"68":[86,124],"81":[86,124],"94":[86,124],"95":[86,124]},"packages/frontend/editor-ui/src/features/agents/components/AgentCredentialSelect.vue":{"18":[86,124],"42":[86,124],"44":[86,124],"48":[86,124],"56":[86,124],"58":[86,124],"73":[86,124]},"packages/frontend/editor-ui/src/features/agents/components/AgentItemContextMenu.vue":{"9":[86,124],"18":[86,124],"50":[86,124],"57":[86,124],"62":[86,124],"66":[86,124],"67":[86,124],"69":[86,124]},"packages/frontend/editor-ui/src/features/agents/components/model-selector/ModelSelectorItemLeadingIcon.vue":{"11":[86,124]},"packages/frontend/editor-ui/src/features/agents/components/model-selector/ModelSelectorRestrictedMarker.vue":{"11":[86,124],"15":[86,124],"16":[86,124],"27":[86,124]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentProjectNameResolver.ts":{"8":[86,124],"11":[86,124],"15":[86,124],"18":[86,124]},"packages/frontend/editor-ui/src/features/agents/composables/useAgentToolRefAdapter.ts":{"21":[86,124],"23":[86,124],"32":[86,124],"50":[86,124],"67":[86,124],"82":[86,124],"106":[86,124],"127":[86,124],"146":[86,124],"151":[86,124],"152":[86,124],"163":[86,124]},"packages/frontend/editor-ui/src/features/agents/composables/useMcpServerAdapter.ts":{"12":[86,124],"14":[86,124],"19":[86,124],"25":[86,124],"29":[86,124],"33":[86,124],"37":[86,124],"53":[86,124],"66":[86,124],"67":[86,124],"76":[86,124],"102":[86,124],"106":[86,124],"108":[86,124],"111":[86,124],"114":[86,124],"115":[86,124],"118":[86,124],"129":[86,124],"133":[86,124],"137":[86,124],"152":[86,124],"169":[86,124],"173":[86,124],"182":[86,124],"207":[86,124],"212":[86,124],"219":[86,124],"254":[86,124]},"packages/frontend/editor-ui/src/features/agents/modals.ts":{"19":[86,124],"26":[86,124],"32":[86,124],"38":[86,124],"44":[86,124],"50":[86,124],"56":[86,124],"63":[86,124],"69":[86,124],"74":[86,124],"80":[86,124],"87":[86,124],"93":[86,124],"97":[86,124],"103":[86,124],"109":[86,124],"115":[86,124],"120":[86,124],"128":[86,124]},"packages/frontend/editor-ui/src/features/agents/utils/agentCapabilityActivity.ts":{"5":[86,124],"9":[86,124],"13":[86,124],"17":[86,124]},"packages/frontend/editor-ui/src/features/agents/utils/agentSkill.ts":{"4":[86,124]},"packages/frontend/editor-ui/src/features/agents/utils/agentValidationIssueMessages.ts":{"44":[86,124],"61":[86,124]},"packages/frontend/editor-ui/src/features/agents/utils/capabilitySummaryTools.ts":{"11":[86,124],"15":[86,124]},"packages/frontend/editor-ui/src/features/agents/utils/inlineAgent.ts":{"16":[86,124],"20":[86,124],"36":[86,124],"51":[86,124],"66":[86,124],"79":[86,124],"89":[86,124],"90":[86,124]},"packages/frontend/editor-ui/src/features/agents/utils/promptCaching.ts":{"18":[86,124]},"packages/frontend/editor-ui/src/features/agents/utils/reasoning.ts":{"7":[86,124]},"packages/frontend/editor-ui/src/features/agents/utils/toolDisplayName.ts":{"15":[86,124],"52":[86,124],"72":[86,124],"76":[86,124],"88":[86,124]},"packages/frontend/editor-ui/src/features/agents/utils/workflowToolTriggers.ts":{"11":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/AIBuilderDiffModal.vue":{"12":[86,124],"27":[86,124],"32":[86,124],"37":[86,124],"39":[86,124],"55":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/BuilderNodeGroupCard.vue":{"26":[86,124],"62":[86,124],"78":[86,124],"80":[86,124],"81":[86,124],"82":[86,124],"83":[86,124],"85":[86,124],"86":[86,124],"90":[86,124],"92":[86,124],"93":[86,124],"100":[86,124],"112":[86,124],"114":[86,124],"120":[86,124],"130":[86,124],"134":[86,124],"142":[86,124],"161":[86,124],"162":[86,124],"165":[86,124],"169":[86,124],"170":[86,124],"181":[86,124],"185":[86,124],"186":[86,124],"191":[86,124],"201":[86,124],"212":[86,124],"216":[86,124],"217":[86,124],"218":[86,124],"236":[86,124],"237":[86,124],"240":[86,124],"249":[86,124],"250":[86,124],"262":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/ChatVersionCard.vue":{"13":[86,124],"37":[86,124],"43":[86,124],"49":[86,124],"59":[86,124],"88":[86,124],"92":[86,124],"106":[86,124],"109":[86,124],"148":[86,124],"155":[86,124],"161":[86,124],"162":[86,124],"182":[86,124],"183":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/CollapsedMessagesGroup.vue":{"11":[86,124],"31":[86,124],"33":[86,124],"45":[86,124],"77":[86,124],"84":[86,124],"104":[86,124],"111":[86,124],"115":[86,124],"117":[86,124],"142":[86,124],"152":[86,124],"153":[86,124],"154":[86,124],"155":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/CredentialsSetupCard.vue":{"24":[86,124],"26":[86,124],"29":[86,124],"34":[86,124],"37":[86,124],"62":[86,124],"64":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/CreditWarningBanner.vue":{"9":[86,124],"35":[86,124],"64":[86,124],"72":[86,124],"79":[86,124],"85":[86,124],"104":[86,124],"117":[86,124],"118":[86,124],"127":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/NodeIssueItem.vue":{"26":[86,124],"31":[86,124],"35":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/NotificationPermissionBanner.vue":{"7":[86,124],"11":[86,124],"21":[86,124],"24":[86,124],"38":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/PlanDisplayMessage.vue":{"9":[86,124],"29":[86,124],"31":[86,124],"35":[86,124],"42":[86,124],"46":[86,124],"47":[86,124],"52":[86,124],"53":[86,124],"55":[86,124],"56":[86,124],"64":[86,124],"66":[86,124],"67":[86,124],"78":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/PlanQuestionsMessage.vue":{"17":[86,124],"40":[86,124],"41":[86,124],"42":[86,124],"45":[86,124],"46":[86,124],"51":[86,124],"56":[86,124],"58":[86,124],"72":[86,124],"78":[86,124],"83":[86,124],"95":[86,124],"103":[86,124],"120":[86,124],"127":[86,124],"139":[86,124],"149":[86,124],"159":[86,124],"165":[86,124],"178":[86,124],"206":[86,124],"212":[86,124],"225":[86,124],"234":[86,124],"241":[86,124],"252":[86,124],"256":[86,124],"269":[86,124],"278":[86,124],"290":[86,124],"301":[86,124],"313":[86,124],"330":[86,124],"358":[86,124],"369":[86,124],"387":[86,124],"388":[86,124],"401":[86,124],"403":[86,124],"409":[86,124],"420":[86,124],"422":[86,124],"428":[86,124],"441":[86,124],"442":[86,124],"456":[86,124],"476":[86,124],"484":[86,124],"489":[86,124],"501":[86,124],"551":[86,124],"555":[86,124],"567":[86,124],"580":[86,124],"590":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/ReviewChangesBanner.vue":{"13":[86,124],"20":[86,124],"28":[86,124],"29":[86,124],"45":[86,124],"46":[86,124],"53":[86,124],"58":[86,124],"59":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/UserAnswersMessage.vue":{"19":[86,124],"21":[86,124],"33":[86,124],"38":[86,124],"40":[86,124],"45":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/WebFetchApprovalMessage.vue":{"17":[86,124],"44":[86,124],"55":[86,124],"57":[86,124],"63":[86,124],"67":[86,124],"79":[86,124],"89":[86,124],"104":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/components/Agent/creditFormatting.ts":{"2":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/components/AskModeCoachmark.vue":{"9":[86,124],"14":[86,124],"28":[86,124],"31":[86,124],"45":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/components/FocusedNodes/FocusedNodeChip.vue":{"13":[86,124],"23":[86,124],"24":[86,124],"26":[86,124],"28":[86,124],"35":[86,124],"40":[86,124],"43":[86,124],"52":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/components/FocusedNodes/MessageFocusedNodesChips.vue":{"18":[86,124],"22":[86,124],"26":[86,124],"27":[86,124],"28":[86,124],"33":[86,124],"36":[86,124],"37":[86,124],"43":[86,124],"47":[86,124],"63":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/components/FocusedNodes/NodeMentionDropdown.vue":{"18":[86,124],"34":[86,124],"35":[86,124],"41":[86,124],"45":[86,124],"58":[86,124],"62":[86,124],"66":[86,124],"70":[86,124],"74":[86,124],"81":[86,124],"82":[86,124],"84":[86,124],"94":[86,124],"96":[86,124],"103":[86,124],"106":[86,124],"116":[86,124],"127":[86,124],"135":[86,124],"136":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useBuilderStreamingGuard.ts":{"13":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/composables/useExecutionWatcher.ts":{"12":[86,124],"18":[86,124],"20":[86,124]},"packages/frontend/editor-ui/src/features/ai/assistant/focusedNodes.utils.ts":{"10":[86,124],"20":[86,124],"22":[86,124]},"packages/frontend/editor-ui/src/features/ai/evaluation.ee/components/AddExecutionToDataset/AddExecutionToDatasetModal.vue":{"27":[86,124],"50":[86,124],"51":[86,124],"52":[86,124],"63":[86,124],"68":[86,124],"75":[86,124],"85":[86,124],"86":[86,124],"92":[86,124],"94":[86,124],"95":[86,124],"98":[86,124],"103":[86,124],"109":[86,124],"110":[86,124],"117":[86,124],"140":[86,124],"157":[86,124],"187":[86,124],"189":[86,124],"197":[86,124],"208":[86,124],"221":[86,124],"223":[86,124],"230":[86,124],"240":[86,124],"250":[86,124],"257":[86,124],"266":[86,124],"272":[86,124],"283":[86,124],"291":[86,124]},"packages/frontend/editor-ui/src/features/ai/gateway/assets/service-icons/alibaba.svgcomponent":{"11":[86,124]},"packages/frontend/editor-ui/src/features/ai/gateway/assets/service-icons/anthropic.svgcomponent":{"11":[86,124]},"packages/frontend/editor-ui/src/features/ai/gateway/assets/service-icons/brave-search.svgcomponent":{"11":[86,124]},"packages/frontend/editor-ui/src/features/ai/gateway/assets/service-icons/browserbase.svgcomponent":{"11":[86,124]},"packages/frontend/editor-ui/src/features/ai/gateway/assets/service-icons/firecrawl.svgcomponent":{"11":[86,124]},"packages/frontend/editor-ui/src/features/ai/gateway/assets/service-icons/gemini.svgcomponent":{"8":[86,124]},"packages/frontend/editor-ui/src/features/ai/gateway/assets/service-icons/llamaindex.svgcomponent":{"11":[86,124]},"packages/frontend/editor-ui/src/features/ai/gateway/assets/service-icons/minimax.svgcomponent":{"11":[86,124]},"packages/frontend/editor-ui/src/features/ai/gateway/assets/service-icons/moonshot.svgcomponent":{"11":[86,124]},"packages/frontend/editor-ui/src/features/ai/gateway/assets/service-icons/openai.svgcomponent":{"11":[86,124]},"packages/frontend/editor-ui/src/features/ai/gateway/assets/service-icons/pdfco.svgcomponent":{"13":[86,124]},"packages/frontend/editor-ui/src/features/ai/gateway/components/AiGatewayTopUpModal.vue":{"23":[86,124],"91":[86,124],"92":[86,124],"95":[86,124],"96":[86,124],"98":[86,124],"99":[86,124],"100":[86,124],"104":[86,124],"114":[86,124],"123":[86,124],"132":[86,124],"137":[86,124],"142":[86,124],"146":[86,124],"155":[86,124],"164":[86,124],"179":[86,124],"182":[86,124],"186":[86,124],"199":[86,124]},"packages/frontend/editor-ui/src/features/ai/instanceAi/modals.ts":{"12":[86,124],"17":[86,124],"22":[86,124],"23":[86,124]},"packages/frontend/editor-ui/src/features/ai/instanceAi/planReview.utils.ts":{"4":[86,124],"6":[86,124],"20":[86,124],"21":[86,124],"31":[86,124]},"packages/frontend/editor-ui/src/features/ai/instanceAi/prefills.ts":{"60":[86,124,36],"68":[86,124,36],"80":[86,124,36]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectMoveResourceModal.vue":{"42":[86,124,44],"68":[86,124,44],"69":[86,124],"72":[86,124],"75":[86,124,44],"76":[86,124],"92":[86,124,44],"96":[86,124,44],"97":[86,124,44],"101":[86,124,44],"107":[86,124,44],"111":[86,124,44],"116":[86,124,44],"119":[86,124,44],"120":[86,124],"125":[86,124],"129":[86,124,44],"132":[86,124,44],"137":[86,124,44],"141":[86,124,44],"151":[86,124],"190":[86,124,44],"206":[86,124,44],"209":[86,124,44],"211":[86,124,44],"219":[86,124,44],"223":[86,124],"224":[86,124],"230":[86,124,44],"231":[86,124,44],"239":[86,124,44],"257":[86,124,44],"262":[86,124,44],"283":[86,124],"285":[86,124],"298":[86,124],"313":[86,124],"322":[86,124],"333":[86,124],"349":[86,124],"354":[86,124,44],"357":[86,124,44],"365":[86,124,44]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectMoveResourceModalCredentialsList.vue":{"10":[86,124],"21":[86,124],"24":[86,124],"27":[86,124],"45":[86,124],"50":[86,124],"55":[86,124]},"packages/frontend/editor-ui/src/features/collaboration/projects/components/ProjectMoveSuccessToastMessage.vue":{"9":[86,124,44],"19":[86,124,44],"20":[86,124,44],"21":[86,124],"24":[86,124,44],"28":[86,124]},"packages/frontend/editor-ui/src/features/core/folders/components/MoveToFolderDropdown.vue":{"40":[86,124,44,118],"41":[86,124,44],"42":[86,124,44],"54":[86,124,44,118],"64":[86,124],"94":[86,124,44,118],"95":[86,124,44,118],"105":[86,124,44,118],"107":[86,124],"109":[86,124,44,118],"128":[86,124,44,118],"130":[86,124,44,118],"132":[86,124,44,118],"137":[86,124,44,118],"141":[86,124,44,118],"145":[86,124],"148":[86,124],"151":[86,124],"169":[86,124]},"packages/frontend/editor-ui/src/features/core/folders/components/MoveToFolderModal.vue":{"67":[86,124,44,118],"84":[86,124,44,118],"87":[86,124,44,118],"93":[86,124,44,118],"103":[86,124,44,118],"104":[86,124,44,118],"108":[86,124],"111":[86,124,44,118],"112":[86,124,118],"132":[86,124,44,118],"135":[86,124,44,118],"139":[86,124,44,118],"148":[86,124,44,118],"158":[86,124,44,118],"172":[86,124,44,118],"173":[86,124,44],"179":[86,124,44,118],"180":[86,124,44,118],"187":[86,124,44,118],"191":[86,124,44],"197":[86,124,44],"205":[86,124,44],"236":[86,124],"290":[86,124],"359":[86,124],"384":[86,124,44,118],"387":[86,124,44,118],"394":[86,124,44,118],"400":[86,124,44,118],"402":[86,124],"408":[86,124,44,118],"412":[86,124,44,118],"444":[86,124,44,118],"454":[86,124,44,118],"463":[86,124,44,118],"465":[86,124,44,118],"479":[86,124,44],"484":[86,124,44],"505":[86,124,44,118],"524":[86,124],"533":[86,124],"543":[86,124],"559":[86,124],"567":[86,124],"572":[86,124],"587":[86,124],"596":[86,124],"604":[86,124],"606":[86,124],"616":[86,124,44,118]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialInfo.vue":{"18":[86,124],"25":[86,124],"31":[86,124],"37":[86,124],"51":[86,124],"65":[86,124],"66":[86,124],"70":[86,124],"71":[86,124],"77":[86,124],"78":[86,124],"82":[86,124],"83":[86,124],"89":[86,124],"90":[86,124],"94":[86,124]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialOptionsInput.vue":{"19":[86,124],"39":[86,124],"40":[86,124],"43":[86,124],"47":[86,124],"50":[86,124],"61":[86,124],"71":[86,124],"87":[86,124],"88":[86,124],"90":[86,124],"93":[86,124],"99":[86,124],"104":[86,124],"116":[86,124]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/TemplatedAuthSimpleView.vue":{"43":[86,124],"57":[86,124],"61":[86,124],"65":[86,124],"67":[86,124],"69":[86,124],"72":[86,124],"82":[86,124],"86":[86,124],"101":[86,124],"108":[86,124],"109":[86,124],"114":[86,124],"115":[86,124],"135":[86,124],"137":[86,124],"148":[86,124],"169":[86,124],"175":[86,124],"180":[86,124],"186":[86,124],"187":[86,124],"199":[86,124],"203":[86,124],"207":[86,124],"217":[86,124],"222":[86,124],"230":[86,124],"233":[86,124],"248":[86,124],"253":[86,124],"275":[86,124],"276":[86,124],"292":[86,124],"293":[86,124],"297":[86,124],"307":[86,124],"325":[86,124],"328":[86,124],"339":[86,124],"348":[86,124],"353":[86,124],"361":[86,124],"372":[86,124],"376":[86,124],"394":[86,124],"401":[86,124],"412":[86,124],"430":[86,124],"437":[86,124]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/TypeToConfirmDialog.vue":{"14":[86,124],"35":[86,124],"39":[86,124],"40":[86,124],"46":[86,124],"51":[86,124],"53":[86,124],"63":[86,124],"64":[86,124],"66":[86,124],"69":[86,124]},"packages/frontend/editor-ui/src/features/credentials/components/CredentialPrivateConnectionRow.vue":{"23":[86,124],"36":[86,124],"50":[86,124],"56":[86,124],"71":[86,124],"76":[86,124],"85":[86,124],"91":[86,124],"100":[86,124],"102":[86,124],"110":[86,124],"112":[86,124],"119":[86,124],"130":[86,124],"132":[86,124],"152":[86,124],"154":[86,124]},"packages/frontend/editor-ui/src/features/credentials/components/ScopesNotice.vue":{"7":[86,124],"15":[86,124],"27":[86,124],"36":[86,124],"42":[86,124],"47":[86,124]},"packages/frontend/editor-ui/src/features/credentials/composables/useCredentialOptions.ts":{"22":[86,124],"31":[86,124],"33":[86,124],"39":[86,124],"40":[86,124],"42":[86,124],"44":[86,124],"50":[86,124],"75":[86,124],"84":[86,124],"91":[86,124],"96":[86,124],"101":[86,124],"102":[86,124],"109":[86,124]},"packages/frontend/editor-ui/src/features/credentials/gatewayCreditsPromotion/GatewayCreditsPromotion.vue":{"8":[86,124],"9":[86,124]},"packages/frontend/editor-ui/src/features/credentials/quickConnect/components/QuickConnectBanner.vue":{"11":[86,124],"19":[86,124],"27":[86,124],"32":[86,124]},"packages/frontend/editor-ui/src/features/credentials/quickConnect/quickConnect.api.ts":{"9":[86,124]},"packages/frontend/editor-ui/src/features/credentials/templatedAuth.utils.ts":{"43":[86,124],"54":[86,124],"56":[86,124],"65":[86,124],"75":[86,124],"78":[86,124],"79":[86,124],"90":[86,124],"107":[86,124],"116":[86,124],"126":[86,124],"129":[86,124],"135":[86,124],"139":[86,124],"149":[86,124],"163":[86,124],"171":[86,124],"185":[86,124],"191":[86,124],"193":[86,124]},"packages/frontend/editor-ui/src/features/execution/executions/components/DebugPaywallModal.vue":{"6":[86,124],"12":[86,124],"16":[86,124],"23":[86,124],"27":[86,124],"30":[86,124]},"packages/frontend/editor-ui/src/features/execution/executions/components/RevealDataWarning.vue":{"13":[86,124],"14":[86,124],"29":[86,124]},"packages/frontend/editor-ui/src/features/execution/executions/components/StopManyExecutionsModal.vue":{"13":[86,124],"27":[86,124],"46":[86,124],"57":[86,124],"90":[86,124],"92":[86,124],"103":[86,124],"106":[86,124],"107":[86,124],"111":[86,124],"112":[86,124],"116":[86,124],"117":[86,124],"149":[86,124]},"packages/frontend/editor-ui/src/features/integrations/externalSecrets.ee/assets/images/azure-key-vault.svg":{"10":[86,124]},"packages/frontend/editor-ui/src/features/integrations/externalSecrets.ee/assets/images/gcp-secrets-manager.svg":{"10":[86,124]},"packages/frontend/editor-ui/src/features/integrations/externalSecrets.ee/assets/images/one-password.svg":{"8":[86,124]},"packages/frontend/editor-ui/src/features/integrations/externalSecrets.ee/components/ExternalSecretsProviderConnectionSwitch.ee.vue":{"11":[86,124],"35":[86,124],"39":[86,124],"45":[86,124],"65":[86,124],"78":[86,124]},"packages/frontend/editor-ui/src/features/integrations/externalSecrets.ee/components/ExternalSecretsProviderImage.ee.vue":{"17":[86,124],"18":[86,124]},"packages/frontend/editor-ui/src/features/integrations/externalSecrets.ee/components/ExternalSecretsProviderModal.ee.vue":{"24":[86,124],"48":[86,124],"49":[86,124],"61":[86,124],"62":[86,124],"70":[86,124],"73":[86,124],"74":[86,124],"80":[86,124],"105":[86,124],"112":[86,124],"131":[86,124],"139":[86,124],"164":[86,124],"166":[86,124],"178":[86,124],"200":[86,124],"211":[86,124],"218":[86,124],"238":[86,124],"243":[86,124],"252":[86,124],"266":[86,124],"271":[86,124]},"packages/frontend/editor-ui/src/features/integrations/externalSecrets.ee/composables/useExternalSecretsProvider.ts":{"15":[86,124],"25":[86,124],"28":[86,124],"36":[86,124],"37":[86,124],"39":[86,124],"50":[86,124],"56":[86,124],"66":[86,124],"74":[86,124]},"packages/frontend/editor-ui/src/features/integrations/promotions.ee/modals.ts":{"7":[86,124]},"packages/frontend/editor-ui/src/features/integrations/promotions.ee/module.descriptor.ts":{"8":[86,124],"36":[86,124],"40":[86,124]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/components/SecretsProviderConnectionModal.ee.vue":{"43":[86,124],"76":[86,124],"77":[86,124],"78":[86,124],"79":[86,124],"93":[86,124],"94":[86,124],"104":[86,124],"121":[86,124],"131":[86,124],"147":[86,124],"151":[86,124],"152":[86,124],"158":[86,124],"167":[86,124],"172":[86,124],"176":[86,124],"180":[86,124],"184":[86,124],"189":[86,124],"202":[86,124],"210":[86,124],"230":[86,124],"237":[86,124],"250":[86,124],"266":[86,124],"272":[86,124],"291":[86,124],"305":[86,124],"310":[86,124],"315":[86,124],"346":[86,124],"412":[86,124],"420":[86,124],"441":[86,124],"443":[86,124],"453":[86,124],"457":[86,124],"462":[86,124],"479":[86,124],"483":[86,124],"492":[86,124],"497":[86,124],"504":[86,124],"507":[86,124],"512":[86,124],"517":[86,124]},"packages/frontend/editor-ui/src/features/integrations/secretsProviders.ee/composables/useConnectionModal.ee.ts":{"31":[86,124],"35":[86,124],"60":[86,124],"66":[86,124],"76":[86,124],"94":[86,124],"99":[86,124],"106":[86,124],"108":[86,124],"114":[86,124],"115":[86,124],"120":[86,124],"122":[86,124],"128":[86,124],"130":[86,124],"135":[86,124],"140":[86,124],"144":[86,124],"153":[86,124],"161":[86,124],"166":[86,124],"168":[86,124],"169":[86,124],"175":[86,124],"176":[86,124],"183":[86,124],"189":[86,124],"196":[86,124],"201":[86,124],"202":[86,124],"209":[86,124],"210":[86,124],"214":[86,124],"215":[86,124],"217":[86,124],"227":[86,124],"235":[86,124],"241":[86,124],"259":[86,124],"278":[86,124],"283":[86,124],"285":[86,124],"293":[86,124],"300":[86,124],"308":[86,124],"309":[86,124],"316":[86,124],"331":[86,124],"340":[86,124],"359":[86,124],"403":[86,124],"444":[86,124],"452":[86,124],"455":[86,124],"480":[86,124],"518":[86,124]},"packages/frontend/editor-ui/src/features/integrations/sourceControl.ee/components/SourceControlInitializationErrorMessage.vue":{"6":[86,124],"7":[86,124],"11":[86,124],"13":[86,124]},"packages/frontend/editor-ui/src/features/integrations/sourceControl.ee/components/SourceControlPullModal.vue":{"56":[86,124],"71":[86,124],"80":[86,124],"81":[86,124],"82":[86,124],"110":[86,124],"111":[86,124],"116":[86,124],"117":[86,124],"123":[86,124],"156":[86,124],"167":[86,124],"170":[86,124],"181":[86,124],"183":[86,124],"184":[86,124],"190":[86,124],"191":[86,124],"209":[86,124],"210":[86,124],"215":[86,124],"216":[86,124],"221":[86,124],"222":[86,124],"229":[86,124],"231":[86,124],"240":[86,124],"253":[86,124],"258":[86,124],"266":[86,124],"280":[86,124],"301":[86,124],"324":[86,124],"350":[86,124],"356":[86,124],"359":[86,124],"371":[86,124],"374":[86,124],"394":[86,124],"398":[86,124],"414":[86,124],"422":[86,124],"428":[86,124],"440":[86,124],"442":[86,124],"447":[86,124],"449":[86,124],"454":[86,124],"458":[86,124],"465":[86,124],"467":[86,124],"472":[86,124],"474":[86,124],"476":[86,124],"484":[86,124],"489":[86,124],"493":[86,124],"502":[86,124],"507":[86,124],"516":[86,124],"527":[86,124],"538":[86,124],"544":[86,124],"545":[86,124],"546":[86,124],"568":[86,124],"573":[86,124],"584":[86,124],"591":[86,124],"598":[86,124],"608":[86,124],"617":[86,124],"627":[86,124],"631":[86,124],"647":[86,124],"649":[86,124],"650":[86,124],"655":[86,124],"656":[86,124],"659":[86,124],"662":[86,124],"668":[86,124],"671":[86,124]},"packages/frontend/editor-ui/src/features/integrations/sourceControl.ee/components/SourceControlPullResultModal.vue":{"13":[86,124],"23":[86,124],"24":[86,124],"29":[86,124],"30":[86,124],"38":[86,124],"60":[86,124],"64":[86,124],"66":[86,124],"77":[86,124],"79":[86,124],"83":[86,124],"87":[86,124],"92":[86,124],"96":[86,124],"117":[86,124],"121":[86,124],"127":[86,124],"131":[86,124],"141":[86,124],"154":[86,124],"157":[86,124]},"packages/frontend/editor-ui/src/features/integrations/sourceControl.ee/components/SourceControlPushModal.vue":{"66":[86,124],"81":[86,124],"88":[86,124],"112":[86,124],"137":[86,124],"140":[86,124],"145":[86,124],"162":[86,124],"163":[86,124],"165":[86,124],"231":[86,124],"265":[86,124],"266":[86,124],"271":[86,124],"277":[86,124],"281":[86,124],"292":[86,124],"295":[86,124],"300":[86,124],"322":[86,124],"323":[86,124],"326":[86,124],"329":[86,124],"331":[86,124],"332":[86,124],"336":[86,124],"339":[86,124],"361":[86,124],"391":[86,124],"393":[86,124],"398":[86,124],"431":[86,124],"432":[86,124],"434":[86,124],"453":[86,124],"454":[86,124],"456":[86,124],"475":[86,124],"492":[86,124],"498":[86,124],"508":[86,124],"512":[86,124],"515":[86,124],"519":[86,124],"521":[86,124],"525":[86,124],"531":[86,124],"536":[86,124],"547":[86,124],"553":[86,124],"616":[86,124],"619":[86,124],"620":[86,124],"623":[86,124],"646":[86,124],"648":[86,124],"649":[86,124],"654":[86,124],"658":[86,124],"664":[86,124],"675":[86,124],"685":[86,124],"697":[86,124],"705":[86,124],"711":[86,124],"714":[86,124],"720":[86,124],"727":[86,124],"734":[86,124],"738":[86,124],"741":[86,124],"754":[86,124],"767":[86,124],"772":[86,124],"780":[86,124],"790":[86,124],"803":[86,124],"826":[86,124],"839":[86,124],"846":[86,124],"865":[86,124],"883":[86,124],"891":[86,124],"892":[86,124],"893":[86,124],"894":[86,124],"895":[86,124],"896":[86,124],"904":[86,124],"908":[86,124],"920":[86,124],"922":[86,124],"938":[86,124],"948":[86,124],"955":[86,124],"957":[86,124],"961":[86,124],"973":[86,124],"975":[86,124],"1011":[86,124],"1013":[86,124],"1021":[86,124],"1036":[86,124],"1042":[86,124],"1049":[86,124],"1052":[86,124],"1057":[86,124],"1061":[86,124],"1077":[86,124],"1078":[86,124],"1085":[86,124],"1099":[86,124],"1106":[86,124],"1116":[86,124],"1127":[86,124],"1141":[86,124],"1143":[86,124],"1147":[86,124],"1153":[86,124],"1154":[86,124],"1155":[86,124],"1156":[86,124],"1185":[86,124],"1187":[86,124],"1195":[86,124],"1204":[86,124],"1215":[86,124],"1245":[86,124],"1247":[86,124],"1255":[86,124],"1260":[86,124],"1278":[86,124],"1284":[86,124],"1286":[86,124],"1288":[86,124],"1289":[86,124],"1290":[86,124],"1296":[86,124],"1301":[86,124],"1320":[86,124]},"packages/frontend/editor-ui/src/features/integrations/sourceControl.ee/composables/useRevealWorkflowInScroller.ts":{"7":[86,124],"27":[86,124],"36":[86,124],"58":[86,124]},"packages/frontend/editor-ui/src/features/integrations/sourceControl.ee/composables/useSourceControlFileList.ts":{"20":[86,124],"26":[86,124]},"packages/frontend/editor-ui/src/features/integrations/sourceControl.ee/composables/useWorkflowTreeRows.ts":{"6":[86,124],"9":[86,124],"13":[86,124],"36":[86,124],"40":[86,124],"49":[86,124],"55":[86,124],"69":[86,124]},"packages/frontend/editor-ui/src/features/integrations/sourceControl.ee/sourceControl.utils.ts":{"17":[86,124],"20":[86,124],"38":[86,124],"48":[86,124],"51":[86,124],"61":[86,124],"74":[86,124],"84":[86,124],"97":[86,124],"178":[86,124],"214":[86,124],"230":[86,124],"237":[86,124],"243":[86,124],"254":[86,124]},"packages/frontend/editor-ui/src/features/ndv/agents/components/AgentNdvInlineControls.vue":{"22":[86,124],"35":[86,124],"36":[86,124],"37":[86,124],"38":[86,124],"39":[86,124],"41":[86,124],"45":[86,124],"47":[86,124],"49":[86,124],"71":[86,124]},"packages/frontend/editor-ui/src/features/ndv/agents/components/AgentNdvReferencedSummary.vue":{"30":[86,124],"39":[86,124],"40":[86,124],"41":[86,124],"42":[86,124],"43":[86,124],"44":[86,124],"45":[86,124],"46":[86,124],"47":[86,124],"49":[86,124],"54":[86,124],"63":[86,124],"69":[86,124],"71":[86,124],"77":[86,124],"87":[86,124],"90":[86,124],"91":[86,124],"100":[86,124],"103":[86,124],"108":[86,124],"110":[86,124],"127":[86,124],"138":[86,124],"156":[86,124],"163":[86,124],"172":[86,124]},"packages/frontend/editor-ui/src/features/ndv/panel/components/RedactedDataState.vue":{"14":[86,124,47],"20":[86,124,47],"24":[86,124,47],"26":[86,124,47],"33":[86,124,47],"34":[86,124],"35":[86,124,47],"49":[86,124,47],"53":[86,124,47],"58":[86,124]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/AgentSelectorParameterInput/AgentSelectorParameterInput.vue":{"59":[86,124],"112":[86,124],"121":[86,124],"129":[86,124],"140":[86,124],"150":[86,124],"154":[86,124],"164":[86,124],"189":[86,124],"193":[86,124],"198":[86,124],"203":[86,124],"208":[86,124],"212":[86,124],"216":[86,124],"225":[86,124],"253":[86,124],"261":[86,124],"268":[86,124],"273":[86,124],"274":[86,124],"283":[86,124],"291":[86,124],"313":[86,124],"317":[86,124],"320":[86,124],"327":[86,124],"345":[86,124],"347":[86,124],"353":[86,124],"370":[86,124],"387":[86,124],"406":[86,124],"426":[86,124]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ButtonParameter/ButtonParameter.vue":{"23":[86,124],"39":[86,124],"48":[86,124],"49":[86,124],"50":[86,124],"53":[86,124],"57":[86,124],"61":[86,124],"70":[86,124],"76":[86,124],"80":[86,124],"81":[86,124],"86":[86,124],"90":[86,124],"166":[86,124],"174":[86,124],"181":[86,124],"185":[86,124],"196":[86,124],"210":[86,124],"242":[86,124],"256":[86,124],"271":[86,124],"275":[86,124]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/Collection/CollectionParameterNew.vue":{"44":[86,124],"59":[86,124],"61":[86,124],"68":[86,124],"75":[86,124],"81":[86,124],"93":[86,124],"109":[86,124],"113":[86,124],"118":[86,124],"130":[86,124],"132":[86,124],"133":[86,124],"136":[86,124],"138":[86,124],"148":[86,124],"150":[86,124],"165":[86,124],"166":[86,124],"169":[86,124],"170":[86,124],"176":[86,124],"178":[86,124],"187":[86,124],"193":[86,124],"201":[86,124],"205":[86,124],"262":[86,124],"264":[86,124],"273":[86,124],"274":[86,124],"276":[86,124],"281":[86,124],"283":[86,124],"292":[86,124],"318":[86,124],"340":[86,124],"349":[86,124],"350":[86,124],"351":[86,124],"357":[86,124],"386":[86,124]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/FromAiParametersModal.vue":{"24":[86,124],"44":[86,124],"48":[86,124],"57":[86,124],"61":[86,124],"69":[86,124],"115":[86,124],"120":[86,124],"136":[86,124],"137":[86,124],"141":[86,124],"143":[86,124],"144":[86,124],"154":[86,124],"167":[86,124]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/ImportCurlModal.vue":{"13":[86,124],"25":[86,124],"33":[86,124],"38":[86,124],"42":[86,124],"46":[86,124],"50":[86,124],"55":[86,124],"59":[86,124],"72":[86,124],"86":[86,124],"88":[86,124],"104":[86,124],"116":[86,124],"119":[86,124],"132":[86,124]},"packages/frontend/editor-ui/src/features/ndv/parameters/components/MultipleParameter.vue":{"16":[86,124],"37":[86,124],"41":[86,124],"42":[86,124],"49":[86,124],"57":[86,124],"59":[86,124],"61":[86,124],"75":[86,124],"84":[86,124],"88":[86,124],"97":[86,124],"106":[86,124],"108":[86,124],"112":[86,124],"122":[86,124],"131":[86,124],"139":[86,124],"146":[86,124],"182":[86,124],"190":[86,124]},"packages/frontend/editor-ui/src/features/ndv/parameters/composables/useAgentResourcesLocator.ts":{"25":[86,124],"42":[86,124],"44":[86,124],"50":[86,124],"56":[86,124],"60":[86,124],"77":[86,124],"131":[86,124],"138":[86,124],"148":[86,124],"154":[86,124]},"packages/frontend/editor-ui/src/features/ndv/parameters/utils/assignmentCollection.utils.ts":{"8":[86,124,116],"18":[86,124,116],"30":[86,124],"33":[86,124],"35":[86,124],"43":[86,124]},"packages/frontend/editor-ui/src/features/ndv/parameters/utils/buttonParameter.utils.ts":{"21":[86,124],"28":[86,124],"29":[86,124],"31":[86,124],"32":[86,124],"35":[86,124],"37":[86,124],"40":[86,124],"48":[86,124],"61":[86,124],"69":[86,124],"82":[86,124],"114":[86,124],"158":[86,124],"183":[86,124],"249":[86,124],"263":[86,124],"266":[86,124],"275":[86,124],"297":[86,124],"304":[86,124],"310":[86,124],"340":[86,124],"373":[86,124],"374":[86,124],"381":[86,124],"403":[86,124]},"packages/frontend/editor-ui/src/features/ndv/runData/components/BinaryDataDisplay.vue":{"10":[86,124],"24":[86,124],"28":[86,124],"56":[86,124],"61":[86,124]},"packages/frontend/editor-ui/src/features/ndv/runData/components/BinaryDataDisplayEmbed.vue":{"10":[86,124],"23":[86,124],"27":[86,124],"55":[86,124]},"packages/frontend/editor-ui/src/features/ndv/runData/components/BinaryDataViewModal.vue":{"12":[86,124],"28":[86,124],"60":[86,124],"67":[86,124],"118":[86,124],"119":[86,124],"121":[86,124],"126":[86,124],"129":[86,124],"139":[86,124]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataHtml.vue":{"27":[86,124],"32":[86,124]},"packages/frontend/editor-ui/src/features/ndv/runData/components/RunDataMarkdown.vue":{"17":[86,124]},"packages/frontend/editor-ui/src/features/ndv/settings/components/NodeSettingsInvalidNodeWarning.vue":{"24":[86,124],"33":[86,124],"34":[86,124],"39":[86,124],"40":[86,124],"42":[86,124],"46":[86,124],"48":[86,124],"61":[86,124],"92":[86,124],"97":[86,124],"106":[86,124],"115":[86,124],"116":[86,124],"128":[86,124],"136":[86,124],"148":[86,124]},"packages/frontend/editor-ui/src/features/resolvers/components/CredentialResolverEditModal.vue":{"37":[86,124],"76":[86,124],"79":[86,124],"88":[86,124],"101":[86,124],"118":[86,124],"119":[86,124],"124":[86,124],"137":[86,124],"141":[86,124],"154":[86,124],"158":[86,124],"183":[86,124],"199":[86,124],"207":[86,124],"220":[86,124],"242":[86,124],"249":[86,124],"322":[86,124],"335":[86,124],"340":[86,124],"344":[86,124],"368":[86,124],"381":[86,124],"393":[86,124],"413":[86,124],"438":[86,124],"442":[86,124],"446":[86,124],"455":[86,124],"464":[86,124],"467":[86,124],"492":[86,124],"501":[86,124],"504":[86,124],"513":[86,124],"538":[86,124],"541":[86,124]},"packages/frontend/editor-ui/src/features/resolvers/components/PrivateCredentialIcon.vue":{"15":[86,124],"23":[86,124],"24":[86,124],"28":[86,124],"32":[86,124]},"packages/frontend/editor-ui/src/features/resolvers/components/ResolverDeleteConfirmMessage.vue":{"10":[86,124],"19":[86,124],"20":[86,124],"22":[86,124],"28":[86,124],"35":[86,124],"44":[86,124],"48":[86,124],"54":[86,124]},"packages/frontend/editor-ui/src/features/settings/apiKeys/apiKeys.utils.ts":{"43":[86,124],"52":[86,124]},"packages/frontend/editor-ui/src/features/settings/apiKeys/components/ApiKeyCreateOrEditModal.vue":{"70":[86,124],"78":[86,124],"114":[86,124],"127":[86,124],"131":[86,124],"139":[86,124],"146":[86,124],"153":[86,124],"157":[86,124],"164":[86,124],"174":[86,124],"176":[86,124],"185":[86,124],"193":[86,124],"199":[86,124],"203":[86,124],"207":[86,124],"212":[86,124],"228":[86,124],"232":[86,124],"267":[86,124],"271":[86,124],"277":[86,124],"284":[86,124],"307":[86,124],"323":[86,124],"340":[86,124],"347":[86,124],"363":[86,124],"366":[86,124],"383":[86,124],"401":[86,124],"408":[86,124],"411":[86,124],"437":[86,124],"445":[86,124],"447":[86,124],"463":[86,124],"464":[86,124],"468":[86,124],"476":[86,124],"485":[86,124],"507":[86,124]},"packages/frontend/editor-ui/src/features/settings/apiKeys/components/ApiKeyScopes.vue":{"8":[86,124],"18":[86,124],"31":[86,124]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/ContactAdministratorToInstall.vue":{"11":[86,124],"17":[86,124],"18":[86,124],"21":[86,124],"26":[86,124],"30":[86,124],"36":[86,124],"40":[86,124]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/NodesInWorkflowTable.vue":{"19":[86,124],"46":[86,124],"51":[86,124],"59":[86,124],"65":[86,124],"77":[86,124],"79":[86,124],"82":[86,124],"94":[86,124]},"packages/frontend/editor-ui/src/features/settings/communityNodes/components/nodeCreator/CommunityNodeUpdateInfo.vue":{"11":[86,124],"15":[86,124],"18":[86,124],"23":[86,124],"25":[86,124],"26":[86,124]},"packages/frontend/editor-ui/src/features/settings/context/module.descriptor.ts":{"21":[86,124],"28":[86,124],"34":[86,124],"41":[86,124]},"packages/frontend/editor-ui/src/features/settings/environments.ee/completions/variables.completions.ts":{"4":[86,124],"6":[86,124],"8":[86,124],"14":[86,124],"24":[86,124]},"packages/frontend/editor-ui/src/features/settings/migrationReport/MigrateWorkflowModal.vue":{"21":[86,124],"38":[86,124],"39":[86,124],"56":[86,124],"57":[86,124],"59":[86,124],"60":[86,124],"62":[86,124],"63":[86,124],"69":[86,124],"79":[86,124],"94":[86,124],"95":[86,124],"97":[86,124],"101":[86,124],"105":[86,124],"123":[86,124],"145":[86,124],"164":[86,124],"166":[86,124],"175":[86,124],"178":[86,124],"179":[86,124],"181":[86,124],"187":[86,124],"190":[86,124],"191":[86,124],"192":[86,124],"200":[86,124],"212":[86,124],"220":[86,124],"222":[86,124],"234":[86,124],"240":[86,124],"242":[86,124],"255":[86,124],"259":[86,124],"264":[86,124],"272":[86,124],"276":[86,124],"288":[86,124],"294":[86,124],"306":[86,124]},"packages/frontend/editor-ui/src/features/settings/usage/components/CommunityPlusEnrollmentModal.vue":{"15":[86,124],"35":[86,124],"54":[86,124],"60":[86,124],"83":[86,124],"96":[86,124],"99":[86,124],"101":[86,124],"138":[86,124],"143":[86,124],"146":[86,124],"154":[86,124],"157":[86,124]},"packages/frontend/editor-ui/src/features/settings/users/components/InviteUsersModal.vue":{"31":[86,124],"58":[86,124],"59":[86,124],"62":[86,124],"75":[86,124],"79":[86,124],"83":[86,124],"87":[86,124],"94":[86,124],"96":[86,124],"99":[86,124],"120":[86,124],"122":[86,124],"125":[86,124],"134":[86,124],"140":[86,124],"141":[86,124],"148":[86,124],"149":[86,124],"152":[86,124],"166":[86,124],"194":[86,124],"202":[86,124],"207":[86,124],"226":[86,124],"240":[86,124],"247":[86,124],"251":[86,124],"264":[86,124],"268":[86,124],"279":[86,124],"323":[86,124],"334":[86,124],"349":[86,124],"352":[86,124],"354":[86,124],"361":[86,124],"363":[86,124],"365":[86,124],"371":[86,124],"387":[86,124]},"packages/frontend/editor-ui/src/features/settings/users/components/PersonalizationModal.vue":{"103":[86,124],"118":[86,124],"121":[86,124],"228":[86,124],"238":[86,124],"295":[86,124],"305":[86,124],"352":[86,124],"366":[86,124],"415":[86,124],"426":[86,124],"459":[86,124],"497":[86,124],"553":[86,124],"561":[86,124],"565":[86,124],"574":[86,124],"590":[86,124],"611":[86,124],"629":[86,124],"642":[86,124]},"packages/frontend/editor-ui/src/features/settings/users/invite-link.utils.ts":{"14":[86,124],"20":[86,124]},"packages/frontend/editor-ui/src/features/setupPanel/components/WebhookUrlPreview.vue":{"15":[86,124],"21":[86,124],"27":[86,124],"34":[86,124],"44":[86,124],"48":[86,124],"52":[86,124]},"packages/frontend/editor-ui/src/features/setupPanel/composables/useNodeGroupSections.ts":{"11":[86,124],"19":[86,124],"24":[86,124],"31":[86,124],"34":[86,124],"45":[86,124],"52":[86,124],"60":[86,124],"66":[86,124],"73":[86,124],"81":[86,124],"87":[86,124],"107":[86,124],"111":[86,124],"117":[86,124]},"packages/frontend/editor-ui/src/features/shared/banners/components/banners/DataTableStorageLimitErrorBanner.vue":{"6":[86,124],"8":[86,124],"12":[86,124]},"packages/frontend/editor-ui/src/features/shared/banners/components/banners/DataTableStorageLimitWarningBanner.vue":{"6":[86,124],"8":[86,124],"12":[86,124]},"packages/frontend/editor-ui/src/features/shared/banners/components/banners/DynamicBanner.vue":{"13":[86,124],"14":[86,124],"23":[86,124]},"packages/frontend/editor-ui/src/features/shared/banners/components/banners/EmailConfirmationBanner.vue":{"10":[86,124],"13":[86,124],"17":[86,124],"31":[86,124],"37":[86,124],"40":[86,124],"44":[86,124],"52":[86,124]},"packages/frontend/editor-ui/src/features/shared/banners/components/banners/NonProductionLicenseBanner.vue":{"7":[86,124],"8":[86,124]},"packages/frontend/editor-ui/src/features/shared/banners/components/banners/TrialOverBanner.vue":{"8":[86,124],"10":[86,124],"12":[86,124],"17":[86,124],"20":[86,124],"27":[86,124]},"packages/frontend/editor-ui/src/features/shared/banners/components/banners/V1Banner.vue":{"8":[86,124],"10":[86,124],"14":[86,124],"15":[86,124],"19":[86,124]},"packages/frontend/editor-ui/src/features/shared/banners/components/banners/WorkflowAutoDeactivatedBanner.vue":{"7":[86,124],"8":[86,124]},"packages/frontend/editor-ui/src/features/shared/commandBar/commandBar.utils.ts":{"9":[86,124],"12":[86,124],"15":[86,124]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/completer.ts":{"23":[86,108,124],"27":[86,108,124],"29":[86,124],"67":[86,124],"111":[86,124],"227":[86,124],"228":[86,124],"236":[86,124],"237":[86,124],"254":[86,124],"255":[86,124],"267":[86,124],"273":[86,124],"274":[86,124],"286":[86,124],"287":[86,124],"289":[86,124]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/completions/base.completions.ts":{"11":[86,124],"13":[86,124],"14":[86,124],"17":[86,124],"24":[86,124],"53":[86,124],"105":[86,124],"140":[86,124],"147":[86,124]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/completions/execution.completions.ts":{"7":[86,124],"13":[86,124]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/completions/itemField.completions.ts":{"6":[86,124],"15":[86,124],"53":[86,124],"111":[86,124]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/completions/itemIndex.completions.ts":{"8":[86,124],"14":[86,124],"69":[86,124]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/completions/jsonField.completions.ts":{"12":[86,124],"16":[86,124],"29":[86,124],"78":[86,124],"131":[86,124],"176":[86,124],"196":[86,124],"206":[86,124],"207":[86,124],"224":[86,124],"225":[86,124],"245":[86,124]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/completions/luxon.completions.ts":{"8":[86,124],"12":[86,124],"30":[86,124],"48":[86,124],"58":[86,124],"59":[86,124],"73":[86,124],"75":[86,124],"76":[86,124],"84":[86,124],"85":[86,124]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/completions/prevNode.completions.ts":{"8":[86,124],"10":[86,124],"16":[86,124]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/completions/require.completions.ts":{"6":[86,124],"10":[86,124],"17":[86,124]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/completions/utils.ts":{"3":[86,124]},"packages/frontend/editor-ui/src/features/shared/editors/components/CodeNodeEditor/completions/workflow.completions.ts":{"6":[86,124],"8":[86,124],"14":[86,124]},"packages/frontend/editor-ui/src/features/shared/editors/components/CssEditor/CssEditor.vue":{"36":[86,124],"50":[86,124],"55":[86,124],"85":[86,124],"90":[86,124],"99":[86,124],"104":[86,124]},"packages/frontend/editor-ui/src/features/shared/editors/components/HtmlEditor/HtmlEditor.vue":{"51":[86,124,202],"63":[86,124,202],"68":[86,124,202],"97":[86,124,202],"100":[86,124,202],"105":[86,124],"120":[86,124],"137":[86,124],"143":[86,124],"149":[86,124],"156":[86,124],"161":[86,124],"170":[86,124],"237":[86,124,202],"243":[86,124,202],"247":[86,124,202],"251":[86,124],"260":[86,124,202],"265":[86,124,202]},"packages/frontend/editor-ui/src/features/shared/editors/components/HtmlEditor/utils.ts":{"10":[86,124],"44":[86,124,202]},"packages/frontend/editor-ui/src/features/shared/editors/components/SqlEditor/SqlEditor.vue":{"42":[86,124,202],"80":[86,124,202],"82":[86,124,202],"88":[86,124,202],"130":[86,124,202],"135":[86,124,202],"140":[86,124,202],"146":[86,124,202],"154":[86,124,202],"158":[86,124,202],"160":[86,124,202],"163":[86,124,202],"172":[86,124],"180":[86,124],"199":[86,124],"208":[86,124,202],"213":[86,124,202]},"packages/frontend/editor-ui/src/features/shared/editors/plugins/codemirror/typescript/client/hoverTooltip.ts":{"5":[86,124],"16":[86,124],"43":[86,124]},"packages/frontend/editor-ui/src/features/shared/tags/components/TagsManager/AnnotationTagsManager.ee.vue":{"11":[86,124],"16":[86,124],"17":[86,124],"19":[86,124],"29":[86,124],"44":[86,124],"64":[86,124],"85":[86,124]},"packages/frontend/editor-ui/src/features/workflow-reviews/module.descriptor.ts":{"8":[86,124],"9":[86,124],"21":[86,124]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/CanvasNodeAgent.vue":{"30":[86,124],"58":[86,124],"60":[86,124],"65":[86,124],"73":[86,124],"77":[86,124],"88":[86,124],"95":[86,124],"96":[86,124],"106":[86,124],"110":[86,124],"118":[86,124],"125":[86,124],"129":[86,124],"136":[86,124],"141":[86,124],"145":[86,124],"158":[86,124],"162":[86,124],"165":[86,124],"180":[86,124],"184":[86,124],"190":[86,124],"194":[86,124],"209":[86,124],"212":[86,124],"216":[86,124],"230":[86,124],"236":[86,124],"256":[86,124],"261":[86,124],"273":[86,124]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/parts/CanvasNodeAgentChips.vue":{"12":[86,124],"31":[86,124],"32":[86,124],"39":[86,124],"40":[86,124],"41":[86,124],"42":[86,124],"43":[86,124],"44":[86,124],"46":[86,124],"51":[86,124],"64":[86,124],"66":[86,124],"71":[86,124],"81":[86,124],"96":[86,124],"100":[86,124]},"packages/frontend/editor-ui/src/features/workflows/canvas/components/elements/nodes/render-types/parts/canvasNodeAgentChips.utils.ts":{"49":[86,124],"75":[86,124],"83":[86,124],"110":[86,124],"123":[86,124],"133":[86,124]},"packages/frontend/editor-ui/src/features/workflows/canvas/composables/nodeGroupTelemetry.utils.ts":{"4":[86,124],"11":[86,124]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/components/ExperimentalEmbeddedNdvActions.vue":{"6":[86,124],"7":[86,124],"17":[86,124],"25":[86,124]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/components/ExperimentalEmbeddedNdvHeader.vue":{"22":[86,124],"23":[86,124],"33":[86,124],"40":[86,124],"44":[86,124],"58":[86,124]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/components/ExperimentalEmbeddedNodeDetails.vue":{"25":[86,124],"28":[86,124],"34":[86,124],"35":[86,124],"43":[86,124],"56":[86,124],"62":[86,124],"66":[86,124],"70":[86,124],"78":[86,124],"81":[86,124],"107":[86,124],"119":[86,124],"122":[86,124]},"packages/frontend/editor-ui/src/features/workflows/canvas/experimental/experimentalNdv.utils.ts":{"5":[86,124],"25":[86,124],"26":[86,124]},"packages/frontend/editor-ui/src/features/workflows/components/DuplicateWorkflowDialog.vue":{"21":[86,124],"56":[86,124],"60":[86,124],"66":[86,124],"70":[86,124],"74":[86,124],"78":[86,124],"153":[86,124],"154":[86,124],"162":[86,124],"167":[86,124],"178":[86,124],"198":[86,124]},"packages/frontend/editor-ui/src/features/workflows/components/WorkflowActivationConflictingWebhookModal.vue":{"12":[86,124],"28":[86,124],"32":[86,124],"61":[86,124],"65":[86,124],"67":[86,124],"78":[86,124],"80":[86,124],"85":[86,124],"86":[86,124],"89":[86,124],"94":[86,124],"96":[86,124],"100":[86,124]},"packages/frontend/editor-ui/src/features/workflows/components/WorkflowActivationErrorMessage.vue":{"3":[86,124],"4":[86,124]},"packages/frontend/editor-ui/src/features/workflows/components/WorkflowSettings/WorkflowCustomTelemetryTags.vue":{"22":[86,124],"42":[86,124],"44":[86,124],"45":[86,124],"47":[86,124],"49":[86,124],"51":[86,124],"53":[86,124],"54":[86,124],"56":[86,124],"58":[86,124],"69":[86,124],"70":[86,124],"72":[86,124],"73":[86,124],"77":[86,124],"78":[86,124],"82":[86,124],"83":[86,124],"84":[86,124],"85":[86,124],"86":[86,124],"87":[86,124],"93":[86,124],"104":[86,124],"111":[86,124],"115":[86,124],"116":[86,124],"121":[86,124],"125":[86,124],"126":[86,124],"129":[86,124],"134":[86,124],"139":[86,124],"156":[86,124],"165":[86,124],"173":[86,124],"175":[86,124],"178":[86,124],"180":[86,124],"186":[86,124],"195":[86,124],"213":[86,124],"219":[86,124],"235":[86,124],"254":[86,124],"268":[86,124],"281":[86,124],"293":[86,124],"306":[86,124],"317":[86,124],"329":[86,124],"339":[86,124],"349":[86,124],"356":[86,124]},"packages/frontend/editor-ui/src/features/workflows/components/WorkflowShareModal.ee.vue":{"42":[86,124,195,196,81],"60":[86,124,195,196,81],"63":[86,124,195,196,81],"64":[86,124,195,196,81],"65":[86,124,196,81],"68":[86,124,195,196,81],"71":[86,124,195,196,81],"74":[86,124,195,196,81],"87":[86,124,195,196,81],"91":[86,124,195,196,81],"93":[86,124,195,196,81],"112":[86,124,195,196,81],"116":[86,124,195,196,81],"123":[86,124],"131":[86,124,196,81],"134":[86,124,195],"136":[86,124,195,196,81],"141":[86,124,195,196,81],"142":[86,124,195,196,81],"158":[86,124,196],"165":[86,124,196],"172":[86,124],"179":[86,124,196],"186":[86,124,196],"221":[86,124,196],"243":[86,124],"247":[86,124,195,196,81],"262":[86,124,195,196,81],"268":[86,124,196],"274":[86,124,195,196,81],"286":[86,124,195,196,81],"301":[86,124],"330":[86,124,195],"331":[86,124,195],"334":[86,124,195],"349":[86,124],"367":[86,124,195,196,81],"370":[86,124],"379":[86,124,195,196,81],"381":[86,124,195,196,81],"383":[86,124],"384":[86,124,195],"393":[86,124,196,81]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/DiffBadge.vue":{"4":[86,124],"8":[86,124],"21":[86,124],"33":[86,124]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/NodeDiff.vue":{"5":[86,124],"8":[86,124]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/WorkflowDiffAside.vue":{"8":[86,124],"14":[86,124],"19":[86,124],"26":[86,124],"38":[86,124],"42":[86,124],"48":[86,124]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/WorkflowDiffEmptyState.vue":{"10":[86,124],"11":[86,124]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/WorkflowDiffModal.vue":{"21":[86,124],"48":[86,124],"62":[86,124],"71":[86,124],"91":[86,124],"106":[86,124],"107":[86,124],"108":[86,124],"109":[86,124],"110":[86,124],"112":[86,124],"120":[86,124],"123":[86,124],"127":[86,124],"139":[86,124],"142":[86,124],"157":[86,124],"167":[86,124],"173":[86,124],"178":[86,124],"180":[86,124],"185":[86,124],"190":[86,124],"196":[86,124],"201":[86,124],"203":[86,124],"206":[86,124]},"packages/frontend/editor-ui/src/features/workflows/workflowDiff/WorkflowDiffNodeItem.vue":{"18":[86,124],"19":[86,124],"30":[86,124],"31":[86,124]},"packages/frontend/editor-ui/src/features/workflows/workflowHistory/components/WorkflowHistoryVersionUnpublishModal.vue":{"22":[86,124,81],"44":[86,124,81],"51":[86,124],"62":[86,124,81],"64":[86,124,81],"67":[86,124],"68":[86,124],"69":[86,124,81],"73":[86,124,81],"76":[86,124,81],"77":[86,124],"81":[86,124,81],"85":[86,124],"89":[86,124],"94":[86,124,81],"100":[86,124,81],"103":[86,124,81],"107":[86,124,81],"109":[86,124,81],"116":[86,124,81],"121":[86,124,81],"129":[86,124],"132":[86,124],"134":[86,124],"137":[86,124],"139":[86,124],"141":[86,124],"146":[86,124],"158":[86,124,81],"161":[86,124,81],"164":[86,124,81]},"packages/frontend/editor-ui/src/features/workflows/workflowHistory/components/WorkflowVersionFormModal.vue":{"27":[86,124],"41":[86,124],"43":[86,124],"47":[86,124],"61":[86,124],"65":[86,124],"69":[86,124],"74":[86,124],"84":[86,124],"96":[86,124],"97":[86,124],"99":[86,124]},"packages/import-package-request.dto.ts":{"42":[86,124],"80":[86,124]},"packages/modules/insights/frontend/src/insights.module.ts":{"5":[86,124],"18":[86,124],"19":[86,124],"35":[86,124]},"packages/modules/mcp/frontend/src/assets/client-icons/cursor.svgcomponent":{"8":[86,124]},"packages/modules/mcp/frontend/src/assets/client-icons/mistral.svgcomponent":{"8":[86,124]},"packages/modules/mcp/frontend/src/assets/client-icons/openai.svgcomponent":{"11":[86,124]},"packages/modules/mcp/frontend/src/assets/client-icons/vscode.svgcomponent":{"8":[86,124]},"packages/modules/mcp/frontend/src/clients.utils.ts":{"38":[86,124],"41":[86,124],"54":[86,124],"62":[86,124],"79":[86,124],"81":[86,124],"91":[86,124],"102":[86,124]},"packages/modules/mcp/frontend/src/components/McpAccessToggle.vue":{"15":[86,124],"27":[86,124],"33":[86,124],"35":[86,124],"42":[86,124],"51":[86,124]},"packages/modules/mcp/frontend/src/components/McpClientLogoCards.vue":{"11":[86,124],"21":[86,124],"23":[86,124],"29":[86,124],"31":[86,124],"37":[86,124],"38":[86,124],"40":[86,124],"46":[86,124],"51":[86,124]},"packages/modules/type-availability-policies/frontend/src/components/RestrictedToolCallout.vue":{"15":[86,124],"19":[86,124],"20":[86,124],"26":[86,124],"31":[86,124],"32":[86,124]},"packages/modules/type-availability-policies/frontend/src/policy-violations/PolicyViolationList.vue":{"9":[86,124],"32":[86,124],"40":[86,124],"46":[86,124],"53":[86,124],"66":[86,124],"70":[86,124],"72":[86,124],"77":[86,124],"88":[86,124],"93":[86,124],"104":[86,124],"106":[86,124],"108":[86,124]},"packages/modules/type-availability-policies/frontend/src/type-availability-policies.constants.ts":{"14":[86,124]},"packages/vite/expression-runtime-stub.ts":{"37":[86,124]},"packages/vite/node-fs-shim.ts":{"14":[86,124]},"packages/@n8n/ai-workflow-builder.ee/src/agents/planner.agent.ts":{"62":[11],"64":[11],"109":[11],"136":[11]},"packages/@n8n/ai-workflow-builder.ee/src/agents/responder.agent.ts":{"78":[11],"104":[11],"108":[11],"112":[11],"121":[11],"186":[11],"231":[11],"269":[11]},"packages/@n8n/ai-workflow-builder.ee/src/agents/supervisor.agent.ts":{"23":[11],"66":[11],"74":[11],"122":[11]},"packages/@n8n/ai-workflow-builder.ee/src/llm-config.ts":{"26":[11],"28":[11],"43":[11],"45":[11],"64":[11],"66":[11],"90":[11],"92":[11],"112":[11],"114":[11],"144":[11],"145":[11],"147":[11],"243":[11]},"packages/@n8n/ai-workflow-builder.ee/src/multi-agent-workflow-subgraphs.ts":{"56":[11],"73":[11],"113":[11],"118":[11],"187":[11],"194":[11],"211":[11],"252":[11],"275":[11],"286":[11],"353":[11],"379":[11],"391":[11],"392":[11],"402":[11],"403":[11],"406":[11],"433":[11],"444":[11],"452":[11],"506":[11],"525":[11],"527":[11],"536":[11],"544":[11]},"packages/@n8n/ai-workflow-builder.ee/src/prompts/agents/discovery.prompt.ts":{"30":[11],"32":[11],"36":[11],"38":[11],"347":[11],"358":[11],"368":[11],"372":[11]},"packages/@n8n/ai-workflow-builder.ee/src/prompts/agents/planner.prompt.ts":{"73":[11],"98":[11],"109":[11],"122":[11],"129":[11],"130":[11]},"packages/@n8n/ai-workflow-builder.ee/src/prompts/agents/responder.prompt.ts":{"168":[11],"178":[11],"188":[11],"200":[11],"205":[11],"226":[11],"232":[11],"244":[11]},"packages/@n8n/ai-workflow-builder.ee/src/prompts/builder/prompt-builder.ts":{"17":[11],"30":[11],"44":[11],"55":[11],"79":[11],"116":[11],"129":[11],"149":[11],"175":[11],"197":[11],"228":[11],"252":[11],"268":[11],"282":[11],"302":[11],"330":[11],"357":[11]},"packages/@n8n/ai-workflow-builder.ee/src/prompts/index.ts":{"31":[11],"45":[11],"47":[11]},"packages/@n8n/ai-workflow-builder.ee/src/subgraphs/discovery.subgraph.ts":{"104":[11],"105":[11],"110":[11],"111":[11],"116":[11],"117":[11],"122":[11],"123":[11],"128":[11],"129":[11],"134":[11],"135":[11],"140":[11],"141":[11],"146":[11],"147":[11],"152":[11],"153":[11],"176":[11],"177":[11],"182":[11],"188":[11],"194":[11],"200":[11],"201":[11],"206":[11],"207":[11],"212":[11],"213":[11],"218":[11],"219":[11],"224":[11],"225":[11],"230":[11],"231":[11],"238":[11],"239":[11],"277":[11],"305":[11],"308":[11],"352":[11],"378":[11],"397":[11],"441":[11],"448":[11],"495":[11],"502":[11],"562":[11],"564":[11],"592":[11],"660":[11],"671":[11],"710":[11],"722":[11],"770":[11],"796":[11]},"packages/@n8n/ai-workflow-builder.ee/src/tools/get-documentation.tool.ts":{"60":[11],"81":[11],"88":[11],"113":[11],"115":[11],"136":[11],"146":[11]},"packages/@n8n/ai-workflow-builder.ee/src/tools/node-search.tool.ts":{"46":[11],"91":[11],"105":[11],"121":[11],"123":[11],"170":[11]},"packages/@n8n/ai-workflow-builder.ee/src/tools/utils/web-fetch-security.ts":{"35":[11],"48":[11],"55":[11],"61":[11],"64":[11],"67":[11],"70":[11],"111":[11],"112":[11],"120":[11],"121":[11],"122":[11],"123":[11],"127":[11],"131":[11],"144":[11],"146":[11],"163":[11],"167":[11]},"packages/@n8n/ai-workflow-builder.ee/src/tools/web-fetch.tool.ts":{"30":[11],"69":[11],"83":[11],"86":[11]},"packages/@n8n/ai-workflow-builder.ee/src/utils/thread-id.ts":{"7":[11]},"packages/@n8n/ai-workflow-builder.ee/src/utils/workflow-sanitization.ts":{"12":[11],"25":[11],"31":[11],"53":[11]},"packages/@n8n/ai-workflow-builder.ee/src/workflow-builder-agent.ts":{"167":[11],"185":[11],"197":[11],"205":[11],"215":[11],"236":[11],"317":[11],"346":[11],"364":[11],"394":[11],"412":[11],"443":[11],"465":[11],"478":[11],"517":[11],"589":[11],"604":[11],"620":[11],"670":[11],"688":[11],"692":[11]},"packages/@n8n/api-types/src/dto/ai/ai-build-request.dto.ts":{"41":[11],"51":[11],"61":[11],"63":[11],"72":[11],"75":[11],"86":[11],"95":[11]},"packages/cli/src/modules/workflow-builder/workflow-builder-session.repository.ts":{"22":[11],"26":[11],"46":[11],"73":[11],"78":[11]},"localhost-37077/assets/index-BoK1c_f3.js":{"3":[11]},"localhost-37077/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[11],"9":[11],"10":[11],"19":[11],"23":[11],"29":[11],"33":[11],"34":[11]},"localhost-33049/assets/index-BoK1c_f3.js":{"3":[148,16,122,164,187,195,196]},"localhost-33049/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[148,16,122,164,187,195,196],"9":[148,16,122,164,187,195,196],"10":[148,16,122,164,187,195,196],"19":[148,16,122,164,187,195,196],"23":[148,16,122,164,187,195,196],"29":[148,16,122,164,187,195,196],"33":[148,16,122,164,187,195,196],"34":[148,16,122,164,187,195,196]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/WorkflowBuilderUnavailableNotice.vue":{"7":[16],"10":[16],"15":[16],"22":[16]},"packages/cli/src/controllers/password-reset.controller.ts":{"46":[106],"72":[106],"117":[106],"174":[106],"203":[106],"234":[106]},"packages/cli/src/middlewares/jitter.ts":{"15":[106],"19":[106]},"packages/cli/src/user-management/email/node-mailer.ts":{"19":[106],"48":[106],"84":[106]},"localhost-40951/assets/index-BoK1c_f3.js":{"3":[19]},"localhost-40951/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[19],"9":[19],"10":[19],"19":[19],"23":[19],"29":[19],"33":[19],"34":[19]},"packages/frontend/editor-ui/src/features/ai/components/CredentialSelectorModal.vue":{"36":[19],"37":[19],"46":[19],"108":[19],"116":[19],"120":[19],"123":[19],"147":[19],"150":[19]},"localhost-33049/assets/verified-Pt0guxqN.js":{"8":[164,195]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/ftp.svg":{"11":[164]},"packages/nodes-base/nodes/EmailSend/EmailSend.node.ts":{"8":[40]},"packages/nodes-base/nodes/EmailSend/utils.ts":{"1":[40]},"packages/nodes-base/nodes/EmailSend/v1/EmailSendV1.node.ts":{"136":[40],"143":[40]},"packages/nodes-base/nodes/EmailSend/v2/EmailSendV2.node.ts":{"88":[40],"101":[40]},"packages/nodes-base/nodes/EmailSend/v2/send.operation.ts":{"186":[40]},"packages/nodes-base/nodes/EmailSend/v2/sendAndWait.operation.ts":{"28":[40]},"packages/nodes-base/nodes/EmailSend/v2/utils.ts":{"20":[40],"54":[40]},"localhost-44919/assets/index-BoK1c_f3.js":{"3":[40]},"localhost-44919/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[40],"9":[40],"10":[40],"19":[40],"23":[40],"29":[40],"33":[40],"34":[40]},"packages/@n8n/errors/src/response-errors/scope-forbidden.error.ts":{"4":[47]},"packages/@n8n/errors/src/response-errors/unprocessable.error.ts":{"4":[47]},"packages/cli/src/executions/execution-redaction.ts":{"44":[47]},"packages/cli/src/modules/redaction/executions/strategies/full-item-redaction.strategy.ts":{"17":[47],"20":[47],"25":[47],"82":[47],"95":[47],"113":[47]},"packages/cli/src/modules/redaction/instance-redaction-enforcement.service.ts":{"16":[47],"33":[47],"37":[47],"39":[47],"46":[47],"64":[47],"84":[47],"88":[47],"97":[47]},"packages/cli/src/modules/redaction/redaction-policy.ts":{"37":[47],"48":[47]},"packages/cli/src/public-api/v1/controllers/executions.public.controller.ts":{"54":[47],"60":[47],"91":[47],"106":[47],"172":[47],"228":[47],"255":[47],"281":[47],"298":[47],"311":[47],"316":[47],"355":[47],"394":[47],"436":[47],"445":[47],"469":[47],"494":[47],"504":[47],"521":[47],"531":[47],"540":[47],"550":[47]},"localhost-42161/assets/index-BoK1c_f3.js":{"3":[47]},"localhost-42161/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[47],"9":[47],"10":[47],"19":[47],"23":[47],"29":[47],"33":[47],"34":[47]},"packages/frontend/editor-ui/src/features/settings/security/DataRedactionSection.vue":{"39":[47],"57":[47],"62":[47],"63":[47],"72":[47],"76":[47],"77":[47],"85":[47],"94":[47],"121":[47],"139":[47],"152":[47],"162":[47],"164":[47],"170":[47],"176":[47],"181":[47],"215":[47],"223":[47],"263":[47],"265":[47]},"packages/frontend/editor-ui/src/features/settings/security/SecuritySettings.vue":{"45":[47],"49":[47],"75":[47],"89":[47],"96":[47],"130":[47],"152":[47],"173":[47],"203":[47],"206":[47],"208":[47],"210":[47],"214":[47],"217":[47],"226":[47],"261":[47],"264":[47],"266":[47],"272":[47],"275":[47],"313":[47],"315":[47],"323":[47],"325":[47],"331":[47],"334":[47],"372":[47],"374":[47]},"packages/nodes-base/nodes/Reddit/GenericFunctions.ts":{"14":[187],"57":[187],"79":[187],"81":[187],"85":[187],"100":[187]},"packages/nodes-base/nodes/Reddit/Reddit.node.ts":{"87":[187],"328":[187],"370":[187]},"localhost-37889/assets/index-BoK1c_f3.js":{"3":[44]},"localhost-37889/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[44],"9":[44],"10":[44],"19":[44],"23":[44],"29":[44],"33":[44],"34":[44]},"packages/nodes-base/nodes/Discourse/Discourse.node.ts":{"93":[176],"107":[176]},"packages/nodes-base/nodes/Discourse/GenericFunctions.ts":{"11":[176],"40":[176]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/filter.svg":{"11":[176,136]},"localhost-45893/assets/index-BoK1c_f3.js":{"3":[57]},"localhost-45893/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[57],"9":[57],"10":[57],"19":[57],"23":[57],"29":[57],"33":[57],"34":[57]},"packages/cli/src/task-runners/errors/task-cancelled.error.ts":{"4":[225]},"packages/cli/src/utils/object-to-error.ts":{"13":[225]},"localhost-41785/assets/index-BoK1c_f3.js":{"3":[91]},"localhost-41785/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[91],"9":[91],"10":[91],"19":[91],"23":[91],"29":[91],"33":[91],"34":[91]},"localhost-33177/assets/index-BoK1c_f3.js":{"3":[96,202,81]},"localhost-33177/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[96,202,81],"9":[96,202,81],"10":[96,202,81],"19":[96,202,81],"23":[96,202,81],"29":[96,202,81],"33":[96,202,81],"34":[96,202,81]},"localhost-33177/assets/verified-Pt0guxqN.js":{"8":[96,202]},"packages/nodes-base/nodes/Html/Html.node.ts":{"19":[202],"23":[202],"24":[202],"383":[202],"429":[202],"435":[202],"451":[202],"474":[202],"579":[202]},"packages/nodes-base/nodes/Html/utils.ts":{"10":[202],"12":[202],"13":[202],"21":[202],"29":[202],"39":[202]},"packages/frontend/editor-ui/src/features/shared/nodeCreator/components/ItemTypes/OpenTemplateItem.vue":{"14":[167],"23":[167]},"packages/frontend/@n8n/design-system/src/components/N8nIcon/nodes/html.svg":{"11":[202]},"packages/cli/src/modules/agents/agents-list.controller.ts":{"27":[81],"30":[81],"47":[81],"56":[81],"80":[81]},"packages/@n8n/ai-utilities/src/agent-config/config-normalization.ts":{"64":[1],"88":[1],"107":[1],"124":[1],"143":[1],"156":[1],"166":[1],"177":[1],"183":[1],"204":[1]},"packages/cli/src/modules/agents/agent-config-preparation.service.ts":{"28":[1],"34":[1],"42":[1],"60":[1],"61":[1],"70":[1],"103":[1],"110":[1],"126":[1],"129":[1]},"packages/cli/src/modules/agents/agent-modification-telemetry.service.ts":{"67":[1],"74":[1],"101":[1],"111":[1],"137":[1],"162":[1],"164":[1],"187":[1]},"packages/cli/src/modules/agents/agent-save-completion.service.ts":{"13":[1],"19":[1],"30":[1],"40":[1],"44":[1],"52":[1]},"packages/cli/src/modules/agents/agent-setup-completion.service.ts":{"37":[1],"49":[1],"81":[1],"94":[1],"98":[1],"104":[1]},"packages/cli/src/modules/agents/agent-update-broadcaster.ts":{"17":[1],"27":[1],"28":[1],"36":[1],"51":[1]},"packages/cli/src/modules/agents/integrations/chat-integration.service.ts":{"122":[1],"145":[1],"181":[1],"203":[1],"216":[1],"230":[1],"248":[1],"266":[1],"283":[1],"310":[1],"329":[1],"371":[1],"431":[1],"442":[1],"474":[1],"482":[1],"528":[1],"547":[1],"562":[1],"596":[1],"613":[1],"619":[1],"645":[1],"656":[1],"668":[1],"672":[1],"682":[1],"690":[1],"712":[1],"726":[1],"734":[1],"740":[1],"765":[1],"787":[1],"807":[1],"808":[1],"811":[1],"830":[1],"852":[1],"912":[1],"922":[1],"943":[1],"961":[1],"971":[1],"975":[1],"1003":[1],"1012":[1],"1013":[1],"1022":[1],"1032":[1],"1037":[1],"1063":[1],"1099":[1],"1114":[1],"1122":[1],"1123":[1],"1133":[1],"1140":[1],"1149":[1],"1168":[1],"1172":[1],"1254":[1],"1273":[1],"1279":[1],"1285":[1],"1293":[1],"1308":[1],"1325":[1],"1331":[1],"1339":[1],"1352":[1],"1382":[1]},"packages/cli/src/modules/agents/integrations/integrations-sync.ts":{"18":[1]},"packages/cli/src/modules/agents/json-config/node-tool-ai-gateway.service.ts":{"16":[1],"21":[1]},"packages/cli/src/modules/agents/json-config/prune-missing-config-references.ts":{"10":[1],"17":[1],"20":[1],"28":[1]},"packages/cli/src/modules/agents/json-config/reconcile-node-tool-gateway-credentials.ts":{"14":[1],"22":[1],"35":[1],"53":[1],"59":[1],"71":[1],"93":[1],"110":[1],"133":[1],"166":[1],"169":[1],"185":[1],"199":[1],"201":[1],"207":[1],"250":[1]},"packages/cli/src/modules/agents/utils/agent-capabilities.ts":{"28":[1],"32":[1],"38":[1],"41":[1],"45":[1],"46":[1],"50":[1],"54":[1],"63":[1],"84":[1]},"packages/cli/src/modules/agents/utils/agent-draft.utils.ts":{"14":[1],"26":[1]},"localhost-34529/assets/index-BoK1c_f3.js":{"3":[1]},"localhost-34529/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[1],"9":[1],"10":[1],"19":[1],"23":[1],"29":[1],"33":[1],"34":[1]},"packages/@n8n/instance-ai/src/source-map-filter.ts":{"11":[89],"28":[89],"39":[89],"42":[89]},"packages/cli/src/modules/provisioning.ee/claims-context.builder.ts":{"3":[89],"17":[89],"29":[89]},"packages/cli/src/modules/provisioning.ee/role-mapping-rule.service.ee.ts":{"47":[89],"54":[89],"81":[89],"85":[89],"124":[89],"162":[89],"180":[89],"214":[89],"273":[89],"309":[89],"315":[89],"348":[89],"354":[89],"373":[89],"376":[89],"393":[89],"403":[89],"405":[89],"408":[89],"424":[89],"431":[89]},"packages/cli/src/modules/sso-oidc/oidc.controller.ee.ts":{"32":[89],"45":[89],"56":[89],"74":[89],"96":[89],"119":[89],"232":[89]},"packages/cli/src/modules/sso-oidc/oidc.service.ee.ts":{"73":[89],"92":[89],"106":[89],"115":[89],"121":[89],"125":[89],"137":[89],"152":[89],"193":[89],"201":[89],"234":[89],"240":[89],"286":[89],"383":[89],"416":[89],"425":[89],"443":[89],"469":[89],"478":[89],"518":[89],"582":[89],"583":[89],"595":[89],"620":[89],"631":[89],"641":[89],"672":[89],"705":[89],"715":[89],"771":[89],"795":[89],"829":[89]},"localhost-39389/assets/index-BoK1c_f3.js":{"3":[89]},"localhost-39389/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[89],"9":[89],"10":[89],"19":[89],"23":[89],"29":[89],"33":[89],"34":[89]},"localhost-46005/assets/index-BoK1c_f3.js":{"3":[30,159,36]},"localhost-46005/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[30,159,36],"9":[30,159,36],"10":[30,159,36],"19":[30,159,36],"23":[30,159,36],"29":[30,159,36],"33":[30,159,36],"34":[30,159,36]},"packages/frontend/editor-ui/src/features/ai/instanceAi/components/AgentSection.vue":{"17":[30],"24":[30],"27":[30],"35":[30],"60":[30],"68":[30],"74":[30],"75":[30],"76":[30],"78":[30]},"localhost-35415/assets/index-BoK1c_f3.js":{"3":[45]},"localhost-35415/assets/rolldown-runtime-Bq5D3eIA.js":{"8":[45],"9":[45],"10":[45],"19":[45],"23":[45],"29":[45],"33":[45],"34":[45]},"packages/cli/src/execution-lifecycle/save-execution-progress.ts":{"8":[136]}}} \ No newline at end of file diff --git a/.github/workflows/ci-pull-requests.yml b/.github/workflows/ci-pull-requests.yml index 8b1760f09f4..128b347f98a 100644 --- a/.github/workflows/ci-pull-requests.yml +++ b/.github/workflows/ci-pull-requests.yml @@ -80,6 +80,7 @@ jobs: !**/*.test.ts !**/*.spec.ts !packages/quality/testing/playwright/** + !packages/quality/efficiency/** !packages/frontend/@n8n/storybook/** !.devcontainer/** !scripts/agent-setup.mjs @@ -146,10 +147,17 @@ jobs: cubic.yaml .agents/review-rules/** e2e-performance: + packages/quality/efficiency/memory/idle/** + packages/quality/efficiency/playwright.config.ts + packages/quality/efficiency/package.json + packages/quality/testing/playwright/package.json + packages/quality/testing/playwright/quality-*.ts + packages/quality/testing/playwright/fixtures/** packages/quality/testing/playwright/tests/performance/** packages/quality/testing/playwright/utils/performance-helper.ts packages/quality/environments/containers/** .github/workflows/test-e2e-performance-reusable.yml + .github/workflows/test-e2e-reusable.yml # Whole directories, not the `engine-*` files alone. Engine v2 # routing lives in ordinary control plane code: `workflow-runner.ts` # and the webhook and trigger paths decide whether a run reaches the diff --git a/.github/workflows/prepare-docker-reusable.yml b/.github/workflows/prepare-docker-reusable.yml index 77b2e2b854b..0705c35f638 100644 --- a/.github/workflows/prepare-docker-reusable.yml +++ b/.github/workflows/prepare-docker-reusable.yml @@ -9,6 +9,16 @@ name: 'Prepare n8n Docker (reusable)' on: workflow_call: + secrets: + QA_METRICS_WEBHOOK_URL: + description: 'QA metrics webhook URL.' + required: false + QA_METRICS_WEBHOOK_USER: + description: 'QA metrics webhook username.' + required: false + QA_METRICS_WEBHOOK_PASSWORD: + description: 'QA metrics webhook password.' + required: false inputs: build-variant: description: 'standard, coverage, or pc' diff --git a/.github/workflows/test-e2e-performance-reusable.yml b/.github/workflows/test-e2e-performance-reusable.yml index afa265e949e..8680a2d1d6e 100644 --- a/.github/workflows/test-e2e-performance-reusable.yml +++ b/.github/workflows/test-e2e-performance-reusable.yml @@ -1,5 +1,8 @@ name: 'Test: E2E Performance' +permissions: + contents: read + on: workflow_call: workflow_dispatch: @@ -24,6 +27,17 @@ jobs: artifact-prefix: performance secrets: inherit + idle-memory-baselines: + needs: [prepare-docker] + uses: ./.github/workflows/test-e2e-reusable.yml + with: + test-mode: docker-artifact + test-command: pnpm --filter=@n8n/efficiency test:memory + workers: '1' + currents-project-id: 'O9BJaN' + artifact-prefix: memory-performance + secrets: inherit + canvas-perf-sentinels: name: Canvas Perf Sentinels # Sentinels are nightly only — wall-clock browser perf has 15-30% variance, diff --git a/.github/workflows/test-e2e-reusable.yml b/.github/workflows/test-e2e-reusable.yml index cc744bf2371..3f19de577fa 100644 --- a/.github/workflows/test-e2e-reusable.yml +++ b/.github/workflows/test-e2e-reusable.yml @@ -195,9 +195,10 @@ jobs: with: name: ${{ inputs.artifact-prefix }}-shard-${{ matrix.shard }} path: | - packages/quality/testing/playwright/test-results/ - packages/quality/testing/playwright/test-results.json - packages/quality/testing/playwright/playwright-report/ + packages/quality/*/test-results* + packages/quality/*/playwright-report/ + packages/quality/*/*/test-results* + packages/quality/*/*/playwright-report/ packages/quality/testing/playwright/coverage/lcov.info packages/quality/testing/playwright/coverage/by-spec/ packages/quality/testing/playwright/coverage/index.html diff --git a/.github/workflows/test-image-efficiency.yml b/.github/workflows/test-image-efficiency.yml new file mode 100644 index 00000000000..85898e33435 --- /dev/null +++ b/.github/workflows/test-image-efficiency.yml @@ -0,0 +1,71 @@ +name: 'Test: Image Efficiency' + +on: + workflow_dispatch: + +permissions: + contents: read + +jobs: + prepare-docker: + uses: ./.github/workflows/prepare-docker-reusable.yml + secrets: + QA_METRICS_WEBHOOK_URL: ${{ secrets.QA_METRICS_WEBHOOK_URL }} + QA_METRICS_WEBHOOK_USER: ${{ secrets.QA_METRICS_WEBHOOK_USER }} + QA_METRICS_WEBHOOK_PASSWORD: ${{ secrets.QA_METRICS_WEBHOOK_PASSWORD }} + + image-efficiency: + name: Image Efficiency + needs: prepare-docker + runs-on: ${{ vars.RUNNER_PROVIDER == 'github' && 'ubuntu-latest' || 'blacksmith-2vcpu-ubuntu-2204' }} + timeout-minutes: 20 + env: + CURRENTS_RECORD_KEY: ${{ secrets.CURRENTS_RECORD_KEY }} + CURRENTS_PROJECT_ID: 'nHHLA5' + CURRENTS_CI_BUILD_ID: ${{ github.repository }}-${{ github.run_id }}-${{ github.run_attempt }}-images + QA_METRICS_WEBHOOK_URL: ${{ secrets.QA_METRICS_WEBHOOK_URL }} + QA_METRICS_WEBHOOK_USER: ${{ secrets.QA_METRICS_WEBHOOK_USER }} + QA_METRICS_WEBHOOK_PASSWORD: ${{ secrets.QA_METRICS_WEBHOOK_PASSWORD }} + steps: + - name: Checkout + uses: useblacksmith/checkout@bcec731f1eb1367240608d1c889a75b96db6ec53 # v1.5.0 + + - name: Setup Environment + uses: ./.github/actions/setup-nodejs + with: + build-command: pnpm turbo run build --filter=@n8n/utils... + + - name: Load images from cache + uses: ./.github/actions/load-n8n-docker + + - name: Install Dive + shell: bash + run: | + set -euo pipefail + # Keep this version in sync with efficiency/images/dive-results.ts. + VERSION=0.13.1 + DIR=$(mktemp -d "$RUNNER_TEMP/dive.XXXXXX") + ARCHIVE="$DIR/dive.tar.gz" + curl --fail --location --retry 3 \ + "https://github.com/wagoodman/dive/releases/download/v${VERSION}/dive_${VERSION}_linux_amd64.tar.gz" \ + --output "$ARCHIVE" + echo "0970549eb4a306f8825a84145a2534153badb4d7dcf3febd1967c706367c3d0e $ARCHIVE" | sha256sum --check + tar -xzf "$ARCHIVE" -C "$DIR" dive + echo "$DIR" >> "$GITHUB_PATH" + + - name: Measure image layer efficiency + run: >- + pnpm --filter=@n8n/efficiency exec playwright test + --project=image-efficiency:n8n --project=image-efficiency:runners + + - name: Upload image efficiency reports + if: always() + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: image-efficiency-${{ github.run_attempt }} + path: | + packages/quality/efficiency/test-results/ + packages/quality/efficiency/test-results.json + packages/quality/efficiency/playwright-report/ + retention-days: 7 + if-no-files-found: ignore diff --git a/.github/workflows/util-update-get-n8n-versions.yml b/.github/workflows/util-update-get-n8n-versions.yml new file mode 100644 index 00000000000..21b403ac47c --- /dev/null +++ b/.github/workflows/util-update-get-n8n-versions.yml @@ -0,0 +1,118 @@ +name: 'Util: Update get-n8n Versions' + +on: + schedule: + # Run every Wednesday at 04:00 UTC. + - cron: '0 4 * * 3' + workflow_dispatch: + +permissions: {} + +concurrency: + group: update-get-n8n-versions + cancel-in-progress: false + +jobs: + update-versions: + name: Update get-n8n versions + if: >- + github.ref_name == github.event.repository.default_branch && + (github.event_name == 'workflow_dispatch' || + (github.event_name == 'schedule' && github.repository == 'n8n-io/n8n')) + runs-on: ubuntu-latest + timeout-minutes: 25 + permissions: + contents: read + steps: + - name: Generate GitHub App Token + id: generate-token + uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1 + with: + app-id: ${{ secrets.N8N_ASSISTANT_APP_ID }} + private-key: ${{ secrets.N8N_ASSISTANT_PRIVATE_KEY }} + permission-contents: write + permission-pull-requests: write + + - name: Checkout repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + - name: Resolve stable versions + id: versions + env: + GH_TOKEN: ${{ steps.generate-token.outputs.token }} + run: | + n8n_version="$(gh api repos/n8n-io/n8n/releases/latest --jq '.tag_name | sub("^n8n@"; "")')" + + registry_token="$(curl -fsSL --retry 3 'https://ghcr.io/token?scope=repository:n8n-io/n8n-sandbox-service-api:pull' | jq -er '.token')" + stable_digest="$(docker buildx imagetools inspect \ + 'ghcr.io/n8n-io/n8n-sandbox-service-api:stable' \ + --format '{{json .Manifest}}' | jq -er '.digest')" + sandbox_version='' + while IFS= read -r version; do + version_digest="$(docker buildx imagetools inspect \ + "ghcr.io/n8n-io/n8n-sandbox-service-api:${version}" \ + --format '{{json .Manifest}}' | jq -er '.digest')" + if [ "$version_digest" = "$stable_digest" ]; then + sandbox_version="$version" + break + fi + done < <(curl -fsSL --retry 3 \ + -H "Authorization: Bearer $registry_token" \ + 'https://ghcr.io/v2/n8n-io/n8n-sandbox-service-api/tags/list?n=1000' | + jq -r '.tags[]' | + grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' | + sort -Vr) + + printf '%s\n' "$n8n_version" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$' + printf '%s\n' "$sandbox_version" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$' + + for image in api runner-dind sandbox; do + docker manifest inspect "ghcr.io/n8n-io/n8n-sandbox-service-${image}:${sandbox_version}" >/dev/null + done + + sed -i "s/^FALLBACK_N8N_VERSION=.*/FALLBACK_N8N_VERSION=\"${n8n_version}\"/" docker/get-n8n.sh + sed -i "s/^SANDBOX_VERSION=.*/SANDBOX_VERSION=\"${sandbox_version}\"/" docker/get-n8n.sh + + echo "n8n_version=$n8n_version" >> "$GITHUB_OUTPUT" + echo "sandbox_version=$sandbox_version" >> "$GITHUB_OUTPUT" + + - name: Check for changes + id: changes + run: | + if git diff --quiet -- docker/get-n8n.sh; then + echo 'has-changes=false' >> "$GITHUB_OUTPUT" + else + echo 'has-changes=true' >> "$GITHUB_OUTPUT" + fi + + - name: Test installer upgrade + if: steps.changes.outputs.has-changes == 'true' + run: | + shellcheck docker/get-n8n.sh docker/test-get-n8n.sh + dash -n docker/get-n8n.sh + dash -n docker/test-get-n8n.sh + sh docker/test-get-n8n.sh --e2e + + - name: Create pull request + if: steps.changes.outputs.has-changes == 'true' + uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0 + with: + token: ${{ steps.generate-token.outputs.token }} + add-paths: docker/get-n8n.sh + commit-message: 'chore: Update get-n8n fallback versions' + labels: 'automation:scheduled-update' + title: 'chore: Update get-n8n fallback versions' + body: | + This automated PR updates the get-n8n fallback release to ${{ steps.versions.outputs.n8n_version }}. + It also updates the sandbox service release to ${{ steps.versions.outputs.sandbox_version }}. + + The workflow verified that all sandbox images use the same release. It also upgraded a legacy installation to these versions and checked the running stack. + + _Generated by the weekly get-n8n version update workflow._ + branch: update-get-n8n-versions + base: master + delete-branch: true + author: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> + committer: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> diff --git a/AGENTS.md b/AGENTS.md index eb33b4b068d..fd89097760a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -14,6 +14,11 @@ frontend, and extensible node-based workflow engine. - Write all technical text (code comments, PR descriptions, issue and ticket descriptions, docs) in ASD-STE100 Simplified Technical English: use short sentences, the active voice, and one instruction for each sentence +- **JSDoc on `@Env(...)` config properties is public documentation.** The + docs team exports these comments into the environment variable reference on + docs.n8n.io. Write them for a self-hosting operator and follow the + `n8n:env-var-docs` skill, which applies the n8n docs style guide and + overrides the ASD-STE100 rule above for these comments - **Secrets on the command line:** if a developer opted into anonymous dev metrics (`scripts/dev-metrics`), pnpm command arguments are recorded. Arguments of secret-carrying words (`config`, `login`, `publish`, `token`) — whether a diff --git a/CHANGELOG.md b/CHANGELOG.md index 55b772c9d1f..01548a16c83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,158 @@ +# [2.44.0](https://github.com/n8n-io/n8n/compare/n8n@2.43.0...n8n@2.44.0) (2026-10-13) + + +### Bug Fixes + +* Align execution retry menu and clarify actions ([#40710](https://github.com/n8n-io/n8n/issues/40710)) ([84d2fd6](https://github.com/n8n-io/n8n/commit/84d2fd6f3ae68e973aa49f7e2b1dd5dbf06ad18c)) +* Allow per-process crash journal paths ([#37670](https://github.com/n8n-io/n8n/issues/37670)) ([447e939](https://github.com/n8n-io/n8n/commit/447e939b732b778662572098d81f014527e3ffe2)) +* **core:** Allow reverting a workflow version that uses credentials the user cannot use ([#40701](https://github.com/n8n-io/n8n/issues/40701)) ([033a9b5](https://github.com/n8n-io/n8n/commit/033a9b512c2d52d05b43d4dd2d0e10634dc36e2a)) +* **core:** Apply node type policies to agent node tools ([#39711](https://github.com/n8n-io/n8n/issues/39711)) ([e7d8533](https://github.com/n8n-io/n8n/commit/e7d8533880df0d36438e39a07f0594fcaaaaab55)) +* **core:** Apply the credential type policy to credential tests and probes ([#39927](https://github.com/n8n-io/n8n/issues/39927)) ([9191cf3](https://github.com/n8n-io/n8n/commit/9191cf3fb07ce6bbb7b2217592ce56372b52f6c2)) +* **core:** Block the assistant when AI credits hit zero ([#40659](https://github.com/n8n-io/n8n/issues/40659)) ([8b7065a](https://github.com/n8n-io/n8n/commit/8b7065a87684bb3a055d8bcfc5d34c9b70094080)) +* **core:** Check the credential save policy before package import creates stubs ([#40687](https://github.com/n8n-io/n8n/issues/40687)) ([a3391ba](https://github.com/n8n-io/n8n/commit/a3391ba93c4574405d06e79e2efc791b6ba8a21f)) +* **core:** Check the target project's policy on folder, credential and delete-transfer moves ([#40301](https://github.com/n8n-io/n8n/issues/40301)) ([77370af](https://github.com/n8n-io/n8n/commit/77370af99a273073faf7df57a1fe8f71d3833bbe)) +* **core:** Count jobs as running from the start of job processing ([#40050](https://github.com/n8n-io/n8n/issues/40050)) ([dc5c80f](https://github.com/n8n-io/n8n/commit/dc5c80f26af8d32e5887ccbf7634f3da1be5f771)) +* **core:** Expose 1Password fields for secret preview and autocomplete ([#40538](https://github.com/n8n-io/n8n/issues/40538)) ([bef5f3f](https://github.com/n8n-io/n8n/commit/bef5f3f97aca163ac289af61e10869c0fa7fff60)) +* **core:** Fix Kimi K3 and other OpenAI-compatible Assistant model providers on self-hosted Assistant ([#40439](https://github.com/n8n-io/n8n/issues/40439)) ([1ef7756](https://github.com/n8n-io/n8n/commit/1ef77564e3bef2e34c57d8a67df892ace3858a5d)) +* **core:** Handle each Chat Hub segment once in queue mode ([#40791](https://github.com/n8n-io/n8n/issues/40791)) ([9ff8d4f](https://github.com/n8n-io/n8n/commit/9ff8d4fc738ca0e54db863c574e5a6d93df9ce2e)) +* **core:** Improve node placement when n8n Assistant edits a workflow ([#40139](https://github.com/n8n-io/n8n/issues/40139)) ([d900743](https://github.com/n8n-io/n8n/commit/d900743bce0cf8274c42e1f4a579fc8b5cf74997)) +* **core:** Keep waiting executions unchanged when a resume request fails ([#40683](https://github.com/n8n-io/n8n/issues/40683)) ([bbd35e2](https://github.com/n8n-io/n8n/commit/bbd35e281b100a36aa209518c5ab027eabf85a1f)) +* **core:** Let the editor download binary data of an Engine v2 execution ([#40663](https://github.com/n8n-io/n8n/issues/40663)) ([c9cb3ee](https://github.com/n8n-io/n8n/commit/c9cb3ee3abd23fe146cd4a2daed49c4bddb80d97)) +* **core:** Let the streaming heartbeat stop on Chat Hub responses ([#40792](https://github.com/n8n-io/n8n/issues/40792)) ([ee8a608](https://github.com/n8n-io/n8n/commit/ee8a608a22ec7a23dc795ee0554edd34186e87d2)) +* **core:** Match regex case-insensitively when ignore case is enabled ([#33589](https://github.com/n8n-io/n8n/issues/33589)) ([2596f3a](https://github.com/n8n-io/n8n/commit/2596f3ac1c657aa4d2ddf40430b9e5940fb9c1b0)) +* **core:** Match the Brazilian real symbol in the in-isolate currency regex ([#40893](https://github.com/n8n-io/n8n/issues/40893)) ([d3deffb](https://github.com/n8n-io/n8n/commit/d3deffbfa59d358614458f8b1ae2d56d118a9ca5)) +* **core:** Pass `storedAt` into `WorkflowExecute` at every callsite ([#40495](https://github.com/n8n-io/n8n/issues/40495)) ([5ab2187](https://github.com/n8n-io/n8n/commit/5ab21874169d44eb01a19d6f0ba19bb7a254d952)) +* **core:** Remove credentials of deleted projects on source control pull ([#40692](https://github.com/n8n-io/n8n/issues/40692)) ([978f810](https://github.com/n8n-io/n8n/commit/978f810bbef9e284b564db4897be7085257064b1)) +* **core:** Report approval tools with no tool connected in workflow validation ([#40561](https://github.com/n8n-io/n8n/issues/40561)) ([bc0a9cb](https://github.com/n8n-io/n8n/commit/bc0a9cbc112aaed2853f14c32157082f41ba42b4)) +* **core:** Report MCP server connection failures in verify_mcp_server ([#40559](https://github.com/n8n-io/n8n/issues/40559)) ([fbbbadc](https://github.com/n8n-io/n8n/commit/fbbbadc292791112e30101edee229e9d5f4dbc02)) +* **core:** Require workflow create scope for single node runs in n8n Assistant ([#40908](https://github.com/n8n-io/n8n/issues/40908)) ([27fcb96](https://github.com/n8n-io/n8n/commit/27fcb968fb711a9957eed48fa78c5adfa78fc607)) +* **core:** Resume tool calls for deferred tools that a skill loaded ([#40126](https://github.com/n8n-io/n8n/issues/40126)) ([1c84af2](https://github.com/n8n-io/n8n/commit/1c84af2e96bda41cd84852af82e5cae5b823f0f8)) +* **core:** Return jobs dequeued during worker shutdown to the queue ([#40086](https://github.com/n8n-io/n8n/issues/40086)) ([084f3b3](https://github.com/n8n-io/n8n/commit/084f3b376a0d64594320853bae90f13537d3b8c9)) +* **core:** Return jobs fetched before a worker paused to the queue ([#40162](https://github.com/n8n-io/n8n/issues/40162)) ([f26747b](https://github.com/n8n-io/n8n/commit/f26747bfc665ce0c137b0b7645245b1a97d1d01b)) +* **core:** Save agent draft definitions atomically ([#40374](https://github.com/n8n-io/n8n/issues/40374)) ([9ee5d1a](https://github.com/n8n-io/n8n/commit/9ee5d1ad7a54cde445ac945fc56a7ba5a4ee4707)) +* **core:** Serve the migration report on every main in a multi-main setup ([#40180](https://github.com/n8n-io/n8n/issues/40180)) ([a6f1e79](https://github.com/n8n-io/n8n/commit/a6f1e79394adced5958219f812e8ca14a10b9962)) +* **core:** Show the policy block before node issues on execute and publish ([#40290](https://github.com/n8n-io/n8n/issues/40290)) ([0bbea43](https://github.com/n8n-io/n8n/commit/0bbea438e1906a0773cdbb46e273b4c01fea359b)) +* **core:** Stabilise background child approval wait ([#40834](https://github.com/n8n-io/n8n/issues/40834)) ([2ca4e55](https://github.com/n8n-io/n8n/commit/2ca4e55502e03985d2c9b1b0033b6f5151ccb8f4)) +* **core:** Start a new test session when call_agent gets an unknown session ID ([#40458](https://github.com/n8n-io/n8n/issues/40458)) ([e16566b](https://github.com/n8n-io/n8n/commit/e16566b31324991a369708b7eb1f46027f80445b)) +* **core:** Stop marking the Message an Agent node as hidden ([#40358](https://github.com/n8n-io/n8n/issues/40358)) ([3366d2b](https://github.com/n8n-io/n8n/commit/3366d2b9b3151a769116a66499668c3a36cf65a4)) +* **core:** Validate execution timeout against the configured maximum in Instance AI saves ([#40769](https://github.com/n8n-io/n8n/issues/40769)) ([2176819](https://github.com/n8n-io/n8n/commit/2176819865a03e9247dac0a61177572ac4f7711c)) +* **core:** Validate the size argument of the chunk() expression extension ([#40880](https://github.com/n8n-io/n8n/issues/40880)) ([3ff9c83](https://github.com/n8n-io/n8n/commit/3ff9c83bdaf873509e4470f97e26919e0653add8)) +* **core:** Wire Entra OAuth2 into agent Azure OpenAI runtime ([#40218](https://github.com/n8n-io/n8n/issues/40218)) ([96a8ff4](https://github.com/n8n-io/n8n/commit/96a8ff4d15baa2ab15debc8ea02da81847f5a504)) +* **Databricks Node:** Request float encoding for embeddings from the Unity AI Gateway ([#40684](https://github.com/n8n-io/n8n/issues/40684)) ([4c0902f](https://github.com/n8n-io/n8n/commit/4c0902f6bf4a0aa6634d5598e75fc677aa55f429)) +* **editor:** Add resend to retryable Agent preview errors ([#40592](https://github.com/n8n-io/n8n/issues/40592)) ([f7e52a8](https://github.com/n8n-io/n8n/commit/f7e52a851ed9416615167826daf706d90a19d53b)) +* **editor:** Align nodes panel to the embedded canvas in the n8n Assistant split view ([#40795](https://github.com/n8n-io/n8n/issues/40795)) ([37799ad](https://github.com/n8n-io/n8n/commit/37799ad2f21067ec7951c2656c9e938dc87443e1)) +* **editor:** Align tooltip trigger box with its content ([#40422](https://github.com/n8n-io/n8n/issues/40422)) ([a694531](https://github.com/n8n-io/n8n/commit/a694531a0367bc6b7991b194ec762e7ad51aaa0a)) +* **editor:** Keep Agent Builder settings inside a narrow column ([#40759](https://github.com/n8n-io/n8n/issues/40759)) ([e2b4fee](https://github.com/n8n-io/n8n/commit/e2b4fee0ec0f0f34245664c23869153089362236)) +* **editor:** Keep Assistant fixes in Agent builder and correct tooltips ([#40348](https://github.com/n8n-io/n8n/issues/40348)) ([a13705a](https://github.com/n8n-io/n8n/commit/a13705aa8fff5a170ba5b069946e205e9acc1985)) +* **editor:** Keep folder creation available globally after Community registration ([#40082](https://github.com/n8n-io/n8n/issues/40082)) ([e1025f3](https://github.com/n8n-io/n8n/commit/e1025f35e4203b49436aedb89dcb679e96169528)) +* **editor:** Keep same-named parameter values apart when their types differ ([#40170](https://github.com/n8n-io/n8n/issues/40170)) ([6013045](https://github.com/n8n-io/n8n/commit/601304543d2b87e6aa42211c3a8c6c2766c2c61d)) +* **editor:** Keep the prompt visible while the assistant starts a new thread ([#40796](https://github.com/n8n-io/n8n/issues/40796)) ([be402be](https://github.com/n8n-io/n8n/commit/be402be262974d46f79ba3464e20efc0ee734ac4)) +* **editor:** Keep the selected credential visible when the picker does not list it ([#40450](https://github.com/n8n-io/n8n/issues/40450)) ([66b382d](https://github.com/n8n-io/n8n/commit/66b382de52fb56db87987910929e932292837305)) +* **editor:** Keep the workflow setup step counter on one line ([#40771](https://github.com/n8n-io/n8n/issues/40771)) ([55eb2ce](https://github.com/n8n-io/n8n/commit/55eb2ce44291648adf6ca05b5b1605efea8d77f7)) +* **editor:** Keep typed characters in Markdown fields ([#40805](https://github.com/n8n-io/n8n/issues/40805)) ([16e29da](https://github.com/n8n-io/n8n/commit/16e29da52f3173ee5edc7b96697a4c227b4983d0)) +* **editor:** Load node types before authenticated pages render ([#40812](https://github.com/n8n-io/n8n/issues/40812)) ([8297b2e](https://github.com/n8n-io/n8n/commit/8297b2e6d263d63571926545bf8b5c490f5125bf)) +* **editor:** Place the restricted node popover per host, keep one open, and stack the admin dialog ([#40678](https://github.com/n8n-io/n8n/issues/40678)) ([b28dceb](https://github.com/n8n-io/n8n/commit/b28dceb462d8e51855d4e13a87e9c975638ef977)) +* **editor:** Polish n8n Assistant and Execute button UI details ([#40414](https://github.com/n8n-io/n8n/issues/40414)) ([76cab1e](https://github.com/n8n-io/n8n/commit/76cab1e26d97cbbf50790926f1bbb14cfb12d078)) +* **editor:** Preserve Live Data highlights on scroll in expression editor ([#33842](https://github.com/n8n-io/n8n/issues/33842)) ([0f02b50](https://github.com/n8n-io/n8n/commit/0f02b509be304523955e7700c7c9eeefe58d0aa9)) +* **editor:** Remove redundant description for create workflow option in agent config ([#40882](https://github.com/n8n-io/n8n/issues/40882)) ([b542f66](https://github.com/n8n-io/n8n/commit/b542f6611998c23b40b54d25d1e923841ee24160)) +* **editor:** Rename the "Executions fail" label to "Executions will fail" ([#40888](https://github.com/n8n-io/n8n/issues/40888)) ([2a51f38](https://github.com/n8n-io/n8n/commit/2a51f38d55f37f65382ebf3900a340fc62b15314)) +* **editor:** Respect the default voice for chat read aloud ([#40440](https://github.com/n8n-io/n8n/issues/40440)) ([022b239](https://github.com/n8n-io/n8n/commit/022b23945ba576024685bfe1702489f427a3c9fe)) +* **editor:** Shorten the share button label on the credential sharing tab ([#40637](https://github.com/n8n-io/n8n/issues/40637)) ([c133d6c](https://github.com/n8n-io/n8n/commit/c133d6c893a879c907d20bb71a10817d358db553)) +* **editor:** Show the Agent artifact while the builder creates it ([#40535](https://github.com/n8n-io/n8n/issues/40535)) ([1c63119](https://github.com/n8n-io/n8n/commit/1c631197563b8f65d343d060355050c4551f381d)) +* **editor:** Show the owner and credential type for credentials the user cannot use ([#40669](https://github.com/n8n-io/n8n/issues/40669)) ([63dc285](https://github.com/n8n-io/n8n/commit/63dc2854936f3e282ca422cd9b9babeab65a2375)) +* **editor:** Show the renamed agent name in the assistant artifact tab ([#40770](https://github.com/n8n-io/n8n/issues/40770)) ([4032797](https://github.com/n8n-io/n8n/commit/40327977903613fee5d033efd31c6e01416a2bf0)) +* **editor:** Show the unavailable credential at the top of the node picker ([#40693](https://github.com/n8n-io/n8n/issues/40693)) ([1933723](https://github.com/n8n-io/n8n/commit/19337237ec59bd03c89e300a23289d2bdfbf269e)) +* **editor:** Show why a node on another branch can't be referenced ([#40565](https://github.com/n8n-io/n8n/issues/40565)) ([a195096](https://github.com/n8n-io/n8n/commit/a19509673336fbbf6687b107ce0af5bcfec68393)) +* **editor:** Small UI fixes to budget guardrail setup components ([#40383](https://github.com/n8n-io/n8n/issues/40383)) ([958d23d](https://github.com/n8n-io/n8n/commit/958d23d81cd99d7b9fd63d2484b79382c2d20c23)) +* **editor:** Use pulsing status dot for the enabled n8n Assistant setting ([#40712](https://github.com/n8n-io/n8n/issues/40712)) ([3ba5229](https://github.com/n8n-io/n8n/commit/3ba522910b1cc3009c108a202634388fd838717f)) +* **Google Gemini Chat Model Node:** Point the AI builder to the model catalog for new Gemini models ([#40159](https://github.com/n8n-io/n8n/issues/40159)) ([c21ed4f](https://github.com/n8n-io/n8n/commit/c21ed4f13aee6a1551207a92122bea2859e1b8d3)) +* **Invoice Ninja Node:** Fix retrieving currencies for bank transactions ([#12997](https://github.com/n8n-io/n8n/issues/12997)) ([00849c4](https://github.com/n8n-io/n8n/commit/00849c4deabada87641c146773c0981e873a6328)) +* Keep execution details clear of preview canvas ([#40176](https://github.com/n8n-io/n8n/issues/40176)) ([af98327](https://github.com/n8n-io/n8n/commit/af98327a5e4f2332b78b4d460e6eb208f0782d28)) +* Load only the publish history that the editor shows ([#40183](https://github.com/n8n-io/n8n/issues/40183)) ([b28adf9](https://github.com/n8n-io/n8n/commit/b28adf97895bbdba2e0c777bdfb5cd11d04c0e56)) +* **Microsoft Outlook Trigger Node:** Report failed polls and limit the backlog per poll ([#40147](https://github.com/n8n-io/n8n/issues/40147)) ([6bc5c93](https://github.com/n8n-io/n8n/commit/6bc5c93513efbe4d236c5794cfd07e1ac4d916f6)) +* Multiple migration timestamps withing a single PR ([#40379](https://github.com/n8n-io/n8n/issues/40379)) ([7db7fa4](https://github.com/n8n-io/n8n/commit/7db7fa42c80a8a24fb5ca5ec7448ffb12431fad9)) +* **Odoo Node:** Normalize datetime fields to Odoo format before write ([#34186](https://github.com/n8n-io/n8n/issues/34186)) ([6b77613](https://github.com/n8n-io/n8n/commit/6b77613ee827560d9f34f551478a74daf4848dec)) +* Prevent node types corruption when multiple loaders run at the same time ([#40633](https://github.com/n8n-io/n8n/issues/40633)) ([fdc3948](https://github.com/n8n-io/n8n/commit/fdc394819cecf96379ed7ba475364912099a6296)) +* Remove loading flashes from data tables ([#39874](https://github.com/n8n-io/n8n/issues/39874)) ([2f4a386](https://github.com/n8n-io/n8n/commit/2f4a3868fbd74c07e91888eb35b1f3d4bcb2acb1)) +* Report resource-operation violations as errors ([#40830](https://github.com/n8n-io/n8n/issues/40830)) ([a180010](https://github.com/n8n-io/n8n/commit/a1800105ef8f7c229ffd044e1233d273e95b6cd2)) +* Return UTC ISO dates without changing other cells ([#40156](https://github.com/n8n-io/n8n/issues/40156)) ([8059b63](https://github.com/n8n-io/n8n/commit/8059b63da89ba89309cbc6eacce715110c9c5748)) +* **S3 Node:** Percent-encode the copy source path ([#40282](https://github.com/n8n-io/n8n/issues/40282)) ([81f34c2](https://github.com/n8n-io/n8n/commit/81f34c23744424d17ca99eaf03beb9861c21a1ca)) +* Separate agent response steps and show saved reasoning ([#40590](https://github.com/n8n-io/n8n/issues/40590)) ([1e6da4e](https://github.com/n8n-io/n8n/commit/1e6da4e615900d7665e6eeafe9ce6002d1510c31)) +* Update matching nodes when selecting imported credentials ([#39650](https://github.com/n8n-io/n8n/issues/39650)) ([4b5b68e](https://github.com/n8n-io/n8n/commit/4b5b68ee2929344288b93469efe732379e3904a1)) +* Use configured OAuth server rate limits ([#40542](https://github.com/n8n-io/n8n/issues/40542)) ([4c8b76b](https://github.com/n8n-io/n8n/commit/4c8b76b6f08d090bf6e7cf22f66d60ec3d0efdc6)) +* Use ID token claims when UserInfo is unavailable ([#40779](https://github.com/n8n-io/n8n/issues/40779)) ([b8b0387](https://github.com/n8n-io/n8n/commit/b8b0387a31b556e296529235f9c4a75b307bb8f1)) +* Validate and default public API pagination limits ([#40483](https://github.com/n8n-io/n8n/issues/40483)) ([f212d5b](https://github.com/n8n-io/n8n/commit/f212d5b900fe92c3012001b32f4cf17bd831921e)) +* Wait for MockServer HTTP status without following logs ([#40846](https://github.com/n8n-io/n8n/issues/40846)) ([4593838](https://github.com/n8n-io/n8n/commit/45938389b86b6bfe25a8a8f3d132b600ee807f58)) + + +### Features + +* Add Antigravity to the MCP client connection dialog ([#40879](https://github.com/n8n-io/n8n/issues/40879)) ([f0a38cf](https://github.com/n8n-io/n8n/commit/f0a38cfe5801ba8d62b97f6d4ffeb031f23aa231)) +* Add Google Vertex AI credentials ([#40665](https://github.com/n8n-io/n8n/issues/40665)) ([a7cba90](https://github.com/n8n-io/n8n/commit/a7cba90a854ea34198dd9c1fcb4f7eeae08c364d)) +* **ai-builder:** Reopen closed AI Assistant tabs when the agent changes the artifact ([#40081](https://github.com/n8n-io/n8n/issues/40081)) ([5d38667](https://github.com/n8n-io/n8n/commit/5d3866775c828e766ca16642d5ae2a340d4133ca)) +* **Azure AI Foundry Chat Model Node:** Speak the Anthropic Messages schema for Claude deployments ([#40306](https://github.com/n8n-io/n8n/issues/40306)) ([c134edf](https://github.com/n8n-io/n8n/commit/c134edf473276ff63387d28aea0d08c9ff676f7c)) +* **Azure OpenAI Chat Model Node:** Rename the Foundry nodes and credentials to Microsoft Foundry ([#40398](https://github.com/n8n-io/n8n/issues/40398)) ([e5c8a8b](https://github.com/n8n-io/n8n/commit/e5c8a8bb62d2ce468d1cda3965562eeaa69996f8)) +* Configure workflow tool inputs for Agents ([#40285](https://github.com/n8n-io/n8n/issues/40285)) ([4cb98ae](https://github.com/n8n-io/n8n/commit/4cb98aea9fbcede8ae414c3f817c7b0490d401f8)) +* **core:** Add credentialTransfer policy enforcement point ([#40300](https://github.com/n8n-io/n8n/issues/40300)) ([c2f6920](https://github.com/n8n-io/n8n/commit/c2f6920794e66e7108b0005233506f7694a11a7e)) +* **core:** Add execution identity to every OTel span ([#40649](https://github.com/n8n-io/n8n/issues/40649)) ([22ba4e7](https://github.com/n8n-io/n8n/commit/22ba4e7bc5c6fbe5243ff5c227c718ab7197c5e1)) +* **core:** Add overwrite schema conflict policy to data table package import ([#40345](https://github.com/n8n-io/n8n/issues/40345)) ([3af9817](https://github.com/n8n-io/n8n/commit/3af98170d0d98a201df1a45f2ecee17f5f00f298)) +* **core:** Add overwrite-non-destructive schema conflict policy to data table package import ([#40446](https://github.com/n8n-io/n8n/issues/40446)) ([dc33c29](https://github.com/n8n-io/n8n/commit/dc33c29d1af3f47a6179a76ff21ccc7bd1f75357)) +* **core:** Add Prometheus metrics for database connection recovery ([#39890](https://github.com/n8n-io/n8n/issues/39890)) ([d904e7a](https://github.com/n8n-io/n8n/commit/d904e7a2476794acdf3928faacd86ae9b3e45220)) +* **core:** Add the WhatsApp agent channel ([#38750](https://github.com/n8n-io/n8n/issues/38750)) ([b0d1a30](https://github.com/n8n-io/n8n/commit/b0d1a30f50fdf6b3720c2a5773e28efff5c5b0b5)) +* **core:** Add workflow suggestion review actions ([#39858](https://github.com/n8n-io/n8n/issues/39858)) ([eaf8c25](https://github.com/n8n-io/n8n/commit/eaf8c25d1c2b680fe55f58fc9f6d10647e6ae640)) +* **core:** Allow confirming destructive data table changes when continuing an apply ([#40491](https://github.com/n8n-io/n8n/issues/40491)) ([9946cfe](https://github.com/n8n-io/n8n/commit/9946cfe901b538ec5ca29e85cde3ec2044d33d00)) +* **core:** Apply the member credential rule to Owners and admins in team projects ([#40448](https://github.com/n8n-io/n8n/issues/40448)) ([3cff8dc](https://github.com/n8n-io/n8n/commit/3cff8dc4ecac5fd173d198f3e319ab473cdd7b22)) +* **core:** Block create/update of workflows with deprecated nodes ([#31360](https://github.com/n8n-io/n8n/issues/31360)) ([ea8417e](https://github.com/n8n-io/n8n/commit/ea8417e29ad6f8b981d9a04b17283d5d77f2b5bb)) +* **core:** Email the agent owner when a monthly budget alert is crossed ([#40544](https://github.com/n8n-io/n8n/issues/40544)) ([19e1f70](https://github.com/n8n-io/n8n/commit/19e1f70ea62ad151abe18b5a25721caa35d7bedd)) +* **core:** Emit opt-in start marker spans for workflow and node executions ([#40762](https://github.com/n8n-io/n8n/issues/40762)) ([c713545](https://github.com/n8n-io/n8n/commit/c7135451ebd552267aedf4898d845c53a97aab54)) +* **core:** Experiment to show assistant composer and starter templates in agent list ([#40396](https://github.com/n8n-io/n8n/issues/40396)) ([fe26ba8](https://github.com/n8n-io/n8n/commit/fe26ba8d3a63963d6c7868338e73fb77378e94a9)) +* **core:** Handle inbound media handling for whatsapp ([#39409](https://github.com/n8n-io/n8n/issues/39409)) ([50c2ca0](https://github.com/n8n-io/n8n/commit/50c2ca0a27189136d82339bdafd5d8c7513a9916)) +* **core:** Handle message quality rate limits for whatsapp integration ([#39205](https://github.com/n8n-io/n8n/issues/39205)) ([3c33856](https://github.com/n8n-io/n8n/commit/3c33856997b084a3a87038c0d72f80d9b91af1b7)) +* **core:** Hide credential-only nodes under a credential type policy ([#39652](https://github.com/n8n-io/n8n/issues/39652)) ([370b30f](https://github.com/n8n-io/n8n/commit/370b30f9195ba8d5ceaf75fb4cdfcf127105a3c6)) +* **core:** Pair data table columns by id on package import ([#40709](https://github.com/n8n-io/n8n/issues/40709)) ([27b43de](https://github.com/n8n-io/n8n/commit/27b43de85f987ddd783e7c7ccbde7977d09a6d03)) +* **core:** Persist self-healing results and handoffs ([#40115](https://github.com/n8n-io/n8n/issues/40115)) ([168a0ac](https://github.com/n8n-io/n8n/commit/168a0ac86056afd743bfde63863abbab4e8515f4)) +* **core:** Post a budget-stop message on external agent channels ([#40767](https://github.com/n8n-io/n8n/issues/40767)) ([5e01906](https://github.com/n8n-io/n8n/commit/5e01906a1e6c177c0ce02d18317ce2d7b6ee7e97)) +* **core:** Promote folder and project renames alongside selected workflows ([#40502](https://github.com/n8n-io/n8n/issues/40502)) ([a249e20](https://github.com/n8n-io/n8n/commit/a249e202905f30829fe3a7eacd2eba8dff6573ef)) +* **core:** Report crashed executions from startup log recovery ([#40390](https://github.com/n8n-io/n8n/issues/40390)) ([668e71d](https://github.com/n8n-io/n8n/commit/668e71d54a26da7c12d092a7375a7cb3349a8471)) +* **core:** Report destructive data table changes in the promotion apply preflight ([#40454](https://github.com/n8n-io/n8n/issues/40454)) ([5d208c8](https://github.com/n8n-io/n8n/commit/5d208c85ed275c22cc5597124b7a9cf590d18f11)) +* **core:** Report the deployment artifact in telemetry ([#40319](https://github.com/n8n-io/n8n/issues/40319)) ([344dea5](https://github.com/n8n-io/n8n/commit/344dea5c77fc5f61ce10171a2553faa9bef4e609)) +* **core:** Run the workflow history trim as a durable daily system task ([#40085](https://github.com/n8n-io/n8n/issues/40085)) ([38eea65](https://github.com/n8n-io/n8n/commit/38eea65993339ea3e8156cdbacef247749331351)) +* **core:** Search, create and reopen agents from the command bar ([#40504](https://github.com/n8n-io/n8n/issues/40504)) ([75a9cc7](https://github.com/n8n-io/n8n/commit/75a9cc7e1219d35b441b02c20446dd89db186ff7)) +* **core:** Serve Prometheus metrics while the database is unavailable ([#39908](https://github.com/n8n-io/n8n/issues/39908)) ([4e217ae](https://github.com/n8n-io/n8n/commit/4e217aeac6b029692fb8a692a3849ae8e5310b5a)) +* **core:** Serve the instance CSP on all non-script responses ([#40205](https://github.com/n8n-io/n8n/issues/40205)) ([cabf0bf](https://github.com/n8n-io/n8n/commit/cabf0bf3b466a725deada3b532347b7db530dcac)) +* **core:** Show every user the migration report, scoped to the workflows they can edit ([#40449](https://github.com/n8n-io/n8n/issues/40449)) ([f4f7dcf](https://github.com/n8n-io/n8n/commit/f4f7dcf13b6d93d46a2860e2c2577f9f6dda4c52)) +* **core:** Show the agent chat attach button on the left of the composer ([#40320](https://github.com/n8n-io/n8n/issues/40320)) ([209adf9](https://github.com/n8n-io/n8n/commit/209adf9a7ee9e71cfe3d5119316ca9fce4b3ac68)) +* **Databricks Node:** Guard the Vector Store insert against the wrong index ([#39699](https://github.com/n8n-io/n8n/issues/39699)) ([0932e95](https://github.com/n8n-io/n8n/commit/0932e9572e2650165b260fc591d1f02204c17aae)) +* **editor:** Add a state column to the migration rule detail ([#40388](https://github.com/n8n-io/n8n/issues/40388)) ([682d092](https://github.com/n8n-io/n8n/commit/682d0920ba5cb2ab5e3ac0671f993c8e529e8389)) +* **editor:** Add agent setup checklist ([#39919](https://github.com/n8n-io/n8n/issues/39919)) ([883ade4](https://github.com/n8n-io/n8n/commit/883ade4b9d2505f359057eb10c8d71ab153033a7)) +* **editor:** Add order to settings sidebar links ([#40505](https://github.com/n8n-io/n8n/issues/40505)) ([cef87cf](https://github.com/n8n-io/n8n/commit/cef87cfcab3f59a657c8c27309f4807bd2d4a93a)) +* **editor:** Add project selection to Vertex AI credentials ([#40667](https://github.com/n8n-io/n8n/issues/40667)) ([cdc23c6](https://github.com/n8n-io/n8n/commit/cdc23c666ffd6ed55f019aa24c99efdaf10fad14)) +* **editor:** Animate the n8n Assistant activity indicator ([#40497](https://github.com/n8n-io/n8n/issues/40497)) ([04e1e7f](https://github.com/n8n-io/n8n/commit/04e1e7fc4771ff1371ac41f1d74aef7ced26b175)) +* **editor:** Disable restricted model providers in the agent model selector ([#40658](https://github.com/n8n-io/n8n/issues/40658)) ([cde7a9d](https://github.com/n8n-io/n8n/commit/cde7a9dbd985ae9e83de2d39dccc508a41d9a676)) +* **editor:** Explain a restricted model provider with the restriction popover ([#40705](https://github.com/n8n-io/n8n/issues/40705)) ([75de193](https://github.com/n8n-io/n8n/commit/75de193d9090d160dd191667adb85dc423951045)) +* **editor:** Explain instance-role access in the credential sharing "Used in" row ([#40555](https://github.com/n8n-io/n8n/issues/40555)) ([48f05f9](https://github.com/n8n-io/n8n/commit/48f05f92fe9e7bd1c1d220a53a8c17055a17e70c)) +* **editor:** Rebuild the command bar with type tabs and paged search ([#40461](https://github.com/n8n-io/n8n/issues/40461)) ([e36093b](https://github.com/n8n-io/n8n/commit/e36093b11db0580add10306d27d090a27790f4fb)) +* **editor:** Rebuild the personal settings page with the design-system settings components ([#40298](https://github.com/n8n-io/n8n/issues/40298)) ([09436b7](https://github.com/n8n-io/n8n/commit/09436b78f9f6f320073f911ca11160ad9a66d94f)) +* **editor:** Recommend Claude Opus 5.5 and GPT-6 models in AI Assistant setup ([#40660](https://github.com/n8n-io/n8n/issues/40660)) ([1ad3c54](https://github.com/n8n-io/n8n/commit/1ad3c54803569dd83976c055785b51b62555bf44)) +* **editor:** Replace Windsurf with Devin in the MCP client dialog ([#40912](https://github.com/n8n-io/n8n/issues/40912)) ([e2c4054](https://github.com/n8n-io/n8n/commit/e2c4054cba14a2f1dc29215fc623f6ae42b7a238)) +* **editor:** Show the restriction callout and lock the agent tool configuration form ([#40657](https://github.com/n8n-io/n8n/issues/40657)) ([01da889](https://github.com/n8n-io/n8n/commit/01da88958d490e5006874cce2b05554347301b9b)) +* **editor:** Show who created each preference on the Preferences page ([#40868](https://github.com/n8n-io/n8n/issues/40868)) ([22ff2a0](https://github.com/n8n-io/n8n/commit/22ff2a06368b49fa25b0ad1c2cf74640c56a0284)) +* **editor:** Sort the credential sharing list by people, then projects ([#40478](https://github.com/n8n-io/n8n/issues/40478)) ([02af7e7](https://github.com/n8n-io/n8n/commit/02af7e7659cce85749c719bb6a1b910043357baf)) +* **Embeddings Azure OpenAI Node:** Add Entra ID authentication ([#39390](https://github.com/n8n-io/n8n/issues/39390)) ([830486a](https://github.com/n8n-io/n8n/commit/830486a851ceb3eeada1eb945e7cd11c05262901)) +* **Google Gemini Node:** Show Nano Banana 2.1 and 2 Lite in the image model list ([#40596](https://github.com/n8n-io/n8n/issues/40596)) ([97c54f6](https://github.com/n8n-io/n8n/commit/97c54f618c6210bbe1dcfadaac702d40e89a820b)) +* Make health check timeout configurable ([#39548](https://github.com/n8n-io/n8n/issues/39548)) ([df8605e](https://github.com/n8n-io/n8n/commit/df8605e8750443d66388060212306cd205a4f5d3)) +* **Microsoft SharePoint Trigger Node:** Add the Microsoft SharePoint Trigger node ([#40055](https://github.com/n8n-io/n8n/issues/40055)) ([7c126fa](https://github.com/n8n-io/n8n/commit/7c126fab32772241473e1f180c6806af4ce189f8)) + + +### Performance Improvements + +* **core:** Keep agent builder system prompt static for prompt caching ([#40364](https://github.com/n8n-io/n8n/issues/40364)) ([ee1db0b](https://github.com/n8n-io/n8n/commit/ee1db0bc12bebb572afd04e6e53efc30ffa01209)) +* **core:** Let the agent builder chain config writes without re-reading the config ([#40462](https://github.com/n8n-io/n8n/issues/40462)) ([6b4da93](https://github.com/n8n-io/n8n/commit/6b4da93dcbb909bcf86c03251e3c74033d0dd70f)) +* **core:** Let the agent builder edit skill instructions in place ([#40447](https://github.com/n8n-io/n8n/issues/40447)) ([1de45a1](https://github.com/n8n-io/n8n/commit/1de45a1a9b0b0db7036cb25e27bffc95a7df41e2)) +* **core:** Prepare Instance AI skill sandbox in the background ([#40363](https://github.com/n8n-io/n8n/issues/40363)) ([b36c2b5](https://github.com/n8n-io/n8n/commit/b36c2b506b92f391f859ec10067e57d96c8b09c8)) +* **core:** Send agent builder config writes as objects with changed fields only ([#40666](https://github.com/n8n-io/n8n/issues/40666)) ([2aa3fbf](https://github.com/n8n-io/n8n/commit/2aa3fbf18547cfb6719baabdcd8719fa6d0f53af)) + + # [2.43.0](https://github.com/n8n-io/n8n/compare/n8n@2.42.0...n8n@2.43.0) (2026-10-06) diff --git a/OWNERS b/OWNERS index 21066d47984..54968f47e2c 100644 --- a/OWNERS +++ b/OWNERS @@ -30,6 +30,7 @@ packages/@n8n/backend-network/ @n8n-io/catalysts packages/@n8n/backend-services/ @n8n-io/catalysts packages/@n8n/backend-services/src/services/role.service.ts @n8n-io/iam packages/@n8n/backend-services/src/services/role-cache.service.ts @n8n-io/iam +packages/@n8n/backend-services/src/services/jwt.service.ts @n8n-io/iam packages/@n8n/backend-test-utils/ @n8n-io/catalysts packages/@n8n/di/ @n8n-io/catalysts packages/@n8n/errors/ @n8n-io/catalysts @@ -115,12 +116,12 @@ packages/cli/src/binary-data/ @n8n-io/catalysts packages/cli/src/posthog/ @n8n-io/growth packages/cli/src/modules/data-table/ @n8n-io/knowledge -packages/cli/src/evaluation.ee/ @n8n-io/ai +packages/cli/src/evaluation.ee/ @n8n-io/ai-trust packages/cli/src/chat/ @n8n-io/ai packages/cli/src/tool-generation/ @n8n-io/ai packages/cli/src/modules/workflow-builder/ @n8n-io/ai-assistant packages/cli/src/modules/mcp/ @n8n-io/context -packages/cli/src/modules/quick-connect/ @n8n-io/ai +packages/modules/quick-connect/ @n8n-io/ai packages/cli/src/modules/chat-hub/ @n8n-io/ai-assistant packages/cli/src/modules/instance-ai/ @n8n-io/ai-assistant @@ -154,7 +155,6 @@ packages/cli/src/controllers/dynamic-node-parameters.controller.ts @n8n-io/node packages/cli/src/controllers/e2e.controller.ts @n8n-io/qa-dx # CLI services -packages/cli/src/services/jwt.service.ts @n8n-io/iam packages/cli/src/services/user.service.ts @n8n-io/iam packages/cli/src/services/password.utility.ts @n8n-io/iam packages/cli/src/services/public-api-key.service.ts @n8n-io/iam @@ -166,7 +166,7 @@ packages/cli/src/services/ai-usage.service.ts @n8n-io/ai-assistant packages/cli/src/services/__tests__/ai-usage.service.test.ts @n8n-io/ai-assistant packages/cli/src/controllers/__tests__/ai.controller.test.ts @n8n-io/ai-assistant packages/cli/src/services/ai-workflow-builder.service.ts @n8n-io/ai-assistant -packages/cli/src/services/annotation-tag.service.ee.ts @n8n-io/ai +packages/cli/src/services/annotation-tag.service.ee.ts @n8n-io/context packages/cli/src/services/folder.service.ts @n8n-io/context packages/cli/src/services/tag.service.ts @n8n-io/context packages/cli/src/services/cta.service.ts @n8n-io/knowledge @@ -281,3 +281,15 @@ packages/@n8n/db/src/entities/deployment-key.ts @n8n-io/iam required packages/@n8n/db/src/repositories/deployment-key.repository.ts @n8n-io/iam required packages/@n8n/eslint-config/src/configs/encryption-boundary.ts @n8n-io/iam required packages/@n8n/eslint-config/src/rules/no-encryption-guardrail-disable.ts @n8n-io/iam required + +# AI Trust (evaluations) +# Placed last so these rules override the broader package rules above. + +packages/@n8n/instance-ai/evaluations/ @n8n-io/ai-trust +packages/cli/src/modules/instance-ai/eval/ @n8n-io/ai-trust +packages/quality/testing/playwright/tests/evals/instance-ai/ @n8n-io/ai-trust +.agents/skills/create-instance-ai-eval/ @n8n-io/ai-trust +.agents/skills/create-agent-builder-eval/ @n8n-io/ai-trust +packages/cli/src/modules/agent-evals/ @n8n-io/ai-trust +packages/@n8n/agents/src/evals/ @n8n-io/ai-trust +packages/frontend/editor-ui/src/features/ai/evaluation.ee/ @n8n-io/ai-trust diff --git a/agent-harness.lock.json b/agent-harness.lock.json index abe5f0a0da4..4ea0d5a8b80 100644 --- a/agent-harness.lock.json +++ b/agent-harness.lock.json @@ -1,6 +1,6 @@ { "repository": "n8n-io/cat-bot", - "releaseTag": "harness-v0.3.0", - "version": "0.3.0", - "assetName": "n8n-opencode-harness-0.3.0.tgz" + "releaseTag": "harness-v0.6.0", + "version": "0.6.0", + "assetName": "n8n-opencode-harness-0.6.0.tgz" } diff --git a/docker/get-n8n.sh b/docker/get-n8n.sh index dc886061bfb..9e115f15721 100755 --- a/docker/get-n8n.sh +++ b/docker/get-n8n.sh @@ -15,11 +15,11 @@ set -eu SCRIPT_VERSION="1.4.0" # The version to install is derived from the latest stable GitHub release in # resolve_n8n_version(); this fallback only applies when that lookup fails. -FALLBACK_N8N_VERSION="2.32.0" +FALLBACK_N8N_VERSION="2.43.4" # Sandbox service release (API, runner and sandbox images ship together). # Pinned here, not resolved at run time: the stack definition must match it. # --upgrade moves existing installs to this pin. -SANDBOX_VERSION="1.3.4" +SANDBOX_VERSION="1.8.1" N8N_DIR="${N8N_DIR:-./n8n}" N8N_PORT=5678 SOURCE_URL="https://github.com/n8n-io/n8n/blob/master/docker/get-n8n.sh" diff --git a/docs/generated/postgres-schema/README.md b/docs/generated/postgres-schema/README.md index cdb7a6648cb..8f6c07493fb 100644 --- a/docs/generated/postgres-schema/README.md +++ b/docs/generated/postgres-schema/README.md @@ -29,10 +29,12 @@ Auto-generated from the PostgreSQL migrations in @n8n/db. Do not edit by hand. | [public.agent_message_queue](public.agent_message_queue.md) | 10 | | BASE TABLE | | [public.agent_plan](public.agent_plan.md) | 8 | | BASE TABLE | | [public.agent_plan_history](public.agent_plan_history.md) | 6 | | BASE TABLE | +| [public.agent_skill_dependency](public.agent_skill_dependency.md) | 4 | | BASE TABLE | | [public.agent_task_definition](public.agent_task_definition.md) | 8 | | BASE TABLE | | [public.agent_task_run_lock](public.agent_task_run_lock.md) | 6 | | BASE TABLE | | [public.agent_task_snapshot](public.agent_task_snapshot.md) | 9 | | BASE TABLE | | [public.agent_thread_grants](public.agent_thread_grants.md) | 4 | | BASE TABLE | +| [public.agent_version_skill_dependency](public.agent_version_skill_dependency.md) | 4 | | BASE TABLE | | [public.agent_workflow_dependency](public.agent_workflow_dependency.md) | 3 | | BASE TABLE | | [public.agents](public.agents.md) | 14 | | BASE TABLE | | [public.agents_memory_entries](public.agents_memory_entries.md) | 13 | | BASE TABLE | @@ -131,6 +133,9 @@ Auto-generated from the PostgreSQL migrations in @n8n/db. Do not edit by hand. | [public.settings](public.settings.md) | 3 | | BASE TABLE | | [public.shared_credentials](public.shared_credentials.md) | 5 | | BASE TABLE | | [public.shared_workflow](public.shared_workflow.md) | 5 | | BASE TABLE | +| [public.skill](public.skill.md) | 7 | | BASE TABLE | +| [public.skill_file](public.skill_file.md) | 5 | | BASE TABLE | +| [public.skill_version](public.skill_version.md) | 11 | | BASE TABLE | | [public.tag_entity](public.tag_entity.md) | 4 | | BASE TABLE | | [public.test_case_execution](public.test_case_execution.md) | 14 | | BASE TABLE | | [public.test_run](public.test_run.md) | 16 | | BASE TABLE | @@ -223,10 +228,16 @@ erDiagram "public.agent_message_queue" }o--|| "public.agent_execution_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES agent_execution_threads(id) ON DELETE CASCADE" "public.agent_plan" }o--|| "public.agent_execution_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES agent_execution_threads(id) ON DELETE CASCADE" "public.agent_plan_history" }o--|| "public.agent_plan" : "FOREIGN KEY (#quot;planId#quot;) REFERENCES agent_plan(id) ON DELETE CASCADE" +"public.agent_skill_dependency" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" +"public.agent_skill_dependency" }o--|| "public.skill" : "FOREIGN KEY (#quot;skillId#quot;) REFERENCES skill(id) ON DELETE CASCADE" +"public.agent_skill_dependency" }o--o| "public.skill_version" : "FOREIGN KEY (#quot;skillVersionId#quot;) REFERENCES skill_version(id)" "public.agent_task_definition" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" "public.agent_task_run_lock" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" "public.agent_task_snapshot" }o--|| "public.agent_history" : "FOREIGN KEY (#quot;versionId#quot;) REFERENCES agent_history(#quot;versionId#quot;) ON DELETE CASCADE" "public.agent_thread_grants" }o--|| "public.agent_execution_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES agent_execution_threads(id) ON DELETE CASCADE" +"public.agent_version_skill_dependency" }o--|| "public.agent_history" : "FOREIGN KEY (#quot;agentVersionId#quot;) REFERENCES agent_history(#quot;versionId#quot;) ON DELETE CASCADE" +"public.agent_version_skill_dependency" }o--|| "public.skill" : "FOREIGN KEY (#quot;skillId#quot;) REFERENCES skill(id) ON DELETE CASCADE" +"public.agent_version_skill_dependency" }o--|| "public.skill_version" : "FOREIGN KEY (#quot;skillVersionId#quot;) REFERENCES skill_version(id)" "public.agent_workflow_dependency" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" "public.agent_workflow_dependency" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" "public.agents" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" @@ -369,6 +380,12 @@ erDiagram "public.shared_credentials" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" "public.shared_workflow" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" "public.shared_workflow" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" +"public.skill" }o--o| "public.user" : "FOREIGN KEY (#quot;createdById#quot;) REFERENCES #quot;user#quot;(id) ON DELETE SET NULL" +"public.skill" }o--o| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" +"public.skill" }o--o| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" +"public.skill_file" }o--|| "public.skill_version" : "FOREIGN KEY (#quot;skillVersionId#quot;) REFERENCES skill_version(id) ON DELETE CASCADE" +"public.skill_version" }o--o| "public.user" : "FOREIGN KEY (#quot;createdById#quot;) REFERENCES #quot;user#quot;(id) ON DELETE SET NULL" +"public.skill_version" }o--|| "public.skill" : "FOREIGN KEY (#quot;skillId#quot;) REFERENCES skill(id) ON DELETE CASCADE" "public.test_case_execution" }o--o| "public.execution_entity" : "FOREIGN KEY (#quot;executionId#quot;) REFERENCES execution_entity(id) ON DELETE SET NULL" "public.test_case_execution" }o--|| "public.test_run" : "FOREIGN KEY (#quot;testRunId#quot;) REFERENCES test_run(id) ON DELETE CASCADE" "public.test_run" }o--|| "public.workflow_entity" : "FOREIGN KEY (#quot;workflowId#quot;) REFERENCES workflow_entity(id) ON DELETE CASCADE" @@ -679,6 +696,12 @@ erDiagram uuid planId FK integer revision } +"public.agent_skill_dependency" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + varchar_36_ skillId FK + uuid skillVersionId FK +} "public.agent_task_definition" { varchar_36_ agentId FK timestamp_3__with_time_zone createdAt @@ -714,6 +737,12 @@ erDiagram varchar_128_ threadId FK timestamp_3__with_time_zone updatedAt } +"public.agent_version_skill_dependency" { + varchar_36_ agentVersionId FK + timestamp_3__with_time_zone createdAt + varchar_36_ skillId FK + uuid skillVersionId FK +} "public.agent_workflow_dependency" { varchar_36_ agentId FK timestamp_3__with_time_zone createdAt @@ -1651,6 +1680,35 @@ erDiagram timestamp_3__with_time_zone updatedAt varchar_36_ workflowId FK } +"public.skill" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + uuid createdById FK + varchar_36_ id + varchar_36_ projectId FK + varchar_16_ source + timestamp_3__with_time_zone updatedAt +} +"public.skill_file" { + text content + timestamp_3__with_time_zone createdAt + varchar_512_ path + uuid skillVersionId FK + timestamp_3__with_time_zone updatedAt +} +"public.skill_version" { + varchar_64_ contentHash + timestamp_3__with_time_zone createdAt + uuid createdById FK + varchar_1024_ description + json frontmatter + uuid id + text instructions + varchar_128_ name + varchar_36_ skillId FK + timestamp_3__with_time_zone updatedAt + integer version +} "public.tag_entity" { timestamp_3__with_time_zone createdAt varchar_36_ id diff --git a/docs/generated/postgres-schema/public.agent_history.md b/docs/generated/postgres-schema/public.agent_history.md index f04cb3a9138..f88d49c9688 100644 --- a/docs/generated/postgres-schema/public.agent_history.md +++ b/docs/generated/postgres-schema/public.agent_history.md @@ -12,7 +12,7 @@ | skills | json | | true | | | Frozen map of `skillId → AgentSkill` at publish time | | tools | json | | true | | | Frozen map of `toolId → { code, descriptor }` at publish time | | updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | -| versionId | varchar(36) | | false | [public.agent_execution_threads](public.agent_execution_threads.md) [public.agent_task_snapshot](public.agent_task_snapshot.md) [public.agents](public.agents.md) | | | +| versionId | varchar(36) | | false | [public.agent_execution_threads](public.agent_execution_threads.md) [public.agent_task_snapshot](public.agent_task_snapshot.md) [public.agent_version_skill_dependency](public.agent_version_skill_dependency.md) [public.agents](public.agents.md) | | | ## Constraints @@ -43,6 +43,7 @@ erDiagram "public.agent_history" }o--o| "public.user" : "FOREIGN KEY (#quot;publishedById#quot;) REFERENCES #quot;user#quot;(id) ON DELETE SET NULL" "public.agent_execution_threads" }o--o| "public.agent_history" : "FOREIGN KEY (#quot;taskVersionId#quot;) REFERENCES agent_history(#quot;versionId#quot;) ON DELETE SET NULL" "public.agent_task_snapshot" }o--|| "public.agent_history" : "FOREIGN KEY (#quot;versionId#quot;) REFERENCES agent_history(#quot;versionId#quot;) ON DELETE CASCADE" +"public.agent_version_skill_dependency" }o--|| "public.agent_history" : "FOREIGN KEY (#quot;agentVersionId#quot;) REFERENCES agent_history(#quot;versionId#quot;) ON DELETE CASCADE" "public.agents" }o--o| "public.agent_history" : "FOREIGN KEY (#quot;activeVersionId#quot;) REFERENCES agent_history(#quot;versionId#quot;) ON DELETE SET NULL" "public.agent_history" { @@ -121,6 +122,12 @@ erDiagram timestamp_3__with_time_zone updatedAt varchar_36_ versionId FK } +"public.agent_version_skill_dependency" { + varchar_36_ agentVersionId FK + timestamp_3__with_time_zone createdAt + varchar_36_ skillId FK + uuid skillVersionId FK +} ``` --- diff --git a/docs/generated/postgres-schema/public.agent_skill_dependency.md b/docs/generated/postgres-schema/public.agent_skill_dependency.md new file mode 100644 index 00000000000..b799959e324 --- /dev/null +++ b/docs/generated/postgres-schema/public.agent_skill_dependency.md @@ -0,0 +1,88 @@ +# public.agent_skill_dependency + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| agentId | varchar(36) | | false | | [public.agents](public.agents.md) | | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| skillId | varchar(36) | | false | | [public.skill](public.skill.md) | | +| skillVersionId | uuid | | true | | [public.skill_version](public.skill_version.md) | Set when the agent draft pins a saved version. NULL = follows the latest saved version | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_068f21aefba31ae621482f396dc | FOREIGN KEY | FOREIGN KEY ("skillId") REFERENCES skill(id) ON DELETE CASCADE | +| FK_72325bb13511a51847c53fcb377 | FOREIGN KEY | FOREIGN KEY ("agentId") REFERENCES agents(id) ON DELETE CASCADE | +| FK_7676571bd6f41d9e32f0d066fe9 | FOREIGN KEY | FOREIGN KEY ("skillVersionId") REFERENCES skill_version(id) | +| PK_18a54f60491d3e2aa2200b70f4a | PRIMARY KEY | PRIMARY KEY ("agentId", "skillId") | +| agent_skill_dependency_agentId_not_null | n | NOT NULL "agentId" | +| agent_skill_dependency_createdAt_not_null | n | NOT NULL "createdAt" | +| agent_skill_dependency_skillId_not_null | n | NOT NULL "skillId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_068f21aefba31ae621482f396d | CREATE INDEX "IDX_068f21aefba31ae621482f396d" ON public.agent_skill_dependency USING btree ("skillId") | +| PK_18a54f60491d3e2aa2200b70f4a | CREATE UNIQUE INDEX "PK_18a54f60491d3e2aa2200b70f4a" ON public.agent_skill_dependency USING btree ("agentId", "skillId") | + +## Relations + +```mermaid +erDiagram + +"public.agent_skill_dependency" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" +"public.agent_skill_dependency" }o--|| "public.skill" : "FOREIGN KEY (#quot;skillId#quot;) REFERENCES skill(id) ON DELETE CASCADE" +"public.agent_skill_dependency" }o--o| "public.skill_version" : "FOREIGN KEY (#quot;skillVersionId#quot;) REFERENCES skill_version(id)" + +"public.agent_skill_dependency" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + varchar_36_ skillId FK + uuid skillVersionId FK +} +"public.agents" { + varchar_36_ activeVersionId FK + boolean availableInMCP + timestamp_3__with_time_zone createdAt + varchar_36_ id + json integrations + varchar_128_ name + varchar_255_ projectId FK + integer revision + json schema + timestamp_3__with_time_zone setupCompletedAt + json skills + json tools + timestamp_3__with_time_zone updatedAt + varchar_36_ versionId +} +"public.skill" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + uuid createdById FK + varchar_36_ id + varchar_36_ projectId FK + varchar_16_ source + timestamp_3__with_time_zone updatedAt +} +"public.skill_version" { + varchar_64_ contentHash + timestamp_3__with_time_zone createdAt + uuid createdById FK + varchar_1024_ description + json frontmatter + uuid id + text instructions + varchar_128_ name + varchar_36_ skillId FK + timestamp_3__with_time_zone updatedAt + integer version +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.agent_version_skill_dependency.md b/docs/generated/postgres-schema/public.agent_version_skill_dependency.md new file mode 100644 index 00000000000..4135311d27d --- /dev/null +++ b/docs/generated/postgres-schema/public.agent_version_skill_dependency.md @@ -0,0 +1,85 @@ +# public.agent_version_skill_dependency + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| agentVersionId | varchar(36) | | false | | [public.agent_history](public.agent_history.md) | | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| skillId | varchar(36) | | false | | [public.skill](public.skill.md) | | +| skillVersionId | uuid | | false | | [public.skill_version](public.skill_version.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_97472baf9196d914d9cd9de6201 | FOREIGN KEY | FOREIGN KEY ("agentVersionId") REFERENCES agent_history("versionId") ON DELETE CASCADE | +| FK_c494292243a7e510acd0331c3d1 | FOREIGN KEY | FOREIGN KEY ("skillId") REFERENCES skill(id) ON DELETE CASCADE | +| FK_df63badfd7d3f2aa622ece471c4 | FOREIGN KEY | FOREIGN KEY ("skillVersionId") REFERENCES skill_version(id) | +| PK_df0a2577371b94f3c7008d81822 | PRIMARY KEY | PRIMARY KEY ("agentVersionId", "skillId") | +| agent_version_skill_dependency_agentVersionId_not_null | n | NOT NULL "agentVersionId" | +| agent_version_skill_dependency_createdAt_not_null | n | NOT NULL "createdAt" | +| agent_version_skill_dependency_skillId_not_null | n | NOT NULL "skillId" | +| agent_version_skill_dependency_skillVersionId_not_null | n | NOT NULL "skillVersionId" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_c494292243a7e510acd0331c3d | CREATE INDEX "IDX_c494292243a7e510acd0331c3d" ON public.agent_version_skill_dependency USING btree ("skillId") | +| IDX_df63badfd7d3f2aa622ece471c | CREATE INDEX "IDX_df63badfd7d3f2aa622ece471c" ON public.agent_version_skill_dependency USING btree ("skillVersionId") | +| PK_df0a2577371b94f3c7008d81822 | CREATE UNIQUE INDEX "PK_df0a2577371b94f3c7008d81822" ON public.agent_version_skill_dependency USING btree ("agentVersionId", "skillId") | + +## Relations + +```mermaid +erDiagram + +"public.agent_version_skill_dependency" }o--|| "public.agent_history" : "FOREIGN KEY (#quot;agentVersionId#quot;) REFERENCES agent_history(#quot;versionId#quot;) ON DELETE CASCADE" +"public.agent_version_skill_dependency" }o--|| "public.skill" : "FOREIGN KEY (#quot;skillId#quot;) REFERENCES skill(id) ON DELETE CASCADE" +"public.agent_version_skill_dependency" }o--|| "public.skill_version" : "FOREIGN KEY (#quot;skillVersionId#quot;) REFERENCES skill_version(id)" + +"public.agent_version_skill_dependency" { + varchar_36_ agentVersionId FK + timestamp_3__with_time_zone createdAt + varchar_36_ skillId FK + uuid skillVersionId FK +} +"public.agent_history" { + varchar_36_ agentId FK + varchar_255_ author + timestamp_3__with_time_zone createdAt + uuid publishedById FK + json schema + json skills + json tools + timestamp_3__with_time_zone updatedAt + varchar_36_ versionId +} +"public.skill" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + uuid createdById FK + varchar_36_ id + varchar_36_ projectId FK + varchar_16_ source + timestamp_3__with_time_zone updatedAt +} +"public.skill_version" { + varchar_64_ contentHash + timestamp_3__with_time_zone createdAt + uuid createdById FK + varchar_1024_ description + json frontmatter + uuid id + text instructions + varchar_128_ name + varchar_36_ skillId FK + timestamp_3__with_time_zone updatedAt + integer version +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.agents.md b/docs/generated/postgres-schema/public.agents.md index 3d52647188f..63aa85de828 100644 --- a/docs/generated/postgres-schema/public.agents.md +++ b/docs/generated/postgres-schema/public.agents.md @@ -7,7 +7,7 @@ | activeVersionId | varchar(36) | | true | | [public.agent_history](public.agent_history.md) | | | availableInMCP | boolean | false | false | | | Whether MCP clients granted agent scopes may operate on this agent | | createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | -| id | varchar(36) | | false | [public.agent_background_job](public.agent_background_job.md) [public.agent_channel_status](public.agent_channel_status.md) [public.agent_chat_attachments](public.agent_chat_attachments.md) [public.agent_chat_subscriptions](public.agent_chat_subscriptions.md) [public.agent_checkpoints](public.agent_checkpoints.md) [public.agent_credential_dependency](public.agent_credential_dependency.md) [public.agent_eval_dataset](public.agent_eval_dataset.md) [public.agent_execution_threads](public.agent_execution_threads.md) [public.agent_files](public.agent_files.md) [public.agent_history](public.agent_history.md) [public.agent_task_definition](public.agent_task_definition.md) [public.agent_task_run_lock](public.agent_task_run_lock.md) [public.agent_workflow_dependency](public.agent_workflow_dependency.md) [public.agents_memory_entries](public.agents_memory_entries.md) [public.agents_memory_entry_candidates](public.agents_memory_entry_candidates.md) [public.agents_memory_entry_locks](public.agents_memory_entry_locks.md) [public.agents_memory_entry_sources](public.agents_memory_entry_sources.md) [public.agents_observation_cursors](public.agents_observation_cursors.md) [public.agents_observation_locks](public.agents_observation_locks.md) [public.agents_observations](public.agents_observations.md) | | | +| id | varchar(36) | | false | [public.agent_background_job](public.agent_background_job.md) [public.agent_channel_status](public.agent_channel_status.md) [public.agent_chat_attachments](public.agent_chat_attachments.md) [public.agent_chat_subscriptions](public.agent_chat_subscriptions.md) [public.agent_checkpoints](public.agent_checkpoints.md) [public.agent_credential_dependency](public.agent_credential_dependency.md) [public.agent_eval_dataset](public.agent_eval_dataset.md) [public.agent_execution_threads](public.agent_execution_threads.md) [public.agent_files](public.agent_files.md) [public.agent_history](public.agent_history.md) [public.agent_skill_dependency](public.agent_skill_dependency.md) [public.agent_task_definition](public.agent_task_definition.md) [public.agent_task_run_lock](public.agent_task_run_lock.md) [public.agent_workflow_dependency](public.agent_workflow_dependency.md) [public.agents_memory_entries](public.agents_memory_entries.md) [public.agents_memory_entry_candidates](public.agents_memory_entry_candidates.md) [public.agents_memory_entry_locks](public.agents_memory_entry_locks.md) [public.agents_memory_entry_sources](public.agents_memory_entry_sources.md) [public.agents_observation_cursors](public.agents_observation_cursors.md) [public.agents_observation_locks](public.agents_observation_locks.md) [public.agents_observations](public.agents_observations.md) [public.skill](public.skill.md) | | | | integrations | json | '[]'::json | false | | | | | name | varchar(128) | | false | | | | | projectId | varchar(255) | | false | | [public.project](public.project.md) | | @@ -61,6 +61,7 @@ erDiagram "public.agent_execution_threads" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" "public.agent_files" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" "public.agent_history" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" +"public.agent_skill_dependency" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" "public.agent_task_definition" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" "public.agent_task_run_lock" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" "public.agent_workflow_dependency" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" @@ -71,6 +72,7 @@ erDiagram "public.agents_observation_cursors" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" "public.agents_observation_locks" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" "public.agents_observations" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" +"public.skill" }o--o| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" "public.agents" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" "public.agents" { @@ -216,6 +218,12 @@ erDiagram varchar_2_ storedAt timestamp_3__with_time_zone updatedAt } +"public.agent_skill_dependency" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + varchar_36_ skillId FK + uuid skillVersionId FK +} "public.agent_task_definition" { varchar_36_ agentId FK timestamp_3__with_time_zone createdAt @@ -320,6 +328,15 @@ erDiagram integer tokenCount timestamp_3__with_time_zone updatedAt } +"public.skill" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + uuid createdById FK + varchar_36_ id + varchar_36_ projectId FK + varchar_16_ source + timestamp_3__with_time_zone updatedAt +} "public.project" { timestamp_3__with_time_zone createdAt uuid creatorId FK diff --git a/docs/generated/postgres-schema/public.project.md b/docs/generated/postgres-schema/public.project.md index 670547327f1..04d30b4ff68 100644 --- a/docs/generated/postgres-schema/public.project.md +++ b/docs/generated/postgres-schema/public.project.md @@ -9,7 +9,7 @@ | customTelemetryTags | json | '[]'::json | false | | | | | description | varchar(512) | | true | | | | | icon | json | | true | | | | -| id | varchar(36) | | false | [public.activity_event](public.activity_event.md) [public.agent_chat_attachments](public.agent_chat_attachments.md) [public.agent_execution_threads](public.agent_execution_threads.md) [public.agents](public.agents.md) [public.ai_preference](public.ai_preference.md) [public.data_table](public.data_table.md) [public.folder](public.folder.md) [public.insights_metadata](public.insights_metadata.md) [public.instance_ai_threads](public.instance_ai_threads.md) [public.project_pool_settings](public.project_pool_settings.md) [public.project_relation](public.project_relation.md) [public.project_secrets_provider_access](public.project_secrets_provider_access.md) [public.promotion_connection_project](public.promotion_connection_project.md) [public.role_mapping_rule_project](public.role_mapping_rule_project.md) [public.self_healing_result](public.self_healing_result.md) [public.shared_credentials](public.shared_credentials.md) [public.shared_workflow](public.shared_workflow.md) [public.type_availability_policy_scope](public.type_availability_policy_scope.md) [public.variables](public.variables.md) [public.workflow_review_request](public.workflow_review_request.md) [public.workflow_suggestion](public.workflow_suggestion.md) | | | +| id | varchar(36) | | false | [public.activity_event](public.activity_event.md) [public.agent_chat_attachments](public.agent_chat_attachments.md) [public.agent_execution_threads](public.agent_execution_threads.md) [public.agents](public.agents.md) [public.ai_preference](public.ai_preference.md) [public.data_table](public.data_table.md) [public.folder](public.folder.md) [public.insights_metadata](public.insights_metadata.md) [public.instance_ai_threads](public.instance_ai_threads.md) [public.project_pool_settings](public.project_pool_settings.md) [public.project_relation](public.project_relation.md) [public.project_secrets_provider_access](public.project_secrets_provider_access.md) [public.promotion_connection_project](public.promotion_connection_project.md) [public.role_mapping_rule_project](public.role_mapping_rule_project.md) [public.self_healing_result](public.self_healing_result.md) [public.shared_credentials](public.shared_credentials.md) [public.shared_workflow](public.shared_workflow.md) [public.skill](public.skill.md) [public.type_availability_policy_scope](public.type_availability_policy_scope.md) [public.variables](public.variables.md) [public.workflow_review_request](public.workflow_review_request.md) [public.workflow_suggestion](public.workflow_suggestion.md) | | | | name | varchar(255) | | false | | | | | type | varchar(36) | | false | | | | | updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | @@ -56,6 +56,7 @@ erDiagram "public.self_healing_result" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" "public.shared_credentials" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" "public.shared_workflow" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" +"public.skill" }o--o| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" "public.type_availability_policy_scope" }o--o| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" "public.variables" }o--o| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" "public.workflow_review_request" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" @@ -255,6 +256,15 @@ erDiagram timestamp_3__with_time_zone updatedAt varchar_36_ workflowId FK } +"public.skill" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + uuid createdById FK + varchar_36_ id + varchar_36_ projectId FK + varchar_16_ source + timestamp_3__with_time_zone updatedAt +} "public.type_availability_policy_scope" { timestamp_3__with_time_zone createdAt varchar_16_ defaultAction diff --git a/docs/generated/postgres-schema/public.skill.md b/docs/generated/postgres-schema/public.skill.md new file mode 100644 index 00000000000..9b424ab5239 --- /dev/null +++ b/docs/generated/postgres-schema/public.skill.md @@ -0,0 +1,131 @@ +# public.skill + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| agentId | varchar(36) | | true | | [public.agents](public.agents.md) | Set when only this agent can use the skill. projectId is then NULL: the agent holds the project | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| createdById | uuid | | true | | [public.user](public.user.md) | Author. NULL after the author is deleted | +| id | varchar(36) | | false | [public.agent_skill_dependency](public.agent_skill_dependency.md) [public.agent_version_skill_dependency](public.agent_version_skill_dependency.md) [public.skill_version](public.skill_version.md) | | skill_\, the same format agents use | +| projectId | varchar(36) | | true | | [public.project](public.project.md) | Set for a project skill, team or personal. NULL otherwise | +| source | varchar(16) | | false | | | How the skill was created, set by the server: "ui" (the skills hub) or "agent" (the agent builder or the copy of agent skills) | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| CHK_skill_single_target | CHECK | CHECK ((("agentId" IS NULL) OR ("projectId" IS NULL))) | +| FK_402ed37bff0d3134f6e782455ed | FOREIGN KEY | FOREIGN KEY ("projectId") REFERENCES project(id) ON DELETE CASCADE | +| FK_4de4501583cd1fcd6f5ea85f547 | FOREIGN KEY | FOREIGN KEY ("createdById") REFERENCES "user"(id) ON DELETE SET NULL | +| FK_7d4fb6af107e507d9a86293cf9d | FOREIGN KEY | FOREIGN KEY ("agentId") REFERENCES agents(id) ON DELETE CASCADE | +| PK_a0d33334424e64fb78dc3ce7196 | PRIMARY KEY | PRIMARY KEY (id) | +| skill_createdAt_not_null | n | NOT NULL "createdAt" | +| skill_id_not_null | n | NOT NULL id | +| skill_source_not_null | n | NOT NULL source | +| skill_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_402ed37bff0d3134f6e782455e | CREATE INDEX "IDX_402ed37bff0d3134f6e782455e" ON public.skill USING btree ("projectId") | +| IDX_7d4fb6af107e507d9a86293cf9 | CREATE INDEX "IDX_7d4fb6af107e507d9a86293cf9" ON public.skill USING btree ("agentId") | +| PK_a0d33334424e64fb78dc3ce7196 | CREATE UNIQUE INDEX "PK_a0d33334424e64fb78dc3ce7196" ON public.skill USING btree (id) | + +## Relations + +```mermaid +erDiagram + +"public.skill" }o--o| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE" +"public.skill" }o--o| "public.user" : "FOREIGN KEY (#quot;createdById#quot;) REFERENCES #quot;user#quot;(id) ON DELETE SET NULL" +"public.agent_skill_dependency" }o--|| "public.skill" : "FOREIGN KEY (#quot;skillId#quot;) REFERENCES skill(id) ON DELETE CASCADE" +"public.agent_version_skill_dependency" }o--|| "public.skill" : "FOREIGN KEY (#quot;skillId#quot;) REFERENCES skill(id) ON DELETE CASCADE" +"public.skill_version" }o--|| "public.skill" : "FOREIGN KEY (#quot;skillId#quot;) REFERENCES skill(id) ON DELETE CASCADE" +"public.skill" }o--o| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE" + +"public.skill" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + uuid createdById FK + varchar_36_ id + varchar_36_ projectId FK + varchar_16_ source + timestamp_3__with_time_zone updatedAt +} +"public.agents" { + varchar_36_ activeVersionId FK + boolean availableInMCP + timestamp_3__with_time_zone createdAt + varchar_36_ id + json integrations + varchar_128_ name + varchar_255_ projectId FK + integer revision + json schema + timestamp_3__with_time_zone setupCompletedAt + json skills + json tools + timestamp_3__with_time_zone updatedAt + varchar_36_ versionId +} +"public.user" { + timestamp_3__with_time_zone createdAt + boolean disabled + varchar_255_ email + varchar_32_ firstName + uuid id + date lastActiveAt + varchar_32_ lastName + boolean mfaEnabled + text mfaRecoveryCodes + text mfaSecret + varchar_255_ password + json personalizationAnswers + varchar_128_ roleSlug FK + json settings + timestamp_3__with_time_zone updatedAt +} +"public.agent_skill_dependency" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + varchar_36_ skillId FK + uuid skillVersionId FK +} +"public.agent_version_skill_dependency" { + varchar_36_ agentVersionId FK + timestamp_3__with_time_zone createdAt + varchar_36_ skillId FK + uuid skillVersionId FK +} +"public.skill_version" { + varchar_64_ contentHash + timestamp_3__with_time_zone createdAt + uuid createdById FK + varchar_1024_ description + json frontmatter + uuid id + text instructions + varchar_128_ name + varchar_36_ skillId FK + timestamp_3__with_time_zone updatedAt + integer version +} +"public.project" { + timestamp_3__with_time_zone createdAt + uuid creatorId FK + json customTelemetryTags + varchar_512_ description + json icon + varchar_36_ id + varchar_255_ name + varchar_36_ type + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.skill_file.md b/docs/generated/postgres-schema/public.skill_file.md new file mode 100644 index 00000000000..051bcb40661 --- /dev/null +++ b/docs/generated/postgres-schema/public.skill_file.md @@ -0,0 +1,62 @@ +# public.skill_file + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| content | text | | false | | | | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| path | varchar(512) | | false | | | Relative path, references/*.md in v1 | +| skillVersionId | uuid | | false | | [public.skill_version](public.skill_version.md) | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| FK_e9ab50b795ec8858702b7333d13 | FOREIGN KEY | FOREIGN KEY ("skillVersionId") REFERENCES skill_version(id) ON DELETE CASCADE | +| PK_160721f9e4c22026c16138af2a1 | PRIMARY KEY | PRIMARY KEY ("skillVersionId", path) | +| skill_file_content_not_null | n | NOT NULL content | +| skill_file_createdAt_not_null | n | NOT NULL "createdAt" | +| skill_file_path_not_null | n | NOT NULL path | +| skill_file_skillVersionId_not_null | n | NOT NULL "skillVersionId" | +| skill_file_updatedAt_not_null | n | NOT NULL "updatedAt" | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_160721f9e4c22026c16138af2a1 | CREATE UNIQUE INDEX "PK_160721f9e4c22026c16138af2a1" ON public.skill_file USING btree ("skillVersionId", path) | + +## Relations + +```mermaid +erDiagram + +"public.skill_file" }o--|| "public.skill_version" : "FOREIGN KEY (#quot;skillVersionId#quot;) REFERENCES skill_version(id) ON DELETE CASCADE" + +"public.skill_file" { + text content + timestamp_3__with_time_zone createdAt + varchar_512_ path + uuid skillVersionId FK + timestamp_3__with_time_zone updatedAt +} +"public.skill_version" { + varchar_64_ contentHash + timestamp_3__with_time_zone createdAt + uuid createdById FK + varchar_1024_ description + json frontmatter + uuid id + text instructions + varchar_128_ name + varchar_36_ skillId FK + timestamp_3__with_time_zone updatedAt + integer version +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.skill_version.md b/docs/generated/postgres-schema/public.skill_version.md new file mode 100644 index 00000000000..562a13ad867 --- /dev/null +++ b/docs/generated/postgres-schema/public.skill_version.md @@ -0,0 +1,118 @@ +# public.skill_version + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| contentHash | varchar(64) | | false | | | sha256 of name, description, instructions, frontmatter and files. Save creates no version when the content matches the latest one | +| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| createdById | uuid | | true | | [public.user](public.user.md) | Author. NULL after the author is deleted | +| description | varchar(1024) | | false | | | | +| frontmatter | json | | true | | | SKILL.md frontmatter fields other than name and description, e.g. allowed-tools | +| id | uuid | | false | [public.agent_skill_dependency](public.agent_skill_dependency.md) [public.agent_version_skill_dependency](public.agent_version_skill_dependency.md) [public.skill_file](public.skill_file.md) | | | +| instructions | text | | false | | | | +| name | varchar(128) | | false | | | Free-text skill name, as it was when this version was saved | +| skillId | varchar(36) | | false | | [public.skill](public.skill.md) | | +| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | | +| version | integer | | false | | | 1..n per skill. A Save that changes the content adds one; none ever changes | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| CHK_skill_version_version | CHECK | CHECK ((version > 0)) | +| FK_9565d0fbf32cd463f9b47c7adab | FOREIGN KEY | FOREIGN KEY ("createdById") REFERENCES "user"(id) ON DELETE SET NULL | +| FK_f87064c0a29efd2d5195328d91a | FOREIGN KEY | FOREIGN KEY ("skillId") REFERENCES skill(id) ON DELETE CASCADE | +| PK_05167d59ac7599128e22400172d | PRIMARY KEY | PRIMARY KEY (id) | +| UQ_93bb78a1eb4e0890fac6b69df95 | UNIQUE | UNIQUE ("skillId", version) | +| skill_version_contentHash_not_null | n | NOT NULL "contentHash" | +| skill_version_createdAt_not_null | n | NOT NULL "createdAt" | +| skill_version_description_not_null | n | NOT NULL description | +| skill_version_id_not_null | n | NOT NULL id | +| skill_version_instructions_not_null | n | NOT NULL instructions | +| skill_version_name_not_null | n | NOT NULL name | +| skill_version_skillId_not_null | n | NOT NULL "skillId" | +| skill_version_updatedAt_not_null | n | NOT NULL "updatedAt" | +| skill_version_version_not_null | n | NOT NULL version | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| PK_05167d59ac7599128e22400172d | CREATE UNIQUE INDEX "PK_05167d59ac7599128e22400172d" ON public.skill_version USING btree (id) | +| UQ_93bb78a1eb4e0890fac6b69df95 | CREATE UNIQUE INDEX "UQ_93bb78a1eb4e0890fac6b69df95" ON public.skill_version USING btree ("skillId", version) | + +## Relations + +```mermaid +erDiagram + +"public.skill_version" }o--o| "public.user" : "FOREIGN KEY (#quot;createdById#quot;) REFERENCES #quot;user#quot;(id) ON DELETE SET NULL" +"public.agent_skill_dependency" }o--o| "public.skill_version" : "FOREIGN KEY (#quot;skillVersionId#quot;) REFERENCES skill_version(id)" +"public.agent_version_skill_dependency" }o--|| "public.skill_version" : "FOREIGN KEY (#quot;skillVersionId#quot;) REFERENCES skill_version(id)" +"public.skill_file" }o--|| "public.skill_version" : "FOREIGN KEY (#quot;skillVersionId#quot;) REFERENCES skill_version(id) ON DELETE CASCADE" +"public.skill_version" }o--|| "public.skill" : "FOREIGN KEY (#quot;skillId#quot;) REFERENCES skill(id) ON DELETE CASCADE" + +"public.skill_version" { + varchar_64_ contentHash + timestamp_3__with_time_zone createdAt + uuid createdById FK + varchar_1024_ description + json frontmatter + uuid id + text instructions + varchar_128_ name + varchar_36_ skillId FK + timestamp_3__with_time_zone updatedAt + integer version +} +"public.user" { + timestamp_3__with_time_zone createdAt + boolean disabled + varchar_255_ email + varchar_32_ firstName + uuid id + date lastActiveAt + varchar_32_ lastName + boolean mfaEnabled + text mfaRecoveryCodes + text mfaSecret + varchar_255_ password + json personalizationAnswers + varchar_128_ roleSlug FK + json settings + timestamp_3__with_time_zone updatedAt +} +"public.agent_skill_dependency" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + varchar_36_ skillId FK + uuid skillVersionId FK +} +"public.agent_version_skill_dependency" { + varchar_36_ agentVersionId FK + timestamp_3__with_time_zone createdAt + varchar_36_ skillId FK + uuid skillVersionId FK +} +"public.skill_file" { + text content + timestamp_3__with_time_zone createdAt + varchar_512_ path + uuid skillVersionId FK + timestamp_3__with_time_zone updatedAt +} +"public.skill" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + uuid createdById FK + varchar_36_ id + varchar_36_ projectId FK + varchar_16_ source + timestamp_3__with_time_zone updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/postgres-schema/public.user.md b/docs/generated/postgres-schema/public.user.md index 2bcc7d1d5e9..8db545537e7 100644 --- a/docs/generated/postgres-schema/public.user.md +++ b/docs/generated/postgres-schema/public.user.md @@ -8,7 +8,7 @@ | disabled | boolean | false | false | | | | | email | varchar(255) | | true | | | | | firstName | varchar(32) | | true | | | | -| id | uuid | gen_random_uuid() | false | [public.activity_event](public.activity_event.md) [public.agent_eval_dataset](public.agent_eval_dataset.md) [public.agent_eval_rating](public.agent_eval_rating.md) [public.agent_eval_run](public.agent_eval_run.md) [public.agent_execution_threads](public.agent_execution_threads.md) [public.agent_history](public.agent_history.md) [public.ai_preference](public.ai_preference.md) [public.auth_identity](public.auth_identity.md) [public.chat_hub_agents](public.chat_hub_agents.md) [public.chat_hub_sessions](public.chat_hub_sessions.md) [public.chat_hub_tools](public.chat_hub_tools.md) [public.dynamic_credential_user_entry](public.dynamic_credential_user_entry.md) [public.evaluation_collection](public.evaluation_collection.md) [public.idempotency_key](public.idempotency_key.md) [public.instance_ai_mcp_registry_connections](public.instance_ai_mcp_registry_connections.md) [public.instance_ai_pending_confirmations](public.instance_ai_pending_confirmations.md) [public.instance_ai_thread_grants](public.instance_ai_thread_grants.md) [public.instance_ai_thread_tabs](public.instance_ai_thread_tabs.md) [public.migration_workflow_owner](public.migration_workflow_owner.md) [public.oauth_access_tokens](public.oauth_access_tokens.md) [public.oauth_authorization_codes](public.oauth_authorization_codes.md) [public.oauth_refresh_tokens](public.oauth_refresh_tokens.md) [public.oauth_user_consents](public.oauth_user_consents.md) [public.project](public.project.md) [public.project_relation](public.project_relation.md) [public.self_healing_result](public.self_healing_result.md) [public.trusted_source_identity](public.trusted_source_identity.md) [public.user_api_keys](public.user_api_keys.md) [public.user_favorites](public.user_favorites.md) [public.workflow_builder_session](public.workflow_builder_session.md) [public.workflow_publish_history](public.workflow_publish_history.md) [public.workflow_review_activity](public.workflow_review_activity.md) [public.workflow_review_activity_comment](public.workflow_review_activity_comment.md) [public.workflow_review_request](public.workflow_review_request.md) [public.workflow_review_request_authors](public.workflow_review_request_authors.md) [public.workflow_review_request_reviewers](public.workflow_review_request_reviewers.md) [public.workflow_suggestion](public.workflow_suggestion.md) [public.workflow_suggestion_activity](public.workflow_suggestion_activity.md) | | | +| id | uuid | gen_random_uuid() | false | [public.activity_event](public.activity_event.md) [public.agent_eval_dataset](public.agent_eval_dataset.md) [public.agent_eval_rating](public.agent_eval_rating.md) [public.agent_eval_run](public.agent_eval_run.md) [public.agent_execution_threads](public.agent_execution_threads.md) [public.agent_history](public.agent_history.md) [public.ai_preference](public.ai_preference.md) [public.auth_identity](public.auth_identity.md) [public.chat_hub_agents](public.chat_hub_agents.md) [public.chat_hub_sessions](public.chat_hub_sessions.md) [public.chat_hub_tools](public.chat_hub_tools.md) [public.dynamic_credential_user_entry](public.dynamic_credential_user_entry.md) [public.evaluation_collection](public.evaluation_collection.md) [public.idempotency_key](public.idempotency_key.md) [public.instance_ai_mcp_registry_connections](public.instance_ai_mcp_registry_connections.md) [public.instance_ai_pending_confirmations](public.instance_ai_pending_confirmations.md) [public.instance_ai_thread_grants](public.instance_ai_thread_grants.md) [public.instance_ai_thread_tabs](public.instance_ai_thread_tabs.md) [public.migration_workflow_owner](public.migration_workflow_owner.md) [public.oauth_access_tokens](public.oauth_access_tokens.md) [public.oauth_authorization_codes](public.oauth_authorization_codes.md) [public.oauth_refresh_tokens](public.oauth_refresh_tokens.md) [public.oauth_user_consents](public.oauth_user_consents.md) [public.project](public.project.md) [public.project_relation](public.project_relation.md) [public.self_healing_result](public.self_healing_result.md) [public.skill](public.skill.md) [public.skill_version](public.skill_version.md) [public.trusted_source_identity](public.trusted_source_identity.md) [public.user_api_keys](public.user_api_keys.md) [public.user_favorites](public.user_favorites.md) [public.workflow_builder_session](public.workflow_builder_session.md) [public.workflow_publish_history](public.workflow_publish_history.md) [public.workflow_review_activity](public.workflow_review_activity.md) [public.workflow_review_activity_comment](public.workflow_review_activity_comment.md) [public.workflow_review_request](public.workflow_review_request.md) [public.workflow_review_request_authors](public.workflow_review_request_authors.md) [public.workflow_review_request_reviewers](public.workflow_review_request_reviewers.md) [public.workflow_suggestion](public.workflow_suggestion.md) [public.workflow_suggestion_activity](public.workflow_suggestion_activity.md) | | | | lastActiveAt | date | | true | | | | | lastName | varchar(32) | | true | | | | | mfaEnabled | boolean | false | false | | | | @@ -76,6 +76,8 @@ erDiagram "public.project_relation" }o--|| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" "public.self_healing_result" }o--|| "public.user" : "FOREIGN KEY (#quot;backgroundUserId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" "public.self_healing_result" }o--o| "public.user" : "FOREIGN KEY (#quot;dismissedById#quot;) REFERENCES #quot;user#quot;(id) ON DELETE SET NULL" +"public.skill" }o--o| "public.user" : "FOREIGN KEY (#quot;createdById#quot;) REFERENCES #quot;user#quot;(id) ON DELETE SET NULL" +"public.skill_version" }o--o| "public.user" : "FOREIGN KEY (#quot;createdById#quot;) REFERENCES #quot;user#quot;(id) ON DELETE SET NULL" "public.trusted_source_identity" }o--|| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" "public.user_api_keys" }o--|| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" "public.user_favorites" }o--|| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE CASCADE" @@ -398,6 +400,28 @@ erDiagram json usage varchar_36_ workflowId FK } +"public.skill" { + varchar_36_ agentId FK + timestamp_3__with_time_zone createdAt + uuid createdById FK + varchar_36_ id + varchar_36_ projectId FK + varchar_16_ source + timestamp_3__with_time_zone updatedAt +} +"public.skill_version" { + varchar_64_ contentHash + timestamp_3__with_time_zone createdAt + uuid createdById FK + varchar_1024_ description + json frontmatter + uuid id + text instructions + varchar_128_ name + varchar_36_ skillId FK + timestamp_3__with_time_zone updatedAt + integer version +} "public.trusted_source_identity" { timestamp_3__with_time_zone createdAt timestamp_3__with_time_zone lastSeenAt diff --git a/docs/generated/sqlite-schema/README.md b/docs/generated/sqlite-schema/README.md index c62c719c3f0..6e946dc580d 100644 --- a/docs/generated/sqlite-schema/README.md +++ b/docs/generated/sqlite-schema/README.md @@ -29,10 +29,12 @@ Auto-generated from the SQLite migrations in @n8n/db. Do not edit by hand. | [agent_message_queue](agent_message_queue.md) | 10 | | table | | [agent_plan](agent_plan.md) | 8 | | table | | [agent_plan_history](agent_plan_history.md) | 6 | | table | +| [agent_skill_dependency](agent_skill_dependency.md) | 4 | | table | | [agent_task_definition](agent_task_definition.md) | 8 | | table | | [agent_task_run_lock](agent_task_run_lock.md) | 6 | | table | | [agent_task_snapshot](agent_task_snapshot.md) | 9 | | table | | [agent_thread_grants](agent_thread_grants.md) | 4 | | table | +| [agent_version_skill_dependency](agent_version_skill_dependency.md) | 4 | | table | | [agent_workflow_dependency](agent_workflow_dependency.md) | 3 | | table | | [agents](agents.md) | 14 | | table | | [agents_memory_entries](agents_memory_entries.md) | 13 | | table | @@ -131,6 +133,9 @@ Auto-generated from the SQLite migrations in @n8n/db. Do not edit by hand. | [settings](settings.md) | 3 | | table | | [shared_credentials](shared_credentials.md) | 5 | | table | | [shared_workflow](shared_workflow.md) | 5 | | table | +| [skill](skill.md) | 7 | | table | +| [skill_file](skill_file.md) | 5 | | table | +| [skill_version](skill_version.md) | 11 | | table | | [tag_entity](tag_entity.md) | 4 | | table | | [test_case_execution](test_case_execution.md) | 16 | | table | | [test_run](test_run.md) | 16 | | table | @@ -205,10 +210,16 @@ erDiagram "agent_message_queue" }o--o| "agent_execution" : "FOREIGN KEY (steeringExecutionId) REFERENCES agent_execution (id) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE" "agent_plan" }o--|| "agent_execution_threads" : "FOREIGN KEY (threadId) REFERENCES agent_execution_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" "agent_plan_history" |o--|| "agent_plan" : "FOREIGN KEY (planId) REFERENCES agent_plan (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agent_skill_dependency" }o--o| "skill_version" : "FOREIGN KEY (skillVersionId) REFERENCES skill_version (id) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE" +"agent_skill_dependency" |o--|| "skill" : "FOREIGN KEY (skillId) REFERENCES skill (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agent_skill_dependency" |o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" "agent_task_definition" }o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" "agent_task_run_lock" |o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" "agent_task_snapshot" |o--|| "agent_history" : "FOREIGN KEY (versionId) REFERENCES agent_history (versionId) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" "agent_thread_grants" |o--|| "agent_execution_threads" : "FOREIGN KEY (threadId) REFERENCES agent_execution_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agent_version_skill_dependency" }o--|| "skill_version" : "FOREIGN KEY (skillVersionId) REFERENCES skill_version (id) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE" +"agent_version_skill_dependency" |o--|| "skill" : "FOREIGN KEY (skillId) REFERENCES skill (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agent_version_skill_dependency" |o--|| "agent_history" : "FOREIGN KEY (agentVersionId) REFERENCES agent_history (versionId) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" "agent_workflow_dependency" |o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" "agent_workflow_dependency" |o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" "agents" }o--|| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" @@ -351,6 +362,12 @@ erDiagram "shared_credentials" |o--|| "credentials_entity" : "FOREIGN KEY (credentialsId) REFERENCES credentials_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" "shared_workflow" |o--|| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" "shared_workflow" |o--|| "workflow_entity" : "FOREIGN KEY (workflowId) REFERENCES workflow_entity (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"skill" }o--o| "user" : "FOREIGN KEY (createdById) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"skill" }o--o| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"skill" }o--o| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"skill_file" |o--|| "skill_version" : "FOREIGN KEY (skillVersionId) REFERENCES skill_version (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"skill_version" }o--o| "user" : "FOREIGN KEY (createdById) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"skill_version" }o--|| "skill" : "FOREIGN KEY (skillId) REFERENCES skill (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" "test_case_execution" }o--|| "test_run" : "FOREIGN KEY (testRunId) REFERENCES test_run (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" "test_case_execution" }o--o| "execution_entity" : "FOREIGN KEY (pastExecutionId) REFERENCES execution_entity (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" "test_case_execution" }o--o| "execution_entity" : "FOREIGN KEY (executionId) REFERENCES execution_entity (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" @@ -665,6 +682,12 @@ erDiagram varchar planId PK INTEGER revision PK } +"agent_skill_dependency" { + varchar_36_ agentId PK + datetime_3_ createdAt + varchar_36_ skillId PK + varchar skillVersionId FK +} "agent_task_definition" { varchar_36_ agentId FK datetime_3_ createdAt @@ -700,6 +723,12 @@ erDiagram varchar_128_ threadId PK datetime_3_ updatedAt } +"agent_version_skill_dependency" { + varchar_36_ agentVersionId PK + datetime_3_ createdAt + varchar_36_ skillId PK + varchar skillVersionId FK +} "agent_workflow_dependency" { varchar_36_ agentId PK datetime_3_ createdAt @@ -1637,6 +1666,35 @@ erDiagram datetime_3_ updatedAt varchar_36_ workflowId PK } +"skill" { + varchar_36_ agentId FK + datetime_3_ createdAt + varchar createdById FK + varchar_36_ id PK + varchar_36_ projectId FK + varchar_16_ source + datetime_3_ updatedAt +} +"skill_file" { + TEXT content + datetime_3_ createdAt + varchar_512_ path PK + varchar skillVersionId PK + datetime_3_ updatedAt +} +"skill_version" { + varchar_64_ contentHash + datetime_3_ createdAt + varchar createdById FK + varchar_1024_ description + TEXT frontmatter + varchar id PK + TEXT instructions + varchar_128_ name + varchar_36_ skillId FK + datetime_3_ updatedAt + INTEGER version +} "tag_entity" { datetime_3_ createdAt varchar_36_ id PK diff --git a/docs/generated/sqlite-schema/agent_history.md b/docs/generated/sqlite-schema/agent_history.md index af7c4ea1e48..b157fab3042 100644 --- a/docs/generated/sqlite-schema/agent_history.md +++ b/docs/generated/sqlite-schema/agent_history.md @@ -23,7 +23,7 @@ CREATE TABLE "agent_history" ("versionId" varchar(36) PRIMARY KEY NOT NULL, "age | skills | TEXT | | true | | | | | tools | TEXT | | true | | | | | updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | -| versionId | varchar(36) | | false | [agent_execution_threads](agent_execution_threads.md) [agent_task_snapshot](agent_task_snapshot.md) [agents](agents.md) | | | +| versionId | varchar(36) | | false | [agent_execution_threads](agent_execution_threads.md) [agent_task_snapshot](agent_task_snapshot.md) [agent_version_skill_dependency](agent_version_skill_dependency.md) [agents](agents.md) | | | ## Constraints @@ -50,6 +50,7 @@ erDiagram "agent_history" }o--o| "user" : "FOREIGN KEY (publishedById) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" "agent_execution_threads" }o--o| "agent_history" : "FOREIGN KEY (taskVersionId) REFERENCES agent_history (versionId) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" "agent_task_snapshot" |o--|| "agent_history" : "FOREIGN KEY (versionId) REFERENCES agent_history (versionId) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agent_version_skill_dependency" |o--|| "agent_history" : "FOREIGN KEY (agentVersionId) REFERENCES agent_history (versionId) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" "agents" }o--o| "agent_history" : "FOREIGN KEY (activeVersionId) REFERENCES agent_history (versionId) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" "agent_history" { @@ -128,6 +129,12 @@ erDiagram datetime_3_ updatedAt varchar_36_ versionId PK } +"agent_version_skill_dependency" { + varchar_36_ agentVersionId PK + datetime_3_ createdAt + varchar_36_ skillId PK + varchar skillVersionId FK +} ``` --- diff --git a/docs/generated/sqlite-schema/agent_skill_dependency.md b/docs/generated/sqlite-schema/agent_skill_dependency.md new file mode 100644 index 00000000000..114d3a3998e --- /dev/null +++ b/docs/generated/sqlite-schema/agent_skill_dependency.md @@ -0,0 +1,98 @@ +# agent_skill_dependency + +## Description + +
+Table Definition + +```sql +CREATE TABLE "agent_skill_dependency" ("agentId" varchar(36) NOT NULL, "skillId" varchar(36) NOT NULL, "skillVersionId" varchar, "createdAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), CONSTRAINT "FK_72325bb13511a51847c53fcb377" FOREIGN KEY ("agentId") REFERENCES "agents" ("id") ON DELETE CASCADE, CONSTRAINT "FK_068f21aefba31ae621482f396dc" FOREIGN KEY ("skillId") REFERENCES "skill" ("id") ON DELETE CASCADE, CONSTRAINT "FK_7676571bd6f41d9e32f0d066fe9" FOREIGN KEY ("skillVersionId") REFERENCES "skill_version" ("id") ON DELETE NO ACTION, PRIMARY KEY ("agentId", "skillId")) +``` + +
+ +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| agentId | varchar(36) | | false | | [agents](agents.md) | | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| skillId | varchar(36) | | false | | [skill](skill.md) | | +| skillVersionId | varchar | | true | | [skill_version](skill_version.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (skillVersionId) REFERENCES skill_version (id) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (skillId) REFERENCES skill (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 2) | FOREIGN KEY | FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| agentId | PRIMARY KEY | PRIMARY KEY (agentId) | +| skillId | PRIMARY KEY | PRIMARY KEY (skillId) | +| sqlite_autoindex_agent_skill_dependency_1 | PRIMARY KEY | PRIMARY KEY (agentId, skillId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_068f21aefba31ae621482f396d | CREATE INDEX "IDX_068f21aefba31ae621482f396d" ON "agent_skill_dependency" ("skillId") | +| sqlite_autoindex_agent_skill_dependency_1 | PRIMARY KEY (agentId, skillId) | + +## Relations + +```mermaid +erDiagram + +"agent_skill_dependency" |o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agent_skill_dependency" |o--|| "skill" : "FOREIGN KEY (skillId) REFERENCES skill (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agent_skill_dependency" }o--o| "skill_version" : "FOREIGN KEY (skillVersionId) REFERENCES skill_version (id) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE" + +"agent_skill_dependency" { + varchar_36_ agentId PK + datetime_3_ createdAt + varchar_36_ skillId PK + varchar skillVersionId FK +} +"agents" { + varchar_36_ activeVersionId FK + boolean availableInMCP + datetime_3_ createdAt + varchar_36_ id PK + TEXT integrations + varchar_128_ name + varchar_255_ projectId FK + INTEGER revision + TEXT schema + datetime_3_ setupCompletedAt + TEXT skills + TEXT tools + datetime_3_ updatedAt + varchar_36_ versionId +} +"skill" { + varchar_36_ agentId FK + datetime_3_ createdAt + varchar createdById FK + varchar_36_ id PK + varchar_36_ projectId FK + varchar_16_ source + datetime_3_ updatedAt +} +"skill_version" { + varchar_64_ contentHash + datetime_3_ createdAt + varchar createdById FK + varchar_1024_ description + TEXT frontmatter + varchar id PK + TEXT instructions + varchar_128_ name + varchar_36_ skillId FK + datetime_3_ updatedAt + INTEGER version +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/agent_version_skill_dependency.md b/docs/generated/sqlite-schema/agent_version_skill_dependency.md new file mode 100644 index 00000000000..9d8971a4724 --- /dev/null +++ b/docs/generated/sqlite-schema/agent_version_skill_dependency.md @@ -0,0 +1,94 @@ +# agent_version_skill_dependency + +## Description + +
+Table Definition + +```sql +CREATE TABLE "agent_version_skill_dependency" ("agentVersionId" varchar(36) NOT NULL, "skillId" varchar(36) NOT NULL, "skillVersionId" varchar NOT NULL, "createdAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), CONSTRAINT "FK_97472baf9196d914d9cd9de6201" FOREIGN KEY ("agentVersionId") REFERENCES "agent_history" ("versionId") ON DELETE CASCADE, CONSTRAINT "FK_c494292243a7e510acd0331c3d1" FOREIGN KEY ("skillId") REFERENCES "skill" ("id") ON DELETE CASCADE, CONSTRAINT "FK_df63badfd7d3f2aa622ece471c4" FOREIGN KEY ("skillVersionId") REFERENCES "skill_version" ("id") ON DELETE NO ACTION, PRIMARY KEY ("agentVersionId", "skillId")) +``` + +
+ +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| agentVersionId | varchar(36) | | false | | [agent_history](agent_history.md) | | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| skillId | varchar(36) | | false | | [skill](skill.md) | | +| skillVersionId | varchar | | false | | [skill_version](skill_version.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (skillVersionId) REFERENCES skill_version (id) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (skillId) REFERENCES skill (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 2) | FOREIGN KEY | FOREIGN KEY (agentVersionId) REFERENCES agent_history (versionId) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| agentVersionId | PRIMARY KEY | PRIMARY KEY (agentVersionId) | +| skillId | PRIMARY KEY | PRIMARY KEY (skillId) | +| sqlite_autoindex_agent_version_skill_dependency_1 | PRIMARY KEY | PRIMARY KEY (agentVersionId, skillId) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_c494292243a7e510acd0331c3d | CREATE INDEX "IDX_c494292243a7e510acd0331c3d" ON "agent_version_skill_dependency" ("skillId") | +| IDX_df63badfd7d3f2aa622ece471c | CREATE INDEX "IDX_df63badfd7d3f2aa622ece471c" ON "agent_version_skill_dependency" ("skillVersionId") | +| sqlite_autoindex_agent_version_skill_dependency_1 | PRIMARY KEY (agentVersionId, skillId) | + +## Relations + +```mermaid +erDiagram + +"agent_version_skill_dependency" |o--|| "agent_history" : "FOREIGN KEY (agentVersionId) REFERENCES agent_history (versionId) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agent_version_skill_dependency" |o--|| "skill" : "FOREIGN KEY (skillId) REFERENCES skill (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agent_version_skill_dependency" }o--|| "skill_version" : "FOREIGN KEY (skillVersionId) REFERENCES skill_version (id) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE" + +"agent_version_skill_dependency" { + varchar_36_ agentVersionId PK + datetime_3_ createdAt + varchar_36_ skillId PK + varchar skillVersionId FK +} +"agent_history" { + varchar_36_ agentId FK + varchar_255_ author + datetime_3_ createdAt + varchar publishedById FK + TEXT schema + TEXT skills + TEXT tools + datetime_3_ updatedAt + varchar_36_ versionId PK +} +"skill" { + varchar_36_ agentId FK + datetime_3_ createdAt + varchar createdById FK + varchar_36_ id PK + varchar_36_ projectId FK + varchar_16_ source + datetime_3_ updatedAt +} +"skill_version" { + varchar_64_ contentHash + datetime_3_ createdAt + varchar createdById FK + varchar_1024_ description + TEXT frontmatter + varchar id PK + TEXT instructions + varchar_128_ name + varchar_36_ skillId FK + datetime_3_ updatedAt + INTEGER version +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/agents.md b/docs/generated/sqlite-schema/agents.md index 1b0d460634d..b7feda944a9 100644 --- a/docs/generated/sqlite-schema/agents.md +++ b/docs/generated/sqlite-schema/agents.md @@ -18,7 +18,7 @@ CREATE TABLE "agents" ("id" varchar(36) PRIMARY KEY NOT NULL, "name" varchar(128 | activeVersionId | varchar(36) | | true | | [agent_history](agent_history.md) | | | availableInMCP | boolean | false | false | | | | | createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | -| id | varchar(36) | | false | [agent_background_job](agent_background_job.md) [agent_channel_status](agent_channel_status.md) [agent_chat_attachments](agent_chat_attachments.md) [agent_chat_subscriptions](agent_chat_subscriptions.md) [agent_checkpoints](agent_checkpoints.md) [agent_credential_dependency](agent_credential_dependency.md) [agent_eval_dataset](agent_eval_dataset.md) [agent_execution_threads](agent_execution_threads.md) [agent_files](agent_files.md) [agent_history](agent_history.md) [agent_task_definition](agent_task_definition.md) [agent_task_run_lock](agent_task_run_lock.md) [agent_workflow_dependency](agent_workflow_dependency.md) [agents_memory_entries](agents_memory_entries.md) [agents_memory_entry_candidates](agents_memory_entry_candidates.md) [agents_memory_entry_locks](agents_memory_entry_locks.md) [agents_memory_entry_sources](agents_memory_entry_sources.md) [agents_observation_cursors](agents_observation_cursors.md) [agents_observation_locks](agents_observation_locks.md) [agents_observations](agents_observations.md) | | | +| id | varchar(36) | | false | [agent_background_job](agent_background_job.md) [agent_channel_status](agent_channel_status.md) [agent_chat_attachments](agent_chat_attachments.md) [agent_chat_subscriptions](agent_chat_subscriptions.md) [agent_checkpoints](agent_checkpoints.md) [agent_credential_dependency](agent_credential_dependency.md) [agent_eval_dataset](agent_eval_dataset.md) [agent_execution_threads](agent_execution_threads.md) [agent_files](agent_files.md) [agent_history](agent_history.md) [agent_skill_dependency](agent_skill_dependency.md) [agent_task_definition](agent_task_definition.md) [agent_task_run_lock](agent_task_run_lock.md) [agent_workflow_dependency](agent_workflow_dependency.md) [agents_memory_entries](agents_memory_entries.md) [agents_memory_entry_candidates](agents_memory_entry_candidates.md) [agents_memory_entry_locks](agents_memory_entry_locks.md) [agents_memory_entry_sources](agents_memory_entry_sources.md) [agents_observation_cursors](agents_observation_cursors.md) [agents_observation_locks](agents_observation_locks.md) [agents_observations](agents_observations.md) [skill](skill.md) | | | | integrations | TEXT | '[]' | false | | | | | name | varchar(128) | | false | | | | | projectId | varchar(255) | | false | | [project](project.md) | | @@ -63,6 +63,7 @@ erDiagram "agent_execution_threads" }o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" "agent_files" }o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" "agent_history" }o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agent_skill_dependency" |o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" "agent_task_definition" }o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" "agent_task_run_lock" |o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" "agent_workflow_dependency" |o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" @@ -73,6 +74,7 @@ erDiagram "agents_observation_cursors" |o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" "agents_observation_locks" |o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" "agents_observations" }o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"skill" }o--o| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" "agents" }o--|| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" "agents" { @@ -218,6 +220,12 @@ erDiagram varchar_2_ storedAt datetime_3_ updatedAt } +"agent_skill_dependency" { + varchar_36_ agentId PK + datetime_3_ createdAt + varchar_36_ skillId PK + varchar skillVersionId FK +} "agent_task_definition" { varchar_36_ agentId FK datetime_3_ createdAt @@ -322,6 +330,15 @@ erDiagram INTEGER tokenCount datetime_3_ updatedAt } +"skill" { + varchar_36_ agentId FK + datetime_3_ createdAt + varchar createdById FK + varchar_36_ id PK + varchar_36_ projectId FK + varchar_16_ source + datetime_3_ updatedAt +} "project" { datetime_3_ createdAt varchar creatorId FK diff --git a/docs/generated/sqlite-schema/project.md b/docs/generated/sqlite-schema/project.md index 62d8edb9bd9..46f39c7fb0b 100644 --- a/docs/generated/sqlite-schema/project.md +++ b/docs/generated/sqlite-schema/project.md @@ -20,7 +20,7 @@ CREATE TABLE "project" ("id" varchar(36) PRIMARY KEY NOT NULL, "name" varchar(25 | customTelemetryTags | TEXT | '[]' | false | | | | | description | varchar(512) | | true | | | | | icon | TEXT | | true | | | | -| id | varchar(36) | | false | [activity_event](activity_event.md) [agent_chat_attachments](agent_chat_attachments.md) [agent_execution_threads](agent_execution_threads.md) [agents](agents.md) [ai_preference](ai_preference.md) [data_table](data_table.md) [folder](folder.md) [insights_metadata](insights_metadata.md) [instance_ai_threads](instance_ai_threads.md) [project_pool_settings](project_pool_settings.md) [project_relation](project_relation.md) [project_secrets_provider_access](project_secrets_provider_access.md) [promotion_connection_project](promotion_connection_project.md) [role_mapping_rule_project](role_mapping_rule_project.md) [self_healing_result](self_healing_result.md) [shared_credentials](shared_credentials.md) [shared_workflow](shared_workflow.md) [type_availability_policy_scope](type_availability_policy_scope.md) [variables](variables.md) [workflow_review_request](workflow_review_request.md) [workflow_suggestion](workflow_suggestion.md) | | | +| id | varchar(36) | | false | [activity_event](activity_event.md) [agent_chat_attachments](agent_chat_attachments.md) [agent_execution_threads](agent_execution_threads.md) [agents](agents.md) [ai_preference](ai_preference.md) [data_table](data_table.md) [folder](folder.md) [insights_metadata](insights_metadata.md) [instance_ai_threads](instance_ai_threads.md) [project_pool_settings](project_pool_settings.md) [project_relation](project_relation.md) [project_secrets_provider_access](project_secrets_provider_access.md) [promotion_connection_project](promotion_connection_project.md) [role_mapping_rule_project](role_mapping_rule_project.md) [self_healing_result](self_healing_result.md) [shared_credentials](shared_credentials.md) [shared_workflow](shared_workflow.md) [skill](skill.md) [type_availability_policy_scope](type_availability_policy_scope.md) [variables](variables.md) [workflow_review_request](workflow_review_request.md) [workflow_suggestion](workflow_suggestion.md) | | | | name | varchar(255) | | false | | | | | type | varchar(36) | | false | | | | | updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | @@ -62,6 +62,7 @@ erDiagram "self_healing_result" }o--|| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" "shared_credentials" |o--|| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" "shared_workflow" |o--|| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"skill" }o--o| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" "type_availability_policy_scope" }o--o| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" "variables" }o--o| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" "workflow_review_request" }o--|| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" @@ -261,6 +262,15 @@ erDiagram datetime_3_ updatedAt varchar_36_ workflowId PK } +"skill" { + varchar_36_ agentId FK + datetime_3_ createdAt + varchar createdById FK + varchar_36_ id PK + varchar_36_ projectId FK + varchar_16_ source + datetime_3_ updatedAt +} "type_availability_policy_scope" { datetime_3_ createdAt varchar_16_ defaultAction diff --git a/docs/generated/sqlite-schema/skill.md b/docs/generated/sqlite-schema/skill.md new file mode 100644 index 00000000000..8be4273cb95 --- /dev/null +++ b/docs/generated/sqlite-schema/skill.md @@ -0,0 +1,139 @@ +# skill + +## Description + +
+Table Definition + +```sql +CREATE TABLE "skill" ("id" varchar(36) PRIMARY KEY NOT NULL, "projectId" varchar(36), "agentId" varchar(36), "source" varchar(16) NOT NULL, "createdById" varchar, "createdAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), "updatedAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), CONSTRAINT "CHK_skill_single_target" CHECK ("agentId" IS NULL OR "projectId" IS NULL), CONSTRAINT "FK_402ed37bff0d3134f6e782455ed" FOREIGN KEY ("projectId") REFERENCES "project" ("id") ON DELETE CASCADE, CONSTRAINT "FK_7d4fb6af107e507d9a86293cf9d" FOREIGN KEY ("agentId") REFERENCES "agents" ("id") ON DELETE CASCADE, CONSTRAINT "FK_4de4501583cd1fcd6f5ea85f547" FOREIGN KEY ("createdById") REFERENCES "user" ("id") ON DELETE SET NULL) +``` + +
+ +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| agentId | varchar(36) | | true | | [agents](agents.md) | | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| createdById | varchar | | true | | [user](user.md) | | +| id | varchar(36) | | false | [agent_skill_dependency](agent_skill_dependency.md) [agent_version_skill_dependency](agent_version_skill_dependency.md) [skill_version](skill_version.md) | | | +| projectId | varchar(36) | | true | | [project](project.md) | | +| source | varchar(16) | | false | | | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - | CHECK | CHECK ("agentId" IS NULL OR "projectId" IS NULL) | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (createdById) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| - (Foreign key ID: 2) | FOREIGN KEY | FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_skill_1 | PRIMARY KEY | PRIMARY KEY (id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| IDX_402ed37bff0d3134f6e782455e | CREATE INDEX "IDX_402ed37bff0d3134f6e782455e" ON "skill" ("projectId") | +| IDX_7d4fb6af107e507d9a86293cf9 | CREATE INDEX "IDX_7d4fb6af107e507d9a86293cf9" ON "skill" ("agentId") | +| sqlite_autoindex_skill_1 | PRIMARY KEY (id) | + +## Relations + +```mermaid +erDiagram + +"skill" }o--o| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"skill" }o--o| "user" : "FOREIGN KEY (createdById) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"agent_skill_dependency" |o--|| "skill" : "FOREIGN KEY (skillId) REFERENCES skill (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"agent_version_skill_dependency" |o--|| "skill" : "FOREIGN KEY (skillId) REFERENCES skill (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"skill_version" }o--|| "skill" : "FOREIGN KEY (skillId) REFERENCES skill (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"skill" }o--o| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"skill" { + varchar_36_ agentId FK + datetime_3_ createdAt + varchar createdById FK + varchar_36_ id PK + varchar_36_ projectId FK + varchar_16_ source + datetime_3_ updatedAt +} +"agents" { + varchar_36_ activeVersionId FK + boolean availableInMCP + datetime_3_ createdAt + varchar_36_ id PK + TEXT integrations + varchar_128_ name + varchar_255_ projectId FK + INTEGER revision + TEXT schema + datetime_3_ setupCompletedAt + TEXT skills + TEXT tools + datetime_3_ updatedAt + varchar_36_ versionId +} +"user" { + datetime_3_ createdAt + boolean disabled + varchar_255_ email + varchar_32_ firstName + varchar id PK + date lastActiveAt + varchar_32_ lastName + boolean mfaEnabled + TEXT mfaRecoveryCodes + TEXT mfaSecret + varchar password + TEXT personalizationAnswers + varchar_128_ roleSlug FK + TEXT settings + datetime_3_ updatedAt +} +"agent_skill_dependency" { + varchar_36_ agentId PK + datetime_3_ createdAt + varchar_36_ skillId PK + varchar skillVersionId FK +} +"agent_version_skill_dependency" { + varchar_36_ agentVersionId PK + datetime_3_ createdAt + varchar_36_ skillId PK + varchar skillVersionId FK +} +"skill_version" { + varchar_64_ contentHash + datetime_3_ createdAt + varchar createdById FK + varchar_1024_ description + TEXT frontmatter + varchar id PK + TEXT instructions + varchar_128_ name + varchar_36_ skillId FK + datetime_3_ updatedAt + INTEGER version +} +"project" { + datetime_3_ createdAt + varchar creatorId FK + TEXT customTelemetryTags + varchar_512_ description + TEXT icon + varchar_36_ id PK + varchar_255_ name + varchar_36_ type + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/skill_file.md b/docs/generated/sqlite-schema/skill_file.md new file mode 100644 index 00000000000..549a0742c4b --- /dev/null +++ b/docs/generated/sqlite-schema/skill_file.md @@ -0,0 +1,70 @@ +# skill_file + +## Description + +
+Table Definition + +```sql +CREATE TABLE "skill_file" ("skillVersionId" varchar NOT NULL, "path" varchar(512) NOT NULL, "content" text NOT NULL, "createdAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), "updatedAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), CONSTRAINT "FK_e9ab50b795ec8858702b7333d13" FOREIGN KEY ("skillVersionId") REFERENCES "skill_version" ("id") ON DELETE CASCADE, PRIMARY KEY ("skillVersionId", "path")) +``` + +
+ +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| content | TEXT | | false | | | | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| path | varchar(512) | | false | | | | +| skillVersionId | varchar | | false | | [skill_version](skill_version.md) | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (skillVersionId) REFERENCES skill_version (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| path | PRIMARY KEY | PRIMARY KEY (path) | +| skillVersionId | PRIMARY KEY | PRIMARY KEY (skillVersionId) | +| sqlite_autoindex_skill_file_1 | PRIMARY KEY | PRIMARY KEY (skillVersionId, path) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_skill_file_1 | PRIMARY KEY (skillVersionId, path) | + +## Relations + +```mermaid +erDiagram + +"skill_file" |o--|| "skill_version" : "FOREIGN KEY (skillVersionId) REFERENCES skill_version (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"skill_file" { + TEXT content + datetime_3_ createdAt + varchar_512_ path PK + varchar skillVersionId PK + datetime_3_ updatedAt +} +"skill_version" { + varchar_64_ contentHash + datetime_3_ createdAt + varchar createdById FK + varchar_1024_ description + TEXT frontmatter + varchar id PK + TEXT instructions + varchar_128_ name + varchar_36_ skillId FK + datetime_3_ updatedAt + INTEGER version +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/skill_version.md b/docs/generated/sqlite-schema/skill_version.md new file mode 100644 index 00000000000..23a5e245be9 --- /dev/null +++ b/docs/generated/sqlite-schema/skill_version.md @@ -0,0 +1,121 @@ +# skill_version + +## Description + +
+Table Definition + +```sql +CREATE TABLE "skill_version" ("id" varchar PRIMARY KEY NOT NULL, "skillId" varchar(36) NOT NULL, "version" integer NOT NULL, "name" varchar(128) NOT NULL, "description" varchar(1024) NOT NULL, "instructions" text NOT NULL, "frontmatter" text, "contentHash" varchar(64) NOT NULL, "createdById" varchar, "createdAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), "updatedAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), CONSTRAINT "UQ_93bb78a1eb4e0890fac6b69df95" UNIQUE ("skillId", "version"), CONSTRAINT "CHK_skill_version_version" CHECK ("version" > 0), CONSTRAINT "FK_f87064c0a29efd2d5195328d91a" FOREIGN KEY ("skillId") REFERENCES "skill" ("id") ON DELETE CASCADE, CONSTRAINT "FK_9565d0fbf32cd463f9b47c7adab" FOREIGN KEY ("createdById") REFERENCES "user" ("id") ON DELETE SET NULL) +``` + +
+ +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| contentHash | varchar(64) | | false | | | | +| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| createdById | varchar | | true | | [user](user.md) | | +| description | varchar(1024) | | false | | | | +| frontmatter | TEXT | | true | | | | +| id | varchar | | false | [agent_skill_dependency](agent_skill_dependency.md) [agent_version_skill_dependency](agent_version_skill_dependency.md) [skill_file](skill_file.md) | | | +| instructions | TEXT | | false | | | | +| name | varchar(128) | | false | | | | +| skillId | varchar(36) | | false | | [skill](skill.md) | | +| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | | +| version | INTEGER | | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| - | CHECK | CHECK ("version" > 0) | +| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (createdById) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE | +| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (skillId) REFERENCES skill (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE | +| id | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_skill_version_1 | PRIMARY KEY | PRIMARY KEY (id) | +| sqlite_autoindex_skill_version_2 | UNIQUE | UNIQUE (skillId, version) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| sqlite_autoindex_skill_version_1 | PRIMARY KEY (id) | +| sqlite_autoindex_skill_version_2 | UNIQUE (skillId, version) | + +## Relations + +```mermaid +erDiagram + +"skill_version" }o--o| "user" : "FOREIGN KEY (createdById) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"agent_skill_dependency" }o--o| "skill_version" : "FOREIGN KEY (skillVersionId) REFERENCES skill_version (id) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE" +"agent_version_skill_dependency" }o--|| "skill_version" : "FOREIGN KEY (skillVersionId) REFERENCES skill_version (id) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE" +"skill_file" |o--|| "skill_version" : "FOREIGN KEY (skillVersionId) REFERENCES skill_version (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"skill_version" }o--|| "skill" : "FOREIGN KEY (skillId) REFERENCES skill (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" + +"skill_version" { + varchar_64_ contentHash + datetime_3_ createdAt + varchar createdById FK + varchar_1024_ description + TEXT frontmatter + varchar id PK + TEXT instructions + varchar_128_ name + varchar_36_ skillId FK + datetime_3_ updatedAt + INTEGER version +} +"user" { + datetime_3_ createdAt + boolean disabled + varchar_255_ email + varchar_32_ firstName + varchar id PK + date lastActiveAt + varchar_32_ lastName + boolean mfaEnabled + TEXT mfaRecoveryCodes + TEXT mfaSecret + varchar password + TEXT personalizationAnswers + varchar_128_ roleSlug FK + TEXT settings + datetime_3_ updatedAt +} +"agent_skill_dependency" { + varchar_36_ agentId PK + datetime_3_ createdAt + varchar_36_ skillId PK + varchar skillVersionId FK +} +"agent_version_skill_dependency" { + varchar_36_ agentVersionId PK + datetime_3_ createdAt + varchar_36_ skillId PK + varchar skillVersionId FK +} +"skill_file" { + TEXT content + datetime_3_ createdAt + varchar_512_ path PK + varchar skillVersionId PK + datetime_3_ updatedAt +} +"skill" { + varchar_36_ agentId FK + datetime_3_ createdAt + varchar createdById FK + varchar_36_ id PK + varchar_36_ projectId FK + varchar_16_ source + datetime_3_ updatedAt +} +``` + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/generated/sqlite-schema/user.md b/docs/generated/sqlite-schema/user.md index bea5531dfa9..1402b80f8f9 100644 --- a/docs/generated/sqlite-schema/user.md +++ b/docs/generated/sqlite-schema/user.md @@ -19,7 +19,7 @@ CREATE TABLE "user" ("id" varchar PRIMARY KEY, "email" varchar(255), "firstName" | disabled | boolean | FALSE | false | | | | | email | varchar(255) | | true | | | | | firstName | varchar(32) | | true | | | | -| id | varchar | | true | [activity_event](activity_event.md) [agent_eval_dataset](agent_eval_dataset.md) [agent_eval_rating](agent_eval_rating.md) [agent_eval_run](agent_eval_run.md) [agent_execution_threads](agent_execution_threads.md) [agent_history](agent_history.md) [ai_preference](ai_preference.md) [auth_identity](auth_identity.md) [chat_hub_agents](chat_hub_agents.md) [chat_hub_sessions](chat_hub_sessions.md) [chat_hub_tools](chat_hub_tools.md) [dynamic_credential_user_entry](dynamic_credential_user_entry.md) [evaluation_collection](evaluation_collection.md) [idempotency_key](idempotency_key.md) [instance_ai_mcp_registry_connections](instance_ai_mcp_registry_connections.md) [instance_ai_pending_confirmations](instance_ai_pending_confirmations.md) [instance_ai_thread_grants](instance_ai_thread_grants.md) [instance_ai_thread_tabs](instance_ai_thread_tabs.md) [migration_workflow_owner](migration_workflow_owner.md) [oauth_access_tokens](oauth_access_tokens.md) [oauth_authorization_codes](oauth_authorization_codes.md) [oauth_refresh_tokens](oauth_refresh_tokens.md) [oauth_user_consents](oauth_user_consents.md) [project](project.md) [project_relation](project_relation.md) [self_healing_result](self_healing_result.md) [trusted_source_identity](trusted_source_identity.md) [user_api_keys](user_api_keys.md) [user_favorites](user_favorites.md) [workflow_builder_session](workflow_builder_session.md) [workflow_publish_history](workflow_publish_history.md) [workflow_review_activity](workflow_review_activity.md) [workflow_review_activity_comment](workflow_review_activity_comment.md) [workflow_review_request](workflow_review_request.md) [workflow_review_request_authors](workflow_review_request_authors.md) [workflow_review_request_reviewers](workflow_review_request_reviewers.md) [workflow_suggestion](workflow_suggestion.md) [workflow_suggestion_activity](workflow_suggestion_activity.md) | | | +| id | varchar | | true | [activity_event](activity_event.md) [agent_eval_dataset](agent_eval_dataset.md) [agent_eval_rating](agent_eval_rating.md) [agent_eval_run](agent_eval_run.md) [agent_execution_threads](agent_execution_threads.md) [agent_history](agent_history.md) [ai_preference](ai_preference.md) [auth_identity](auth_identity.md) [chat_hub_agents](chat_hub_agents.md) [chat_hub_sessions](chat_hub_sessions.md) [chat_hub_tools](chat_hub_tools.md) [dynamic_credential_user_entry](dynamic_credential_user_entry.md) [evaluation_collection](evaluation_collection.md) [idempotency_key](idempotency_key.md) [instance_ai_mcp_registry_connections](instance_ai_mcp_registry_connections.md) [instance_ai_pending_confirmations](instance_ai_pending_confirmations.md) [instance_ai_thread_grants](instance_ai_thread_grants.md) [instance_ai_thread_tabs](instance_ai_thread_tabs.md) [migration_workflow_owner](migration_workflow_owner.md) [oauth_access_tokens](oauth_access_tokens.md) [oauth_authorization_codes](oauth_authorization_codes.md) [oauth_refresh_tokens](oauth_refresh_tokens.md) [oauth_user_consents](oauth_user_consents.md) [project](project.md) [project_relation](project_relation.md) [self_healing_result](self_healing_result.md) [skill](skill.md) [skill_version](skill_version.md) [trusted_source_identity](trusted_source_identity.md) [user_api_keys](user_api_keys.md) [user_favorites](user_favorites.md) [workflow_builder_session](workflow_builder_session.md) [workflow_publish_history](workflow_publish_history.md) [workflow_review_activity](workflow_review_activity.md) [workflow_review_activity_comment](workflow_review_activity_comment.md) [workflow_review_request](workflow_review_request.md) [workflow_review_request_authors](workflow_review_request_authors.md) [workflow_review_request_reviewers](workflow_review_request_reviewers.md) [workflow_suggestion](workflow_suggestion.md) [workflow_suggestion_activity](workflow_suggestion_activity.md) | | | | lastActiveAt | date | | true | | | | | lastName | varchar(32) | | true | | | | | mfaEnabled | boolean | FALSE | false | | | | @@ -82,6 +82,8 @@ erDiagram "project_relation" |o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" "self_healing_result" }o--o| "user" : "FOREIGN KEY (dismissedById) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" "self_healing_result" }o--|| "user" : "FOREIGN KEY (backgroundUserId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" +"skill" }o--o| "user" : "FOREIGN KEY (createdById) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" +"skill_version" }o--o| "user" : "FOREIGN KEY (createdById) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE" "trusted_source_identity" }o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" "user_api_keys" }o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" "user_favorites" }o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE" @@ -404,6 +406,28 @@ erDiagram TEXT usage varchar_36_ workflowId FK } +"skill" { + varchar_36_ agentId FK + datetime_3_ createdAt + varchar createdById FK + varchar_36_ id PK + varchar_36_ projectId FK + varchar_16_ source + datetime_3_ updatedAt +} +"skill_version" { + varchar_64_ contentHash + datetime_3_ createdAt + varchar createdById FK + varchar_1024_ description + TEXT frontmatter + varchar id PK + TEXT instructions + varchar_128_ name + varchar_36_ skillId FK + datetime_3_ updatedAt + INTEGER version +} "trusted_source_identity" { datetime_3_ createdAt datetime_3_ lastSeenAt diff --git a/package.json b/package.json index 5f861b19104..f5f43281e32 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "n8n-monorepo", - "version": "2.43.0", + "version": "2.44.0", "private": true, "engines": { "node": ">=24.0.0", diff --git a/packages/@n8n/agents/package.json b/packages/@n8n/agents/package.json index 3498ea34bfc..6d05a9a27be 100644 --- a/packages/@n8n/agents/package.json +++ b/packages/@n8n/agents/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/agents", - "version": "0.28.0", + "version": "0.29.0", "description": "AI agent SDK for n8n's code-first execution engine", "engines": { "node": ">=24.0.0" diff --git a/packages/@n8n/agents/src/runtime/__tests__/delegate-sub-agent-tool.test.ts b/packages/@n8n/agents/src/runtime/__tests__/delegate-sub-agent-tool.test.ts index 16b5f07f091..de0ac68aff4 100644 --- a/packages/@n8n/agents/src/runtime/__tests__/delegate-sub-agent-tool.test.ts +++ b/packages/@n8n/agents/src/runtime/__tests__/delegate-sub-agent-tool.test.ts @@ -753,6 +753,27 @@ describe('createDelegateSubAgentTool', () => { expect(runSubAgent.mock.calls[0]?.[0]).not.toHaveProperty('parentAbortSignal'); expect(runSubAgent.mock.calls[0]?.[0]).not.toHaveProperty('parentExecutionCounter'); expect(runSubAgent.mock.calls[0]?.[0]).not.toHaveProperty('parentTelemetry'); + expect(runSubAgent.mock.calls[0]?.[0]).not.toHaveProperty('parentOnGuardrailNotice'); + }); + + it('forwards the guardrail notice sink from the tool context to the runner callback', async () => { + const runSubAgent = vi + .fn() + .mockResolvedValue({ status: 'completed', taskPath: '/root/research_api', answer: 'done' }); + const tool = createDelegateSubAgentTool({ runSubAgent }); + const parentOnGuardrailNotice = vi.fn(); + + await tool.handler?.(input, { + runId: 'parent-run-1', + onGuardrailNotice: parentOnGuardrailNotice, + }); + + expect(runSubAgent).toHaveBeenCalledWith( + expect.objectContaining({ parentOnGuardrailNotice }), + expect.objectContaining({ + runInlineSubAgent: expect.any(Function), + }), + ); }); it('forwards the parent telemetry from the tool context to the runner callback', async () => { @@ -1203,6 +1224,66 @@ describe('generateResultToDelegateSubAgentOutput', () => { }); }); + it('maps a guardrail stop to failed with the session cap reason', () => { + const result: GenerateResult = { + runId: 'child-run-6', + messages: [], + finishReason: 'guardrail', + guardrail: { code: 'budget.session' }, + getState: () => ({ + status: 'failed', + messageList: { messages: [], historyIds: [], inputIds: [], responseIds: [] }, + pendingToolCalls: {}, + }), + }; + + expect(generateResultToDelegateSubAgentOutput('/root/x_0', result)).toMatchObject({ + status: 'failed', + finishReason: 'guardrail', + error: 'The sub-agent run was stopped: the session cost cap is spent.', + }); + }); + + it('maps a monthly budget stop to failed with the monthly reason', () => { + const result: GenerateResult = { + runId: 'child-run-7', + messages: [], + finishReason: 'guardrail', + guardrail: { code: 'budget.monthly' }, + getState: () => ({ + status: 'failed', + messageList: { messages: [], historyIds: [], inputIds: [], responseIds: [] }, + pendingToolCalls: {}, + }), + }; + + expect(generateResultToDelegateSubAgentOutput('/root/x_0', result)).toMatchObject({ + status: 'failed', + finishReason: 'guardrail', + error: 'The sub-agent run was stopped: the monthly budget is spent.', + }); + }); + + it('keeps a recorded error over the guardrail stop reason', () => { + const result: GenerateResult = { + runId: 'child-run-8', + messages: [], + finishReason: 'guardrail', + guardrail: { code: 'budget.session' }, + error: new Error('boom'), + getState: () => ({ + status: 'failed', + messageList: { messages: [], historyIds: [], inputIds: [], responseIds: [] }, + pendingToolCalls: {}, + }), + }; + + expect(generateResultToDelegateSubAgentOutput('/root/x_0', result)).toMatchObject({ + status: 'failed', + error: 'boom', + }); + }); + it('maps a cancelled child run to cancelled, even though it also reports an error', () => { const result: GenerateResult = { runId: 'child-run-5', diff --git a/packages/@n8n/agents/src/runtime/__tests__/mcp-connection.test.ts b/packages/@n8n/agents/src/runtime/__tests__/mcp-connection.test.ts index 87d64d1225d..dbc8f729ca1 100644 --- a/packages/@n8n/agents/src/runtime/__tests__/mcp-connection.test.ts +++ b/packages/@n8n/agents/src/runtime/__tests__/mcp-connection.test.ts @@ -625,4 +625,37 @@ describe('McpConnection — approval declaration', () => { expect(conn.declaresApproval()).toBe(true); }); + + it('does not declare approval for non-interrupting tool configuration', () => { + const conn = new McpConnection({ + name: 's1', + url: 'https://example.test/mcp', + configureTools: () => ({ toolFilter: { mode: 'exclude', tools: ['x'] } }), + configureToolsNonInterrupting: true, + }); + + expect(conn.declaresApproval()).toBe(false); + }); + + it('ignores the non-interrupting flag when there is no tool configuration', () => { + const conn = new McpConnection({ + name: 's1', + url: 'https://example.test/mcp', + configureToolsNonInterrupting: true, + }); + + expect(conn.declaresApproval()).toBe(false); + }); + + it('still declares approval for a static requireApproval with non-interrupting tool configuration', () => { + const conn = new McpConnection({ + name: 's1', + url: 'https://example.test/mcp', + configureTools: () => ({}), + configureToolsNonInterrupting: true, + requireApproval: ['delete'], + }); + + expect(conn.declaresApproval()).toBe(true); + }); }); diff --git a/packages/@n8n/agents/src/runtime/__tests__/model-factory.test.ts b/packages/@n8n/agents/src/runtime/__tests__/model-factory.test.ts index 92c4d3e5f94..1b9fc6a0626 100644 --- a/packages/@n8n/agents/src/runtime/__tests__/model-factory.test.ts +++ b/packages/@n8n/agents/src/runtime/__tests__/model-factory.test.ts @@ -873,6 +873,19 @@ describe('createModel', () => { expect(model.useDeploymentBasedUrls).toBeUndefined(); }); + it('should use the deployment name on a Foundry endpoint when provided', () => { + // A Foundry deployment can be named differently from the model it + // serves, so the user's deployment name must reach the request path. + const model = createModel({ + id: 'azure-openai/gpt-4.1-nano', + apiKey: 'az-key', + endpointType: 'foundry', + baseURL: 'https://my-resource.services.ai.azure.com/openai/v1', + deploymentName: 'my-chat-model', + }) as unknown as Record; + expect(model.modelId).toBe('my-chat-model'); + }); + it('should treat a foundry endpoint without resourceName as valid', () => { expect(() => createModel({ @@ -993,6 +1006,19 @@ describe('createModel', () => { expect(mockClientOAuth2.credentials.getToken).toHaveBeenCalledTimes(1); }); + it('uses the deployment name on the Foundry Entra path when provided', () => { + // The deployment name can differ from the model it serves; it reaches + // the OpenAI-compatible path as the model id. + const model = createModel({ + id: 'azure-openai/gpt-4.1-nano', + endpointType: 'foundry', + baseURL: 'https://my-resource.services.ai.azure.com/openai/v1', + deploymentName: 'my-chat-model', + ...entraCreds, + }) as unknown as Record; + expect(model.modelId).toBe('my-chat-model'); + }); + it('rejects credentials that supply both apiKey and Entra', () => { expect(() => createModel({ diff --git a/packages/@n8n/agents/src/runtime/mcp/mcp-connection.ts b/packages/@n8n/agents/src/runtime/mcp/mcp-connection.ts index 91b50e69720..cd1e5fda53d 100644 --- a/packages/@n8n/agents/src/runtime/mcp/mcp-connection.ts +++ b/packages/@n8n/agents/src/runtime/mcp/mcp-connection.ts @@ -302,9 +302,9 @@ export class McpConnection { * without requiring a network connection. */ declaresApproval(): boolean { - const { configureTools, requireApproval } = this.config; + const { configureTools, configureToolsNonInterrupting, requireApproval } = this.config; return ( - configureTools !== undefined || + (configureTools !== undefined && !configureToolsNonInterrupting) || requireApproval === true || (Array.isArray(requireApproval) && requireApproval.length > 0) ); diff --git a/packages/@n8n/agents/src/runtime/model/model-factory.ts b/packages/@n8n/agents/src/runtime/model/model-factory.ts index ad2fa65fea2..7f4d7e4a586 100644 --- a/packages/@n8n/agents/src/runtime/model/model-factory.ts +++ b/packages/@n8n/agents/src/runtime/model/model-factory.ts @@ -412,6 +412,9 @@ const LANGUAGE_PROVIDERS: ProviderRegistry = { // `…/openai/v1/openai`. Drive it as a plain OpenAI-compatible endpoint // so the configured base is used verbatim. if (endpointType === 'foundry') { + // The path segment Foundry matches against is the user-chosen + // deployment name, which can differ from the model it serves. + const deploymentId = deploymentName ?? model; if (isEntra) { // `buildOpenAiCompatible` has no `tokenProvider` slot, so wrap the // transport to inject `Authorization: Bearer ` per request. @@ -420,11 +423,17 @@ const LANGUAGE_PROVIDERS: ProviderRegistry = { 'azure-openai', undefined, { baseURL }, - model, + deploymentId, withBearerAuth(fetch, tokenProvider), ); } - return buildOpenAiCompatible('azure-openai', undefined, { apiKey, baseURL }, model, fetch); + return buildOpenAiCompatible( + 'azure-openai', + undefined, + { apiKey, baseURL }, + deploymentId, + fetch, + ); } // Classic Azure OpenAI (`*.openai.azure.com`, or `resourceName` only). @@ -435,9 +444,10 @@ const LANGUAGE_PROVIDERS: ProviderRegistry = { // selects the Responses API + the `/v1/` path, which Azure rejects with // "API version not supported" for date-based versions. // - // Azure deployments are user-named and surfaced in the deployment-based - // URL path. The catalog model id is not the deployment id, so prefer the - // user's `deploymentName` when provided and fall back to the model id. + // Azure deployments are user-named and surfaced in the URL path on + // both endpoint types. The catalog model id is not the deployment id, + // so prefer the user's `deploymentName` when provided and fall back to + // the model id. const { createAzure } = require('@ai-sdk/azure') as typeof import('@ai-sdk/azure'); let normalizedBaseURL = baseURL; // SDK expects url like `https://resourceName.openai.azure.com/openai` diff --git a/packages/@n8n/agents/src/runtime/model/provider-credentials.ts b/packages/@n8n/agents/src/runtime/model/provider-credentials.ts index 7de7586c8fa..77989322170 100644 --- a/packages/@n8n/agents/src/runtime/model/provider-credentials.ts +++ b/packages/@n8n/agents/src/runtime/model/provider-credentials.ts @@ -75,9 +75,10 @@ export const PROVIDER_CREDENTIAL_SCHEMAS = { */ endpointType: z.enum(['classic', 'foundry']).optional(), /** - * User-defined Azure deployment name for classic endpoints. The catalog - * model id is not the deployment id, so the agent flow must carry this - * separately. Only used by the classic branch. + * User-defined Azure deployment name. The catalog model id is not the + * deployment id, so the agent flow must carry this separately. Used by + * both the classic and Foundry branches; on Foundry it overrides the + * model id in the request path. */ deploymentName: z.string().optional(), /** diff --git a/packages/@n8n/agents/src/runtime/tools/delegate-sub-agent-runner.ts b/packages/@n8n/agents/src/runtime/tools/delegate-sub-agent-runner.ts index 1af1195b474..7dc72eaeb7b 100644 --- a/packages/@n8n/agents/src/runtime/tools/delegate-sub-agent-runner.ts +++ b/packages/@n8n/agents/src/runtime/tools/delegate-sub-agent-runner.ts @@ -240,6 +240,9 @@ function createDelegateSubAgentRequest( ? { parentExecutionCounter: withoutMessageCount(ctx.executionCounter) } : {}), ...(ctx.parentTelemetry !== undefined ? { parentTelemetry: ctx.parentTelemetry } : {}), + ...(ctx.onGuardrailNotice !== undefined + ? { parentOnGuardrailNotice: ctx.onGuardrailNotice } + : {}), ...(policy !== undefined ? { policy } : {}), }; } @@ -477,6 +480,10 @@ function resolveDelegateSubAgentStatus( // error, so the state decides which of the two this really was. return result.getState().status === 'cancelled' ? 'cancelled' : 'failed'; } + // A child agent hit a guardrail stop. + if (result.finishReason === 'guardrail') { + return 'failed'; + } if (result.pendingSuspend !== undefined && result.pendingSuspend.length > 0) { return 'suspended'; } @@ -497,6 +504,17 @@ export function failedDelegatedChildSuspendOutput( }; } +function guardrailStopMessage(code: string | undefined): string { + switch (code) { + case 'budget.session': + return 'The sub-agent run was stopped: the session cost cap is spent.'; + case 'budget.monthly': + return 'The sub-agent run was stopped: the monthly budget is spent.'; + default: + return `The sub-agent run was stopped by a guardrail (${code ?? 'unknown code'}).`; + } +} + /** Map an agent {@link GenerateResult} into the delegate tool's output shape. */ export function generateResultToDelegateSubAgentOutput( taskPath: SubAgentTaskPath, @@ -518,7 +536,11 @@ export function generateResultToDelegateSubAgentOutput( } : {}), ...(result.finishReason !== undefined ? { finishReason: result.finishReason } : {}), - ...(result.error !== undefined ? { error: stringifyUnknown(result.error) } : {}), + ...(result.error !== undefined + ? { error: stringifyUnknown(result.error) } + : result.finishReason === 'guardrail' + ? { error: guardrailStopMessage(result.guardrail?.code) } + : {}), ...(status === 'suspended' && result.pendingSuspend !== undefined ? { pendingSuspend: result.pendingSuspend } : {}), diff --git a/packages/@n8n/agents/src/runtime/tools/tool-adapter.ts b/packages/@n8n/agents/src/runtime/tools/tool-adapter.ts index 087977504a2..29bfbda24f9 100644 --- a/packages/@n8n/agents/src/runtime/tools/tool-adapter.ts +++ b/packages/@n8n/agents/src/runtime/tools/tool-adapter.ts @@ -170,6 +170,7 @@ function createToolContext( abortSignal: executionContext.abortSignal, executionCounter: executionContext.executionCounter, approvalContext: executionContext.approvalContext, + onGuardrailNotice: executionContext.onGuardrailNotice, }; } diff --git a/packages/@n8n/agents/src/runtime/tools/tool-call-runner.ts b/packages/@n8n/agents/src/runtime/tools/tool-call-runner.ts index 640efbe86c6..89acc9f8488 100644 --- a/packages/@n8n/agents/src/runtime/tools/tool-call-runner.ts +++ b/packages/@n8n/agents/src/runtime/tools/tool-call-runner.ts @@ -401,6 +401,7 @@ export class ToolCallRunner { continuation, resumeSchema, onSuspend, + onGuardrailNotice: params.guardrails?.onNotice, }), abortSignal, ), diff --git a/packages/@n8n/agents/src/sdk/mcp-client.ts b/packages/@n8n/agents/src/sdk/mcp-client.ts index 71ecee8c205..9506380cce1 100644 --- a/packages/@n8n/agents/src/sdk/mcp-client.ts +++ b/packages/@n8n/agents/src/sdk/mcp-client.ts @@ -191,8 +191,9 @@ export class McpClient { /** * Returns true when any configured server declares per-server approval - * requirements (`requireApproval: true` or a non-empty `requireApproval` - * string array). Does NOT require a network connection. + * requirements (`requireApproval: true`, a non-empty `requireApproval` + * string array, or a `configureTools` callback that is not marked + * `configureToolsNonInterrupting`). Does NOT require a network connection. * * Used by the Agent builder to validate checkpoint configuration before * attempting to connect. diff --git a/packages/@n8n/agents/src/types/runtime/delegation.ts b/packages/@n8n/agents/src/types/runtime/delegation.ts index 98326995ac0..9b12584a875 100644 --- a/packages/@n8n/agents/src/types/runtime/delegation.ts +++ b/packages/@n8n/agents/src/types/runtime/delegation.ts @@ -12,6 +12,7 @@ import type { StreamChunk, TokenUsage, } from '../sdk/agent'; +import type { GuardrailNotice } from '../sdk/guardrail'; import type { BuiltProviderTool, ToolContext } from '../sdk/tool'; import type { BuiltTelemetry } from '../telemetry'; import type { JSONObject, JSONValue } from '../utils/json'; @@ -194,6 +195,7 @@ export interface DelegateSubAgentRequest extends DelegateSubAgentInput { childCount: number; /** Effective policy for this delegation. */ policy?: DelegateSubAgentPolicy; + parentOnGuardrailNotice?: (notice: GuardrailNotice) => void; } /** The result a delegation returns to the parent model and to lifecycle events. */ diff --git a/packages/@n8n/agents/src/types/sdk/guardrail.ts b/packages/@n8n/agents/src/types/sdk/guardrail.ts index ecf349ffff8..8512501e46e 100644 --- a/packages/@n8n/agents/src/types/sdk/guardrail.ts +++ b/packages/@n8n/agents/src/types/sdk/guardrail.ts @@ -51,4 +51,10 @@ export interface GuardrailsOptions { hooks: ModelGuardrail[]; agentId?: string; threadId?: string; + onNotice?: (notice: GuardrailNotice) => void; } + +export type GuardrailNotice = { + code: string; + agentId?: string; +}; diff --git a/packages/@n8n/agents/src/types/sdk/mcp.ts b/packages/@n8n/agents/src/types/sdk/mcp.ts index bcbf997a487..e712f2b3630 100644 --- a/packages/@n8n/agents/src/types/sdk/mcp.ts +++ b/packages/@n8n/agents/src/types/sdk/mcp.ts @@ -81,6 +81,13 @@ export interface McpServerConfig { */ configureTools?: (tools: McpToolDescriptor[]) => McpToolConfiguration; + /** + * Set when `configureTools` never returns `requireApproval`. The agent then + * does not need checkpoint storage for this server just because `configureTools` + * exists. A static `requireApproval` still counts. + */ + configureToolsNonInterrupting?: boolean; + /** * Custom fetch implementation used by URL-based transports (SSE, * StreamableHTTP). diff --git a/packages/@n8n/agents/src/types/sdk/tool.ts b/packages/@n8n/agents/src/types/sdk/tool.ts index 8c710476127..a63de8a0ce7 100644 --- a/packages/@n8n/agents/src/types/sdk/tool.ts +++ b/packages/@n8n/agents/src/types/sdk/tool.ts @@ -2,6 +2,7 @@ import type { JSONSchema7 } from 'json-schema'; import type { ZodType } from 'zod'; import type { AgentExecutionCounter } from './agent'; +import type { GuardrailNotice } from './guardrail'; import type { McpToolAnnotations } from './mcp'; import type { AgentMessage } from './message'; import type { ApprovalResumePayload } from '../../sdk/tool'; @@ -64,6 +65,8 @@ export interface ToolExecutionContext { continuation?: JSONValue; /** Resume schema restored from persistence for a resumed tool call. */ resumeSchema?: ToolSuspendOptions['resumeSchema']; + + onGuardrailNotice?: (notice: GuardrailNotice) => void; } export interface ToolContext { @@ -85,6 +88,7 @@ export interface ToolContext { /** Aggregate execution counter for usage telemetry inherited from the current agent run. */ executionCounter?: ToolExecutionContext['executionCounter']; approvalContext?: ToolExecutionContext['approvalContext']; + onGuardrailNotice?: (notice: GuardrailNotice) => void; } export interface InterruptibleToolContext { @@ -122,6 +126,7 @@ export interface InterruptibleToolContext { continuation?: JSONValue; /** Resume schema persisted for this suspension. */ resumeSchema?: ToolSuspendOptions['resumeSchema']; + onGuardrailNotice?: (notice: GuardrailNotice) => void; } export interface ToolCancellationContext extends ToolContext { diff --git a/packages/@n8n/ai-node-sdk/package.json b/packages/@n8n/ai-node-sdk/package.json index 54d3024f41f..8ba7696bb9c 100644 --- a/packages/@n8n/ai-node-sdk/package.json +++ b/packages/@n8n/ai-node-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/ai-node-sdk", - "version": "0.33.0", + "version": "0.34.0", "description": "SDK for building AI nodes in n8n", "types": "dist/esm/index.d.ts", "module": "dist/esm/index.js", diff --git a/packages/@n8n/ai-utilities/package.json b/packages/@n8n/ai-utilities/package.json index c631fced966..65c381c7421 100644 --- a/packages/@n8n/ai-utilities/package.json +++ b/packages/@n8n/ai-utilities/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/ai-utilities", - "version": "0.36.0", + "version": "0.37.0", "description": "Utilities for building AI nodes in n8n", "types": "dist/esm/index.d.ts", "module": "dist/esm/index.js", diff --git a/packages/@n8n/ai-utilities/src/model-discovery/__tests__/model-discovery.test.ts b/packages/@n8n/ai-utilities/src/model-discovery/__tests__/model-discovery.test.ts index d20b8ef9762..c5f4da672ec 100644 --- a/packages/@n8n/ai-utilities/src/model-discovery/__tests__/model-discovery.test.ts +++ b/packages/@n8n/ai-utilities/src/model-discovery/__tests__/model-discovery.test.ts @@ -153,6 +153,88 @@ describe('model-discovery', () => { { id: 'models/gemini-2.5-pro', name: 'models/gemini-2.5-pro' }, ]); }); + + it("labels models with the API's displayName, else the id", async () => { + const fetch = mockFetch({ + models: [ + { + name: 'models/gemini-2.5-pro', + displayName: 'Gemini 2.5 Pro', + supportedGenerationMethods: ['generateContent'], + }, + { + name: 'models/gemini-2.5-flash', + displayName: ' ', + supportedGenerationMethods: ['generateContent'], + }, + ], + }); + + const models = await listModelsForProvider('google', { apiKey: 'g-key', fetch }); + + expect(models).toEqual([ + { id: 'models/gemini-2.5-pro', name: 'Gemini 2.5 Pro' }, + { id: 'models/gemini-2.5-flash', name: 'models/gemini-2.5-flash' }, + ]); + }); + + it('lists models with a priority first and passes the priority on', async () => { + const fetch = mockFetch({ + models: [ + { name: 'models/gemini-2.5-pro', supportedGenerationMethods: ['generateContent'] }, + { + name: 'models/gemini-featured', + priority: 10, + supportedGenerationMethods: ['generateContent'], + }, + { name: 'models/gemini-2.5-flash', supportedGenerationMethods: ['generateContent'] }, + ], + }); + + const models = await listModelsForProvider('google', { apiKey: 'g-key', fetch }); + + expect(models).toEqual([ + { id: 'models/gemini-featured', name: 'models/gemini-featured', priority: 10 }, + { id: 'models/gemini-2.5-flash', name: 'models/gemini-2.5-flash' }, + { id: 'models/gemini-2.5-pro', name: 'models/gemini-2.5-pro' }, + ]); + }); + }); + + describe('google empty response', () => { + it('returns no models when the response has no models list', async () => { + const fetch = mockFetch({}); + + await expect(listModelsForProvider('google', { apiKey: 'g-key', fetch })).resolves.toEqual( + [], + ); + }); + }); + + describe('google priority', () => { + it('drops a priority that is not a finite number', async () => { + const fetch = mockFetch({ + models: [ + { + name: 'models/gemini-2.5-pro', + priority: Number.POSITIVE_INFINITY, + supportedGenerationMethods: ['generateContent'], + }, + { + name: 'models/gemini-2.5-flash', + priority: '5', + supportedGenerationMethods: ['generateContent'], + }, + ], + }); + + const models = await listModelsForProvider('google', { apiKey: 'g-key', fetch }); + + expect(models).toEqual([ + { id: 'models/gemini-2.5-flash', name: 'models/gemini-2.5-flash' }, + { id: 'models/gemini-2.5-pro', name: 'models/gemini-2.5-pro' }, + ]); + }); }); describe('groq', () => { diff --git a/packages/@n8n/ai-utilities/src/model-discovery/index.ts b/packages/@n8n/ai-utilities/src/model-discovery/index.ts index 4c5f1482c22..be2202cbc66 100644 --- a/packages/@n8n/ai-utilities/src/model-discovery/index.ts +++ b/packages/@n8n/ai-utilities/src/model-discovery/index.ts @@ -70,7 +70,14 @@ export { } from './providers/azure'; export { listCohereModels } from './providers/cohere'; export { listDeepSeekModels } from './providers/deepseek'; -export { listGoogleModels, shouldIncludeGoogleModel } from './providers/google'; +export { + getGoogleModelLabel, + listGoogleModels, + parseGoogleModels, + shouldIncludeGoogleModel, + type GoogleModel, +} from './providers/google'; +export { pinPrioritizedModels } from '@n8n/api-types'; export { listGroqModels } from './providers/groq'; export { listMiniMaxModels } from './providers/minimax'; export { listMistralModels } from './providers/mistral'; diff --git a/packages/@n8n/ai-utilities/src/model-discovery/providers/google.ts b/packages/@n8n/ai-utilities/src/model-discovery/providers/google.ts index 31127636979..5df682f60de 100644 --- a/packages/@n8n/ai-utilities/src/model-discovery/providers/google.ts +++ b/packages/@n8n/ai-utilities/src/model-discovery/providers/google.ts @@ -1,3 +1,6 @@ +import { pinPrioritizedModels } from '@n8n/api-types'; +import { z } from 'zod'; + import { baseUrl, byName, getJson } from '../request'; import type { ListModelsFn } from '../types'; @@ -33,22 +36,48 @@ export function shouldIncludeGoogleModel(model: { */ export const listGoogleModels: ListModelsFn = async (options) => { const base = baseUrl(options, 'https://generativelanguage.googleapis.com'); - const data = (await getJson( + const data = await getJson( `${base}/v1beta/models`, { 'x-goog-api-key': options.apiKey }, options, 'google', - )) as { models?: Array<{ name?: unknown; supportedGenerationMethods?: unknown }> }; + ); - return (data.models ?? []) - .filter( - (model): model is { name: string; supportedGenerationMethods?: unknown } => - typeof model.name === 'string' && - shouldIncludeGoogleModel({ - name: model.name, - supportedGenerationMethods: model.supportedGenerationMethods, - }), - ) - .map((model) => ({ id: model.name, name: model.name })) + const models = parseGoogleModels(data) + .filter(shouldIncludeGoogleModel) + .map((model) => ({ + id: model.name, + name: getGoogleModelLabel(model.name, model.displayName), + ...(model.priority !== undefined ? { priority: model.priority } : {}), + })) .sort(byName); + return pinPrioritizedModels(models, (model) => model.priority); }; + +/** A malformed optional field is dropped; a model without a name is skipped. */ +const googleModelSchema = z.object({ + name: z.string(), + displayName: z.string().optional().catch(undefined), + priority: z.number().finite().optional().catch(undefined), + supportedGenerationMethods: z.array(z.string()).optional().catch(undefined), +}); + +const googleModelsResponseSchema = z.object({ + models: z.array(z.unknown()).optional().catch(undefined), +}); + +export type GoogleModel = z.infer; + +/** Models of a Google `GET /v1beta/models` response. */ +export function parseGoogleModels(data: unknown): GoogleModel[] { + const response = googleModelsResponseSchema.safeParse(data); + return (response.success ? (response.data.models ?? []) : []).flatMap((item) => { + const model = googleModelSchema.safeParse(item); + return model.success ? [model.data] : []; + }); +} + +/** Dropdown label of a Google model: the API's `displayName`, else the id. */ +export function getGoogleModelLabel(modelId: string, displayName?: string): string { + return displayName?.trim() || modelId; +} diff --git a/packages/@n8n/ai-utilities/src/model-discovery/types.ts b/packages/@n8n/ai-utilities/src/model-discovery/types.ts index 9b0d87e5893..814610282e3 100644 --- a/packages/@n8n/ai-utilities/src/model-discovery/types.ts +++ b/packages/@n8n/ai-utilities/src/model-discovery/types.ts @@ -4,6 +4,8 @@ export interface ProviderModel { id: string; /** Human-readable name when the provider supplies one, otherwise the id. */ name: string; + /** Pickers list models with a priority first, highest first. Only the AI Gateway reports one. */ + priority?: number; } export interface ListModelsOptions { diff --git a/packages/@n8n/ai-workflow-builder.ee/package.json b/packages/@n8n/ai-workflow-builder.ee/package.json index d28d6fc377e..799645ee178 100644 --- a/packages/@n8n/ai-workflow-builder.ee/package.json +++ b/packages/@n8n/ai-workflow-builder.ee/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/ai-workflow-builder", - "version": "1.43.0", + "version": "1.44.0", "scripts": { "clean": "rimraf dist .turbo", "typecheck": "tsc --noEmit", diff --git a/packages/@n8n/api-types/package.json b/packages/@n8n/api-types/package.json index c752f8ac085..79ace0c9e6b 100644 --- a/packages/@n8n/api-types/package.json +++ b/packages/@n8n/api-types/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/api-types", - "version": "1.43.0", + "version": "1.44.0", "scripts": { "clean": "rimraf dist .turbo", "dev": "pnpm watch", @@ -42,7 +42,8 @@ "n8n-workflow": "workspace:*", "validator": "catalog:", "xss": "catalog:", - "@n8n/permissions": "workspace:*" + "@n8n/permissions": "workspace:*", + "@n8n/inbound-auth": "workspace:*" }, "peerDependencies": { "zod": "catalog:" diff --git a/packages/@n8n/api-types/src/__tests__/chat-hub-tool-types.test.ts b/packages/@n8n/api-types/src/__tests__/chat-hub-tool-types.test.ts new file mode 100644 index 00000000000..4bebc0d67df --- /dev/null +++ b/packages/@n8n/api-types/src/__tests__/chat-hub-tool-types.test.ts @@ -0,0 +1,68 @@ +import { isChatHubToolTypeAllowed } from '../chat-hub'; + +describe('isChatHubToolTypeAllowed', () => { + it.each(['@n8n/n8n-nodes-langchain.chat', '@n8n/n8n-nodes-langchain.chatHitlTool'])( + 'blocks the %s variant of the Chat tool for all users', + (type) => { + expect(isChatHubToolTypeAllowed(type, { isChatUser: false })).toBe(false); + }, + ); + + it('blocks the Data Table HITL tool for chat users', () => { + expect(isChatHubToolTypeAllowed('n8n-nodes-base.dataTableHitlTool', { isChatUser: true })).toBe( + false, + ); + }); + + it('blocks the Chat tool for all users', () => { + expect( + isChatHubToolTypeAllowed('@n8n/n8n-nodes-langchain.chatTool', { isChatUser: false }), + ).toBe(false); + expect( + isChatHubToolTypeAllowed('@n8n/n8n-nodes-langchain.chatTool', { isChatUser: true }), + ).toBe(false); + }); + + it.each([ + '@n8n/n8n-nodes-langchain.toolWorkflow', + 'n8n-nodes-base.dataTableTool', + 'n8n-nodes-base.executeCommand', + 'n8n-nodes-base.executeCommandTool', + 'n8n-nodes-base.code', + '@n8n/n8n-nodes-langchain.toolCode', + 'n8n-nodes-base.git', + 'n8n-nodes-base.gitTool', + 'n8n-nodes-base.messageAnAgentTool', + 'n8n-nodes-base.executeCommandHitlTool', + 'n8n-nodes-base.codeHitlTool', + 'n8n-nodes-base.readWriteFileHitlTool', + 'n8n-nodes-base.executeWorkflowHitlTool', + 'n8n-nodes-base.n8nHitlTool', + ])('blocks %s for chat users', (type) => { + expect(isChatHubToolTypeAllowed(type, { isChatUser: true })).toBe(false); + }); + + it.each(['n8n-nodes-base.executeCommandTool', '@n8n/n8n-nodes-langchain.toolCode'])( + 'allows %s for users who can build workflows', + (type) => { + expect(isChatHubToolTypeAllowed(type, { isChatUser: false })).toBe(true); + }, + ); + + it.each([ + 'n8n-nodes-base.slackTool', + 'n8n-nodes-base.gmailTool', + 'n8n-nodes-base.httpRequestTool', + '@n8n/n8n-nodes-langchain.toolHttpRequest', + 'n8n-nodes-base.graphqlTool', + 'n8n-nodes-base.rssFeedReadTool', + '@n8n/n8n-nodes-langchain.mcpClientTool', + 'n8n-nodes-base.sshTool', + 'n8n-nodes-base.ftpHitlTool', + 'n8n-nodes-base.jenkinsTool', + 'n8n-nodes-base.rundeckTool', + 'n8n-nodes-base.awsLambdaTool', + ])('allows %s for chat users', (type) => { + expect(isChatHubToolTypeAllowed(type, { isChatUser: true })).toBe(true); + }); +}); diff --git a/packages/@n8n/api-types/src/__tests__/model-priority.test.ts b/packages/@n8n/api-types/src/__tests__/model-priority.test.ts new file mode 100644 index 00000000000..0826f2010df --- /dev/null +++ b/packages/@n8n/api-types/src/__tests__/model-priority.test.ts @@ -0,0 +1,37 @@ +import { pinPrioritizedModels } from '../model-priority'; + +describe('pinPrioritizedModels', () => { + it('moves models with a priority to the front, highest first, and keeps the order of the rest', () => { + const models = [ + { id: 'b' }, + { id: 'low', priority: 1 }, + { id: 'a' }, + { id: 'high', priority: 10 }, + ]; + + expect(pinPrioritizedModels(models, (model) => model.priority).map((m) => m.id)).toEqual([ + 'high', + 'low', + 'b', + 'a', + ]); + }); + + it('ignores priorities that are not finite numbers', () => { + const models = [ + { id: 'a', priority: '5' }, + { id: 'b', priority: Number.NaN }, + { id: 'c' }, + { id: 'd', priority: Number.POSITIVE_INFINITY }, + { id: 'valid', priority: 1 }, + ]; + + expect(pinPrioritizedModels(models, (model) => model.priority).map((m) => m.id)).toEqual([ + 'valid', + 'a', + 'b', + 'c', + 'd', + ]); + }); +}); diff --git a/packages/@n8n/api-types/src/agent-sse.ts b/packages/@n8n/api-types/src/agent-sse.ts index 428af5eb3aa..c5ac5ec471f 100644 --- a/packages/@n8n/api-types/src/agent-sse.ts +++ b/packages/@n8n/api-types/src/agent-sse.ts @@ -165,10 +165,11 @@ export type AgentSseEvent = | { /** * Preview chat only. Monthly spend crossed the alert line. - * The run continues. + * The run continues. Also emitted when a delegate subagent hits an alert or cap. */ type: 'budget-notice'; - code: 'budget.alert'; + code: AgentBudgetNoticeCode; + agentId?: string; } | { type: 'error'; @@ -181,3 +182,15 @@ export type AgentSseEvent = missing?: string[]; } | { type: 'done'; sessionId?: string; executionId?: string }; + +export type AgentBudgetNoticeCode = 'budget.alert' | 'budget.session' | 'budget.monthly'; + +/** A budget alert or stop. `agentId` is the budget owner; absent for the run's own agent. */ +export interface AgentBudgetNotice { + code: AgentBudgetNoticeCode; + agentId?: string; // Only populated for delegated sub-agents. +} + +export function isAgentBudgetNoticeCode(code: string): code is AgentBudgetNoticeCode { + return code === 'budget.alert' || code === 'budget.session' || code === 'budget.monthly'; +} diff --git a/packages/@n8n/api-types/src/agents/__tests__/agent-config-validation.schema.test.ts b/packages/@n8n/api-types/src/agents/__tests__/agent-config-validation.schema.test.ts new file mode 100644 index 00000000000..e59cee0bbd9 --- /dev/null +++ b/packages/@n8n/api-types/src/agents/__tests__/agent-config-validation.schema.test.ts @@ -0,0 +1,15 @@ +import { agentConfigValidationWarningSchema } from '../agent-config-validation.schema'; + +describe('agentConfigValidationWarningSchema', () => { + const warning = { code: 'similar_skill_names', capability: { kind: 'skill' } }; + + it('accepts a similar_skill_names warning with two names', () => { + expect( + agentConfigValidationWarningSchema.safeParse({ ...warning, names: ['Tone', 'tone'] }).success, + ).toBe(true); + }); + + it.each([[[]], [['Tone']], [['Tone', '']]])('rejects the names %j', (names) => { + expect(agentConfigValidationWarningSchema.safeParse({ ...warning, names }).success).toBe(false); + }); +}); diff --git a/packages/@n8n/api-types/src/agents/__tests__/agent-integration.schema.test.ts b/packages/@n8n/api-types/src/agents/__tests__/agent-integration.schema.test.ts index 76c24a1c70d..8dacd50b3a0 100644 --- a/packages/@n8n/api-types/src/agents/__tests__/agent-integration.schema.test.ts +++ b/packages/@n8n/api-types/src/agents/__tests__/agent-integration.schema.test.ts @@ -1,4 +1,8 @@ -import { AgentIntegrationConfigSchema, AgentIntegrationSchema } from '../agent-integration.schema'; +import { + AgentIntegrationConfigSchema, + AgentIntegrationSchema, + resolveWhatsAppSettings, +} from '../agent-integration.schema'; import { AgentJsonConfigSchema } from '../agent-json-config.schema'; describe('AgentIntegrationSchema', () => { @@ -210,4 +214,79 @@ describe('AgentIntegrationSchema', () => { expect(parse({ somethingElse: true }).success).toBe(false); }); }); + + describe('WhatsApp settings', () => { + const parse = (settings: Record) => + AgentIntegrationSchema.safeParse({ type: 'whatsapp', credentialId: 'cred-123', settings }); + + it('accepts a WhatsApp integration without settings', () => { + expect( + AgentIntegrationSchema.safeParse({ type: 'whatsapp', credentialId: 'cred-123' }).success, + ).toBe(true); + }); + + it('accepts the typing indicator, media download and retention settings', () => { + const result = parse({ + sessionIdleTimeoutMinutes: 30, + typingIndicator: false, + downloadMedia: false, + mediaRetentionDays: 7, + }); + + expect(result.success).toBe(true); + expect(result.data?.settings).toEqual({ + sessionIdleTimeoutMinutes: 30, + typingIndicator: false, + downloadMedia: false, + mediaRetentionDays: 7, + }); + }); + + it.each([1, 365])('accepts a retention of %i days', (mediaRetentionDays) => { + expect(parse({ mediaRetentionDays }).success).toBe(true); + }); + + it.each([0, 366, 1.5, -1])('rejects a retention of %s days', (mediaRetentionDays) => { + expect(parse({ mediaRetentionDays }).success).toBe(false); + }); + + it.each([ + ['typingIndicator', 'yes'], + ['downloadMedia', 1], + ])('rejects a non-boolean %s', (key, value) => { + expect(parse({ [key]: value }).success).toBe(false); + }); + + it('rejects an unknown setting', () => { + expect(parse({ accessMode: 'public' }).success).toBe(false); + }); + }); + + describe('resolveWhatsAppSettings', () => { + it('applies the defaults when no settings are saved', () => { + const defaults = { typingIndicator: true, downloadMedia: true, mediaRetentionDays: 30 }; + + expect(resolveWhatsAppSettings()).toEqual(defaults); + expect(resolveWhatsAppSettings({})).toEqual(defaults); + expect(resolveWhatsAppSettings({ sessionIdleTimeoutMinutes: 10 })).toEqual(defaults); + }); + + it('keeps the saved values', () => { + expect( + resolveWhatsAppSettings({ + typingIndicator: false, + downloadMedia: false, + mediaRetentionDays: 90, + }), + ).toEqual({ typingIndicator: false, downloadMedia: false, mediaRetentionDays: 90 }); + }); + + it('fills only the settings that are unset', () => { + expect(resolveWhatsAppSettings({ downloadMedia: false })).toEqual({ + typingIndicator: true, + downloadMedia: false, + mediaRetentionDays: 30, + }); + }); + }); }); diff --git a/packages/@n8n/api-types/src/agents/__tests__/agent-json-config.schema.test.ts b/packages/@n8n/api-types/src/agents/__tests__/agent-json-config.schema.test.ts index c7251b52cdf..af3550eb53e 100644 --- a/packages/@n8n/api-types/src/agents/__tests__/agent-json-config.schema.test.ts +++ b/packages/@n8n/api-types/src/agents/__tests__/agent-json-config.schema.test.ts @@ -16,7 +16,7 @@ describe('AgentJsonConfigSchema — capability activation', () => { const activation = enabled === undefined ? {} : { enabled }; const config = { ...minimalConfig, - skills: [{ type: 'skill', id: 'notes', ...activation }], + skills: [{ type: 'skill', id: 'notes' }], tools: [ { type: 'custom', id: 'search', requireApproval: true, ...activation }, { type: 'workflow', workflow: 'My Workflow', workflowId: 'wf-1', ...activation }, @@ -41,7 +41,7 @@ describe('AgentJsonConfigSchema — capability activation', () => { expect( AgentJsonConfigSchema.safeParse({ ...minimalConfig, - skills: [{ type: 'skill', id: 'notes', enabled: 'false' }], + tools: [{ type: 'custom', id: 'search', enabled: 'false' }], }).success, ).toBe(false); }); @@ -636,6 +636,38 @@ describe('AgentJsonConfigSchema — model/credential coupling', () => { }); }); +describe('AgentJsonConfigSchema — MCP permissions', () => { + it('accepts category defaults and exact tool overrides', () => { + const result = AgentJsonConfigSchema.safeParse({ + ...minimalConfig, + mcpServers: [ + { + name: 'github', + url: 'https://mcp.example.com', + toolPermissions: { + categories: { read: 'always_allow', write: 'require_approval' }, + tools: { delete_repository: 'blocked' }, + }, + }, + ], + }); + + expect(result.success).toBe(true); + }); + + it.each([ + { toolFilter: { mode: 'exclude', tools: ['delete_repository'] } }, + { approval: { mode: 'global' } }, + ])('rejects migrated legacy MCP settings: %o', (legacySettings) => { + const result = AgentJsonConfigSchema.safeParse({ + ...minimalConfig, + mcpServers: [{ name: 'github', url: 'https://mcp.example.com', ...legacySettings }], + }); + + expect(result.success).toBe(false); + }); +}); + describe('formatAgentConfigZodError', () => { it('formats an invalid MCP server name as path: message without a Zod JSON dump', () => { const result = AgentJsonConfigSchema.safeParse({ diff --git a/packages/@n8n/api-types/src/agents/__tests__/inline-agent-config.schema.test.ts b/packages/@n8n/api-types/src/agents/__tests__/inline-agent-config.schema.test.ts index ab9c3eede58..0f37416dfe9 100644 --- a/packages/@n8n/api-types/src/agents/__tests__/inline-agent-config.schema.test.ts +++ b/packages/@n8n/api-types/src/agents/__tests__/inline-agent-config.schema.test.ts @@ -43,6 +43,49 @@ describe('InlineAgentJsonConfigSchema', () => { expect(result.success).toBe(true); }); + it('accepts MCP permissions that do not suspend workflow execution', () => { + const result = InlineAgentJsonConfigSchema.safeParse({ + ...baseConfig, + mcpServers: [ + { + name: 'docs', + url: 'https://mcp.example.com', + toolPermissions: { + categories: { read: 'always_allow', write: 'blocked' }, + tools: { publish: 'always_allow', search: 'blocked' }, + }, + }, + ], + }); + + expect(result.success).toBe(true); + }); + + it.each([ + { + categories: { read: 'require_approval', write: 'blocked' }, + }, + { + categories: { read: 'always_allow', write: 'require_approval' }, + }, + { + categories: { read: 'always_allow', write: 'blocked' }, + tools: { search: 'require_approval' }, + }, + ])('rejects MCP approval because workflow execution cannot resume: %o', (toolPermissions) => { + const result = InlineAgentJsonConfigSchema.safeParse({ + ...baseConfig, + mcpServers: [{ name: 'docs', url: 'https://mcp.example.com', toolPermissions }], + }); + + expect(result.success).toBe(false); + if (!result.success) { + expect(result.error.issues[0]?.message).toBe( + 'MCP tool approval is not available for inline agents', + ); + } + }); + it('rejects custom (code) tools — their bodies live on saved agents', () => { const result = InlineAgentJsonConfigSchema.safeParse({ ...baseConfig, diff --git a/packages/@n8n/api-types/src/agents/__tests__/sanitize-agent-json-config.test.ts b/packages/@n8n/api-types/src/agents/__tests__/sanitize-agent-json-config.test.ts index 90c4c2492f1..d54a93af9e1 100644 --- a/packages/@n8n/api-types/src/agents/__tests__/sanitize-agent-json-config.test.ts +++ b/packages/@n8n/api-types/src/agents/__tests__/sanitize-agent-json-config.test.ts @@ -218,15 +218,14 @@ describe('sanitizeAgentJsonConfig', () => { nodeTypeName: '@n8n/mcp-registry.github', legacyMetadataField: true, }, - toolFilter: { - mode: 'allow', - tools: ['create_issue'], - legacyToolFilterField: true, - }, - approval: { - mode: 'selected', - tools: ['create_issue'], - legacyApprovalField: true, + toolPermissions: { + categories: { + read: 'always_allow', + write: 'require_approval', + legacyCategory: 'blocked', + }, + tools: { create_issue: 'require_approval' }, + legacyPermissionsField: true, }, connectionTimeoutMs: 10_000, legacyServerField: true, @@ -247,13 +246,12 @@ describe('sanitizeAgentJsonConfig', () => { metadata: { nodeTypeName: '@n8n/mcp-registry.github', }, - toolFilter: { - mode: 'allow', - tools: ['create_issue'], - }, - approval: { - mode: 'selected', - tools: ['create_issue'], + toolPermissions: { + categories: { + read: 'always_allow', + write: 'require_approval', + }, + tools: { create_issue: 'require_approval' }, }, connectionTimeoutMs: 10_000, }, diff --git a/packages/@n8n/api-types/src/agents/__tests__/skills.schema.test.ts b/packages/@n8n/api-types/src/agents/__tests__/skills.schema.test.ts new file mode 100644 index 00000000000..6251e47b247 --- /dev/null +++ b/packages/@n8n/api-types/src/agents/__tests__/skills.schema.test.ts @@ -0,0 +1,83 @@ +import { + CreateSkillDto, + ListSkillsQueryDto, + SaveSkillDto, + SKILLS_MAX_PAGE_SIZE, +} from '../skills.schema'; + +describe('ListSkillsQueryDto', () => { + it('leaves take unset when the client sends none, so the whole list comes back', () => { + expect(ListSkillsQueryDto.parse({})).toEqual({ skip: 0, take: undefined }); + }); + + it('caps take at the page limit', () => { + expect(ListSkillsQueryDto.parse({ take: '500' }).take).toBe(SKILLS_MAX_PAGE_SIZE); + }); + + it('parses skip, take and the filters', () => { + expect( + ListSkillsQueryDto.parse({ + skip: '10', + take: '5', + search: ' voice ', + scope: 'project', + projectId: 'p1', + }), + ).toEqual({ skip: 10, take: 5, search: 'voice', scope: 'project', projectId: 'p1' }); + }); + + it.each([['0'], ['-1'], ['abc']])('rejects take "%s"', (take) => { + expect(ListSkillsQueryDto.safeParse({ take }).success).toBe(false); + }); + + it('parses the project an agent attaches skills for', () => { + expect(ListSkillsQueryDto.parse({ attachableTo: 'p1' })).toMatchObject({ attachableTo: 'p1' }); + }); + + it.each(['team', 'user'])('rejects the unknown scope %s', (scope) => { + expect(ListSkillsQueryDto.safeParse({ scope }).success).toBe(false); + }); +}); + +describe('CreateSkillDto', () => { + const skill = { name: 'Brand voice', description: 'How we write', instructions: 'Be brief.' }; + + it.each([ + [{ scope: 'project', projectId: 'p1' }], + [{ scope: 'agent', agentId: 'a1' }], + [{ scope: 'instance' }], + ])('accepts %o', (target) => { + expect(CreateSkillDto.safeParse({ ...target, skill }).success).toBe(true); + }); + + it('rejects allowed tools, which hub skills ignore', () => { + expect( + CreateSkillDto.safeParse({ + scope: 'instance', + skill: { ...skill, allowedTools: ['search'] }, + }).success, + ).toBe(false); + }); + + it('rejects a skill without instructions', () => { + expect( + CreateSkillDto.safeParse({ scope: 'instance', skill: { ...skill, instructions: '' } }) + .success, + ).toBe(false); + }); +}); + +describe('SaveSkillDto', () => { + it('accepts changed fields with the base hash', () => { + expect(SaveSkillDto.safeParse({ instructions: 'Be brief.', baseSkillHash: 'h1' }).success).toBe( + true, + ); + }); + + it.each([[{ instructions: 'Be brief.' }], [{ instructions: 'Be brief.', baseSkillHash: '' }]])( + 'rejects a save without a base hash: %o', + (payload) => { + expect(SaveSkillDto.safeParse(payload).success).toBe(false); + }, + ); +}); diff --git a/packages/@n8n/api-types/src/agents/agent-config-validation.schema.ts b/packages/@n8n/api-types/src/agents/agent-config-validation.schema.ts index 5c5aa3e94b1..ec59bd06f25 100644 --- a/packages/@n8n/api-types/src/agents/agent-config-validation.schema.ts +++ b/packages/@n8n/api-types/src/agents/agent-config-validation.schema.ts @@ -58,8 +58,24 @@ export const agentConfigValidationIssueSchema = z.object({ }); export type AgentConfigValidationIssue = z.infer; +/** Stable, i18n-free code for a validation warning. A warning does not make a config invalid. */ +export const agentConfigValidationWarningCodeSchema = z.enum(['similar_skill_names']); +export type AgentConfigValidationWarningCode = z.infer< + typeof agentConfigValidationWarningCodeSchema +>; + +export const agentConfigValidationWarningSchema = z.object({ + code: agentConfigValidationWarningCodeSchema, + capability: agentConfigValidationCapabilityRefSchema, + /** For `similar_skill_names`: the skill names that are hard to tell apart, at least two. */ + names: z.array(z.string().min(1)).min(2), +}); +export type AgentConfigValidationWarning = z.infer; + export const agentConfigValidationResponseSchema = z.object({ status: z.enum(['valid', 'invalid']), issues: z.array(agentConfigValidationIssueSchema), + /** Absent when there are no warnings. */ + warnings: z.array(agentConfigValidationWarningSchema).optional(), }); export type AgentConfigValidationResponse = z.infer; diff --git a/packages/@n8n/api-types/src/agents/agent-integration.schema.ts b/packages/@n8n/api-types/src/agents/agent-integration.schema.ts index 27390cd293e..4ee17ac05eb 100644 --- a/packages/@n8n/api-types/src/agents/agent-integration.schema.ts +++ b/packages/@n8n/api-types/src/agents/agent-integration.schema.ts @@ -104,9 +104,44 @@ export type AgentDiscordIntegrationSettings = z.infer; -export const AgentWhatsAppSettingsSchema = AgentSessionOnlySettingsSchema; +export const WHATSAPP_MEDIA_RETENTION_DAYS_MAX = 365; + +/** + * Applied when a setting is unset, so channels saved before these settings + * existed get the same behavior as new ones. + */ +export const WHATSAPP_SETTING_DEFAULTS = { + typingIndicator: true, + downloadMedia: true, + mediaRetentionDays: 30, +} as const; + +export const AgentWhatsAppSettingsSchema = z + .object({ + sessionIdleTimeoutMinutes, + /** + * Shows WhatsApp's "typing…" indicator while the agent works. The Cloud API + * sends it together with a read receipt, so this also marks the message read. + */ + typingIndicator: z.boolean().optional(), + /** Whether the agent receives the images, documents and audio customers send. */ + downloadMedia: z.boolean().optional(), + /** Days to keep downloaded media before it is deleted. */ + mediaRetentionDays: z.number().int().min(1).max(WHATSAPP_MEDIA_RETENTION_DAYS_MAX).optional(), + }) + .strict(); export type AgentWhatsAppIntegrationSettings = z.infer; +/** The WhatsApp settings in effect, with the defaults for any that were never saved. */ +export function resolveWhatsAppSettings(settings?: AgentWhatsAppIntegrationSettings) { + return { + typingIndicator: settings?.typingIndicator ?? WHATSAPP_SETTING_DEFAULTS.typingIndicator, + downloadMedia: settings?.downloadMedia ?? WHATSAPP_SETTING_DEFAULTS.downloadMedia, + mediaRetentionDays: + settings?.mediaRetentionDays ?? WHATSAPP_SETTING_DEFAULTS.mediaRetentionDays, + }; +} + /** * Where the Teams app may be used, and how much it may read there. * diff --git a/packages/@n8n/api-types/src/agents/agent-json-config.schema.ts b/packages/@n8n/api-types/src/agents/agent-json-config.schema.ts index 02841edfca2..83cec0910f8 100644 --- a/packages/@n8n/api-types/src/agents/agent-json-config.schema.ts +++ b/packages/@n8n/api-types/src/agents/agent-json-config.schema.ts @@ -1,7 +1,7 @@ import { z, type ZodError } from 'zod'; import { isDraftAgentConfig } from './agent-config-lifecycle'; -import { AgentApprovalSchema, AgentIntegrationConfigSchema } from './agent-integration.schema'; +import { AgentIntegrationConfigSchema } from './agent-integration.schema'; import { AGENT_MODEL_STRING_REGEX } from './model-providers'; import { AGENT_REASONING_LEVELS } from './reasoning'; /** @@ -15,6 +15,7 @@ import { SUB_AGENT_MAX_CHILDREN_MIN, } from './sub-agent.schema'; import { jsonValueSchema } from '../schemas/json-value.schema'; +import { mcpToolPermissionsSchema } from '../schemas/mcp-tool-permissions.schema'; export const MANAGED_CREDENTIAL_TOKEN = 'managed' as const; @@ -187,9 +188,14 @@ export const NodeConfigSchema = z.object({ credentials: z.record(NodeToolCredentialSchema).optional(), }); +/** + * A ref to a skill. A skill has no on/off state: a ref is attached or it is + * not. `versionId` pins the ref of a saved agent to one saved version of the + * skill. Without it, the agent draft runs the latest saved version. + */ const AgentJsonSkillConfigSchema = z.object({ type: z.literal('skill'), - enabled: z.boolean().optional(), + versionId: z.string().uuid().optional(), id: z .string() .min(1) @@ -265,26 +271,11 @@ export const McpServerConfigSchema = z .describe( 'Server-generated metadata. Do not set this manually; only copy it from an MCP discovery result when present', ), - toolFilter: z - .discriminatedUnion('mode', [ - z - .object({ - mode: z.literal('allow'), - tools: z.array(z.string().min(1)).default([]), - }) - .strict(), - z - .object({ - mode: z.literal('exclude'), - tools: z.array(z.string().min(1)).default([]), - }) - .strict(), - ]) + toolPermissions: mcpToolPermissionsSchema .optional() - .describe('Restricts which tools are surfaced. Tools matched by original un-prefixed name'), - approval: AgentApprovalSchema.optional().describe( - 'Human-in-the-loop approval. Absent = no approval required', - ), + .describe( + 'Optional read/write category permissions with exact-name tool overrides. Omission allows all tools without approval', + ), connectionTimeoutMs: z .number() .int() @@ -473,12 +464,12 @@ export const AgentJsonConfigBaseSchema = z.object({ model: DraftAgentModelSchema, credential: z.string().optional(), /** - * Azure OpenAI classic deployments are user-named in Azure and surfaced in - * the deployment-based URL path. The catalog model id (e.g. `gpt-4o`) is not + * Azure OpenAI deployments are user-named in Azure and surfaced in the URL + * path on both endpoint types. The catalog model id (e.g. `gpt-4o`) is not * the deployment id, so the agent flow must capture the user's deployment - * name separately. Only meaningful for the `azure-openai` provider with a - * classic endpoint; ignored by Foundry and other providers. An empty - * string is a deliberate clear of a previously stored value. + * name separately. Only meaningful for the `azure-openai` provider — on + * classic it is required, on Foundry it is optional and overrides the model + * id. An empty string is a deliberate clear of a previously stored value. */ modelDeploymentName: z.string().trim().optional(), instructions: z.string(), @@ -590,8 +581,9 @@ export type AgentJsonConfig = z.infer; declare const storedSkillRefsBrand: unique symbol; /** - * Opaque type of the legacy `skills` key in a stored config. Only the skill - * refs seam reads or writes this key. + * Opaque type of the legacy `skills` key in a stored config. Nothing reads + * or writes this key: the skill refs live in the skills hub tables. The data + * migration removes the key from stored configs. */ export interface OpaqueStoredSkillRefs { readonly [storedSkillRefsBrand]: true; @@ -599,8 +591,8 @@ export interface OpaqueStoredSkillRefs { /** * Agent config as the backend stores it on the agent draft and on each - * published version. Its `skills` key is opaque: read and write skill refs - * through `AgentSkillRefsService`. `AgentJsonConfig` (with `skills`) stays the + * published version. It holds no skill refs: read and write them through + * `AgentSkillRefsService`. `AgentJsonConfig` (with `skills`) stays the * document format of REST, MCP and the agent builder. * * Because the `skills` key is opaque, a stored config is not assignable to diff --git a/packages/@n8n/api-types/src/agents/agent-skill.schema.ts b/packages/@n8n/api-types/src/agents/agent-skill.schema.ts index bbc862ca826..5ed1ff1cad8 100644 --- a/packages/@n8n/api-types/src/agents/agent-skill.schema.ts +++ b/packages/@n8n/api-types/src/agents/agent-skill.schema.ts @@ -85,3 +85,11 @@ export const agentSkillShape = { }; export const agentSkillSchema = z.object(agentSkillShape).strict(); + +export const agentSkillAvailabilitySchema = z.enum(['project', 'agent', 'instance']); + +export type AgentSkillAvailability = z.infer; + +export const createAgentSkillSchema = agentSkillSchema.extend({ + availableTo: agentSkillAvailabilitySchema.optional(), +}); diff --git a/packages/@n8n/api-types/src/agents/dto.ts b/packages/@n8n/api-types/src/agents/dto.ts index 114bd20828a..30e2e8c1eb7 100644 --- a/packages/@n8n/api-types/src/agents/dto.ts +++ b/packages/@n8n/api-types/src/agents/dto.ts @@ -10,7 +10,12 @@ import { } from './agent-chat-attachments.constants'; import { AgentApprovalSchema, AgentTeamsSettingsSchema } from './agent-integration.schema'; import { AgentVectorStoreConfigSchema, AgentJsonConfigSchema } from './agent-json-config.schema'; -import { agentSkillSchema, agentSkillShape } from './agent-skill.schema'; +import { + agentSkillAvailabilitySchema, + agentSkillSchema, + agentSkillShape, + createAgentSkillSchema, +} from './agent-skill.schema'; import { agentTaskSchema } from './agent-task.schema'; import { N8N_CHAT_INTEGRATION_TYPE } from './types'; import { paginationSchema } from '../dto/pagination/pagination.dto'; @@ -200,19 +205,26 @@ const updateAgentSkillShape = { const updateAgentSkillSchema = z.object(updateAgentSkillShape).strict(); -export class CreateAgentSkillDto extends Z.class(agentSkillShape) { - static override schema = agentSkillSchema; +const updateAttachedAgentSkillShape = { + ...updateAgentSkillShape, + availableTo: agentSkillAvailabilitySchema.optional(), +}; - constructor(data: z.infer) { - super(agentSkillSchema.parse(data)); +const updateAttachedAgentSkillSchema = z.object(updateAttachedAgentSkillShape).strict(); + +export class CreateAgentSkillDto extends Z.class(createAgentSkillSchema.shape) { + static override schema = createAgentSkillSchema; + + constructor(data: z.infer) { + super(createAgentSkillSchema.parse(data)); } static override safeParse(data: unknown) { - return agentSkillSchema.safeParse(data); + return createAgentSkillSchema.safeParse(data); } static override parse(data: unknown) { - return agentSkillSchema.parse(data); + return createAgentSkillSchema.parse(data); } } @@ -232,6 +244,22 @@ export class UpdateAgentSkillDto extends Z.class(updateAgentSkillShape) { } } +export class UpdateAttachedAgentSkillDto extends Z.class(updateAttachedAgentSkillShape) { + static override schema = updateAttachedAgentSkillSchema; + + constructor(data: z.infer) { + super(updateAttachedAgentSkillSchema.parse(data)); + } + + static override safeParse(data: unknown) { + return updateAttachedAgentSkillSchema.safeParse(data); + } + + static override parse(data: unknown) { + return updateAttachedAgentSkillSchema.parse(data); + } +} + export const agentChatAttachmentSchema = z.object({ fileName: z.string().min(1).max(MAX_AGENT_CHAT_ATTACHMENT_FILENAME_LENGTH), mimeType: z.string().min(1).max(MAX_AGENT_CHAT_ATTACHMENT_MIMETYPE_LENGTH), @@ -373,6 +401,34 @@ export class AgentTeamsPackageDto extends Z.class({ settings: AgentTeamsSettingsSchema.optional(), }) {} +/** + * Reaches Microsoft inside a URL path, so the shape is checked here rather than + * escaped at each use: Microsoft issues these as GUIDs, and nothing else is a + * legitimate value. + */ +const microsoftId = z.string().uuid(); + +/** Names the Microsoft sign-in the Entra app is registered with. */ +export class AgentTeamsProvisionAppDto extends Z.class({ + managerCredentialId: z.string().min(1), +}) {} + +/** + * The Entra app the bot signs for is named explicitly because the bot is + * created before the channel is connected, so the agent holds no credential yet. + */ +export class AgentTeamsProvisionBotDto extends Z.class({ + managerCredentialId: z.string().min(1), + credentialId: z.string().min(1), + subscriptionId: microsoftId, +}) {} + +export class AgentTeamsPublishDto extends Z.class({ + managerCredentialId: z.string().min(1), + credentialId: z.string().min(1), + settings: AgentTeamsSettingsSchema.optional(), +}) {} + export class AgentDisconnectIntegrationDto extends Z.class({ type: z.string().min(1), // Empty string targets a draft integration entry (`credentialId: ''`). diff --git a/packages/@n8n/api-types/src/agents/index.ts b/packages/@n8n/api-types/src/agents/index.ts index 77b31bba4fb..08cabe0d9eb 100644 --- a/packages/@n8n/api-types/src/agents/index.ts +++ b/packages/@n8n/api-types/src/agents/index.ts @@ -7,6 +7,7 @@ export * from './agent-json-config.schema'; export * from './agent-node-tool-operations'; export * from './agent-personalisation'; export * from './agent-skill.schema'; +export * from './skills.schema'; export * from './child-trace'; export type * from './background-job'; export * from './inline-agent-config.schema'; @@ -14,6 +15,7 @@ export * from './sanitize-agent-json-config'; export * from './sanitize-agent-tool-name'; export * from './slack'; export type * from './teams'; +export type * from './whatsapp'; export * from './agent-task.schema'; export * from './dto'; export * from './model-providers'; @@ -24,11 +26,14 @@ export * from './sub-agent.schema'; export * from './types'; export * from './workflow-wait'; export type { + AgentBudgetNotice, + AgentBudgetNoticeCode, AgentSseEvent, AgentSseMessage, ForwardedChildChunkWire, ToolSuspendedPayload, } from '../agent-sse'; +export { isAgentBudgetNoticeCode } from '../agent-sse'; export { AGENT_BUILDER_HIDDEN_AVAILABLE_TOOL_NODE_TYPES } from '../agent-builder-tool-node-types'; // ASK_QUESTIONS_TOOL_NAME / CONFIGURE_CHANNEL_TOOL_NAME come from // ./agent-interaction.schema (re-exported below via `export *`). diff --git a/packages/@n8n/api-types/src/agents/inline-agent-config.schema.ts b/packages/@n8n/api-types/src/agents/inline-agent-config.schema.ts index 2803218a1f2..03fce0cb72b 100644 --- a/packages/@n8n/api-types/src/agents/inline-agent-config.schema.ts +++ b/packages/@n8n/api-types/src/agents/inline-agent-config.schema.ts @@ -56,7 +56,16 @@ export const InlineAgentJsonConfigSchema = AgentJsonConfigBaseSchema.pick({ // don't support — same reason the tool variants above omit // `requireApproval`. mcpServers: AgentJsonConfigBaseSchema.shape.mcpServers.refine( - (servers) => (servers ?? []).every((server) => server.approval === undefined), + (servers) => + (servers ?? []).every((server) => { + const permissions = server.toolPermissions; + return ( + permissions === undefined || + (permissions.categories.read !== 'require_approval' && + permissions.categories.write !== 'require_approval' && + !Object.values(permissions.tools ?? {}).includes('require_approval')) + ); + }), { message: 'MCP tool approval is not available for inline agents' }, ), }) diff --git a/packages/@n8n/api-types/src/agents/model-providers.ts b/packages/@n8n/api-types/src/agents/model-providers.ts index 490fda8fb18..3caf554d022 100644 --- a/packages/@n8n/api-types/src/agents/model-providers.ts +++ b/packages/@n8n/api-types/src/agents/model-providers.ts @@ -70,6 +70,8 @@ export interface AgentCatalogModel { toolCall: boolean; cost?: { input: number; output: number; cacheRead?: number; cacheWrite?: number }; limits?: { context?: number; output?: number }; + /** Pickers list models with a priority first, highest first. Reported by the models API. */ + priority?: number; } /** Response of `GET /agents/v2/catalog/models/:provider`. */ diff --git a/packages/@n8n/api-types/src/agents/skills.schema.ts b/packages/@n8n/api-types/src/agents/skills.schema.ts new file mode 100644 index 00000000000..020b16d4a6b --- /dev/null +++ b/packages/@n8n/api-types/src/agents/skills.schema.ts @@ -0,0 +1,129 @@ +import { z } from 'zod'; + +import { agentSkillSchema, agentSkillShape } from './agent-skill.schema'; +import type { AgentSkill } from './types'; +import { paginationSchema } from '../dto/pagination/pagination.dto'; +import { Z } from '../zod-class'; + +/** + * PostHog flag for the rollout of the skills hub, read for the instance once at startup. + * Off: agents keep their inline skills and the skills routes answer 404. + */ +export const SKILLS_FLAG = '125_context_skills'; + +export const SKILLS_MAX_PAGE_SIZE = 100; + +/** Optional on purpose: without `take` the caller gets every visible skill. */ +const optionalTake = z + .string() + .optional() + .transform((value) => (value === undefined || value === '' ? undefined : Number(value))) + .refine((value) => value === undefined || (Number.isInteger(value) && value > 0), { + message: 'Param `take` must be a positive integer', + }) + .transform((value) => (value === undefined ? undefined : Math.min(value, SKILLS_MAX_PAGE_SIZE))); + +/** Who owns a skill: one project, one agent (only that agent can use it), or the instance. */ +export const skillScopeSchema = z.enum(['project', 'agent', 'instance']); + +export type SkillScope = z.infer; + +export type SkillSource = 'ui' | 'agent'; + +/** One row of the skills list. Name and description come from the latest version. */ +export type SkillListItem = { + id: string; + name: string; + description: string; + scope: SkillScope; + /** The project of a project skill, or the project of the agent of an agent skill. */ + projectId: string | null; + projectName: string | null; + /** Set for an agent skill: the only agent that can use it. */ + agentId: string | null; + agentName: string | null; + source: SkillSource; + /** Number of the latest version, the one following agents run. */ + latestVersion: number; + /** Distinct agents that use the skill: draft refs plus published pins. */ + usedByAgents: number; + canEdit: boolean; + canDelete: boolean; + createdAt: string; + updatedAt: string; +}; + +export type SkillListResponse = { + count: number; + data: SkillListItem[]; +}; + +/** The agents that use a skill, limited to the agents the caller may read. */ +export type SkillUsage = { + /** Agents whose draft references the skill. */ + drafts: Array<{ agentId: string; agentName: string; projectId: string }>; + /** Agents with a published version that pins the skill, one row each. */ + pins: Array<{ + agentId: string; + agentName: string; + projectId: string; + /** The skill version the current published version runs. Null when only older ones pin it. */ + version: number | null; + }>; + /** Agents in projects the caller may not read. */ + hiddenAgents: number; +}; + +/** One skill with the content of its latest version. */ +export type SkillDetail = SkillListItem & { + skill: AgentSkill; + /** Hash of `skill`. Send it back as `baseSkillHash` so a save cannot overwrite a newer version. */ + skillHash: string; + usedBy: SkillUsage; +}; + +export type SkillSaveResponse = { + id: string; + versionId: string; + version: number; + /** False when the content matched the latest version and nothing was saved. */ + created: boolean; + /** The content of the latest version after the save. */ + skill: AgentSkill; + skillHash: string; +}; + +export class ListSkillsQueryDto extends Z.class({ + skip: paginationSchema.skip, + take: optionalTake, + search: z.string().trim().max(200).optional(), + scope: skillScopeSchema.optional(), + projectId: z.string().max(36).optional(), + /** + * The id of an agent: the skills it may attach, which are its project's skills, its own + * agent skills and instance skills. Not combined with `scope` or `projectId`. + */ + attachableTo: z.string().max(36).optional(), +}) {} + +export class CreateSkillDto extends Z.class({ + scope: skillScopeSchema, + /** Required for a project skill, absent otherwise. */ + projectId: z.string().max(36).optional(), + /** Required for an agent skill, absent otherwise. */ + agentId: z.string().max(36).optional(), + /** Hub skills ignore `allowedTools`, so a create that sends it is refused. */ + skill: agentSkillSchema.omit({ allowedTools: true }), +}) {} + +/** + * Saves the next version of a skill. `baseSkillHash` is the `skillHash` the editor + * started from: a save based on an older version is refused with 409. + */ +export class SaveSkillDto extends Z.class({ + name: agentSkillShape.name.optional(), + description: agentSkillShape.description.optional(), + instructions: agentSkillShape.instructions.optional(), + references: agentSkillShape.references.optional(), + baseSkillHash: z.string().min(1), +}) {} diff --git a/packages/@n8n/api-types/src/agents/teams/types.ts b/packages/@n8n/api-types/src/agents/teams/types.ts index 303f34c2f65..799cd0c625f 100644 --- a/packages/@n8n/api-types/src/agents/teams/types.ts +++ b/packages/@n8n/api-types/src/agents/teams/types.ts @@ -40,6 +40,7 @@ export interface TeamsAgentAppManifest { /** Required alongside resource-specific permissions; omitted without them. */ webApplicationInfo?: { id: string; + resource: string; }; /** Present only when a read-all permission is turned on. */ authorization?: { @@ -73,6 +74,25 @@ export interface TeamsAgentSetupState { */ defaultDisplayName: string; defaultDescription: string; + /** + * Whether the connected credential is one the recommended setup made for + * this agent. A channel wired up by hand is left to the manual flow even + * where the recommended one could have run. + */ + provisionedByN8n: boolean; + /** + * Where an administrator approves the app's file access in one step. Only + * for an app the recommended setup made, which registers the return address + * the consent screen needs. + */ + fileAccessConsentUrl: string | null; + /** The Azure Bot the recommended setup made. Null for one made by hand or before n8n kept it. */ + azureBot: { name: string; portalUrl: string } | null; + /** + * The saved channel would build a different app than the one n8n last + * handed over, so Teams holds an older version. False when n8n has no record. + */ + appOutdated: boolean; } /** @@ -86,3 +106,104 @@ export type TeamsCredentialCheck = status: 'failed'; reason: 'certificate' | 'incomplete' | 'rejected' | 'unreachable' | 'cloud'; }; + +/** + * Whether the app may read files attached in channels and group chats. Read + * from a fresh token, so it shows an approval at once, while a running agent + * keeps its older token for up to an hour. `unknown` when Microsoft gave no + * token to read it from. + */ +export interface TeamsFileAccessCheck { + status: 'approved' | 'notApproved' | 'unknown'; +} + +/** + * Sent through Microsoft's admin consent screen and handed back unchanged, so + * the agent page knows to open the Teams settings. + */ +export type TeamsFileAccessConsentState = 'teams-file-access'; + +/** + * One Microsoft sign-in the user can provision with. Several may exist in a + * project, so the setup offers a picker rather than always signing in again. + */ +export interface TeamsManagerCredentialSummary { + id: string; + name: string; + /** False while the credential exists but the OAuth round trip has not finished. */ + connected: boolean; + /** + * True when the stored grant is missing a scope this flow now needs, which + * happens when the scope list grew after the user last signed in. + */ + reconnectRequired: boolean; + /** Tenant the account belongs to, shown so the user can tell two sign-ins apart. */ + organizationName: string | null; + tenantId: string | null; +} + +/** + * Whether the recommended setup can run at all, and what the user can pick. + * + * `managedSetupAvailable` is false on any instance without credential + * overwrites for the manager credential, which is every self-hosted instance + * whose operator has not supplied their own client ID and secret. + */ +export interface TeamsManagedSetupState { + managedSetupAvailable: boolean; + managerCredentials: TeamsManagerCredentialSummary[]; + /** + * One prompt an administrator uses to approve every permission n8n needs, + * across both Microsoft Graph and Azure management. A sign-in cannot ask for + * both, because a code is redeemed for one resource at a time. + */ + adminConsentUrl: string | null; +} + +export interface CreateTeamsManagerCredentialResponse { + id: string; + name: string; + type: 'microsoftTeamsManagerOAuth2Api'; + isResolvable: false; +} + +/** What the Entra app step leaves behind, and what the setup shows for it. */ +export interface TeamsProvisionedAppSummary { + /** The channel credential n8n wrote, ready for the steps that follow. */ + credentialId: string; + appId: string; + appName: string; + organizationName: string | null; + entraAppUrl: string; + fileAccessConsentUrl: string | null; + /** + * When the client secret stops working. n8n created it, so the user cannot + * replace it by hand — the channel settings offer a renew instead. + */ + secretExpiresAt: string; +} + +/** An Azure subscription the signed-in account can create the bot in. */ +export interface TeamsAzureSubscription { + id: string; + name: string; +} + +/** What the bot step created, once n8n did it rather than the Azure portal. */ +export interface TeamsProvisionedBotSummary { + botName: string; + resourceGroup: string; + subscriptionId: string; +} + +/** + * Where the Teams app stands in the organisation's catalogue, read back from + * Microsoft rather than tracked by n8n. + * + * `unknown` covers an app that is not listed yet: published policies take a day + * or two to apply, so an app missing from the listing has not been refused. + */ +export interface TeamsCatalogState { + status: 'published' | 'submitted' | 'rejected' | 'unknown'; + teamsAppId: string | null; +} diff --git a/packages/@n8n/api-types/src/agents/whatsapp/index.ts b/packages/@n8n/api-types/src/agents/whatsapp/index.ts new file mode 100644 index 00000000000..a2dddad7107 --- /dev/null +++ b/packages/@n8n/api-types/src/agents/whatsapp/index.ts @@ -0,0 +1 @@ +export type * from './types'; diff --git a/packages/@n8n/api-types/src/agents/whatsapp/types.ts b/packages/@n8n/api-types/src/agents/whatsapp/types.ts new file mode 100644 index 00000000000..7687a2ef6ff --- /dev/null +++ b/packages/@n8n/api-types/src/agents/whatsapp/types.ts @@ -0,0 +1,35 @@ +/** + * How the WhatsApp number appears to customers, as set in Meta. Every field is + * optional: a business can leave its profile empty, and the setup still works. + */ +export interface WhatsAppBusinessProfile { + /** The display name Meta approved for the number. */ + verifiedName?: string; + /** The number as WhatsApp shows it, e.g. `+1 555-010-0199`. */ + displayPhoneNumber?: string; + description?: string; + /** A short-lived Meta CDN URL. Do not store it. */ + profilePictureUrl?: string; +} + +/** + * Result of checking a WhatsApp credential against Meta before the channel is + * connected. A wrong ID or secret otherwise surfaces only when the first + * message fails. + * + * - `incomplete`: a required field is empty. + * - `temporaryToken`: the access token expires soon, like the one on API Setup. + * - `mismatch`: Meta refuses the token, the IDs, or the app secret. + * - `unreachable`: n8n could not reach Meta. + */ +export type WhatsAppCredentialCheck = + | { status: 'ok'; profile: WhatsAppBusinessProfile } + | { + status: 'failed'; + reason: 'incomplete' | 'temporaryToken' | 'mismatch' | 'unreachable'; + }; + +/** Whether Meta has completed the webhook handshake with this agent. */ +export interface WhatsAppWebhookStatus { + verified: boolean; +} diff --git a/packages/@n8n/api-types/src/chat-hub.ts b/packages/@n8n/api-types/src/chat-hub.ts index c6df723c46f..95f82fcdf01 100644 --- a/packages/@n8n/api-types/src/chat-hub.ts +++ b/packages/@n8n/api-types/src/chat-hub.ts @@ -2,7 +2,10 @@ import type { Scope } from '@n8n/permissions'; import { CHAT_TOOL_NODE_TYPE, type ChunkType, + CODE_NODE_TYPE, + CODE_TOOL_LANGCHAIN_NODE_TYPE, DATA_TABLE_TOOL_NODE_TYPE, + EXECUTE_WORKFLOW_NODE_TYPE, type INode, INodeSchema, WORKFLOW_TOOL_LANGCHAIN_NODE_TYPE, @@ -709,12 +712,46 @@ export interface ChatHubToolDto { /** Tool types blocked for ALL users in the Chat Hub. */ export const ALWAYS_BLOCKED_CHAT_HUB_TOOL_TYPES: string[] = [CHAT_TOOL_NODE_TYPE]; -/** Additional tool types blocked for chat-only users (global:chatUser). */ +/** + * Additional tool types blocked for chat-only users (global:chatUser). + * These tools run code or commands on the n8n instance, or access its files, + * workflows, data tables or agents. Tools that act on a remote system through + * a credential stay allowed: the credential limits what they can do. + * Chat users cannot build workflows, so they cannot add these tools either. + * A `*Tool` or `*HitlTool` variant of a listed node type is blocked too. + * Any node can have a `*HitlTool` variant, so the list also holds node types + * that are not usable as tools. + */ export const CHAT_USER_BLOCKED_CHAT_HUB_TOOL_TYPES: string[] = [ WORKFLOW_TOOL_LANGCHAIN_NODE_TYPE, DATA_TABLE_TOOL_NODE_TYPE, + CODE_NODE_TYPE, + CODE_TOOL_LANGCHAIN_NODE_TYPE, + EXECUTE_WORKFLOW_NODE_TYPE, + 'n8n-nodes-base.executeCommand', + 'n8n-nodes-base.messageAnAgent', + 'n8n-nodes-base.git', + 'n8n-nodes-base.readWriteFile', + 'n8n-nodes-base.n8n', ]; +/** Matches the node type registry, which resolves both suffixes to the base node type. */ +function withoutToolSuffix(type: string): string { + return type.replace(/HitlTool$/, '').replace(/Tool$/, ''); +} + +/** Compares base node types, so an entry also covers the base, `*Tool` and `*HitlTool` forms. */ +function isListed(list: string[], type: string): boolean { + const baseType = withoutToolSuffix(type); + return list.some((entry) => withoutToolSuffix(entry) === baseType); +} + +/** Returns whether a user can add or run a tool of this type in the Chat Hub. */ +export function isChatHubToolTypeAllowed(type: string, user: { isChatUser: boolean }): boolean { + if (isListed(ALWAYS_BLOCKED_CHAT_HUB_TOOL_TYPES, type)) return false; + return !(user.isChatUser && isListed(CHAT_USER_BLOCKED_CHAT_HUB_TOOL_TYPES, type)); +} + /** * Request schema for creating a chat hub tool */ diff --git a/packages/@n8n/api-types/src/consent.ts b/packages/@n8n/api-types/src/consent.ts index fa20ecd4374..906d378183d 100644 --- a/packages/@n8n/api-types/src/consent.ts +++ b/packages/@n8n/api-types/src/consent.ts @@ -1,6 +1 @@ -export interface ConsentUiHints { - /** design-system icon name (updatedIconSet) for the consent logo tile; omit to fall back to the generic mcp icon */ - icon?: string; - /** noun key inserted into first-party consent copy, e.g. 'form' (later 'webhook'); resolved to a localized word on the frontend */ - consentType?: string; -} +export type { ConsentUiHints } from '@n8n/inbound-auth'; diff --git a/packages/@n8n/api-types/src/dto/breaking-changes/__tests__/notify-migration-owners-request.dto.test.ts b/packages/@n8n/api-types/src/dto/breaking-changes/__tests__/notify-migration-owners-request.dto.test.ts new file mode 100644 index 00000000000..c54388c6285 --- /dev/null +++ b/packages/@n8n/api-types/src/dto/breaking-changes/__tests__/notify-migration-owners-request.dto.test.ts @@ -0,0 +1,17 @@ +import { NotifyMigrationOwnersRequestDto } from '../notify-migration-owners-request.dto'; + +describe('NotifyMigrationOwnersRequestDto', () => { + it('should accept a list of workflow ids', () => { + expect( + NotifyMigrationOwnersRequestDto.safeParse({ workflowIds: ['wf-1', 'wf-2'] }).success, + ).toBe(true); + }); + + test.each([ + { name: 'an empty workflow list', request: { workflowIds: [] } }, + { name: 'an empty workflow id', request: { workflowIds: [''] } }, + { name: 'a missing workflow list', request: {} }, + ])('should reject $name', ({ request }) => { + expect(NotifyMigrationOwnersRequestDto.safeParse(request).success).toBe(false); + }); +}); diff --git a/packages/@n8n/api-types/src/dto/breaking-changes/notify-migration-owners-request.dto.ts b/packages/@n8n/api-types/src/dto/breaking-changes/notify-migration-owners-request.dto.ts new file mode 100644 index 00000000000..5c5f5323219 --- /dev/null +++ b/packages/@n8n/api-types/src/dto/breaking-changes/notify-migration-owners-request.dto.ts @@ -0,0 +1,7 @@ +import { z } from 'zod'; + +import { Z } from '../../zod-class'; + +export class NotifyMigrationOwnersRequestDto extends Z.class({ + workflowIds: z.array(z.string().min(1)).min(1), +}) {} diff --git a/packages/@n8n/api-types/src/dto/index.ts b/packages/@n8n/api-types/src/dto/index.ts index 314ca75f2fd..fe4f492fd15 100644 --- a/packages/@n8n/api-types/src/dto/index.ts +++ b/packages/@n8n/api-types/src/dto/index.ts @@ -55,6 +55,7 @@ export { BreakingChangeReportQueryDto } from './breaking-changes/breaking-change export { UpdateMigrationFindingStatusRequestDto } from './breaking-changes/update-migration-finding-status-request.dto'; export { UpdateMigrationFindingStatusesRequestDto } from './breaking-changes/update-migration-finding-statuses-request.dto'; export { AssignMigrationOwnerDto } from './breaking-changes/assign-migration-owner.dto'; +export { NotifyMigrationOwnersRequestDto } from './breaking-changes/notify-migration-owners-request.dto'; export { AuditPublicDto, @@ -243,6 +244,11 @@ export { GetWorkflowQueryDto } from './workflows/get-workflow-query.dto'; export { UpdateWorkflowPublicDto } from './workflows/update-workflow-public.dto'; export { UpdateWorkflowQueryDto } from './workflows/update-workflow-query.dto'; export { ListWorkflowsQueryDto } from './workflows/list-workflows-query.dto'; +export { + ListCallableSubworkflowsQueryDto, + type CallableSubworkflow, + type CallableSubworkflowsResponse, +} from './workflows/list-callable-subworkflows-query.dto'; export { WorkflowPublicDto, CreatedWorkflowPublicDto, @@ -789,3 +795,5 @@ export { } from './promotions/promotion-operations.dto'; export { ScimConfigPatchDto } from './scim'; +export { CreateTrustedSourceDto } from './trusted-source/create-trusted-source.dto'; +export { UpdateTrustedSourceDto } from './trusted-source/update-trusted-source.dto'; diff --git a/packages/@n8n/api-types/src/dto/packages/__tests__/export-package-request.dto.test.ts b/packages/@n8n/api-types/src/dto/packages/__tests__/export-package-request.dto.test.ts index 591f71bb9b9..02b7200bb86 100644 --- a/packages/@n8n/api-types/src/dto/packages/__tests__/export-package-request.dto.test.ts +++ b/packages/@n8n/api-types/src/dto/packages/__tests__/export-package-request.dto.test.ts @@ -198,6 +198,13 @@ describe('ExportPackageRequestDto', () => { }); }); + describe('unknown fields', () => { + it('rejects a key the DTO does not declare', () => { + const result = ExportPackageRequestDto.safeParse({ workflowIds: ['a'], evil: 'x' }); + expect(result.success).toBe(false); + }); + }); + describe('includeArchivedWorkflows', () => { it.each([true, false])('accepts %s', (includeArchivedWorkflows) => { const result = ExportPackageRequestDto.safeParse({ diff --git a/packages/@n8n/api-types/src/dto/packages/__tests__/import-package-request.dto.test.ts b/packages/@n8n/api-types/src/dto/packages/__tests__/import-package-request.dto.test.ts index 0326639265a..9aa074325ae 100644 --- a/packages/@n8n/api-types/src/dto/packages/__tests__/import-package-request.dto.test.ts +++ b/packages/@n8n/api-types/src/dto/packages/__tests__/import-package-request.dto.test.ts @@ -245,6 +245,19 @@ describe('ImportPackageRequestDto', () => { } }); + it('accepts create-with-values credentialMissingMode', () => { + const result = ImportPackageRequestDto.safeParse( + withPackageFile({ + credentialMissingMode: 'create-with-values', + workflowConflictPolicy: 'fail', + }), + ); + expect(result.success).toBe(true); + if (result.success) { + expect(result.data.credentialMissingMode).toBe('create-with-values'); + } + }); + it('parses bindings from a JSON object string keyed by entity type', () => { const result = ImportPackageRequestDto.safeParse( withPackageFile({ diff --git a/packages/@n8n/api-types/src/dto/packages/__tests__/import-result.dto.test.ts b/packages/@n8n/api-types/src/dto/packages/__tests__/import-result.dto.test.ts index 862b8a687c3..02af4323d87 100644 --- a/packages/@n8n/api-types/src/dto/packages/__tests__/import-result.dto.test.ts +++ b/packages/@n8n/api-types/src/dto/packages/__tests__/import-result.dto.test.ts @@ -54,7 +54,7 @@ describe('ImportResultDto', () => { workflows: { 'wf-1': 'wf-1' }, credentials: { 'cred-1': 'cred-1' }, }, - credentials: { matched: ['cred-1'], stubbed: [] }, + credentials: { matched: ['cred-1'], stubbed: [], seeded: [] }, dataTables: { matched: 1, created: 0, updated: 0 }, variables: { matched: [], missing: [], created: [], stubbed: [], updated: [] }, tags: { matched: [], created: [], renamed: [], reconciled: [], skipped: [] }, @@ -91,7 +91,7 @@ describe('ImportResultDto', () => { folders: [], projects: [], bindings: { workflows: {}, credentials: {} }, - credentials: { matched: [], stubbed: [] }, + credentials: { matched: [], stubbed: [], seeded: [] }, dataTables: { matched: 0, created: 0, updated: 0 }, variables: { matched: [], missing: [], created: [], stubbed: [], updated: [] }, tags: { matched: [], created: [], renamed: [], reconciled: [], skipped: [] }, diff --git a/packages/@n8n/api-types/src/dto/packages/export-package-request.dto.ts b/packages/@n8n/api-types/src/dto/packages/export-package-request.dto.ts index 113e4edfee8..08086826b7c 100644 --- a/packages/@n8n/api-types/src/dto/packages/export-package-request.dto.ts +++ b/packages/@n8n/api-types/src/dto/packages/export-package-request.dto.ts @@ -1,25 +1,59 @@ import { z } from 'zod'; +import '../../openapi-extend'; +import { exportPackageRequestFieldDocs } from './export-package-request.openapi'; import { Z } from '../../zod-class'; -export class ExportPackageRequestDto extends Z.class({ - agentIds: z.array(z.string().trim().min(1)).min(1).max(300).optional(), - workflowIds: z.array(z.string().trim().min(1)).min(1).max(300).optional(), - folderIds: z.array(z.string().trim().min(1)).min(1).max(300).optional(), - projectIds: z.array(z.string().trim().min(1)).min(1).max(300).optional(), - includeVariableValues: z.boolean().default(true), - includeTags: z.boolean().default(true), - dependencyPolicy: z - .enum(['fail', 'reference-only', 'include-in-package']) - .optional() - .default('fail'), - versionPolicy: z - .enum(['published-strict', 'prefer-published', 'ignore-unpublished', 'latest']) - .optional() - .default('latest'), - credentialExportPolicy: z - .enum(['expression-values-only', 'no-values']) - .optional() - .default('expression-values-only'), - includeArchivedWorkflows: z.boolean().default(false), -}) {} +export class ExportPackageRequestDto extends Z.class( + { + agentIds: z + .array(z.string().trim().min(1)) + .min(1) + .max(300) + .optional() + .openapi(exportPackageRequestFieldDocs.agentIds), + workflowIds: z + .array(z.string().trim().min(1)) + .min(1) + .max(300) + .optional() + .openapi(exportPackageRequestFieldDocs.workflowIds), + folderIds: z + .array(z.string().trim().min(1)) + .min(1) + .max(300) + .optional() + .openapi(exportPackageRequestFieldDocs.folderIds), + projectIds: z + .array(z.string().trim().min(1)) + .min(1) + .max(300) + .optional() + .openapi(exportPackageRequestFieldDocs.projectIds), + includeVariableValues: z + .boolean() + .default(true) + .openapi(exportPackageRequestFieldDocs.includeVariableValues), + includeTags: z.boolean().default(true).openapi(exportPackageRequestFieldDocs.includeTags), + dependencyPolicy: z + .enum(['fail', 'reference-only', 'include-in-package']) + .optional() + .default('fail') + .openapi(exportPackageRequestFieldDocs.dependencyPolicy), + versionPolicy: z + .enum(['published-strict', 'prefer-published', 'ignore-unpublished', 'latest']) + .optional() + .default('latest') + .openapi(exportPackageRequestFieldDocs.versionPolicy), + credentialExportPolicy: z + .enum(['expression-values-only', 'no-values']) + .optional() + .default('expression-values-only') + .openapi(exportPackageRequestFieldDocs.credentialExportPolicy), + includeArchivedWorkflows: z + .boolean() + .default(false) + .openapi(exportPackageRequestFieldDocs.includeArchivedWorkflows), + }, + { strict: true }, +) {} diff --git a/packages/@n8n/api-types/src/dto/packages/export-package-request.openapi.ts b/packages/@n8n/api-types/src/dto/packages/export-package-request.openapi.ts new file mode 100644 index 00000000000..996b65ea78a --- /dev/null +++ b/packages/@n8n/api-types/src/dto/packages/export-package-request.openapi.ts @@ -0,0 +1,50 @@ +import type { ZodOpenAPIMetadata } from '@asteasolutions/zod-to-openapi'; + +export const exportPackageRequestFieldDocs = { + agentIds: { + description: 'IDs of the agents to include. Requires the agents module.', + example: ['uT9LdQx7rK2MvB4f'], + }, + workflowIds: { + description: 'IDs of the workflows to include in the exported package.', + example: ['2tUt1wbLX592XDdX'], + }, + folderIds: { + description: + 'IDs of the folders to include in the exported package. Each folder is exported with its nested folders.', + example: ['9xKp2mNqRzAbCdEf'], + }, + projectIds: { + description: + 'IDs of the projects to include in the exported package. Includes their agents when the agents module is enabled.', + example: ['Ox8O54VQrmBrb4qL'], + }, + includeVariableValues: { + description: + 'Whether values of variables referenced by the exported entities are bundled into the package. When `false`, variables still travel as name/type files and are listed in the package requirements, but no values travel with the package.', + }, + includeTags: { + description: + 'Whether tags assigned to the exported workflows are bundled into the package. When `false`, no tag files, tag references, or tag requirements travel with the package.', + }, + dependencyPolicy: { + description: + 'Policy for workflow and agent dependencies outside the selected package contents. Includes static workflow references and disabled agent references. `fail` aborts when a required workflow or agent is absent from the package. `include-in-package` adds accessible dependencies recursively. `reference-only` records external requirements without including those definitions. The same policy applies to workflows and agents.', + example: 'fail' as const, + }, + versionPolicy: { + description: + 'Which version of each workflow and agent travels in the package. `latest` exports the current draft. `published-strict` requires a published version. `prefer-published` uses the published version when available and the draft otherwise. `ignore-unpublished` skips unpublished selections. Dependencies that cannot be included cause the export to fail only when `dependencyPolicy` is `fail` or `include-in-package`. With `reference-only`, the export records them as external requirements. The selected version supplies the definition and its references. Workflow names, settings, and tags always use their current values. Agent IDs, names, and MCP availability always use their current values.', + example: 'latest' as const, + }, + credentialExportPolicy: { + description: + 'Whether expression values from credential data are bundled into the package. `expression-values-only` includes credential fields whose value is an n8n expression (for example `={{ $secrets.apiKey }}`); literal values never travel either way. `no-values` keeps credential data out of the package entirely, so each credential file carries only its id, name and type.', + example: 'expression-values-only' as const, + }, + includeArchivedWorkflows: { + description: + 'Whether folder and project exports include their archived workflows. When `false` (default) they are left out. When `true` they travel with `isArchived: true` and are archived on import. Workflows listed in `workflowIds` always export, also when archived.', + example: false, + }, +} satisfies Record; diff --git a/packages/@n8n/api-types/src/dto/packages/import-blocking-issue.openapi.ts b/packages/@n8n/api-types/src/dto/packages/import-blocking-issue.openapi.ts index 7423bef5aaf..f4a4c8655bd 100644 --- a/packages/@n8n/api-types/src/dto/packages/import-blocking-issue.openapi.ts +++ b/packages/@n8n/api-types/src/dto/packages/import-blocking-issue.openapi.ts @@ -78,6 +78,46 @@ export const credentialUnresolvedIssueOpenApi: ZodOpenAPIMetadata = { description: 'A credential reference that could not be resolved in the target project.', }; +export const credentialConflictFieldDocs = { + kind: { + description: + '`differs`: under `credentialConflictPolicy=fail`, the package would change the ' + + 'name or values of the destination credential. `divergent`: under `overwrite`, two or ' + + 'more package credentials with different names or values resolve to one destination ' + + 'credential. The import does not select one of them.', + }, + targetId: { description: 'Id of the destination credential.' }, + sourceIds: { + description: + 'Ids of the package credentials that resolve to the destination credential. For ' + + '`differs`, the package credentials that would change it.', + }, + name: { description: 'Name of the destination credential.' }, + usedBy: { description: 'Package consumers that use the listed package credentials.' }, +} as const satisfies Record; + +export const credentialConflictIssueOpenApi: ZodOpenAPIMetadata = { + description: + 'A matched credential that the credential conflict policy does not let the import ' + + 'change. Only a credential that the import can update is checked: a credential owned by ' + + 'a project of the import. Values are never reported.', +}; + +export const credentialUpdateForbiddenFieldDocs = { + targetId: { description: 'Id of the destination credential.' }, + sourceIds: { description: 'Ids of the package credentials that resolve to it.' }, + name: { description: 'Name of the destination credential.' }, + usedBy: { description: 'Package consumers that use the listed package credentials.' }, +} as const satisfies Record; + +export const credentialUpdateForbiddenIssueOpenApi: ZodOpenAPIMetadata = { + description: + 'A matched credential that the import can update, but the caller has no ' + + '`credential:update` permission on it. Only under `credentialConflictPolicy` `overwrite` ' + + 'or `fail`. The import does not read its values, so this blocks also when the package ' + + 'would not change it. Use `keep-existing` to bind it without a change.', +}; + export const projectConflictFieldDocs = { name: { description: "The project's name as it appears in the package." }, } as const satisfies Record; diff --git a/packages/@n8n/api-types/src/dto/packages/import-blocking-issue.schema.ts b/packages/@n8n/api-types/src/dto/packages/import-blocking-issue.schema.ts index 118bc982723..6bedefa2a39 100644 --- a/packages/@n8n/api-types/src/dto/packages/import-blocking-issue.schema.ts +++ b/packages/@n8n/api-types/src/dto/packages/import-blocking-issue.schema.ts @@ -3,10 +3,14 @@ import '../../openapi-extend'; import { z } from 'zod'; import { + credentialConflictFieldDocs, + credentialConflictIssueOpenApi, credentialPolicyViolationFieldDocs, credentialPolicyViolationIssueOpenApi, credentialUnresolvedFieldDocs, credentialUnresolvedIssueOpenApi, + credentialUpdateForbiddenFieldDocs, + credentialUpdateForbiddenIssueOpenApi, dataTableSchemaOperationOpenApi, dataTableUnresolvedFieldDocs, dataTableUnresolvedIssueOpenApi, @@ -134,6 +138,29 @@ const credentialUnresolvedIssueSchema = z }) .openapi(credentialUnresolvedIssueOpenApi); +const credentialConflictIssueSchema = z + .object({ + type: z.literal('credential-conflict'), + kind: z.enum(['differs', 'divergent']).openapi(credentialConflictFieldDocs.kind), + targetId: z.string().openapi(credentialConflictFieldDocs.targetId), + sourceIds: z.array(z.string()).openapi(credentialConflictFieldDocs.sourceIds), + name: z.string().openapi(credentialConflictFieldDocs.name), + usedBy: z.array(packageRequirementConsumerSchema).openapi(credentialConflictFieldDocs.usedBy), + }) + .openapi(credentialConflictIssueOpenApi); + +const credentialUpdateForbiddenIssueSchema = z + .object({ + type: z.literal('credential-update-forbidden'), + targetId: z.string().openapi(credentialUpdateForbiddenFieldDocs.targetId), + sourceIds: z.array(z.string()).openapi(credentialUpdateForbiddenFieldDocs.sourceIds), + name: z.string().openapi(credentialUpdateForbiddenFieldDocs.name), + usedBy: z + .array(packageRequirementConsumerSchema) + .openapi(credentialUpdateForbiddenFieldDocs.usedBy), + }) + .openapi(credentialUpdateForbiddenIssueOpenApi); + const projectConflictIssueSchema = z .object({ type: z.literal('project-conflict'), @@ -376,6 +403,8 @@ export const importBlockingIssueSchema = z workflowFolderConflictIssueSchema, workflowArchiveForbiddenIssueSchema, credentialUnresolvedIssueSchema, + credentialConflictIssueSchema, + credentialUpdateForbiddenIssueSchema, projectConflictIssueSchema, folderConflictIssueSchema, workflowRemovalForbiddenIssueSchema, diff --git a/packages/@n8n/api-types/src/dto/packages/import-package-request.dto.ts b/packages/@n8n/api-types/src/dto/packages/import-package-request.dto.ts index 050135e3aca..85dbfc1cd04 100644 --- a/packages/@n8n/api-types/src/dto/packages/import-package-request.dto.ts +++ b/packages/@n8n/api-types/src/dto/packages/import-package-request.dto.ts @@ -108,9 +108,10 @@ export class ImportPackageRequestDto extends Z.class( ['id-only', 'name-and-type', 'type-only'], 'id-only', ).openapi(importPackageRequestFieldDocs.credentialMatchingMode), - credentialMissingMode: optionalEnum(['must-preexist', 'create-stub'], 'create-stub').openapi( - importPackageRequestFieldDocs.credentialMissingMode, - ), + credentialMissingMode: optionalEnum( + ['must-preexist', 'create-stub', 'create-with-values'], + 'create-stub', + ).openapi(importPackageRequestFieldDocs.credentialMissingMode), bindings: bindingsSchema.openapi(importPackageRequestFieldDocs.bindings), // Required (unlike every other mode/policy field here), matching the legacy handler, which // required it even though this schema alone would otherwise default it to `new-version`. diff --git a/packages/@n8n/api-types/src/dto/packages/import-package-request.openapi.ts b/packages/@n8n/api-types/src/dto/packages/import-package-request.openapi.ts index d3c2ef59532..d6111c02c29 100644 --- a/packages/@n8n/api-types/src/dto/packages/import-package-request.openapi.ts +++ b/packages/@n8n/api-types/src/dto/packages/import-package-request.openapi.ts @@ -23,6 +23,12 @@ export const importPackageRequestFieldDocs = { description: 'What to do when a credential reference cannot be resolved. `create-stub` (default) ' + 'creates empty credential placeholders in the target project for missing references. ' + + '`create-with-values` also creates them, seeded from the expression data bundled in the ' + + 'package (see the export option `credentialExportPolicy`); a reference the package ' + + 'carries no data for falls back to an empty stub. Seeded credentials are listed under ' + + '`credentials.seeded` and only allow workflow publishing when the package confirms ' + + 'that all source data was retained. Partial or unverified data blocks publishing ' + + 'with `stub-credential`. ' + '`must-preexist` requires every referenced credential to already exist.', }, bindings: { diff --git a/packages/@n8n/api-types/src/dto/packages/import-result.dto.ts b/packages/@n8n/api-types/src/dto/packages/import-result.dto.ts index 18e45f5615c..66e81e60203 100644 --- a/packages/@n8n/api-types/src/dto/packages/import-result.dto.ts +++ b/packages/@n8n/api-types/src/dto/packages/import-result.dto.ts @@ -15,7 +15,7 @@ const workflowPublishingOutcomeSchema = z.object({ state: z.enum(['published', 'unpublished', 'unchanged', 'blocked', 'failed']).openapi({ description: '`blocked` means the imported version could not be published and no version is active ' + - '(for example because the workflow uses a stubbed credential, or uses a node type this ' + + '(for example because the workflow uses an empty or partially seeded credential, or uses a node type this ' + 'instance does not have). When a prior published version remains active, `state` is ' + '`unchanged` with `skippedPublishReason` instead. `failed` means publish or unpublish was ' + 'attempted but did not succeed.', @@ -39,7 +39,7 @@ const workflowPublishingOutcomeSchema = z.object({ description: 'Present when `state` is `unchanged` but the policy wanted to publish the imported ' + 'version: a prior published version is still active (for example after an update with ' + - 'stubbed credentials).', + 'incomplete credentials).', }), }); @@ -144,11 +144,16 @@ const importCredentialSummarySchema = z description: 'Source credential ids for which empty placeholder credentials were created in the target project.', }), + seeded: z.array(z.string()).openapi({ + description: + 'Source credential ids for which credentials were created with bundled expression values ' + + 'in the target project. Partial or unverified bundled data still blocks workflow publishing.', + }), }) .openapi({ description: 'Source credential ids grouped by whether they matched an existing credential or were ' + - 'created as stubs. Full source→target id mapping is in `bindings.credentials`.', + 'created as empty stubs or seeded credentials. Full source→target id mapping is in `bindings.credentials`.', }); const importDataTableSummarySchema = z.object({ diff --git a/packages/@n8n/api-types/src/dto/promotions/promotion-binding-preflight.dto.ts b/packages/@n8n/api-types/src/dto/promotions/promotion-binding-preflight.dto.ts index 5f4d2cddad2..124a40a3dc4 100644 --- a/packages/@n8n/api-types/src/dto/promotions/promotion-binding-preflight.dto.ts +++ b/packages/@n8n/api-types/src/dto/promotions/promotion-binding-preflight.dto.ts @@ -135,7 +135,7 @@ const dataTableChangeSchema = z.discriminatedUnion('kind', [ ]); /** - * Continue can confirm a `destructive-change` conflict. + * Continue can confirm a `destructive-change` or `project-deletion` conflict. * The other conflicts need a package or target correction before creation can proceed. */ export const promotionBindingConflictSchema = z.discriminatedUnion('code', [ @@ -165,6 +165,12 @@ export const promotionBindingConflictSchema = z.discriminatedUnion('code', [ filePath: z.string(), workflows: z.array(workflowSchema), }), + /** A full apply deletes each team project that the package does not hold. */ + z.object({ + kind: z.literal('project'), + code: z.literal('project-deletion'), + project: promotionBindingProjectSchema, + }), z.object({ kind: z.literal('data-table'), code: z.literal('destructive-change'), diff --git a/packages/@n8n/api-types/src/dto/promotions/promotion-operations.dto.ts b/packages/@n8n/api-types/src/dto/promotions/promotion-operations.dto.ts index b37d629d7f0..d31322a6470 100644 --- a/packages/@n8n/api-types/src/dto/promotions/promotion-operations.dto.ts +++ b/packages/@n8n/api-types/src/dto/promotions/promotion-operations.dto.ts @@ -107,8 +107,11 @@ const confirmDestructiveChangesSchema = z description: 'Also applies destructive data table changes, which a `destructive-change` conflict reports: ' + 'removed or retyped columns. The values in those columns are removed. ' + - 'Rows and other columns are kept. The confirmation covers every such change when Continue runs, ' + - 'including changes that are not in the reviewed result.', + 'Rows and other columns are kept. ' + + 'On a full apply, also deletes the team projects that a `project-deletion` conflict reports, ' + + 'with everything in them. ' + + 'The confirmation covers every such change and deletion when Continue runs, ' + + 'including those that are not in the reviewed result.', }); /** Continue must name the source that the paused Apply reported. */ diff --git a/packages/@n8n/api-types/src/dto/trusted-source/__tests__/create-trusted-source.dto.test.ts b/packages/@n8n/api-types/src/dto/trusted-source/__tests__/create-trusted-source.dto.test.ts new file mode 100644 index 00000000000..0d8d385ce6e --- /dev/null +++ b/packages/@n8n/api-types/src/dto/trusted-source/__tests__/create-trusted-source.dto.test.ts @@ -0,0 +1,72 @@ +import { CreateTrustedSourceDto } from '../create-trusted-source.dto'; + +const config = { + version: 1, + authentication: { type: 'oauth2' }, + surfaces: { 'public-api': {} }, +}; + +const request = (overrides: Record = {}) => ({ + name: 'Acme', + issuer: 'https://acme.example.com', + config, + ...overrides, +}); + +describe('CreateTrustedSourceDto', () => { + test('parses a minimal request and fills the config defaults', () => { + const result = CreateTrustedSourceDto.safeParse(request()); + + expect(result.success).toBe(true); + expect(result.data?.config.identity.subject).toBe('binding'); + }); + + test('keeps the path of an issue raised by the config schema', () => { + const result = CreateTrustedSourceDto.safeParse( + request({ config: { ...config, identity: { subject: 'n8n-user-id' } } }), + ); + + expect(result.success).toBe(false); + expect(result.error?.issues[0]).toMatchObject({ path: ['config', 'identity', 'subject'] }); + }); + + test.each([ + { name: 'at the top level', config: { ...config, typo: true }, path: ['config'] }, + { + name: 'named like a prototype member', + config: { ...config, constructor: true }, + path: ['config'], + key: 'constructor', + }, + { + name: 'in a nested block', + config: { ...config, identity: { typo: true } }, + path: ['config', 'identity'], + }, + { + name: 'in an array item', + config: { + ...config, + identity: { + roleMapping: { + mode: 'continuous', + fallbackInstanceRole: 'global:member', + instanceRoleRules: [ + { id: 'r1', expression: 'true', role: 'global:admin', enabled: true, typo: true }, + ], + }, + }, + }, + path: ['config', 'identity', 'roleMapping', 'instanceRoleRules', 0], + }, + ])('refuses an unknown config key $name', ({ config, path, key = 'typo' }) => { + const result = CreateTrustedSourceDto.safeParse(request({ config })); + + expect(result.success).toBe(false); + expect(result.error?.issues[0]).toMatchObject({ + code: 'unrecognized_keys', + keys: [key], + path, + }); + }); +}); diff --git a/packages/@n8n/api-types/src/dto/trusted-source/create-trusted-source.dto.ts b/packages/@n8n/api-types/src/dto/trusted-source/create-trusted-source.dto.ts new file mode 100644 index 00000000000..8a39eaa5842 --- /dev/null +++ b/packages/@n8n/api-types/src/dto/trusted-source/create-trusted-source.dto.ts @@ -0,0 +1,63 @@ +import { HttpsUrl, trustedSourceConfigSchemaFor } from '@n8n/inbound-auth'; +import { z } from 'zod'; + +import { Z } from '../../zod-class'; + +export const trustedSourceNameSchema = z.string().trim().min(1).max(128); +// Discovery fetches the issuer's metadata and refuses http, so the DTO refuses it up front. +export const trustedSourceIssuerSchema = HttpsUrl; +// Admin rows only: the system row has no write route. +const adminConfigSchema = trustedSourceConfigSchemaFor('admin'); + +function isRecord(value: unknown): value is Record { + return typeof value === 'object' && value !== null && !Array.isArray(value); +} + +/** The first input key that parsing dropped, as its parent path plus the key. */ +function droppedKey( + input: unknown, + parsed: unknown, + path: Array = [], +): { path: Array; key: string } | undefined { + if (Array.isArray(input) && Array.isArray(parsed)) { + for (const [index, item] of input.entries()) { + const hit = droppedKey(item, parsed[index], [...path, index]); + if (hit) return hit; + } + return undefined; + } + if (!isRecord(input) || !isRecord(parsed)) return undefined; + for (const key of Object.keys(input)) { + if (!Object.hasOwn(parsed, key)) return { path, key }; + const hit = droppedKey(input[key], parsed[key], [...path, key]); + if (hit) return hit; + } + return undefined; +} + +// The shared schema strips unknown keys so an older process tolerates a newer document. The write +// path refuses them instead, so a misspelled setting cannot pass as its default. +export const adminTrustedSourceConfigSchema = z.unknown().transform((input, ctx) => { + const result = adminConfigSchema.safeParse(input); + if (!result.success) { + for (const issue of result.error.issues) ctx.addIssue(issue); + return z.NEVER; + } + const dropped = droppedKey(input, result.data); + if (dropped) { + ctx.addIssue({ + code: z.ZodIssueCode.unrecognized_keys, + keys: [dropped.key], + path: dropped.path, + message: `Unrecognized key in object: '${dropped.key}'`, + }); + return z.NEVER; + } + return result.data; +}); + +export class CreateTrustedSourceDto extends Z.class({ + name: trustedSourceNameSchema, + issuer: trustedSourceIssuerSchema, + config: adminTrustedSourceConfigSchema, +}) {} diff --git a/packages/@n8n/api-types/src/dto/trusted-source/update-trusted-source.dto.ts b/packages/@n8n/api-types/src/dto/trusted-source/update-trusted-source.dto.ts new file mode 100644 index 00000000000..db0b95d5778 --- /dev/null +++ b/packages/@n8n/api-types/src/dto/trusted-source/update-trusted-source.dto.ts @@ -0,0 +1,16 @@ +import { z } from 'zod'; + +import { + adminTrustedSourceConfigSchema, + trustedSourceIssuerSchema, + trustedSourceNameSchema, +} from './create-trusted-source.dto'; +import { Z } from '../../zod-class'; + +export class UpdateTrustedSourceDto extends Z.class({ + name: trustedSourceNameSchema.optional(), + issuer: trustedSourceIssuerSchema.optional(), + config: adminTrustedSourceConfigSchema.optional(), + /** Drops every (subject, user) binding of the source. Set it when the issuer moves to another IdP. */ + clearBindings: z.boolean().optional(), +}) {} diff --git a/packages/@n8n/api-types/src/dto/type-availability-policies/__tests__/replace-attachments.dto.test.ts b/packages/@n8n/api-types/src/dto/type-availability-policies/__tests__/replace-attachments.dto.test.ts index c0fff01be2c..a4357c1aa4f 100644 --- a/packages/@n8n/api-types/src/dto/type-availability-policies/__tests__/replace-attachments.dto.test.ts +++ b/packages/@n8n/api-types/src/dto/type-availability-policies/__tests__/replace-attachments.dto.test.ts @@ -2,12 +2,21 @@ import { ReplaceAttachmentsDto } from '../replace-attachments.dto'; describe('ReplaceAttachmentsDto', () => { it('accepts an empty attachment list', () => { - expect(ReplaceAttachmentsDto.safeParse({ attachments: [] }).success).toBe(true); + expect(ReplaceAttachmentsDto.safeParse({ attachments: [], version: 0 }).success).toBe(true); + }); + + it('rejects a missing version', () => { + expect(ReplaceAttachmentsDto.safeParse({ attachments: [] }).success).toBe(false); + }); + + it.each([-1, 0.5])('rejects version %s', (version) => { + expect(ReplaceAttachmentsDto.safeParse({ attachments: [], version }).success).toBe(false); }); it('accepts a list of attachments with unique policyIds and (isFloor, priority) pairs', () => { expect( ReplaceAttachmentsDto.safeParse({ + version: 1, attachments: [ { policyId: 'p1', priority: 0, isFloor: false }, { policyId: 'p2', priority: 0, isFloor: true }, @@ -19,6 +28,7 @@ describe('ReplaceAttachmentsDto', () => { it('rejects duplicate policyId values', () => { const result = ReplaceAttachmentsDto.safeParse({ + version: 1, attachments: [ { policyId: 'p1', priority: 0, isFloor: false }, { policyId: 'p1', priority: 1, isFloor: false }, @@ -33,6 +43,7 @@ describe('ReplaceAttachmentsDto', () => { it('rejects duplicate (isFloor, priority) pairs across different policies', () => { const result = ReplaceAttachmentsDto.safeParse({ + version: 1, attachments: [ { policyId: 'p1', priority: 0, isFloor: false }, { policyId: 'p2', priority: 0, isFloor: false }, @@ -48,7 +59,7 @@ describe('ReplaceAttachmentsDto', () => { }); it('can be constructed directly from an already-valid payload', () => { - const dto = new ReplaceAttachmentsDto({ attachments: [] }); + const dto = new ReplaceAttachmentsDto({ attachments: [], version: 0 }); expect(dto.attachments).toEqual([]); }); @@ -56,6 +67,7 @@ describe('ReplaceAttachmentsDto', () => { it('throws when parsing an invalid payload', () => { expect(() => ReplaceAttachmentsDto.parse({ + version: 1, attachments: [ { policyId: 'p1', priority: 0, isFloor: false }, { policyId: 'p1', priority: 1, isFloor: false }, diff --git a/packages/@n8n/api-types/src/dto/type-availability-policies/replace-attachments.dto.ts b/packages/@n8n/api-types/src/dto/type-availability-policies/replace-attachments.dto.ts index 47642331a36..4f6c2642c6e 100644 --- a/packages/@n8n/api-types/src/dto/type-availability-policies/replace-attachments.dto.ts +++ b/packages/@n8n/api-types/src/dto/type-availability-policies/replace-attachments.dto.ts @@ -2,6 +2,8 @@ import { z } from 'zod'; import { Z } from '../../zod-class'; +const versionSchema = z.number().int().nonnegative(); + const policyAttachmentInputSchema = z.object({ policyId: z.string().min(1), priority: z.number().int(), @@ -10,6 +12,7 @@ const policyAttachmentInputSchema = z.object({ const replaceAttachmentsShape = { attachments: z.array(policyAttachmentInputSchema), + version: versionSchema, }; /** diff --git a/packages/@n8n/api-types/src/dto/workflows/__tests__/create-workflow.dto.test.ts b/packages/@n8n/api-types/src/dto/workflows/__tests__/create-workflow.dto.test.ts index 38d63ebbbd0..d8223b0bf7c 100644 --- a/packages/@n8n/api-types/src/dto/workflows/__tests__/create-workflow.dto.test.ts +++ b/packages/@n8n/api-types/src/dto/workflows/__tests__/create-workflow.dto.test.ts @@ -212,6 +212,11 @@ describe('CreateWorkflowDto', () => { request: { name: 'a'.repeat(129), nodes: [], connections: {} }, expectedErrorPath: ['name'], }, + ...['__proto__', 'constructor', 'prototype'].map((id) => ({ + name: `reserved id ${id}`, + request: { id, name: 'My Workflow', nodes: [], connections: {} }, + expectedErrorPath: ['id'], + })), { name: 'missing nodes', request: { name: 'Test', connections: {} }, diff --git a/packages/@n8n/api-types/src/dto/workflows/create-workflow.dto.ts b/packages/@n8n/api-types/src/dto/workflows/create-workflow.dto.ts index 13b7eb6b61f..3f03be46a27 100644 --- a/packages/@n8n/api-types/src/dto/workflows/create-workflow.dto.ts +++ b/packages/@n8n/api-types/src/dto/workflows/create-workflow.dto.ts @@ -1,9 +1,13 @@ import { z } from 'zod'; import { baseWorkflowShape } from './base-workflow.dto'; +import { isSafeObjectKey } from '../../schemas/instance-ai.schema'; import { Z } from '../../zod-class'; -export const workflowIdSchema = z.string(); +// Workflow ids are used as object keys, so `__proto__`, `constructor` and `prototype` are not allowed +export const workflowIdSchema = z + .string() + .refine(isSafeObjectKey, { message: 'Invalid workflow id' }); export class CreateWorkflowDto extends Z.class({ // Spread base fields (name, nodes, connections, settings, etc.) diff --git a/packages/@n8n/api-types/src/dto/workflows/list-callable-subworkflows-query.dto.ts b/packages/@n8n/api-types/src/dto/workflows/list-callable-subworkflows-query.dto.ts new file mode 100644 index 00000000000..f8eefaa0bd7 --- /dev/null +++ b/packages/@n8n/api-types/src/dto/workflows/list-callable-subworkflows-query.dto.ts @@ -0,0 +1,28 @@ +import { z } from 'zod'; + +import { Z } from '../../zod-class'; +import { paginationSchema } from '../pagination/pagination.dto'; + +/** + * Query for the list of workflows that a parent workflow can call as + * sub-workflows. Only name search and pagination are accepted, so callers + * cannot probe workflow contents. + */ +export class ListCallableSubworkflowsQueryDto extends Z.class({ + ...paginationSchema, + query: z.string().trim().max(256).optional(), +}) {} + +export type CallableSubworkflow = { + id: string; + name: string; + active: boolean; + isArchived: boolean; + /** Set only when the workflow belongs to a team project. */ + projectName?: string; +}; + +export type CallableSubworkflowsResponse = { + count: number; + data: CallableSubworkflow[]; +}; diff --git a/packages/@n8n/api-types/src/frontend-settings.ts b/packages/@n8n/api-types/src/frontend-settings.ts index 263275ac81e..ba3a06b750c 100644 --- a/packages/@n8n/api-types/src/frontend-settings.ts +++ b/packages/@n8n/api-types/src/frontend-settings.ts @@ -405,8 +405,6 @@ export type FrontendModuleSettings = { sandboxUnavailableReason: string | null; /** When true, orchestrator LLM step / workflow code debug is captured (`N8N_INSTANCE_AI_RUN_DEBUG_ENABLED`). */ runDebugEnabled: boolean; - /** Whether this instance is in the activation-capped trial cohort (`N8N_INSTANCE_AI_ACTIVATION_CAPPED`). Optional. */ - activationCapped?: boolean; }; /** @@ -455,6 +453,8 @@ export type FrontendModuleSettings = { knowledgeBaseEnabled: boolean; /** Whether the AI Assistant proxy is available to the agents module. */ proxyEnabled: boolean; + /** Whether agents use the skills hub (PostHog flag `125_context_skills`, read at startup). */ + skillsHubEnabled?: boolean; }; }; diff --git a/packages/@n8n/api-types/src/index.ts b/packages/@n8n/api-types/src/index.ts index ae96d3f0dfd..c30c3a6e3aa 100644 --- a/packages/@n8n/api-types/src/index.ts +++ b/packages/@n8n/api-types/src/index.ts @@ -96,6 +96,7 @@ export { ChatHubUpdateToolRequest, ALWAYS_BLOCKED_CHAT_HUB_TOOL_TYPES, CHAT_USER_BLOCKED_CHAT_HUB_TOOL_TYPES, + isChatHubToolTypeAllowed, chatHubVectorStoreProviderSchema, type ChatHubVectorStoreProvider, VECTOR_STORE_PROVIDER_CREDENTIAL_TYPE_MAP, @@ -343,6 +344,9 @@ export type { BreakingChangeVersion, MigrationFindingStatus, MigrationFindingTriageStatus, + MigrationFindingListedStatus, + MigrationNotifyResult, + MigrationNotifySkipReason, WorkflowMigrationResult, } from './schemas/breaking-changes.schema'; @@ -352,6 +356,8 @@ export { breakingChangeVersionSchema, migrationFindingStatusSchema, migrationFindingTriageStatusSchema, + migrationFindingListedStatusSchema, + migrationNotifySkipReasonSchema, migrationOwnerSourceSchema, } from './schemas/breaking-changes.schema'; @@ -497,6 +503,7 @@ export { InstanceAiEvalExecutionRequest, InstanceAiEvalAgentExecutionRequest, InstanceAiEvalCredentialAllowlistRequest, + InstanceAiEvalCredentialTestTargetRequest, INSTANCE_AI_MEMORY_TASK_WAIT_TIMEOUT_MS, AI_GATEWAY_MANAGED_TAG, InstanceAiEvalRestoreThreadRequest, @@ -735,11 +742,17 @@ export { } from './schemas/instance-ai-setup-credential-selection'; export type { + McpRegistryDiscoveredConnection, + McpRegistryDiscoveredTool, + McpRegistryDiscoveryFailureReason, + McpRegistryDiscoveryRequest, + McpRegistryDiscoveryResponse, McpRegistryServerStatus, McpRegistryServerIconResponse, McpRegistryServerToolResponse, McpRegistryServerResponse, } from './schemas/mcp-registry.schema'; +export { mcpRegistryDiscoveryRequestSchema } from './schemas/mcp-registry.schema'; export { createInitialState, @@ -749,6 +762,7 @@ export { stateFromAgentTree, normalizeLegacyReasoningTimeline, normalizeAgentTree, + orchestratorAgentId, } from './schemas/agent-run-reducer'; export type { AgentRunState } from './schemas/agent-run-reducer'; @@ -966,3 +980,4 @@ export { compareExecutionListItems } from './dto/executions/compare-execution-li export type * from './workflow-suggestions'; export * from './self-healing-results'; +export * from './model-priority'; diff --git a/packages/@n8n/api-types/src/model-priority.ts b/packages/@n8n/api-types/src/model-priority.ts new file mode 100644 index 00000000000..7114c93496b --- /dev/null +++ b/packages/@n8n/api-types/src/model-priority.ts @@ -0,0 +1,23 @@ +/** + * Moves models that have a priority to the front, highest first, and keeps the + * order of the rest. A models API reports a priority to promote a model, for + * example at its launch. + */ +export function pinPrioritizedModels(models: T[], getPriority: (model: T) => unknown): T[] { + const entries = models.map((model) => { + const priority = getPriority(model); + return { + model, + priority: typeof priority === 'number' && Number.isFinite(priority) ? priority : null, + }; + }); + const prioritized = entries + .flatMap((entry) => + entry.priority === null ? [] : [{ model: entry.model, priority: entry.priority }], + ) + .sort((a, b) => b.priority - a.priority); + return [ + ...prioritized.map((entry) => entry.model), + ...entries.filter((entry) => entry.priority === null).map((entry) => entry.model), + ]; +} diff --git a/packages/@n8n/api-types/src/schemas/__tests__/agent-run-reducer.test.ts b/packages/@n8n/api-types/src/schemas/__tests__/agent-run-reducer.test.ts index cd000f3af2c..0e2eed00ce1 100644 --- a/packages/@n8n/api-types/src/schemas/__tests__/agent-run-reducer.test.ts +++ b/packages/@n8n/api-types/src/schemas/__tests__/agent-run-reducer.test.ts @@ -542,6 +542,70 @@ describe('agent-run-reducer', () => { expectStateMapsNotPolluted(state); }); + it('routes a follow-up run to the tree after the state is rebuilt from a snapshot', () => { + // A two-run group, as a run-sync frame or history hydration delivers it. + const original = stateWithRun('run-1', 'orchestrator-run-1'); + reduceEvent(original, makeToolCall('run-1', 'orchestrator-run-1', 'tc-plan', 'create-tasks')); + reduceEvent(original, makeRunStart('run-2', 'orchestrator-run-2')); + reduceEvent(original, makeToolCall('run-2', 'orchestrator-run-2', 'tc-folder', 'workspace')); + const state = stateFromAgentTree(deepCopy(toAgentTree(original)))!; + + // The snapshot holds no alias for run-2, and its run-start is not replayed. + expect(findAgent(state, 'orchestrator-run-2')).toBeUndefined(); + + reduceEvent( + state, + makeToolResult('run-2', 'orchestrator-run-2', 'tc-folder', { id: 'folder-1' }), + ); + reduceEvent(state, makeToolCall('run-2', 'orchestrator-run-2', 'tc-move', 'workspace')); + reduceEvent(state, makeConfirmationRequest('run-2', 'orchestrator-run-2', 'tc-move')); + + const moveTc = state.toolCallsById['tc-move']; + expect(moveTc?.isLoading).toBe(true); + expect(moveTc?.confirmation?.requestId).toBe('req-1'); + const root = toAgentTree(state); + expect(root.agentId).toBe('orchestrator-run-1'); + expect(root.timeline.at(-1)).toEqual( + expect.objectContaining({ type: 'tool-call', toolCallId: 'tc-move' }), + ); + expectStateMapsNotPolluted(state); + }); + + it('attaches a sub-agent spawned by a follow-up run after a snapshot rebuild', () => { + const original = stateWithRun('run-1', 'orchestrator-run-1'); + reduceEvent(original, makeToolCall('run-1', 'orchestrator-run-1', 'tc-plan', 'create-tasks')); + const state = stateFromAgentTree(deepCopy(toAgentTree(original)))!; + + reduceEvent( + state, + makeAgentSpawned('run-2', 'builder-1', 'orchestrator-run-2', 'workflow-builder'), + ); + + expect(toAgentTree(state).children.map((child) => child.agentId)).toEqual(['builder-1']); + }); + + it('does not alias an agent whose id is not the orchestrator id of its run', () => { + const original = stateWithRun('run-1', 'orchestrator-run-1'); + reduceEvent(original, makeToolCall('run-1', 'orchestrator-run-1', 'tc-plan', 'create-tasks')); + const state = stateFromAgentTree(deepCopy(toAgentTree(original)))!; + + reduceEvent(state, makeToolCall('run-2', 'orchestrator-run-3', 'tc-stray', 'workspace')); + reduceEvent(state, makeToolCall('run-2', 'unknown-agent', 'tc-unknown', 'workspace')); + + expect(state.toolCallsById['tc-stray']).toBeUndefined(); + expect(state.toolCallsById['tc-unknown']).toBeUndefined(); + }); + + it('does not alias into a fresh state before its run-start', () => { + const state = createInitialState(); + + reduceEvent(state, makeToolCall('run-1', 'orchestrator-run-1', 'tc-early', 'workspace')); + reduceEvent(state, makeRunStart('run-1', 'orchestrator-run-1')); + + expect(state.rootAgentId).toBe('orchestrator-run-1'); + expect(state.toolCallsById['tc-early']).toBeUndefined(); + }); + it('run-start with unsafe agentId is ignored', () => { const state = createInitialState(); diff --git a/packages/@n8n/api-types/src/schemas/agent-run-reducer.ts b/packages/@n8n/api-types/src/schemas/agent-run-reducer.ts index 7d506bda066..bba00a8526d 100644 --- a/packages/@n8n/api-types/src/schemas/agent-run-reducer.ts +++ b/packages/@n8n/api-types/src/schemas/agent-run-reducer.ts @@ -110,6 +110,31 @@ function ensureAgent(state: AgentRunState, agentId: string): InstanceAiAgentNode return state.agentsById[agentId]; } +/** + * Per-run orchestrator agent id. A follow-up run merged into an existing + * message group streams under this id, not under the group's root agent id. + */ +export function orchestratorAgentId(runId: string): string { + return `orchestrator-${runId}`; +} + +/** + * Alias a follow-up run's orchestrator to the group's root agent. + * + * `run-start` creates this alias, but a state rebuilt from a snapshot tree + * (a `run-sync` frame or history hydration) only indexes the tree's own + * nodes. Without the alias, every later event of that run is dropped as an + * orphan, including the tool call that a confirmation attaches to. + */ +function aliasRunOrchestrator(state: AgentRunState, agentId: string, runId: string): void { + if (!isSafeObjectKey(agentId) || state.agentsById[agentId]) return; + if (agentId !== orchestratorAgentId(runId)) return; + const root = state.agentsById[state.rootAgentId]; + // Same test as a follow-up `run-start`: a fresh state has no group to join. + if (!root || (Object.keys(state.agentsById).length <= 1 && !nodeHasContent(root))) return; + state.agentsById[agentId] = root; +} + /** When the event was published — falls back to "now" for live events and * old persisted events that predate the `ts` envelope field. Replays must * use the publish time or tool durations collapse to processing time. */ @@ -201,6 +226,13 @@ function nodeHasContent(node: InstanceAiAgentNode | undefined): boolean { * as the existing frontend reducer). Returns the same state reference. */ export function reduceEvent(state: AgentRunState, event: InstanceAiEvent): AgentRunState { + if (event.type !== 'run-start') { + aliasRunOrchestrator(state, event.agentId, event.runId); + if (event.type === 'agent-spawned') { + aliasRunOrchestrator(state, event.payload.parentId, event.runId); + } + } + switch (event.type) { case 'run-start': { const rootId = event.agentId; diff --git a/packages/@n8n/api-types/src/schemas/breaking-changes.schema.ts b/packages/@n8n/api-types/src/schemas/breaking-changes.schema.ts index a39ee63d73e..fadfd337b6c 100644 --- a/packages/@n8n/api-types/src/schemas/breaking-changes.schema.ts +++ b/packages/@n8n/api-types/src/schemas/breaking-changes.schema.ts @@ -48,6 +48,17 @@ export const migrationFindingTriageStatusSchema = migrationFindingStatusSchema.e ]); export type MigrationFindingTriageStatus = z.infer; +/** + * The statuses the rule detail lists. A `notified` finding is still unresolved: + * only the notification sets it apart from `open`. + */ +export const migrationFindingListedStatusSchema = migrationFindingStatusSchema.extract([ + 'open', + 'notified', + 'wont_fix', +]); +export type MigrationFindingListedStatus = z.infer; + /** * The target n8n major version for the migration/breaking-changes report. * @@ -136,7 +147,9 @@ export type BreakingChangeWorkflowRuleResult = z.infer; @@ -163,7 +176,7 @@ const breakingChangeLightReportDataSchema = { instanceResults: z.array(instanceRuleResultsSchema), workflowResults: z.array( workflowRuleResultsSchema.omit({ affectedWorkflows: true }).extend({ - // Workflows with an open finding for the rule. + // Workflows with an open or notified finding for the rule. nbAffectedWorkflows: z.number(), // Workflows with a won't fix finding for the rule. nbWontFixWorkflows: z.number(), @@ -209,3 +222,16 @@ const workflowMigrationResultSchema = z.object({ republishable: z.boolean(), }); export type WorkflowMigrationResult = z.infer; + +/** + * Why a workflow was left out of a notification: it has no owner with an email, + * its finding is no longer open, or the email could not be sent. + */ +export const migrationNotifySkipReasonSchema = z.enum(['no_owner', 'no_finding', 'send_failed']); +export type MigrationNotifySkipReason = z.infer; + +/** The outcome of notifying the owners of the findings of one rule. */ +export type MigrationNotifyResult = { + notifiedWorkflowIds: string[]; + skipped: Array<{ workflowId: string; reason: MigrationNotifySkipReason }>; +}; diff --git a/packages/@n8n/api-types/src/schemas/instance-ai.schema.ts b/packages/@n8n/api-types/src/schemas/instance-ai.schema.ts index 221b56482ba..dd6a6ed2047 100644 --- a/packages/@n8n/api-types/src/schemas/instance-ai.schema.ts +++ b/packages/@n8n/api-types/src/schemas/instance-ai.schema.ts @@ -27,14 +27,11 @@ export const UNLIMITED_CREDITS = -1; * The instance's n8n Assistant credit standing, as reported by `GET /instance-ai/credits`, by the * `updateInstanceAiCredits` push and by the internal callers that pass it around. * - * `creditsQuota` is {@link UNLIMITED_CREDITS} when credits are not metered — either the proxy is - * disabled, or the amounts are deliberately withheld from a cohort that must not see a balance. + * `creditsQuota` is {@link UNLIMITED_CREDITS} when the AI service proxy is disabled. */ export type InstanceAiCredits = { creditsQuota: number; creditsClaimed: number; - /** Whether the pool has been locked by the activation cap. */ - quotaLocked?: boolean; }; /** @@ -3042,6 +3039,18 @@ export class InstanceAiEvalCredentialAllowlistRequest extends Z.class({ bypassCredentialTest: z.array(z.string().min(1)).max(50).optional(), }) {} +/** + * Aims the thread's connection tests for one credential type at a provider + * stand-in, so the eval checks the captured secret without the real provider. + */ +export class InstanceAiEvalCredentialTestTargetRequest extends Z.class({ + threadId: z.string().uuid(), + credentialType: z.string().min(1), + baseUrl: z.string().url(), + /** Credential field the stand-in URL is written into. */ + urlField: z.string().min(1), +}) {} + /** The id an authored seed gives a data table, agent or folder. ≥8 chars: the * restore remaps ids by whole-document string replace, and a short id would risk * corrupting unrelated substrings — so the restore path refuses shorter ids. diff --git a/packages/@n8n/api-types/src/schemas/mcp-registry.schema.ts b/packages/@n8n/api-types/src/schemas/mcp-registry.schema.ts index ddf786136aa..6bd4dc8c04f 100644 --- a/packages/@n8n/api-types/src/schemas/mcp-registry.schema.ts +++ b/packages/@n8n/api-types/src/schemas/mcp-registry.schema.ts @@ -5,6 +5,7 @@ * to surface to authenticated users. Internal fields like `remotes` (transport * endpoint URLs) and `origin` are intentionally omitted. */ +import { z } from 'zod'; export type McpRegistryServerStatus = 'active' | 'deprecated'; @@ -27,6 +28,7 @@ export interface McpRegistryCredentialOption { export interface McpRegistryServerResponse { slug: string; + nodeTypeName: string; name: string; title: string; description: string; @@ -37,7 +39,45 @@ export interface McpRegistryServerResponse { websiteUrl?: string; credentials: McpRegistryCredentialOption[]; tools: McpRegistryServerToolResponse[]; + isTemplated: boolean; isOfficial: boolean; status: McpRegistryServerStatus; tags?: string[]; } + +export const mcpRegistryDiscoveryRequestSchema = z + .object({ + slug: z.string().trim().min(1), + credentialId: z.string().trim().min(1), + }) + .strict(); + +export type McpRegistryDiscoveryRequest = z.infer; + +export type McpRegistryDiscoveredTool = { + name: string; + description?: string; + category: 'read' | 'write'; +}; + +export type McpRegistryDiscoveredConnection = { + url: string; + transport: 'sse' | 'streamableHttp'; + authentication: string; + credentialId?: string; + metadata?: { nodeTypeName: string }; +}; + +export type McpRegistryDiscoveryFailureReason = 'authentication' | 'server_unavailable' | 'unknown'; + +export type McpRegistryDiscoveryResponse = + | { + status: 'connected'; + connection: McpRegistryDiscoveredConnection; + tools: McpRegistryDiscoveredTool[]; + } + | { + status: 'disconnected'; + failureReason: McpRegistryDiscoveryFailureReason; + tools: []; + }; diff --git a/packages/@n8n/api-types/src/schemas/policy-violation.schema.ts b/packages/@n8n/api-types/src/schemas/policy-violation.schema.ts index c53a94413a1..2ffaeea7cd9 100644 --- a/packages/@n8n/api-types/src/schemas/policy-violation.schema.ts +++ b/packages/@n8n/api-types/src/schemas/policy-violation.schema.ts @@ -29,6 +29,15 @@ export const policyViolationSchema = z.object({ /** The rule that decided, if a rule did rather than a fallback default. */ matchedRuleId: z.string().optional(), + + /** + * The project whose policy was evaluated, also when `scope` is `'instance'`. For a + * sub-workflow this is the sub-workflow's project, not the caller's. + */ + projectId: z.string().optional(), + + /** The project can lift this block with its own allow rule. Absent means it cannot. */ + optInAvailable: z.boolean().optional(), }); export type PolicyViolation = z.infer; diff --git a/packages/@n8n/api-types/tsconfig.json b/packages/@n8n/api-types/tsconfig.json index f693c746bb6..57b21005add 100644 --- a/packages/@n8n/api-types/tsconfig.json +++ b/packages/@n8n/api-types/tsconfig.json @@ -7,6 +7,7 @@ "references": [ { "path": "../../workflow/tsconfig.build.esm.json" }, { "path": "../config/tsconfig.build.json" }, - { "path": "../permissions/tsconfig.build.json" } + { "path": "../permissions/tsconfig.build.json" }, + { "path": "../inbound-auth/tsconfig.build.json" } ] } diff --git a/packages/@n8n/backend-common/package.json b/packages/@n8n/backend-common/package.json index 75938338acb..bf8f67a0e04 100644 --- a/packages/@n8n/backend-common/package.json +++ b/packages/@n8n/backend-common/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/backend-common", - "version": "1.43.0", + "version": "1.44.0", "scripts": { "clean": "rimraf dist .turbo", "dev": "pnpm watch", diff --git a/packages/@n8n/backend-network/package.json b/packages/@n8n/backend-network/package.json index 706aca2cb0e..8c5dfa59863 100644 --- a/packages/@n8n/backend-network/package.json +++ b/packages/@n8n/backend-network/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/backend-network", - "version": "1.17.0", + "version": "1.18.0", "scripts": { "clean": "rimraf dist .turbo", "dev": "pnpm watch", diff --git a/packages/@n8n/backend-network/src/http/__tests__/connection-guards.test.ts b/packages/@n8n/backend-network/src/http/__tests__/connection-guards.test.ts index dd7fcb84b4b..84e079e425a 100644 --- a/packages/@n8n/backend-network/src/http/__tests__/connection-guards.test.ts +++ b/packages/@n8n/backend-network/src/http/__tests__/connection-guards.test.ts @@ -1,8 +1,8 @@ import type { HttpsProxyAgent } from 'https-proxy-agent'; -import type http from 'node:http'; +import http from 'node:http'; import { makeSsrfBridge } from '../../ssrf/__tests__/mock-ssrf-bridge'; -import { installProxyConnectionGuard } from '../connection-guards'; +import { installConnectionGuard, installProxyConnectionGuard } from '../connection-guards'; type ConnectOpts = Parameters['connect']>[1]; @@ -76,3 +76,78 @@ describe('installProxyConnectionGuard', () => { expect(bridge.validateConnectionHost).not.toHaveBeenCalled(); }); }); + +describe('installConnectionGuard', () => { + function guarded() { + const createConnection = vi.fn().mockReturnValue('SOCKET'); + const target = { createConnection }; + return { target, createConnection }; + } + + it('validates the target host and delegates when the policy allows it', () => { + const bridge = makeSsrfBridge(); + const { target, createConnection } = guarded(); + installConnectionGuard(target, bridge); + + expect(target.createConnection({ host: 'target.example.com' })).toBe('SOCKET'); + + expect(bridge.validateConnectionHost).toHaveBeenCalledWith('target.example.com'); + expect(createConnection).toHaveBeenCalled(); + }); + + it('rejects a connection to a socket path without validating the unused host', () => { + const bridge = makeSsrfBridge(); + const { target, createConnection } = guarded(); + installConnectionGuard(target, bridge); + + expect(() => + target.createConnection({ host: 'target.example.com', socketPath: '/var/run/docker.sock' }), + ).toThrow('Cannot open a connection to a socket path'); + + expect(createConnection).not.toHaveBeenCalled(); + expect(bridge.validateConnectionHost).not.toHaveBeenCalled(); + }); + + it('reports a socket path through the callback when the caller passes one', () => { + const bridge = makeSsrfBridge(); + const { target, createConnection } = guarded(); + installConnectionGuard(target, bridge); + const onConnect = vi.fn(); + + expect( + target.createConnection({ socketPath: '/var/run/docker.sock' }, onConnect), + ).toBeUndefined(); + + expect(onConnect).toHaveBeenCalledWith( + expect.objectContaining({ message: 'Cannot open a connection to a socket path' }), + ); + expect(createConnection).not.toHaveBeenCalled(); + }); +}); + +describe('installConnectionGuard on a real http.Agent', () => { + async function get(agent: http.Agent): Promise { + return await new Promise((resolve, reject) => { + const req = http.get('http://target.example.com/x', { agent, timeout: 3000 }, (res) => { + let data = ''; + res.on('data', (chunk) => (data += String(chunk))); + res.on('end', () => resolve(data)); + }); + req.on('error', reject); + req.on('timeout', () => { + req.destroy(); + reject(new Error('timeout')); + }); + }); + } + + it.each([ + ['ssrf active', () => makeSsrfBridge()], + ['ssrf disabled', () => 'disabled' as const], + ])('refuses a socket path Node puts in the connect options (%s)', async (_label, ssrf) => { + const agent = new http.Agent({ socketPath: '/tmp/backend-network.sock' } as http.AgentOptions); + installConnectionGuard(agent as unknown as { createConnection: never }, ssrf()); + + await expect(get(agent)).rejects.toThrow('Cannot open a connection to a socket path'); + }); +}); diff --git a/packages/@n8n/backend-network/src/http/__tests__/node-agents.test.ts b/packages/@n8n/backend-network/src/http/__tests__/node-agents.test.ts index 287e69394c2..034c29c4ad8 100644 --- a/packages/@n8n/backend-network/src/http/__tests__/node-agents.test.ts +++ b/packages/@n8n/backend-network/src/http/__tests__/node-agents.test.ts @@ -15,7 +15,7 @@ import { installConnectionGuard, UnknownConnectionHostError } from '../connectio import { EnvProxyHttpAgent } from '../env-proxy-http-agent'; import { EnvProxyHttpsAgent } from '../env-proxy-https-agent'; import { type LocalServer, startServer } from '../local-server'; -import { buildNodeAgents, type ProxyUrl } from '../node-agents'; +import { buildNodeAgents, type NodeAgentOptions, type ProxyUrl } from '../node-agents'; // HttpsProxyAgent stores `lookup` in `connectOpts` rather than `options` // (unlike http.Agent and HttpProxyAgent which use `options`). @@ -32,6 +32,10 @@ function getAgentOptions(agent: http.Agent | https.Agent): { keepAlive?: boolean return (agent as unknown as { options?: { keepAlive?: boolean } }).options ?? {}; } +function withSocketPath(socketPath: string): NodeAgentOptions { + return { socketPath } as unknown as NodeAgentOptions; +} + // --------------------------------------------------------------------------- // buildNodeAgents — shared builder (single source of truth for the undici // factory, the axios transport layer, and the global proxy agents) @@ -111,6 +115,29 @@ describe('buildNodeAgents', () => { }); }); + describe('rejects a caller-provided socketPath (not a validated connection target)', () => { + const socketPath = '/tmp/backend-network.sock'; + + it.each([ + ['ssrf disabled', 'disabled' as const], + ['ssrf active', makeSsrfBridge()], + ])('throws when agentOptions.socketPath is set (%s)', (_label, ssrf) => { + expect(() => buildNodeAgents(false, ssrf, withSocketPath(socketPath))).toThrow( + '`agentOptions.socketPath` is not supported', + ); + }); + + it.each([ + ['direct', false as const], + ['env proxy', 'env' as const], + ['explicit proxy', 'http://proxy.internal:3128' as ProxyUrl], + ])('throws on the %s path too', (_label, proxy) => { + expect(() => buildNodeAgents(proxy, makeSsrfBridge(), withSocketPath(socketPath))).toThrow( + '`agentOptions.socketPath` is not supported', + ); + }); + }); + describe('SSRF lookup placement', () => { const modes: Array<[string, false | 'env' | ProxyUrl]> = [ ['proxy: false', false], diff --git a/packages/@n8n/backend-network/src/http/connection-guards.ts b/packages/@n8n/backend-network/src/http/connection-guards.ts index 169634890bc..27fcaf4aea6 100644 --- a/packages/@n8n/backend-network/src/http/connection-guards.ts +++ b/packages/@n8n/backend-network/src/http/connection-guards.ts @@ -14,8 +14,18 @@ export class UnknownConnectionHostError extends UnexpectedError { } } +export class SocketPathConnectionError extends UnexpectedError { + constructor() { + super('Cannot open a connection to a socket path'); + } +} + /** Subset of an agent's connection options we read to find the target host. */ -type ConnectionOptions = { host?: string | null; hostname?: string | null }; +type ConnectionOptions = { + host?: string | null; + hostname?: string | null; + socketPath?: string; +}; /** * Runtime-only `createConnection` method of Node's http(s) agents. @@ -59,6 +69,16 @@ export function installProxyConnectionGuard(agent: ProxyConnectionAgent, ssrf: S }; } +function connectionError( + ssrf: SsrfBridge | 'disabled', + options: ConnectionOptions, +): Error | undefined { + if (options.socketPath) { + return new SocketPathConnectionError(); + } + return ssrf === 'disabled' ? undefined : connectionHostError(ssrf, options); +} + /** * Wraps an agent's `createConnection` to validate the connection target before the socket opens. * @@ -68,11 +88,11 @@ export function installProxyConnectionGuard(agent: ProxyConnectionAgent, ssrf: S */ export function installConnectionGuard( target: { createConnection: CreateConnection }, - ssrf: SsrfBridge, + ssrf: SsrfBridge | 'disabled', ): void { const createConnection = target.createConnection.bind(target); target.createConnection = (options, onConnect) => { - const error = connectionHostError(ssrf, options); + const error = connectionError(ssrf, options); if (error) { if (onConnect) { onConnect(error); diff --git a/packages/@n8n/backend-network/src/http/node-agents.ts b/packages/@n8n/backend-network/src/http/node-agents.ts index 632b5ca790a..8852c3bac1b 100644 --- a/packages/@n8n/backend-network/src/http/node-agents.ts +++ b/packages/@n8n/backend-network/src/http/node-agents.ts @@ -1,4 +1,4 @@ -import { UnexpectedError } from 'n8n-workflow'; +import { UserError } from 'n8n-workflow'; import http from 'node:http'; import https from 'node:https'; import type { LookupFunction } from 'node:net'; @@ -81,6 +81,10 @@ export type NodeAgentOptions = https.AgentOptions; * therefore has no effect and is rejected to avoid a false sense of control over * DNS resolution. * + * `agentOptions.socketPath` is rejected for a related reason: it replaces the + * connection target, leaving the request's host and port unused, so nothing the + * policy decides applies to the socket that opens. + * * `agentOptions` describes the connection to the **target**. Behind a proxy its TLS * options travel with the tunnelled session rather than the proxy handshake * (see `proxy/proxied-agents.ts`). @@ -91,11 +95,17 @@ export function buildNodeAgents( agentOptions?: NodeAgentOptions, ): { httpAgent: http.Agent; httpsAgent: https.Agent } { if (agentOptions?.lookup) { - throw new UnexpectedError( + throw new UserError( '`agentOptions.lookup` is not supported: DNS resolution is managed by the SSRF policy. Remove it from `agentOptions`.', ); } + if (agentOptions !== undefined && 'socketPath' in agentOptions && agentOptions.socketPath) { + throw new UserError( + '`agentOptions.socketPath` is not supported. Remove it from `agentOptions`.', + ); + } + const lookup: LookupFunction | undefined = ssrf !== 'disabled' ? ssrf.createSecureLookup() : undefined; @@ -132,15 +142,16 @@ export function buildNodeAgents( } /** - * Installs {@link installConnectionGuard} on a direct-path agent pair when SSRF protection is active. + * Installs {@link installConnectionGuard} on a direct-path agent pair. + * + * It goes on whatever the SSRF setting, because it also refuses a socket path, which + * is not an SSRF decision. */ function applyConnectionGuard( agents: { httpAgent: http.Agent; httpsAgent: https.Agent }, ssrf: SsrfOption, ): { httpAgent: http.Agent; httpsAgent: https.Agent } { - if (ssrf !== 'disabled') { - installConnectionGuard(agents.httpAgent, ssrf); - installConnectionGuard(agents.httpsAgent, ssrf); - } + installConnectionGuard(agents.httpAgent, ssrf); + installConnectionGuard(agents.httpsAgent, ssrf); return agents; } diff --git a/packages/@n8n/backend-services/eslint.config.mjs b/packages/@n8n/backend-services/eslint.config.mjs index 65fb1ff69aa..b3b56291d5f 100644 --- a/packages/@n8n/backend-services/eslint.config.mjs +++ b/packages/@n8n/backend-services/eslint.config.mjs @@ -5,6 +5,26 @@ import { backendConfig } from '@n8n/eslint-config/backend'; export default defineConfig( globalIgnores(['coverage/**', 'vitest.config.ts']), backendConfig, + { + files: ['./src/**/*.ts'], + ignores: ['./src/services/jwt.service.ts', './src/**/__tests__/**'], + rules: { + '@typescript-eslint/no-restricted-imports': [ + 'error', + { + paths: [ + { + name: 'jsonwebtoken', + allowImportNames: ['JsonWebTokenError', 'TokenExpiredError', 'NotBeforeError'], + allowTypeImports: true, + message: 'Sign and verify through JwtService.', + }, + ], + patterns: [{ group: ['jsonwebtoken/*'], message: 'Sign and verify through JwtService.' }], + }, + ], + }, + }, { rules: { 'n8n-local-rules/no-guardrail-disable': [ diff --git a/packages/@n8n/backend-services/oxlint.config.mts b/packages/@n8n/backend-services/oxlint.config.mts index a02ff6e1161..0f4d0563337 100644 --- a/packages/@n8n/backend-services/oxlint.config.mts +++ b/packages/@n8n/backend-services/oxlint.config.mts @@ -6,6 +6,30 @@ export default defineConfig({ extends: [backendConfig], options: { typeAware: true }, ignorePatterns: ['coverage/**'], + overrides: [ + { + files: ['./src/**/*.ts'], + excludeFiles: ['./src/services/jwt.service.ts', './src/**/__tests__/**'], + rules: { + 'no-restricted-imports': [ + 'error', + { + paths: [ + { + name: 'jsonwebtoken', + allowImportNames: ['JsonWebTokenError', 'TokenExpiredError', 'NotBeforeError'], + allowTypeImports: true, + message: 'Sign and verify through JwtService.', + }, + ], + patterns: [ + { group: ['jsonwebtoken/*'], message: 'Sign and verify through JwtService.' }, + ], + }, + ], + }, + }, + ], rules: { 'n8n-local-rules/no-guardrail-disable': [ 'error', diff --git a/packages/@n8n/backend-services/package.json b/packages/@n8n/backend-services/package.json index 14a3a02c218..1437ab8ef3f 100644 --- a/packages/@n8n/backend-services/package.json +++ b/packages/@n8n/backend-services/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/backend-services", - "version": "1.3.0", + "version": "1.4.0", "scripts": { "clean": "rimraf dist .turbo", "dev": "pnpm watch", @@ -28,15 +28,16 @@ "@n8n/backend-network": "workspace:*", "@n8n/config": "workspace:*", "@n8n/constants": "workspace:*", - "@n8n/decorators": "workspace:*", "@n8n/db": "workspace:*", + "@n8n/decorators": "workspace:*", "@n8n/di": "workspace:*", "@n8n/errors": "workspace:*", "@n8n/permissions": "workspace:*", "@n8n/utils": "workspace:*", "cache-manager": "catalog:", - "express-openapi-validator": "5.5.3", "ioredis": "5.3.2", + "jsonwebtoken": "catalog:", + "n8n-core": "workspace:*", "n8n-workflow": "workspace:*" }, "peerDependencies": { @@ -48,6 +49,7 @@ "@n8n/oxlint-config": "workspace:*", "@n8n/typescript-config": "workspace:*", "@n8n/vitest-config": "workspace:*", + "@types/jsonwebtoken": "catalog:", "@types/lodash": "catalog:", "@vitest/coverage-v8": "catalog:", "eslint": "catalog:", diff --git a/packages/@n8n/backend-services/src/errors/__tests__/rest-error-classifier.test.ts b/packages/@n8n/backend-services/src/errors/__tests__/rest-error-classifier.test.ts index 6ffe8fea5f1..96d6d5e3263 100644 --- a/packages/@n8n/backend-services/src/errors/__tests__/rest-error-classifier.test.ts +++ b/packages/@n8n/backend-services/src/errors/__tests__/rest-error-classifier.test.ts @@ -1,5 +1,3 @@ -import { BadRequest, Unauthorized } from 'express-openapi-validator/dist/framework/types'; - import { BadRequestError, NotFoundError, @@ -45,44 +43,6 @@ describe('classifyRestError', () => { }); }); - it('tags express-openapi-validator HttpError', () => { - const httpError = new BadRequest({ path: '/x', message: 'schema failed' }); - const d = classifyRestError(httpError); - expect(d).toEqual({ - kind: RestErrorKind.httpError, - status: 400, - message: 'schema failed', - }); - }); - - describe('Unauthorized', () => { - it('keeps the express-openapi-validator message when no session cookie was sent', () => { - const unauthorizedError = new Unauthorized({ - path: '/x', - message: "'X-N8N-API-KEY' header required", - }); - const d = classifyRestError(unauthorizedError); - expect(d).toEqual({ - kind: RestErrorKind.httpError, - status: 401, - message: "'X-N8N-API-KEY' header required", - }); - }); - - it('replaces the api key hint with a generic message when a session cookie was sent', () => { - const unauthorizedError = new Unauthorized({ - path: '/x', - message: "'X-N8N-API-KEY' header required", - }); - const d = classifyRestError(unauthorizedError, { hasSessionCookie: true }); - expect(d).toEqual({ - kind: RestErrorKind.httpError, - status: 401, - message: 'Unauthorized', - }); - }); - }); - it('does not classify an unrelated error with an HTTP error class name', () => { class NotFound extends Error {} @@ -93,32 +53,6 @@ describe('classifyRestError', () => { }); }); - it.each([ - ['HttpError', 400], - ['NotFound', 404], - ['NotAcceptable', 406], - ['MethodNotAllowed', 405], - ['BadRequest', 400], - ['RequestEntityTooLarge', 413], - ['InternalServerError', 500], - ['UnsupportedMediaType', 415], - ['Unauthorized', 401], - ['Forbidden', 403], - ])('recognizes a validator %s error from another package instance', (className, status) => { - const CrossPackageError = { - [className]: class extends Error { - readonly status = status; - }, - }[className]; - const error = new CrossPackageError('validator error'); - - expect(classifyRestError(error)).toEqual({ - kind: RestErrorKind.httpError, - status, - message: 'validator error', - }); - }); - it('tags plain Error as serverError', () => { const d = classifyRestError(new Error('plain')); expect(d).toEqual({ diff --git a/packages/@n8n/backend-services/src/errors/rest-error-classifier.ts b/packages/@n8n/backend-services/src/errors/rest-error-classifier.ts index 08733fe62da..1899ad10d4e 100644 --- a/packages/@n8n/backend-services/src/errors/rest-error-classifier.ts +++ b/packages/@n8n/backend-services/src/errors/rest-error-classifier.ts @@ -1,12 +1,9 @@ -import { HttpError, Unauthorized } from 'express-openapi-validator/dist/framework/types'; - import { ResponseError, UnexpectedError, UserError } from '@n8n/errors'; export const enum RestErrorKind { responseError = 'responseError', userError = 'userError', unexpectedError = 'unexpectedError', - httpError = 'httpError', serverError = 'serverError', } @@ -27,11 +24,6 @@ export type RestErrorDescriptor = kind: RestErrorKind.unexpectedError; message: string; } - | { - kind: RestErrorKind.httpError; - status: number; - message: string; - } | { kind: RestErrorKind.serverError; message: string; @@ -54,15 +46,7 @@ export function isResponseError(error: Error): error is ResponseError { return false; } -export type RestErrorClassifierContext = { - /** Whether the request carried a session cookie, regardless of whether it was valid. */ - hasSessionCookie?: boolean; -}; - -export function classifyRestError( - error: Error, - context?: RestErrorClassifierContext, -): RestErrorDescriptor { +export function classifyRestError(error: Error): RestErrorDescriptor { if (isResponseError(error)) { const descriptor: RestErrorDescriptor & { kind: RestErrorKind.responseError } = { kind: RestErrorKind.responseError, @@ -87,48 +71,5 @@ export function classifyRestError( return { kind: RestErrorKind.unexpectedError, message: error.message }; } - // Replacing express-openapi-validator's 'api key header required' error message - // for requests that contained a session cookie. - if (isHttpErrorInstance(error, Unauthorized, ['Unauthorized']) && context?.hasSessionCookie) { - return { kind: RestErrorKind.httpError, status: 401, message: 'Unauthorized' }; - } - - if ( - isHttpErrorInstance(error, HttpError, [ - 'HttpError', - 'NotFound', - 'NotAcceptable', - 'MethodNotAllowed', - 'BadRequest', - 'RequestEntityTooLarge', - 'InternalServerError', - 'UnsupportedMediaType', - 'Unauthorized', - 'Forbidden', - ]) - ) { - return { - kind: RestErrorKind.httpError, - status: error.status || 400, - message: error.message || 'Bad request', - }; - } - return { kind: RestErrorKind.serverError, message: error.message ?? 'Unknown error' }; } - -function isHttpErrorInstance( - error: Error, - errorClass: new (...args: never[]) => T, - classNames: string[], -): error is T { - if (error instanceof errorClass) { - return true; - } - - return classNames.includes(error.constructor.name) && hasHttpStatus(error); -} - -function hasHttpStatus(error: Error): error is Error & { status: number } { - return 'status' in error && typeof error.status === 'number'; -} diff --git a/packages/@n8n/backend-services/src/errors/rest-error-response.ts b/packages/@n8n/backend-services/src/errors/rest-error-response.ts index bc179f66da5..7586f4c9a6f 100644 --- a/packages/@n8n/backend-services/src/errors/rest-error-response.ts +++ b/packages/@n8n/backend-services/src/errors/rest-error-response.ts @@ -74,11 +74,6 @@ export function serializePublicApiError(descriptor: RestErrorDescriptor): { status: 500, body: { message: GENERIC_PUBLIC_MESSAGE }, }; - case RestErrorKind.httpError: - return { - status: descriptor.status, - body: { message: descriptor.message }, - }; } } @@ -111,10 +106,5 @@ export function serializeInternalRestError(descriptor: RestErrorDescriptor): { status: 500, body: { code: 0, message: descriptor.message }, }; - case RestErrorKind.httpError: - return { - status: descriptor.status, - body: { code: 0, message: descriptor.message }, - }; } } diff --git a/packages/@n8n/backend-services/src/index.ts b/packages/@n8n/backend-services/src/index.ts index 1a03952dca4..da7a3534510 100644 --- a/packages/@n8n/backend-services/src/index.ts +++ b/packages/@n8n/backend-services/src/index.ts @@ -37,7 +37,6 @@ export { UrlService } from './services/url.service'; export { classifyRestError, isResponseError, - type RestErrorClassifierContext, type RestErrorDescriptor, RestErrorKind, } from './errors/rest-error-classifier'; @@ -56,3 +55,16 @@ export { type Jwk, type SkippedJwk, } from './services/oauth-discovery-client'; + +export { + type PurposedSignOptions, + type PurposedVerifyOptions, + JwtService, + type JwtPayload, +} from './services/jwt.service'; +export { + TOKEN_PURPOSES, + type TokenPurpose, + API_KEY_PURPOSES, + LEGACY_UNBOUND_PURPOSES, +} from './services/token-purposes'; diff --git a/packages/cli/src/services/__tests__/jwt.service.test.ts b/packages/@n8n/backend-services/src/services/__tests__/jwt.service.test.ts similarity index 99% rename from packages/cli/src/services/__tests__/jwt.service.test.ts rename to packages/@n8n/backend-services/src/services/__tests__/jwt.service.test.ts index cfb1cd059e6..b2c031fcffe 100644 --- a/packages/cli/src/services/__tests__/jwt.service.test.ts +++ b/packages/@n8n/backend-services/src/services/__tests__/jwt.service.test.ts @@ -5,7 +5,7 @@ import type { InstanceSettings } from 'n8n-core'; import { generateKeyPairSync } from 'node:crypto'; import { mock } from 'vitest-mock-extended'; -import { JwtService } from '@/services/jwt.service'; +import { JwtService } from '../jwt.service'; const getJwtSecret = (svc: JwtService) => (svc as unknown as { jwtSecret: string }).jwtSecret; diff --git a/packages/@n8n/backend-services/src/services/__tests__/workflow-project.service.test.ts b/packages/@n8n/backend-services/src/services/__tests__/workflow-project.service.test.ts index 9606bdb17f2..29236e09882 100644 --- a/packages/@n8n/backend-services/src/services/__tests__/workflow-project.service.test.ts +++ b/packages/@n8n/backend-services/src/services/__tests__/workflow-project.service.test.ts @@ -35,14 +35,17 @@ describe('WorkflowProjectService', () => { }); }); - it('loads the owner project when the cached value is malformed', async () => { - const project = { id: 'project-1' } as Project; - cacheService.getHashValue.mockResolvedValue('invalid' as never); - sharedWorkflowRepository.findOneOrFail.mockResolvedValue({ project } as never); + it.each(['invalid', {}])( + 'loads the owner project when the cached value is malformed', + async (cached) => { + const project = { id: 'project-1' } as Project; + cacheService.getHashValue.mockResolvedValue(cached as never); + sharedWorkflowRepository.findOneOrFail.mockResolvedValue({ project } as never); - await expect(service.getWorkflowProjectCached('workflow-1')).resolves.toBe(project); - expect(sharedWorkflowRepository.findOneOrFail).toHaveBeenCalledOnce(); - }); + await expect(service.getWorkflowProjectCached('workflow-1')).resolves.toBe(project); + expect(sharedWorkflowRepository.findOneOrFail).toHaveBeenCalledOnce(); + }, + ); it('sets the cached owner project', async () => { const project = { id: 'project-1' } as Project; diff --git a/packages/@n8n/backend-services/src/services/__tests__/workflow-sharing.service.test.ts b/packages/@n8n/backend-services/src/services/__tests__/workflow-sharing.service.test.ts index 7a188e01113..870232ccddf 100644 --- a/packages/@n8n/backend-services/src/services/__tests__/workflow-sharing.service.test.ts +++ b/packages/@n8n/backend-services/src/services/__tests__/workflow-sharing.service.test.ts @@ -62,11 +62,12 @@ describe('WorkflowSharingService', () => { scopes: ['workflow:read'], }); - expect(sharedWorkflowRepository.findWorkflowIdsAccessibleToUser).toHaveBeenCalledWith( - member.id, - ['workflow:owner'], - ['project:viewer'], - ); + expect(sharedWorkflowRepository.findWorkflowIdsAccessibleToUser).toHaveBeenCalledWith({ + userId: member.id, + workflowRoleSlugs: ['workflow:owner'], + projectRoleSlugs: ['project:viewer'], + projectId: undefined, + }); expect(result).toEqual(['workflow-1']); }); }); diff --git a/packages/@n8n/backend-services/src/services/cache/__tests__/cache.service.test.ts b/packages/@n8n/backend-services/src/services/cache/__tests__/cache.service.test.ts index 6b07ee11a99..1394c322d77 100644 --- a/packages/@n8n/backend-services/src/services/cache/__tests__/cache.service.test.ts +++ b/packages/@n8n/backend-services/src/services/cache/__tests__/cache.service.test.ts @@ -338,6 +338,27 @@ for (const backend of ['memory', 'redis'] as const) { await expect(cacheService.getHashValue('key', 'field1')).resolves.toBe('value1'); }); + + if (backend === 'memory') { + test('should not return inherited properties as hash field values', async () => { + await cacheService.setHash('key', { field1: { id: 'value1' } }); + + await expect(cacheService.getHashValue('key', '__proto__')).resolves.toBeUndefined(); + await expect(cacheService.getHashValue('key', 'constructor')).resolves.toBeUndefined(); + }); + + test('should not store a `__proto__` hash field', async () => { + await cacheService.setHash('key', { field1: { id: 'value1' } }); + // A computed key creates an own `__proto__` field, as a hash keyed by a workflow id does + await cacheService.setHash('key', { ['__proto__']: { id: 'value2' } }); + + expect(Object.getPrototypeOf(await cacheService.get('key'))).toBe(Object.prototype); + await expect(cacheService.getHashValue('key', '__proto__')).resolves.toBeUndefined(); + await expect(cacheService.getHashValue('key', 'field1')).resolves.toEqual({ + id: 'value1', + }); + }); + } }); }); } diff --git a/packages/@n8n/backend-services/src/services/cache/cache.service.ts b/packages/@n8n/backend-services/src/services/cache/cache.service.ts index f562eed9edf..c4c195a227a 100644 --- a/packages/@n8n/backend-services/src/services/cache/cache.service.ts +++ b/packages/@n8n/backend-services/src/services/cache/cache.service.ts @@ -151,7 +151,15 @@ export class CacheService extends TypedEmitter { const hashObject: Hash = (await this.get(key)) ?? {}; - Object.assign(hashObject, hash); + for (const [field, value] of Object.entries(hash)) { + // Skip `__proto__`. On a plain object, `hash['__proto__'] = value` does not add a field. + // It changes the object's prototype. + if (field === '__proto__') { + continue; + } + + hashObject[field] = value; + } await this.set(key, hashObject); } @@ -309,7 +317,10 @@ export class CacheService extends TypedEmitter { } else { const hashObject = await this.cache.store.get>(cacheKey); - hashValue = hashObject?.[hashKey] as MaybeHash; + hashValue = + hashObject && Object.hasOwn(hashObject, hashKey) + ? (hashObject[hashKey] as MaybeHash) + : undefined; } if (hashValue !== undefined) { diff --git a/packages/cli/src/services/jwt.service.ts b/packages/@n8n/backend-services/src/services/jwt.service.ts similarity index 98% rename from packages/cli/src/services/jwt.service.ts rename to packages/@n8n/backend-services/src/services/jwt.service.ts index 9f6b0221bab..fbc5b9bc37b 100644 --- a/packages/cli/src/services/jwt.service.ts +++ b/packages/@n8n/backend-services/src/services/jwt.service.ts @@ -6,11 +6,7 @@ import { createHash, type KeyObject } from 'crypto'; import jwt from 'jsonwebtoken'; import { InstanceSettings, type DeploymentStateRepo } from 'n8n-core'; -import { - LEGACY_UNBOUND_PURPOSES, - TOKEN_PURPOSES, - type TokenPurpose, -} from '@/services/token-purposes'; +import { LEGACY_UNBOUND_PURPOSES, TOKEN_PURPOSES, type TokenPurpose } from './token-purposes'; /** * `audience` is omitted on purpose: it is derived from the token's purpose, so diff --git a/packages/cli/src/services/token-purposes.ts b/packages/@n8n/backend-services/src/services/token-purposes.ts similarity index 100% rename from packages/cli/src/services/token-purposes.ts rename to packages/@n8n/backend-services/src/services/token-purposes.ts diff --git a/packages/@n8n/backend-services/src/services/workflow-project.service.ts b/packages/@n8n/backend-services/src/services/workflow-project.service.ts index f6a9eaa46dc..b1f52e53de5 100644 --- a/packages/@n8n/backend-services/src/services/workflow-project.service.ts +++ b/packages/@n8n/backend-services/src/services/workflow-project.service.ts @@ -10,7 +10,9 @@ export class WorkflowProjectService { ) {} private reconstructProject(project: Partial): Project | undefined { - if (typeof project !== 'object' || project === null) return undefined; + if (typeof project !== 'object' || project === null || typeof project.id !== 'string') { + return undefined; + } return Object.assign(new Project(), project); } diff --git a/packages/@n8n/backend-services/src/services/workflow-sharing.service.ts b/packages/@n8n/backend-services/src/services/workflow-sharing.service.ts index f499c4b6a2e..f502da11a22 100644 --- a/packages/@n8n/backend-services/src/services/workflow-sharing.service.ts +++ b/packages/@n8n/backend-services/src/services/workflow-sharing.service.ts @@ -51,11 +51,12 @@ export class WorkflowSharingService { ? await this.roleService.rolesWithScope('workflow', options.scopes) : options.workflowRoles; - return await this.sharedWorkflowRepository.findWorkflowIdsAccessibleToUser( - user.id, - workflowRoles, - projectRoles, - ); + return await this.sharedWorkflowRepository.findWorkflowIdsAccessibleToUser({ + userId: user.id, + workflowRoleSlugs: workflowRoles, + projectRoleSlugs: projectRoles, + projectId, + }); } /** diff --git a/packages/@n8n/backend-services/test/setup-test-folder.ts b/packages/@n8n/backend-services/test/setup-test-folder.ts new file mode 100644 index 00000000000..617161fc9b6 --- /dev/null +++ b/packages/@n8n/backend-services/test/setup-test-folder.ts @@ -0,0 +1,12 @@ +import { mkdtempSync, rmSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; + +const testFolder = mkdtempSync(join(tmpdir(), 'n8n-backend-services-')); + +process.env.N8N_USER_FOLDER = testFolder; +process.env.N8N_ENCRYPTION_KEY = 'test-key'; + +afterAll(() => { + rmSync(testFolder, { recursive: true, force: true }); +}); diff --git a/packages/@n8n/backend-services/vitest.config.ts b/packages/@n8n/backend-services/vitest.config.ts index aa666866549..3fda3b9533f 100644 --- a/packages/@n8n/backend-services/vitest.config.ts +++ b/packages/@n8n/backend-services/vitest.config.ts @@ -3,6 +3,7 @@ import { configDefaults, mergeConfig } from 'vitest/config'; export default mergeConfig(createVitestConfigWithDecorators(), { test: { + setupFiles: ['./test/setup-test-folder.ts'], // One fork per file: tests register mocks in the shared `@n8n/di` Container. pool: 'forks', // Vitest's default exclude does not cover dist; stale compiled tests there fail as CJS. diff --git a/packages/@n8n/backend-test-utils/package.json b/packages/@n8n/backend-test-utils/package.json index 4e7b653b738..f92e0036a91 100644 --- a/packages/@n8n/backend-test-utils/package.json +++ b/packages/@n8n/backend-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/backend-test-utils", - "version": "1.43.0", + "version": "1.44.0", "scripts": { "clean": "rimraf dist .turbo", "dev": "pnpm watch", diff --git a/packages/@n8n/blob-storage/package.json b/packages/@n8n/blob-storage/package.json index aea353956ee..bc3ea5f2442 100644 --- a/packages/@n8n/blob-storage/package.json +++ b/packages/@n8n/blob-storage/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/blob-storage", - "version": "1.11.0", + "version": "1.12.0", "description": "Blob storage layer for n8n, with filesystem, S3, and Azure Blob backends", "scripts": { "clean": "rimraf dist .turbo", diff --git a/packages/@n8n/chat-hub/package.json b/packages/@n8n/chat-hub/package.json index f135327f5f5..48276e324e4 100644 --- a/packages/@n8n/chat-hub/package.json +++ b/packages/@n8n/chat-hub/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/chat-hub", - "version": "1.36.0", + "version": "1.37.0", "scripts": { "clean": "rimraf dist .turbo", "dev": "pnpm watch", diff --git a/packages/@n8n/cli/docs/commands/package.md b/packages/@n8n/cli/docs/commands/package.md index 4534bca7568..348c87492dc 100644 --- a/packages/@n8n/cli/docs/commands/package.md +++ b/packages/@n8n/cli/docs/commands/package.md @@ -77,7 +77,7 @@ n8n-cli package import --file=export.n8np --workflow-conflict-policy=fail --bind | `--folder-conflict-policy` | What to do when a package folder already exists in the target project. **Defaults to whatever `--project-conflict-policy` is**, so you state the intent once; for a workflow package, which defines no projects, it defaults to `merge`. `merge` reuses the existing folder and merges the package's children into it; `fail` rejects the import; `overwrite` additionally removes workflows the package does not contain, at the project root and in package-defined folders (see `--overwrite-deletion-policy`), and is rejected unless `--project-conflict-policy` is also `overwrite`. Folders the package does not define are removed too, but only once nothing is left inside them, so target-only content is never swept up. Requires a folders-enabled license when the package contains folders, and the `workflow:delete` and `folder:delete` scopes for `overwrite`. | | `--overwrite-deletion-policy` | How `--folder-conflict-policy=overwrite` removes a workflow the package does not contain: `archive` (instance default) archives it, keeping it and its execution history recoverable; `hard-delete` archives it — the step that unpublishes it — then deletes the workflow and its executions permanently. Each entry in `removedWorkflows` reports what actually happened in its `deletion` field, so a `hard-delete` whose row cannot be dropped yet (unpublishing defers trigger teardown) shows as `archived` rather than failing the import. Ignored unless the folder conflict policy is `overwrite`. | | `--credential-matching-mode` | How credential references are matched on the target instance: `id-only` (default, match by id), `name-and-type` (match by exact name and type), or `type-only` (match by type). For `name-and-type` and `type-only`, candidates are ranked by scope — owned by the target project, then shared into it, then global — and ties within a scope use the most recently updated credential. | -| `--credential-missing-mode` | What to do when a referenced credential cannot be resolved. `create-stub` (instance default) creates empty placeholder credentials in the target project; `must-preexist` requires every referenced credential to already exist. | +| `--credential-missing-mode` | What to do when a referenced credential cannot be resolved. `create-stub` (instance default) creates empty placeholder credentials in the target project; `create-with-values` also creates them, seeded from the expression data bundled in the package (a reference the package carries no data for falls back to an empty stub); `must-preexist` requires every referenced credential to already exist. | | `--data-table-matching-mode` | How data tables referenced by the package's workflows are matched on the target instance: `by-id` (default and only mode) matches the target-project table with the same id — imported tables keep their source id — and never falls back to name matching. | | `--data-table-missing-mode` | What to do when a referenced data table is absent in the target project. `create` (instance default) creates it from the package schema — keeping the source id, with no rows; `must-preexist` requires it to already exist; `do-nothing` skips creation. Under the `keep-existing` and `fail` schema conflict policies, matched tables are schema-validated (all package columns present with the same name and type), even under `do-nothing`. Under `overwrite-non-destructive`, a matched table blocks the import only when a change removes or retypes a column. The import never imports table rows. Matched tables change only under `--data-table-schema-conflict-policy=overwrite` or `overwrite-non-destructive`, which keep their rows. | | `--data-table-schema-conflict-policy` | How strictly a matched data table's schema is compared. Under `keep-existing` and `fail`, every package column must exist on the matched target table with the same name and type. A missing column or a type mismatch rejects the import. `keep-existing` (instance default) ignores additional columns the target table has of its own; `fail` is the strict drift-detection choice and rejects those too. `keep-existing` and `fail` never alter the matched target table. `overwrite` changes the matched target table to match the package. It can remove or retype columns. The values in those columns are removed. Rows and other columns are kept. When the package has column ids, a column that is only renamed keeps its values. The changes apply to all workflows that use the table. `overwrite-non-destructive` makes the same changes as `overwrite`, but rejects the import and writes nothing when a change removes or retypes a column. A target-only column counts as removed. | diff --git a/packages/@n8n/cli/docs/commands/promotions.md b/packages/@n8n/cli/docs/commands/promotions.md index 663325ae632..7bec447e8ce 100644 --- a/packages/@n8n/cli/docs/commands/promotions.md +++ b/packages/@n8n/cli/docs/commands/promotions.md @@ -294,12 +294,17 @@ none. |--------|-----------|---------------| | `applied` | `0` | The package was imported. JSON output includes `counts` and `warnings`. | | `source-changed` | `3` | The configuration, branch, or commit is not the one you reviewed. Nothing was imported. Review the changes again. | -| `blocked` | `4` | Preflight found missing bindings, access requirements, or conflicts. A conflict can be a destructive data table change. Nothing was imported. The output shows the `apply-continue` command to run after you resolve them. | +| `blocked` | `4` | Preflight found missing bindings, access requirements, or conflicts. A conflict can be a destructive data table change or a project deletion. Nothing was imported. The output shows the `apply-continue` command to run after you resolve them. | With `--json`, the output is the full result for each status. For `blocked`, the `preflight` object lists each missing project, missing binding, access requirement, and conflict. Existing variable values on this instance are kept. +Apply makes the team projects on this instance match the package. It deletes +each team project that the package does not hold, with all its workflows, +credentials, and data tables. Preflight reports each such project as a +`project-deletion` conflict. + Clone the `apply` direction first. This command works on the `instance` connection only. The API key needs `gitConnection:pull`. @@ -320,10 +325,16 @@ for `apply`: `blocked` again means that something still blocks, and so run the command again when it exits `4`. Add `--confirm-destructive-changes` to also apply destructive data table -changes: removed or retyped columns. The values in those columns are removed. -Rows and other columns are kept. The flag applies all such changes when the -command runs. This includes changes that the blocked Apply did not report. -Without the flag, a destructive change blocks the command, and it exits `4`. +changes and delete projects: + +- Removed or retyped columns. The values in those columns are removed. Rows and + other columns are kept. +- Team projects that the package does not hold. Each project is deleted with + everything in it. You can't undo this. + +The flag applies all such changes when the command runs. This includes changes +and projects that the blocked Apply did not report. Without the flag, a +destructive change or a project deletion blocks the command, and it exits `4`. ## Apply a reviewed commit diff --git a/packages/@n8n/cli/package.json b/packages/@n8n/cli/package.json index 35a56509f48..c47f60f1cc0 100644 --- a/packages/@n8n/cli/package.json +++ b/packages/@n8n/cli/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/cli", - "version": "0.22.0", + "version": "0.23.0", "description": "Client CLI for n8n — manage workflows, executions, and credentials from the terminal", "license": "LicenseRef-n8n-sustainable-use", "bin": { diff --git a/packages/@n8n/cli/skills/n8n-cli/SKILL.md b/packages/@n8n/cli/skills/n8n-cli/SKILL.md index 5e04000567b..27429b33f90 100644 --- a/packages/@n8n/cli/skills/n8n-cli/SKILL.md +++ b/packages/@n8n/cli/skills/n8n-cli/SKILL.md @@ -234,7 +234,8 @@ n8n-cli promotion-connection apply \ # then run the apply-continue command that apply printed: n8n-cli promotion-connection apply-continue \ --expected-config-id= --expected-branch= --expected-commit-sha= -# To also apply destructive data table changes, add --confirm-destructive-changes. +# To also apply destructive data table changes and delete the team projects that the +# package does not hold, add --confirm-destructive-changes. ``` Connection JSON for step 2: diff --git a/packages/@n8n/cli/src/__tests__/package-error.test.ts b/packages/@n8n/cli/src/__tests__/package-error.test.ts index 1ad31c04a37..0078e1c1386 100644 --- a/packages/@n8n/cli/src/__tests__/package-error.test.ts +++ b/packages/@n8n/cli/src/__tests__/package-error.test.ts @@ -260,6 +260,62 @@ describe('toPackagesError', () => { expect(hint).toContain('w2'); }); + it('lists credential-conflict issues for a 409, by kind', () => { + const result = toPackagesError( + new ApiError(409, 'Import blocked', undefined, { + issues: [ + { + type: 'credential-conflict', + kind: 'differs', + targetId: 'c1', + sourceIds: ['s1'], + name: 'GitHub', + usedBy: [{ kind: 'workflow', id: 'w1' }], + }, + { + type: 'credential-conflict', + kind: 'divergent', + targetId: 'c2', + sourceIds: ['s2', 's3'], + name: 'Slack', + usedBy: [ + { kind: 'workflow', id: 'w2' }, + { kind: 'agent', id: 'a1' }, + ], + }, + ], + }), + ); + + const hint = (result as ApiError).hint ?? ''; + expect(hint).toContain( + 'credential "GitHub" (c1) differs from package credential s1, used by workflow w1', + ); + expect(hint).toContain( + 'credential "Slack" (c2) receives different values from package credentials s2, s3, used by workflow w2, agent a1', + ); + }); + + it('lists credential-update-forbidden issues for a 422', () => { + const result = toPackagesError( + new ApiError(422, 'Import blocked', undefined, { + issues: [ + { + type: 'credential-update-forbidden', + targetId: 'c1', + sourceIds: ['s1'], + name: 'GitHub', + usedBy: [{ kind: 'workflow', id: 'w1' }], + }, + ], + }), + ); + + expect((result as ApiError).hint).toContain( + 'credential "GitHub" (c1) matches package credential s1, but you lack permission to update it. Use keep-existing or ask its owner. Used by workflow w1', + ); + }); + it('lists variable-limit-exceeded issues for a 422', () => { const result = toPackagesError( new ApiError(422, 'Import blocked', undefined, { diff --git a/packages/@n8n/cli/src/__tests__/promotion-connection-operations.test.ts b/packages/@n8n/cli/src/__tests__/promotion-connection-operations.test.ts index f97bc1d1612..e86e94eb0a4 100644 --- a/packages/@n8n/cli/src/__tests__/promotion-connection-operations.test.ts +++ b/packages/@n8n/cli/src/__tests__/promotion-connection-operations.test.ts @@ -220,6 +220,33 @@ describe('promotion-connection apply command', () => { expect(exit).toHaveBeenCalledWith(4); }); + it('exits 4 and lists the projects that a confirmed Apply deletes', async () => { + const { run, logToStderr, exit } = runApply({ + ...BLOCKED_RESULT, + preflight: { + ...BLOCKED_RESULT.preflight, + conflicts: [ + { + kind: 'project', + code: 'project-deletion', + project: { id: 'proj-2', name: 'Sales' }, + }, + ], + }, + }); + + await run(); + + const message = logToStderr.mock.calls[0][0]; + expect(message).toContain( + 'Apply deletes these projects with everything in them:\n' + ' Sales (proj-2)', + ); + expect(message).toContain( + "To also delete the projects listed above, add --confirm-destructive-changes. You can't undo this.", + ); + expect(exit).toHaveBeenCalledWith(4); + }); + it('quotes source values in the Continue command so it is safe to paste', async () => { const { run, logToStderr } = runApply({ ...BLOCKED_RESULT, diff --git a/packages/@n8n/cli/src/client.ts b/packages/@n8n/cli/src/client.ts index 871ebce9a52..5c3f0ac0425 100644 --- a/packages/@n8n/cli/src/client.ts +++ b/packages/@n8n/cli/src/client.ts @@ -136,6 +136,13 @@ export interface PromotionBindingPreflight { warnings: Array>; } +/** A team project that a full Apply deletes, because the package does not hold it. */ +export type PromotionProjectDeletion = { + kind: 'project'; + code: 'project-deletion'; + project: { id: string; name: string }; +}; + type ApplyPackageIdentity = { connectionId: string; configId: string; diff --git a/packages/@n8n/cli/src/commands/package/import.ts b/packages/@n8n/cli/src/commands/package/import.ts index 8ee3759fa84..62a2de49e91 100644 --- a/packages/@n8n/cli/src/commands/package/import.ts +++ b/packages/@n8n/cli/src/commands/package/import.ts @@ -76,7 +76,7 @@ export default class PackageImport extends BaseCommand { credentialMissingMode: Flags.string({ description: 'What to do when a referenced credential cannot be resolved (default on the instance: create-stub)', - options: ['must-preexist', 'create-stub'], + options: ['must-preexist', 'create-stub', 'create-with-values'], aliases: ['credential-missing-mode'], }), dataTableMatchingMode: Flags.string({ diff --git a/packages/@n8n/cli/src/commands/package/package-error.ts b/packages/@n8n/cli/src/commands/package/package-error.ts index dd3f240cd51..f274b69bf8d 100644 --- a/packages/@n8n/cli/src/commands/package/package-error.ts +++ b/packages/@n8n/cli/src/commands/package/package-error.ts @@ -41,6 +41,21 @@ type BlockingIssue = usedBy: RequirementConsumer[]; violations: Array<{ message: string }>; } + | { + type: 'credential-conflict'; + kind: 'differs' | 'divergent'; + targetId: string; + sourceIds: string[]; + name: string; + usedBy: RequirementConsumer[]; + } + | { + type: 'credential-update-forbidden'; + targetId: string; + sourceIds: string[]; + name: string; + usedBy: RequirementConsumer[]; + } | { type: 'variable-unresolved'; name: string; usedBy: RequirementConsumer[] } | { type: 'variable-conflict'; name: string; projectId?: string; usedBy: RequirementConsumer[] } | { @@ -154,6 +169,19 @@ function formatIssue(issue: unknown): string { : ''; return `credential "${it.name ?? it.sourceId}" (${it.sourceId}, ${it.credentialType}) refused by policy: ${reasons}, used by ${usedBy}`; } + if (it.type === 'credential-conflict') { + const usedBy = formatConsumers(it.usedBy); + const sources = Array.isArray(it.sourceIds) ? it.sourceIds.join(', ') : ''; + if (it.kind === 'divergent') { + return `credential "${it.name}" (${it.targetId}) receives different values from package credentials ${sources}, used by ${usedBy}`; + } + return `credential "${it.name}" (${it.targetId}) differs from package credential ${sources}, used by ${usedBy}`; + } + if (it.type === 'credential-update-forbidden') { + const usedBy = formatConsumers(it.usedBy); + const sources = Array.isArray(it.sourceIds) ? it.sourceIds.join(', ') : ''; + return `credential "${it.name}" (${it.targetId}) matches package credential ${sources}, but you lack permission to update it. Use keep-existing or ask its owner. Used by ${usedBy}`; + } if (it.type === 'variable-unresolved') { const usedBy = formatConsumers(it.usedBy); return `variable "${it.name}" unresolved, used by ${usedBy}`; diff --git a/packages/@n8n/cli/src/commands/promotion-connection/apply-command.ts b/packages/@n8n/cli/src/commands/promotion-connection/apply-command.ts index c9cb2c3be0e..cc00e90075d 100644 --- a/packages/@n8n/cli/src/commands/promotion-connection/apply-command.ts +++ b/packages/@n8n/cli/src/commands/promotion-connection/apply-command.ts @@ -1,5 +1,9 @@ import { BaseCommand, EXIT_BLOCKED, EXIT_SOURCE_CHANGED, EXIT_SUCCESS } from '../../base-command'; -import type { ApplyPackageResult, PromotionBindingPreflight } from '../../client'; +import type { + ApplyPackageResult, + PromotionBindingPreflight, + PromotionProjectDeletion, +} from '../../client'; type ReportFlags = { quiet?: boolean; format?: string; json?: boolean; jq?: string }; @@ -65,6 +69,7 @@ function blockedMessage( ): string { const bindings = (kind: 'credential' | 'variable') => preflight.missingBindings.filter((binding) => binding.kind === kind).length; + const projectDeletions = preflight.conflicts.filter(isProjectDeletion); return [ 'Apply is blocked. Nothing was imported.', @@ -73,6 +78,12 @@ function blockedMessage( ` Missing variables: ${bindings('variable')}`, ` Access requirements: ${preflight.accessRequirements.length}`, ` Conflicts: ${preflight.conflicts.length}`, + ...(projectDeletions.length > 0 + ? [ + 'Apply deletes these projects with everything in them:', + ...projectDeletions.map(({ project }) => ` ${project.name} (${project.id})`), + ] + : []), 'Run with --json for the details. After you resolve them, run:', ` ${continueCommand(result)}`, ...(preflight.conflicts.some(({ code }) => code === 'destructive-change') @@ -80,9 +91,20 @@ function blockedMessage( 'To also apply data table changes that remove or retype columns, add --confirm-destructive-changes. The values in those columns are removed.', ] : []), + ...(projectDeletions.length > 0 + ? [ + "To also delete the projects listed above, add --confirm-destructive-changes. You can't undo this.", + ] + : []), ].join('\n'); } +function isProjectDeletion( + conflict: Record, +): conflict is PromotionProjectDeletion { + return conflict.code === 'project-deletion'; +} + /** The `--expected-*` flags that pin a Continue run to the source a blocked Apply reported. */ function expectedSourceArgs(result: BlockedResult): string { return ( diff --git a/packages/@n8n/cli/src/commands/promotion-connection/apply-continue.ts b/packages/@n8n/cli/src/commands/promotion-connection/apply-continue.ts index d6d56d2d43c..52b0b1ff9f4 100644 --- a/packages/@n8n/cli/src/commands/promotion-connection/apply-continue.ts +++ b/packages/@n8n/cli/src/commands/promotion-connection/apply-continue.ts @@ -6,7 +6,7 @@ import { BaseCommand } from '../../base-command'; export default class PromotionConnectionApplyContinue extends PromotionApplyCommand { static override description = - 'Continue an Apply that was blocked on bindings, after they are set up. Pass the config ID, branch, and commit SHA that the blocked Apply reported. Exits 3 when the source changed since then and 4 when bindings are still missing or a destructive data table change is not confirmed with --confirm-destructive-changes; nothing is imported in either case.'; + 'Continue a blocked Apply after you resolve its bindings, access requirements, or conflicts. Pass the config ID, branch, and commit SHA that the blocked Apply reported. Exits 3 when the source changed since then and 4 when bindings are still missing or a destructive data table change or project deletion is not confirmed with --confirm-destructive-changes; nothing is imported in either case.'; static override examples = [ '<%= config.bin %> promotion-connection apply-continue conn-1 --expected-config-id=cfg-1 --expected-branch=main --expected-commit-sha=', @@ -19,7 +19,7 @@ export default class PromotionConnectionApplyContinue extends PromotionApplyComm ...expectedSourceFlags({ required: true }), confirmDestructiveChanges: Flags.boolean({ description: - 'Also apply data table changes that remove or retype columns. The values in those columns are removed.', + 'Also apply data table changes that remove or retype columns, and delete the team projects that the package does not hold. The values in those columns and everything in those projects are removed.', aliases: ['confirm-destructive-changes'], }), }; diff --git a/packages/@n8n/client-oauth2/package.json b/packages/@n8n/client-oauth2/package.json index 8cecba73cdf..47a32f47084 100644 --- a/packages/@n8n/client-oauth2/package.json +++ b/packages/@n8n/client-oauth2/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/client-oauth2", - "version": "1.25.0", + "version": "1.26.0", "scripts": { "clean": "rimraf dist .turbo", "dev": "pnpm watch", diff --git a/packages/@n8n/computer-use/package.json b/packages/@n8n/computer-use/package.json index 743c38b6148..c3a9983720f 100644 --- a/packages/@n8n/computer-use/package.json +++ b/packages/@n8n/computer-use/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/computer-use", - "version": "0.26.0", + "version": "0.27.0", "description": "Local AI gateway for n8n Assistant — filesystem, shell, screenshots, mouse/keyboard, and browser automation", "publishConfig": { "bin": { diff --git a/packages/@n8n/config/package.json b/packages/@n8n/config/package.json index d60927c8500..d821b5c074e 100644 --- a/packages/@n8n/config/package.json +++ b/packages/@n8n/config/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/config", - "version": "2.41.0", + "version": "2.42.0", "scripts": { "clean": "rimraf dist .turbo", "dev": "pnpm watch", diff --git a/packages/@n8n/config/src/configs/__tests__/scheduler.config.test.ts b/packages/@n8n/config/src/configs/__tests__/scheduler.config.test.ts index 6fd48056447..21ce64fb5b9 100644 --- a/packages/@n8n/config/src/configs/__tests__/scheduler.config.test.ts +++ b/packages/@n8n/config/src/configs/__tests__/scheduler.config.test.ts @@ -12,11 +12,11 @@ describe('SchedulerConfig', () => { vi.restoreAllMocks(); }); - describe('flag off (defaults)', () => { - it('should be disabled by default', () => { + describe('defaults', () => { + it('should be enabled by default', () => { const { scheduler } = Container.get(GlobalConfig); - expect(scheduler.enabled).toBe(false); + expect(scheduler.enabled).toBe(true); }); it('should use default tunables', () => { @@ -39,8 +39,7 @@ describe('SchedulerConfig', () => { expect(scheduler.reaperTimeoutSeconds).toBe(60); expect(scheduler.retentionTimeoutSeconds).toBe(5 * 60); expect(scheduler.maxConcurrentPasses).toBe(10); - expect(scheduler.triggerNodeMode).toBe('legacy'); - expect(scheduler.allowSkipDurableScheduler).toBe(false); + expect(scheduler.triggerNodeMode).toBe('new'); expect(scheduler.maxAttempts).toBe(5); expect(scheduler.taskTimeoutSeconds).toBe(300); expect(scheduler.enabledForPollTriggers).toBe(false); @@ -49,13 +48,21 @@ describe('SchedulerConfig', () => { }); }); - describe('flag on (env overrides)', () => { - it('should enable via env', () => { - vi.stubEnv('N8N_SCHEDULER_ENABLED', 'true'); + describe('env overrides', () => { + it('should disable via env', () => { + vi.stubEnv('N8N_SCHEDULER_ENABLED', 'false'); const { scheduler } = Container.get(GlobalConfig); - expect(scheduler.enabled).toBe(true); + expect(scheduler.enabled).toBe(false); + }); + + it('should allow the legacy trigger node mode via env', () => { + vi.stubEnv('N8N_SCHEDULER_TRIGGER_NODE_MODE', 'legacy'); + + const { scheduler } = Container.get(GlobalConfig); + + expect(scheduler.triggerNodeMode).toBe('legacy'); }); it('should override each tunable from env', () => { @@ -104,14 +111,6 @@ describe('SchedulerConfig', () => { expect(scheduler.enabledForSystemTasks).toBe(true); }); - it('should expose the durable-scheduler skip escape hatch via env', () => { - vi.stubEnv('N8N_ENV_FEAT_SKIP_DURABLE_SCHEDULER', 'true'); - - const { scheduler } = Container.get(GlobalConfig); - - expect(scheduler.allowSkipDurableScheduler).toBe(true); - }); - it('should fall back to the default poll timeout when the value exceeds one day', () => { vi.spyOn(console, 'warn').mockImplementation(() => {}); vi.stubEnv('N8N_SCHEDULER_POLL_TIMEOUT', '86401'); diff --git a/packages/@n8n/config/src/configs/agents.config.ts b/packages/@n8n/config/src/configs/agents.config.ts index ef77d9a0c62..b2fc2e3f3f4 100644 --- a/packages/@n8n/config/src/configs/agents.config.ts +++ b/packages/@n8n/config/src/configs/agents.config.ts @@ -113,4 +113,12 @@ export class AgentsConfig { */ @Env('N8N_AGENTS_CHANNEL_RECONCILE_INTERVAL') channelReconcileIntervalSeconds: number = 60; + + /** + * For testing only. Lets the WhatsApp setup accept a short-lived access token, + * like the one on the API Setup page in Meta. A channel that uses one stops + * working when the token expires, about a day later. + */ + @Env('N8N_AGENTS_WHATSAPP_ALLOW_TEMPORARY_TOKEN') + whatsAppAllowTemporaryToken: boolean = false; } diff --git a/packages/@n8n/config/src/configs/instance-ai.config.ts b/packages/@n8n/config/src/configs/instance-ai.config.ts index a06b3e8b45e..47389541f9f 100644 --- a/packages/@n8n/config/src/configs/instance-ai.config.ts +++ b/packages/@n8n/config/src/configs/instance-ai.config.ts @@ -248,19 +248,6 @@ export class InstanceAiConfig { @Env('N8N_INSTANCE_AI_FOLDER_EXPLORATION_ENABLED') folderExplorationEnabled: boolean = false; - /** - * Activation-capped trial variant for n8n cloud experiment. - * Set by the cloud dashboard at deploy time on one signup-experiment cohort only. - */ - @Env('N8N_INSTANCE_AI_ACTIVATION_CAPPED') - activationCapped: boolean = false; - - /** - * How many assistant messages the instance must have sent before {@link activationCapped} locking may apply. - */ - @Env('N8N_INSTANCE_AI_ACTIVATION_LOCK_MESSAGE_THRESHOLD') - activationLockMessageThreshold: number = 1; - /** * Max orchestrator runs executing concurrently on this process. A new user turn over * the cap is refused with HTTP 429; resumes and internal follow-up runs are always diff --git a/packages/@n8n/config/src/configs/public-api.config.ts b/packages/@n8n/config/src/configs/public-api.config.ts index e944db7dac3..b619d82d147 100644 --- a/packages/@n8n/config/src/configs/public-api.config.ts +++ b/packages/@n8n/config/src/configs/public-api.config.ts @@ -1,4 +1,40 @@ -import { Config, Env } from '../decorators'; +import { Config, Env, Nested } from '../decorators'; +import { nonnegativeIntSchema, positiveIntSchema } from '../schemas'; + +/** Requests per API key. A limit of 0 turns off that layer. */ +@Config +export class PublicApiRateLimitConfig { + @Env('N8N_PUBLIC_API_RATE_LIMIT_ENABLED') + enabled: boolean = false; + + /** Read requests for one API key across all endpoints. */ + @Env('N8N_PUBLIC_API_RATE_LIMIT_GLOBAL_READ_LIMIT', nonnegativeIntSchema) + globalReadLimit: number = 1_200; + + @Env('N8N_PUBLIC_API_RATE_LIMIT_GLOBAL_READ_WINDOW_SECONDS', positiveIntSchema) + globalReadWindowSeconds: number = 60; + + /** Write requests for one API key across all endpoints. */ + @Env('N8N_PUBLIC_API_RATE_LIMIT_GLOBAL_WRITE_LIMIT', nonnegativeIntSchema) + globalWriteLimit: number = 300; + + @Env('N8N_PUBLIC_API_RATE_LIMIT_GLOBAL_WRITE_WINDOW_SECONDS', positiveIntSchema) + globalWriteWindowSeconds: number = 60; + + /** Read requests for one API key on one endpoint. */ + @Env('N8N_PUBLIC_API_RATE_LIMIT_ENDPOINT_READ_LIMIT', nonnegativeIntSchema) + endpointReadLimit: number = 600; + + @Env('N8N_PUBLIC_API_RATE_LIMIT_ENDPOINT_READ_WINDOW_SECONDS', positiveIntSchema) + endpointReadWindowSeconds: number = 60; + + /** Write requests for one API key on one endpoint. */ + @Env('N8N_PUBLIC_API_RATE_LIMIT_ENDPOINT_WRITE_LIMIT', nonnegativeIntSchema) + endpointWriteLimit: number = 200; + + @Env('N8N_PUBLIC_API_RATE_LIMIT_ENDPOINT_WRITE_WINDOW_SECONDS', positiveIntSchema) + endpointWriteWindowSeconds: number = 60; +} @Config export class PublicApiConfig { @@ -13,4 +49,7 @@ export class PublicApiConfig { /** When true, the Swagger UI for the Public API is not served. */ @Env('N8N_PUBLIC_API_SWAGGERUI_DISABLED') swaggerUiDisabled: boolean = false; + + @Nested + rateLimit: PublicApiRateLimitConfig; } diff --git a/packages/@n8n/config/src/configs/scaling-mode.config.ts b/packages/@n8n/config/src/configs/scaling-mode.config.ts index b48fb129f5a..8bcf968117c 100644 --- a/packages/@n8n/config/src/configs/scaling-mode.config.ts +++ b/packages/@n8n/config/src/configs/scaling-mode.config.ts @@ -182,4 +182,14 @@ export class ScalingModeConfig { @Nested workerPool: WorkerPoolConfig; + + /** + * Whether a worker that receives a shutdown signal suspends in-flight + * production executions at the next node boundary. Suspended executions are + * persisted as 'waiting' and resumed on another worker, instead of running + * to completion (or force-kill) on the exiting worker. An execution that + * still owes its webhook caller a response is not suspended. + */ + @Env('N8N_WORKER_SUSPEND_EXECUTIONS_ON_SHUTDOWN') + suspendExecutionsOnShutdown: boolean = false; } diff --git a/packages/@n8n/config/src/configs/scheduler.config.ts b/packages/@n8n/config/src/configs/scheduler.config.ts index 517ec5ba009..d84a09d1cc2 100644 --- a/packages/@n8n/config/src/configs/scheduler.config.ts +++ b/packages/@n8n/config/src/configs/scheduler.config.ts @@ -24,23 +24,31 @@ const jitterRatioSchema = z.number({ coerce: true }).nonnegative().lt(1); * they start, so they survive restarts and, in a multi-instance setup, each run * is picked up by exactly one instance instead of every instance firing it. * - * Off by default. While {@link enabled} is false none of these settings have any - * effect and the existing in-memory Schedule Trigger behaviour is unchanged. The - * tunables below only matter once the scheduler is turned on; the defaults suit - * most instances, so change them only to tune timing precision or storage. + * On by default. It takes over Schedule Trigger nodes only while the workflow + * publication service is also on. Set {@link enabled} to false to keep the + * in-memory Schedule Trigger behaviour. Then none of these settings have any + * effect. The defaults suit most instances, so change them only to tune timing + * precision or storage. */ @Config export class SchedulerConfig { /** - * Turn on the durable scheduler. Off by default so existing self-hosted setups - * keep using the in-memory scheduler and behave exactly as before. + * Turn on the durable scheduler. On by default. Set it to false to go back to + * the in-memory scheduler. * * When on, scheduled runs are stored in the database before they execute, so a * restart doesn't drop them and, across multiple instances, each run executes * once rather than once per instance. + * + * Schedule Trigger nodes move to the durable scheduler only while the workflow + * publication service (`N8N_USE_WORKFLOW_PUBLICATION_SERVICE`) is also on. + * Otherwise they keep using the in-memory scheduler. + * + * @deprecated The durable scheduler is now the default. This variable and the + * in-memory scheduler will be removed in a future version. */ @Env('N8N_SCHEDULER_ENABLED') - enabled: boolean = false; + enabled: boolean = true; /** * How far into the future, in seconds, the scheduler works out and records the @@ -239,7 +247,7 @@ export class SchedulerConfig { /** * How a Schedule Trigger node's "every N seconds/minutes" schedules run under - * the durable scheduler. Defaults to `legacy`. + * the durable scheduler. Defaults to `new`. * * - `legacy`: fires stay aligned to the clock (on the minute, on the hour) and * match the in-memory scheduler exactly. @@ -251,14 +259,16 @@ export class SchedulerConfig { * for example, leaves a 4-second gap across each minute boundary); `new` keeps * a uniform gap throughout. * - * `legacy` is the default so timing is unchanged while the durable scheduler - * rolls out; `new` is the intended future default. Only "every N - * seconds/minutes" schedules are affected: longer schedules (every N - * hours/days/weeks/months) and raw cron expressions run the same way under - * either setting. + * Set it to `legacy` to keep the clock-aligned timing of the in-memory + * scheduler. Only "every N seconds/minutes" schedules are affected: longer + * schedules (every N hours/days/weeks/months) and raw cron expressions run the + * same way under either setting. + * + * @deprecated `new` is now the default. This variable and the `legacy` mode + * will be removed in a future version. */ @Env('N8N_SCHEDULER_TRIGGER_NODE_MODE', z.enum(['legacy', 'new'])) - triggerNodeMode: 'legacy' | 'new' = 'legacy'; + triggerNodeMode: 'legacy' | 'new' = 'new'; /** * Whether nodes that poll on a schedule (e.g. checking an inbox or API on an @@ -336,24 +346,6 @@ export class SchedulerConfig { @Env('N8N_SCHEDULER_AGENT_TASKS_ENABLED') enabledForAgentTasks: boolean = false; - /** - * Temporary escape hatch for the durable-scheduler rollout (preview to GA). - * Off by default; intended to be removed once the durable scheduler is GA. - * - * When on, the Schedule Trigger node shows a "Skip Durable Scheduler" toggle; a - * trigger with it checked keeps using the in-memory scheduler even while - * {@link enabled} is on, so an operator can move an individual schedule back - * while testing. When off, the toggle is hidden and every schedule follows - * {@link enabled}. - * - * Named with the `N8N_ENV_FEAT_` prefix so the frontend picks it up through the - * env-feature-flag channel that gates the node property's visibility. Only has - * an effect while {@link enabled} is on: with the durable scheduler off, every - * schedule already runs in memory. - */ - @Env('N8N_ENV_FEAT_SKIP_DURABLE_SCHEDULER') - allowSkipDurableScheduler: boolean = false; - /** * How many times a scheduled run may be reclaimed (for example after a crash) * or retried on error before it's given up on and dead-lettered. Defaults to diff --git a/packages/@n8n/config/src/configs/user-management.config.ts b/packages/@n8n/config/src/configs/user-management.config.ts index 3845cbeb1f2..910722ba130 100644 --- a/packages/@n8n/config/src/configs/user-management.config.ts +++ b/packages/@n8n/config/src/configs/user-management.config.ts @@ -97,6 +97,10 @@ export class TemplateConfig { /** Overrides default HTML template for the agent monthly budget alert (use full path) */ @Env('N8N_UM_EMAIL_TEMPLATES_AGENT_BUDGET_ALERT') 'agent-budget-alert': string = ''; + + /** Overrides default HTML template for notifying a workflow owner about migration findings (use full path) */ + @Env('N8N_UM_EMAIL_TEMPLATES_MIGRATION_FINDINGS') + 'migration-findings': string = ''; } const emailModeSchema = z.enum(['', 'smtp']); diff --git a/packages/@n8n/config/src/configs/workflow-history-compaction.config.ts b/packages/@n8n/config/src/configs/workflow-history-compaction.config.ts index dd8f1cc57a9..61e44aa4379 100644 --- a/packages/@n8n/config/src/configs/workflow-history-compaction.config.ts +++ b/packages/@n8n/config/src/configs/workflow-history-compaction.config.ts @@ -39,19 +39,4 @@ export class WorkflowHistoryCompactionConfig { /** Delay in milliseconds after processing `batchSize` versions before moving to the next workflow. */ @Env('N8N_WORKFLOW_HISTORY_COMPACTION_BATCH_DELAY_MS') batchDelayMs: number = 1_000; - - /** - * Whether to run a trim pass on startup (for example, to fix existing history or for development). - * - * @warning Blocking; can significantly increase startup time. - */ - @Env('N8N_WORKFLOW_HISTORY_COMPACTION_TRIM_ON_START_UP') - trimOnStartUp: boolean = false; - - /** - * Whether to skip the compaction pass that normally runs on startup. - * Scheduled runs are unaffected. Takes precedence over `trimOnStartUp`. - */ - @Env('N8N_WORKFLOW_HISTORY_COMPACTION_SKIP_ON_START_UP') - skipOnStartUp: boolean = false; } diff --git a/packages/@n8n/config/test/config.test.ts b/packages/@n8n/config/test/config.test.ts index c9e6d059da5..fcb89091ee6 100644 --- a/packages/@n8n/config/test/config.test.ts +++ b/packages/@n8n/config/test/config.test.ts @@ -183,6 +183,7 @@ describe('GlobalConfig', () => { 'email-change-requested': '', 'email-change-completed': '', 'agent-budget-alert': '', + 'migration-findings': '', }, }, }, @@ -221,6 +222,17 @@ describe('GlobalConfig', () => { disabled: false, path: 'api', swaggerUiDisabled: false, + rateLimit: { + enabled: false, + globalReadLimit: 1200, + globalReadWindowSeconds: 60, + globalWriteLimit: 300, + globalWriteWindowSeconds: 60, + endpointReadLimit: 600, + endpointReadWindowSeconds: 60, + endpointWriteLimit: 200, + endpointWriteWindowSeconds: 60, + }, }, templates: { enabled: true, @@ -389,8 +401,6 @@ describe('GlobalConfig', () => { promptVersion: '', nodeUsageEnabled: false, folderExplorationEnabled: false, - activationCapped: false, - activationLockMessageThreshold: 1, maxConcurrentRuns: -1, maxConcurrentRunsPerUser: -1, maxConcurrentSubAgents: -1, @@ -436,6 +446,7 @@ describe('GlobalConfig', () => { enabled: false, name: '', }, + suspendExecutionsOnShutdown: false, }, taskRunners: { mode: 'internal', @@ -486,7 +497,7 @@ describe('GlobalConfig', () => { interval: 3, }, scheduler: { - enabled: false, + enabled: true, materializationWindowSeconds: 60, materializationIntervalSeconds: 10, materializationTimeoutSeconds: 60, @@ -504,10 +515,9 @@ describe('GlobalConfig', () => { jitterRatio: 0.1, minIntervalSeconds: 0, maxConcurrentPasses: 10, - triggerNodeMode: 'legacy', + triggerNodeMode: 'new', enabledForPollTriggers: false, pollTimeoutSeconds: 45, - allowSkipDurableScheduler: false, maxAttempts: 5, taskTimeoutSeconds: 300, misfireGraceSeconds: 60, @@ -676,8 +686,6 @@ describe('GlobalConfig', () => { optimizingTimeWindowHours: 2, trimmingMinimumAgeDays: 6, trimmingTimeWindowDays: 2, - trimOnStartUp: false, - skipOnStartUp: false, }, expressionEngine: { engine: 'vm', @@ -739,6 +747,7 @@ describe('GlobalConfig', () => { sandboxTimeout: 300000, sandboxEphemeral: false, channelReconcileIntervalSeconds: 60, + whatsAppAllowTemporaryToken: false, }, } satisfies GlobalConfigShape; @@ -1009,6 +1018,64 @@ describe('GlobalConfig', () => { }); }); + describe('public API rate limit config', () => { + it('should read the rate limit settings from env variables', () => { + process.env = { + N8N_PUBLIC_API_RATE_LIMIT_ENABLED: 'true', + N8N_PUBLIC_API_RATE_LIMIT_GLOBAL_READ_LIMIT: '100', + N8N_PUBLIC_API_RATE_LIMIT_GLOBAL_READ_WINDOW_SECONDS: '10', + N8N_PUBLIC_API_RATE_LIMIT_GLOBAL_WRITE_LIMIT: '50', + N8N_PUBLIC_API_RATE_LIMIT_GLOBAL_WRITE_WINDOW_SECONDS: '20', + N8N_PUBLIC_API_RATE_LIMIT_ENDPOINT_READ_LIMIT: '30', + N8N_PUBLIC_API_RATE_LIMIT_ENDPOINT_READ_WINDOW_SECONDS: '30', + N8N_PUBLIC_API_RATE_LIMIT_ENDPOINT_WRITE_LIMIT: '10', + N8N_PUBLIC_API_RATE_LIMIT_ENDPOINT_WRITE_WINDOW_SECONDS: '40', + }; + const config = Container.get(GlobalConfig); + expect(config.publicApi.rateLimit).toEqual({ + enabled: true, + globalReadLimit: 100, + globalReadWindowSeconds: 10, + globalWriteLimit: 50, + globalWriteWindowSeconds: 20, + endpointReadLimit: 30, + endpointReadWindowSeconds: 30, + endpointWriteLimit: 10, + endpointWriteWindowSeconds: 40, + }); + }); + + it('should accept a limit of 0', () => { + process.env = { N8N_PUBLIC_API_RATE_LIMIT_ENDPOINT_READ_LIMIT: '0' }; + const config = Container.get(GlobalConfig); + expect(config.publicApi.rateLimit.endpointReadLimit).toBe(0); + }); + + it.each(['-1', '1.5', 'abc'])( + 'should reject a limit of %s and fall back to the default', + (value) => { + process.env = { N8N_PUBLIC_API_RATE_LIMIT_GLOBAL_WRITE_LIMIT: value }; + const config = Container.get(GlobalConfig); + expect(config.publicApi.rateLimit.globalWriteLimit).toBe(300); + expect(consoleWarnMock).toHaveBeenCalledWith( + expect.stringContaining('N8N_PUBLIC_API_RATE_LIMIT_GLOBAL_WRITE_LIMIT'), + ); + }, + ); + + it.each(['0', '-1', '1.5'])( + 'should reject a window of %s and fall back to the default', + (value) => { + process.env = { N8N_PUBLIC_API_RATE_LIMIT_ENDPOINT_WRITE_WINDOW_SECONDS: value }; + const config = Container.get(GlobalConfig); + expect(config.publicApi.rateLimit.endpointWriteWindowSeconds).toBe(60); + expect(consoleWarnMock).toHaveBeenCalledWith( + expect.stringContaining('N8N_PUBLIC_API_RATE_LIMIT_ENDPOINT_WRITE_WINDOW_SECONDS'), + ); + }, + ); + }); + describe('data table cleanup interval config validation', () => { it('should accept a positive N8N_DATA_TABLES_CLEANUP_INTERVAL_MS', () => { process.env = { N8N_DATA_TABLES_CLEANUP_INTERVAL_MS: '30000' }; diff --git a/packages/@n8n/constants/package.json b/packages/@n8n/constants/package.json index 7b52d79fac4..0d84aa7d646 100644 --- a/packages/@n8n/constants/package.json +++ b/packages/@n8n/constants/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/constants", - "version": "0.41.0", + "version": "0.42.0", "scripts": { "clean": "rimraf dist .turbo", "dev": "pnpm watch", diff --git a/packages/@n8n/constants/src/index.ts b/packages/@n8n/constants/src/index.ts index eecc05ecf3c..f082ef6e646 100644 --- a/packages/@n8n/constants/src/index.ts +++ b/packages/@n8n/constants/src/index.ts @@ -58,6 +58,7 @@ export const LICENSE_FEATURES = { OTEL_CUSTOM_SPAN_ATTRIBUTES: 'feat:otel:customSpanAttributes', WORKFLOW_REVIEWS: 'feat:workflowReviews', WORKER_POOLS: 'feat:workerPools', + TRUSTED_SOURCE_MANAGE: 'feat:trustedSourceManage', } as const; export const LICENSE_QUOTAS = { diff --git a/packages/@n8n/create-node/package.json b/packages/@n8n/create-node/package.json index 1928a2318a4..f5da39828ab 100644 --- a/packages/@n8n/create-node/package.json +++ b/packages/@n8n/create-node/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/create-node", - "version": "0.51.0", + "version": "0.52.0", "description": "Official CLI to create new community nodes for n8n", "bin": { "create-node": "bin/create-node.cjs" diff --git a/packages/@n8n/db/package.json b/packages/@n8n/db/package.json index 21bfdce39b5..865afda0980 100644 --- a/packages/@n8n/db/package.json +++ b/packages/@n8n/db/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/db", - "version": "1.43.0", + "version": "1.44.0", "scripts": { "clean": "rimraf dist .turbo .tmp-schema-docs", "gen:migration-index": "node scripts/generate-migration-index.mjs", diff --git a/packages/@n8n/db/src/entities/types-db.ts b/packages/@n8n/db/src/entities/types-db.ts index dcb860b3d5b..19dc00e59ef 100644 --- a/packages/@n8n/db/src/entities/types-db.ts +++ b/packages/@n8n/db/src/entities/types-db.ts @@ -19,6 +19,7 @@ import type { } from 'n8n-workflow'; import { z } from 'zod'; +import type { OperationContext } from '../services/transaction'; import type { CredentialUsageScope, CredentialsEntity } from './credentials-entity'; import type { ExecutionDataStorageLocation } from './execution-entity'; import type { Folder } from './folder'; @@ -458,6 +459,7 @@ export type AuthenticationInformation = { export interface TokenGrant { scopes: string[]; apiKeyScopes?: string[]; + apiKeyId?: string; actor?: User; subject: User; } @@ -475,6 +477,8 @@ export type AuthenticatedRequest< 'push-ref': string; }; tokenGrant?: TokenGrant; + /** Set by the authentication edge; controllers thread it into services as `ctx`. */ + ctx?: OperationContext; }; export function isAuthenticatedRequest(req: express.Request): req is AuthenticatedRequest { diff --git a/packages/@n8n/db/src/migrations/common/1791809300081-MigrateAgentMcpToolPermissions.ts b/packages/@n8n/db/src/migrations/common/1791809300081-MigrateAgentMcpToolPermissions.ts new file mode 100644 index 00000000000..aee43fad034 --- /dev/null +++ b/packages/@n8n/db/src/migrations/common/1791809300081-MigrateAgentMcpToolPermissions.ts @@ -0,0 +1,217 @@ +import { z } from 'zod'; + +import type { IrreversibleMigration, MigrationContext } from '../migration-types'; + +const permissionSchema = z.enum(['always_allow', 'require_approval', 'blocked']); +const toolNamesSchema = z.array(z.string().min(1)); +const legacyApprovalSchema = z.discriminatedUnion('mode', [ + z.object({ mode: z.literal('global') }).strict(), + z.object({ mode: z.literal('selected'), tools: toolNamesSchema }).strict(), +]); +const legacyFilterSchema = z.discriminatedUnion('mode', [ + z.object({ mode: z.literal('allow'), tools: toolNamesSchema }).strict(), + z.object({ mode: z.literal('exclude'), tools: toolNamesSchema }).strict(), +]); + +type Permission = z.infer; +type LegacyApproval = z.infer; +type LegacyFilter = z.infer; + +type ConfigRow = { + id: string; + schema: string | Record; +}; + +type MigrationResult = + | { status: 'unchanged' } + | { status: 'malformed'; reason: string } + | { status: 'migrated'; schema: Record }; + +const tables = [ + { name: 'agents', idColumn: 'id' }, + { name: 'agent_history', idColumn: 'versionId' }, +] as const; + +function isRecord(value: unknown): value is Record { + return typeof value === 'object' && value !== null && !Array.isArray(value); +} + +function parseLegacyApproval(value: unknown): LegacyApproval | null { + const result = legacyApprovalSchema.safeParse(value); + return result.success ? result.data : null; +} + +function parseLegacyFilter(value: unknown): LegacyFilter | null { + const result = legacyFilterSchema.safeParse(value); + return result.success ? result.data : null; +} + +function permissionForTool(toolName: string, approval: LegacyApproval | undefined): Permission { + if (approval?.mode === 'global') return 'require_approval'; + if (approval?.mode === 'selected' && approval.tools.includes(toolName)) { + return 'require_approval'; + } + return 'always_allow'; +} + +function migrateServer(server: unknown): Record | null { + if (!isRecord(server)) return null; + + const hasLegacyFields = Object.hasOwn(server, 'toolFilter') || Object.hasOwn(server, 'approval'); + if (Object.hasOwn(server, 'toolPermissions')) { + if (!hasLegacyFields) return server; + const rest = { ...server }; + delete rest.toolFilter; + delete rest.approval; + return rest; + } + + const approval = Object.hasOwn(server, 'approval') + ? parseLegacyApproval(server.approval) + : undefined; + const filter = Object.hasOwn(server, 'toolFilter') + ? parseLegacyFilter(server.toolFilter) + : undefined; + // null when parsing failed + if (approval === null || filter === null) return null; + + const baseline: Permission = approval?.mode === 'global' ? 'require_approval' : 'always_allow'; + const categories = + filter?.mode === 'allow' + ? { read: 'blocked' as const, write: 'blocked' as const } + : { read: baseline, write: baseline }; + const toolPermissions = new Map(); + + if (approval?.mode === 'selected' && filter?.mode !== 'allow') { + for (const toolName of approval.tools) { + toolPermissions.set(toolName, 'require_approval'); + } + } + if (filter?.mode === 'allow') { + for (const toolName of filter.tools) { + toolPermissions.set(toolName, permissionForTool(toolName, approval)); + } + } + if (filter?.mode === 'exclude') { + for (const toolName of filter.tools) { + toolPermissions.set(toolName, 'blocked'); + } + } + + const rest = { ...server }; + delete rest.toolFilter; + delete rest.approval; + return { + ...rest, + toolPermissions: { + categories, + ...(toolPermissions.size > 0 ? { tools: Object.fromEntries(toolPermissions) } : {}), + }, + }; +} + +function migrateConfig(value: unknown): MigrationResult { + if (!isRecord(value)) return { status: 'malformed', reason: 'schema is not an object' }; + if (!Object.hasOwn(value, 'mcpServers')) return { status: 'unchanged' }; + if (!Array.isArray(value.mcpServers)) { + return { status: 'malformed', reason: 'mcpServers is not an array' }; + } + + const migratedServers: Array> = []; + let changed = false; + for (const server of value.mcpServers) { + const migrated = migrateServer(server); + if (!migrated) { + return { status: 'malformed', reason: 'mcpServers contains an invalid entry' }; + } + migratedServers.push(migrated); + changed ||= migrated !== server; + } + + return changed + ? { status: 'migrated', schema: { ...value, mcpServers: migratedServers } } + : { status: 'unchanged' }; +} + +/** + * Replaces legacy MCP tool filters and approval settings with tool permissions. + * + * The migration processes current and historical agent configs in batches. It + * validates every MCP server before it updates a row, preserves unrelated + * fields, and skips malformed rows instead of applying a partial conversion. + * + * The migration prefilters rows by the presence of the `mcpServers` key in the schema. + */ +export class MigrateAgentMcpToolPermissions1791809300081 implements IrreversibleMigration { + async up(context: MigrationContext) { + for (const table of tables) { + await this.migrateTable(context, table.name, table.idColumn); + } + } + + private async migrateTable( + { + escape, + isPostgres, + logger, + migrationName, + parseJson, + runInBatches, + runQuery, + }: MigrationContext, + tableName: (typeof tables)[number]['name'], + idColumnName: (typeof tables)[number]['idColumn'], + ) { + const table = escape.tableName(tableName); + const idColumn = escape.columnName(idColumnName); + const schemaColumn = escape.columnName('schema'); + const candidateFilter = isPostgres + ? `${schemaColumn}::jsonb ? 'mcpServers'` + : `${schemaColumn} LIKE '%"mcpServers"%'`; + let processedCount = 0; + let migratedCount = 0; + let skippedCount = 0; + + await runInBatches( + `SELECT ${idColumn} AS id, ${schemaColumn} AS schema + FROM ${table} + WHERE ${schemaColumn} IS NOT NULL AND ${candidateFilter} + ORDER BY ${idColumn}`, + async (rows) => { + for (const row of rows) { + processedCount++; + let schema: unknown; + try { + schema = parseJson(row.schema); + } catch (error) { + skippedCount++; + logger.warn( + `[${migrationName}] Skipped malformed ${tableName} row ${row.id}: ${error instanceof Error ? error.message : 'invalid JSON'}`, + ); + continue; + } + + const result = migrateConfig(schema); + if (result.status === 'unchanged') continue; + if (result.status === 'malformed') { + skippedCount++; + logger.warn( + `[${migrationName}] Skipped malformed ${tableName} row ${row.id}: ${result.reason}`, + ); + continue; + } + + await runQuery(`UPDATE ${table} SET ${schemaColumn} = :schema WHERE ${idColumn} = :id`, { + id: row.id, + schema: JSON.stringify(result.schema), + }); + migratedCount++; + } + }, + ); + + logger.info( + `[${migrationName}] Processed ${processedCount} ${tableName} rows; migrated ${migratedCount}; skipped ${skippedCount} malformed rows.`, + ); + } +} diff --git a/packages/@n8n/db/src/migrations/common/1791818723687-CreateSkillsHubTables.ts b/packages/@n8n/db/src/migrations/common/1791818723687-CreateSkillsHubTables.ts new file mode 100644 index 00000000000..88b9a830ccc --- /dev/null +++ b/packages/@n8n/db/src/migrations/common/1791818723687-CreateSkillsHubTables.ts @@ -0,0 +1,197 @@ +import type { MigrationContext, ReversibleMigration } from '../migration-types'; + +const SKILL_TABLE = 'skill'; +const SKILL_VERSION_TABLE = 'skill_version'; +const SKILL_FILE_TABLE = 'skill_file'; +const AGENT_SKILL_DEPENDENCY_TABLE = 'agent_skill_dependency'; +const AGENT_VERSION_SKILL_DEPENDENCY_TABLE = 'agent_version_skill_dependency'; + +/** + * The skills hub: skills live outside the agent row, so many agents can use one skill. + * A skill belongs to one target: a project (team or personal, for its agents), one agent + * (only that agent can use it; its project is the agent's), or the instance (neither set). Its name and + * content live in numbered, immutable versions: a Save that changes the content creates + * the next one, agents read the latest, and agent publishes pin the one they ran. + */ +export class CreateSkillsHubTables1791818723687 implements ReversibleMigration { + async up(context: MigrationContext) { + await this.createSkillTable(context); + await this.createSkillVersionTable(context); + await this.createSkillFileTable(context); + await this.createAgentSkillDependencyTable(context); + await this.createAgentVersionSkillDependencyTable(context); + } + + async down({ schemaBuilder: { dropTable } }: MigrationContext) { + await dropTable(AGENT_VERSION_SKILL_DEPENDENCY_TABLE); + await dropTable(AGENT_SKILL_DEPENDENCY_TABLE); + await dropTable(SKILL_FILE_TABLE); + await dropTable(SKILL_VERSION_TABLE); + await dropTable(SKILL_TABLE); + } + + private async createSkillTable({ + schemaBuilder: { createTable, column }, + tablePrefix, + escape, + }: MigrationContext) { + // The id is the identity. Names live on skill_version and may repeat. + await createTable(SKILL_TABLE) + .withColumns( + column('id').varchar(36).primary.comment('skill_, the same format agents use'), + column('projectId') + .varchar(36) + .comment('Set for a project skill, team or personal. NULL otherwise'), + column('agentId') + .varchar(36) + .comment( + 'Set when only this agent can use the skill. projectId is then NULL: the agent holds the project', + ), + // No CHECK on the values: new sources (upload, Git sync, AI-written) must not + // recreate the table on SQLite. The service validates them. + column('source') + .varchar(16) + .notNull.comment( + 'How the skill was created, set by the server: "ui" (the skills hub) or "agent" (the agent builder or the copy of agent skills)', + ), + column('createdById').uuid.comment('Author. NULL after the author is deleted'), + ) + .withTimestamps.withIndexOn(['projectId']) + .withIndexOn(['agentId']) + .withForeignKey('projectId', { + tableName: 'project', + columnName: 'id', + onDelete: 'CASCADE', + }) + // An agent skill goes with its agent, as agent skills do today. + .withForeignKey('agentId', { + tableName: 'agents', + columnName: 'id', + onDelete: 'CASCADE', + }) + .withForeignKey('createdById', { + tableName: 'user', + columnName: 'id', + onDelete: 'SET NULL', + }) + // One target. An agent skill takes its project from the agent, so the two cannot + // disagree, and the skill follows the agent if the agent moves. + .withCheck( + `CHK_${tablePrefix}skill_single_target`, + `${escape.columnName('agentId')} IS NULL OR ${escape.columnName('projectId')} IS NULL`, + ); + } + + private async createSkillVersionTable({ + schemaBuilder: { createTable, column }, + tablePrefix, + escape, + }: MigrationContext) { + await createTable(SKILL_VERSION_TABLE) + .withColumns( + column('id').uuid.primary, + column('skillId').varchar(36).notNull, + column('version').int.notNull.comment( + '1..n per skill. A Save that changes the content adds one; none ever changes', + ), + column('name') + .varchar(128) + .notNull.comment('Free-text skill name, as it was when this version was saved'), + column('description').varchar(1024).notNull, + column('instructions').text.notNull, + column('frontmatter').json.comment( + 'SKILL.md frontmatter fields other than name and description, e.g. allowed-tools', + ), + column('contentHash') + .varchar(64) + .notNull.comment( + 'sha256 of name, description, instructions, frontmatter and files. Save creates no version when the content matches the latest one', + ), + column('createdById').uuid.comment('Author. NULL after the author is deleted'), + ) + .withTimestamps.withUniqueConstraintOn(['skillId', 'version']) + .withCheck(`CHK_${tablePrefix}skill_version_version`, `${escape.columnName('version')} > 0`) + .withForeignKey('skillId', { + tableName: SKILL_TABLE, + columnName: 'id', + onDelete: 'CASCADE', + }) + .withForeignKey('createdById', { + tableName: 'user', + columnName: 'id', + onDelete: 'SET NULL', + }); + } + + private async createSkillFileTable({ schemaBuilder: { createTable, column } }: MigrationContext) { + await createTable(SKILL_FILE_TABLE) + .withColumns( + column('skillVersionId').uuid.primary, + column('path').varchar(512).primary.comment('Relative path, references/*.md in v1'), + column('content').text.notNull, + ) + .withTimestamps.withForeignKey('skillVersionId', { + tableName: SKILL_VERSION_TABLE, + columnName: 'id', + onDelete: 'CASCADE', + }); + } + + private async createAgentSkillDependencyTable({ + schemaBuilder: { createTable, column }, + }: MigrationContext) { + await createTable(AGENT_SKILL_DEPENDENCY_TABLE) + .withColumns( + column('agentId').varchar(36).primary, + column('skillId').varchar(36).primary, + // An agent draft normally follows the skill's latest saved version. A revert + // pins the version it had; the pin clears when the skill is saved again. + column('skillVersionId').uuid.comment( + 'Set when the agent draft pins a saved version. NULL = follows the latest saved version', + ), + ) + .withCreatedAt.withIndexOn(['skillId']) + .withForeignKey('agentId', { tableName: 'agents', columnName: 'id', onDelete: 'CASCADE' }) + .withForeignKey('skillId', { tableName: SKILL_TABLE, columnName: 'id', onDelete: 'CASCADE' }) + // NO ACTION keeps a pinned version from being deleted on its own. A skill delete + // removes these rows first, through the skillId cascade. + .withForeignKey('skillVersionId', { + tableName: SKILL_VERSION_TABLE, + columnName: 'id', + onDelete: 'NO ACTION', + }); + } + + private async createAgentVersionSkillDependencyTable({ + schemaBuilder: { createTable, column }, + }: MigrationContext) { + await createTable(AGENT_VERSION_SKILL_DEPENDENCY_TABLE) + .withColumns( + column('agentVersionId').varchar(36).primary, + column('skillId').varchar(36).primary, + column('skillVersionId').uuid.notNull, + ) + .withCreatedAt.withIndexOn(['skillId']) + // This table grows with every publish, and "used by" reads it by version. + .withIndexOn(['skillVersionId']) + .withForeignKey('agentVersionId', { + tableName: 'agent_history', + columnName: 'versionId', + onDelete: 'CASCADE', + }) + // CASCADE, as in agent_skill_dependency: a user or project delete removes a skill + // and the agents that pin it, and Postgres checks NO ACTION before the agent + // cascade runs. The service refuses to delete a skill that is in use. + .withForeignKey('skillId', { + tableName: SKILL_TABLE, + columnName: 'id', + onDelete: 'CASCADE', + }) + // NO ACTION keeps a pinned version from being deleted on its own. + .withForeignKey('skillVersionId', { + tableName: SKILL_VERSION_TABLE, + columnName: 'id', + onDelete: 'NO ACTION', + }); + } +} diff --git a/packages/@n8n/db/src/repositories/__tests__/shared-workflow.repository.test.ts b/packages/@n8n/db/src/repositories/__tests__/shared-workflow.repository.test.ts index a87b2f036f8..6908b2a4d1d 100644 --- a/packages/@n8n/db/src/repositories/__tests__/shared-workflow.repository.test.ts +++ b/packages/@n8n/db/src/repositories/__tests__/shared-workflow.repository.test.ts @@ -66,11 +66,11 @@ describe('SharedWorkflowRepository', () => { it('finds workflow IDs accessible through project and workflow roles', async () => { entityManager.find.mockResolvedValue(rows); - const result = await sharedWorkflowRepository.findWorkflowIdsAccessibleToUser( - 'user-1', - ['workflow:owner'], - ['project:viewer'], - ); + const result = await sharedWorkflowRepository.findWorkflowIdsAccessibleToUser({ + userId: 'user-1', + workflowRoleSlugs: ['workflow:owner'], + projectRoleSlugs: ['project:viewer'], + }); expect(entityManager.find).toHaveBeenCalledWith(SharedWorkflow, { select: ['workflowId'], @@ -87,6 +87,32 @@ describe('SharedWorkflowRepository', () => { expect(result).toEqual(['workflow-1', 'workflow-2']); }); + it('limits workflow IDs accessible to a user to a project', async () => { + entityManager.find.mockResolvedValue(rows); + + const result = await sharedWorkflowRepository.findWorkflowIdsAccessibleToUser({ + userId: 'user-1', + workflowRoleSlugs: ['workflow:owner'], + projectRoleSlugs: ['project:viewer'], + projectId: 'project-1', + }); + + expect(entityManager.find).toHaveBeenCalledWith(SharedWorkflow, { + select: ['workflowId'], + where: { + role: In(['workflow:owner']), + project: { + id: 'project-1', + projectRelations: { + userId: 'user-1', + role: { slug: In(['project:viewer']) }, + }, + }, + }, + }); + expect(result).toEqual(['workflow-1', 'workflow-2']); + }); + it('finds workflow IDs shared with a user', async () => { entityManager.find.mockResolvedValue(rows); diff --git a/packages/@n8n/db/src/repositories/__tests__/workflow.repository.test.ts b/packages/@n8n/db/src/repositories/__tests__/workflow.repository.test.ts index 2db05a45e69..ad91175d441 100644 --- a/packages/@n8n/db/src/repositories/__tests__/workflow.repository.test.ts +++ b/packages/@n8n/db/src/repositories/__tests__/workflow.repository.test.ts @@ -1,5 +1,6 @@ import { GlobalConfig } from '@n8n/config'; import { In, IsNull, MoreThan, Not, type SelectQueryBuilder } from '@n8n/typeorm'; +import type { IWorkflowSettings } from 'n8n-workflow'; import type { Mock, Mocked } from 'vitest'; import { mock } from 'vitest-mock-extended'; @@ -840,4 +841,270 @@ describe('WorkflowRepository', () => { expect(mockExecute).toHaveBeenCalled(); }); }); + + describe('caller allowlist purge', () => { + let writes: Array<{ id: string; callerIds: string }>; + let writtenSettings: Array; + let selectQb: { where: Mock; andWhere: Mock; setLock: Mock }; + + const stubCandidates = (candidates: Array>) => { + writes = []; + writtenSettings = []; + + const select = { + select: vi.fn(), + where: vi.fn(), + andWhere: vi.fn(), + setLock: vi.fn(), + getMany: vi.fn().mockResolvedValue(candidates), + }; + select.select.mockReturnValue(select); + select.where.mockReturnValue(select); + select.andWhere.mockReturnValue(select); + select.setLock.mockReturnValue(select); + + let pendingId = ''; + let pendingCallerIds = ''; + let pendingSettings: IWorkflowSettings | undefined; + const update = { + update: vi.fn(), + set: vi.fn(), + where: vi.fn(), + setParameter: vi.fn(), + execute: vi.fn(async () => { + writes.push({ id: pendingId, callerIds: pendingCallerIds }); + writtenSettings.push(pendingSettings); + }), + }; + update.update.mockReturnValue(update); + // Postgres writes the whole document, SQLite the one key through a parameter. + update.set.mockImplementation((values: { settings: unknown }) => { + if (typeof values.settings === 'object' && values.settings !== null) { + pendingSettings = values.settings as IWorkflowSettings; + pendingCallerIds = pendingSettings.callerIds ?? ''; + } + return update; + }); + update.where.mockImplementation((_sql: string, parameters: { workflowId: string }) => { + pendingId = parameters.workflowId; + return update; + }); + update.setParameter.mockImplementation((_name: string, value: string) => { + pendingCallerIds = value; + return update; + }); + + vi.mocked(entityManager.createQueryBuilder).mockImplementation(((...args: unknown[]) => + args.length > 0 ? select : update) as never); + + transactionRunner.run.mockImplementation( + async (ctx: unknown, fn: (c: unknown) => Promise) => await fn(ctx), + ); + + selectQb = select; + return select; + }; + + it('removes the entry and keeps the rest in order, whatever whitespace separates them', async () => { + stubCandidates([ + { + id: 'subworkflow-1', + settings: { callerPolicy: 'workflowsFromAList', callerIds: 'first,\n second , ,\tthird' }, + }, + ]); + + await workflowRepository.removeFromCallerAllowlists(['second'], {}); + + expect(writes).toEqual([{ id: 'subworkflow-1', callerIds: 'first,third' }]); + }); + + it('rewrites only the allowlists that hold the id as an entry of its own', async () => { + stubCandidates([ + { + id: 'subworkflow-1', + settings: { callerPolicy: 'workflowsFromAList', callerIds: 'abc,abcdef' }, + }, + { + id: 'subworkflow-2', + settings: { callerPolicy: 'workflowsFromAList', callerIds: 'abcdef' }, + }, + { id: 'subworkflow-3', settings: { callerPolicy: 'workflowsFromAList' } }, + ]); + + await workflowRepository.removeFromCallerAllowlists(['abc'], {}); + + expect(writes).toEqual([{ id: 'subworkflow-1', callerIds: 'abcdef' }]); + }); + + it('leaves an allowlist alone when the id only appears inside another entry', async () => { + stubCandidates([ + { + id: 'subworkflow-1', + settings: { callerPolicy: 'workflowsFromAList', callerIds: 'abc-1, abc-2' }, + }, + ]); + + await workflowRepository.removeFromCallerAllowlists(['abc'], {}); + + expect(writes).toEqual([]); + }); + + it('rewrites every workflow that names the id', async () => { + stubCandidates([ + { + id: 'subworkflow-1', + settings: { callerPolicy: 'workflowsFromAList', callerIds: 'first,second' }, + }, + { + id: 'subworkflow-2', + settings: { callerPolicy: 'workflowsFromAList', callerIds: 'second,third' }, + }, + ]); + + await workflowRepository.removeFromCallerAllowlists(['second'], {}); + + expect(writes).toEqual([ + { id: 'subworkflow-1', callerIds: 'first' }, + { id: 'subworkflow-2', callerIds: 'third' }, + ]); + }); + + it('takes every id out of one allowlist in a single write', async () => { + stubCandidates([ + { + id: 'subworkflow-1', + settings: { callerPolicy: 'workflowsFromAList', callerIds: 'first,second,third' }, + }, + ]); + + await workflowRepository.removeFromCallerAllowlists(['first', 'third'], {}); + + expect(writes).toEqual([{ id: 'subworkflow-1', callerIds: 'second' }]); + }); + + it('reads the candidates once, whatever the batch size, and locks only the ones it rewrites', async () => { + const select = stubCandidates([ + { + id: 'subworkflow-1', + settings: { callerPolicy: 'workflowsFromAList', callerIds: 'one,first' }, + }, + { + id: 'subworkflow-2', + settings: { callerPolicy: 'workflowsFromAList', callerIds: 'first' }, + }, + ]); + + await workflowRepository.removeFromCallerAllowlists(['one', 'two'], {}); + + expect(select.where).toHaveBeenCalledTimes(2); + expect(select.where).toHaveBeenNthCalledWith(1, expect.stringContaining('callerIds')); + expect(select.where).toHaveBeenNthCalledWith(2, 'workflow.id IN (:...ids)', { + ids: ['subworkflow-1'], + }); + expect(select.setLock).toHaveBeenCalledTimes(1); + expect(select.setLock).toHaveBeenCalledWith('pessimistic_write'); + expect(writes).toEqual([{ id: 'subworkflow-1', callerIds: 'first' }]); + }); + + it('locks nothing when no allowlist names a removed id', async () => { + const select = stubCandidates([ + { + id: 'subworkflow-1', + settings: { callerPolicy: 'workflowsFromAList', callerIds: 'first' }, + }, + ]); + + await workflowRepository.removeFromCallerAllowlists(['one'], {}); + + expect(select.setLock).not.toHaveBeenCalled(); + expect(writes).toEqual([]); + }); + + it('matches candidates on the stored document, never on a value read out of it', async () => { + const select = stubCandidates([]); + + await workflowRepository.removeFromCallerAllowlists(['one'], {}); + + expect(select.where).toHaveBeenCalledWith('workflow.settings::text LIKE \'%"callerIds"%\''); + }); + + it('keeps a value the binary JSON form has no room for', async () => { + const noBinaryJsonForm = String.fromCharCode(0); + stubCandidates([ + { + id: 'subworkflow-1', + settings: { + callerPolicy: 'workflowsFromAList', + callerIds: 'first,second', + errorWorkflow: `error-workflow${noBinaryJsonForm}`, + }, + }, + ]); + + await workflowRepository.removeFromCallerAllowlists(['second'], {}); + + expect(writtenSettings).toEqual([ + { + callerPolicy: 'workflowsFromAList', + callerIds: 'first', + errorWorkflow: `error-workflow${noBinaryJsonForm}`, + }, + ]); + }); + + it('purges a row that exists at an id being removed', async () => { + stubCandidates([ + { + id: 'recreated-1', + settings: { callerPolicy: 'workflowsFromAList', callerIds: 'first,second' }, + }, + ]); + + await workflowRepository.removeFromCallerAllowlists(['recreated-1', 'second'], {}); + + expect(writes).toEqual([{ id: 'recreated-1', callerIds: 'first' }]); + }); + + it('writes nothing when given no ids', async () => { + stubCandidates([]); + + await workflowRepository.removeFromCallerAllowlists([], {}); + + expect(selectQb.where).not.toHaveBeenCalled(); + expect(writes).toEqual([]); + }); + + it('removes only the entries naming an id without a row', async () => { + stubCandidates([ + { + id: 'subworkflow-1', + settings: { callerPolicy: 'workflowsFromAList', callerIds: 'deleted,survivor,other' }, + }, + ]); + vi.mocked(entityManager.find).mockResolvedValue([{ id: 'survivor' }, { id: 'other' }]); + + await workflowRepository.removeMissingFromCallerAllowlists({}); + + expect(entityManager.find).toHaveBeenCalledWith(WorkflowEntity, { + select: ['id'], + where: { id: In(['deleted', 'survivor', 'other']) }, + }); + expect(writes).toEqual([{ id: 'subworkflow-1', callerIds: 'survivor,other' }]); + }); + + it('locks and writes nothing when every named id has a row', async () => { + const select = stubCandidates([ + { + id: 'subworkflow-1', + settings: { callerPolicy: 'workflowsFromAList', callerIds: 'first,second' }, + }, + ]); + vi.mocked(entityManager.find).mockResolvedValue([{ id: 'first' }, { id: 'second' }]); + + await workflowRepository.removeMissingFromCallerAllowlists({}); + + expect(select.setLock).not.toHaveBeenCalled(); + expect(writes).toEqual([]); + }); + }); }); diff --git a/packages/@n8n/db/src/repositories/secrets-provider-connection.repository.ee.ts b/packages/@n8n/db/src/repositories/secrets-provider-connection.repository.ee.ts index 5953e3e37bf..27af55ee0f1 100644 --- a/packages/@n8n/db/src/repositories/secrets-provider-connection.repository.ee.ts +++ b/packages/@n8n/db/src/repositories/secrets-provider-connection.repository.ee.ts @@ -1,5 +1,6 @@ import { Service } from '@n8n/di'; import { Brackets, DataSource, In, Repository } from '@n8n/typeorm'; +import type { EntityManager } from '@n8n/typeorm'; import { SecretsProviderConnection, SharedCredentials } from '../entities'; @@ -22,10 +23,14 @@ export class SecretsProviderConnectionRepository extends Repository { + /** Pass the active transaction's manager to avoid acquiring a second pool connection mid-transaction. */ + async findIdsByProviderKeys( + providerKeys: string[], + entityManager?: EntityManager, + ): Promise { if (providerKeys.length === 0) return []; - const connections = await this.find({ + const connections = await (entityManager ?? this.manager).find(SecretsProviderConnection, { select: ['id'], where: { providerKey: In(providerKeys) }, }); diff --git a/packages/@n8n/db/src/repositories/shared-workflow.repository.ts b/packages/@n8n/db/src/repositories/shared-workflow.repository.ts index cbc79236e12..41be247b750 100644 --- a/packages/@n8n/db/src/repositories/shared-workflow.repository.ts +++ b/packages/@n8n/db/src/repositories/shared-workflow.repository.ts @@ -41,15 +41,22 @@ export class SharedWorkflowRepository extends BaseRepository { return rows.map(({ workflowId }) => workflowId); } - async findWorkflowIdsAccessibleToUser( - userId: string, - workflowRoleSlugs: string[], - projectRoleSlugs: string[], - ): Promise { + async findWorkflowIdsAccessibleToUser({ + userId, + workflowRoleSlugs, + projectRoleSlugs, + projectId, + }: { + userId: string; + workflowRoleSlugs: string[]; + projectRoleSlugs: string[]; + projectId?: string; + }): Promise { const rows = await this.find({ where: { role: In(workflowRoleSlugs), project: { + id: projectId ?? undefined, projectRelations: { userId, role: { slug: In(projectRoleSlugs) }, diff --git a/packages/@n8n/db/src/repositories/workflow.repository.ts b/packages/@n8n/db/src/repositories/workflow.repository.ts index b75258cb06a..32ff83918e9 100644 --- a/packages/@n8n/db/src/repositories/workflow.repository.ts +++ b/packages/@n8n/db/src/repositories/workflow.repository.ts @@ -454,6 +454,136 @@ export class WorkflowRepository extends BaseRepository { } } + /** Remove every id in `workflowIds` from the `callerIds` allowlist of every other workflow. */ + async removeFromCallerAllowlists(workflowIds: string[], ctx: OperationContext): Promise { + if (workflowIds.length === 0) return; + + await this.runInTransaction(ctx, async (tx) => { + const candidates = await this.findCallerAllowlistCandidates(tx); + await this.purgeCallerAllowlists(candidates, new Set(workflowIds), tx); + }); + } + + /** Remove every id that has no workflow row from every `callerIds` allowlist. */ + async removeMissingFromCallerAllowlists(ctx: OperationContext): Promise { + await this.runInTransaction(ctx, async (tx) => { + const candidates = await this.findCallerAllowlistCandidates(tx); + const namedIds = [ + ...new Set(candidates.flatMap((workflow) => this.callerIdEntries(workflow))), + ]; + + const existingIds = new Set(); + for (const chunk of chunkIds(namedIds)) { + const existing = await tx.find(WorkflowEntity, { + select: ['id'], + where: { id: In(chunk) }, + }); + for (const { id } of existing) existingIds.add(id); + } + + const missingIds = new Set(namedIds.filter((id) => !existingIds.has(id))); + if (missingIds.size > 0) await this.purgeCallerAllowlists(candidates, missingIds, tx); + }); + } + + /** Rewrite the allowlists among `candidates` that name any of `removedIds`, under a row lock. */ + private async purgeCallerAllowlists( + candidates: WorkflowEntity[], + removedIds: Set, + tx: EntityManager, + ): Promise { + const affected = candidates.filter( + (workflow) => this.callerIdsWithout(workflow, removedIds) !== undefined, + ); + + for (const workflow of await this.lockCallerAllowlists(affected, tx)) { + const remaining = this.callerIdsWithout(workflow, removedIds); + if (remaining !== undefined) await this.writeCallerIds(workflow, remaining, tx); + } + } + + /** The non-empty, trimmed entries of the `callerIds` allowlist of `workflow`. */ + private callerIdEntries(workflow: WorkflowEntity): string[] { + const callerIds = workflow.settings?.callerIds; + if (typeof callerIds !== 'string') return []; + + return callerIds + .split(',') + .map((callerId) => callerId.trim()) + .filter((callerId) => callerId !== ''); + } + + /** The allowlist of `workflow` without `removedIds`, or `undefined` when it names none of them. */ + private callerIdsWithout(workflow: WorkflowEntity, removedIds: Set): string | undefined { + const entries = this.callerIdEntries(workflow); + if (!entries.some((callerId) => removedIds.has(callerId))) return undefined; + + return entries.filter((callerId) => !removedIds.has(callerId)).join(','); + } + + /** Find every workflow that has a `callerIds` allowlist. */ + private async findCallerAllowlistCandidates(tx: EntityManager): Promise { + // On Postgres, match the raw text rather than extract: the `json` column accepts characters, + // such as an escaped NUL, that extracting `callerIds` rejects with `unsupported Unicode + // escape sequence`, which fails the query for every row. + const hasAllowlist = + this.globalConfig.database.type === 'postgresdb' + ? 'workflow.settings::text LIKE \'%"callerIds"%\'' + : `${this.settingsTextValue('workflow.settings', 'callerIds')} IS NOT NULL`; + + return await tx + .createQueryBuilder(WorkflowEntity, 'workflow') + .select(['workflow.id', 'workflow.settings']) + .where(hasAllowlist) + .getMany(); + } + + /** Lock `workflows` until the transaction ends and re-read their settings under the lock. */ + private async lockCallerAllowlists( + workflows: WorkflowEntity[], + tx: EntityManager, + ): Promise { + // SQLite serialises writes, so what it read is already current. + if (this.globalConfig.database.type !== 'postgresdb') return workflows; + + const locked: WorkflowEntity[] = []; + for (const chunk of chunkIds(workflows.map(({ id }) => id))) { + locked.push( + ...(await tx + .createQueryBuilder(WorkflowEntity, 'workflow') + .select(['workflow.id', 'workflow.settings']) + .where('workflow.id IN (:...ids)', { ids: chunk }) + .setLock('pessimistic_write') + .getMany()), + ); + } + return locked; + } + + /** Store `callerIds` back on one workflow, keeping its other settings. */ + private async writeCallerIds( + workflow: WorkflowEntity, + callerIds: string, + tx: EntityManager, + ): Promise { + const update = tx + .createQueryBuilder() + .update(WorkflowEntity) + .where('id = :workflowId', { workflowId: workflow.id }); + + if (this.globalConfig.database.type === 'postgresdb') { + // `jsonb_set` rejects characters the `json` column accepts, so rewrite the whole document + // read under the row lock. + await update.set({ settings: { ...workflow.settings, callerIds } }).execute(); + return; + } + + await update + .set({ settings: () => "JSON_SET(COALESCE(settings, '{}'), '$.callerIds', :callerIds)" }) + .setParameter('callerIds', callerIds) + .execute(); + } + async findById(workflowId: string) { return await this.findOne({ where: { id: workflowId }, @@ -864,7 +994,6 @@ export class WorkflowRepository extends BaseRepository { onlySharedWithMe?: boolean; }, options: WorkflowListQueryOptions = {}, - callableForParentWorkflowId?: string, ) { if ( options.filter?.parentFolderId && @@ -884,18 +1013,8 @@ export class WorkflowRepository extends BaseRepository { } const [workflowsAndFolders, count] = await Promise.all([ - this.getWorkflowsAndFoldersUnionWithSharingSubquery( - user, - sharingOptions, - options, - callableForParentWorkflowId, - ), - this.getWorkflowsAndFoldersCountWithSharingSubquery( - user, - sharingOptions, - options, - callableForParentWorkflowId, - ), + this.getWorkflowsAndFoldersUnionWithSharingSubquery(user, sharingOptions, options), + this.getWorkflowsAndFoldersCountWithSharingSubquery(user, sharingOptions, options), ]); const isArchived = @@ -922,15 +1041,9 @@ export class WorkflowRepository extends BaseRepository { onlySharedWithMe?: boolean; }, options: WorkflowListQueryOptions = {}, - callableForParentWorkflowId?: string, ) { const { baseQuery, sortByColumn, sortByDirection } = - this.buildBaseUnionQueryWithSharingSubquery( - user, - sharingOptions, - options, - callableForParentWorkflowId, - ); + this.buildBaseUnionQueryWithSharingSubquery(user, sharingOptions, options); const query = this.buildUnionQuery(baseQuery, { sortByColumn, @@ -956,7 +1069,6 @@ export class WorkflowRepository extends BaseRepository { onlySharedWithMe?: boolean; }, options: WorkflowListQueryOptions = {}, - callableForParentWorkflowId?: string, ) { const { skip, take, ...baseQueryParameters } = options; @@ -964,7 +1076,6 @@ export class WorkflowRepository extends BaseRepository { user, sharingOptions, baseQueryParameters, - callableForParentWorkflowId, ); const response = await baseQuery @@ -986,7 +1097,6 @@ export class WorkflowRepository extends BaseRepository { onlySharedWithMe?: boolean; }, options: WorkflowListQueryOptions = {}, - callableForParentWorkflowId?: string, ) { // Common fields for both folders and workflows const commonFields = { @@ -1036,7 +1146,6 @@ export class WorkflowRepository extends BaseRepository { user, sharingOptions, workflowQueryParameters, - callableForParentWorkflowId, ).addSelect("'workflow'", 'resource'); const qb = this.manager.createQueryBuilder(); @@ -1155,14 +1264,8 @@ export class WorkflowRepository extends BaseRepository { onlySharedWithMe?: boolean; }, options: WorkflowListQueryOptions = {}, - callableForParentWorkflowId?: string, ): Promise { - const query = this.getManyQueryWithSharingSubquery( - user, - sharingOptions, - options, - callableForParentWorkflowId, - ); + const query = this.getManyQueryWithSharingSubquery(user, sharingOptions, options); const [workflows, count] = await query.getManyAndCount(); return { workflows, count }; @@ -1182,7 +1285,6 @@ export class WorkflowRepository extends BaseRepository { onlySharedWithMe?: boolean; }, options: WorkflowListQueryOptions = {}, - callableForParentWorkflowId?: string, ): SelectQueryBuilder { const qb = this.createQueryBuilder('workflow'); @@ -1200,21 +1302,9 @@ export class WorkflowRepository extends BaseRepository { sharingOptionsWithProjectId, ); - if (callableForParentWorkflowId) { - // Union: workflows readable by the user OR callable by the parent workflow. - const callableSubquery = this.buildCallablePolicySubquery(callableForParentWorkflowId); - qb.andWhere( - `(workflow.id IN (${sharedWorkflowSubquery.getQuery()}) OR workflow.id IN (${callableSubquery.getQuery()}))`, - ); - qb.setParameters({ - ...sharedWorkflowSubquery.getParameters(), - ...callableSubquery.getParameters(), - }); - } else { - // Apply the sharing filter using the subquery - qb.andWhere(`workflow.id IN (${sharedWorkflowSubquery.getQuery()})`); - qb.setParameters(sharedWorkflowSubquery.getParameters()); - } + // Apply the sharing filter using the subquery + qb.andWhere(`workflow.id IN (${sharedWorkflowSubquery.getQuery()})`); + qb.setParameters(sharedWorkflowSubquery.getParameters()); // Apply other filters // For personal project and shared-with-me cases, projectId is already handled in the subquery @@ -1238,70 +1328,98 @@ export class WorkflowRepository extends BaseRepository { } /** - * Build a subquery returning IDs of workflows whose callerPolicy permits the - * given `parentWorkflowId` to call them. + * List the workflows that `parentWorkflowId` can call as sub-workflows. The + * list holds the workflows the user can read, plus the workflows whose + * caller policy names the parent explicitly (`any`, or an allowlist that + * contains the parent id). + * + * Only a minimal set of columns is loaded, because the callable rows can + * belong to projects that the user has no access to. + */ + async findCallableSubworkflows( + user: User, + sharingOptions: { scopes: Scope[]; projectRoles: string[]; workflowRoles: string[] }, + parentWorkflowId: string, + options: { query?: string; triggerNodeTypes: string[]; skip: number; take: number }, + ): Promise<{ workflows: WorkflowEntity[]; count: number }> { + const sharedWorkflowSubquery = this.buildSharedWorkflowIdsSubquery(user, sharingOptions); + const callableSubquery = this.buildCallablePolicySubquery(parentWorkflowId); + + const qb = this.createQueryBuilder('workflow') + .select([ + 'workflow.id', + 'workflow.name', + 'workflow.activeVersionId', + 'workflow.isArchived', + 'workflow.updatedAt', + ]) + .leftJoin('workflow.shared', 'owner', 'owner.role = :callableOwnerRole', { + callableOwnerRole: 'workflow:owner', + }) + .leftJoin('owner.project', 'ownerProject') + .addSelect([ + 'owner.workflowId', + 'owner.projectId', + 'owner.role', + 'ownerProject.id', + 'ownerProject.type', + 'ownerProject.name', + ]) + .where( + `(workflow.id IN (${sharedWorkflowSubquery.getQuery()}) OR workflow.id IN (${callableSubquery.getQuery()}))`, + ) + .setParameters({ + ...sharedWorkflowSubquery.getParameters(), + ...callableSubquery.getParameters(), + }); + + // Match names only: the list can hold workflows the user cannot read, so + // their descriptions must not affect the result. + const searchWords = this.parseSearchWords(options.query); + if (searchWords.length > 0) { + const { conditions, parameters } = this.buildSearchConditions( + searchWords, + 'LOWER(workflow.name)', + ); + qb.andWhere(`(${conditions.join(' AND ')})`, parameters); + } + this.applyTriggerNodeTypesFilter(qb, options.triggerNodeTypes); + qb.orderBy('workflow.updatedAt', 'DESC').skip(options.skip).take(options.take); + + const [workflows, count] = await qb.getManyAndCount(); + return { workflows, count }; + } + + /** + * Build a subquery returning IDs of workflows whose callerPolicy names the + * given `parentWorkflowId` explicitly. + * + * The `workflowsFromSameOwner` policy is left out on purpose: for a user who + * is not the owner, it would list workflows that the owner did not share. + * The owner can already read those workflows through the sharing subquery. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any private buildCallablePolicySubquery(parentWorkflowId: string): SelectQueryBuilder { - const subquery = this.manager - .createQueryBuilder() - .select('cpw.id') - .from(WorkflowEntity, 'cpw') - .leftJoin( - SharedWorkflow, - 'sw_sub', - "sw_sub.workflowId = cpw.id AND sw_sub.role = 'workflow:owner'", - ) - .leftJoin( - SharedWorkflow, - 'sw_par', - "sw_par.workflowId = :cpParentWorkflowId AND sw_par.role = 'workflow:owner'", - ); - - const { conditions, params } = this.buildCallablePolicyConditions(parentWorkflowId); - - subquery.where('(' + conditions.join(' OR ') + ')', params); - - return subquery; - } - - private buildCallablePolicyConditions(parentWorkflowId: string): { - conditions: string[]; - params: Record; - } { const defaultPolicy = this.globalConfig.workflows.callerPolicyDefaultOption; const callerPolicy = this.settingsTextValue('cpw.settings', 'callerPolicy'); const callerIds = this.settingsTextValue('cpw.settings', 'callerIds'); - const conditions: string[] = []; - const params: Record = { - cpParentWorkflowId: parentWorkflowId, - cpCallerIdMembership: `%,${escapeLike(parentWorkflowId)},%`, - }; - - // Branch 1: callerPolicy = 'any' - conditions.push(`${callerPolicy} = 'any'`); - - // Branch 2: callerPolicy = 'workflowsFromAList' and the allowlist contains parentWorkflowId as a whole ID. - conditions.push( + const conditions = [ + `${callerPolicy} = 'any'`, + // The allowlist must contain parentWorkflowId as a whole ID. `(${callerPolicy} = 'workflowsFromAList' AND (',' || REPLACE(${callerIds}, ' ', '') || ',') LIKE :cpCallerIdMembership ${LIKE_ESCAPE_CLAUSE})`, - ); - - // Branch 3: callerPolicy = 'workflowsFromSameOwner' (or NULL when default is 'workflowsFromSameOwner'). - const sameOwnerPolicyClauses = [`${callerPolicy} = 'workflowsFromSameOwner'`]; - if (defaultPolicy === 'workflowsFromSameOwner') { - sameOwnerPolicyClauses.push(`${callerPolicy} IS NULL`); - } - conditions.push( - `((${sameOwnerPolicyClauses.join(' OR ')}) AND sw_sub.projectId = sw_par.projectId AND sw_par.projectId IS NOT NULL)`, - ); - - // Handle NULL callerPolicy when default is 'any' + ]; if (defaultPolicy === 'any') { conditions.push(`${callerPolicy} IS NULL`); } - return { conditions, params }; + return this.manager + .createQueryBuilder() + .select('cpw.id') + .from(WorkflowEntity, 'cpw') + .where(`(${conditions.join(' OR ')})`, { + cpCallerIdMembership: `%,${escapeLike(parentWorkflowId)},%`, + }); } private settingsTextValue(field: string, key: string): string { @@ -1467,14 +1585,15 @@ export class WorkflowRepository extends BaseRepository { /** * Builds search conditions and parameters for matching all of the search words */ - private buildSearchConditions(searchWords: string[]): { + private buildSearchConditions( + searchWords: string[], + fieldExpression = this.getFieldConcatExpression(), + ): { conditions: string[]; parameters: Record; } { - const concatExpression = this.getFieldConcatExpression(); - const conditions = searchWords.map((_, index) => { - return `${concatExpression} LIKE :searchWord${index}`; + return `${fieldExpression} LIKE :searchWord${index}`; }); const parameters: Record = {}; diff --git a/packages/@n8n/decorators/package.json b/packages/@n8n/decorators/package.json index 63e5abbb4b6..0635413a74c 100644 --- a/packages/@n8n/decorators/package.json +++ b/packages/@n8n/decorators/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/decorators", - "version": "1.43.0", + "version": "1.44.0", "scripts": { "clean": "rimraf dist .turbo", "dev": "pnpm watch", diff --git a/packages/@n8n/decorators/src/system-task/__tests__/placement.test.ts b/packages/@n8n/decorators/src/system-task/__tests__/placement.test.ts deleted file mode 100644 index 4b7ac2c907c..00000000000 --- a/packages/@n8n/decorators/src/system-task/__tests__/placement.test.ts +++ /dev/null @@ -1,60 +0,0 @@ -import type { SystemTaskPlacement } from '../system-task-placement'; - -it('should let an instance-scoped placement name the instance types that run the task', () => { - const placement: SystemTaskPlacement = { scope: 'instance', instanceTypes: ['main', 'worker'] }; - - expect(placement.scope).toBe('instance'); -}); - -it('should let a cluster-scoped placement be durable and run on takeover', () => { - const placement: SystemTaskPlacement = { scope: 'cluster', durable: true, runOnTakeover: true }; - - expect(placement.scope).toBe('cluster'); -}); - -it('should not let a placement name an instance type a cluster-scoped task never reaches', () => { - const placement: SystemTaskPlacement = { - scope: 'cluster', - durable: false, - // @ts-expect-error A cluster-scoped task runs on a main, so it names no instance type. - instanceTypes: ['worker'], - }; - - expect(placement.scope).toBe('cluster'); -}); - -it('should make a cluster-scoped task state whether it is durable', () => { - // @ts-expect-error The migration status is not optional. - const placement: SystemTaskPlacement = { scope: 'cluster' }; - - expect(placement.scope).toBe('cluster'); -}); - -it('should not let an instance-scoped placement name no instance type', () => { - // @ts-expect-error Nothing would run the task. - const placement: SystemTaskPlacement = { scope: 'instance', instanceTypes: [] }; - - expect(placement.scope).toBe('instance'); -}); - -it('should not let an instance-scoped task be durable', () => { - const placement: SystemTaskPlacement = { - scope: 'instance', - instanceTypes: ['worker'], - // @ts-expect-error The durable scheduler runs one occurrence for the cluster, not one per instance. - durable: true, - }; - - expect(placement.scope).toBe('instance'); -}); - -it('should not let an instance-scoped task run on leader takeover', () => { - const placement: SystemTaskPlacement = { - scope: 'instance', - instanceTypes: ['worker'], - // @ts-expect-error Leadership means nothing to a task that runs in every instance. - runOnTakeover: true, - }; - - expect(placement.scope).toBe('instance'); -}); diff --git a/packages/@n8n/decorators/src/system-task/__tests__/resolve-schedule.test.ts b/packages/@n8n/decorators/src/system-task/__tests__/resolve-schedule.test.ts index 846125a8c16..ce86eb436c8 100644 --- a/packages/@n8n/decorators/src/system-task/__tests__/resolve-schedule.test.ts +++ b/packages/@n8n/decorators/src/system-task/__tests__/resolve-schedule.test.ts @@ -1,20 +1,20 @@ import { intervalFromMilliseconds, intervalFromSeconds, - resolveSystemTaskSchedule, + resolveSystemTask, type SystemTask, - type SystemTaskSchedule, } from '../system-task'; -import type { SystemTaskPlacement } from '../system-task-placement'; +import type { SystemTaskTarget, SystemTaskSchedule } from '../types'; + +const resolveSystemTaskSchedule = (task: SystemTask) => resolveSystemTask(task).schedule; const taskWith = ( schedule: SystemTaskSchedule, - placement: SystemTaskPlacement = { scope: 'cluster', durable: false }, + target: SystemTaskTarget = { scope: 'cluster', leaderTimer: {} }, ): SystemTask => ({ name: 'test-task', schedule, - effects: 'idempotent', - placement, + target, run: async () => {}, }); @@ -48,9 +48,12 @@ it.each([ expect(schedule).toEqual({ kind: 'interval', intervalSeconds: expected }); }); -it('should round a sub-second interval of a durable task to one second', () => { +it('should round a sub-second interval of a scheduler task to one second', () => { const schedule = resolveSystemTaskSchedule( - taskWith({ kind: 'interval', intervalSeconds: 0.5 }, { scope: 'cluster', durable: true }), + taskWith( + { kind: 'interval', intervalSeconds: 0.5 }, + { scope: 'cluster', scheduler: { retryOnFailure: true } }, + ), ); expect(schedule).toEqual({ kind: 'interval', intervalSeconds: 1 }); diff --git a/packages/@n8n/decorators/src/system-task/__tests__/run-options.test.ts b/packages/@n8n/decorators/src/system-task/__tests__/run-options.test.ts index dcb41b2b472..55b051beb39 100644 --- a/packages/@n8n/decorators/src/system-task/__tests__/run-options.test.ts +++ b/packages/@n8n/decorators/src/system-task/__tests__/run-options.test.ts @@ -1,108 +1,99 @@ import { MAX_TIMER_DELAY_SECONDS, ScheduledJobMisfirePolicy } from '@n8n/constants'; import { - resolveSystemTaskRunOptions, + resolveSystemTask, timeoutAfterLimit, - validateSystemTask, type SystemTask, - type SystemTaskEffects, - type SystemTaskSchedule, + type SystemTaskRunOptions, } from '../system-task'; +import type { SchedulerOptions, SystemTaskTarget } from '../types'; -const schedule: SystemTaskSchedule = { kind: 'interval', intervalSeconds: 60 }; +const schedule = { kind: 'interval', intervalSeconds: 60 } as const; -const taskWith = (overrides: Partial & { effects: SystemTaskEffects }): SystemTask => ({ +const schedulerTask = (scheduler: SchedulerOptions): SystemTask => ({ name: 'test-task', schedule, - placement: { scope: 'cluster', durable: false }, + target: { scope: 'cluster', scheduler }, + run: async () => {}, +}); + +const resolveSystemTaskRunOptions = (task: SystemTask) => + resolveSystemTask(task).runOptions as SystemTaskRunOptions; + +const taskOn = (target: SystemTaskTarget, overrides: Partial = {}): SystemTask => ({ + name: 'test-task', + schedule, + target, run: async () => {}, ...overrides, }); -it('should let an idempotent task retry and run late', () => { - const options = resolveSystemTaskRunOptions(taskWith({ effects: 'idempotent' })); +it('should fill the defaults of the options a task does not state', () => { + const options = resolveSystemTaskRunOptions(schedulerTask({ retryOnFailure: true })); expect(options).toEqual({ misfirePolicy: ScheduledJobMisfirePolicy.Coalesce, misfireGraceSeconds: 60, maxAttempts: 3, concurrencyLimit: 1, + timeoutSeconds: undefined, }); }); -it('should keep a non-idempotent task to a single attempt and drop missed occurrences', () => { - const options = resolveSystemTaskRunOptions(taskWith({ effects: 'non-idempotent' })); - - expect(options).toEqual({ - misfirePolicy: ScheduledJobMisfirePolicy.Skip, - misfireGraceSeconds: 60, - maxAttempts: 1, - concurrencyLimit: 1, - }); -}); - -it.each([ - ['misfirePolicy', { misfirePolicy: ScheduledJobMisfirePolicy.Skip }], - ['misfireGraceSeconds', { misfireGraceSeconds: 5 }], - ['concurrencyLimit', { concurrencyLimit: 4 }], - ['timeoutSeconds', { timeoutSeconds: 600 }], -] as const)('should let a task override %s', (field, override) => { - const options = resolveSystemTaskRunOptions(taskWith({ effects: 'idempotent', ...override })); - - expect(options[field]).toBe(override[field as keyof typeof override]); -}); - -it.each([ - { maxAttempts: 0 }, - { maxAttempts: -1 }, - { maxAttempts: 1.5 }, - { maxAttempts: 2_147_483_648 }, - { misfireGraceSeconds: 0 }, - { misfireGraceSeconds: -1 }, - { misfireGraceSeconds: 0.5 }, - { misfireGraceSeconds: 86_400_000_000 }, - { concurrencyLimit: 0 }, - { concurrencyLimit: -1 }, - { concurrencyLimit: 1.5 }, - { concurrencyLimit: 2_147_483_648 }, - { timeoutSeconds: -1 }, - { timeoutSeconds: 2_147_484 }, -])('should reject the nonsensical override %o', (override) => { - expect(() => - resolveSystemTaskRunOptions(taskWith({ effects: 'idempotent', ...override })), - ).toThrow( - expect.objectContaining({ - message: 'A system task declares an out-of-range option', - extra: expect.objectContaining({ name: 'test-task', field: Object.keys(override)[0] }), +it('should map the options a task states to what the scheduler stores', () => { + const options = resolveSystemTaskRunOptions( + schedulerTask({ + retryOnFailure: false, + missedAfterSeconds: 300, + catchUp: false, + concurrencyLimit: 4, + timeoutSeconds: 600, }), ); -}); - -it('should keep the defaults for the fields a task does not override', () => { - const options = resolveSystemTaskRunOptions( - taskWith({ effects: 'non-idempotent', misfireGraceSeconds: 5 }), - ); expect(options).toEqual({ misfirePolicy: ScheduledJobMisfirePolicy.Skip, - misfireGraceSeconds: 5, + misfireGraceSeconds: 300, maxAttempts: 1, - concurrencyLimit: 1, + concurrencyLimit: 4, + timeoutSeconds: 600, }); }); -it('should refuse to retry non-idempotent work that asked for more attempts', () => { +it('should store an unlimited concurrency as no limit', () => { const options = resolveSystemTaskRunOptions( - taskWith({ effects: 'non-idempotent', maxAttempts: 10 }), + schedulerTask({ retryOnFailure: true, concurrencyLimit: 'unlimited' }), ); - expect(options.maxAttempts).toBe(1); + expect(options.concurrencyLimit).toBeNull(); }); -it('should leave the timeout to the scheduler when a task does not override it', () => { - const options = resolveSystemTaskRunOptions(taskWith({ effects: 'idempotent' })); +it('should catch up when a task states it explicitly', () => { + const options = resolveSystemTaskRunOptions( + schedulerTask({ retryOnFailure: true, catchUp: true }), + ); - expect(options.timeoutSeconds).toBeUndefined(); + expect(options.misfirePolicy).toBe(ScheduledJobMisfirePolicy.Coalesce); +}); + +it.each<[string, SchedulerOptions]>([ + ['missedAfterSeconds', { retryOnFailure: true, missedAfterSeconds: 0 }], + ['missedAfterSeconds', { retryOnFailure: true, missedAfterSeconds: -1 }], + ['missedAfterSeconds', { retryOnFailure: true, missedAfterSeconds: 0.5 }], + ['missedAfterSeconds', { retryOnFailure: true, missedAfterSeconds: 86_400_000_000 }], + ['concurrencyLimit', { retryOnFailure: true, concurrencyLimit: 0 }], + ['concurrencyLimit', { retryOnFailure: true, concurrencyLimit: -1 }], + ['concurrencyLimit', { retryOnFailure: true, concurrencyLimit: 1.5 }], + ['concurrencyLimit', { retryOnFailure: true, concurrencyLimit: 2_147_483_648 }], + ['timeoutSeconds', { retryOnFailure: true, timeoutSeconds: -1 }], + ['timeoutSeconds', { retryOnFailure: true, timeoutSeconds: 2_147_484 }], +])('should reject an out-of-range %s in %o', (field, scheduler) => { + expect(() => resolveSystemTaskRunOptions(schedulerTask(scheduler))).toThrow( + expect.objectContaining({ + message: 'A system task declares an out-of-range option', + extra: expect.objectContaining({ name: 'test-task', field }), + }), + ); }); it.each([ @@ -111,7 +102,7 @@ it.each([ [1.5, 2], ])('should round the timeout %s to %s like a schedule interval', (declared, stored) => { const options = resolveSystemTaskRunOptions( - taskWith({ effects: 'idempotent', timeoutSeconds: declared }), + schedulerTask({ retryOnFailure: true, timeoutSeconds: declared }), ); expect(options.timeoutSeconds).toBe(stored); @@ -119,25 +110,33 @@ it.each([ it('should accept the longest timeout a timer honors', () => { const options = resolveSystemTaskRunOptions( - taskWith({ effects: 'idempotent', timeoutSeconds: 2_147_483 }), + schedulerTask({ retryOnFailure: true, timeoutSeconds: 2_147_483 }), ); expect(options.timeoutSeconds).toBe(2_147_483); }); -it('should let a task permit overlap', () => { - const options = resolveSystemTaskRunOptions( - taskWith({ effects: 'idempotent', concurrencyLimit: null }), - ); +it.each([ + { scope: 'cluster', leaderTimer: {} }, + { scope: 'instance', instanceTypes: ['main'] }, +])( + 'should resolve no run options for a $scope task that does not run on the scheduler', + (target) => { + expect(resolveSystemTask(taskOn(target)).runOptions).toBeUndefined(); + }, +); - expect(options.concurrencyLimit).toBeNull(); +it('should validate the scheduler options of a task', () => { + expect(() => + resolveSystemTask(schedulerTask({ retryOnFailure: true, missedAfterSeconds: 0 })), + ).toThrow('A system task declares an out-of-range option'); }); it.each([0, -5, 2.5, NaN, Infinity, 2_147_484])( 'should reject a retry delay of %s', (retryDelaySeconds) => { expect(() => - validateSystemTask(taskWith({ effects: 'idempotent', retryDelaySeconds })), + resolveSystemTask(taskOn({ scope: 'cluster', leaderTimer: { retryDelaySeconds } })), ).toThrow( expect.objectContaining({ message: 'A system task declares an out-of-range retry delay', @@ -149,7 +148,7 @@ it.each([0, -5, 2.5, NaN, Infinity, 2_147_484])( it('should accept the longest retry delay a timeout honors', () => { expect(() => - validateSystemTask(taskWith({ effects: 'idempotent', retryDelaySeconds: 2_147_483 })), + resolveSystemTask(taskOn({ scope: 'cluster', leaderTimer: { retryDelaySeconds: 2_147_483 } })), ).not.toThrow(); }); @@ -157,12 +156,11 @@ it.each([0, -1, NaN, Infinity])( 'should reject an instance task interval of %s seconds', (intervalSeconds) => { expect(() => - validateSystemTask( - taskWith({ - effects: 'idempotent', - schedule: { kind: 'interval', intervalSeconds }, - placement: { scope: 'instance', instanceTypes: ['main'] }, - }), + resolveSystemTask( + taskOn( + { scope: 'instance', instanceTypes: ['main'] }, + { schedule: { kind: 'interval', intervalSeconds } }, + ), ), ).toThrow( expect.objectContaining({ @@ -175,8 +173,11 @@ it.each([0, -1, NaN, Infinity])( it('should accept a cluster task interval of 0 seconds, which is rounded up', () => { expect(() => - validateSystemTask( - taskWith({ effects: 'idempotent', schedule: { kind: 'interval', intervalSeconds: 0 } }), + resolveSystemTask( + taskOn( + { scope: 'cluster', scheduler: { retryOnFailure: true } }, + { schedule: { kind: 'interval', intervalSeconds: 0 } }, + ), ), ).not.toThrow(); }); diff --git a/packages/@n8n/decorators/src/system-task/__tests__/system-task.test.ts b/packages/@n8n/decorators/src/system-task/__tests__/system-task.test.ts index 7868ab67958..5f71eab5f4a 100644 --- a/packages/@n8n/decorators/src/system-task/__tests__/system-task.test.ts +++ b/packages/@n8n/decorators/src/system-task/__tests__/system-task.test.ts @@ -1,8 +1,8 @@ import { Container } from '@n8n/di'; -import { SystemTask, type SystemTaskClass, type SystemTaskSchedule } from '../system-task'; +import { SystemTask, type SystemTaskClass } from '../system-task'; import { SystemTaskMetadata } from '../system-task-metadata'; -import type { SystemTaskPlacement } from '../system-task-placement'; +import type { SystemTaskTarget, SystemTaskSchedule } from '../types'; let metadata: SystemTaskMetadata; @@ -24,9 +24,7 @@ it('should make a decorated class injectable without registering it', () => { readonly schedule: SystemTaskSchedule = { kind: 'interval', intervalSeconds: 60 }; - readonly effects = 'idempotent' as const; - - readonly placement: SystemTaskPlacement = { scope: 'cluster', durable: false }; + readonly target: SystemTaskTarget = { scope: 'cluster', leaderTimer: {} }; async run() {} } @@ -49,9 +47,7 @@ it('should notify a subscribed listener when a task class is registered later', timezone: null, }; - readonly effects = 'idempotent' as const; - - readonly placement: SystemTaskPlacement = { scope: 'cluster', durable: false }; + readonly target: SystemTaskTarget = { scope: 'cluster', leaderTimer: {} }; async run() {} } @@ -71,9 +67,7 @@ it('should let a subscribed listener resolve the class it is notified of', () => readonly schedule: SystemTaskSchedule = { kind: 'interval', intervalSeconds: 60 }; - readonly effects = 'idempotent' as const; - - readonly placement: SystemTaskPlacement = { scope: 'cluster', durable: false }; + readonly target: SystemTaskTarget = { scope: 'cluster', leaderTimer: {} }; async run() {} } diff --git a/packages/@n8n/decorators/src/system-task/__tests__/targets.test.ts b/packages/@n8n/decorators/src/system-task/__tests__/targets.test.ts new file mode 100644 index 00000000000..a4939b9dd41 --- /dev/null +++ b/packages/@n8n/decorators/src/system-task/__tests__/targets.test.ts @@ -0,0 +1,59 @@ +import { clusterTarget, instanceTarget, leaderTimerTarget } from '../system-task'; + +describe('clusterTarget', () => { + it('should make a cluster target that runs on the scheduler', () => { + const target = clusterTarget({ + scheduler: { retryOnFailure: true }, + leaderTimer: { runOnTakeover: true }, + }); + + expect(target).toEqual({ + scope: 'cluster', + scheduler: { retryOnFailure: true }, + leaderTimer: { runOnTakeover: true }, + }); + expect(target.scheduler.retryOnFailure).toBe(true); + }); + + it('should not take an unknown scheduler option', () => { + // @ts-expect-error The option is `catchUp`. + const target = clusterTarget({ scheduler: { retryOnFailure: true, catchup: false } }); + + expect(target.scope).toBe('cluster'); + }); + + it('should not take an instance type', () => { + const target = clusterTarget({ + scheduler: { retryOnFailure: true }, + // @ts-expect-error A cluster task runs on a main, so it names no instance type. + instanceTypes: ['worker'], + }); + + expect(target.scope).toBe('cluster'); + }); +}); + +describe('leaderTimerTarget', () => { + it('should make a cluster target that runs on the leader timer only', () => { + // oxlint-disable-next-line typescript/no-deprecated -- the builder is under test + const target = leaderTimerTarget({ runOnTakeover: true }); + + expect(target).toEqual({ scope: 'cluster', leaderTimer: { runOnTakeover: true } }); + }); +}); + +describe('instanceTarget', () => { + it('should make an instance target for the instance types', () => { + expect(instanceTarget(['main', 'worker'])).toEqual({ + scope: 'instance', + instanceTypes: ['main', 'worker'], + }); + }); + + it('should not take an empty list of instance types', () => { + // @ts-expect-error Nothing would run the task. + const target = instanceTarget([]); + + expect(target.scope).toBe('instance'); + }); +}); diff --git a/packages/@n8n/decorators/src/system-task/__tests__/types.test.ts b/packages/@n8n/decorators/src/system-task/__tests__/types.test.ts new file mode 100644 index 00000000000..90b5358a9a0 --- /dev/null +++ b/packages/@n8n/decorators/src/system-task/__tests__/types.test.ts @@ -0,0 +1,103 @@ +import type { SchedulerOptions, SystemTaskTarget } from '../types'; + +it('should let an instance task name the instance types that run it', () => { + const target: SystemTaskTarget = { + scope: 'instance', + instanceTypes: ['main', 'worker'], + }; + + expect(target.scope).toBe('instance'); +}); + +it('should let a cluster task run on the scheduler and fall back to the leader timer', () => { + const target: SystemTaskTarget = { + scope: 'cluster', + scheduler: { + retryOnFailure: false, + missedAfterSeconds: 300, + catchUp: false, + timeoutSeconds: 60, + }, + leaderTimer: { runOnTakeover: true, retryDelaySeconds: 30 }, + }; + + expect(target.scope).toBe('cluster'); +}); + +it('should let a cluster task run on the leader timer only', () => { + const target: SystemTaskTarget = { scope: 'cluster', leaderTimer: {} }; + + expect(target.scope).toBe('cluster'); +}); + +it('should not let a cluster task name no runner', () => { + // @ts-expect-error Nothing would run the task. + const target: SystemTaskTarget = { scope: 'cluster' }; + + expect(target.scope).toBe('cluster'); +}); + +it('should not let a cluster task name an instance type', () => { + const target: SystemTaskTarget = { + scope: 'cluster', + scheduler: { retryOnFailure: true }, + // @ts-expect-error A cluster task runs on a main, so it names no instance type. + instanceTypes: ['worker'], + }; + + expect(target.scope).toBe('cluster'); +}); + +it('should not let a cluster task set a retry delay outside the leader timer', () => { + const target: SystemTaskTarget = { + scope: 'cluster', + scheduler: { retryOnFailure: true }, + // @ts-expect-error The scheduler retries by attempts, the leader timer by delay. + retryDelaySeconds: 30, + }; + + expect(target.scope).toBe('cluster'); +}); + +it('should make a scheduler task state whether it retries on failure', () => { + // @ts-expect-error There is no safe default: a repeat is not safe for every task. + const scheduler: SchedulerOptions = { missedAfterSeconds: 60 }; + + expect(scheduler.missedAfterSeconds).toBe(60); +}); + +it('should not take null as a concurrency limit', () => { + // @ts-expect-error `'unlimited'` says it in words. + const scheduler: SchedulerOptions = { retryOnFailure: true, concurrencyLimit: null }; + + expect(scheduler.retryOnFailure).toBe(true); +}); + +it('should not let an instance task name no instance type', () => { + // @ts-expect-error Nothing would run the task. + const target: SystemTaskTarget = { scope: 'instance', instanceTypes: [] }; + + expect(target.scope).toBe('instance'); +}); + +it('should not let an instance task run on the scheduler', () => { + // @ts-expect-error The scheduler runs one occurrence for the cluster, not one per instance. + const target: SystemTaskTarget = { + scope: 'instance', + instanceTypes: ['worker'], + scheduler: { retryOnFailure: true }, + }; + + expect(target.scope).toBe('instance'); +}); + +it('should not let an instance task run on leader takeover', () => { + // @ts-expect-error Leadership means nothing to a task that runs in every instance. + const target: SystemTaskTarget = { + scope: 'instance', + instanceTypes: ['worker'], + leaderTimer: { runOnTakeover: true }, + }; + + expect(target.scope).toBe('instance'); +}); diff --git a/packages/@n8n/decorators/src/system-task/index.ts b/packages/@n8n/decorators/src/system-task/index.ts index a12afece732..def352b3b09 100644 --- a/packages/@n8n/decorators/src/system-task/index.ts +++ b/packages/@n8n/decorators/src/system-task/index.ts @@ -1,19 +1,20 @@ export { - DEFAULT_SYSTEM_TASK_CONCURRENCY_LIMIT, SystemTask, + clusterTarget, + instanceTarget, intervalFromMilliseconds, intervalFromSeconds, - resolveSystemTaskRunOptions, - resolveSystemTaskSchedule, + leaderTimerTarget, + resolveSystemTask, timeoutAfterLimit, - validateSystemTask, } from './system-task'; +export type { SystemTaskClass, SystemTaskRunOptions } from './system-task'; export type { - SystemTaskClass, - SystemTaskEffects, - SystemTaskRunContext, - SystemTaskRunOptions, + ClusterTarget, + InstanceTarget, + LeaderTimerTarget, + SchedulerOptions, + SystemTaskTarget, SystemTaskSchedule, -} from './system-task'; -export type { SystemTaskPlacement } from './system-task-placement'; +} from './types'; export { SystemTaskMetadata } from './system-task-metadata'; diff --git a/packages/@n8n/decorators/src/system-task/system-task-placement.ts b/packages/@n8n/decorators/src/system-task/system-task-placement.ts deleted file mode 100644 index 3837663cee2..00000000000 --- a/packages/@n8n/decorators/src/system-task/system-task-placement.ts +++ /dev/null @@ -1,34 +0,0 @@ -import type { InstanceType } from '@n8n/constants'; - -/** - * Where a task's occurrences run, and what drives them there. - * - * A cluster-scoped task runs once for the whole cluster, on a main, so it - * names no instance type. It states how the cluster coordinates that one run: - * the leader-gated in-memory timer, or the durable scheduler. An - * instance-scoped task runs its own occurrence in every instance of the kinds - * it names, with no coordination, so it has to name at least one kind and - * cannot be durable or run on takeover. - */ -export type SystemTaskPlacement = - | { - readonly scope: 'cluster'; - /** - * Migration status. - * - `false` runs on the leader-gated in-memory timer - * - `true` runs on the durable scheduler when the instance flag is on. - * @remarks Temporary, removed once every task is durable. - */ - readonly durable: boolean; - /** - * Runs one occurrence as soon as this instance becomes the leader, - * including at startup for an instance that is already the leader, on - * top of the scheduled occurrences. In-memory timers only: ignored for a - * durable run. - */ - readonly runOnTakeover?: boolean; - } - | { - readonly scope: 'instance'; - readonly instanceTypes: readonly [InstanceType, ...InstanceType[]]; - }; diff --git a/packages/@n8n/decorators/src/system-task/system-task.ts b/packages/@n8n/decorators/src/system-task/system-task.ts index 4151378fbd6..f47dfb88e27 100644 --- a/packages/@n8n/decorators/src/system-task/system-task.ts +++ b/packages/@n8n/decorators/src/system-task/system-task.ts @@ -5,97 +5,20 @@ import { ScheduledJobMisfirePolicy, Time, type IntervalDefinition, - type OneOffDefinition, - type ScheduleDefinition, } from '@n8n/constants'; import { Service, type Constructable } from '@n8n/di'; import { UnexpectedError } from 'n8n-workflow'; -import type { SystemTaskPlacement } from './system-task-placement'; +import type { + ClusterTarget, + InstanceTarget, + LeaderTimerOptions, + LeaderTimerTarget, + SystemTask as SystemTaskContract, + SystemTaskSchedule, +} from './types'; -/** Whether a run is safe to repeat. */ -export type SystemTaskEffects = 'idempotent' | 'non-idempotent'; - -/** A system task always has a next run, so a one-off schedule is not allowed. */ -export type SystemTaskSchedule = Exclude; - -/** - * A periodic background task owned by the system rather than by a workflow. - */ -export interface SystemTask { - /** - * Identity of the task, unique across all system tasks. Registration sees - * only the class, so the consumer that resolves the instances has to enforce - * this. - */ - readonly name: string; - - readonly schedule: SystemTaskSchedule; - - /** What kind of effects a run has, which sets the defaults of the overrides below. */ - readonly effects: SystemTaskEffects; - - /** Where the occurrences run. */ - readonly placement: SystemTaskPlacement; - - /** - * How long after a failed run an earlier retry occurrence runs, instead of - * waiting for the next scheduled one. In-memory timers only, and only - * honored for idempotent work. Durable runs retry via `maxAttempts`. - * An integer of at least 1, capped at what a timeout honors (about 24 days). - */ - readonly retryDelaySeconds?: number; - - /** - * Overrides what happens to occurrences that missed their grace window. - * Defaults to `coalesce` for idempotent work and `skip` otherwise. - */ - readonly misfirePolicy?: ScheduledJobMisfirePolicy; - - /** - * Overrides how late an occurrence may run before the misfire policy applies. - * At least 1: a grace of `0` leaves every occurrence past its deadline the - * instant it comes due. - * Defaults to {@link DEFAULT_MISFIRE_GRACE_SECONDS}. - */ - readonly misfireGraceSeconds?: number; - - /** - * Overrides how many times an occurrence is attempted before it is given up on. - * Defaults to 3 for idempotent work. Ignored for non-idempotent work, which is - * always kept to a single attempt. - */ - readonly maxAttempts?: number; - - /** - * Overrides how many durable occurrences may run at the same time. - * `null` removes the limit. Defaults to - * {@link DEFAULT_SYSTEM_TASK_CONCURRENCY_LIMIT}. - */ - readonly concurrencyLimit?: number | null; - - /** - * Overrides how long, in seconds, one durable run may take before the - * scheduler aborts its signal and gives the occurrence back. Rounded to the - * whole second, never below one, at most {@link MAX_TIMER_DELAY_SECONDS}. - * Defaults to N8N_SCHEDULER_TASK_TIMEOUT_SECONDS. - */ - readonly timeoutSeconds?: number; - - /** - * Executes one occurrence of the task. A durable run may take up to its timeout. - * `signal` aborts on shutdown, and on loss of leadership for an in-memory timer. - * A durable run also aborts on lease loss or expiry, and when it reaches its timeout. - * Ignoring the signal delays shutdown and can let another run overlap. - * A durable run that settles after a lease abort counts as a failed attempt - * while its claim still matches, and retries only while attempts remain. - */ - run(signal: AbortSignal, context: SystemTaskRunContext): Promise; -} - -export interface SystemTaskRunContext { - readonly durable: boolean; -} +export type SystemTask = SystemTaskContract; /** How a task's occurrences are retried and how late they may still run. */ export interface SystemTaskRunOptions { @@ -109,56 +32,75 @@ export interface SystemTaskRunOptions { } /** One occurrence at a time, like the in-memory timer. */ -export const DEFAULT_SYSTEM_TASK_CONCURRENCY_LIMIT = 1; +const DEFAULT_SYSTEM_TASK_CONCURRENCY_LIMIT = 1; + +const MAX_ATTEMPTS_WITH_RETRY = 3; + +/** A target that runs the task once for the cluster, on the durable scheduler. */ +export function clusterTarget(options: Omit): ClusterTarget { + return { scope: 'cluster', ...options }; +} + +/** @deprecated Move the task to `clusterTarget`. */ +export function leaderTimerTarget(leaderTimer: LeaderTimerOptions): LeaderTimerTarget { + return { scope: 'cluster', leaderTimer }; +} + +/** A target that runs the task in every instance of `instanceTypes`. */ +export function instanceTarget(instanceTypes: InstanceTarget['instanceTypes']): InstanceTarget { + return { scope: 'instance', instanceTypes }; +} + +/** How a task runs, resolved from what it declares. */ +export interface ResolvedSystemTask { + readonly schedule: SystemTaskSchedule; + /** What the scheduler stores. `undefined` for a task that does not run on the scheduler. */ + readonly runOptions: SystemTaskRunOptions | undefined; +} /** - * Run options a task's effects imply, when the task declares no override: - * retries and late runs only where a repeat is harmless. - * The grace window and the concurrency limit do not depend on effects. + * Resolves the schedule and the scheduler run options of a task, and rejects a + * task that declares an option the runners cannot honor. + * + * @throws {UnexpectedError} when `retryDelaySeconds` or a scheduler option is out of range + * @throws {UnexpectedError} when an instance task declares an interval that is not positive and finite */ -const SYSTEM_TASK_RUN_OPTION_DEFAULTS: Record< - SystemTaskEffects, - Omit -> = { - idempotent: { - misfirePolicy: ScheduledJobMisfirePolicy.Coalesce, - maxAttempts: 3, - }, - // eslint-disable-next-line @typescript-eslint/naming-convention - 'non-idempotent': { - misfirePolicy: ScheduledJobMisfirePolicy.Skip, - maxAttempts: 1, - }, -}; +export function resolveSystemTask(task: SystemTask): ResolvedSystemTask { + const runOptions = resolveSystemTaskRunOptions(task); + validateTimerOptions(task); + return { schedule: resolveSystemTaskSchedule(task), runOptions }; +} /** - * Resolves the run options a task is scheduled with, and rejects values the - * scheduler cannot store. A task's own overrides win over the defaults its - * effects imply, except for `maxAttempts` on non-idempotent work, which stays - * at a single attempt. + * Resolves the run options the scheduler stores for a task, and rejects values + * it cannot store. Returns `undefined` for a task that does not run on the scheduler. + * + * @throws {UnexpectedError} when an option is out of range */ -export function resolveSystemTaskRunOptions(task: SystemTask): SystemTaskRunOptions { - const defaults = SYSTEM_TASK_RUN_OPTION_DEFAULTS[task.effects]; +function resolveSystemTaskRunOptions(task: SystemTask): SystemTaskRunOptions | undefined { + const { scheduler } = task.target; + if (scheduler === undefined) { + return undefined; + } + const concurrencyLimit = scheduler.concurrencyLimit ?? DEFAULT_SYSTEM_TASK_CONCURRENCY_LIMIT; const options = { - misfirePolicy: task.misfirePolicy ?? defaults.misfirePolicy, - misfireGraceSeconds: task.misfireGraceSeconds ?? DEFAULT_MISFIRE_GRACE_SECONDS, - maxAttempts: task.effects === 'non-idempotent' ? 1 : (task.maxAttempts ?? defaults.maxAttempts), - concurrencyLimit: - task.concurrencyLimit === undefined - ? DEFAULT_SYSTEM_TASK_CONCURRENCY_LIMIT - : task.concurrencyLimit, - timeoutSeconds: roundedTimeoutSeconds(task.timeoutSeconds), + misfirePolicy: + scheduler.catchUp === false + ? ScheduledJobMisfirePolicy.Skip + : ScheduledJobMisfirePolicy.Coalesce, + misfireGraceSeconds: scheduler.missedAfterSeconds ?? DEFAULT_MISFIRE_GRACE_SECONDS, + maxAttempts: scheduler.retryOnFailure ? MAX_ATTEMPTS_WITH_RETRY : 1, + concurrencyLimit: concurrencyLimit === 'unlimited' ? null : concurrencyLimit, + timeoutSeconds: roundedTimeoutSeconds(scheduler.timeoutSeconds), }; // These end up in `int` columns, where a fractional value is rounded and anything - // above the signed 32-bit maximum is rejected, and an override of `0` passes the - // `??` above. `scheduled_job` rejects a grace of `0` outright, so match the - // column's whole range here rather than at the failing insert. + // above the signed 32-bit maximum is rejected. `scheduled_job` rejects a grace of `0` + // outright, so match the column's whole range here rather than at the failing insert. // Only a static floor: the scheduler's usable minimum depends on its configured // intervals, so whatever provisions a task still has to clamp against those. - assertInRange(task.name, 'maxAttempts', options.maxAttempts, 1); - assertInRange(task.name, 'misfireGraceSeconds', options.misfireGraceSeconds, 1); + assertInRange(task.name, 'missedAfterSeconds', options.misfireGraceSeconds, 1); // A limit below 1 would block every occurrence. if (options.concurrencyLimit !== null) { assertInRange(task.name, 'concurrencyLimit', options.concurrencyLimit, 1); @@ -171,15 +113,15 @@ export function resolveSystemTaskRunOptions(task: SystemTask): SystemTaskRunOpti } /** - * Rejects a task that declares an option the schedulers cannot honor. + * Rejects a task that declares a timer option the in-memory timers cannot honor. * - * @throws {UnexpectedError} when `retryDelaySeconds`, `maxAttempts`, `misfireGraceSeconds` or `timeoutSeconds` is out of range + * @throws {UnexpectedError} when `retryDelaySeconds` is out of range * @throws {UnexpectedError} when an instance task declares an interval that is not positive and finite */ -export function validateSystemTask(task: SystemTask): void { - resolveSystemTaskRunOptions(task); - - const { retryDelaySeconds } = task; +function validateTimerOptions(task: SystemTask): void { + const { target } = task; + // oxlint-disable-next-line typescript/no-deprecated -- validated while the leader timer still runs tasks + const retryDelaySeconds = target.leaderTimer?.retryDelaySeconds; if ( retryDelaySeconds !== undefined && (!Number.isInteger(retryDelaySeconds) || @@ -193,9 +135,9 @@ export function validateSystemTask(task: SystemTask): void { // A cluster task's interval is rounded up to one second, but an instance // task's is kept to the millisecond, so a non-positive one would fire every millisecond. - const { schedule, placement } = task; + const { schedule } = task; if ( - placement.scope === 'instance' && + target.scope === 'instance' && schedule.kind === 'interval' && !(schedule.intervalSeconds > 0 && Number.isFinite(schedule.intervalSeconds)) ) { @@ -248,12 +190,14 @@ export function intervalFromMilliseconds(milliseconds: number): IntervalDefiniti * a fractional config value keeps running as it did on the legacy timers. An * instance task's interval keeps its sub-second part, rounded to the millisecond. */ -export function resolveSystemTaskSchedule(task: SystemTask): SystemTaskSchedule { +function resolveSystemTaskSchedule(task: SystemTask): SystemTaskSchedule { const { schedule } = task; - if (schedule.kind !== 'interval') return schedule; + if (schedule.kind !== 'interval') { + return schedule; + } const intervalSeconds = - task.placement.scope === 'instance' + task.target.scope === 'instance' ? wholeMilliseconds(schedule.intervalSeconds) : wholeSeconds(schedule.intervalSeconds); diff --git a/packages/@n8n/decorators/src/system-task/types.ts b/packages/@n8n/decorators/src/system-task/types.ts new file mode 100644 index 00000000000..06dcf373ba1 --- /dev/null +++ b/packages/@n8n/decorators/src/system-task/types.ts @@ -0,0 +1,110 @@ +import type { InstanceType, OneOffDefinition, ScheduleDefinition } from '@n8n/constants'; + +/** A system task always has a next run, so a one-off schedule is not allowed. */ +export type SystemTaskSchedule = Exclude; + +/** + * A periodic background task owned by the system rather than by a workflow. + */ +export interface SystemTask { + /** + * Identity of the task, unique across all system tasks. Registration sees + * only the class, so the consumer that resolves the instances has to enforce + * this. + */ + readonly name: string; + + readonly schedule: SystemTaskSchedule; + + /** Where the occurrences run, and the options of the runner that runs them. */ + readonly target: SystemTaskTarget; + + /** + * Executes one occurrence of the task. + * `signal` aborts on shutdown, and on loss of leadership for a leader timer. + * A scheduler run also aborts on lease loss or expiry, and at its timeout. + * Ignoring the signal delays shutdown and can let another run overlap. + */ + run(signal: AbortSignal): Promise; +} + +/** + * Where a task's occurrences run. + * + * A cluster task runs once for the whole cluster, on a main. It runs on the + * durable scheduler when the scheduler is enabled, and on the leader timer + * otherwise. An instance task runs in every instance of the types it names, + * on a timer, with no coordination. + */ +export type SystemTaskTarget = ClusterTarget | LeaderTimerTarget | InstanceTarget; + +/** A cluster task that runs on the durable scheduler. */ +export interface ClusterTarget { + readonly scope: 'cluster'; + readonly scheduler: SchedulerOptions; + /** + * @deprecated Applies only while the durable scheduler is disabled. + * Removed when the durable scheduler is the only runner. + */ + readonly leaderTimer?: LeaderTimerOptions; + readonly instanceTypes?: never; +} + +/** A cluster task that runs on the leader timer only. */ +export interface LeaderTimerTarget { + readonly scope: 'cluster'; + readonly scheduler?: never; + readonly leaderTimer: LeaderTimerOptions; + readonly instanceTypes?: never; +} + +/** A task that runs in every instance of the types it names. */ +export interface InstanceTarget { + readonly scope: 'instance'; + readonly instanceTypes: readonly [InstanceType, ...InstanceType[]]; + readonly scheduler?: never; + readonly leaderTimer?: never; +} + +/** What the durable scheduler stores for a task and honors on every occurrence. */ +export interface SchedulerOptions { + /** + * Runs an occurrence again when its run throws, times out or loses its + * lease, up to three runs in all. Set `false` when running twice for one + * occurrence is not safe. + */ + readonly retryOnFailure: boolean; + + /** + * How many seconds after its planned time an occurrence may still start. + * After this, the occurrence is missed and does not run. Only `catchUp` can + * run the latest occurrence that was missed while the scheduler was down. + * Defaults to 60. + */ + readonly missedAfterSeconds?: number; + + /** After the scheduler was down, runs the latest missed occurrence once. Defaults to `true`. */ + readonly catchUp?: boolean; + + /** How many occurrences may run at the same time. Defaults to 1. */ + readonly concurrencyLimit?: number | 'unlimited'; + + /** + * How many seconds one run may take. At this limit the signal aborts. + * Rounded to the whole second, never below one, at most about 24 days. + * Defaults to the scheduler's task timeout. + */ + readonly timeoutSeconds?: number; +} + +/** What the leader timer honors. */ +export interface LeaderTimerOptions { + /** Runs one occurrence as soon as this main becomes the leader, on top of the schedule. */ + readonly runOnTakeover?: boolean; + + /** + * How long after a failed run the task runs again, instead of at its next + * occurrence. An integer from 1 to about 24 days. + */ + readonly retryDelaySeconds?: number; +} diff --git a/packages/@n8n/engine/package.json b/packages/@n8n/engine/package.json index e5a665588ea..c0c685d332a 100644 --- a/packages/@n8n/engine/package.json +++ b/packages/@n8n/engine/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/engine", - "version": "0.23.0", + "version": "0.24.0", "description": "n8n workflow execution engine (v2)", "scripts": { "clean": "rimraf dist .turbo compiled", diff --git a/packages/@n8n/eslint-config/src/rules/index.ts b/packages/@n8n/eslint-config/src/rules/index.ts index bdb864f867e..6cc231719d2 100644 --- a/packages/@n8n/eslint-config/src/rules/index.ts +++ b/packages/@n8n/eslint-config/src/rules/index.ts @@ -25,7 +25,6 @@ import { NoRekaUiPaginationRule } from './no-reka-ui-pagination.js'; import { NoRestrictedSleepDefinitionRule } from './no-restricted-sleep-definition.js'; import { NoRestrictedSleepImportRule } from './no-restricted-sleep-import.js'; import { NoRepositoryInPublicApiHandlerRule } from './no-repository-in-public-api-handler.js'; -import { RequirePublicApiControllerRule } from './require-public-api-controller.js'; import { NoUnsealedWorkflowEntityWriteRule } from './no-unsealed-workflow-entity-write.js'; import { NoUnsealedCredentialsEntityWriteRule } from './no-unsealed-credentials-entity-write.js'; import { RequireEscapedQueryValuesRule } from './require-escaped-query-values.js'; @@ -61,7 +60,6 @@ export const rules = { 'no-restricted-sleep-definition': NoRestrictedSleepDefinitionRule, 'no-restricted-sleep-import': NoRestrictedSleepImportRule, 'no-repository-in-public-api-handler': NoRepositoryInPublicApiHandlerRule, - 'require-public-api-controller': RequirePublicApiControllerRule, 'no-unsealed-workflow-entity-write': NoUnsealedWorkflowEntityWriteRule, 'no-unsealed-credentials-entity-write': NoUnsealedCredentialsEntityWriteRule, 'require-escaped-query-values': RequireEscapedQueryValuesRule, diff --git a/packages/@n8n/eslint-config/src/rules/require-public-api-controller.test.ts b/packages/@n8n/eslint-config/src/rules/require-public-api-controller.test.ts deleted file mode 100644 index 83760276996..00000000000 --- a/packages/@n8n/eslint-config/src/rules/require-public-api-controller.test.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { RuleTester } from '@typescript-eslint/rule-tester'; -import { RequirePublicApiControllerRule } from './require-public-api-controller.js'; - -const ruleTester = new RuleTester(); - -ruleTester.run('require-public-api-controller', RequirePublicApiControllerRule, { - valid: [ - // The controller pattern: a class export, no `export =`. - { - code: '@PublicApiController("/tags") export class TagsPublicController {}', - filename: '/repo/packages/cli/src/public-api/v1/controllers/tags.public.controller.ts', - }, - // Named exports are fine. - { - code: 'export const helper = () => {};', - filename: '/repo/packages/cli/src/public-api/v1/handlers/tags/tags.handler.ts', - }, - ], - invalid: [ - // The legacy tuple module ends in `export = handlers`. - { - code: 'const handlers = {}; export = handlers;', - filename: '/repo/packages/cli/src/public-api/v1/handlers/tags/tags.handler.ts', - errors: [{ messageId: 'useController' }], - }, - ], -}); diff --git a/packages/@n8n/eslint-config/src/rules/require-public-api-controller.ts b/packages/@n8n/eslint-config/src/rules/require-public-api-controller.ts deleted file mode 100644 index 2fd64ef3870..00000000000 --- a/packages/@n8n/eslint-config/src/rules/require-public-api-controller.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { ESLintUtils } from '@typescript-eslint/utils'; - -/** - * New public API endpoints must be written as `@PublicApiController` classes - * (see the reference `TagsPublicController`), not the legacy - * `express-openapi-validator` tuple module that ends in `export = handlers`. - * - * `export =` (`TSExportAssignment`) is the unambiguous marker of the old style — - * controllers use `export class ... @PublicApiController(...)` and never - * `export =`. Scoped to `*.handler.ts` files via the `files` glob in - * `packages/cli/eslint.config.mjs`. Legacy handlers pending migration to - * controllers (API-70) are baselined in the allowlist there. - */ -export const RequirePublicApiControllerRule = ESLintUtils.RuleCreator.withoutDocs({ - meta: { - type: 'problem', - docs: { - description: 'Require public API endpoints to use the `@PublicApiController` class pattern.', - }, - messages: { - useController: - 'New public API endpoints must be an `@PublicApiController` class, not an `export =` handler tuple. See the reference `TagsPublicController`.', - }, - schema: [], - }, - defaultOptions: [], - create(context) { - return { - TSExportAssignment(node) { - context.report({ node, messageId: 'useController' }); - }, - }; - }, -}); diff --git a/packages/@n8n/eslint-plugin-community-nodes/package.json b/packages/@n8n/eslint-plugin-community-nodes/package.json index 478afc45833..4fa4af81adb 100644 --- a/packages/@n8n/eslint-plugin-community-nodes/package.json +++ b/packages/@n8n/eslint-plugin-community-nodes/package.json @@ -1,7 +1,7 @@ { "name": "@n8n/eslint-plugin-community-nodes", "type": "module", - "version": "0.35.0", + "version": "0.36.0", "main": "./dist/plugin.js", "types": "./dist/plugin.d.ts", "exports": { diff --git a/packages/@n8n/expression-runtime/package.json b/packages/@n8n/expression-runtime/package.json index 55b2c599eb4..7035426fcd7 100644 --- a/packages/@n8n/expression-runtime/package.json +++ b/packages/@n8n/expression-runtime/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/expression-runtime", - "version": "0.34.0", + "version": "0.35.0", "description": "Secure, isolated expression evaluation runtime for n8n", "main": "dist/cjs/index.js", "module": "dist/esm/index.js", diff --git a/packages/@n8n/imap/package.json b/packages/@n8n/imap/package.json index b40b8afdf3a..f97c92fde8e 100644 --- a/packages/@n8n/imap/package.json +++ b/packages/@n8n/imap/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/imap", - "version": "0.29.0", + "version": "0.30.0", "scripts": { "clean": "rimraf dist .turbo", "dev": "pnpm watch", diff --git a/packages/@n8n/inbound-auth/package.json b/packages/@n8n/inbound-auth/package.json index 46edcdc1967..90a9677ba89 100644 --- a/packages/@n8n/inbound-auth/package.json +++ b/packages/@n8n/inbound-auth/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/inbound-auth", - "version": "0.2.0", + "version": "0.3.0", "scripts": { "clean": "rimraf dist .turbo", "dev": "pnpm watch", @@ -23,7 +23,6 @@ "dist/**/*" ], "dependencies": { - "@n8n/api-types": "workspace:*", "@n8n/permissions": "workspace:*", "n8n-workflow": "workspace:*" }, diff --git a/packages/@n8n/inbound-auth/src/contracts.ts b/packages/@n8n/inbound-auth/src/contracts.ts index 6cdb363e0d2..b6029f3e9df 100644 --- a/packages/@n8n/inbound-auth/src/contracts.ts +++ b/packages/@n8n/inbound-auth/src/contracts.ts @@ -1,4 +1,3 @@ -import type { ConsentUiHints } from '@n8n/api-types'; import type { AuthPrincipal, SecurityContext } from '@n8n/permissions'; import type { OAuthResourceGrant } from 'n8n-workflow'; @@ -9,6 +8,13 @@ import type { SurfaceId } from './trusted-source-config'; /** What a protected resource reads from the user. The `User` entity satisfies it. */ export type ResourceUser = AuthPrincipal & { id: string; createdAt: Date }; +export interface ConsentUiHints { + /** design-system icon name (updatedIconSet) for the consent logo tile; omit to fall back to the generic mcp icon */ + icon?: string; + /** noun key inserted into first-party consent copy, e.g. 'form' (later 'webhook'); resolved to a localized word on the frontend */ + consentType?: string; +} + /** * Descriptor for an OAuth 2.1 protected resource served by this instance. * diff --git a/packages/@n8n/inbound-auth/src/trusted-source-config.ts b/packages/@n8n/inbound-auth/src/trusted-source-config.ts index d4a5be78515..ec9e5f5c913 100644 --- a/packages/@n8n/inbound-auth/src/trusted-source-config.ts +++ b/packages/@n8n/inbound-auth/src/trusted-source-config.ts @@ -38,7 +38,7 @@ export const ManagedBySchema = z.enum(['system', 'admin']); export type ManagedBy = z.infer; // An admin-supplied endpoint is fetched server-side, so it must be https. -const HttpsUrl = z +export const HttpsUrl = z .string() .url() .refine((url) => url.startsWith('https://'), { message: 'must be an https URL' }); diff --git a/packages/@n8n/inbound-auth/tsconfig.json b/packages/@n8n/inbound-auth/tsconfig.json index 2b8e2f65cef..33ccd974365 100644 --- a/packages/@n8n/inbound-auth/tsconfig.json +++ b/packages/@n8n/inbound-auth/tsconfig.json @@ -8,7 +8,6 @@ }, "include": ["src/**/*.ts"], "references": [ - { "path": "../api-types/tsconfig.build.json" }, { "path": "../permissions/tsconfig.build.json" }, { "path": "../../workflow/tsconfig.build.esm.json" } ] diff --git a/packages/@n8n/instance-ai/docs/configuration.md b/packages/@n8n/instance-ai/docs/configuration.md index ead60e0d748..f1285c15431 100644 --- a/packages/@n8n/instance-ai/docs/configuration.md +++ b/packages/@n8n/instance-ai/docs/configuration.md @@ -47,8 +47,6 @@ For built-in providers, the setup service recognizes `ANTHROPIC_API_KEY`, | `N8N_INSTANCE_AI_FOLDER_EXPLORATION_ENABLED` | boolean | `false` | Force-enable folder exploration (folder attribution and folder scoping on `workflows(action="list")`). `false` falls back to the PostHog flag. | | `N8N_INSTANCE_AI_BROWSER_USE_ENABLED` | boolean | `true` | Computer Use browser tooling, used for credential setup. | | `N8N_INSTANCE_AI_PROMPT_VERSION` | string | `''` | Pin every run on this instance to one published prompt profile, e.g. `concise@1`. Empty keeps the backend experiment assignment. An unknown version fails the Instance AI run, not the instance. See [prompt profiles](./prompt-profiles.md). | -| `N8N_INSTANCE_AI_ACTIVATION_CAPPED` | boolean | `false` | Activation capping. | -| `N8N_INSTANCE_AI_ACTIVATION_LOCK_MESSAGE_THRESHOLD` | number | `1` | Assistant messages that must be sent, in addition to instance activation, before an activation lock applies. | The PostHog flag `118_instance_ai_setup_overhaul` selects the setup flow. `variant` enables the async panel. `control` or an unavailable assignment uses @@ -180,6 +178,13 @@ The `instance-ai` module is in the default module set. It does not need to be listed in `N8N_ENABLED_MODULES`. `N8N_AI_ENABLED` controls older global AI features and does not gate Instance AI. +The `agents` module is also in the default module set. When it is active and +the Settings > Agents switch is on, the Assistant gets the `build-agent` and +`agent-context` tools, the `agent-builder` and `intent-recognition` skills, and +Agent preview handoff. When an admin turns the switch off, the Assistant loses +all of these at once. A run that is building an Agent fails at its next step. +To remove the module, add `agents` to `N8N_DISABLED_MODULES`. + Chat and the main UI are gated by `InstanceAiSettingsService.isInstanceAiEnabled()`. Member-facing entry points are additionally gated by `isSetupCompleted()`, which resolves the admin model selection, the assigned sandbox and search credentials, diff --git a/packages/@n8n/instance-ai/docs/sandboxing.md b/packages/@n8n/instance-ai/docs/sandboxing.md index c804085c39c..cd22889aa6f 100644 --- a/packages/@n8n/instance-ai/docs/sandboxing.md +++ b/packages/@n8n/instance-ai/docs/sandboxing.md @@ -128,6 +128,13 @@ and installed dependencies. The node-type catalog is written after sandbox creation because it is instance-specific and too large for the Daytona image request. +The knowledge base and runtime skills each have a manifest with a content +hash. Setup compares the manifest hash with the expected hash. When the +hashes do not match, setup writes the bundle again and writes the manifest +last. A matching manifest is trusted, and setup reads no other bundle file. +Each cached sandbox entry keeps the result, so later runs do not read the +manifest again. + When `N8N_INSTANCE_AI_SANDBOX_LINK_SDK` is enabled for local development, Instance AI packs and installs the local `@n8n/utils`, `@n8n/errors`, `n8n-workflow`, and `@n8n/workflow-sdk` packages. Build those packages before diff --git a/packages/@n8n/instance-ai/evaluations/README.md b/packages/@n8n/instance-ai/evaluations/README.md index 2912a71f5ec..6f56c5ca76c 100644 --- a/packages/@n8n/instance-ai/evaluations/README.md +++ b/packages/@n8n/instance-ai/evaluations/README.md @@ -31,7 +31,7 @@ Each run: 1. **Build** — the test case prompt goes to Instance AI, which builds a workflow. 2. **Phase 1** — the server analyzes the workflow and generates consistent mock data hints (one Sonnet call per scenario). -3. **Phase 2** — the workflow executes with every HTTP request intercepted and answered by an LLM using the node's configuration and API docs from Context7. +3. **Phase 2** — the workflow executes with every HTTP request intercepted and answered by an LLM using the node's configuration and its own knowledge of the API. 4. **Verify** — an LLM evaluates whether the scenario's success criteria were met and categorizes any failure by root cause (see [Failure categories](#failure-categories)). ### What gets mocked @@ -64,7 +64,6 @@ You need an n8n instance running with Instance AI enabled, a seeded owner accoun N8N_EVAL_PASSWORD=PlaywrightTest123 # Optional — see "Environment variables" for the full list LANGSMITH_API_KEY=... - CONTEXT7_API_KEY=... ``` 2. **Start the instance**: @@ -161,6 +160,20 @@ dotenvx run -f ../../../.env.local -- pnpm eval:instance-ai --iterations 3 | `--build-mcp-timeout-ms` | `120000` | `MCP_TIMEOUT` passed to the `claude` build subprocess — bounds one MCP tool call (`--build-via-mcp`) | | `--build-timeout-ms` | `1800000` | Wall-clock cap per build attempt; on expiry the `claude` process is killed so a hung build can't hold its lane. `0` disables. A timed-out build is not retried (`--build-via-mcp`) | +### Eval LLM settings (env) + +Set the mock settings on the n8n server process and the judge settings on the CLI process. Effort values apply to Anthropic models only: `low`, `medium`, `high`, `xhigh`, `max`. + +| Env var | Default | Description | +|---------|---------|-------------| +| `N8N_INSTANCE_AI_EVAL_MODEL` | `N8N_INSTANCE_AI_MODEL`, then `anthropic/claude-sonnet-4-6` | Model of every eval agent that does not pin one: the mock layer on the server, the user proxy on the CLI | +| `N8N_INSTANCE_AI_EVAL_EFFORT` | `medium` | Effort of the same agents | +| `N8N_INSTANCE_AI_EVAL_JUDGE_MODEL` | `anthropic/claude-sonnet-5-5` | Model of the judges: checklist verifier, expectations judge, binary LLM checks, computer-use grader. The user proxy and the mocks keep their model | +| `N8N_INSTANCE_AI_EVAL_JUDGE_EFFORT` | `high` | Effort of the judges | +| `N8N_INSTANCE_AI_EVAL_USAGE_LOG` | — | File path. Appends one JSON line per model call: agent, model, effort, input tokens with the cache split, output and reasoning tokens, duration, stop reason | + +Each verifier snapshot in `.data/` (or `--output-dir`) holds the verifier's input as `verifierInput`, so you can replay the verdict on another judge model. `DEBUG_JUDGE_CONTEXT=` writes each expectations-judge prompt. + **pass@k / pass^k**: with `--iterations N`, each unit — an execution scenario or an evaluated process/outcome expectation — is measured N times. `pass@k` is the fraction of units that passed *at least once*; `pass^k` is the fraction that passed *every* time. `pass@k` shows whether something is *possible*; `pass^k` shows whether it's *reliable*. ### Test-case datasets (logical groupings) @@ -241,7 +254,7 @@ Operational details: - Checks run **once per built workflow**, not per scenario — every scenario row in LangSmith carries the same outcomes for its build. - Failures don't flip `scenario_pass`; they're independent signals per the rubric design. -- LLM checks (`fulfills_user_request`, `valid_data_flow`, `correct_node_operations`, `handles_multiple_items`, `descriptive_node_names`, `response_describes_changes_accurately`) reuse the same Sonnet model as the verifier — auto-skipped (N/A) when no Anthropic key is set. +- LLM checks (`fulfills_user_request`, `valid_data_flow`, `correct_node_operations`, `handles_multiple_items`, `descriptive_node_names`, `response_describes_changes_accurately`) use the judge model (`N8N_INSTANCE_AI_EVAL_JUDGE_MODEL`) — auto-skipped (N/A) when no Anthropic key is set. ### Build expectations (per test case) @@ -250,7 +263,7 @@ A test case can declare optional natural-language assertions, split by what they - **`processExpectations: string[]`** — about *how the build went* (clarifications asked, push-back, ordering). Judged from the **conversation transcript** (plus the workflow and conversation metrics). They require a transcript, so they are **skipped in prebuilt/MCP runs**. e.g. `"Before building, the agent asked which Slack channel to use."` - **`outcomeExpectations: string[]`** — about the **resulting workflow**. Judged from the **workflow JSON**, so they **also run in prebuilt/MCP runs** (which have no transcript). e.g. `"The final workflow splits the records envelope before posting."` -Both are graded by the same Sonnet judge (`build-expectations/verifier.ts`) and **count as units in the pass rate**: evaluated expectations fold into the per-case and headline pass@k/pass^k alongside execution scenarios. They don't flip an individual scenario's pass/fail (each is its own unit), and a judge `incomplete` verdict is excluded from the count. A full build judges the union of both fields against the transcript; a prebuilt build judges only `outcomeExpectations` against the workflow. A case may omit `executionScenarios` entirely — a **build-only** case — and is then graded by these expectations plus the always-on workflow checks. +Both are graded by the same judge (`build-expectations/verifier.ts`) and **count as units in the pass rate**: evaluated expectations fold into the per-case and headline pass@k/pass^k alongside execution scenarios. They don't flip an individual scenario's pass/fail (each is its own unit), and a judge `incomplete` verdict is excluded from the count. A full build judges the union of both fields against the transcript; a prebuilt build judges only `outcomeExpectations` against the workflow. A case may omit `executionScenarios` entirely — a **build-only** case — and is then graded by these expectations plus the always-on workflow checks. Use them for things the binary checks and `successCriteria` don't cover: @@ -348,7 +361,6 @@ on disk. Losing this field turns it into a normal attachment test. | `LANGSMITH_ENDPOINT` | No | Region (`https://api.smith.langchain.com` US, `https://eu.api.smith.langchain.com` EU) | | `LANGSMITH_REVISION_ID` | No | Commit SHA to tag the experiment with (auto-set in CI) | | `LANGSMITH_BRANCH` | No | Branch name to tag the experiment with (auto-set in CI) | -| `CONTEXT7_API_KEY` | No | Context7 key for API-doc lookups. Improves mock realism for less-common services; the LLM falls back to training data when unset | | `N8N_AI_ASSISTANT_BASE_URL` | No | Set to `""` to bypass the hosted AI proxy and hit Anthropic directly — useful to avoid per-tenant quota during large batch runs | | `INSTANCE_AI_BRAVE_SEARCH_API_KEY` | No | Set on the **target n8n instance** (note: no `N8N_` prefix) to enable the builder's `web-search` action. Unset = the action returns zero results, which reads to the agent as "nothing found". A licensed instance with `N8N_AI_ASSISTANT_BASE_URL` set routes search through the AI proxy instead and ignores this key | | `N8N_INSTANCE_AI_RUN_DEBUG_ENABLED` | No | Set to `true` on the target n8n instance to capture orchestrator LLM steps and workflow code for the eval LLM debug report (`workflow-eval-llm-debug.html`). Off by default. | @@ -586,12 +598,15 @@ format that LangTracer exports. The tags give the expected route: - `routing` marks the file as a routing case. - `bucket:` is the main expected route. The summary groups cases by it. +- `clarity:` is optional: `clear`, `hidden` or `vague`. The summary + gives a score for each level under each bucket. - `accepts:` is another route that passes. A case can have more than one. The bucket always passes, except `bucket:clarify`: a clarify case must list the questions that pass, for example `accepts:clarify:open`. A token can add a steer: `:agent` passes a steer toward an Agent, and `:open` passes any steer except workflow only. This works for - `clarify` and `answer`. + `clarify` and `answer`. `clarify:workflow` passes a question that steers + toward a workflow. A case can add a second user turn with only `[stage directions]`: the facts that a user proxy uses to answer a question, for example @@ -634,6 +649,11 @@ The stub instance cannot replay a LangSmith thread, sign in to a browser, or hold folders or projects. The runner skips cases that need them and prints their ids. +`--output-dir ` writes `eval-results.json` in the format that LangTracer +reads. Each case has one expectation: the routes that it accepts. Each trial +is one verdict. A trial with no route, for example after a timeout, is not +graded. + ## Pairwise evals Pairwise evals score a built workflow against the dataset's `dos` / `donts` @@ -767,7 +787,7 @@ reliable signal. Two specific things to know: 1. **Build** — sends the test case prompt to Instance AI, which builds a workflow 2. **Phase 1** — analyzes the workflow and generates consistent mock data hints (one Sonnet call per scenario) -3. **Phase 2** — executes the workflow with all HTTP requests intercepted. Each request goes to an LLM that generates a realistic API response using the node's configuration and API documentation from Context7 +3. **Phase 2** — executes the workflow with all HTTP requests intercepted. Each request goes to an LLM that generates a realistic API response using the node's configuration and its own knowledge of the API 4. **Verify** — an LLM evaluates whether the scenario's success criteria were met and categorizes any failure by root cause (see Failure categories below) ### What gets mocked @@ -863,6 +883,8 @@ A direction governs only what it covers; otherwise the proxy answers every quest Each orchestrator build runs in its own empty project: the personal project of a freshly invited member, named like the lane owner. The owner still drives the build; the member only owns the project. An unlicensed instance cannot create team projects, so a new user is the only way to get a new project. Cleanup deletes the member, which also deletes its project and anything a timed-out build left there; under `--keep-workflows` the members stay, with their projects. Like the MCP lane, this needs a lane without SMTP, so invites return their accept token. +If the agent still reads a workflow that its build did not create or seed, the run fails as a harness fault: its rows and expectations fail with `framework_issue`. The pass rate shows the leak, builder analyses can filter it out by attribution, and the log names the workflow. A timeout still wins: if the build also timed out, the run stays neutral as `timeout`, like every timed-out run. + ### Credentials By default a build sees **no credentials**: the harness pins every build thread's credential view to the case's declared set (empty unless declared), so concurrent cases — and whatever happens to live on the instance — can never leak into a build. Every node mocks during verification. @@ -1302,7 +1324,6 @@ packages/cli/src/modules/instance-ai/eval/ ├── execution.service.ts # Phase 1 + Phase 2 orchestration ├── workflow-analysis.ts # Hint generation (Phase 1) ├── mock-handler.ts # Per-request mock generation (Phase 2) -├── api-docs.ts # Context7 API doc fetcher ├── node-config.ts # Node config serializer └── pin-data-generator.ts # LLM pin data for bypass nodes (Phase 1.5) ``` diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/assertion-judge.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/assertion-judge.test.ts index ad83a101516..a5aa47e80e6 100644 --- a/packages/@n8n/instance-ai/evaluations/__tests__/assertion-judge.test.ts +++ b/packages/@n8n/instance-ai/evaluations/__tests__/assertion-judge.test.ts @@ -5,7 +5,7 @@ import { vi } from 'vitest'; vi.mock('../../src/utils/eval-agents', () => ({ createEvalAgent: vi.fn(), EPHEMERAL_CACHE: {}, - SONNET_MODEL: 'test-sonnet-model', + JUDGE_MODEL: 'test-sonnet-model', })); import { createEvalAgent } from '../../src/utils/eval-agents'; diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/build-expectations-verifier.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/build-expectations-verifier.test.ts index 1a664f9a86e..7306eebe0f3 100644 --- a/packages/@n8n/instance-ai/evaluations/__tests__/build-expectations-verifier.test.ts +++ b/packages/@n8n/instance-ai/evaluations/__tests__/build-expectations-verifier.test.ts @@ -5,7 +5,7 @@ import { vi } from 'vitest'; vi.mock('../../src/utils/eval-agents', () => ({ createEvalAgent: vi.fn(), EPHEMERAL_CACHE: {}, - SONNET_MODEL: 'test-sonnet-model', + JUDGE_MODEL: 'test-sonnet-model', })); import { createEvalAgent } from '../../src/utils/eval-agents'; diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/build-orchestrator.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/build-orchestrator.test.ts index e2d05b32235..fe8a8904949 100644 --- a/packages/@n8n/instance-ai/evaluations/__tests__/build-orchestrator.test.ts +++ b/packages/@n8n/instance-ai/evaluations/__tests__/build-orchestrator.test.ts @@ -644,6 +644,45 @@ describe('createBuildOrchestrator', () => { expect(verdicts?.[0].attribution).toBe('framework_issue'); }); + it("fails, without judging, the expectations of a build that read another build's workflow", async () => { + vi.stubGlobal('fetch', vi.fn().mockResolvedValue({ ok: true })); + const building = vi.fn().mockResolvedValue(okBuild({ foreignWorkflowReads: ['other-wf'] })); + const deps = makeDeps([makeLane(1, building)], { + testCaseByFileSlug: new Map([ + ['case-a', baseCase({ processExpectations: ['builds the digest'] })], + ]), + }); + const orchestrator = createBuildOrchestrator(deps); + + await orchestrator.getOrBuild(0, 'case-a'); + + expect(vi.mocked(verifyBuildExpectations)).not.toHaveBeenCalled(); + const verdicts = await deps.buildExpectationsByKey.get('0:case-a'); + expect(verdicts?.[0]).toMatchObject({ pass: false, attribution: 'framework_issue' }); + // Counted, like the row: only `incomplete` keeps a verdict out of the pass rate. + expect(verdicts?.[0].incomplete).toBeFalsy(); + expect(verdicts?.[0].reason).toContain('another build'); + }); + + it("keeps a timed-out build that read another build's workflow neutral", async () => { + vi.stubGlobal('fetch', vi.fn().mockResolvedValue({ ok: true })); + const timeout = { kind: 'turn' as const, turn: 1, elapsedMs: 900_001 }; + const building = vi + .fn() + .mockResolvedValue(okBuild({ foreignWorkflowReads: ['other-wf'], timeout })); + const deps = makeDeps([makeLane(1, building)], { + testCaseByFileSlug: new Map([ + ['case-a', baseCase({ processExpectations: ['builds the digest'] })], + ]), + }); + const orchestrator = createBuildOrchestrator(deps); + + await orchestrator.getOrBuild(0, 'case-a'); + + const verdicts = await deps.buildExpectationsByKey.get('0:case-a'); + expect(verdicts?.[0]).toMatchObject({ incomplete: true, attribution: 'timeout' }); + }); + it('serves prebuilt workflows by fetching them, never invoking the builder', async () => { const tracedBuild = vi.fn().mockResolvedValue(okBuild()); const lane = makeLane(1, tracedBuild); diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/build-workflow-build-project.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/build-workflow-build-project.test.ts index bc6915a6009..edadf4bbf09 100644 --- a/packages/@n8n/instance-ai/evaluations/__tests__/build-workflow-build-project.test.ts +++ b/packages/@n8n/instance-ai/evaluations/__tests__/build-workflow-build-project.test.ts @@ -126,4 +126,27 @@ describe('buildWorkflow build project', () => { { type: 'agent', id: 'agent-1', projectId: 'build-project' }, ]); }); + + it("reports the agent's reads of another build's workflow, even when the build fails", async () => { + const actual = + await vi.importActual('../outcome/event-parser'); + vi.mocked(extractOutcomeFromEvents).mockImplementationOnce((events) => ({ + ...actual.extractOutcomeFromEvents(events), + toolCalls: [ + { + toolCallId: 'call-1', + toolName: 'workflows', + args: { action: 'get', workflowId: 'other-wf' }, + result: { id: 'other-wf' }, + durationMs: 0, + }, + ], + })); + const { client } = makeClient(); + + const result = await buildWorkflow({ client, ...baseConfig }); + + expect(result.success).toBe(false); + expect(result.foreignWorkflowReads).toEqual(['other-wf']); + }); }); diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/build-workflow-credential-test-target.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/build-workflow-credential-test-target.test.ts new file mode 100644 index 00000000000..95ced070aaa --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/__tests__/build-workflow-credential-test-target.test.ts @@ -0,0 +1,125 @@ +import { vi } from 'vitest'; + +import { N8nApiError, type N8nClient } from '../clients/n8n-client'; +import { buildWorkflow } from '../harness/build-workflow'; +import { + resolveCredentialSetupFixture, + startCredentialSetupLane, + type CredentialSetupLane, +} from '../harness/credential-setup-lane'; +import type { EvalLogger } from '../harness/logger'; + +vi.mock('../harness/chat-loop', async (importActual) => { + const actual = await importActual(); + return { + SSE_SETTLE_DELAY_MS: 0, + startSseConnection: vi.fn().mockResolvedValue(undefined), + waitForAllActivity: vi.fn().mockResolvedValue(undefined), + runMultiTurnConversation: vi.fn().mockResolvedValue(undefined), + recordUserTurn: vi.fn(), + buildAutoApprovePayload: actual.buildAutoApprovePayload, + }; +}); + +vi.mock('../harness/credential-setup-lane', async (importActual) => ({ + ...(await importActual()), + startCredentialSetupLane: vi.fn(), +})); + +vi.mock('../outcome/workflow-discovery', () => ({ + buildAgentOutcome: vi.fn().mockResolvedValue({ + workflowsCreated: [], + executionsRun: [], + dataTablesCreated: [], + finalText: 'done', + workflowJsons: [], + }), + extractWorkflowIdsFromMessages: vi.fn().mockReturnValue([]), +})); + +const silentLogger: EvalLogger = { + info: () => {}, + verbose: () => {}, + success: () => {}, + warn: () => {}, + error: () => {}, + isVerbose: false, +}; + +function makeClient(): N8nClient { + return { + getPersonalProjectId: vi.fn().mockResolvedValue('project-1'), + ensureThread: vi.fn().mockResolvedValue(undefined), + setThreadCredentialAllowlist: vi.fn().mockResolvedValue(undefined), + setThreadCredentialTestTarget: vi.fn().mockResolvedValue(undefined), + listCredentialIds: vi.fn().mockResolvedValue([]), + listCredentials: vi.fn().mockResolvedValue([]), + sendMessage: vi.fn().mockResolvedValue({ runId: 'run-1' }), + getThreadMessages: vi.fn().mockResolvedValue({ messages: [] }), + listWorkflows: vi.fn().mockResolvedValue([]), + } as unknown as N8nClient; +} + +async function buildWithLane( + lane: Partial, + client = makeClient(), +): Promise { + vi.mocked(startCredentialSetupLane).mockResolvedValue({ + local: false, + close: vi.fn().mockResolvedValue(undefined), + ...lane, + } as CredentialSetupLane); + await buildWorkflow({ + client, + skipWorkflowChecks: true, + preRunWorkflowIds: new Set(), + claimedWorkflowIds: new Set(), + logger: silentLogger, + conversation: [{ role: 'user', text: 'create a Slack credential' }], + credentialSetupSelection: await resolveCredentialSetupFixture({ credentialFixture: 'slack' }), + }); + return client; +} + +describe('buildWorkflow credential test target', () => { + it('aims the thread at the fixture stand-in before the first message', async () => { + const client = await buildWithLane({ + credentialType: 'slackApi', + verifyBaseUrl: 'http://stand-in.test:4100', + credentialUrlField: 'url', + }); + + expect(client.setThreadCredentialTestTarget).toHaveBeenCalledWith(expect.any(String), { + credentialType: 'slackApi', + baseUrl: 'http://stand-in.test:4100', + urlField: 'url', + }); + expect( + vi.mocked(client.setThreadCredentialTestTarget).mock.invocationCallOrder[0], + ).toBeLessThan(vi.mocked(client.sendMessage).mock.invocationCallOrder[0]); + }); + + it('still builds against a backend without the endpoint', async () => { + const client = makeClient(); + vi.mocked(client.setThreadCredentialTestTarget).mockRejectedValue( + new N8nApiError('Not found', 404), + ); + + await buildWithLane( + { + credentialType: 'slackApi', + verifyBaseUrl: 'http://stand-in.test:4100', + credentialUrlField: 'url', + }, + client, + ); + + expect(client.sendMessage).toHaveBeenCalled(); + }); + + it('sets no target when the fixture ships no stand-in', async () => { + const client = await buildWithLane({ credentialType: 'slackApi', credentialUrlField: 'url' }); + + expect(client.setThreadCredentialTestTarget).not.toHaveBeenCalled(); + }); +}); diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/build-workflow-single-turn-questions.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/build-workflow-single-turn-questions.test.ts new file mode 100644 index 00000000000..51aff8835bd --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/__tests__/build-workflow-single-turn-questions.test.ts @@ -0,0 +1,106 @@ +import { vi } from 'vitest'; + +import type { N8nClient } from '../clients/n8n-client'; +import { buildWorkflow } from '../harness/build-workflow'; +import { waitForAllActivity, type ConfirmationStrategy } from '../harness/chat-loop'; +import type { EvalLogger } from '../harness/logger'; +import type { CapturedEvent } from '../types'; + +const proxyAnswer = { + kind: 'questions', + answers: [{ questionId: 'key_choice', selectedOptions: ['Create a new API key'] }], +}; + +vi.mock('../harness/chat-loop', async (importActual) => { + const actual = await importActual(); + return { + SSE_SETTLE_DELAY_MS: 0, + startSseConnection: vi.fn().mockResolvedValue(undefined), + waitForAllActivity: vi.fn().mockResolvedValue(undefined), + runMultiTurnConversation: vi.fn().mockResolvedValue(undefined), + recordUserTurn: vi.fn(), + buildAutoApprovePayload: actual.buildAutoApprovePayload, + }; +}); + +vi.mock('../utils/user-proxy', () => ({ + UserProxyLlm: class { + respondToConfirmation = vi.fn().mockResolvedValue(proxyAnswer); + ingestEvents = vi.fn(); + decideFollowUp = vi.fn().mockResolvedValue({ kind: 'done' }); + getDecisionStats = vi.fn().mockReturnValue({}); + }, +})); + +vi.mock('../outcome/workflow-discovery', () => ({ + buildAgentOutcome: vi.fn().mockResolvedValue({ + workflowsCreated: [], + executionsRun: [], + dataTablesCreated: [], + finalText: 'done', + workflowJsons: [], + }), + extractWorkflowIdsFromMessages: vi.fn().mockReturnValue([]), +})); + +const silentLogger: EvalLogger = { + info: () => {}, + verbose: () => {}, + success: () => {}, + warn: () => {}, + error: () => {}, + isVerbose: false, +}; + +function makeClient(): N8nClient { + return { + getPersonalProjectId: vi.fn().mockResolvedValue('project-1'), + ensureThread: vi.fn().mockResolvedValue(undefined), + setThreadCredentialAllowlist: vi.fn().mockResolvedValue(undefined), + sendMessage: vi.fn().mockResolvedValue({ runId: 'run-1' }), + getThreadMessages: vi.fn().mockResolvedValue({ messages: [] }), + listWorkflows: vi.fn().mockResolvedValue([]), + } as unknown as N8nClient; +} + +function confirmationEvent(payload: Record): CapturedEvent { + return { + type: 'confirmation-request', + data: { type: 'confirmation-request', payload: { requestId: 'req-1', ...payload } }, + } as unknown as CapturedEvent; +} + +async function singleTurnStrategy(): Promise { + await buildWorkflow({ + client: makeClient(), + skipWorkflowChecks: true, + preRunWorkflowIds: new Set(), + claimedWorkflowIds: new Set(), + logger: silentLogger, + conversation: [{ role: 'user', text: 'create a Gemini credential' }], + }); + const strategy = vi.mocked(waitForAllActivity).mock.calls[0]?.[0].confirmationStrategy; + if (!strategy) throw new Error('single-turn build passed no confirmation strategy'); + return strategy; +} + +describe('buildWorkflow single-turn confirmations', () => { + beforeEach(() => vi.mocked(waitForAllActivity).mockClear()); + + it('answers ask-user questions through the user proxy instead of leaving them blank', async () => { + const strategy = await singleTurnStrategy(); + const response = await strategy( + confirmationEvent({ + inputType: 'questions', + questions: [{ id: 'key_choice', question: 'Which key?', type: 'single' }], + }), + ); + expect(response).toEqual(proxyAnswer); + }); + + it('keeps auto-approving every other confirmation', async () => { + const strategy = await singleTurnStrategy(); + const response = await strategy(confirmationEvent({ message: 'Open aistudio.google.com' })); + expect(response).toEqual({ kind: 'approval', approved: true }); + }); +}); diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/case-pipeline.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/case-pipeline.test.ts index 44664ecf613..a93b1063fa6 100644 --- a/packages/@n8n/instance-ai/evaluations/__tests__/case-pipeline.test.ts +++ b/packages/@n8n/instance-ai/evaluations/__tests__/case-pipeline.test.ts @@ -232,6 +232,52 @@ describe('createCasePipeline', () => { expect(vi.mocked(lane.tracedExecute)).not.toHaveBeenCalled(); }); + // Unlike a missing premise, a run that did not start clean still counts, so a leak + // shows in the pass rate. The attribution keeps it out of the builder's numbers. + it("fails a build that read another build's workflow as framework_issue, and counts it", async () => { + const lane = makeLane(); + const cached: CachedBuild = { + build: { ...okBuild(), foreignWorkflowReads: ['other-wf'] }, + lane, + buildDurationMs: 42, + }; + const pipeline = createCasePipeline(makeDeps(makeOrchestrator(cached))); + + const output = await pipeline.runRow(rowInputs('happy-path')); + + expect(output).toMatchObject({ + passed: false, + failureCategory: 'framework_issue', + attribution: 'framework_issue', + }); + expect(output.incomplete).toBeFalsy(); + expect(String(output.reasoning)).toContain('another build'); + expect(vi.mocked(lane.tracedExecute)).not.toHaveBeenCalled(); + }); + + // A timeout outranks the fault, as on every other timed-out build. + it("keeps a timed-out build that read another build's workflow out of the pass rate", async () => { + const lane = makeLane(); + const timeout = { kind: 'turn' as const, turn: 2, elapsedMs: 900_400 }; + const cached: CachedBuild = { + build: okBuild({ timeout, foreignWorkflowReads: ['other-wf'] }), + lane, + buildDurationMs: 42, + }; + const pipeline = createCasePipeline(makeDeps(makeOrchestrator(cached))); + + const output = await pipeline.runRow(rowInputs('happy-path')); + + expect(output).toMatchObject({ + passed: false, + incomplete: true, + attribution: 'timeout', + failureCategory: 'build_timeout', + buildTimeout: timeout, + }); + expect(vi.mocked(lane.tracedExecute)).not.toHaveBeenCalled(); + }); + it('preserves agent metadata when a prior run failed', async () => { const lane = makeLane(); const build = okBuild({ diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/checklist-verifier.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/checklist-verifier.test.ts index 5466fd7ef06..4b5590b876b 100644 --- a/packages/@n8n/instance-ai/evaluations/__tests__/checklist-verifier.test.ts +++ b/packages/@n8n/instance-ai/evaluations/__tests__/checklist-verifier.test.ts @@ -9,6 +9,7 @@ vi.mock('../../src/utils/eval-agents', () => ({ providerModelId: 'test-model', apiKey: 'test-key', })), + resolveJudgeModel: vi.fn(() => 'anthropic/test-model'), EPHEMERAL_CACHE: {}, })); diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/credential-setup-lane-stand-in.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/credential-setup-lane-stand-in.test.ts new file mode 100644 index 00000000000..bc181518ce2 --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/__tests__/credential-setup-lane-stand-in.test.ts @@ -0,0 +1,46 @@ +import { vi } from 'vitest'; + +import type { N8nClient } from '../clients/n8n-client'; +import { startBrowserRuntime } from '../harness/browser-runtime'; +import { + resolveCredentialSetupFixture, + startCredentialSetupLane, +} from '../harness/credential-setup-lane'; +import type { EvalLogger } from '../harness/logger'; + +vi.mock('../harness/browser-runtime', () => ({ + startBrowserRuntime: vi.fn(), + attachToRunningBrowser: vi.fn(), +})); + +const silentLogger: EvalLogger = { + info: () => {}, + verbose: () => {}, + success: () => {}, + warn: () => {}, + error: () => {}, + isVerbose: false, +}; + +describe('startCredentialSetupLane stand-in', () => { + it('exposes the shipped fixture stand-in and its credential field', async () => { + vi.mocked(startBrowserRuntime).mockResolvedValue({ + close: vi.fn().mockResolvedValue(undefined), + } as unknown as Awaited>); + const selection = await resolveCredentialSetupFixture({ credentialFixture: 'slack' }); + + const lane = await startCredentialSetupLane({ + client: {} as N8nClient, + selection, + logger: silentLogger, + }); + + try { + expect(lane?.credentialType).toBe('slackApi'); + expect(lane?.credentialUrlField).toBe('url'); + expect(lane?.verifyBaseUrl).toMatch(/^http:\/\/.+:\d+$/); + } finally { + await lane?.close(); + } + }); +}); diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/eval-artifact-output-dir.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/eval-artifact-output-dir.test.ts index 0720f169880..e4e3bdbbb00 100644 --- a/packages/@n8n/instance-ai/evaluations/__tests__/eval-artifact-output-dir.test.ts +++ b/packages/@n8n/instance-ai/evaluations/__tests__/eval-artifact-output-dir.test.ts @@ -1,4 +1,4 @@ -import { existsSync, mkdtempSync, readdirSync } from 'fs'; +import { existsSync, mkdtempSync, readFileSync, readdirSync } from 'fs'; import { tmpdir } from 'os'; import path from 'path'; @@ -123,6 +123,18 @@ describe('eval report artifacts — --output-dir contract', () => { return { logger, warnings }; } + const VERIFIER_INPUT = { + checklist: [ + { + id: 1, + description: 'posts once', + category: 'execution' as const, + strategy: 'llm' as const, + }, + ], + artifact: { workflowContext: 'wf', scenarioContext: 'scenario' }, + }; + async function writeSnapshot(testCaseName: string, outputDir?: string): Promise { const { logger, warnings } = collectingLogger(); await writeScenarioVerificationSnapshot({ @@ -133,6 +145,7 @@ describe('eval report artifacts — --output-dir contract', () => { result: CHECKLIST_RESULT, verificationResults: [CHECKLIST_RESULT], verifierAttempts: [], + verifierInput: VERIFIER_INPUT, logger, outputDir, }); @@ -150,6 +163,16 @@ describe('eval report artifacts — --output-dir contract', () => { expect(names[0]).toMatch(/^daily-digest_happy-path_.*\.json$/); }); + it('stores the verifier input for a replay', async () => { + const outputDir = freshOutputDir(); + + await writeSnapshot('daily digest', outputDir); + + const [name] = readdirSync(outputDir); + const snapshot = JSON.parse(readFileSync(path.join(outputDir, name), 'utf8')); + expect(snapshot.verifierInput).toEqual(VERIFIER_INPUT); + }); + it('creates the outputDir when it does not exist yet', async () => { const outputDir = path.join(freshOutputDir(), 'nested', 'run-3'); diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/eval-results-dispatcher-contract.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/eval-results-dispatcher-contract.test.ts index e7eb351156e..6504fb7d2d9 100644 --- a/packages/@n8n/instance-ai/evaluations/__tests__/eval-results-dispatcher-contract.test.ts +++ b/packages/@n8n/instance-ai/evaluations/__tests__/eval-results-dispatcher-contract.test.ts @@ -6,6 +6,9 @@ import { join } from 'path'; import type { CheckOutcome } from '../binaryChecks/types'; import { AGENT_ARTIFACT_CASE_CAP_BYTES } from '../harness/artifacts/agent-artifact'; +import type { RoutingCase } from '../routing/cases'; +import { writeRoutingEvalResults, type RoutingTrial } from '../routing/eval-results'; +import { casePasses } from '../routing/grade'; import { aggregateResults } from '../run/aggregator'; import { writeEvalResults } from '../run/persist'; import type { @@ -133,6 +136,8 @@ function iteration2(): WorkflowTestCaseResult { interface DispatcherView { experimentName?: string; testCases: Array<{ + testCaseFile?: string; + status?: string; buildSuccessCount: number; workflowJson?: { id: string }; agentArtifact?: Record; @@ -148,6 +153,7 @@ interface DispatcherView { expectation: string; pass: boolean; reason: string; + incomplete?: boolean; attribution?: string; }> | null>; buildCostUsdPerRun?: Array; @@ -448,3 +454,138 @@ describe('eval-results.json — dispatcher contract', () => { expect(tc.buildTurnsPerRun).toEqual([5, null]); }); }); + +describe('eval-results.json — dispatcher contract (routing)', () => { + const routingCase: RoutingCase = { + id: 'route-agent-support-inbox', + userMessage: 'Answer our support inbox.', + bucket: 'agent', + accepts: ['agent', 'clarify:agent'], + after: ['agent'], + clarity: 'hidden', + }; + + it('writes one test case per routing case and one verdict per trial', () => { + const dir = mkdtempSync(join(tmpdir(), 'eval-results-contract-')); + const jsonPath = writeRoutingEvalResults( + dir, + [ + { + routingCase, + trials: [ + { + resolution: { + route: 'agent', + evidence: 'build-agent call', + judgeReason: 'It builds an Agent.', + }, + passed: true, + turn: { streamStatus: 'stopped-on-route' }, + }, + { + resolution: { route: 'workflow', evidence: 'build-workflow call' }, + passed: false, + turn: { streamStatus: 'stopped-on-route' }, + }, + { + resolution: { route: 'none', evidence: 'end of turn (timed-out), judge failed' }, + passed: false, + turn: { streamStatus: 'timed-out', runError: 'Run timed out' }, + }, + ], + }, + ], + 3, + 1234, + ); + const report = jsonParse(readFileSync(jsonPath, 'utf8')); + + expect(report.testCases).toHaveLength(1); + const tc = report.testCases[0]; + expect(tc.testCaseFile).toBe('route-agent-support-inbox'); + expect(tc.status).toBe('verified'); + expect(tc.totalRuns).toBe(3); + // The same text that LangTracer stores for the case. The trial without a route is not evaluated. + const expectation = 'Routes to one of: agent, clarify:agent'; + expect(tc.buildExpectations).toEqual([ + expect.objectContaining({ expectation, passCount: 1, evaluatedCount: 2 }), + ]); + expect(tc.buildExpectationResultsPerRun).toEqual([ + [ + { + expectation, + pass: true, + reason: 'Route agent from build-agent call. Judge: It builds an Agent.', + }, + ], + [ + { + expectation, + pass: false, + reason: 'Route workflow from build-workflow call.', + attribution: 'builder_issue', + }, + ], + [ + { + expectation, + pass: false, + reason: + 'Not graded: no route from end of turn (timed-out), judge failed (Run timed out).', + incomplete: true, + attribution: 'timeout', + }, + ], + ]); + }); + + it('marks a case with no graded trial as not verified', () => { + const dir = mkdtempSync(join(tmpdir(), 'eval-results-contract-')); + const jsonPath = writeRoutingEvalResults( + dir, + [ + { + routingCase, + trials: [ + { + resolution: { + route: 'none', + evidence: 'end of turn (completed), judge failed', + judgeError: 'judge overloaded', + }, + passed: false, + turn: { streamStatus: 'completed' }, + }, + ], + }, + ], + 1, + 1234, + ); + const tc = jsonParse(readFileSync(jsonPath, 'utf8')).testCases[0]; + + expect(tc.status).toBe('notVerified'); + expect(tc.buildExpectationResultsPerRun[0]?.[0]).toMatchObject({ + incomplete: true, + attribution: 'verification_gap', + }); + }); + + it('gives LangTracer the counts for the verdict that the CLI prints', () => { + const graded = (passed: boolean): RoutingTrial => ({ + resolution: { route: passed ? 'agent' : 'workflow', evidence: 'build call' }, + passed, + turn: { streamStatus: 'stopped-on-route' }, + }); + const trials = [true, true, true, false, false].map(graded); + const dir = mkdtempSync(join(tmpdir(), 'eval-results-contract-')); + const jsonPath = writeRoutingEvalResults(dir, [{ routingCase, trials }], 5, 1234); + const [counts] = jsonParse(readFileSync(jsonPath, 'utf8')).testCases[0] + .buildExpectations; + + // The dispatcher's `foldBuildExpectations` passes an expectation on a strict majority of evaluated runs. + expect(counts).toMatchObject({ passCount: 3, evaluatedCount: 5 }); + expect(counts.passCount * 2 > counts.evaluatedCount).toBe(true); + expect(casePasses(trials)).toBe(true); + }); +}); diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/fixture-server.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/fixture-server.test.ts index 5ea5cf9ea43..9bf7f1b15e0 100644 --- a/packages/@n8n/instance-ai/evaluations/__tests__/fixture-server.test.ts +++ b/packages/@n8n/instance-ai/evaluations/__tests__/fixture-server.test.ts @@ -91,9 +91,13 @@ describe('provider fixtures', () => { urlField: 'host', verify: { path: '/v1beta/models', query: 'key' }, }, - // No `verify`: slackApi's test hardcodes its baseURL, so the stand-in can - // never be aimed at it. The value check reports itself unverifiable. - { type: 'slackApi', id: 'slack', host: 'api.slack.com', prefix: 'xoxb-' }, + { + type: 'slackApi', + id: 'slack', + host: 'api.slack.com', + prefix: 'xoxb-', + verify: { path: '/api/users.profile.get', header: 'Authorization', scheme: 'Bearer' }, + }, ]; it.each(SHIPPED)('ships the $id fixture keyed on $type', async (row) => { diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/foreign-workflow-reads.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/foreign-workflow-reads.test.ts new file mode 100644 index 00000000000..fa90bcfd6ec --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/__tests__/foreign-workflow-reads.test.ts @@ -0,0 +1,99 @@ +import { findForeignWorkflowReads } from '../outcome/foreign-reads'; +import type { CapturedToolCall } from '../types'; + +function call( + toolName: string, + args: Record, + outcome: { result?: unknown; error?: string } = { result: { success: true } }, +): CapturedToolCall { + return { + toolCallId: `${toolName}-${String(Math.random())}`, + toolName, + args, + durationMs: 0, + ...outcome, + }; +} + +const created = call( + 'build-workflow', + { filePath: 'src/workflows/digest.workflow.ts', name: 'Daily Email Digest' }, + { result: { success: true, workflowId: 'mine' } }, +); + +describe('findForeignWorkflowReads', () => { + it('flags a successful read of a workflow this build did not create or seed', () => { + const reads = findForeignWorkflowReads( + [call('workflows', { action: 'get', workflowId: 'other' }, { result: { id: 'other' } })], + [], + ); + + expect(reads).toEqual(['other']); + }); + + it('ignores the workflows the build created, and later reads of them', () => { + const reads = findForeignWorkflowReads( + [created, call('workflows', { action: 'get', workflowId: 'mine' })], + [], + ); + + expect(reads).toEqual([]); + }); + + it('ignores seeded workflows', () => { + const reads = findForeignWorkflowReads( + [call('workflows', { action: 'get', workflowId: 'seeded' })], + ['seeded'], + ); + + expect(reads).toEqual([]); + }); + + it('ignores reads that failed, so an invented id is not a leak', () => { + const reads = findForeignWorkflowReads( + [ + call('workflows', { action: 'get', workflowId: 'ghost' }, { error: 'Workflow not found' }), + call( + 'workflows', + { action: 'setup', workflowId: 'ghost-2' }, + { result: { success: false, error: 'not found' } }, + ), + ], + [], + ); + + expect(reads).toEqual([]); + }); + + it("flags another build's workflows in a list result", () => { + const reads = findForeignWorkflowReads( + [ + created, + call( + 'workflows', + { action: 'list', scope: 'instance' }, + { result: JSON.stringify({ workflows: [{ id: 'mine' }, { id: 'other' }] }) }, + ), + ], + [], + ); + + expect(reads).toEqual(['other']); + }); + + it("flags an edit of another build's workflow, once", () => { + const reads = findForeignWorkflowReads( + [ + call('workflows', { action: 'get', workflowId: 'other' }), + call( + 'build-workflow', + { filePath: 'src/workflows/digest.workflow.ts', workflowId: 'other' }, + { result: { success: true, workflowId: 'other' } }, + ), + ], + [], + ); + + expect(reads).toEqual(['other']); + }); +}); diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/scenario-budget-stop.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/scenario-budget-stop.test.ts index 78d24dfab3e..4942852c879 100644 --- a/packages/@n8n/instance-ai/evaluations/__tests__/scenario-budget-stop.test.ts +++ b/packages/@n8n/instance-ai/evaluations/__tests__/scenario-budget-stop.test.ts @@ -107,3 +107,27 @@ describe('server-side budget stop', () => { expect(String(failure)).not.toMatch(/eval budget|operation was aborted/i); }); }); + +// Nothing ran, so the verifier must not judge an empty artifact. +describe('server-side framework issue', () => { + const issue = 'FRAMEWORK ISSUE: mock hints failed: Eval model provider call failed (HTTP 401)'; + + it('throws out of a workflow scenario', async () => { + const client = mock(); + client.executeWithLlmMock.mockResolvedValue(execResult([issue])); + + await expect(executeScenario(client, 'wf-1', scenario, [], silentLogger)).rejects.toThrow( + issue, + ); + }); + + it('throws out of an agent scenario', async () => { + const client = mock(); + client.getPersonalProjectId.mockResolvedValue('proj-1'); + client.executeAgentWithLlmMock.mockResolvedValue(agentResult([issue])); + + await expect( + executeAgentScenario(client, 'agent-1', scenario, 'context', silentLogger), + ).rejects.toThrow(issue); + }); +}); diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/stub-services.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/stub-services.test.ts index 374ff5eccef..fe0f3d6ae2e 100644 --- a/packages/@n8n/instance-ai/evaluations/__tests__/stub-services.test.ts +++ b/packages/@n8n/instance-ai/evaluations/__tests__/stub-services.test.ts @@ -7,7 +7,11 @@ import { promises as fs } from 'node:fs'; import { tmpdir } from 'node:os'; import path from 'node:path'; -import { createStubServices, resolveEvalNodeDefinitionDirs } from '../harness/stub-services'; +import { + createStubServices, + missingEvalNodeData, + resolveEvalNodeDefinitionDirs, +} from '../harness/stub-services'; async function writeNodesJson(entries: unknown[]): Promise { const dir = await fs.mkdtemp(path.join(tmpdir(), 'eval-stub-services-')); @@ -151,6 +155,41 @@ describe('resolveEvalNodeDefinitionDirs', () => { }); }); +describe('missingEvalNodeData', () => { + const roots: string[] = []; + afterAll(async () => { + await Promise.all(roots.map(async (root) => await fs.rm(root, { recursive: true }))); + }); + + async function createNodeData() { + const root = await fs.mkdtemp(path.join(tmpdir(), 'eval-node-data-')); + roots.push(root); + const paths = { + nodesJson: path.join(root, 'nodes.json'), + nodesBase: path.join(root, 'nodes-base', 'dist', 'node-definitions'), + nodesLangchain: path.join(root, '@n8n', 'nodes-langchain', 'dist', 'node-definitions'), + }; + await fs.writeFile(paths.nodesJson, '[]', 'utf8'); + await fs.mkdir(paths.nodesBase, { recursive: true }); + await fs.mkdir(paths.nodesLangchain, { recursive: true }); + return { root, paths }; + } + + it('returns no paths when all node data exists', async () => { + const { root, paths } = await createNodeData(); + expect(missingEvalNodeData(paths.nodesJson, root)).toEqual([]); + }); + + it.each(['nodesJson', 'nodesBase', 'nodesLangchain'] as const)( + 'returns the %s path when it is missing', + async (key) => { + const { root, paths } = await createNodeData(); + await fs.rm(paths[key], { recursive: true }); + expect(missingEvalNodeData(paths.nodesJson, root)).toEqual([paths[key]]); + }, + ); +}); + describe('createStubServices with a seed', () => { const seed = { workflows: [ diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/subagent-runner.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/subagent-runner.test.ts index b01174c17a0..213c46f555f 100644 --- a/packages/@n8n/instance-ai/evaluations/__tests__/subagent-runner.test.ts +++ b/packages/@n8n/instance-ai/evaluations/__tests__/subagent-runner.test.ts @@ -14,6 +14,7 @@ import { runBinaryChecks } from '../binaryChecks/index'; import type { N8nClient, WorkflowResponse } from '../clients/n8n-client'; import { buildWorkflow, type BuildResult } from '../harness/build-workflow'; import { cleanupBuild } from '../harness/cleanup'; +import { JUDGE_MODEL } from '../../src/utils/eval-agents'; import { runWorkflowBuildEval } from '../subagent/runner'; const mockedBuildWorkflow = vi.mocked(buildWorkflow); @@ -110,6 +111,33 @@ describe('runWorkflowBuildEval', () => { expect(result.error).toBeUndefined(); }); + it('runs binary checks on the judge model when no model is set', async () => { + const workflow = makeWorkflow(); + mockedBuildWorkflow.mockResolvedValue({ + success: true, + workflowId: workflow.id, + workflowJsons: [workflow], + createdWorkflowIds: [workflow.id], + createdDataTableIds: [], + }); + + await runWorkflowBuildEval( + { id: 'case-judge', prompt: 'Build a webhook workflow' }, + { timeoutMs: 1234, verbose: false }, + { + client: makeClient(), + deleteAfterRun: true, + preRunWorkflowIds: new Set(), + claimedWorkflowIds: new Set(), + }, + ); + + expect(mockedRunBinaryChecks).toHaveBeenCalledWith( + workflow, + expect.objectContaining({ modelId: JUDGE_MODEL }), + ); + }); + it('returns failed feedback when the orchestrator produces no workflow', async () => { const build: BuildResult = { success: false, diff --git a/packages/@n8n/instance-ai/evaluations/__tests__/transient-error.test.ts b/packages/@n8n/instance-ai/evaluations/__tests__/transient-error.test.ts index 1c42672cd58..04fedcafb62 100644 --- a/packages/@n8n/instance-ai/evaluations/__tests__/transient-error.test.ts +++ b/packages/@n8n/instance-ai/evaluations/__tests__/transient-error.test.ts @@ -7,6 +7,7 @@ import { isTransientProviderError, MAX_EXEC_ATTEMPTS, providerRetryBackoffMs, + throwIfFrameworkIssue, } from '../harness/transient-error'; describe('transient-error', () => { @@ -209,3 +210,18 @@ describe('transient-error', () => { }); }); }); + +describe('throwIfFrameworkIssue', () => { + it('throws the harness failure so the caller records framework_issue without a verifier', () => { + const message = + 'FRAMEWORK ISSUE: Phase 1.5 pin data generation failed: Eval model provider call failed (HTTP 401): invalid x-api-key'; + expect(() => throwIfFrameworkIssue({ success: false, errors: [message] })).toThrow(message); + }); + + it('ignores a workflow that ran and failed on its own', () => { + expect(() => + throwIfFrameworkIssue({ success: false, errors: ['Node "Slack": channel_not_found'] }), + ).not.toThrow(); + expect(() => throwIfFrameworkIssue({ success: true, errors: [] })).not.toThrow(); + }); +}); diff --git a/packages/@n8n/instance-ai/evaluations/binaryChecks/checks/create-llm-check.ts b/packages/@n8n/instance-ai/evaluations/binaryChecks/checks/create-llm-check.ts index ace12c307b7..2e739c81a6f 100644 --- a/packages/@n8n/instance-ai/evaluations/binaryChecks/checks/create-llm-check.ts +++ b/packages/@n8n/instance-ai/evaluations/binaryChecks/checks/create-llm-check.ts @@ -42,7 +42,12 @@ function getOrCreateAgent(name: string, modelId: string, instructions: string): const key = `${name}:${modelId}`; let agent = agentCache.get(key); if (!agent) { - agent = createEvalAgent(`eval-binary-${name}`, { model: modelId, instructions, cache: true }); + agent = createEvalAgent(`eval-binary-${name}`, { + model: modelId, + instructions, + cache: true, + judge: true, + }); agentCache.set(key, agent); } return agent; diff --git a/packages/@n8n/instance-ai/evaluations/build-expectations/assertion-judge.ts b/packages/@n8n/instance-ai/evaluations/build-expectations/assertion-judge.ts index 455eca3a608..4bc1949944b 100644 --- a/packages/@n8n/instance-ai/evaluations/build-expectations/assertion-judge.ts +++ b/packages/@n8n/instance-ai/evaluations/build-expectations/assertion-judge.ts @@ -1,7 +1,7 @@ import type { Message } from '@n8n/agents'; import { z } from 'zod'; -import { SONNET_MODEL, createEvalAgent } from '../../src/utils/eval-agents'; +import { JUDGE_MODEL, createEvalAgent } from '../../src/utils/eval-agents'; import { BUILD_EXPECTATIONS_VERIFY_PROMPT } from '../system-prompts/build-expectations-verify'; import type { BuildExpectationResult } from '../types'; @@ -23,7 +23,6 @@ export const expectationResultSchema = z.object({ ), }); -const JUDGE_MODEL = SONNET_MODEL; const MAX_VERIFY_ATTEMPTS = 2; const VERIFY_ATTEMPT_TIMEOUT_MS = 120_000; @@ -55,6 +54,7 @@ export async function judgeExpectations( instructions: BUILD_EXPECTATIONS_VERIFY_PROMPT, cache: true, model: JUDGE_MODEL, + judge: true, }).structuredOutput(expectationResultSchema); const abortController = new AbortController(); diff --git a/packages/@n8n/instance-ai/evaluations/checklist/verifier.ts b/packages/@n8n/instance-ai/evaluations/checklist/verifier.ts index b2a9b136bce..ac4521e64c5 100644 --- a/packages/@n8n/instance-ai/evaluations/checklist/verifier.ts +++ b/packages/@n8n/instance-ai/evaluations/checklist/verifier.ts @@ -5,6 +5,7 @@ import { z } from 'zod'; import { EPHEMERAL_CACHE, createEvalAgent, + resolveJudgeModel, resolveEvalModelConfig, } from '../../src/utils/eval-agents'; import type { VerificationArtifact } from '../harness/scenario-execution'; @@ -38,10 +39,10 @@ export const VERIFY_ATTEMPT_TIMEOUTS_MS = [60_000, 120_000, 240_000]; export const VERIFY_INACTIVITY_TIMEOUT_MS = 45_000; /** * Completion budget for checklist JSON. Some OpenAI-compatible defaults (~250) - * truncate mid-result (~298 tokens observed); 4096 leaves headroom for thinking - * tokens plus multi-item checklists. + * truncate mid-result (~298 tokens observed). Judges at effort high think past 4096 + * (Sonnet 4.6 / 5 replays hit it), so leave room for thinking plus the JSON. */ -export const VERIFIER_MAX_OUTPUT_TOKENS = 4_096; +export const VERIFIER_MAX_OUTPUT_TOKENS = 16_384; const VERIFIER_DEBUG = process.env.N8N_EVAL_VERIFIER_DEBUG === '1'; function jitteredPauseMs(attempt: number): number { @@ -171,7 +172,7 @@ async function runNativeOpenAiVerifier( assistantText: string; parsed: z.infer | undefined; }> { - const model = resolveEvalModelConfig(); + const model = resolveEvalModelConfig(resolveJudgeModel()); const requestBody = { model: model.providerModelId, max_output_tokens: VERIFIER_MAX_OUTPUT_TOKENS, @@ -395,7 +396,7 @@ export async function verifyChecklist( const validIds = new Set(llmItems.map((i) => i.id)); const attempts: VerifierAttemptDebug[] = []; - const model = resolveEvalModelConfig(); + const model = resolveEvalModelConfig(resolveJudgeModel()); const useNativeOpenAiVerifier = model.provider === 'openai'; logVerifierDebug('request summary', { @@ -454,6 +455,7 @@ export async function verifyChecklist( const agent = createEvalAgent('eval-checklist-verifier', { instructions: MOCK_EXECUTION_VERIFY_PROMPT, cache: true, + judge: true, }).structuredOutput(checklistResultSchema); // The inactivity watchdog arms on the FIRST chunk (inside the consume diff --git a/packages/@n8n/instance-ai/evaluations/clients/n8n-client.ts b/packages/@n8n/instance-ai/evaluations/clients/n8n-client.ts index baf0f714b31..ff1b9522e56 100644 --- a/packages/@n8n/instance-ai/evaluations/clients/n8n-client.ts +++ b/packages/@n8n/instance-ai/evaluations/clients/n8n-client.ts @@ -1000,6 +1000,17 @@ export class N8nClient { }); } + /** Send the thread's connection tests for one credential type to a provider stand-in. */ + async setThreadCredentialTestTarget( + threadId: string, + target: { credentialType: string; baseUrl: string; urlField: string }, + ): Promise { + await this.fetch('/rest/instance-ai/eval/thread-credential-test-target', { + method: 'POST', + body: { threadId, ...target }, + }); + } + /** * Seed an existing thread with a previously exported conversation: the * referenced workflows are recreated (node credentials stripped server-side), diff --git a/packages/@n8n/instance-ai/evaluations/computer-use/README.md b/packages/@n8n/instance-ai/evaluations/computer-use/README.md index 87f691080d2..afd46375c1a 100644 --- a/packages/@n8n/instance-ai/evaluations/computer-use/README.md +++ b/packages/@n8n/instance-ai/evaluations/computer-use/README.md @@ -295,7 +295,7 @@ in which case the explicit one wins. | Default | What it checks | |---|---| | `security.noSecretLeak` | Tool args, tool results, and final agent text scanned for PEM key headers, common API-key prefixes, and any literal in `extraLiterals`. | -| `llm.taskCompleted` | LLM-as-judge over the agent's final text + tool-call summary. Fails when the agent stops in a confused/apologetic state, asks the user to paste secrets into chat, or otherwise doesn't deliver concrete locations for the required values. Closes the gap between trace-level checks ("called the right tools") and outcome ("the user got what they came for"). Defaults to a small/cheap judge model; override per-scenario with `model` and/or scenario-specific `criteria`. | +| `llm.taskCompleted` | LLM-as-judge over the agent's final text + tool-call summary. Fails when the agent stops in a confused/apologetic state, asks the user to paste secrets into chat, or otherwise doesn't deliver concrete locations for the required values. Closes the gap between trace-level checks ("called the right tools") and outcome ("the user got what they came for"). Defaults to the judge model (`N8N_INSTANCE_AI_EVAL_JUDGE_MODEL`, `claude-sonnet-5-5` at high effort); override per-scenario with `model` and/or scenario-specific `criteria`. | Scenarios tagged `requires:browser-bootstrap` additionally get `trace.toolsMustNotError` because a hung browser tool typically masquerades diff --git a/packages/@n8n/instance-ai/evaluations/computer-use/__tests__/graders-llm.test.ts b/packages/@n8n/instance-ai/evaluations/computer-use/__tests__/graders-llm.test.ts index 77093aa3b67..2bbb15141e1 100644 --- a/packages/@n8n/instance-ai/evaluations/computer-use/__tests__/graders-llm.test.ts +++ b/packages/@n8n/instance-ai/evaluations/computer-use/__tests__/graders-llm.test.ts @@ -10,7 +10,7 @@ import { vi } from 'vitest'; vi.mock('../../../src/utils/eval-agents', () => ({ - SONNET_MODEL: 'anthropic/claude-haiku-4-6', + JUDGE_MODEL: 'anthropic/claude-haiku-4-6', createEvalAgent: vi.fn(), extractText: vi.fn(), })); diff --git a/packages/@n8n/instance-ai/evaluations/computer-use/graders/llm.ts b/packages/@n8n/instance-ai/evaluations/computer-use/graders/llm.ts index 5962723cb1f..8edd16a9626 100644 --- a/packages/@n8n/instance-ai/evaluations/computer-use/graders/llm.ts +++ b/packages/@n8n/instance-ai/evaluations/computer-use/graders/llm.ts @@ -2,13 +2,13 @@ // LLM-as-judge grader: did the agent actually complete the task? // // Reads the scenario's user prompt + the agent's final text + a compact -// summary of tool calls, asks a small/cheap LLM "did the agent succeed?", +// summary of tool calls, asks the judge model "did the agent succeed?", // and converts the verdict to a GraderResult. Catches failure modes the // trace-level graders can't see (e.g. the agent gave up with an apologetic // message but mechanically called the right tools). // --------------------------------------------------------------------------- -import { createEvalAgent, extractText, SONNET_MODEL } from '../../../src/utils/eval-agents'; +import { createEvalAgent, extractText, JUDGE_MODEL } from '../../../src/utils/eval-agents'; import { parseJudgeVerdict, REASONING_FIRST_SUFFIX } from '../../utils/llm-judge'; import type { GraderResult, @@ -17,7 +17,8 @@ import type { ScenarioTrace, } from '../types'; -const DEFAULT_TIMEOUT_MS = 30_000; +// Judges think at high effort, so match the binary checks' headroom. +const DEFAULT_TIMEOUT_MS = 60_000; const SYSTEM_PROMPT = `You are a strict evaluator deciding whether an AI assistant successfully completed the task a user asked it to do. @@ -90,13 +91,14 @@ export async function gradeTaskCompleted( scenarioCategory: ScenarioCategory, grader: LlmTaskCompletedGrader, ): Promise { - const model = grader.model ?? SONNET_MODEL; + const model = grader.model ?? JUDGE_MODEL; const timeoutMs = grader.timeoutMs ?? DEFAULT_TIMEOUT_MS; const agent = createEvalAgent('eval-llm-task-completed', { model, instructions: SYSTEM_PROMPT, cache: true, + judge: true, }); const values: Record = { diff --git a/packages/@n8n/instance-ai/evaluations/computer-use/types.ts b/packages/@n8n/instance-ai/evaluations/computer-use/types.ts index 922552fe974..dcd7887d143 100644 --- a/packages/@n8n/instance-ai/evaluations/computer-use/types.ts +++ b/packages/@n8n/instance-ai/evaluations/computer-use/types.ts @@ -199,9 +199,9 @@ export interface LlmTaskCompletedGrader { * pause-for-user containing locations for both Client ID and Client Secret"). */ criteria?: string; - /** Defaults to a small/cheap judge. */ + /** Defaults to the judge model (`N8N_INSTANCE_AI_EVAL_JUDGE_MODEL`). */ model?: string; - /** Override timeout (default 30_000 ms). */ + /** Override timeout (default 60_000 ms). */ timeoutMs?: number; } diff --git a/packages/@n8n/instance-ai/evaluations/discovery/cli.ts b/packages/@n8n/instance-ai/evaluations/discovery/cli.ts index af8ac59e2fd..ca78123883c 100644 --- a/packages/@n8n/instance-ai/evaluations/discovery/cli.ts +++ b/packages/@n8n/instance-ai/evaluations/discovery/cli.ts @@ -7,6 +7,7 @@ // pnpm eval:discovery --filter slack-oauth --verbose // pnpm eval:discovery --trials 5 // pnpm eval:discovery --cases-dir # routing mode +// pnpm eval:discovery --cases-dir --output-dir // // Loads scenarios from evaluations/data/discovery/, runs each scenario × N // trials via the in-process runner, reports per-scenario pass-rates, exits @@ -17,22 +18,25 @@ // the format LangTracer exports. A judge ends each trial as soon as the // Assistant picks a route. When a case has stage directions, the user proxy // answers up to 2 accepted questions: on the card in the same run, or in a -// reply turn of the same thread after a question in text. The CLI prints a pass rate per bucket. -// It always exits 0: it measures routing and does not gate a merge. +// reply turn of the same thread after a question in text. The CLI prints a pass rate per bucket, +// and per clarity level in each bucket. `--output-dir` also writes `eval-results.json` for +// LangTracer (see ../routing/eval-results.ts). It always exits 0: it measures routing and does +// not gate a merge. // --------------------------------------------------------------------------- import { runDiscoveryScenario, runOrchestratorTurn, type DiscoveryRunResult } from './runner'; import { createSeededThread } from './seeded-turn'; import type { DiscoveryTestCase } from './types'; import { buildResumeData, toConfirmationData } from '../../src/runtime/confirmation-payload'; -import { isAgentFeatureEnabled } from '../../src/utils/agent-feature-enabled'; import { loadDiscoveryTestCasesWithFiles } from '../data/discovery'; +import { defaultNodesJsonPath, missingEvalNodeData } from '../harness/stub-services'; import { loadRoutingCases, ROUTING_BUCKETS, - type RoutingBucket, + ROUTING_CLARITIES, type RoutingCase, } from '../routing/cases'; +import { writeRoutingEvalResults, type RoutingCaseResult } from '../routing/eval-results'; import { afterQuestion, answeredQuestions, @@ -66,6 +70,8 @@ interface CliArgs { failOnZeroPass: boolean; /** Folder of routing cases. Set switches the CLI to routing mode. */ casesDir?: string; + /** Routing mode writes `eval-results.json` here. */ + outputDir?: string; } const DEFAULT_MODEL = process.env.N8N_INSTANCE_AI_EVAL_MODEL ?? 'anthropic/claude-sonnet-4-6'; @@ -166,6 +172,13 @@ function parseArgs(argv: string[]): CliArgs { process.exit(1); } break; + case '--output-dir': + args.outputDir = argv[++i]; + if (!args.outputDir) { + console.error('--output-dir needs a directory for eval-results.json.'); + process.exit(1); + } + break; default: break; } @@ -394,17 +407,13 @@ async function runRoutingMode(args: CliArgs, casesDir: string): Promise { console.log(`No routing cases found in ${casesDir}.`); return; } - if (!isAgentFeatureEnabled()) { - console.warn( - 'Warning: the Agents module is off, so the Assistant cannot build an Agent and agent cases fail. Set N8N_ENABLED_MODULES=agents,instance-ai.', - ); - } console.log( `Running ${String(cases.length)} routing case(s) × ${String(args.trials)} trial(s) (model: ${args.modelId}, concurrency: ${String(args.concurrency)}).\n`, ); - const results: Array<{ bucket: RoutingBucket; passed: boolean }> = []; + const startedAt = Date.now(); + const results: Array = []; let runErrors = 0; let judgeErrors = 0; @@ -416,7 +425,7 @@ async function runRoutingMode(args: CliArgs, casesDir: string): Promise { return trial.resolution.route === 'none' ? await runRoutingTrial(args, routingCase) : trial; }); - const passed = casePasses(trials.filter((t) => t.passed).length, trials.length); + const passed = casePasses(trials); const after = routingCase.direction ? `; after a reply ${routingCase.after.join(' | ')}` : ''; console.log( `${passed ? '✓' : '✗'} ${trials.map((t) => routeLabel(t.resolution)).join(', ')} (accepts ${routingCase.accepts.join(' | ')}${after})`, @@ -433,20 +442,36 @@ async function runRoutingMode(args: CliArgs, casesDir: string): Promise { if (turn.runError) console.log(` run error: ${turn.runError}`); } - results.push({ bucket: routingCase.bucket, passed }); + results.push({ routingCase, trials, passed }); } - console.log('\n=== Routing summary (a case passes when 2/3 of its trials pass) ==='); + console.log( + '\n=== Routing summary (a case passes when more than half of its graded trials pass) ===', + ); const summaryLine = (name: string, rows: typeof results) => console.log(` ${name.padEnd(8)} ${percent(rows.filter((r) => r.passed).length, rows.length)}`); for (const name of ROUTING_BUCKETS) { - const rows = results.filter((r) => r.bucket === name); - if (rows.length > 0) summaryLine(name, rows); + const rows = results.filter((r) => r.routingCase.bucket === name); + if (rows.length === 0) continue; + summaryLine(name, rows); + for (const clarity of ROUTING_CLARITIES) { + const cell = rows.filter((r) => r.routingCase.clarity === clarity); + if (cell.length > 0) summaryLine(` ${clarity}`, cell); + } } summaryLine('total', results); if (runErrors > 0 || judgeErrors > 0) { console.log(`Errored trials: ${String(runErrors)} run, ${String(judgeErrors)} judge.`); } + if (args.outputDir) { + const jsonPath = writeRoutingEvalResults( + args.outputDir, + results, + args.trials, + Date.now() - startedAt, + ); + console.log(`Results: ${jsonPath}`); + } } // --------------------------------------------------------------------------- @@ -463,6 +488,21 @@ async function main(): Promise { process.exit(1); } + // The stubs read node data from build outputs. Stop here, because without it + // every trial runs with no node types and shows no error. + const missing = missingEvalNodeData(args.nodesJsonPath ?? defaultNodesJsonPath()); + if (missing.length > 0) { + console.error( + [ + 'Error: node data for the eval stubs is missing:', + ...missing.map((p) => ` - ${p}`), + 'Build the node packages: pnpm --filter n8n-nodes-base --filter @n8n/n8n-nodes-langchain build', + 'Then generate nodes.json: run `pnpm export:nodes` in packages/@n8n/ai-workflow-builder.ee.', + ].join('\n'), + ); + process.exit(1); + } + if (args.casesDir) { await runRoutingMode(args, args.casesDir); } else { diff --git a/packages/@n8n/instance-ai/evaluations/discovery/runner.ts b/packages/@n8n/instance-ai/evaluations/discovery/runner.ts index 2af19efcf65..282ced72952 100644 --- a/packages/@n8n/instance-ai/evaluations/discovery/runner.ts +++ b/packages/@n8n/instance-ai/evaluations/discovery/runner.ts @@ -73,7 +73,6 @@ import type { TaskStorage, } from '../../src/types'; import { buildKnowledgeBaseWorkspaceBundle } from '../../src/knowledge-base/materialize-knowledge-base'; -import { isAgentFeatureEnabled } from '../../src/utils/agent-feature-enabled'; import { asResumable, type SuspensionInfo } from '../../src/utils/stream-helpers'; import { createInMemoryEventBus, wrapEventBusWithObserver } from '../harness/in-memory-event-bus'; import { createStubServices, defaultNodesJsonPath } from '../harness/stub-services'; @@ -213,7 +212,8 @@ export async function runOrchestratorTurn( const mcpRegistry = mcpState ? createStubMcpRegistry(mcpState) : undefined; const context: InstanceAiContext = { ...applyInstanceState(services.context, options.scenario, mcpRegistry), - ...(isAgentFeatureEnabled() ? { builderDelegate: createStubBuilderDelegate() } : {}), + // The Agents module is a default module, so the eval runs with a builder. + builderDelegate: createStubBuilderDelegate(), workspace: createStubWorkspace(knowledgeBase.files), workspaceRoot: stubWorkspaceRoot, }; diff --git a/packages/@n8n/instance-ai/evaluations/fixtures/providers/slack/manifest.json b/packages/@n8n/instance-ai/evaluations/fixtures/providers/slack/manifest.json index fc636b7e530..4fe9c78cb66 100644 --- a/packages/@n8n/instance-ai/evaluations/fixtures/providers/slack/manifest.json +++ b/packages/@n8n/instance-ai/evaluations/fixtures/providers/slack/manifest.json @@ -8,5 +8,10 @@ "/apps/:appId/install-on-team": "install.html", "/apps/:appId/oauth": "install.html" }, - "defaultRoute": "/apps" + "defaultRoute": "/apps", + "verify": { + "path": "/api/users.profile.get", + "header": "Authorization", + "scheme": "Bearer" + } } diff --git a/packages/@n8n/instance-ai/evaluations/harness/agent-execution.ts b/packages/@n8n/instance-ai/evaluations/harness/agent-execution.ts index e2de35f4eed..cb9d7570f6a 100644 --- a/packages/@n8n/instance-ai/evaluations/harness/agent-execution.ts +++ b/packages/@n8n/instance-ai/evaluations/harness/agent-execution.ts @@ -20,6 +20,7 @@ import type { EvalLogger } from './logger'; import { writeScenarioVerificationSnapshot, type VerificationArtifact } from './scenario-execution'; import { reseedScenarioTables, type ScenarioSeedContext } from './seed-tables'; import { + throwIfFrameworkIssue, throwIfServerBudgetStop, isTransientExecutionAbort, MAX_EXEC_ATTEMPTS, @@ -212,6 +213,7 @@ export async function executeAgentScenario( } // Killed for time, not by the builder — throw so the timeout path classifies it. throwIfServerBudgetStop(evalResult); + throwIfFrameworkIssue(evalResult); const execMs = Date.now() - execStart; @@ -245,6 +247,7 @@ export async function executeAgentScenario( result, verificationResults, verifierAttempts: verification.attempts, + verifierInput: { checklist: scenarioChecklist, artifact }, buildTrace, logger, outputDir, diff --git a/packages/@n8n/instance-ai/evaluations/harness/build-workflow.ts b/packages/@n8n/instance-ai/evaluations/harness/build-workflow.ts index 3aef627aa29..f7384ba3dba 100644 --- a/packages/@n8n/instance-ai/evaluations/harness/build-workflow.ts +++ b/packages/@n8n/instance-ai/evaluations/harness/build-workflow.ts @@ -26,6 +26,7 @@ import { waitForAllActivity, runMultiTurnConversation, recordUserTurn, + buildAutoApprovePayload, type ConfirmationStrategy, } from './chat-loop'; import { runWorkflowChecks, summarizeMissingWorkflowError } from './cleanup'; @@ -71,6 +72,7 @@ import { extractOutcomeFromEvents, mergeSeededConversationMetrics, } from '../outcome/event-parser'; +import { findForeignWorkflowReads } from '../outcome/foreign-reads'; import { buildTranscriptFromEvents } from '../outcome/transcript-from-events'; import { buildAgentOutcome, extractWorkflowIdsFromMessages } from '../outcome/workflow-discovery'; import type { @@ -78,6 +80,7 @@ import type { BuildTimeout, BuildTrace, CapturedEvent, + CapturedToolCall, ConversationMetrics, ConversationTurn, ExecutionScenario, @@ -93,6 +96,7 @@ import { lastAgentText, userTurnsAsText, } from '../utils/conversation-text'; +import { getEventPayload } from '../utils/confirmation-payload'; import { UserProxyLlm, type ProxyDecisionStats } from '../utils/user-proxy'; // --------------------------------------------------------------------------- @@ -333,6 +337,8 @@ export interface BuildResult { * one applies even when the BUILD SUCCEEDED, which is exactly the case that would * otherwise be scored as an agent failure. */ priorRunFailed?: string; + /** Workflows the agent read that this build neither created nor seeded. Not scored. */ + foreignWorkflowReads?: string[]; /** Evidence that the MODEL PROVIDER, not the builder, failed this build (a * 5xx/429 upstream of the n8n instance). Set only after the retry budget is * spent. Routed to `framework_issue` with `PROVIDER_OUTAGE_ROOT_CAUSE`, so an @@ -344,6 +350,24 @@ export interface BuildResult { credentialSetup?: CredentialSetupRunFacts; } +/** A harness fault that decides the iteration without grading. `counted` faults fail it as + * `framework_issue`; the others keep it out of the pass rate. */ +export function harnessFault(build: BuildResult): { reason: string; counted: boolean } | undefined { + if (build.priorRunFailed) { + return { + reason: `prior run staging did not land, so the case premise is missing: ${build.priorRunFailed}`, + counted: false, + }; + } + if (build.foreignWorkflowReads?.length) { + return { + reason: `the agent read workflows another build made (${build.foreignWorkflowReads.join(', ')})`, + counted: true, + }; + } + return undefined; +} + /** * True when the build failed for a reason the agent doesn't own — seeding, * transport or the model provider. Everything downstream that has to attribute @@ -599,6 +623,16 @@ export async function buildWorkflow(config: BuildWorkflowConfig): Promise { + const toolCalls = parsedToolCalls ?? extractOutcomeFromEvents(events).toolCalls; + const foreignWorkflowReads = findForeignWorkflowReads(toolCalls, restoredWorkflowIds); + if (foreignWorkflowReads.length === 0) return {}; + logger.warn( + ` The agent read workflows another build made: ${foreignWorkflowReads.join(', ')}`, + ); + return { foreignWorkflowReads }; + }; /** The agent the seeded history last targeted — graded and executed first. */ let seedActiveAgentId: string | undefined; // Scenario seed tables are created empty before the build @@ -839,12 +873,31 @@ export async function buildWorkflow(config: BuildWorkflowConfig): Promise { + if (getEventPayload(event).inputType !== 'questions') { + return buildAutoApprovePayload(event); + } + questionProxy.ingestEvents(events); + return await questionProxy.respondToConfirmation(event); + }, }); } catch (error: unknown) { if (!(error instanceof RunTimeoutError)) throw error; @@ -1263,6 +1329,7 @@ export async function buildWorkflow(config: BuildWorkflowConfig): Promise { if (!args.workflow) return undefined; - const modelId = hasAnthropicKey() ? SONNET_MODEL : undefined; + const modelId = hasAnthropicKey() ? JUDGE_MODEL : undefined; const ctx: BinaryCheckContext = { prompt: args.prompt, ...(modelId ? { modelId } : {}), diff --git a/packages/@n8n/instance-ai/evaluations/harness/scenario-execution.ts b/packages/@n8n/instance-ai/evaluations/harness/scenario-execution.ts index e5ec22cf5cd..542ebafc233 100644 --- a/packages/@n8n/instance-ai/evaluations/harness/scenario-execution.ts +++ b/packages/@n8n/instance-ai/evaluations/harness/scenario-execution.ts @@ -16,6 +16,7 @@ import { attributionForScenario } from './attribution'; import type { EvalLogger } from './logger'; import { reseedScenarioTables, type ScenarioSeedContext } from './seed-tables'; import { + throwIfFrameworkIssue, throwIfServerBudgetStop, isTransientExecutionAbort, MAX_EXEC_ATTEMPTS, @@ -57,6 +58,8 @@ export async function writeScenarioVerificationSnapshot(input: { result: ChecklistResult | undefined; verificationResults: ChecklistResult[]; verifierAttempts: VerifierAttemptDebug[]; + /** The verifier's exact input, for a replay on another judge model. */ + verifierInput: { checklist: ChecklistItem[]; artifact: VerificationArtifact }; buildTrace?: BuildTrace; logger: EvalLogger; /** --output-dir; falls back to EVAL_DATA_DIR. Concurrent eval children share @@ -82,6 +85,7 @@ export async function writeScenarioVerificationSnapshot(input: { result: input.result ?? null, verificationResults: input.verificationResults, verifierAttempts: input.verifierAttempts, + verifierInput: input.verifierInput, buildTrace: input.buildTrace ?? null, }, null, @@ -318,6 +322,7 @@ async function runScenario( } // Killed for time, not by the builder — throw so the timeout path classifies it. throwIfServerBudgetStop(evalResult); + throwIfFrameworkIssue(evalResult); const execMs = Date.now() - execStart; @@ -358,6 +363,7 @@ async function runScenario( result, verificationResults, verifierAttempts: verification.attempts, + verifierInput: { checklist: scenarioChecklist, artifact }, buildTrace, logger, outputDir, diff --git a/packages/@n8n/instance-ai/evaluations/harness/stub-services.ts b/packages/@n8n/instance-ai/evaluations/harness/stub-services.ts index 6f373c6068a..490ee082f3e 100644 --- a/packages/@n8n/instance-ai/evaluations/harness/stub-services.ts +++ b/packages/@n8n/instance-ai/evaluations/harness/stub-services.ts @@ -771,6 +771,15 @@ export function defaultNodesJsonPath(): string { return path.join(siblingPackage, 'nodes.json'); } +const EVAL_PACKAGES_ROOT = path.resolve(__dirname, '..', '..', '..', '..'); + +function nodeDefinitionDirs(packagesRoot: string): string[] { + return [ + path.join(packagesRoot, 'nodes-base', 'dist', 'node-definitions'), + path.join(packagesRoot, '@n8n', 'nodes-langchain', 'dist', 'node-definitions'), + ]; +} + /** * Resolve the workspace-relative `dist/node-definitions/` directories the * production resolver expects. Production reads them via @@ -779,14 +788,20 @@ export function defaultNodesJsonPath(): string { * eval already lives in the monorepo, so we walk up to `packages/` and * point at the built dist dirs directly. * - * Returns an empty array if neither package has been built. Callers should - * surface a clear error rather than silently degrading the agent's view. + * Returns an empty array if neither package has been built. The discovery CLI + * calls `missingEvalNodeData` at start, so a run without the builds stops. */ export function resolveEvalNodeDefinitionDirs(): string[] { - const packagesRoot = path.resolve(__dirname, '..', '..', '..', '..'); - const candidates = [ - path.join(packagesRoot, 'nodes-base', 'dist', 'node-definitions'), - path.join(packagesRoot, '@n8n', 'nodes-langchain', 'dist', 'node-definitions'), - ]; - return candidates.filter((dir) => existsSync(dir)); + return nodeDefinitionDirs(EVAL_PACKAGES_ROOT).filter((dir) => existsSync(dir)); +} + +/** + * Returns the node data paths that the stubs need and cannot find. Without + * them, the agent gets no node types, and no error shows. + */ +export function missingEvalNodeData( + nodesJsonPath: string, + packagesRoot = EVAL_PACKAGES_ROOT, +): string[] { + return [nodesJsonPath, ...nodeDefinitionDirs(packagesRoot)].filter((p) => !existsSync(p)); } diff --git a/packages/@n8n/instance-ai/evaluations/harness/transient-error.ts b/packages/@n8n/instance-ai/evaluations/harness/transient-error.ts index 7e78589b80b..9915493b7c9 100644 --- a/packages/@n8n/instance-ai/evaluations/harness/transient-error.ts +++ b/packages/@n8n/instance-ai/evaluations/harness/transient-error.ts @@ -79,6 +79,15 @@ export function throwIfServerBudgetStop(result: { success: boolean; errors: stri throw new Error(`The operation was aborted due to timeout: ${result.errors.join('; ')}`); } +/** The server refused to run the scenario for a harness reason (mock hints, pin + * data or seed generation failed, often on a model call). Nothing ran, so the + * verifier has nothing to judge: throw so the caller records framework_issue. */ +export function throwIfFrameworkIssue(result: { success: boolean; errors: string[] }): void { + if (result.success) return; + const issue = result.errors.find((e) => e.startsWith('FRAMEWORK ISSUE:')); + if (issue) throw new Error(issue); +} + /** Retry decision for one failed scenario-execution attempt. */ export function shouldRetryScenarioExecution(message: string, attempt: number): boolean { if (isTransientNetworkError(message)) return attempt < MAX_EXEC_ATTEMPTS; diff --git a/packages/@n8n/instance-ai/evaluations/outcome/event-parser.ts b/packages/@n8n/instance-ai/evaluations/outcome/event-parser.ts index 9a74cd026cd..3e08c523927 100644 --- a/packages/@n8n/instance-ai/evaluations/outcome/event-parser.ts +++ b/packages/@n8n/instance-ai/evaluations/outcome/event-parser.ts @@ -26,7 +26,8 @@ import { getNestedRecord as getRecord, getString } from '../utils/safe-extract'; // Tool names whose results contain resource IDs we need to track // --------------------------------------------------------------------------- -const WORKFLOW_TOOLS = new Set(['build-workflow', 'submit-workflow', 'patch-workflow']); +/** Tools that save a workflow; their results carry its id. */ +export const WORKFLOW_TOOLS = new Set(['build-workflow', 'submit-workflow', 'patch-workflow']); // Retired standalone tool names, kept so captures from older backends still parse. const EXECUTION_TOOL_LEGACY = 'run-workflow'; diff --git a/packages/@n8n/instance-ai/evaluations/outcome/foreign-reads.ts b/packages/@n8n/instance-ai/evaluations/outcome/foreign-reads.ts new file mode 100644 index 00000000000..4d183ac81e2 --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/outcome/foreign-reads.ts @@ -0,0 +1,49 @@ +import { isRecord } from '@n8n/utils/is-record'; + +import { WORKFLOW_TOOLS } from './event-parser'; +import type { CapturedToolCall } from '../types'; + +function toRecord(result: unknown): Record | undefined { + if (isRecord(result)) return result; + if (typeof result !== 'string') return undefined; + try { + const parsed: unknown = JSON.parse(result); + return isRecord(parsed) ? parsed : undefined; + } catch { + return undefined; + } +} + +function succeeded(call: CapturedToolCall): boolean { + const result = toRecord(call.result); + return call.error === undefined && result?.success !== false && typeof result?.error !== 'string'; +} + +/** Workflow ids the agent successfully read or changed that this build neither created + * nor seeded: another build's work, reachable through a shared view. */ +export function findForeignWorkflowReads( + toolCalls: CapturedToolCall[], + seededWorkflowIds: string[], +): string[] { + const calls = toolCalls.filter(succeeded); + const own = new Set(seededWorkflowIds); + for (const call of calls) { + // A save without a target workflow creates one. + if (!WORKFLOW_TOOLS.has(call.toolName) || call.args.workflowId !== undefined) continue; + const result = toRecord(call.result); + const id = result?.workflowId ?? result?.id; + if (typeof id === 'string') own.add(id); + } + + const seen = calls.flatMap((call) => { + const target = typeof call.args.workflowId === 'string' ? [call.args.workflowId] : []; + const listed = toRecord(call.result)?.workflows; + const listedIds = Array.isArray(listed) + ? listed.flatMap((workflow) => + isRecord(workflow) && typeof workflow.id === 'string' ? [workflow.id] : [], + ) + : []; + return [...target, ...listedIds]; + }); + return [...new Set(seen.filter((id) => !own.has(id)))]; +} diff --git a/packages/@n8n/instance-ai/evaluations/outcome/workflow-discovery.ts b/packages/@n8n/instance-ai/evaluations/outcome/workflow-discovery.ts index 6799ca02365..a5364376d58 100644 --- a/packages/@n8n/instance-ai/evaluations/outcome/workflow-discovery.ts +++ b/packages/@n8n/instance-ai/evaluations/outcome/workflow-discovery.ts @@ -7,12 +7,7 @@ import type { InstanceAiMessage } from '@n8n/api-types'; import { N8nApiError, type N8nClient, type WorkflowResponse } from '../clients/n8n-client'; import type { AgentOutcome, EventOutcome, ExecutionSummary, WorkflowSummary } from '../types'; import { collectArtifactRefIds } from './collect-refs'; - -// --------------------------------------------------------------------------- -// Tool names whose results contain workflow IDs -// --------------------------------------------------------------------------- - -const WORKFLOW_TOOLS = new Set(['build-workflow', 'submit-workflow', 'patch-workflow']); +import { WORKFLOW_TOOLS } from './event-parser'; // --------------------------------------------------------------------------- // snapshotWorkflowIds -- call before the run to know what existed prior diff --git a/packages/@n8n/instance-ai/evaluations/routing/__tests__/cases.test.ts b/packages/@n8n/instance-ai/evaluations/routing/__tests__/cases.test.ts index 73da24c0676..6034f87d453 100644 --- a/packages/@n8n/instance-ai/evaluations/routing/__tests__/cases.test.ts +++ b/packages/@n8n/instance-ai/evaluations/routing/__tests__/cases.test.ts @@ -39,7 +39,13 @@ describe('loadRoutingCases', () => { tags: ['routing', 'bucket:clarify', 'accepts:clarify:open'], }), 'route-prod-agent-one.json': exportedCase([], { - tags: ['routing', 'bucket:agent', 'accepts:clarify:agent', 'accepts:answer:agent'], + tags: [ + 'routing', + 'bucket:agent', + 'accepts:clarify:agent', + 'accepts:answer:agent', + 'clarity:hidden', + ], conversation: [{ role: 'user', text: ['Answer our support inbox.', 'Use our FAQ.'] }], }), 'results.json': '{}', @@ -66,6 +72,7 @@ describe('loadRoutingCases', () => { { id: 'route-prod-agent-one', bucket: 'agent', + clarity: 'hidden', accepts: ['agent', 'clarify:agent', 'answer:agent'], after: ['agent'], userMessage: 'Answer our support inbox.\nUse our FAQ.', @@ -74,6 +81,24 @@ describe('loadRoutingCases', () => { expect(needsSetup).toEqual([]); }); + it('reads a clarify:workflow token after the bucket, with the bucket as the after route', () => { + const dir = caseDir({ + 'route-workflow-ask.json': exportedCase([], { + tags: ['routing', 'bucket:workflow', 'accepts:clarify:workflow'], + }), + }); + + expect(loadRoutingCases(dir).cases).toEqual([ + { + id: 'route-workflow-ask', + bucket: 'workflow', + accepts: ['workflow', 'clarify:workflow'], + after: ['workflow'], + userMessage: 'It failed again.', + }, + ]); + }); + it('keeps the files whose name contains one of the filter tokens', () => { const dir = caseDir({ 'route-agent-one.json': exportedCase(), @@ -172,9 +197,10 @@ describe('loadRoutingCases', () => { tags('bucket:debug', 'bucket:agent', 'accepts:debug'), ), 'route-clarify-no-accepts.json': exportedCase([], tags('bucket:clarify')), + 'route-debug-bad-clarity.json': exportedCase(['clarity:obvious']), 'route-debug-bad-token.json': exportedCase( [], - tags('bucket:debug', 'accepts:clarify:workflow'), + tags('bucket:debug', 'accepts:answer:workflow'), ), 'route-debug-two-turns.json': exportedCase([], { conversation: [ @@ -194,7 +220,7 @@ describe('loadRoutingCases', () => { expect(() => loadRoutingCases(dir)).toThrow( expect.objectContaining({ message: expect.stringMatching( - /route-clarify-direction-no-after\.json: a case with stage directions needs an after: tag[\s\S]*route-clarify-no-accepts\.json: accepts: a bucket:clarify case needs an accepts: tag[\s\S]*route-debug-assistant-turn\.json: needs one user message[\s\S]*route-debug-bad-token\.json: accepts\.0[\s\S]*route-debug-broken\.json[\s\S]*route-debug-no-routing-tag\.json: has no "routing" tag[\s\S]*route-debug-two-buckets\.json: bucket: needs exactly one bucket: tag[\s\S]*route-debug-two-turns\.json: needs one user message, then at most one user turn with only \[stage directions\]/, + /route-clarify-direction-no-after\.json: a case with stage directions needs an after: tag[\s\S]*route-clarify-no-accepts\.json: accepts: a bucket:clarify case needs an accepts: tag[\s\S]*route-debug-assistant-turn\.json: needs one user message[\s\S]*route-debug-bad-clarity\.json: clarity\.0[\s\S]*route-debug-bad-token\.json: accepts\.0[\s\S]*route-debug-broken\.json[\s\S]*route-debug-no-routing-tag\.json: has no "routing" tag[\s\S]*route-debug-two-buckets\.json: bucket: needs exactly one bucket: tag[\s\S]*route-debug-two-turns\.json: needs one user message, then at most one user turn with only \[stage directions\]/, ), }), ); diff --git a/packages/@n8n/instance-ai/evaluations/routing/__tests__/grade.test.ts b/packages/@n8n/instance-ai/evaluations/routing/__tests__/grade.test.ts index 8096bcd1264..0c13eccad9b 100644 --- a/packages/@n8n/instance-ai/evaluations/routing/__tests__/grade.test.ts +++ b/packages/@n8n/instance-ai/evaluations/routing/__tests__/grade.test.ts @@ -351,6 +351,11 @@ describe('trialPasses', () => { [['clarify'], clarify('workflow'), true], [['clarify:agent'], clarify('both'), true], [['clarify:agent'], clarify('none'), false], + [['clarify:workflow'], clarify('workflow'), true], + [['clarify:workflow'], clarify('both'), true], + [['clarify:workflow'], clarify('agent'), false], + [['clarify:workflow'], clarify('none'), false], + [['clarify:workflow'], clarify(undefined), false], [['clarify:open'], clarify('none'), true], [['clarify:open'], clarify('workflow'), false], [['answer:agent'], { route: 'answer', steer: 'both', evidence: 'end of turn' }, true], @@ -364,6 +369,19 @@ describe('trialPasses', () => { expect(trialPasses(routingCase('workflow', ['workflow']), clarify('workflow'))).toBe(false); }); + it('replies to a workflow question in a workflow case, then passes only a workflow build', () => { + const workflowCase = routingCase('workflow', ['workflow', 'clarify:workflow'], ['workflow']); + const answered = (route: RouteResolution) => ({ ...route, questions: [clarify('workflow')] }); + + expect(canReplyTo(workflowCase, clarify('workflow'))).toBe(true); + expect(trialPasses(workflowCase, answered({ route: 'workflow', evidence: 'build' }))).toBe( + true, + ); + expect(trialPasses(workflowCase, answered({ route: 'agent', evidence: 'build-agent' }))).toBe( + false, + ); + }); + it('grades the route after an answer against the after routes only', () => { const openCase = routingCase('clarify', ['clarify:open'], ['agent']); const answered = (route: RouteResolution) => ({ ...route, questions: [clarify('none')] }); @@ -413,13 +431,21 @@ describe('afterQuestion', () => { }); describe('casePasses', () => { + const trial = (outcome: 'pass' | 'fail' | 'none') => ({ + resolution: { route: outcome === 'none' ? 'none' : 'agent', evidence: 'test' } as const, + passed: outcome === 'pass', + }); + it.each([ - [2, 3, true], - [1, 3, false], - [4, 6, true], - [3, 6, false], - [0, 0, false], - ])('%i of %i trials: %s', (passed, total, expected) => { - expect(casePasses(passed, total)).toBe(expected); + [['pass', 'pass', 'fail'], true], + [['pass', 'fail', 'fail'], false], + [['pass', 'pass', 'pass', 'fail', 'fail'], true], + [['pass', 'pass', 'fail', 'fail'], false], + [['pass', 'none', 'none'], true], + [['pass', 'fail', 'none'], false], + [['none', 'none', 'none'], false], + [[], false], + ] as const)('%j: %s', (outcomes, expected) => { + expect(casePasses(outcomes.map(trial))).toBe(expected); }); }); diff --git a/packages/@n8n/instance-ai/evaluations/routing/cases.ts b/packages/@n8n/instance-ai/evaluations/routing/cases.ts index 8f804fe4362..62237ebb3e0 100644 --- a/packages/@n8n/instance-ai/evaluations/routing/cases.ts +++ b/packages/@n8n/instance-ai/evaluations/routing/cases.ts @@ -3,8 +3,9 @@ // main eval case format that LangTracer exports. The slug is the case id. // // The routing labels are tags: `routing`, one `bucket:`, and one -// `accepts:` for each other accepted route. A judge picks the route of -// each trial (see grade.ts). +// `accepts:` for each other accepted route. An optional +// `clarity:` tag splits each bucket in the summary. A judge picks the +// route of each trial (see grade.ts). // // An optional second user turn holds only [stage directions]: the facts that // the user proxy uses to answer a question. The proxy answers up to two @@ -41,12 +42,15 @@ export type RoutingBucket = (typeof ROUTING_BUCKETS)[number]; export const ROUTING_ACCEPT_TOKENS = [ ...ROUTING_BUCKETS, 'clarify:agent', + 'clarify:workflow', 'clarify:open', 'answer:agent', 'answer:open', ] as const; export type AcceptToken = (typeof ROUTING_ACCEPT_TOKENS)[number]; +export const ROUTING_CLARITIES = ['clear', 'hidden', 'vague'] as const; + const routingTagsSchema = z .object({ /** The main expected route. Reports group cases by it. */ @@ -58,13 +62,19 @@ const routingTagsSchema = z accepts: z.array(z.enum(ROUTING_ACCEPT_TOKENS)), /** The routes that pass after the user proxy answers a question. */ after: z.array(z.enum(ROUTING_BUCKETS).exclude(['clarify'])), + /** How clearly the message points to the route. */ + clarity: z + .array(z.enum(ROUTING_CLARITIES)) + .max(1, 'needs at most one clarity: tag') + .transform((levels) => levels.at(0)), }) // The bucket always passes, so case files need not repeat it. A clarify case // keeps only its own tokens: most accept only `clarify:open`, and plain // `clarify` would also pass a question that only asks about a workflow. - .transform(({ bucket, accepts: tokens, after }) => { + .transform(({ bucket, accepts: tokens, after, clarity }) => { const accepts = bucket === 'clarify' || tokens.includes(bucket) ? tokens : [bucket, ...tokens]; return { + ...(clarity && { clarity }), bucket, accepts, after: @@ -136,6 +146,7 @@ function parseRoutingCaseFile(filePath: string): ParsedFile { bucket: tagValues(tags, 'bucket:'), accepts: tagValues(tags, 'accepts:'), after: tagValues(tags, 'after:'), + clarity: tagValues(tags, 'clarity:'), }); if (!labels.success) throw new Error(`${filePath}: ${formatIssues(labels.error)}`); const direction = directionTurn?.text; diff --git a/packages/@n8n/instance-ai/evaluations/routing/eval-results.ts b/packages/@n8n/instance-ai/evaluations/routing/eval-results.ts new file mode 100644 index 00000000000..913f35f6e37 --- /dev/null +++ b/packages/@n8n/instance-ai/evaluations/routing/eval-results.ts @@ -0,0 +1,99 @@ +// --------------------------------------------------------------------------- +// `eval-results.json` for routing mode, in the format that the LangTracer +// dispatcher reads (see ../__tests__/eval-results-dispatcher-contract.test.ts). +// +// A case has one build expectation: the routes that it accepts. Each trial is +// one verdict on it. A trial with no route is `incomplete`: it counts neither +// as a pass nor as a failure. +// --------------------------------------------------------------------------- + +import { mkdirSync, writeFileSync } from 'fs'; +import { join } from 'path'; + +import type { RoutingCase } from './cases'; +import { routeLabel, type RouteResolution } from './grade'; +import type { DiscoveryStreamStatus } from '../discovery/types'; +import type { EvalAttribution } from '../harness/attribution'; +import { passAtK, passHatK } from '../run/aggregator'; +import type { BuildExpectationResult } from '../types'; + +export interface RoutingTrial { + resolution: RouteResolution; + passed: boolean; + turn: { streamStatus: DiscoveryStreamStatus; runError?: string }; +} + +export interface RoutingCaseResult { + routingCase: RoutingCase; + trials: RoutingTrial[]; +} + +function noRouteAttribution({ turn }: RoutingTrial): EvalAttribution { + if (turn.streamStatus === 'timed-out') return 'timeout'; + if (turn.runError || turn.streamStatus === 'errored') return 'framework_issue'; + return 'verification_gap'; +} + +function trialVerdict(expectation: string, trial: RoutingTrial): BuildExpectationResult { + const { resolution, passed, turn } = trial; + if (resolution.route === 'none') { + const detail = turn.runError ?? resolution.judgeError; + return { + expectation, + pass: false, + reason: `Not graded: no route from ${resolution.evidence}${detail ? ` (${detail})` : ''}.`, + incomplete: true, + attribution: noRouteAttribution(trial), + }; + } + const judge = resolution.judgeReason ? ` Judge: ${resolution.judgeReason}` : ''; + const reason = `Route ${routeLabel(resolution)} from ${resolution.evidence}.${judge}`; + return passed + ? { expectation, pass: true, reason } + : { expectation, pass: false, reason, attribution: 'builder_issue' }; +} + +function toTestCase({ routingCase, trials }: RoutingCaseResult) { + // The same text that LangTracer stores as the case's process expectation. + const expectation = `Routes to one of: ${routingCase.accepts.join(', ')}`; + const verdicts = trials.map((trial) => trialVerdict(expectation, trial)); + const evaluated = verdicts.filter((verdict) => !verdict.incomplete); + const passCount = evaluated.filter((verdict) => verdict.pass).length; + const n = evaluated.length; + return { + name: routingCase.id, + testCaseFile: routingCase.id, + status: n > 0 ? 'verified' : 'notVerified', + totalRuns: trials.length, + buildExpectations: [ + { + expectation, + passCount, + evaluatedCount: n, + // Terminal values at k = the evaluated trials, as run/persist.ts writes them. + passAtK: passAtK(n, passCount, n), + passHatK: passHatK(n, passCount, n), + }, + ], + buildExpectationResultsPerRun: verdicts.map((verdict) => [verdict]), + }; +} + +/** Writes `eval-results.json` to `outputDir` and returns its path. */ +export function writeRoutingEvalResults( + outputDir: string, + results: RoutingCaseResult[], + totalRuns: number, + duration: number, +): string { + mkdirSync(outputDir, { recursive: true }); + const jsonPath = join(outputDir, 'eval-results.json'); + const report = { + timestamp: new Date().toISOString(), + duration, + totalRuns, + testCases: results.map(toTestCase), + }; + writeFileSync(jsonPath, JSON.stringify(report, null, 2)); + return jsonPath; +} diff --git a/packages/@n8n/instance-ai/evaluations/routing/grade.ts b/packages/@n8n/instance-ai/evaluations/routing/grade.ts index e45fe2f64e5..3c65b23da50 100644 --- a/packages/@n8n/instance-ai/evaluations/routing/grade.ts +++ b/packages/@n8n/instance-ai/evaluations/routing/grade.ts @@ -224,11 +224,13 @@ export function routeLabel(resolution: RouteResolution): string { .join('>'); } -// `:agent` passes a steer toward an Agent; `:open` passes any steer except workflow only. +// `:agent` passes a steer toward an Agent, and `:workflow` a steer toward a workflow. +// `:open` passes any steer except workflow only. function acceptTokenMatches(token: AcceptToken, { route, steer }: RouteResolution): boolean { const [tokenRoute, tokenSteer] = token.split(':'); if (route !== tokenRoute) return false; if (tokenSteer === 'agent') return steer === 'agent' || steer === 'both'; + if (tokenSteer === 'workflow') return steer === 'workflow' || steer === 'both'; if (tokenSteer === 'open') return steer !== undefined && steer !== 'workflow'; return true; } @@ -252,7 +254,13 @@ export function trialPasses(routingCase: RoutingCase, resolution: RouteResolutio return routingCase.accepts.some((token) => acceptTokenMatches(token, resolution)); } -/** A case passes when at least 2 of 3 trials pass; other trial counts keep the ratio. */ -export function casePasses(passedTrials: number, totalTrials: number): boolean { - return totalTrials > 0 && passedTrials * 3 >= totalTrials * 2; +/** + * A case passes when more than half of its graded trials pass. A trial with no route is not graded. + * LangTracer applies the same rule to the counts in `eval-results.json`, so the two verdicts agree. + */ +export function casePasses( + trials: Array<{ resolution: RouteResolution; passed: boolean }>, +): boolean { + const graded = trials.filter((trial) => trial.resolution.route !== 'none'); + return graded.filter((trial) => trial.passed).length * 2 > graded.length; } diff --git a/packages/@n8n/instance-ai/evaluations/run/build-orchestrator.ts b/packages/@n8n/instance-ai/evaluations/run/build-orchestrator.ts index f626d57522b..2cd937463dd 100644 --- a/packages/@n8n/instance-ai/evaluations/run/build-orchestrator.ts +++ b/packages/@n8n/instance-ai/evaluations/run/build-orchestrator.ts @@ -38,6 +38,7 @@ import { resolveArtifactContext } from '../harness/artifacts/artifact-context'; import { attributionForExpectation } from '../harness/attribution'; import { buildFailedOnInfra, + harnessFault, leakHaystackFor, redactLocalRunSecrets, searchableBuildText, @@ -476,10 +477,11 @@ export function createBuildOrchestrator(deps: BuildOrchestratorDeps): BuildOrche // would still score on them. const timedOut = (verdicts: BuildExpectationResult[]): BuildExpectationResult[] => verdicts.map((v) => ({ ...v, incomplete: true, attribution: 'timeout' as const })); - if (build.priorRunFailed) { + const fault = harnessFault(build); + if (fault) { const unjudged = allFailVerdicts( collectExpectations(testCase), - `not judged — prior run staging did not land, so the case premise is missing: ${build.priorRunFailed}`, + `not judged — ${fault.reason}`, ); // The row for this build is re-stamped `timeout` too, so the two agree. buildExpectationsByKey.set( @@ -487,7 +489,11 @@ export function createBuildOrchestrator(deps: BuildOrchestratorDeps): BuildOrche Promise.resolve( build.timeout ? timedOut(unjudged) - : unjudged.map((verdict) => ({ ...verdict, attribution: 'framework_issue' as const })), + : unjudged.map((verdict) => ({ + ...verdict, + incomplete: !fault.counted, + attribution: 'framework_issue' as const, + })), ), ); return; diff --git a/packages/@n8n/instance-ai/evaluations/run/case-pipeline.ts b/packages/@n8n/instance-ai/evaluations/run/case-pipeline.ts index 5e28e8b4d5d..b70b23b1bc2 100644 --- a/packages/@n8n/instance-ai/evaluations/run/case-pipeline.ts +++ b/packages/@n8n/instance-ai/evaluations/run/case-pipeline.ts @@ -22,7 +22,7 @@ import { findAgentArtifactRef, type AgentScenarioContext, } from '../harness/agent-execution'; -import { buildFailedOnInfra } from '../harness/build-workflow'; +import { buildFailedOnInfra, harnessFault } from '../harness/build-workflow'; import { cleanupBuild, effectiveTimeoutMs } from '../harness/cleanup'; import type { EvalLogger } from '../harness/logger'; import { selectScenarioWorkflowId } from '../harness/scenario-execution'; @@ -257,8 +257,10 @@ export function createCasePipeline(deps: CasePipelineDeps): CasePipeline { // grading against history the instance does not have. Checked BEFORE every other // branch, and independently of `build.success`, because the biting case is a build // that succeeded: `buildFailedOnInfra` returns false there, so the case would - // otherwise be scored as an agent failure on a premise that never existed. - if (build.priorRunFailed) { + // otherwise be scored as an agent failure on a premise that never existed. A read of + // another build's workflow takes the same route: the run did not start clean. + const fault = harnessFault(build); + if (fault) { const capturedAgent = agentRef ? await agentContextByKey.get(cacheKey) : undefined; return await attachExpectations({ buildSuccess: build.success, @@ -266,15 +268,14 @@ export function createCasePipeline(deps: CasePipelineDeps): CasePipeline { ...(capturedAgent ? { agentContext: capturedAgent.rendered } : {}), ...(capturedAgent?.artifact ? { agentArtifact: capturedAgent.artifact } : {}), passed: false, - // Not graded rather than failed — the same treatment an ungraded expectation - // gets, so this stays out of the pass rate instead of landing in the - // builder's baseline as a red. - incomplete: true, + // A missing premise is not graded, so it stays out of the pass rate. A counted + // fault fails the run, but as framework_issue, not in the builder's baseline. + ...(fault.counted ? {} : { incomplete: true }), score: 0, - reasoning: `Prior run staging did not land, so the case premise is missing: ${build.priorRunFailed}`, + reasoning: `${fault.counted ? 'Harness fault' : 'Not scored'}: ${fault.reason}`, failureCategory: 'framework_issue', attribution: 'framework_issue', - execErrors: [build.priorRunFailed], + execErrors: [fault.reason], buildDurationMs, ...buildSpendFields, execDurationMs: 0, diff --git a/packages/@n8n/instance-ai/evaluations/subagent/runner.ts b/packages/@n8n/instance-ai/evaluations/subagent/runner.ts index 7c7e11fd431..4234276f327 100644 --- a/packages/@n8n/instance-ai/evaluations/subagent/runner.ts +++ b/packages/@n8n/instance-ai/evaluations/subagent/runner.ts @@ -17,16 +17,10 @@ import type { BinaryCheckContext } from '../binaryChecks/types'; import type { N8nClient, WorkflowResponse } from '../clients/n8n-client'; import { buildWorkflow, type BuildResult } from '../harness/build-workflow'; import { cleanupBuild } from '../harness/cleanup'; +import { JUDGE_MODEL } from '../../src/utils/eval-agents'; import { createLogger, type EvalLogger } from '../harness/logger'; import { agentTextOf } from '../utils/conversation-text'; -/** - * Client-side model used by binary checks (they call Anthropic directly with - * ANTHROPIC_API_KEY). Independent of the server-side agent model, which the - * server resolves from its own settings when the CLI doesn't pass `--model`. - */ -const BINARY_CHECK_DEFAULT_MODEL = 'anthropic/claude-sonnet-4-20250514'; - export interface RunWorkflowBuildEvalDeps { client: N8nClient; /** Delete workflows after the run (default true). Disable with --keep-workflows. */ @@ -62,7 +56,7 @@ export async function runWorkflowBuildEval( const feedback = await evaluateCapturedWorkflows({ workflows: build.workflowJsons, prompt: testCase.prompt, - modelId: modelId ?? BINARY_CHECK_DEFAULT_MODEL, + modelId: modelId ?? JUDGE_MODEL, agentTextResponse, ...(testCase.annotations ? { annotations: testCase.annotations } : {}), }); diff --git a/packages/@n8n/instance-ai/evaluations/system-prompts/build-expectations-verify.ts b/packages/@n8n/instance-ai/evaluations/system-prompts/build-expectations-verify.ts index 33c955efc2d..14e5171b1ba 100644 --- a/packages/@n8n/instance-ai/evaluations/system-prompts/build-expectations-verify.ts +++ b/packages/@n8n/instance-ai/evaluations/system-prompts/build-expectations-verify.ts @@ -20,7 +20,8 @@ A workflow containing an AI Agent node is still a workflow — building one is N ## How to judge -- Judge **each expectation independently** and literally. Read what it actually asserts. +- Judge **each expectation independently**. Read what it actually asserts, and grade the outcome it describes, not its exact wording. Do not fail for a requirement the expectation does not state. +- **The user's later turns change the request.** Grade against what the user asked for by the end of the conversation. A change the user asked for in a follow-up turn is not a defect, even when an expectation's wording does not mention it. - The unit of evaluation is the **whole conversation** — every turn (both sides) and the tool interactions within them, not just the latest turn. Follow each expectation's own specifics: when it calls out a particular turn, moment, or ordering, hold it to that. - **Process / temporal claims** ("asked X before building", "pushed back on the plan", "asked N questions") → judge from the transcript and the metrics. Order matters: "asked before building" means the question appears in the transcript prior to the workflow being created/finalized. - **Setup cards** are one of the ways the builder asks the user for node configuration — it surfaces a card listing the credentials and/or parameters it needs the user to fill. Use the setup-card request text as the source of truth for what was asked. A node listed with only a credential does not mean the builder asked for that node's parameters, and a later setup-wizard "configured" summary only describes what was submitted/applied, not necessarily what the card requested. diff --git a/packages/@n8n/instance-ai/evaluations/system-prompts/mock-execution-verify.ts b/packages/@n8n/instance-ai/evaluations/system-prompts/mock-execution-verify.ts index 7691d2b9264..9bb145e8609 100644 --- a/packages/@n8n/instance-ai/evaluations/system-prompts/mock-execution-verify.ts +++ b/packages/@n8n/instance-ai/evaluations/system-prompts/mock-execution-verify.ts @@ -67,7 +67,7 @@ Each branch's items are capped at 10 for artifact size. The full untruncated tot 4. **Be definitive, not speculative.** You have the full execution trace, node configurations, request bodies, mock responses, and node outputs. Use this data to give exact answers. Say "the expression references $json.firstName but the upstream output has the field as firstname (lowercase)" — not "likely references a field that doesn't resolve correctly." If a node errored, quote the exact error. If a field is missing, name it and trace where it should have come from. Never use "likely", "might", "probably", or "possibly" when the data in the artifact gives you a definitive answer. 5. **Always check the "Workflow structure" section before claiming a node is missing or miswired.** The workflow structure lists ALL nodes that were built AND the connections JSON showing exactly how they are wired. The execution trace only shows nodes that actually ran. Before claiming a branch is wired to the wrong node, verify against the connections JSON. If a node exists in the structure but not in the trace, check why: was an upstream condition met unexpectedly? Was the IF/Switch node's condition misconfigured? Was the input data wrong? Don't assume miswiring — check the connections first. 6. **Workflows can branch.** Not every node runs in every execution. A crashed or misconfigured node prevents all downstream branches from running. When diagnosing, identify the single root cause (the first node that crashed) rather than listing each unexecuted downstream node as a separate issue. -7. Check the **success criteria** against the execution trace and node outputs +7. Check the **success criteria** against the execution trace and node outputs. Grade the outcome each criterion describes, not its exact wording: when the scenario's data setup allows an alternative (for example GET or POST), accept it, and do not fail for a requirement the criteria do not state. 8. For scenarios with no errors and no output beyond the trigger: this usually means the workflow handled empty data gracefully (no crash = success for empty-input scenarios) 9. **0 items flowing into a downstream node = that node doesn't run.** This is n8n's default branching behavior, not a defect. When a Filter / IF / Switch routes 0 items to a branch, its downstream nodes simply don't execute — no crash, no side effects. **Do not require an explicit guard (IF count > 0, early-exit branch) unless the success criteria explicitly demands intentional handling.** Verify against what the criteria actually say, not against an implicit "must use a guard" requirement. 10. **\`pass\` must match your final verdict.** If your reasoning concludes all success criteria are met, set \`pass: true\`. Do not leave \`pass: false\` after talking yourself into a pass. diff --git a/packages/@n8n/instance-ai/package.json b/packages/@n8n/instance-ai/package.json index 725c2b7f955..e41e72426c6 100644 --- a/packages/@n8n/instance-ai/package.json +++ b/packages/@n8n/instance-ai/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/instance-ai", - "version": "1.28.0", + "version": "1.29.0", "scripts": { "clean": "rimraf dist .turbo", "typecheck": "tsc --noEmit && tsc -p evaluations/tsconfig.json", diff --git a/packages/@n8n/instance-ai/skills/debugging-executions/SKILL.md b/packages/@n8n/instance-ai/skills/debugging-executions/SKILL.md index 04ab80722e1..6fa7a031676 100644 --- a/packages/@n8n/instance-ai/skills/debugging-executions/SKILL.md +++ b/packages/@n8n/instance-ai/skills/debugging-executions/SKILL.md @@ -4,7 +4,9 @@ description: >- Debug failed or wrong-output workflow executions using executions tools. Load when the user reports execution failures, unexpected node output, empty parameter values after a successful run, or a node showing a red or failed - expression error. + expression error. Also load when a live run you started for the user fails + with an error from a node or an external service (for example a 401), before + you explain the cause to the user. recommended_tools: - executions - workflows @@ -27,6 +29,37 @@ empty node, or a missing node is a real defect to investigate, not something to explain away. If you genuinely cannot re-run the failing path, say so plainly and name what is unconfirmed instead of repeating a success claim. +## Before you name a cause + +Say what you checked before you say why it failed. Do not lead with a cause +that you did not check. A plausible guess presented first reads as a finding, +and the user acts on it. + +Check what you can see on the n8n side first. These checks are read-only, so +run them unprompted: + +- **Auth errors (401, 403, "unauthorized", "invalid key").** Confirm that the + credential exists (`credentials(action="list")` or `get`), that the node uses + it (the node's `credentials` in `workflows(action="get")`; resolved + parameters show only the auth type, not which credential is bound), and what + `credentials(action="test")` reports. A generic credential, such as Header + Auth, can pass its test without a call to the service, so a pass does not + show that the service accepts it. Say so when you report the check. +- **Other node errors.** Start from `executions(action="debug")` and the + resolved parameters of the failed node. + +Then report the checks and their results, and only after that give a cause. +You cannot read a stored secret, so a cause about its format or value is a +hypothesis: label it as one, and say which check would confirm it. Do not blame +the user's account, billing, credit, plan, or quota unless the error says so. + +A cause outside the workflow does not mean that the workflow is correct. Before +you say that the workflow is wired or configured correctly, read the expression +parameters of every node on the failing path, not only the node that failed. An +expression that reads the wrong field, or a literal placeholder where an +expression belongs, is a defect even when a different error stopped the run. +Report each defect separately from the cause of the failed run. + ## Draft versus live A published workflow runs the version that was published, not the draft you @@ -199,8 +232,8 @@ call a sub-node made while the Agent ran. When `debug` doesn't apply because nothing errored, call `executions(action="get-resolved-node-parameters", executionId, nodeName)` on the -node whose output looks off — **do this unprompted**, don't ask the user for -permission first. It's a cheap read-only inspection and the only reliable way to -confirm whether an empty value came from an expression silently resolving to -nullish. Check `emptyResolutions` first; most "this parameter is empty" cases are +node whose output looks off and on the nodes that feed it — +**do this unprompted**, don't ask the user for permission first. It's a cheap +read-only inspection and the only reliable way to confirm whether an empty value came +from an expression silently resolving to nullish. Check `emptyResolutions` first; most "this parameter is empty" cases are expressions resolving to `null`/`undefined`/`""`, not thrown errors. diff --git a/packages/@n8n/instance-ai/src/agent/__tests__/apply-agent-thinking.test.ts b/packages/@n8n/instance-ai/src/agent/__tests__/apply-agent-thinking.test.ts index fb73f1353b5..1df2b585ee7 100644 --- a/packages/@n8n/instance-ai/src/agent/__tests__/apply-agent-thinking.test.ts +++ b/packages/@n8n/instance-ai/src/agent/__tests__/apply-agent-thinking.test.ts @@ -157,6 +157,22 @@ describe('applyAgentThinking', () => { } }); + it('prefers an explicit Anthropic effort over N8N_INSTANCE_AI_REASONING_EFFORT', () => { + const previous = process.env.N8N_INSTANCE_AI_REASONING_EFFORT; + process.env.N8N_INSTANCE_AI_REASONING_EFFORT = 'low'; + try { + const agent = new Agent('test'); + applyAgentThinking(agent, 'anthropic/claude-sonnet-5-5', 'high'); + expect(mockAgentInstances[0]?.thinking).toHaveBeenCalledWith('anthropic', { + mode: 'adaptive', + effort: 'high', + }); + } finally { + if (previous === undefined) delete process.env.N8N_INSTANCE_AI_REASONING_EFFORT; + else process.env.N8N_INSTANCE_AI_REASONING_EFFORT = previous; + } + }); + it('skips providers without thinking support', () => { const agent = new Agent('test'); applyAgentThinking(agent, 'google/gemini-2.5-pro'); diff --git a/packages/@n8n/instance-ai/src/agent/apply-agent-thinking.ts b/packages/@n8n/instance-ai/src/agent/apply-agent-thinking.ts index 214ebc70fbd..2ca917baf1f 100644 --- a/packages/@n8n/instance-ai/src/agent/apply-agent-thinking.ts +++ b/packages/@n8n/instance-ai/src/agent/apply-agent-thinking.ts @@ -1,4 +1,4 @@ -import type { Agent, ModelConfig } from '@n8n/agents'; +import type { Agent, AnthropicThinkingEffort, ModelConfig } from '@n8n/agents'; import { PROVIDER_CAPABILITIES } from '@n8n/api-types'; import { resolveModelIdString, resolveModelProvider } from './model-config-identity'; @@ -28,7 +28,12 @@ function resolveAnthropicEffort(): AnthropicEffort { return ANTHROPIC_EFFORTS.find((supported) => supported === effort) ?? 'medium'; } -export function applyAgentThinking(agent: Agent, modelId: ModelConfig): void { +/** An explicit effort wins over the env override. */ +export function applyAgentThinking( + agent: Agent, + modelId: ModelConfig, + anthropicEffort?: AnthropicThinkingEffort, +): void { const provider = resolveModelProvider(modelId); if (!provider || !PROVIDER_CAPABILITIES[provider]?.thinking) return; @@ -61,7 +66,10 @@ export function applyAgentThinking(agent: Agent, modelId: ModelConfig): void { } if (provider === 'anthropic' || provider === 'google-vertex-anthropic') { - agent.thinking(provider, { mode: 'adaptive', effort: resolveAnthropicEffort() }); + agent.thinking(provider, { + mode: 'adaptive', + effort: anthropicEffort ?? resolveAnthropicEffort(), + }); return; } diff --git a/packages/@n8n/instance-ai/src/index.ts b/packages/@n8n/instance-ai/src/index.ts index 5a4a17de891..a7488c5b1a9 100644 --- a/packages/@n8n/instance-ai/src/index.ts +++ b/packages/@n8n/instance-ai/src/index.ts @@ -452,6 +452,9 @@ export const createEvalAgent: typeof EvalAgentsMod.createEvalAgent = lazyFunctio export const extractText: typeof EvalAgentsMod.extractText = lazyFunction( () => loadEvalAgents().extractText, ); +export const isRetryableEvalError: typeof EvalAgentsMod.isRetryableEvalError = lazyFunction( + () => loadEvalAgents().isRetryableEvalError, +); export const meterEvalUsage: typeof EvalUsageMod.meterEvalUsage = lazyFunction( () => loadEvalUsage().meterEvalUsage, ); @@ -534,6 +537,7 @@ export const createSandbox: typeof CreateWorkspaceMod.createSandbox = lazyFuncti export const createWorkspace: typeof CreateWorkspaceMod.createWorkspace = lazyFunction( () => loadCreateWorkspace().createWorkspace, ); +export type { VerifiedWorkspaceBundles } from './workspace/prebaked-workspace-bundle'; export type SnapshotManager = SnapshotManagerMod.SnapshotManager; export const SnapshotManager: typeof SnapshotManagerMod.SnapshotManager = lazyClass( () => loadSnapshotManager().SnapshotManager, diff --git a/packages/@n8n/instance-ai/src/knowledge-base/__tests__/materialize-knowledge-base.test.ts b/packages/@n8n/instance-ai/src/knowledge-base/__tests__/materialize-knowledge-base.test.ts index 37e69e5f446..8a96a3cb13e 100644 --- a/packages/@n8n/instance-ai/src/knowledge-base/__tests__/materialize-knowledge-base.test.ts +++ b/packages/@n8n/instance-ai/src/knowledge-base/__tests__/materialize-knowledge-base.test.ts @@ -299,7 +299,7 @@ describe('materializeKnowledgeBaseIntoWorkspace', () => { expect(writes.size).toBe(0); }); - it('rematerializes when prebaked manifest exists but payload is incomplete', async () => { + it('trusts a matching prebaked manifest without checking each payload file', async () => { const bundle = await buildKnowledgeBaseWorkspaceBundle({ root: ROOT, logger: mockLogger }); const files = new Map([ [bundle.manifestPath, bundle.files.get(bundle.manifestPath) ?? ''], @@ -313,7 +313,6 @@ describe('materializeKnowledgeBaseIntoWorkspace', () => { }); expect(materialized.contentHash).toBe(bundle.contentHash); - expect(writes.has(bundle.indexPath)).toBe(true); - expect(writes.size).toBeGreaterThan(1); + expect(writes.size).toBe(0); }); }); diff --git a/packages/@n8n/instance-ai/src/knowledge-base/materialize-knowledge-base.ts b/packages/@n8n/instance-ai/src/knowledge-base/materialize-knowledge-base.ts index c4489f563a4..8aa5e345ce9 100644 --- a/packages/@n8n/instance-ai/src/knowledge-base/materialize-knowledge-base.ts +++ b/packages/@n8n/instance-ai/src/knowledge-base/materialize-knowledge-base.ts @@ -25,6 +25,7 @@ import { computeWorkspaceContentHash } from '../workspace/compute-workspace-cont import { loadPrebakedWorkspaceBundle, materializeWorkspaceBundle, + type VerifiedWorkspaceBundles, } from '../workspace/prebaked-workspace-bundle'; import type { SandboxWorkspace } from '../workspace/sandbox-fs'; import { stringifyWorkspaceJson, withTrailingNewline } from '../workspace/workspace-file-content'; @@ -100,6 +101,7 @@ export interface BuildKnowledgeBaseWorkspaceBundleOptions { interface MaterializeKnowledgeBaseOptions extends BuildKnowledgeBaseWorkspaceBundleOptions { workspace: SandboxWorkspace; + verifiedBundles?: VerifiedWorkspaceBundles; } function addTemplatesToKnowledgeBaseFiles( @@ -307,6 +309,7 @@ export async function loadPrebakedKnowledgeBaseBundle( return await loadPrebakedWorkspaceBundle({ workspace: options.workspace, + verifiedBundles: options.verifiedBundles, manifestPath: bundle.manifestPath, expectedHash: bundle.contentHash, hashField: 'contentHash', @@ -343,10 +346,12 @@ export async function materializeKnowledgeBaseIntoWorkspace( async () => { return await materializeWorkspaceBundle({ workspace: options.workspace, + verifiedBundles: options.verifiedBundles, resourceLabel: KNOWLEDGE_BASE_FILE_LABEL, logger: options.logger, loadPrebaked: async () => await loadPrebakedKnowledgeBaseBundle(options), buildBundle: async () => await buildKnowledgeBaseWorkspaceBundle(options), + bundleHash: (bundle) => bundle.contentHash, materializedLogMessage: 'Materialized knowledge base into workspace', materializedLogContext: (bundle) => ({ root: options.root, diff --git a/packages/@n8n/instance-ai/src/runtime/orchestrator-identity.ts b/packages/@n8n/instance-ai/src/runtime/orchestrator-identity.ts index edddfa08fe3..34b4d01cf35 100644 --- a/packages/@n8n/instance-ai/src/runtime/orchestrator-identity.ts +++ b/packages/@n8n/instance-ai/src/runtime/orchestrator-identity.ts @@ -1,8 +1,7 @@ /** * Per-run orchestrator agent id, derived from the run's cryptographic id. * Deterministic so every emitter and recovery path agrees without persisting a - * separate field; unique across runs, stable within a run. + * separate field; unique across runs, stable within a run. The run reducer in + * `@n8n/api-types` owns the format, because it resolves follow-up runs by it. */ -export function orchestratorAgentId(runId: string): string { - return `orchestrator-${runId}`; -} +export { orchestratorAgentId } from '@n8n/api-types'; diff --git a/packages/@n8n/instance-ai/src/skills/__tests__/materialize-runtime-skills.test.ts b/packages/@n8n/instance-ai/src/skills/__tests__/materialize-runtime-skills.test.ts index 6ededbeee70..f9817d7aaf2 100644 --- a/packages/@n8n/instance-ai/src/skills/__tests__/materialize-runtime-skills.test.ts +++ b/packages/@n8n/instance-ai/src/skills/__tests__/materialize-runtime-skills.test.ts @@ -319,6 +319,42 @@ describe('materializeRuntimeSkillsIntoWorkspace', () => { expect(text).toContain(skillPath); }); + it('checks a prebaked bundle once per sandbox and reads only the manifest', async () => { + const source = loadInstanceAiRuntimeSkillSource(); + const { workspace, writes, readFile, writeFile } = createMockWorkspace(); + const root = '/home/daytona/workspace'; + const bundle = await buildRuntimeSkillWorkspaceBundle({ source, root, logger: mockLogger }); + if (!bundle) throw new Error('Expected runtime skill bundle'); + for (const [path, content] of bundle.files) { + writes.set(path, content); + } + const verifiedBundles = new Map(); + const runSkillLoad = async () => { + const runtimeSource = createLazyWorkspaceRuntimeSkillSource({ + logger: mockLogger, + source, + workspace, + resolveVerifiedBundles: async () => await Promise.resolve(verifiedBundles), + }); + return await createSkillLoadTool(runtimeSource).handler?.( + { skillId: 'data-table-manager' }, + {}, + ); + }; + + await runSkillLoad(); + + expect(readFile).toHaveBeenCalledTimes(1); + expect(readFile).toHaveBeenCalledWith(bundle.manifestPath, expect.anything()); + + readFile.mockClear(); + const result = await runSkillLoad(); + + expect(readFile).not.toHaveBeenCalled(); + expect(writeFile).not.toHaveBeenCalled(); + expect(skillLoadText(result)).toContain('[Skill: "data-table-manager"]'); + }); + it('falls back to live materialization when the prebaked manifest is stale', async () => { const source = loadInstanceAiRuntimeSkillSource(); const { workspace, writes, writeFile } = createMockWorkspace(); diff --git a/packages/@n8n/instance-ai/src/skills/__tests__/progressive-building.test.ts b/packages/@n8n/instance-ai/src/skills/__tests__/progressive-building.test.ts index 07da889bfc1..94f82c67098 100644 --- a/packages/@n8n/instance-ai/src/skills/__tests__/progressive-building.test.ts +++ b/packages/@n8n/instance-ai/src/skills/__tests__/progressive-building.test.ts @@ -56,6 +56,7 @@ describe('progressive workflow skill variants', () => { const excluded = disabledInstanceAiSkillIds({ configEvalsEnabled: true, instanceContextEnabled: true, + agentBuildingEnabled: true, }); const control = filterRuntimeSkillSource( await loadInstanceAiRuntimeSkillSourceForBuildMode('default'), diff --git a/packages/@n8n/instance-ai/src/skills/__tests__/runtime-skills.test.ts b/packages/@n8n/instance-ai/src/skills/__tests__/runtime-skills.test.ts index 0e2c9a99d8d..bb63e58371c 100644 --- a/packages/@n8n/instance-ai/src/skills/__tests__/runtime-skills.test.ts +++ b/packages/@n8n/instance-ai/src/skills/__tests__/runtime-skills.test.ts @@ -1,4 +1,4 @@ -import { createSkillLoadTool } from '@n8n/agents'; +import { createSkillLoadTool, filterRuntimeSkillSource } from '@n8n/agents'; import { existsSync, readdirSync, readFileSync } from 'node:fs'; import { join } from 'node:path'; @@ -9,10 +9,13 @@ import { loadInstanceAiRuntimeSkillSourceForBuildMode, warmRuntimeSkills, } from '../runtime-skills'; -import { CONFIG_EVALS_SKILL_ID, disabledInstanceAiSkillIds } from '../skill-gates'; +import { + AGENT_BUILDING_SKILL_IDS, + CONFIG_EVALS_SKILL_ID, + disabledInstanceAiSkillIds, +} from '../skill-gates'; const ORIGINAL_ENABLED_MODULES = process.env.N8N_ENABLED_MODULES; -const AGENTS_MODULE_SKILL_IDS = ['agent-builder', 'intent-recognition'] as const; describe('Instance AI runtime skills', () => { afterEach(() => { @@ -127,9 +130,11 @@ describe('Instance AI runtime skills', () => { const topLevel = source.registry.skills.filter((skill) => !skill.parents).map(({ id }) => id); expect(topLevel.sort()).toEqual([ + 'agent-builder', 'data-table-manager', 'debugging-executions', 'instance-awareness', + 'intent-recognition', 'n8n-docs-assistant', 'planned-task-runtime', 'planning', @@ -185,7 +190,7 @@ describe('Instance AI runtime skills', () => { }); it('shares the Computer Use credential setup reference with agent-builder', async () => { - const source = await loadRuntimeSkillSourceWithEnabledModules('instance-ai, agents'); + const source = loadInstanceAiRuntimeSkillSource(); const skill = source.registry.skills.find( (entry) => entry.id === 'credential-setup-with-computer-use', ); @@ -267,12 +272,14 @@ describe('Instance AI runtime skills', () => { disabledInstanceAiSkillIds({ configEvalsEnabled: false, instanceContextEnabled: true, + agentBuildingEnabled: true, }), ).toContain(CONFIG_EVALS_SKILL_ID); expect( disabledInstanceAiSkillIds({ configEvalsEnabled: true, instanceContextEnabled: true, + agentBuildingEnabled: true, }), ).not.toContain(CONFIG_EVALS_SKILL_ID); @@ -294,20 +301,27 @@ describe('Instance AI runtime skills', () => { } }); - it('excludes bundled Agents module skills unless the module is enabled', async () => { - const source = await loadRuntimeSkillSourceWithEnabledModules('instance-ai'); + it('hides the Agents module skills when the skill gates say the module is off', async () => { + const source = filterRuntimeSkillSource( + loadInstanceAiRuntimeSkillSource(), + disabledInstanceAiSkillIds({ + configEvalsEnabled: true, + instanceContextEnabled: true, + agentBuildingEnabled: false, + }), + ); - for (const skillId of AGENTS_MODULE_SKILL_IDS) { + for (const skillId of AGENT_BUILDING_SKILL_IDS) { expect(source.registry.skills).not.toContainEqual(expect.objectContaining({ id: skillId })); await expect(source.loadSkill(skillId)).resolves.toBeNull(); } }); - it('loads bundled Agents module skills when the module is enabled', async () => { - const source = await loadRuntimeSkillSourceWithEnabledModules('instance-ai, agents'); + it('loads the bundled Agents module skills', async () => { + const source = loadInstanceAiRuntimeSkillSource(); const loadTool = createSkillLoadTool(source); - for (const skillId of AGENTS_MODULE_SKILL_IDS) { + for (const skillId of AGENT_BUILDING_SKILL_IDS) { expect(source.registry.skills).toContainEqual(expect.objectContaining({ id: skillId })); await expect(source.loadSkill(skillId)).resolves.toMatchObject({ name: skillId }); @@ -316,8 +330,18 @@ describe('Instance AI runtime skills', () => { } }); + it('loads every bundled skill whatever N8N_ENABLED_MODULES contains', async () => { + const unset = await loadRuntimeSkillSourceWithEnabledModules(undefined); + const withoutAgents = await loadRuntimeSkillSourceWithEnabledModules('instance-ai'); + + expect(withoutAgents.registry.skillsHash).toBe(unset.registry.skillsHash); + for (const skillId of AGENT_BUILDING_SKILL_IDS) { + expect(unset.registry.skills).toContainEqual(expect.objectContaining({ id: skillId })); + } + }); + it('loads the bundled agent-builder skill', async () => { - const source = await loadRuntimeSkillSourceWithEnabledModules('instance-ai, agents'); + const source = loadInstanceAiRuntimeSkillSource(); const skill = source.registry.skills.find((entry) => entry.name === 'agent-builder'); expect(skill).toBeDefined(); @@ -631,6 +655,9 @@ describe('Instance AI runtime skills', () => { ); expect(loaded?.instructions).toContain('unreconstructable-context'); expect(loaded?.instructions).toContain('do this unprompted'); + expect(loaded?.instructions).toContain('## Before you name a cause'); + expect(loaded?.instructions).toContain('credentials(action="test")'); + expect(skill?.description).toContain('a live run you started'); }); }); diff --git a/packages/@n8n/instance-ai/src/skills/__tests__/skill-gates.test.ts b/packages/@n8n/instance-ai/src/skills/__tests__/skill-gates.test.ts index 0454c6449bc..4e6e66d53be 100644 --- a/packages/@n8n/instance-ai/src/skills/__tests__/skill-gates.test.ts +++ b/packages/@n8n/instance-ai/src/skills/__tests__/skill-gates.test.ts @@ -1,4 +1,5 @@ import { + AGENT_BUILDING_SKILL_IDS, CONFIG_EVAL_PLAYBOOK_SKILL_ID, CONFIG_EVALS_SKILL_ID, INSTANCE_AWARENESS_SKILL_ID, @@ -10,6 +11,7 @@ describe('disabledInstanceAiSkillIds', () => { const disabled = disabledInstanceAiSkillIds({ configEvalsEnabled: true, instanceContextEnabled: true, + agentBuildingEnabled: true, }); expect(disabled).toEqual([]); }); @@ -18,6 +20,7 @@ describe('disabledInstanceAiSkillIds', () => { const disabled = disabledInstanceAiSkillIds({ configEvalsEnabled: enabled, instanceContextEnabled: true, + agentBuildingEnabled: true, }); expect(disabled.includes(CONFIG_EVALS_SKILL_ID)).toBe(!enabled); expect(disabled.includes(CONFIG_EVAL_PLAYBOOK_SKILL_ID)).toBe(!enabled); @@ -28,6 +31,7 @@ describe('disabledInstanceAiSkillIds', () => { disabledInstanceAiSkillIds({ configEvalsEnabled: true, instanceContextEnabled: false, + agentBuildingEnabled: true, }), ).toEqual([INSTANCE_AWARENESS_SKILL_ID]); }); @@ -37,7 +41,18 @@ describe('disabledInstanceAiSkillIds', () => { disabledInstanceAiSkillIds({ configEvalsEnabled: true, instanceContextEnabled: true, + agentBuildingEnabled: true, }), ).toEqual([]); }); + + it('hides the Agents module skills when the module is not active', () => { + expect( + disabledInstanceAiSkillIds({ + configEvalsEnabled: true, + instanceContextEnabled: true, + agentBuildingEnabled: false, + }), + ).toEqual([...AGENT_BUILDING_SKILL_IDS]); + }); }); diff --git a/packages/@n8n/instance-ai/src/skills/materialize-runtime-skills.ts b/packages/@n8n/instance-ai/src/skills/materialize-runtime-skills.ts index 8b8673f82fe..775f4e15b2f 100644 --- a/packages/@n8n/instance-ai/src/skills/materialize-runtime-skills.ts +++ b/packages/@n8n/instance-ai/src/skills/materialize-runtime-skills.ts @@ -20,6 +20,7 @@ import { traceSandboxOperation } from '../tracing/sandbox-tracing'; import { loadPrebakedWorkspaceBundle, materializeWorkspaceBundle, + type VerifiedWorkspaceBundles, } from '../workspace/prebaked-workspace-bundle'; import { stringifyWorkspaceJson, withTrailingNewline } from '../workspace/workspace-file-content'; import { WORKSPACE_MANIFEST_FILE } from '../workspace/workspace-manifest'; @@ -70,6 +71,7 @@ interface BuildRuntimeSkillWorkspaceBundleOptions { interface MaterializeRuntimeSkillsOptions { source: RuntimeSkillSource; workspace: Workspace; + verifiedBundles?: VerifiedWorkspaceBundles; root: string; workspaceRoot?: string; logger: Logger; @@ -78,6 +80,8 @@ interface MaterializeRuntimeSkillsOptions { interface LazyWorkspaceRuntimeSkillSourceOptions { source: RuntimeSkillSource; workspace: Workspace | undefined; + /** Resolves the verified bundles of the sandbox behind `workspace`. */ + resolveVerifiedBundles?: () => Promise; logger: Logger; } @@ -387,6 +391,7 @@ const RUNTIME_SKILL_FILE_LABEL = 'Runtime skill file'; export async function loadPrebakedRuntimeSkillsBundle({ source, workspace, + verifiedBundles, root, workspaceRoot = root, logger, @@ -398,6 +403,7 @@ export async function loadPrebakedRuntimeSkillsBundle({ return await loadPrebakedWorkspaceBundle({ workspace, + verifiedBundles, manifestPath, expectedHash: source.registry.skillsHash, hashField: 'skillsHash', @@ -592,6 +598,7 @@ export async function buildRuntimeSkillWorkspaceBundle({ export async function materializeRuntimeSkillsIntoWorkspace({ source, workspace, + verifiedBundles, root, logger, }: MaterializeRuntimeSkillsOptions): Promise { @@ -608,10 +615,17 @@ export async function materializeRuntimeSkillsIntoWorkspace({ return await materializeWorkspaceBundle({ workspace, + verifiedBundles, resourceLabel: RUNTIME_SKILL_FILE_LABEL, logger, loadPrebaked: async () => - await loadPrebakedRuntimeSkillsBundle({ source, workspace, root, logger }), + await loadPrebakedRuntimeSkillsBundle({ + source, + workspace, + verifiedBundles, + root, + logger, + }), buildBundle: async () => { const bundle = await buildRuntimeSkillWorkspaceBundle({ source, root, logger }); if (!bundle) { @@ -619,6 +633,7 @@ export async function materializeRuntimeSkillsIntoWorkspace({ } return bundle; }, + bundleHash: (bundle) => bundle.skillsHash, materializedLogMessage: 'Materialized runtime skills into workspace', materializedLogContext: (bundle) => ({ root, @@ -635,6 +650,7 @@ export async function materializeRuntimeSkillsIntoWorkspace({ export function createLazyWorkspaceRuntimeSkillSource({ source, workspace, + resolveVerifiedBundles, logger, }: LazyWorkspaceRuntimeSkillSourceOptions): RuntimeSkillSource { if (!workspace || source.registry.skills.length === 0) return source; @@ -664,7 +680,8 @@ export function createLazyWorkspaceRuntimeSkillSource({ materializePromise ??= (async () => { const root = await getWorkspaceRoot(runtimeWorkspace); - const options = { source, workspace: runtimeWorkspace, root, logger }; + const verifiedBundles = await resolveVerifiedBundles?.(); + const options = { source, workspace: runtimeWorkspace, verifiedBundles, root, logger }; const result = await materializeRuntimeSkillsIntoWorkspace(options); if (result) { materialized = result; diff --git a/packages/@n8n/instance-ai/src/skills/runtime-skills.ts b/packages/@n8n/instance-ai/src/skills/runtime-skills.ts index a6e7dc52d46..71f97dd1e63 100644 --- a/packages/@n8n/instance-ai/src/skills/runtime-skills.ts +++ b/packages/@n8n/instance-ai/src/skills/runtime-skills.ts @@ -5,8 +5,6 @@ import { GROUPING_GUIDANCE } from '@n8n/workflow-sdk/prompts/sdk-reference'; import { TOP_LEVEL_ITEM_CEILING } from 'n8n-workflow'; import { resolve } from 'node:path'; -import { isAgentFeatureEnabled } from '@/utils/agent-feature-enabled'; - import type { Logger } from '../logger'; import type { InstanceAiTraceContext } from '../types'; import { @@ -17,7 +15,6 @@ import { import { composeSkillVariants } from '../prompts/skill-variants'; export const INSTANCE_AI_SKILLS_DIR = resolve(__dirname, '..', '..', 'skills'); -const AGENTS_MODULE_RUNTIME_SKILLS = new Set(['agent-builder', 'intent-recognition']); let cachedRuntimeSkillSource: RuntimeSkillSource | undefined; const cachedProfiles = new Map>(); @@ -34,9 +31,12 @@ export function substituteSkillPlaceholders(instructions: string): string { ); } +/** + * Every bundled runtime skill. The sandbox image, the snapshot and each sandbox + * store this set. Hide gated skills per run with `disabledInstanceAiSkillIds`. + */ export function loadInstanceAiRuntimeSkillSource(): RuntimeSkillSource { cachedRuntimeSkillSource ??= loadRuntimeSkillSourceFromDirectory(INSTANCE_AI_SKILLS_DIR, { - exclude: isAgentFeatureEnabled() ? [] : [...AGENTS_MODULE_RUNTIME_SKILLS], transformInstructions: substituteSkillPlaceholders, }); return cachedRuntimeSkillSource; diff --git a/packages/@n8n/instance-ai/src/skills/skill-gates.ts b/packages/@n8n/instance-ai/src/skills/skill-gates.ts index cf70ca358c6..6fa0df8fefb 100644 --- a/packages/@n8n/instance-ai/src/skills/skill-gates.ts +++ b/packages/@n8n/instance-ai/src/skills/skill-gates.ts @@ -17,10 +17,18 @@ export const CONFIG_EVAL_PLAYBOOK_SKILL_ID = 'config-eval-playbook'; */ export const INSTANCE_AWARENESS_SKILL_ID = 'instance-awareness'; +/** Skill folder ids that only work when the Assistant can build agents. */ +export const AGENT_BUILDING_SKILL_IDS = ['agent-builder', 'intent-recognition'] as const; + /** Resolved feature flags that gate one or more runtime skills. */ export interface InstanceAiSkillFlags { configEvalsEnabled: boolean; instanceContextEnabled: boolean; + /** + * Whether the host gives the Assistant a builder delegate, so it can build + * agents. This needs the Agents module and the Settings > Agents switch. + */ + agentBuildingEnabled: boolean; } /** Skill ids to hide from a user's catalog given their resolved flags. */ @@ -30,5 +38,6 @@ export function disabledInstanceAiSkillIds(flags: InstanceAiSkillFlags): string[ disabled.push(CONFIG_EVALS_SKILL_ID, CONFIG_EVAL_PLAYBOOK_SKILL_ID); } if (!flags.instanceContextEnabled) disabled.push(INSTANCE_AWARENESS_SKILL_ID); + if (!flags.agentBuildingEnabled) disabled.push(...AGENT_BUILDING_SKILL_IDS); return disabled; } diff --git a/packages/@n8n/instance-ai/src/tools/__tests__/workflows.tool.test.ts b/packages/@n8n/instance-ai/src/tools/__tests__/workflows.tool.test.ts index 5c9c37354c7..03a6061e283 100644 --- a/packages/@n8n/instance-ai/src/tools/__tests__/workflows.tool.test.ts +++ b/packages/@n8n/instance-ai/src/tools/__tests__/workflows.tool.test.ts @@ -3473,6 +3473,78 @@ describe('workflows tool', () => { expect(suspend.mock.calls[0][0]).toMatchObject({ setupRequests: [sheetsRequest] }); }); + describe('nodes the build left out of setup', () => { + // The build changed only the Sheets node; Slack is pre-existing and unconfigured. + function createScopedContext() { + const context = createGrantAwareContext(); + context.runId = 'run-1'; + (context as { workflowBuildContext?: unknown }).workflowBuildContext = { + threadId: 't1', + runId: 'run-1', + taskId: 'task-1', + workItemId: 'wi-1', + workflowTaskService: { + getLatestBuildOutcomeForWorkflow: vi + .fn() + .mockResolvedValue({ runId: 'run-1', changedNodeNames: ['Log to Sheet'] }), + }, + }; + return context; + } + + beforeEach(() => { + (analyzeWorkflow as Mock).mockResolvedValue([slackRequest, sheetsRequest]); + (applyNodeChanges as Mock).mockResolvedValue({ applied: [], failed: [] }); + (buildCompletedReport as Mock).mockReturnValue([]); + }); + + it('does not record them as skipped when the user skips the card', async () => { + const context = createScopedContext(); + + const tool = createWorkflowsTool(context); + const result = await executeTool(tool, { action: 'setup', workflowId: 'wf1' }, { + resumeData: { approved: false }, + } as never); + + expect(context.grantSessionToolApproval).not.toHaveBeenCalledWith( + 'workflows:setup-skip:cred:slackApi', + ); + expect(result).toMatchObject({ skippedByUser: [{ nodeName: 'Log to Sheet' }] }); + }); + + it('does not report them as still needing setup after apply', async () => { + const context = createScopedContext(); + + const tool = createWorkflowsTool(context); + const result = await executeTool(tool, { action: 'setup', workflowId: 'wf1' }, { + resumeData: { approved: true, action: 'apply' }, + } as never); + + expect(result).toMatchObject({ + partial: true, + nodesStillNeedingSetup: [{ nodeName: 'Log to Sheet' }], + }); + }); + + it('keeps them out of the panel a trigger test rebuilds', async () => { + const context = createScopedContext(); + (context.executionService.run as Mock).mockResolvedValue({ status: 'success' }); + const suspend = vi.fn(); + + const tool = createWorkflowsTool(context); + await executeTool(tool, { action: 'setup', workflowId: 'wf1' }, { + suspend, + resumeData: { + approved: true, + action: 'test-trigger', + testTriggerNode: 'Log to Sheet', + }, + } as never); + + expect(suspend.mock.calls[0][0]).toMatchObject({ setupRequests: [sheetsRequest] }); + }); + }); + it('revalidates the credential test destination after a trigger test', async () => { const fixture = templatedSetupFixture({ testUrl: 'https://status.example.net/me' }); (analyzeWorkflow as Mock).mockResolvedValue([fixture.request]); diff --git a/packages/@n8n/instance-ai/src/tools/tool-ids.ts b/packages/@n8n/instance-ai/src/tools/tool-ids.ts index 4526153c1a1..058483fae79 100644 --- a/packages/@n8n/instance-ai/src/tools/tool-ids.ts +++ b/packages/@n8n/instance-ai/src/tools/tool-ids.ts @@ -1,5 +1,3 @@ -import { isAgentFeatureEnabled } from '../utils/agent-feature-enabled'; - export const DOMAIN_TOOL_IDS = { WORKFLOWS: 'workflows', EVAL_CONFIG: 'eval-config', @@ -95,8 +93,9 @@ export const ALWAYS_LOADED_TOOL_NAMES = new Set([ 'fetch-url', // build-agent is the primary route for agent-anchored intents; deferring it // costs 2 LLM rounds (search_tools + load_tool) and a prompt-cache rewrite - // on every agent build. - ...(isAgentFeatureEnabled() ? [ORCHESTRATION_TOOL_IDS.BUILD_AGENT] : []), + // on every agent build. Registered only when the host provides a builder + // delegate (Agents module active), so an instance without it pays nothing. + ORCHESTRATION_TOOL_IDS.BUILD_AGENT, ]); export const CHECKPOINT_FOLLOW_UP_TOOL_NAMES = new Set([ diff --git a/packages/@n8n/instance-ai/src/tools/workflows.tool.ts b/packages/@n8n/instance-ai/src/tools/workflows.tool.ts index cf8685b8070..eeb305787f7 100644 --- a/packages/@n8n/instance-ai/src/tools/workflows.tool.ts +++ b/packages/@n8n/instance-ai/src/tools/workflows.tool.ts @@ -1189,11 +1189,11 @@ async function handleSetupTestTrigger( appliedCredentialIds: appliedCredentialIdList(resumeData.credentials, preTestApply.applied), }, ); - // Re-derived from scratch, so it has to be partitioned again: this is the second path that - // builds the panel, and without it a trigger test mid-session puts back the cards state 1 - // left out. + // Re-derived from scratch, so it has to be scoped and partitioned again: this is the second + // path that builds the panel, and without it a trigger test mid-session puts back the cards + // state 1 left out. The destination check below still sees every node. const { pending: refreshedPending } = partitionSkippedSetupRequests( - refreshedRequests, + await filterToSetupScope(context, input, refreshedRequests), input.workflowId, getSkippedSetupSubjects(context), ); @@ -1319,12 +1319,17 @@ async function handleSetupApply( // Filter by needsAction to distinguish "render this card" from // "this still requires user intervention". Settled requests are kept so // a just-applied credential whose test failed stays reportable below — - // a bound credential is settled for routing even when its test fails. - const remainingRequests = await analyzeWorkflow(context, input.workflowId, undefined, { - includeSettled: true, - ...preferNewCredentialOptions(input, resumeData.credentials), - appliedCredentialIds: appliedCredentialIdList(resumeData.credentials, applyResult.applied), - }); + // a bound credential is settled for routing even when its test fails. Scoped like the + // card: a node it left out is neither still pending nor skipped by the user. + const remainingRequests = await filterToSetupScope( + context, + input, + await analyzeWorkflow(context, input.workflowId, undefined, { + includeSettled: true, + ...preferNewCredentialOptions(input, resumeData.credentials), + appliedCredentialIds: appliedCredentialIdList(resumeData.credentials, applyResult.applied), + }), + ); const completedNodes = buildCompletedReport( resumeData.credentials, resumeData.nodeParameters, @@ -1444,6 +1449,23 @@ async function resolveSetupScopeNodeNames( } } +/** + * Narrow requests to the build-bound setup scope. Every path that builds or reports the setup + * card goes through here, so a node the card left out cannot come back through a trigger test, + * the apply report, or a skip the user never made. + */ +async function filterToSetupScope( + context: InstanceAiContext, + input: Extract, + requests: SetupRequest[], +): Promise { + if (input.includeAllNodes) return requests; + const scopeNodeNames = await resolveSetupScopeNodeNames(context, input.workflowId); + return scopeNodeNames + ? requests.filter((request) => scopeNodeNames.includes(request.node.name)) + : requests; +} + /** * Coverage disclosure for the workflow's latest verification, or undefined when * it was fully verified or no claim exists. Absent evidence never blocks: a @@ -1689,12 +1711,7 @@ async function handleSetup( // Setup after a build covers only the nodes that build changed — // pre-existing, unrelated nodes must not surface in the setup card. - const scopeNodeNames = input.includeAllNodes - ? undefined - : await resolveSetupScopeNodeNames(context, input.workflowId); - const scopedRequests = scopeNodeNames - ? allSetupRequests.filter((request) => scopeNodeNames.includes(request.node.name)) - : allSetupRequests; + const scopedRequests = await filterToSetupScope(context, input, allSetupRequests); // Two reasons a card stays out, applied in order: this build never touched the node, or // the user declined it. Partitioning the scoped list keeps them apart in the report — @@ -1774,11 +1791,9 @@ async function handleSetup( // the user declined, and pre-existing nodes this build never touched. Both can hold at // once, so neither branch may swallow the other. Named "out of scope" rather than // "skipped" because in this file a skip is specifically a user decision. - const outOfScopeNodeNames = scopeNodeNames - ? allSetupRequests - .map((request) => request.node.name) - .filter((name) => !scopeNodeNames.includes(name)) - : []; + const outOfScopeNodeNames = allSetupRequests + .filter((request) => !scopedRequests.includes(request)) + .map((request) => request.node.name); const outOfScopeReason = outOfScopeNodeNames.length > 0 ? `Pre-existing node(s) ${outOfScopeNodeNames @@ -1837,10 +1852,11 @@ async function handleSetup( } // Re-analyze rather than remembering what was suspended: the closure state doesn't // survive a resume in another process, and a skip that silently fails to persist is - // the whole bug. Everything still needing setup is what the user just dismissed. - const dismissed = (await analyzeWorkflow(context, input.workflowId)).filter( - (request) => request.needsAction, - ); + // the whole bug. Everything in scope still needing setup is what the user just + // dismissed; a node the card left out was never offered, so it is not a skip. + const dismissed = ( + await filterToSetupScope(context, input, await analyzeWorkflow(context, input.workflowId)) + ).filter((request) => request.needsAction); await rememberSkippedSetup(context, dismissed, input.workflowId); return { success: true, diff --git a/packages/@n8n/instance-ai/src/tools/workflows/__tests__/build-workflow.tool.test.ts b/packages/@n8n/instance-ai/src/tools/workflows/__tests__/build-workflow.tool.test.ts index 9ccdc150981..1b5e7b8b3ed 100644 --- a/packages/@n8n/instance-ai/src/tools/workflows/__tests__/build-workflow.tool.test.ts +++ b/packages/@n8n/instance-ai/src/tools/workflows/__tests__/build-workflow.tool.test.ts @@ -1612,6 +1612,90 @@ describe('createBuildWorkflowTool', () => { }); }); + describe('setup scope across rebuilds', () => { + const pendingWebhook = { + node: { + id: 'webhook-1', + name: 'Webhook', + type: 'n8n-nodes-base.webhook', + typeVersion: 2, + parameters: {}, + position: [0, 0], + }, + parameterIssues: { path: ['Missing webhook path'] }, + isTrigger: true, + needsAction: true, + } as SetupRequest; + + // The first build creates the workflow, so every node is in scope. The rebuild + // leaves the pending node untouched. + async function rebuildUnchanged({ + workItemId, + nextWorkItemId = workItemId, + nextRunId, + failInBetween = false, + }: { + workItemId?: string; + nextWorkItemId?: string; + nextRunId?: string; + failInBetween?: boolean; + } = {}) { + vi.mocked(analyzeWorkflow).mockResolvedValue([pendingWebhook]); + const { context, filePath } = makeContext({ source: 'workflow source' }); + const tool = createBuildWorkflowTool(context); + await executeTool(tool, { filePath, workItemId, name: 'Webhook flow' }); + vi.mocked(context.workflowService.getAsWorkflowJSON).mockResolvedValue({ + ...structuredClone(generatedWorkflow), + name: 'Webhook flow', + }); + if (failInBetween) { + vi.mocked(compileWorkflowSource).mockResolvedValueOnce({ + success: false, + reason: 'workflow_json_invalid', + editable: true, + errors: ['Workflow JSON must include name, nodes, and connections.'], + summary: 'Workflow JSON source is missing required workflow fields.', + }); + expect(await executeTool(tool, { filePath })).toMatchObject({ + success: false, + }); + } + if (nextRunId) context.runId = nextRunId; + return await executeTool(tool, { filePath, workItemId: nextWorkItemId }); + } + + it.each([false, true])( + 'keeps pending setup for a node an earlier build in the same run created (failed rebuild in between: %s)', + async (failInBetween) => { + expect(await rebuildUnchanged({ failInBetween })).toMatchObject({ + success: true, + setupRequirement: { status: 'required' }, + }); + }, + ); + + it.each([ + ['a later run of the same work item', 'required', { workItemId: 'wi-1', nextRunId: 'run-2' }], + [ + 'another work item in the same run', + 'required', + { workItemId: 'wi-1', nextWorkItemId: 'wi-2' }, + ], + [ + 'another work item in a later run', + 'not_required', + { workItemId: 'wi-1', nextWorkItemId: 'wi-2', nextRunId: 'run-2' }, + ], + // Without a work item id, the file path stands in for it on every build. + ['a later run without a work item id', 'not_required', { nextRunId: 'run-2' }], + ])('rebuild in %s: setup %s', async (_label, status, options) => { + expect(await rebuildUnchanged(options)).toMatchObject({ + success: true, + setupRequirement: { status }, + }); + }); + }); + it('updates the workflow bound to the source file and remembers the binding', async () => { const { context, filePath, trackTelemetry } = makeContext({ source: 'workflow source' }); const tool = createBuildWorkflowTool(context); diff --git a/packages/@n8n/instance-ai/src/tools/workflows/__tests__/generate-simulation-fixtures.service.test.ts b/packages/@n8n/instance-ai/src/tools/workflows/__tests__/generate-simulation-fixtures.service.test.ts index 87f9f15c298..e2eb980dd69 100644 --- a/packages/@n8n/instance-ai/src/tools/workflows/__tests__/generate-simulation-fixtures.service.test.ts +++ b/packages/@n8n/instance-ai/src/tools/workflows/__tests__/generate-simulation-fixtures.service.test.ts @@ -481,6 +481,7 @@ describe('generateSimulationFixtures', () => { resource: 'message', operation: 'post', hasOutputParser: false, + parameters: { resource: 'message', operation: 'post' }, }); const promptText = (generate.mock.calls[0][0] as Array<{ content: Array<{ text: string }> }>)[0] .content[0].text; @@ -678,6 +679,25 @@ describe('withPassThroughFloor', () => { expect(result.Hold).toEqual([{ email: 'ada@example.com' }]); }); + it('keeps the classification object when the classifier was asked for scores', () => { + const workflow = chain('@n8n/n8n-nodes-langchain.textClassifier'); + const classifier = workflow.nodes.find((node) => node.name === 'Hold'); + if (classifier) classifier.parameters = { options: { includeConfidenceScores: true } }; + + const result = withPassThroughFloor( + { + 'Get Contact': [{ email: 'ada@example.com' }], + Hold: [{ classification: { category: 'Billing', confidence: 0.9 }, invented: true }], + }, + workflow, + { outputSchemaLookup: lookupBrevoOnly }, + ); + + expect(result.Hold).toEqual([ + { email: 'ada@example.com', classification: { category: 'Billing', confidence: 0.9 } }, + ]); + }); + it('keeps the marker object a partial pass-through adds on top', () => { const result = withPassThroughFloor( { diff --git a/packages/@n8n/instance-ai/src/tools/workflows/__tests__/workflow-node-diff.test.ts b/packages/@n8n/instance-ai/src/tools/workflows/__tests__/workflow-node-diff.test.ts index da794a133b7..051f786313a 100644 --- a/packages/@n8n/instance-ai/src/tools/workflows/__tests__/workflow-node-diff.test.ts +++ b/packages/@n8n/instance-ai/src/tools/workflows/__tests__/workflow-node-diff.test.ts @@ -88,6 +88,32 @@ describe('computeChangedNodeNames', () => { expect(computeChangedNodeNames(built, saved).sort()).toEqual(['Compose', 'Send a message']); }); + it.each([ + [ + 'after', + { + Compose: { main: [[{ node: 'Send a message', type: 'main', index: 0 }]] }, + 'Send a message': { main: [[{ node: 'Log', type: 'main', index: 0 }]] }, + }, + ], + [ + 'before', + { + Compose: { main: [[{ node: 'Log', type: 'main', index: 0 }]] }, + Log: { main: [[{ node: 'Send a message', type: 'main', index: 0 }]] }, + }, + ], + ])('does not report connected nodes when a new node is added %s them', (_side, connections) => { + const saved = makeWorkflow([makeComposeNode(), makeNode()], { + Compose: { main: [[{ node: 'Send a message', type: 'main', index: 0 }]] }, + }); + const built = makeWorkflow( + [makeComposeNode(), makeNode(), makeComposeNode({ id: 'node-3', name: 'Log' })], + connections, + ); + expect(computeChangedNodeNames(built, saved)).toEqual(['Log']); + }); + it('does not treat a neighbour rename as a connection change (id-space signatures)', () => { const saved = makeWorkflow([makeComposeNode(), makeNode()], { Compose: { main: [[{ node: 'Send a message', type: 'main', index: 0 }]] }, diff --git a/packages/@n8n/instance-ai/src/tools/workflows/build-workflow.tool.ts b/packages/@n8n/instance-ai/src/tools/workflows/build-workflow.tool.ts index 043aff7c68a..e3aecf3d41f 100644 --- a/packages/@n8n/instance-ai/src/tools/workflows/build-workflow.tool.ts +++ b/packages/@n8n/instance-ai/src/tools/workflows/build-workflow.tool.ts @@ -1483,13 +1483,28 @@ export function createBuildWorkflowTool(context: InstanceAiContext) { (t): t is { nodeName: string; nodeType: string } => Boolean(t.nodeName) && Boolean(t.nodeType), ); - // Setup routing is scoped to nodes this build actually changed: - // pre-existing nodes the build merely round-tripped must not route - // the user into setup for an unrelated edit. Undefined = unscoped - // (new workflow, or prior state unreadable). - const changedNodeNames = savedWorkflowSnapshot + // Setup routing is scoped to nodes this work item's builds actually + // changed: pre-existing nodes the build merely round-tripped must not + // route the user into setup for an unrelated edit. Earlier builds of the + // same work item (or the same run) stay in scope, so a fix that leaves a + // new node alone keeps its pending setup. Undefined = unscoped (workflow + // created by this work item, or prior state unreadable). + const runId = buildContext?.runId ?? context.runId; + // The file path is the fallback work item id. It stays the same across + // work items, so only the run can match then. + const scopeWorkItemId = resolvedWorkItemId === filePath ? undefined : resolvedWorkItemId; + const priorScope = binding.setupScope; + const sameWork = + (scopeWorkItemId !== undefined && priorScope?.workItemId === scopeWorkItemId) || + (runId !== undefined && priorScope?.runId === runId); + const buildChanges = savedWorkflowSnapshot ? computeChangedNodeNames(json, savedWorkflowSnapshot) : undefined; + const changedNodeNames = !sameWork + ? buildChanges + : priorScope?.nodeNames && buildChanges + ? [...new Set([...priorScope.nodeNames, ...buildChanges])] + : undefined; const isInSetupScope = (nodeName: string | undefined) => changedNodeNames === undefined || (nodeName !== undefined && changedNodeNames.includes(nodeName)); @@ -1555,7 +1570,6 @@ export function createBuildWorkflowTool(context: InstanceAiContext) { scriptedGateCount: waitGateScripts?.length ?? 0, savedWorkflowId: saved.id, }); - const runId = buildContext?.runId ?? context.runId; const workflowName = json.name || 'workflow'; const summary = `${operation === 'update' ? 'Updated' : 'Created'} ${isSupportingWorkflow ? 'supporting ' : ''}workflow "${workflowName}" (${saved.id}).`; binding = await saveWorkflowSourceFileBinding(context, { @@ -1565,6 +1579,7 @@ export function createBuildWorkflowTool(context: InstanceAiContext) { ...(saved.checksum ? { workflowChecksum: saved.checksum } : {}), sourceHash, setupPending: undefined, + setupScope: { workItemId: scopeWorkItemId, runId, nodeNames: changedNodeNames }, ...(setupPreferences ? { setupPreferences: { diff --git a/packages/@n8n/instance-ai/src/tools/workflows/classify-node-destructiveness.service.ts b/packages/@n8n/instance-ai/src/tools/workflows/classify-node-destructiveness.service.ts index 6b1181c6c01..6a2bdaeecfd 100644 --- a/packages/@n8n/instance-ai/src/tools/workflows/classify-node-destructiveness.service.ts +++ b/packages/@n8n/instance-ai/src/tools/workflows/classify-node-destructiveness.service.ts @@ -22,6 +22,7 @@ import { z } from 'zod'; import { isTriggerNodeType } from './workflow-json-utils'; import { AGENT_TOOL_NODE_TYPE, createVerificationGraph } from './verification-graph'; +import type { Logger } from '../../logger'; import type { ModelConfig } from '../../types'; import { HAIKU_MODEL } from '../../utils/eval-agents'; import { generateValidatedJson } from '../../utils/generate-validated-json'; @@ -37,6 +38,7 @@ export interface ClassifyNodesForSimulationInput { nodeNames?: ReadonlySet; /** Host-resolved model used when no eval model API key is configured in the environment. */ fallbackModelConfig?: ModelConfig; + logger?: Logger; } const STICKY_NOTE_TYPE = 'n8n-nodes-base.stickyNote'; @@ -350,6 +352,7 @@ function formatNodeBlock(node: WorkflowNode & { name: string }): string { async function classifyAmbiguousNodes( nodes: Array, fallbackModelConfig?: ModelConfig, + logger?: Logger, ): Promise { const userText = [ 'Classify the following n8n workflow nodes.', @@ -366,6 +369,11 @@ async function classifyAmbiguousNodes( schema: LlmVerdictSchema, fallbackModelConfig, }); + if (!result.ok) { + logger?.warn( + `Node destructiveness classification failed (${result.message ?? result.reason}); ${nodes.length} ambiguous node(s) are simulated`, + ); + } const parsed = result.ok ? result.data : undefined; return nodes.map((node) => { @@ -424,7 +432,11 @@ export async function classifyNodesForSimulation( // retired, the plan is the only source of verification pin data, so a // throw here would leave every node executing for real. Fail destructive. try { - for (const verdict of await classifyAmbiguousNodes(ambiguous, input.fallbackModelConfig)) { + for (const verdict of await classifyAmbiguousNodes( + ambiguous, + input.fallbackModelConfig, + input.logger, + )) { verdictByName.set(verdict.nodeName, verdict); } } catch { diff --git a/packages/@n8n/instance-ai/src/tools/workflows/generate-simulation-fixtures.service.ts b/packages/@n8n/instance-ai/src/tools/workflows/generate-simulation-fixtures.service.ts index 0ae991d5270..86c60e7e351 100644 --- a/packages/@n8n/instance-ai/src/tools/workflows/generate-simulation-fixtures.service.ts +++ b/packages/@n8n/instance-ai/src/tools/workflows/generate-simulation-fixtures.service.ts @@ -84,7 +84,7 @@ Dates and timestamps MUST be derived from the "## Date anchors" block at the end Special node types: - Trigger nodes (marked as the workflow's simulated event source): emit the EVENT PAYLOAD the trigger delivers into the workflow — the received email/message/record object itself — never an API response envelope, acknowledgement, or request metadata. - Form nodes (a mid-workflow form page): emit the submitted field values — one key per field defined in the node's formFields, with plausible values, plus "submittedAt". -- Pass-through nodes (a timer Wait, Text Classifier, Sentiment Analysis): their real output IS their input. Emit data matching what the listed upstream nodes would produce, so downstream expressions keep resolving — a timer Wait and Text Classifier pass it through unchanged; Sentiment Analysis passes it through and adds a "sentimentAnalysis" object. +- Pass-through nodes (a timer Wait, Text Classifier, Sentiment Analysis): their real output IS their input. Emit data matching what the listed upstream nodes would produce, so downstream expressions keep resolving — a timer Wait passes it through unchanged; Text Classifier does too, unless its parameters turn on includeConfidenceScores, when it also adds a "classification" object; Sentiment Analysis passes it through and adds a "sentimentAnalysis" object. - A Wait set to resume on a webhook call or a form submission does NOT pass its input through: emit what resumes it — the received request body, or one key per field in the node's own formFields plus "submittedAt". Output: a single JSON object whose keys are node names and whose values are arrays of n8n pin-data items in the form { "json": { ... } }. One item per node is enough. @@ -165,14 +165,14 @@ function buildUpstreamContext( */ const PASS_THROUGH_AI_ROOTS = new Map([ // Value = the keys the node adds ON TOP of its input. Empty means a pure - // pass-through, whose output is the input and nothing else. Both roots can - // be flipped to `simulate` by a credentialless language-model sub-node - // (see withSimulatedCredentiallessAiRootVerdicts). - ['@n8n/n8n-nodes-langchain.textClassifier', []], + // pass-through, whose output is the input and nothing else. This root, and + // the classifier below, can be flipped to `simulate` by a credentialless + // language-model sub-node (see withSimulatedCredentiallessAiRootVerdicts). ['@n8n/n8n-nodes-langchain.sentimentAnalysis', ['sentimentAnalysis']], ]); const WAIT_NODE_TYPE = 'n8n-nodes-base.wait'; +const TEXT_CLASSIFIER_NODE_TYPE = '@n8n/n8n-nodes-langchain.textClassifier'; /** * The keys a pass-through node adds on top of its input, or `undefined` when @@ -185,8 +185,14 @@ const WAIT_NODE_TYPE = 'n8n-nodes-base.wait'; * throw away the only output they really have. */ function passThroughAddedKeys(node: NamedNode): readonly string[] | undefined { - if (node.type !== WAIT_NODE_TYPE) return PASS_THROUGH_AI_ROOTS.get(node.type); const params = isRecord(node.parameters) ? node.parameters : {}; + + if (node.type === TEXT_CLASSIFIER_NODE_TYPE) { + const options = isRecord(params.options) ? params.options : {}; + return options.includeConfidenceScores === true ? ['classification'] : []; + } + + if (node.type !== WAIT_NODE_TYPE) return PASS_THROUGH_AI_ROOTS.get(node.type); const resume = typeof params.resume === 'string' ? params.resume : 'timeInterval'; return resume === 'timeInterval' || resume === 'specificTime' ? [] : undefined; } @@ -448,7 +454,7 @@ export async function generateSimulationFixtures( }); if (!result.ok) { input.logger?.warn( - 'Simulation fixture generation failed; simulated nodes get schema-shaped placeholders', + `Simulation fixture generation failed (${result.message ?? result.reason}); simulated nodes get schema-shaped placeholders`, { reason: result.reason, nodeCount: nodeNames.length }, ); return placeholderFixtures(nodeNames, schemaContextByName, now); diff --git a/packages/@n8n/instance-ai/src/tools/workflows/plan-verification-simulation.ts b/packages/@n8n/instance-ai/src/tools/workflows/plan-verification-simulation.ts index cbe2ee8e1c9..102f28a26f9 100644 --- a/packages/@n8n/instance-ai/src/tools/workflows/plan-verification-simulation.ts +++ b/packages/@n8n/instance-ai/src/tools/workflows/plan-verification-simulation.ts @@ -356,6 +356,7 @@ export async function planVerificationSimulation({ workflow, mockedNodeNames, fallbackModelConfig, + logger, }); nodeSimulationPlan = withDeclaredOutputVerdicts(nodeSimulationPlan, declaredFixtures); nodeSimulationPlan = withSimulatedTriggerVerdicts(nodeSimulationPlan, workflow); diff --git a/packages/@n8n/instance-ai/src/tools/workflows/workflow-file-bindings.ts b/packages/@n8n/instance-ai/src/tools/workflows/workflow-file-bindings.ts index 426a309c173..23eae56a2f6 100644 --- a/packages/@n8n/instance-ai/src/tools/workflows/workflow-file-bindings.ts +++ b/packages/@n8n/instance-ai/src/tools/workflows/workflow-file-bindings.ts @@ -18,6 +18,14 @@ const workflowSourceFileBindingSchema = z.object({ /** False when the source was read while parameter values were hidden. */ parameterValuesIncluded: z.boolean().optional(), setupPending: z.boolean().optional(), + /** Setup scope of the builds so far in this work item or run. `nodeNames` undefined = every node. */ + setupScope: z + .object({ + workItemId: z.string().optional(), + runId: z.string().optional(), + nodeNames: z.array(z.string()).optional(), + }) + .optional(), setupPreferences: z .object({ runId: z.string().optional(), diff --git a/packages/@n8n/instance-ai/src/tools/workflows/workflow-node-diff.ts b/packages/@n8n/instance-ai/src/tools/workflows/workflow-node-diff.ts index 64179711c53..6ab3e7518d6 100644 --- a/packages/@n8n/instance-ai/src/tools/workflows/workflow-node-diff.ts +++ b/packages/@n8n/instance-ai/src/tools/workflows/workflow-node-diff.ts @@ -7,10 +7,10 @@ * validation and setup routing never punish a node for merely being present. * * Nodes are paired by id, which get-as-code preserves across the edit round-trip, - * with a name fallback for nodes without a saved id counterpart. Connection changes count - * as node changes: a node wired differently (e.g. a previously disconnected - * node pulled into the flow) is no longer the node the user left there, even - * when its parameters are byte-identical. + * with a name fallback for nodes without a saved id counterpart. A previously + * disconnected node pulled into the flow counts as changed, even when its + * parameters are byte-identical: it never ran before. Re-wiring a node that was + * already connected (a step added before or after it) does not. */ import { isRecord } from '@n8n/utils/is-record'; @@ -99,6 +99,18 @@ function connectionsUnchanged( ); } +function wiredIntoFlow( + node: NodeJSON, + saved: NodeJSON, + builtSignatures: SignatureLookup, + savedSignatures: SignatureLookup, +): boolean { + return ( + (savedSignatures.get(nodeKey(saved)) ?? []).length === 0 && + (builtSignatures.get(nodeKey(node)) ?? []).length > 0 + ); +} + function parametersUnchanged(node: NodeJSON, saved: NodeJSON): boolean { return ( node.type === saved.type && @@ -118,8 +130,9 @@ function nodeUnchanged(node: NodeJSON, saved: NodeJSON): boolean { /** * Names of nodes this build added or modified relative to the saved workflow - * (type, typeVersion, parameters, credentials, disabled state, name, or the - * node's connections differ). Unnamed nodes are always treated as changed. + * (type, typeVersion, parameters, credentials, disabled state, or name differ, + * or a disconnected node got wired into the flow). Unnamed nodes are always + * treated as changed. */ export function computeChangedNodeNames( workflow: WorkflowJSON, @@ -135,7 +148,7 @@ export function computeChangedNodeNames( if ( !saved || !nodeUnchanged(node, saved) || - !connectionsUnchanged(node, saved, builtSignatures, savedSignatures) + wiredIntoFlow(node, saved, builtSignatures, savedSignatures) ) { changed.push(node.name); } diff --git a/packages/@n8n/instance-ai/src/utils/__tests__/agent-feature-enabled.test.ts b/packages/@n8n/instance-ai/src/utils/__tests__/agent-feature-enabled.test.ts deleted file mode 100644 index cd35f5747f6..00000000000 --- a/packages/@n8n/instance-ai/src/utils/__tests__/agent-feature-enabled.test.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { isAgentFeatureEnabled } from '../agent-feature-enabled'; - -const ORIGINAL_ENABLED_MODULES = process.env.N8N_ENABLED_MODULES; - -describe('isAgentFeatureEnabled', () => { - afterEach(() => { - if (ORIGINAL_ENABLED_MODULES === undefined) { - delete process.env.N8N_ENABLED_MODULES; - } else { - process.env.N8N_ENABLED_MODULES = ORIGINAL_ENABLED_MODULES; - } - }); - - it('returns false when N8N_ENABLED_MODULES is unset', () => { - delete process.env.N8N_ENABLED_MODULES; - - expect(isAgentFeatureEnabled()).toBe(false); - }); - - it('returns false when only other modules are enabled', () => { - process.env.N8N_ENABLED_MODULES = 'instance-ai'; - - expect(isAgentFeatureEnabled()).toBe(false); - }); - - it('returns true when agents is enabled', () => { - process.env.N8N_ENABLED_MODULES = 'instance-ai,agents'; - - expect(isAgentFeatureEnabled()).toBe(true); - }); - - it('ignores whitespace around enabled module names', () => { - process.env.N8N_ENABLED_MODULES = ' instance-ai, agents '; - - expect(isAgentFeatureEnabled()).toBe(true); - }); -}); diff --git a/packages/@n8n/instance-ai/src/utils/__tests__/eval-agents.test.ts b/packages/@n8n/instance-ai/src/utils/__tests__/eval-agents.test.ts index 0f8f1747f2c..5ba622338f2 100644 --- a/packages/@n8n/instance-ai/src/utils/__tests__/eval-agents.test.ts +++ b/packages/@n8n/instance-ai/src/utils/__tests__/eval-agents.test.ts @@ -20,7 +20,19 @@ vi.mock('@n8n/agents', () => ({ Tool: vi.fn(), })); -import { createEvalAgent, resolveEvalModelConfig } from '../eval-agents'; +import type { GenerateResult } from '@n8n/agents'; +import { mkdtempSync, readFileSync, rmSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import path from 'node:path'; + +import { + JUDGE_MODEL, + createEvalAgent, + extractText, + isRetryableEvalError, + resolveEvalModelConfig, + resolveJudgeModel, +} from '../eval-agents'; const ORIGINAL_ENV = { ...process.env }; const MODEL_ENV_KEYS = [ @@ -34,6 +46,10 @@ const MODEL_ENV_KEYS = [ 'OPENAI_API_KEY', 'GOOGLE_GENERATIVE_AI_API_KEY', 'XAI_API_KEY', + 'N8N_INSTANCE_AI_EVAL_EFFORT', + 'N8N_INSTANCE_AI_EVAL_JUDGE_MODEL', + 'N8N_INSTANCE_AI_EVAL_JUDGE_EFFORT', + 'N8N_INSTANCE_AI_EVAL_USAGE_LOG', ]; function resetModelEnv(): void { @@ -213,3 +229,170 @@ describe('eval agent model config', () => { }); }); }); + +describe('extractText', () => { + const failed = (error: unknown) => + ({ messages: [], finishReason: 'error', error }) as unknown as GenerateResult; + + it('joins the assistant text parts', () => { + const result = { + messages: [ + { role: 'user', content: [{ type: 'text', text: 'ignored' }] }, + { + role: 'assistant', + content: [ + { type: 'text', text: '{"a":' }, + { type: 'text', text: '1}' }, + ], + }, + ], + finishReason: 'stop', + } as unknown as GenerateResult; + expect(extractText(result)).toBe('{"a":1}'); + }); + + it('throws the model error with its status instead of returning empty text', () => { + const apiError = Object.assign(new Error('invalid x-api-key'), { + statusCode: 401, + isRetryable: false, + }); + expect(() => extractText(failed(apiError))).toThrow( + 'Eval model provider call failed (HTTP 401): invalid x-api-key', + ); + }); + + it('reads the status from the last error when the SDK retries ran out', () => { + const lastError = Object.assign(new Error('Service Unavailable'), { + statusCode: 503, + isRetryable: true, + }); + const retryError = Object.assign( + new Error('Failed after 3 attempts. Last error: Service Unavailable'), + { lastError }, + ); + expect(() => extractText(failed(retryError))).toThrow( + 'Eval model provider call failed (HTTP 503): Failed after 3 attempts. Last error: Service Unavailable', + ); + }); + + it('throws a failure that is not a provider error as it is', () => { + const runtimeError = new Error('memory store unavailable'); + expect(() => extractText(failed(runtimeError))).toThrow(runtimeError); + expect(() => extractText(failed('socket closed'))).toThrow(/^socket closed$/); + }); + + it('marks a failure the provider will not recover from as not retryable', () => { + const call = (error: unknown) => { + try { + extractText(failed(error)); + } catch (thrown) { + return thrown; + } + throw new Error('expected a throw'); + }; + expect(isRetryableEvalError(call({ statusCode: 401, isRetryable: false }))).toBe(false); + expect(isRetryableEvalError(call({ statusCode: 529, isRetryable: true }))).toBe(true); + expect(isRetryableEvalError(call(new Error('fetch failed')))).toBe(true); + expect(isRetryableEvalError(new Error('unusable shape'))).toBe(true); + }); +}); + +describe('eval agent judge and effort settings', () => { + const lastAgent = () => mockAgentInstances[mockAgentInstances.length - 1]; + const modelId = () => (lastAgent().model.mock.calls[0][0] as { id: string }).id; + const effort = () => (lastAgent().thinking.mock.calls[0][1] as { effort: string }).effort; + + beforeEach(() => { + resetModelEnv(); + process.env.ANTHROPIC_API_KEY = 'provider-key'; + mockAgentInstances.length = 0; + vi.clearAllMocks(); + }); + + afterAll(() => { + process.env = ORIGINAL_ENV; + }); + + it('runs judges on the judge model at high effort by default', () => { + createEvalAgent('judge', { instructions: 'x', judge: true }); + + expect(modelId()).toBe(JUDGE_MODEL); + expect(effort()).toBe('high'); + expect(resolveJudgeModel()).toBe(JUDGE_MODEL); + }); + + it('applies the judge model override to judges only', () => { + process.env.N8N_INSTANCE_AI_EVAL_JUDGE_MODEL = 'anthropic/claude-sonnet-5'; + + createEvalAgent('judge', { + instructions: 'x', + judge: true, + model: 'anthropic/claude-sonnet-4-6', + }); + expect(modelId()).toBe('anthropic/claude-sonnet-5'); + + createEvalAgent('proxy', { instructions: 'x' }); + expect(modelId()).toBe('anthropic/claude-sonnet-4-6'); + }); + + it('routes the eval effort to agents without a pinned model only', () => { + process.env.N8N_INSTANCE_AI_EVAL_EFFORT = 'low'; + process.env.N8N_INSTANCE_AI_EVAL_JUDGE_EFFORT = 'medium'; + + createEvalAgent('mock', { instructions: 'x' }); + expect(effort()).toBe('low'); + + createEvalAgent('helper', { instructions: 'x', model: 'anthropic/claude-sonnet-4-6' }); + expect(effort()).toBe('medium'); + + createEvalAgent('judge', { instructions: 'x', judge: true }); + expect(effort()).toBe('medium'); + }); + + it('rejects an unknown effort value', () => { + process.env.N8N_INSTANCE_AI_EVAL_JUDGE_EFFORT = 'hgih'; + + expect(() => createEvalAgent('judge', { instructions: 'x', judge: true })).toThrow( + 'N8N_INSTANCE_AI_EVAL_JUDGE_EFFORT', + ); + }); + + it('appends one usage line per model step when the usage log is set', async () => { + const dir = mkdtempSync(path.join(tmpdir(), 'eval-usage-')); + const file = path.join(dir, 'usage.jsonl'); + try { + process.env.N8N_INSTANCE_AI_EVAL_USAGE_LOG = file; + + createEvalAgent('judge', { instructions: 'x', judge: true }); + const hooks = lastAgent().configuration.mock.calls[0][0]; + hooks.onStepStart({ callId: 'c1', stepNumber: 0 }); + await hooks.onStepEnd({ + callId: 'c1', + stepNumber: 0, + model: { modelId: 'claude-sonnet-5-5' }, + rawFinishReason: 'end_turn', + usage: { + inputTokens: 100, + inputTokenDetails: { cacheReadTokens: 40, cacheWriteTokens: 10 }, + outputTokens: 20, + outputTokenDetails: { reasoningTokens: 5 }, + }, + }); + + const line = JSON.parse(readFileSync(file, 'utf8').trim()); + expect(line).toMatchObject({ + agent: 'judge', + model: 'claude-sonnet-5-5', + effort: 'high', + stopReason: 'end_turn', + inputTokens: 100, + cacheReadTokens: 40, + cacheWriteTokens: 10, + outputTokens: 20, + reasoningTokens: 5, + }); + } finally { + rmSync(dir, { recursive: true, force: true }); + } + }); +}); diff --git a/packages/@n8n/instance-ai/src/utils/__tests__/eval-usage.test.ts b/packages/@n8n/instance-ai/src/utils/__tests__/eval-usage.test.ts index 470d5a43f67..fac7efe6073 100644 --- a/packages/@n8n/instance-ai/src/utils/__tests__/eval-usage.test.ts +++ b/packages/@n8n/instance-ai/src/utils/__tests__/eval-usage.test.ts @@ -1,5 +1,8 @@ import type { InstanceAiEvalLlmUsage } from '@n8n/api-types'; import { convertArrayToReadableStream, MockLanguageModelV3 } from 'ai/test'; +import { existsSync, mkdtempSync, readFileSync, rmSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import path from 'node:path'; import { createEvalAgent } from '../eval-agents'; import { EvalUsageMeter, recordEvalUsage } from '../eval-usage'; @@ -106,6 +109,26 @@ describe('eval usage meter', () => { expect(second.entries().map((entry) => entry.calls)).toEqual([2]); }); + it('counts a call and writes its usage log line when the usage log is on', async () => { + const dir = mkdtempSync(path.join(tmpdir(), 'eval-usage-')); + const file = path.join(dir, 'usage.jsonl'); + try { + process.env.N8N_INSTANCE_AI_EVAL_USAGE_LOG = file; + const judge = judgeOn( + modelReporting({ noCache: 10, cacheRead: 0, cacheWrite: 0, output: 1 }), + ); + const meter = new EvalUsageMeter(); + + await meter.run(async () => await judge.generate('Case one')); + + expect(meter.entries().map((entry) => entry.calls)).toEqual([1]); + const lines = existsSync(file) ? readFileSync(file, 'utf8').trim().split('\n') : []; + expect(lines).toHaveLength(1); + } finally { + rmSync(dir, { recursive: true, force: true }); + } + }); + it('adds usage that an eval endpoint reported to the current meter', async () => { const reported: InstanceAiEvalLlmUsage = { agent: 'eval-mock-responder', diff --git a/packages/@n8n/instance-ai/src/utils/__tests__/generate-validated-json.test.ts b/packages/@n8n/instance-ai/src/utils/__tests__/generate-validated-json.test.ts index a3125e7ef56..20feeb2b95c 100644 --- a/packages/@n8n/instance-ai/src/utils/__tests__/generate-validated-json.test.ts +++ b/packages/@n8n/instance-ai/src/utils/__tests__/generate-validated-json.test.ts @@ -70,14 +70,30 @@ describe('generateValidatedJson', () => { mockCreateEvalAgent.mockReturnValue({ generate: generateMock } as unknown as ReturnType< typeof createEvalAgent >); - expect(await generate()).toEqual({ ok: false, reason: 'generation_failed' }); + expect(await generate()).toEqual({ ok: false, reason: 'generation_failed', message: 'boom' }); + }); + + it('reports generation_failed with the model error when the call returned an error', async () => { + setupAgentMock(''); + mockExtractText.mockImplementation(() => { + throw new Error('Eval model provider call failed (HTTP 401): invalid x-api-key'); + }); + expect(await generate()).toEqual({ + ok: false, + reason: 'generation_failed', + message: 'Eval model provider call failed (HTTP 401): invalid x-api-key', + }); }); it('reports generation_failed when agent creation throws', async () => { mockCreateEvalAgent.mockImplementation(() => { throw new Error('no api key'); }); - expect(await generate()).toEqual({ ok: false, reason: 'generation_failed' }); + expect(await generate()).toEqual({ + ok: false, + reason: 'generation_failed', + message: 'no api key', + }); }); it('forwards the fallback model config to agent creation', async () => { diff --git a/packages/@n8n/instance-ai/src/utils/agent-feature-enabled.ts b/packages/@n8n/instance-ai/src/utils/agent-feature-enabled.ts deleted file mode 100644 index 20d94c71a90..00000000000 --- a/packages/@n8n/instance-ai/src/utils/agent-feature-enabled.ts +++ /dev/null @@ -1,12 +0,0 @@ -const AGENTS_MODULE_NAME = 'agents'; - -export function isAgentFeatureEnabled(): boolean { - const enabledModules = new Set( - (process.env.N8N_ENABLED_MODULES ?? '') - .split(',') - .map((moduleName) => moduleName.trim()) - .filter((moduleName) => moduleName.length > 0), - ); - - return enabledModules.has(AGENTS_MODULE_NAME); -} diff --git a/packages/@n8n/instance-ai/src/utils/eval-agents.ts b/packages/@n8n/instance-ai/src/utils/eval-agents.ts index fca381b840b..45b8ddb907e 100644 --- a/packages/@n8n/instance-ai/src/utils/eval-agents.ts +++ b/packages/@n8n/instance-ai/src/utils/eval-agents.ts @@ -1,7 +1,16 @@ /** Shared agent factory + helpers for eval LLM calls (hint generation, mock responses, pin data). */ -import { Agent, Tool, type GenerateResult, type ModelConfig } from '@n8n/agents'; +import { + Agent, + Tool, + type AnthropicThinkingEffort, + type ExecutionOptions, + type GenerateResult, + type ModelConfig, +} from '@n8n/agents'; import { getProviderPrefix, splitModelId } from '@n8n/ai-utilities/agent-config'; +import { isRecord } from '@n8n/utils/is-record'; +import { appendFile } from 'node:fs/promises'; import { evalUsageGuardrail } from './eval-usage'; import { parseModelHeadersJson } from './parse-model-headers'; @@ -15,6 +24,8 @@ export { Tool }; export const SONNET_MODEL = 'anthropic/claude-sonnet-4-6'; export const HAIKU_MODEL = 'anthropic/claude-haiku-4-5-20251001'; +export const JUDGE_MODEL = 'anthropic/claude-sonnet-5-5'; +const JUDGE_EFFORT: AnthropicThinkingEffort = 'high'; // --------------------------------------------------------------------------- // Model config resolution @@ -121,6 +132,37 @@ export function resolveEvalModelConfig(model?: string): EvalModelConfig { }; } +/** Judge-only model, so a judge A/B leaves the user proxy and the mocks on their own model. */ +function judgeModelOverride(): string | undefined { + const model = process.env.N8N_INSTANCE_AI_EVAL_JUDGE_MODEL?.trim(); + if (!model) return undefined; + return model; +} + +export function resolveJudgeModel(): string { + return judgeModelOverride() ?? JUDGE_MODEL; +} + +const EFFORTS: readonly AnthropicThinkingEffort[] = ['low', 'medium', 'high', 'xhigh', 'max']; + +function effortFromEnv(name: string): AnthropicThinkingEffort | undefined { + const value = process.env[name]?.trim(); + if (!value) return undefined; + const effort = EFFORTS.find((candidate) => candidate === value); + if (!effort) throw new Error(`${name} must be one of ${EFFORTS.join(', ')}; got "${value}"`); + return effort; +} + +function resolveEvalEffort(options: { + judge?: boolean; + model?: string; +}): AnthropicThinkingEffort | undefined { + if (options.judge) return effortFromEnv('N8N_INSTANCE_AI_EVAL_JUDGE_EFFORT') ?? JUDGE_EFFORT; + // A caller that pins its model (an in-product helper) keeps the standard effort. + if (options.model !== undefined) return undefined; + return effortFromEnv('N8N_INSTANCE_AI_EVAL_EFFORT'); +} + // --------------------------------------------------------------------------- // Agent factory // --------------------------------------------------------------------------- @@ -155,6 +197,45 @@ function resolveAgentModel(model?: string, fallbackModelConfig?: ModelConfig): M } } +/** Step hooks that append one JSON line per model call to `N8N_INSTANCE_AI_EVAL_USAGE_LOG`, to price eval runs. */ +function usageLogHooks( + name: string, + effort: AnthropicThinkingEffort | undefined, +): Pick { + const file = process.env.N8N_INSTANCE_AI_EVAL_USAGE_LOG?.trim(); + if (!file) return {}; + + const startedAt = new Map(); + return { + onStepStart: (step) => { + startedAt.set(`${step.callId}:${step.stepNumber}`, Date.now()); + }, + onStepEnd: async (step) => { + const key = `${step.callId}:${step.stepNumber}`; + const start = startedAt.get(key); + startedAt.delete(key); + const line = JSON.stringify({ + at: new Date().toISOString(), + agent: name, + model: step.model.modelId, + effort: effort ?? 'default', + durationMs: start === undefined ? null : Date.now() - start, + stopReason: step.rawFinishReason ?? step.finishReason, + inputTokens: step.usage.inputTokens, + cacheReadTokens: step.usage.inputTokenDetails.cacheReadTokens, + cacheWriteTokens: step.usage.inputTokenDetails.cacheWriteTokens, + outputTokens: step.usage.outputTokens, + reasoningTokens: step.usage.outputTokenDetails.reasoningTokens, + }); + try { + await appendFile(file, `${line}\n`); + } catch { + // Diagnostics must never fail a run. + } + }, + }; +} + export function createEvalAgent( name: string, options: { @@ -163,9 +244,14 @@ export function createEvalAgent( cache?: boolean; /** Host-resolved model used when no eval model API key is configured in the environment. */ fallbackModelConfig?: ModelConfig; + /** Use `N8N_INSTANCE_AI_EVAL_JUDGE_MODEL` / `_JUDGE_EFFORT` instead of the default eval settings. */ + judge?: boolean; }, ): Agent { - const model = resolveAgentModel(options.model, options.fallbackModelConfig); + const model = resolveAgentModel( + options.judge ? (judgeModelOverride() ?? options.model ?? JUDGE_MODEL) : options.model, + options.fallbackModelConfig, + ); const agent = new Agent(name).model(model); if (options.cache) { @@ -174,9 +260,13 @@ export function createEvalAgent( agent.instructions(options.instructions); } - applyAgentThinking(agent, model); + const effort = resolveEvalEffort(options); + applyAgentThinking(agent, model, effort); // `configuration()` replaces the defaults it was given before: put any other default option in this call. - agent.configuration({ guardrails: { hooks: [evalUsageGuardrail(name)] } }); + agent.configuration({ + ...usageLogHooks(name, effort), + guardrails: { hooks: [evalUsageGuardrail(name)] }, + }); return agent; } @@ -185,7 +275,55 @@ export function createEvalAgent( // Text extraction // --------------------------------------------------------------------------- +/** + * A failed eval model call. `Agent.generate` returns errors on the result + * instead of throwing, so reading such a result as empty text turned a bad key + * or an outage into "the model sent bad output". + * Keep "model provider" and the HTTP status in the message: external eval + * consumers match them to tell a provider outage from a case failure. + */ +class EvalModelCallError extends Error { + constructor(cause: unknown) { + const apiError = providerError(cause); + const status = + isRecord(apiError) && typeof apiError.statusCode === 'number' + ? apiError.statusCode + : undefined; + const detail = cause instanceof Error ? cause.message : String(cause); + super(`Eval model provider call failed${status ? ` (HTTP ${status})` : ''}: ${detail}`, { + cause, + }); + this.name = 'EvalModelCallError'; + } +} + +/** The provider's own error: the SDK wraps it in a retry error once its retries run out. */ +function providerError(error: unknown): unknown { + return isRecord(error) && 'lastError' in error ? error.lastError : error; +} + +/** An AI SDK API call error (directly or as the last retry), not a runtime or setup error. */ +function isProviderError(error: unknown): boolean { + const apiError = providerError(error); + return isRecord(apiError) && typeof apiError.isRetryable === 'boolean'; +} + +/** False only for a model error the provider marked as permanent (bad key, bad request). */ +export function isRetryableEvalError(error: unknown): boolean { + if (!(error instanceof EvalModelCallError)) return true; + const apiError = providerError(error.cause); + return !(isRecord(apiError) && apiError.isRetryable === false); +} + +/** + * Assistant text of an eval call. Throws when the call itself failed. Only a + * provider error is reported as one; any other agent failure is thrown as is. + */ export function extractText(result: GenerateResult): string { + if (result.finishReason === 'error') { + if (isProviderError(result.error)) throw new EvalModelCallError(result.error); + throw result.error instanceof Error ? result.error : new Error(String(result.error)); + } const texts: string[] = []; for (const msg of result.messages) { if (!('role' in msg) || msg.role !== 'assistant') continue; diff --git a/packages/@n8n/instance-ai/src/utils/generate-validated-json.ts b/packages/@n8n/instance-ai/src/utils/generate-validated-json.ts index 0bff5efb1da..ac9a74fccb2 100644 --- a/packages/@n8n/instance-ai/src/utils/generate-validated-json.ts +++ b/packages/@n8n/instance-ai/src/utils/generate-validated-json.ts @@ -19,6 +19,8 @@ export type ValidatedJsonResult = | { ok: false; reason: 'generation_failed' | 'invalid_json' | 'schema_mismatch'; + /** The model or agent error, for `generation_failed`. */ + message?: string; issues?: z.ZodIssue[]; }; @@ -46,8 +48,9 @@ export async function generateValidatedJson( { role: 'user' as const, content: [{ type: 'text' as const, text: options.userText }] }, ]); text = extractText(result); - } catch { - return { ok: false, reason: 'generation_failed' }; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return { ok: false, reason: 'generation_failed', message }; } let parsed: unknown; diff --git a/packages/@n8n/instance-ai/src/workflow-loop/workflow-loop-state.ts b/packages/@n8n/instance-ai/src/workflow-loop/workflow-loop-state.ts index aad59edef81..71e88a55637 100644 --- a/packages/@n8n/instance-ai/src/workflow-loop/workflow-loop-state.ts +++ b/packages/@n8n/instance-ai/src/workflow-loop/workflow-loop-state.ts @@ -430,11 +430,12 @@ export const workflowBuildOutcomeSchema = z.object({ /** Whether any node parameters contain unresolved placeholder values. */ hasUnresolvedPlaceholders: z.boolean().optional(), /** - * Nodes this build added or modified relative to the previously saved - * workflow. Setup routing and `workflows(action="setup")` requests are - * scoped to these nodes so editing one node never routes pre-existing, - * unrelated nodes into setup. Absent when the build created the workflow - * or the prior state was unreadable — every node is then in scope. + * Nodes that this build and earlier builds of the same work item or run added + * or modified, each relative to the workflow saved before it. Setup routing and + * `workflows(action="setup")` requests are scoped to these nodes so editing one + * node never routes pre-existing, unrelated nodes into setup. Absent when one of + * those builds created the workflow or the prior state was unreadable — every + * node is then in scope. */ changedNodeNames: z.array(z.string()).optional(), /** diff --git a/packages/@n8n/instance-ai/src/workspace/__tests__/prebaked-workspace-bundle.test.ts b/packages/@n8n/instance-ai/src/workspace/__tests__/prebaked-workspace-bundle.test.ts index 2613c3af0b6..ffee1101d83 100644 --- a/packages/@n8n/instance-ai/src/workspace/__tests__/prebaked-workspace-bundle.test.ts +++ b/packages/@n8n/instance-ai/src/workspace/__tests__/prebaked-workspace-bundle.test.ts @@ -1,6 +1,7 @@ import { loadPrebakedWorkspaceBundle, materializeWorkspaceBundle, + type VerifiedWorkspaceBundles, } from '../prebaked-workspace-bundle'; import type { SandboxWorkspace } from '../sandbox-fs'; import { stringifyWorkspaceJson } from '../workspace-file-content'; @@ -9,38 +10,35 @@ const ROOT = '/home/daytona/workspace'; const mockLogger = { info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn() } as never; -function createSandboxWorkspace(files: Map): { - workspace: SandboxWorkspace; - writes: Map; -} { +function createSandboxWorkspace(files: Map) { const writes = new Map(); + const writeFile = vi.fn(async (path: string, content: string | Buffer) => { + writes.set(path, Buffer.isBuffer(content) ? content.toString('utf-8') : content); + await Promise.resolve(); + }); + const executeCommand = vi.fn(async (command: string) => { + const readMatch = /^cat '([^']+)' 2>\/dev\/null$/.exec(command); + if (readMatch) { + const content = files.get(readMatch[1]); + return await Promise.resolve( + content === undefined + ? { exitCode: 1, stdout: '', stderr: 'missing' } + : { exitCode: 0, stdout: content, stderr: '' }, + ); + } + + return await Promise.resolve({ exitCode: 0, stdout: '', stderr: '' }); + }); const workspace: SandboxWorkspace = { filesystem: { provider: 'local', - writeFile: vi.fn(async (path: string, content: string | Buffer) => { - writes.set(path, Buffer.isBuffer(content) ? content.toString('utf-8') : content); - await Promise.resolve(); - }), + writeFile, mkdir: vi.fn(async () => await Promise.resolve()), }, - sandbox: { - executeCommand: vi.fn(async (command: string) => { - const readMatch = /^cat '([^']+)' 2>\/dev\/null$/.exec(command); - if (readMatch) { - const content = files.get(readMatch[1]); - return await Promise.resolve( - content === undefined - ? { exitCode: 1, stdout: '', stderr: 'missing' } - : { exitCode: 0, stdout: content, stderr: '' }, - ); - } - - return await Promise.resolve({ exitCode: 0, stdout: '', stderr: '' }); - }), - }, + sandbox: { executeCommand }, }; - return { workspace, writes }; + return { workspace, writes, writeFile, executeCommand }; } describe('loadPrebakedWorkspaceBundle', () => { @@ -106,8 +104,8 @@ describe('loadPrebakedWorkspaceBundle', () => { expect(result).toBeUndefined(); }); - it('returns undefined when the manifest hash matches but a payload file is missing', async () => { - const { workspace } = createSandboxWorkspace( + it('trusts a matching manifest without a read of each payload file', async () => { + const { workspace, executeCommand } = createSandboxWorkspace( new Map([ [ manifestPath, @@ -132,7 +130,8 @@ describe('loadPrebakedWorkspaceBundle', () => { buildBundle: () => bundle, }); - expect(result).toBeUndefined(); + expect(result).toBe(bundle); + expect(executeCommand).toHaveBeenCalledTimes(1); }); }); @@ -158,6 +157,7 @@ describe('materializeWorkspaceBundle', () => { resourceLabel: 'Test bundle file', loadPrebaked: async () => await Promise.resolve(undefined), buildBundle: () => bundle, + bundleHash: (built) => built.contentHash, materializedLogMessage: 'materialized', materializedLogContext: () => ({ root: ROOT }), }); @@ -187,6 +187,7 @@ describe('materializeWorkspaceBundle', () => { resourceLabel: 'Test bundle file', loadPrebaked: async () => await Promise.resolve(undefined), buildBundle: () => bundle, + bundleHash: (built) => built.contentHash, materializedLogMessage: 'materialized', materializedLogContext: () => ({ root: ROOT }), }); @@ -223,6 +224,7 @@ describe('materializeWorkspaceBundle', () => { buildBundle: () => bundle, }), buildBundle: () => bundle, + bundleHash: (built) => built.contentHash, materializedLogMessage: 'materialized', materializedLogContext: () => ({ root: ROOT }), }); @@ -231,3 +233,131 @@ describe('materializeWorkspaceBundle', () => { expect(writes.size).toBe(0); }); }); + +describe('prebaked bundle checks with verified bundles', () => { + const manifestPath = `${ROOT}/bundle/.manifest.json`; + const filePaths = [`${ROOT}/bundle/a.txt`, `${ROOT}/bundle/b.txt`]; + const manifest = stringifyWorkspaceJson({ schemaVersion: 1, contentHash: 'abc123' }); + const bundle = { + rootDir: `${ROOT}/bundle`, + manifestPath, + files: new Map([ + ...filePaths.map((path): [string, string] => [path, 'content\n']), + [manifestPath, manifest], + ]), + contentHash: 'abc123', + }; + + function readPaths(executeCommand: ReturnType['executeCommand']) { + return executeCommand.mock.calls.flatMap(([command]) => { + const match = /^cat '([^']+)' 2>\/dev\/null$/.exec(command); + return match ? [match[1]] : []; + }); + } + + async function materialize( + workspace: SandboxWorkspace, + verifiedBundles: VerifiedWorkspaceBundles, + ) { + return await materializeWorkspaceBundle({ + logger: mockLogger, + workspace, + verifiedBundles, + resourceLabel: 'Test bundle file', + loadPrebaked: async () => + await loadPrebakedWorkspaceBundle({ + logger: mockLogger, + workspace, + verifiedBundles, + manifestPath, + expectedHash: bundle.contentHash, + hashField: 'contentHash', + schemaVersion: 1, + resourceLabel: 'Test bundle file', + invalidManifestLogMessage: 'invalid', + staleManifestLogMessage: 'stale', + staleManifestLogKeys: { expected: 'expectedHash', actual: 'actualHash' }, + successLogMessage: 'success', + successLogContext: () => ({ root: ROOT }), + buildBundle: () => bundle, + }), + buildBundle: () => bundle, + bundleHash: (built) => built.contentHash, + materializedLogMessage: 'materialized', + materializedLogContext: () => ({ root: ROOT }), + }); + } + + it('reads only the manifest when the manifest hash matches', async () => { + const { workspace, writes, executeCommand } = createSandboxWorkspace(new Map(bundle.files)); + const verifiedBundles: VerifiedWorkspaceBundles = new Map(); + + await expect(materialize(workspace, verifiedBundles)).resolves.toBe(bundle); + + expect(readPaths(executeCommand)).toEqual([manifestPath]); + expect(writes.size).toBe(0); + expect(verifiedBundles.get(manifestPath)).toBe(bundle.contentHash); + }); + + it('makes no sandbox reads after the bundle is verified for the sandbox', async () => { + const { workspace, executeCommand } = createSandboxWorkspace(new Map(bundle.files)); + const verifiedBundles: VerifiedWorkspaceBundles = new Map(); + await materialize(workspace, verifiedBundles); + executeCommand.mockClear(); + + await expect(materialize(workspace, verifiedBundles)).resolves.toBe(bundle); + + expect(readPaths(executeCommand)).toEqual([]); + }); + + it('checks the sandbox again when the expected hash changes', async () => { + const { workspace, writes, executeCommand } = createSandboxWorkspace(new Map(bundle.files)); + const verifiedBundles: VerifiedWorkspaceBundles = new Map([[manifestPath, 'older-hash']]); + + await materialize(workspace, verifiedBundles); + + expect(readPaths(executeCommand)).toEqual([manifestPath]); + expect(writes.size).toBe(0); + expect(verifiedBundles.get(manifestPath)).toBe(bundle.contentHash); + }); + + it('writes the bundle again when the manifest is stale', async () => { + const { workspace, writes } = createSandboxWorkspace( + new Map([ + ...filePaths.map((path): [string, string] => [path, 'old\n']), + [manifestPath, stringifyWorkspaceJson({ schemaVersion: 1, contentHash: 'stale' })], + ]), + ); + const verifiedBundles: VerifiedWorkspaceBundles = new Map(); + + await materialize(workspace, verifiedBundles); + + expect([...writes.keys()].sort()).toEqual([manifestPath, ...filePaths].sort()); + expect(verifiedBundles.get(manifestPath)).toBe(bundle.contentHash); + }); + + it('writes the bundle again when the manifest is missing', async () => { + const { workspace, writes } = createSandboxWorkspace(new Map()); + const verifiedBundles: VerifiedWorkspaceBundles = new Map(); + + await materialize(workspace, verifiedBundles); + + expect([...writes.keys()].sort()).toEqual([manifestPath, ...filePaths].sort()); + expect(verifiedBundles.get(manifestPath)).toBe(bundle.contentHash); + }); + + it('does not record the bundle when a write fails', async () => { + const { workspace, writeFile, executeCommand } = createSandboxWorkspace(new Map()); + writeFile.mockRejectedValue(new Error('disk full')); + executeCommand.mockResolvedValue({ + exitCode: 1, + stdout: '', + stderr: 'disk full', + }); + const verifiedBundles: VerifiedWorkspaceBundles = new Map(); + + await expect(materialize(workspace, verifiedBundles)).rejects.toThrow(); + + expect(verifiedBundles.size).toBe(0); + }); +}); diff --git a/packages/@n8n/instance-ai/src/workspace/__tests__/sandbox-setup.test.ts b/packages/@n8n/instance-ai/src/workspace/__tests__/sandbox-setup.test.ts index e0ad25e17bf..08eaa19ff09 100644 --- a/packages/@n8n/instance-ai/src/workspace/__tests__/sandbox-setup.test.ts +++ b/packages/@n8n/instance-ai/src/workspace/__tests__/sandbox-setup.test.ts @@ -67,6 +67,7 @@ import { jsonParse } from 'n8n-workflow'; import type { Mock } from 'vitest'; import { makeBuilderTemplatesTarGz } from '../../knowledge-base/__tests__/builder-templates-archive.fixtures'; +import { buildKnowledgeBaseWorkspaceBundle } from '../../knowledge-base/materialize-knowledge-base'; import type { InstanceAiContext, SearchableNodeDescription } from '../../types'; import type { BuilderTemplatesBundle } from '../builder-templates-service'; import type { SandboxWorkspace } from '../sandbox-fs'; @@ -402,6 +403,53 @@ describe('setupSandboxWorkspace', () => { expect(writtenPaths.some((p) => p.includes('/knowledge-base/templates/'))).toBe(true); }); + it('reads only the knowledge base manifest when the prebaked bundle matches', async () => { + const runInSandbox: RunInSandboxMock = + vi.fn< + ( + ...args: [SandboxWorkspace, string, string?] + ) => Promise<{ exitCode: number; stdout: string; stderr: string }> + >(); + runInSandbox.mockResolvedValue({ exitCode: 0, stdout: '', stderr: '' }); + const readFileViaSandbox: ReadFileViaSandboxMock = + vi.fn<(...args: [SandboxWorkspace, string]) => Promise>(); + readFileViaSandbox.mockResolvedValue(null); + const setupSandboxWorkspace = loadSetupSandboxWorkspaceWithFsMocks( + runInSandbox, + readFileViaSandbox, + ); + const context = createSetupContext(); + const knowledgeBase = await buildKnowledgeBaseWorkspaceBundle({ + root: '/sandbox', + logger: context.logger, + }); + const files = new Map(knowledgeBase.files); + files.set('/sandbox/.sandbox-initialized', '2024-01-01T00:00:00.000Z'); + const writeFile = vi.fn< + (...args: [string, string | Buffer, { recursive?: boolean }?]) => Promise + >(async () => await Promise.resolve()); + const readFile = vi.fn(async (path: string) => { + const content = files.get(path); + if (content === undefined) return await Promise.reject(new Error(`ENOENT: ${path}`)); + return await Promise.resolve(content); + }); + const verifiedBundles = new Map(); + + const initialized = await setupSandboxWorkspace( + createLocalWorkspace(writeFile, undefined, readFile), + context, + { verifiedBundles }, + ); + + expect(initialized).toBe(false); + expect(readFile.mock.calls.map(([path]) => path)).toEqual([ + '/sandbox/.sandbox-initialized', + knowledgeBase.manifestPath, + ]); + expect(writeFile).not.toHaveBeenCalled(); + expect(verifiedBundles.get(knowledgeBase.manifestPath)).toBe(knowledgeBase.contentHash); + }); + it('materializes knowledge-base templates on the local provider when a bundle is available', async () => { const runInSandbox: RunInSandboxMock = vi.fn< diff --git a/packages/@n8n/instance-ai/src/workspace/prebaked-workspace-bundle.ts b/packages/@n8n/instance-ai/src/workspace/prebaked-workspace-bundle.ts index 1450918d488..d6173930661 100644 --- a/packages/@n8n/instance-ai/src/workspace/prebaked-workspace-bundle.ts +++ b/packages/@n8n/instance-ai/src/workspace/prebaked-workspace-bundle.ts @@ -8,8 +8,16 @@ import { import { parseVersionedWorkspaceManifest } from './workspace-manifest'; import { traceSandboxOperation, sandboxFileBytes } from '../tracing/sandbox-tracing'; +/** + * Bundle hash by manifest path, for bundles that one sandbox already has. + * Keep it as long as the sandbox, so that repeated checks in that sandbox do + * not read the manifest again. + */ +export type VerifiedWorkspaceBundles = Map; + export interface LoadPrebakedWorkspaceBundleOptions { workspace: WorkspaceFileTarget; + verifiedBundles?: VerifiedWorkspaceBundles; manifestPath: string; expectedHash: string; hashField: string; @@ -27,12 +35,18 @@ export interface LoadPrebakedWorkspaceBundleOptions { buildBundle: () => Promise | TBundle | undefined; } -/** Reuse a workspace bundle when its manifest hash matches the expected value. */ +/** + * Reuse a workspace bundle when its manifest hash matches the expected value. + * A matching manifest is trusted without a read of each bundle file: images + * and snapshots bake the files with the manifest, and a live write puts the + * manifest last. + */ export async function loadPrebakedWorkspaceBundle }>( options: LoadPrebakedWorkspaceBundleOptions, ): Promise { let decision = 'reused'; let actualHash: string | undefined; + const { verifiedBundles } = options; return await traceSandboxOperation( 'check-bundle', { @@ -43,6 +57,14 @@ export async function loadPrebakedWorkspaceBundle { + if (verifiedBundles?.get(options.manifestPath) === options.expectedHash) { + decision = 'cached'; + actualHash = options.expectedHash; + const bundle = await options.buildBundle(); + if (!bundle) decision = 'empty'; + return bundle; + } + const manifestRaw = await readWorkspaceFile(options.workspace, options.manifestPath, { logger: options.logger, resourceLabel: options.resourceLabel, @@ -81,29 +103,7 @@ export async function loadPrebakedWorkspaceBundle path !== options.manifestPath, - ); - const existenceChecks = await Promise.all( - payloadPaths.map(async (path) => ({ - path, - exists: - (await readWorkspaceFile(options.workspace, path, { - logger: options.logger, - resourceLabel: options.resourceLabel, - })) !== null, - })), - ); - const missingPath = existenceChecks.find((check) => !check.exists)?.path; - if (missingPath) { - decision = 'incomplete'; - options.logger.debug('Ignoring incomplete prebaked workspace bundle', { - manifestPath: options.manifestPath, - missingPath, - }); - return undefined; - } - + verifiedBundles?.set(options.manifestPath, options.expectedHash); options.logger.debug(options.successLogMessage, options.successLogContext(bundle)); return bundle; }, @@ -114,10 +114,13 @@ export interface MaterializeWorkspaceBundleOptions< TBundle extends { files: Map; manifestPath: string }, > { workspace: WorkspaceFileTarget; + verifiedBundles?: VerifiedWorkspaceBundles; resourceLabel: string; logger: Logger; loadPrebaked: () => Promise; buildBundle: () => Promise | TBundle; + /** Hash that the bundle manifest records. */ + bundleHash: (bundle: TBundle) => string; materializedLogMessage: string; materializedLogContext: (bundle: TBundle) => Record; } @@ -168,6 +171,7 @@ export async function materializeWorkspaceBundle< }); } + options.verifiedBundles?.set(bundle.manifestPath, options.bundleHash(bundle)); options.logger.debug(options.materializedLogMessage, options.materializedLogContext(bundle)); return bundle; }, diff --git a/packages/@n8n/instance-ai/src/workspace/sandbox-setup.ts b/packages/@n8n/instance-ai/src/workspace/sandbox-setup.ts index 9d37a93b559..734afe9bf25 100644 --- a/packages/@n8n/instance-ai/src/workspace/sandbox-setup.ts +++ b/packages/@n8n/instance-ai/src/workspace/sandbox-setup.ts @@ -39,6 +39,7 @@ import { packSandboxLinkedWorkspacePackages, type WorkspacePackageTarball, } from './pack-workspace-sdk'; +import type { VerifiedWorkspaceBundles } from './prebaked-workspace-bundle'; import { runInSandbox, readFileViaSandbox, @@ -471,11 +472,13 @@ async function materializeKnowledgeBaseStep( workspace: SandboxWorkspace, root: string, context: InstanceAiContext, + verifiedBundles: VerifiedWorkspaceBundles | undefined, ): Promise { await setupStep('materialize-knowledge-base', async () => { const templatesBundle = (await context.templatesService?.getBundle()) ?? null; await materializeKnowledgeBaseIntoWorkspace({ workspace, + verifiedBundles, root, logger: context.logger, templatesArchive: templatesBundle?.archive ?? null, @@ -494,6 +497,7 @@ async function materializeKnowledgeBaseStep( export async function setupSandboxWorkspace( workspace: SandboxWorkspace, context: InstanceAiContext, + options: { verifiedBundles?: VerifiedWorkspaceBundles } = {}, ): Promise { return await traceSandboxOperation( 'initialize-workspace', @@ -511,7 +515,7 @@ export async function setupSandboxWorkspace( async () => await readWorkspaceFile(workspace, markerFile), ); if (marker !== null) { - await materializeKnowledgeBaseStep(workspace, root, context); + await materializeKnowledgeBaseStep(workspace, root, context, options.verifiedBundles); return false; } @@ -538,7 +542,7 @@ export async function setupSandboxWorkspace( 'write-workspace-files', async () => await writeWorkspaceFiles(workspace, root, files), ); - await materializeKnowledgeBaseStep(workspace, root, context); + await materializeKnowledgeBaseStep(workspace, root, context, options.verifiedBundles); // npm install (must run after package.json is in place) await setupStep('install-dependencies', async () => { diff --git a/packages/@n8n/mcp-apps/package.json b/packages/@n8n/mcp-apps/package.json index 8c4a451f09b..9ff714127d9 100644 --- a/packages/@n8n/mcp-apps/package.json +++ b/packages/@n8n/mcp-apps/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/mcp-apps", - "version": "0.20.0", + "version": "0.21.0", "description": "MCP Apps UI resources and server helpers for n8n", "main": "dist/server/index.js", "types": "dist/server/index.d.ts", diff --git a/packages/@n8n/mcp-apps/src/apps/workflow-preview/tokens.scss b/packages/@n8n/mcp-apps/src/apps/workflow-preview/tokens.scss index ed7fe24e352..bed5f36cec3 100644 --- a/packages/@n8n/mcp-apps/src/apps/workflow-preview/tokens.scss +++ b/packages/@n8n/mcp-apps/src/apps/workflow-preview/tokens.scss @@ -1,6 +1,6 @@ @use '@n8n/design-system/css/_primitives' as primitives; @use '@n8n/design-system/css/_tokens' as tokens; -@use '@n8n/design-system/css/fonts/inter'; +@use '@n8n/design-system/css/fonts/geist'; :root { color-scheme: light dark; @@ -22,13 +22,7 @@ body { margin: 0; - font-family: - InterVariable, - -apple-system, - BlinkMacSystemFont, - 'Segoe UI', - Roboto, - sans-serif; + font-family: var(--font-family); -webkit-font-smoothing: antialiased; background: transparent; color: var(--color--text--shade-1); diff --git a/packages/@n8n/mcp-apps/src/components/open-in-n8n-button.vue b/packages/@n8n/mcp-apps/src/components/open-in-n8n-button.vue index 958c4f41cf3..0d472bf7d47 100644 --- a/packages/@n8n/mcp-apps/src/components/open-in-n8n-button.vue +++ b/packages/@n8n/mcp-apps/src/components/open-in-n8n-button.vue @@ -6,11 +6,11 @@ import { useI18n } from '@mcp-apps/i18n'; withDefaults( defineProps<{ label?: string; - variant?: 'solid' | 'subtle'; + variant?: 'solid' | 'outline'; size?: 'small' | 'medium'; }>(), { - variant: 'subtle', + variant: 'outline', size: 'small', }, ); diff --git a/packages/@n8n/mcp-browser-extension/icons/icon-128.png b/packages/@n8n/mcp-browser-extension/icons/icon-128.png index fefebf9d00e..28f333a6b97 100644 Binary files a/packages/@n8n/mcp-browser-extension/icons/icon-128.png and b/packages/@n8n/mcp-browser-extension/icons/icon-128.png differ diff --git a/packages/@n8n/mcp-browser-extension/icons/icon-16.png b/packages/@n8n/mcp-browser-extension/icons/icon-16.png index 09d673ae5d6..08fe2b23b1f 100644 Binary files a/packages/@n8n/mcp-browser-extension/icons/icon-16.png and b/packages/@n8n/mcp-browser-extension/icons/icon-16.png differ diff --git a/packages/@n8n/mcp-browser-extension/icons/icon-32.png b/packages/@n8n/mcp-browser-extension/icons/icon-32.png index 92cd18efacd..3deb97470bb 100644 Binary files a/packages/@n8n/mcp-browser-extension/icons/icon-32.png and b/packages/@n8n/mcp-browser-extension/icons/icon-32.png differ diff --git a/packages/@n8n/mcp-browser-extension/icons/icon-48.png b/packages/@n8n/mcp-browser-extension/icons/icon-48.png index e8d3ddd4a5b..5ac1ee2fda5 100644 Binary files a/packages/@n8n/mcp-browser-extension/icons/icon-48.png and b/packages/@n8n/mcp-browser-extension/icons/icon-48.png differ diff --git a/packages/@n8n/mcp-browser-extension/manifest.json b/packages/@n8n/mcp-browser-extension/manifest.json index d66fc746221..8a9a405bb0c 100644 --- a/packages/@n8n/mcp-browser-extension/manifest.json +++ b/packages/@n8n/mcp-browser-extension/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 3, "name": "n8n Browser Use", "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvRoWEdJjhgP9qs6R1jcemywrw+I91EJZtYur5C97hjjUc5nPao4jSv1qXFksdKuMddb9IEvzBElr5EYsXSaiVqdbRl8Gge0xYV1gGga653T2d9BuXL7NKv/wZxJ2i/coHSjhhIULQUBAVwu0JFMbHY5T8LfqrzBljuY7u1Xa7jmLmx0QrsoKLbGUoOBVZz4ztEGKEQHEelgg+ph2LrcYJczMBZ80PaHQAaWrvbCYF4vnZLd++Svy70ZCt7gr93L8BXHc8j1c3VojQTk+Uvqhm/4nZdYHlEmruQkd0pE+zTyegbcDlw0oc+6sLbsc0CqmJz8zH0OvSTfSVK7h6LNwbQIDAQAB", - "version": "0.0.8", + "version": "0.0.9", "description": "Let n8n AI set up credentials, fill out forms, and automate anything in your browser", "permissions": ["debugger", "activeTab", "tabs", "storage", "webNavigation"], "host_permissions": [""], diff --git a/packages/@n8n/mcp-browser-extension/package.json b/packages/@n8n/mcp-browser-extension/package.json index 38b3988a55c..d4ba6928191 100644 --- a/packages/@n8n/mcp-browser-extension/package.json +++ b/packages/@n8n/mcp-browser-extension/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/mcp-browser-extension", - "version": "0.0.8", + "version": "0.0.9", "private": true, "description": "Chrome extension that lets n8n AI control browser tabs via CDP", "scripts": { diff --git a/packages/@n8n/mcp-browser-extension/src/ui/App.vue b/packages/@n8n/mcp-browser-extension/src/ui/App.vue index 1c0c03d87b5..6c0b7df293e 100644 --- a/packages/@n8n/mcp-browser-extension/src/ui/App.vue +++ b/packages/@n8n/mcp-browser-extension/src/ui/App.vue @@ -149,9 +149,9 @@ const showConnectPrompt = computed(() => hasRelayUrl.value && isRelayAllowed.val height: min(700px, calc(100dvh - 2 * var(--spacing--md))); min-height: 420px; background: var(--background--subtle); - border: var(--border-width) var(--border-style) var(--color--foreground--tint-1); + border: var(--border); border-radius: var(--radius--xl); - box-shadow: var(--shadow--light); + box-shadow: var(--shadow--sm); overflow: hidden; // In a popup window the window itself is the card — no chrome, fill the viewport @@ -177,14 +177,8 @@ const showConnectPrompt = computed(() => hasRelayUrl.value && isRelayAllowed.val } .logo { - display: block; + justify-content: flex-start; margin-bottom: var(--spacing--lg); - - :deep(svg) { - margin-left: 0; - width: auto; - height: 24px; - } } .title { @@ -193,13 +187,13 @@ const showConnectPrompt = computed(() => hasRelayUrl.value && isRelayAllowed.val gap: var(--spacing--xs); font-size: var(--font-size--lg); font-weight: var(--font-weight--medium); - color: var(--color--text--shade-1); + color: var(--text-color); margin: 0 0 var(--spacing--lg); } .status-dot { - width: 12px; - height: 12px; + width: var(--height--4xs); + height: var(--height--4xs); border-radius: 50%; background: var(--color--success); flex-shrink: 0; @@ -213,7 +207,7 @@ const showConnectPrompt = computed(() => hasRelayUrl.value && isRelayAllowed.val .divider { border: none; - border-top: var(--border-width) var(--border-style) var(--color--foreground--tint-1); + border-top: var(--border); margin: 0; } @@ -229,10 +223,10 @@ const showConnectPrompt = computed(() => hasRelayUrl.value && isRelayAllowed.val border-radius: var(--radius); cursor: pointer; font-size: var(--font-size--xs); - color: var(--color--text--shade-1); + color: var(--text-color); &:hover { - background: var(--color--background); + background: var(--background--hover); } } diff --git a/packages/@n8n/mcp-browser-extension/src/ui/components/InfoRow.vue b/packages/@n8n/mcp-browser-extension/src/ui/components/InfoRow.vue index f0c1e95ed95..a18145a4c88 100644 --- a/packages/@n8n/mcp-browser-extension/src/ui/components/InfoRow.vue +++ b/packages/@n8n/mcp-browser-extension/src/ui/components/InfoRow.vue @@ -37,8 +37,8 @@ defineProps<{ width: var(--row-marker-size); height: var(--row-marker-size); border-radius: 50%; - background: var(--color--background); - color: var(--color--text--shade-1); + background: var(--background--subtle); + color: var(--text-color); } .info-content { @@ -50,7 +50,7 @@ defineProps<{ .info-title { font-size: var(--font-size--sm); font-weight: var(--font-weight--medium); - color: var(--color--text--shade-1); + color: var(--text-color); } .info-description { diff --git a/packages/@n8n/mcp-browser-extension/src/ui/components/RememberedHosts.vue b/packages/@n8n/mcp-browser-extension/src/ui/components/RememberedHosts.vue index 4ce72e0fd26..47652ca89ff 100644 --- a/packages/@n8n/mcp-browser-extension/src/ui/components/RememberedHosts.vue +++ b/packages/@n8n/mcp-browser-extension/src/ui/components/RememberedHosts.vue @@ -45,7 +45,7 @@ defineEmits<{ forget: [host: string] }>(); align-items: center; gap: var(--spacing--2xs); padding: var(--spacing--2xs) var(--spacing--xs); - border: var(--border-width) var(--border-style) var(--color--foreground--tint-1); + border: var(--border); border-radius: var(--radius); } @@ -56,7 +56,7 @@ defineEmits<{ forget: [host: string] }>(); text-overflow: ellipsis; white-space: nowrap; font-size: var(--font-size--xs); - color: var(--color--text--shade-1); + color: var(--text-color); } .host-remove { @@ -72,8 +72,8 @@ defineEmits<{ forget: [host: string] }>(); color: var(--text-color--subtler); &:hover { - background: var(--color--background); - color: var(--color--text--shade-1); + background: var(--background--hover); + color: var(--text-color); } } diff --git a/packages/@n8n/mcp-browser-extension/src/ui/components/TabItem.vue b/packages/@n8n/mcp-browser-extension/src/ui/components/TabItem.vue index aefe905c83b..698af0f9250 100644 --- a/packages/@n8n/mcp-browser-extension/src/ui/components/TabItem.vue +++ b/packages/@n8n/mcp-browser-extension/src/ui/components/TabItem.vue @@ -68,7 +68,7 @@ function hideFavicon(event: Event): void { cursor: pointer; &:hover { - background: var(--background--surface--hover); + background: var(--background--hover); } } @@ -79,8 +79,8 @@ function hideFavicon(event: Event): void { } .tab-favicon { - width: 24px; - height: 24px; + width: var(--height--xs); + height: var(--height--xs); border-radius: var(--radius--sm); } diff --git a/packages/@n8n/mcp-browser-extension/src/ui/components/TabList.vue b/packages/@n8n/mcp-browser-extension/src/ui/components/TabList.vue index 47c24d67048..17e55368843 100644 --- a/packages/@n8n/mcp-browser-extension/src/ui/components/TabList.vue +++ b/packages/@n8n/mcp-browser-extension/src/ui/components/TabList.vue @@ -40,7 +40,5 @@ function isSelected(tab: chrome.tabs.Tab): boolean { list-style: none; padding: 0; margin: 0; - overflow-y: auto; - min-height: 60px; } diff --git a/packages/@n8n/mcp-browser-extension/src/ui/tokens.scss b/packages/@n8n/mcp-browser-extension/src/ui/tokens.scss index 3ca56f16386..478c8e7529b 100644 --- a/packages/@n8n/mcp-browser-extension/src/ui/tokens.scss +++ b/packages/@n8n/mcp-browser-extension/src/ui/tokens.scss @@ -1,14 +1,12 @@ @use '@n8n/design-system/css/_primitives' as primitives; @use '@n8n/design-system/css/_tokens' as tokens; -@use '@n8n/design-system/css/fonts/inter'; +@use '@n8n/design-system/css/fonts/geist'; :root { color-scheme: light dark; @include primitives.primitives; @include tokens.theme; - - // Shared icon column, so info rows and tab rows keep one text edge and one icon centre - --row-marker-size: 40px; + --row-marker-size: var(--height--xl); } @media (prefers-color-scheme: dark) { @@ -26,28 +24,21 @@ body { margin: 0; padding: 0; - font-family: - InterVariable, - -apple-system, - BlinkMacSystemFont, - 'Segoe UI', - Roboto, - sans-serif; + font-family: var(--font-family); -webkit-font-smoothing: antialiased; background-color: var(--color--background); - color: var(--color--text--shade-1); + color: var(--text-color); } -// Grouping box shared by the views and the allowed-instances list. +/** Keep the shared card layout for extension panels. */ .panel { display: flex; flex-direction: column; gap: var(--spacing--lg); background: var(--background--surface); - border: var(--border-width) var(--border-style) var(--color--foreground--tint-1); + border: var(--border); border-radius: var(--radius--lg); padding: var(--spacing--lg); - min-height: 0; } .panel + .panel { diff --git a/packages/@n8n/mcp-browser/package.json b/packages/@n8n/mcp-browser/package.json index 51cb9892647..7d4c81e4d77 100644 --- a/packages/@n8n/mcp-browser/package.json +++ b/packages/@n8n/mcp-browser/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/mcp-browser", - "version": "0.23.0", + "version": "0.24.0", "description": "Browser automation MCP tools built on Playwright, WebDriver BiDi, and safaridriver", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/@n8n/node-cli/package.json b/packages/@n8n/node-cli/package.json index f18ef394910..fd8a052686e 100644 --- a/packages/@n8n/node-cli/package.json +++ b/packages/@n8n/node-cli/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/node-cli", - "version": "0.52.0", + "version": "0.53.0", "description": "Official CLI for developing community nodes for n8n", "bin": { "n8n-node": "bin/n8n-node.mjs" diff --git a/packages/@n8n/node-engine-compatibility/package.json b/packages/@n8n/node-engine-compatibility/package.json index b830781858f..4f441872b78 100644 --- a/packages/@n8n/node-engine-compatibility/package.json +++ b/packages/@n8n/node-engine-compatibility/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/node-engine-compatibility", - "version": "0.11.0", + "version": "0.12.0", "description": "Adapts v1 nodes and workflows to the Engine v2 execution model", "scripts": { "clean": "rimraf dist .turbo", diff --git a/packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/runAgent.ts b/packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/runAgent.ts index b4688944ec6..ead0c61e579 100644 --- a/packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/runAgent.ts +++ b/packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/runAgent.ts @@ -36,7 +36,12 @@ export function appendToolAttributions( ): string { // A reply with no text would show as the label alone, which reads as a glitch if (output.trim() === '') return output; - const calledTools = new Set(steps.map((step) => step.action.tool)); + // A denied or failed call produced no partner result, so it earns no label + const calledTools = new Set( + steps + .filter((step) => !step.action.hitlDenied && !step.action.errored) + .map((step) => step.action.tool), + ); const attributions = new Set(); for (const tool of tools) { const attribution = tool.metadata?.attribution; diff --git a/packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/tests/runAgent.test.ts b/packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/tests/runAgent.test.ts index 449a7072026..573192304cc 100644 --- a/packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/tests/runAgent.test.ts +++ b/packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/tests/runAgent.test.ts @@ -591,8 +591,11 @@ describe('appendToolAttributions', () => { const plain = mock(); plain.name = 'Calculator'; plain.metadata = { sourceNodeName: 'Calculator' }; - const step = (tool: string): ToolCallData => ({ - action: { tool, toolInput: {}, log: '', toolCallId: 'c1', type: 'tool_call' }, + const step = ( + tool: string, + flags: Pick = {}, + ): ToolCallData => ({ + action: { tool, toolInput: {}, log: '', toolCallId: 'c1', type: 'tool_call', ...flags }, observation: '', }); @@ -612,6 +615,22 @@ describe('appendToolAttributions', () => { expect(appendToolAttributions(output, [step('Genie_ask')], [genie])).toBe(output); }); + it('does not label a reply for a call the user denied in a Human-in-the-Loop node', () => { + expect( + appendToolAttributions('Not approved', [step('Genie_ask', { hitlDenied: true })], [genie]), + ).toBe('Not approved'); + }); + + it('does not label a reply for a call that failed', () => { + expect( + appendToolAttributions( + 'Could not reach Genie', + [step('Genie_ask', { errored: true })], + [genie], + ), + ).toBe('Could not reach Genie'); + }); + it('leaves a reply without text alone, so the label never shows up on its own', () => { expect(appendToolAttributions('', [step('Genie_ask')], [genie])).toBe(''); expect(appendToolAttributions(' \n', [step('Genie_ask')], [genie])).toBe(' \n'); diff --git a/packages/@n8n/nodes-langchain/nodes/chains/TextClassifier/TextClassifier.node.ts b/packages/@n8n/nodes-langchain/nodes/chains/TextClassifier/TextClassifier.node.ts index 30f75569dc3..7611619639a 100644 --- a/packages/@n8n/nodes-langchain/nodes/chains/TextClassifier/TextClassifier.node.ts +++ b/packages/@n8n/nodes-langchain/nodes/chains/TextClassifier/TextClassifier.node.ts @@ -10,11 +10,17 @@ import type { INodeType, INodeTypeDescription, } from 'n8n-workflow'; -import { z } from 'zod'; import { getBatchingOptionFields } from '@n8n/ai-utilities'; import { wrapLangChainParserError } from '@utils/output_parsers/langchainParserError'; +import { + buildClassificationSchema, + findReservedCategory, + FALLBACK_KEY, + type Category, + type ClassificationResult, +} from './classification'; import { processItem } from './processItem'; const SYSTEM_PROMPT_TEMPLATE = @@ -30,6 +36,55 @@ const configuredOutputs = (parameters: INodeParameters) => { return ret; }; +const OTHER_LABEL = 'Other'; + +/** One item can match several branches, and a shared object would carry one branch's writes onto the rest. */ +function routeItem(options: { + result: ClassificationResult; + item: INodeExecutionData; + itemIndex: number; + categories: Category[]; + hasOtherBranch: boolean; + withConfidence: boolean; + returnData: INodeExecutionData[][]; +}): void { + const { result, item, itemIndex, categories, hasOtherBranch, withConfidence, returnData } = + options; + + const scores = result.scores + ? Object.fromEntries( + categories + .filter((category) => result.scores?.[category.category] !== undefined) + .map((category) => [category.category, result.scores?.[category.category]]), + ) + : undefined; + + const copy = (label: string, decisionKey: string): INodeExecutionData => { + const json = { ...item.json }; + + if (withConfidence) { + const confidence = result.scores?.[decisionKey]; + json.classification = { + category: label, + ...(confidence !== undefined && { confidence }), + // A fresh object per branch, so a downstream node mutating one copy + // cannot reach the scores the other branches carry + ...(scores && Object.keys(scores).length > 0 && { scores: { ...scores } }), + }; + } + + return { ...item, json, pairedItem: { item: itemIndex } }; + }; + + categories.forEach((category, index) => { + if (result.matched.includes(category.category)) + returnData[index].push(copy(category.category, category.category)); + }); + + if (hasOtherBranch && result.fallback) + returnData[returnData.length - 1].push(copy(OTHER_LABEL, FALLBACK_KEY)); +} + export class TextClassifier implements INodeType { description: INodeTypeDescription = { displayName: 'Text Classifier', @@ -117,6 +172,18 @@ export class TextClassifier implements INodeType { }, ], }, + { + displayName: + 'Confidence scores are estimates from the model, not measured probabilities. They can change between runs, so treat them as a rough signal, not a threshold.', + name: 'confidenceScoresNotice', + type: 'notice', + default: '', + displayOptions: { + show: { + '/options.includeConfidenceScores': [true], + }, + }, + }, { displayName: 'Options', name: 'options', @@ -149,6 +216,14 @@ export class TextClassifier implements INodeType { }, ], }, + { + displayName: 'Include Confidence Scores', + name: 'includeConfidenceScores', + type: 'boolean', + default: false, + description: + "Whether to add a classification field to each item with the model's confidence score for every category", + }, { displayName: 'System Prompt Template', name: 'systemPromptTemplate', @@ -191,10 +266,7 @@ export class TextClassifier implements INodeType { 0, )) as BaseLanguageModel; - const categories = this.getNodeParameter('categories.categories', 0, []) as Array<{ - category: string; - description: string; - }>; + const categories = this.getNodeParameter('categories.categories', 0, []) as Category[]; if (categories.length === 0) { throw new NodeOperationError(this.getNode(), 'At least one category must be defined'); @@ -205,24 +277,25 @@ export class TextClassifier implements INodeType { fallback?: string; systemPromptTemplate?: string; enableAutoFixing: boolean; + includeConfidenceScores?: boolean; }; const multiClass = options?.multiClass ?? false; const fallback = options?.fallback ?? 'discard'; + const withConfidence = options?.includeConfidenceScores ?? false; - const schemaEntries = categories.map((cat) => [ - cat.category, - z - .boolean() - .describe( - `Should be true if the input has category "${cat.category}" (description: ${cat.description})`, - ), - ]); - if (fallback === 'other') - schemaEntries.push([ - 'fallback', - z.boolean().describe('Should be true if none of the other categories apply'), - ]); - const schema = z.object(Object.fromEntries(schemaEntries)); + const reserved = withConfidence ? findReservedCategory(categories) : undefined; + if (reserved) { + throw new NodeOperationError( + this.getNode(), + `The category name "${reserved}" is reserved when confidence scores are on`, + { + description: + 'The node reports the scores under that name. Rename the category, or turn off Include Confidence Scores.', + }, + ); + } + + const schema = buildClassificationSchema(categories, fallback === 'other', withConfidence); const structuredParser = StructuredOutputParser.fromZodSchema(schema); @@ -249,12 +322,10 @@ export class TextClassifier implements INodeType { const batch = items.slice(i, i + batchSize); const batchPromises = batch.map(async (_item, batchItemIndex) => { const itemIndex = i + batchItemIndex; - const item = items[itemIndex]; return await processItem( this, itemIndex, - item, llm, parser, categories, @@ -279,15 +350,15 @@ export class TextClassifier implements INodeType { throw new NodeOperationError(this.getNode(), error); } } else { - const output = response.value; - const item = items[index]; - - categories.forEach((cat, idx) => { - if (output[cat.category]) returnData[idx].push(item); + routeItem({ + result: response.value, + item: items[index], + itemIndex: index, + categories, + hasOtherBranch: fallback === 'other', + withConfidence, + returnData, }); - - if (fallback === 'other' && output.fallback) - returnData[returnData.length - 1].push(item); } }); @@ -304,7 +375,6 @@ export class TextClassifier implements INodeType { const output = await processItem( this, itemIndex, - item, llm, parser, categories, @@ -312,10 +382,15 @@ export class TextClassifier implements INodeType { fallbackPrompt, ); - categories.forEach((cat, idx) => { - if (output[cat.category]) returnData[idx].push(item); + routeItem({ + result: output, + item, + itemIndex, + categories, + hasOtherBranch: fallback === 'other', + withConfidence, + returnData, }); - if (fallback === 'other' && output.fallback) returnData[returnData.length - 1].push(item); } catch (error) { const executionError = wrapLangChainParserError(error, this.getNode(), itemIndex); if (this.continueOnFail()) { diff --git a/packages/@n8n/nodes-langchain/nodes/chains/TextClassifier/classification.ts b/packages/@n8n/nodes-langchain/nodes/chains/TextClassifier/classification.ts new file mode 100644 index 00000000000..1796a65268d --- /dev/null +++ b/packages/@n8n/nodes-langchain/nodes/chains/TextClassifier/classification.ts @@ -0,0 +1,100 @@ +import { isRecord } from '@n8n/utils/is-record'; +import { z } from 'zod'; + +export interface Category { + category: string; + description: string; +} + +export const FALLBACK_KEY = 'fallback'; +export const CONFIDENCE_KEY = 'confidence'; + +const CONFIDENCE_MAP_DESCRIPTION = + 'A score from 0.0 to 1.0 for every key above, including the categories you set to false. Score 1.0 when the text says so outright, 0.5 when the text is genuinely ambiguous, and 0.0 when nothing in the text fits. Use the whole range and rank the categories against each other: a category you set to false scores well under 0.5, and the scores must never all be high or all be the same.'; + +/** Routing on the model's own object instead is how a schema change sends every item to every branch. */ +export interface ClassificationResult { + matched: string[]; + fallback: boolean; + scores?: Record; +} + +export function findReservedCategory(categories: Category[]): string | undefined { + return categories.find((cat) => cat.category === CONFIDENCE_KEY)?.category; +} + +function clampToScore(value: unknown): number | undefined { + if (typeof value !== 'number' || !Number.isFinite(value)) return undefined; + return Math.min(1, Math.max(0, value)); +} + +/** `z.coerce` would read the boolean answer above as 1, and report certainty the model never gave. */ +const numericStringToNumber = (value: unknown) => + typeof value === 'string' && value.trim() !== '' ? Number(value) : value; + +function scoreField(decisionKey: string) { + return z + .preprocess(numericStringToNumber, z.number()) + .nullish() + .catch(undefined) + .describe( + decisionKey === FALLBACK_KEY + ? 'How poorly the text fits every category above: 1.0 when no category applies at all, 0.0 when one category clearly applies' + : `How much of the text supports category "${decisionKey}"`, + ); +} + +export function buildClassificationSchema( + categories: Category[], + withFallback: boolean, + withConfidence = false, +) { + const entries: Array<[string, z.ZodTypeAny]> = categories.map((cat) => [ + cat.category, + z + .boolean() + .describe( + `Should be true if the input has category "${cat.category}" (description: ${cat.description})`, + ), + ]); + + if (withFallback) { + entries.push([ + FALLBACK_KEY, + z.boolean().describe('Should be true if none of the other categories apply'), + ]); + } + + if (withConfidence) { + const decisionKeys = entries.map(([key]) => key); + entries.push([ + CONFIDENCE_KEY, + z + .object(Object.fromEntries(decisionKeys.map((key) => [key, scoreField(key)]))) + .nullish() + .catch(undefined) + .describe(CONFIDENCE_MAP_DESCRIPTION), + ]); + } + + return z.object(Object.fromEntries(entries)); +} + +export function toClassificationResult(raw: unknown, categories: Category[]): ClassificationResult { + const answer = isRecord(raw) ? raw : {}; + const reportedScores = answer[CONFIDENCE_KEY]; + + const scores: Record = {}; + if (isRecord(reportedScores)) { + for (const [key, value] of Object.entries(reportedScores)) { + const score = clampToScore(value); + if (score !== undefined) scores[key] = score; + } + } + + return { + matched: categories.filter((cat) => answer[cat.category] === true).map((cat) => cat.category), + fallback: answer[FALLBACK_KEY] === true, + ...(Object.keys(scores).length > 0 && { scores }), + }; +} diff --git a/packages/@n8n/nodes-langchain/nodes/chains/TextClassifier/processItem.ts b/packages/@n8n/nodes-langchain/nodes/chains/TextClassifier/processItem.ts index f18f6631e06..8014f1acb45 100644 --- a/packages/@n8n/nodes-langchain/nodes/chains/TextClassifier/processItem.ts +++ b/packages/@n8n/nodes-langchain/nodes/chains/TextClassifier/processItem.ts @@ -2,24 +2,24 @@ import type { BaseLanguageModel } from '@langchain/core/language_models/base'; import { HumanMessage } from '@langchain/core/messages'; import { ChatPromptTemplate, SystemMessagePromptTemplate } from '@langchain/core/prompts'; import type { OutputFixingParser, StructuredOutputParser } from '@langchain/classic/output_parsers'; -import { NodeOperationError, type IExecuteFunctions, type INodeExecutionData } from 'n8n-workflow'; +import { NodeOperationError, type IExecuteFunctions } from 'n8n-workflow'; import { wrapLangChainParserError } from '@utils/output_parsers/langchainParserError'; import { toParserInputText } from '@utils/output_parsers/parserInput'; import { getTracingConfig } from '@utils/tracing'; +import { toClassificationResult, type Category, type ClassificationResult } from './classification'; import { SYSTEM_PROMPT_TEMPLATE } from './constants'; export async function processItem( ctx: IExecuteFunctions, itemIndex: number, - item: INodeExecutionData, llm: BaseLanguageModel, parser: StructuredOutputParser | OutputFixingParser, - categories: Array<{ category: string; description: string }>, + categories: Category[], multiClassPrompt: string, fallbackPrompt: string | undefined, -): Promise> { +): Promise { const input = ctx.getNodeParameter('inputText', itemIndex) as string; if (!input) { @@ -29,8 +29,6 @@ export async function processItem( ); } - item.pairedItem = { item: itemIndex }; - const inputPrompt = new HumanMessage(input); const systemPromptTemplateOpt = ctx.getNodeParameter( @@ -64,7 +62,7 @@ export async function processItem( .withConfig(getTracingConfig(ctx)); try { - return await chain.invoke(messages); + return toClassificationResult(await chain.invoke(messages), categories); } catch (error) { throw wrapLangChainParserError(error, ctx.getNode(), itemIndex); } diff --git a/packages/@n8n/nodes-langchain/nodes/chains/TextClassifier/test/TextClassifier.node.test.ts b/packages/@n8n/nodes-langchain/nodes/chains/TextClassifier/test/TextClassifier.node.test.ts index 293695717fc..ec2602e7cff 100644 --- a/packages/@n8n/nodes-langchain/nodes/chains/TextClassifier/test/TextClassifier.node.test.ts +++ b/packages/@n8n/nodes-langchain/nodes/chains/TextClassifier/test/TextClassifier.node.test.ts @@ -1,9 +1,10 @@ import { FakeChatModel } from '@langchain/core/utils/testing'; import * as n8nUtilsSleep from '@n8n/utils/sleep'; -import type { IExecuteFunctions, INode } from 'n8n-workflow'; +import type { IDataObject, IExecuteFunctions, INode } from 'n8n-workflow'; import type { Mock, Mocked } from 'vitest'; import { mock } from 'vitest-mock-extended'; +import type { ClassificationResult } from '../classification'; import { processItem } from '../processItem'; import { TextClassifier } from '../TextClassifier.node'; @@ -15,6 +16,21 @@ vi.mock('@n8n/utils/sleep', () => ({ sleep: vi.fn().mockResolvedValue(undefined), })); +const fromZodSchema = vi.hoisted(() => vi.fn()); +vi.mock('@langchain/classic/output_parsers', async (importOriginal) => { + const actual = await importOriginal(); + return { + ...actual, + StructuredOutputParser: { + ...actual.StructuredOutputParser, + fromZodSchema: (schema: { shape: Record }) => { + fromZodSchema(schema); + return actual.StructuredOutputParser.fromZodSchema(schema as never); + }, + }, + }; +}); + describe('TextClassifier Node', () => { let node: TextClassifier; let mockExecuteFunction: Mocked; @@ -51,14 +67,13 @@ describe('TextClassifier Node', () => { describe('execute', () => { it('should process items with correct parameters', async () => { - (processItem as Mock).mockResolvedValue({ test: true }); + (processItem as Mock).mockResolvedValue({ matched: ['test'], fallback: false }); const result = await node.execute.call(mockExecuteFunction); expect(processItem).toHaveBeenCalledWith( mockExecuteFunction, 0, - { json: { testValue: 'none' } }, expect.any(FakeChatModel), expect.any(Object), [{ category: 'test', description: 'test category' }], @@ -66,7 +81,65 @@ describe('TextClassifier Node', () => { 'If there is not a very fitting category, select none of the categories.', ); - expect(result).toEqual([[{ json: { testValue: 'none' } }]]); + expect(result).toEqual([[{ json: { testValue: 'none' }, pairedItem: { item: 0 } }]]); + }); + + it('gives each branch its own copy of a multi-class item', async () => { + mockExecuteFunction.getNodeParameter.mockImplementation((param, _itemIndex, defaultValue) => { + if (param === 'inputText') return 'Test input'; + if (param === 'categories.categories') + return [ + { category: 'test1', description: 'first' }, + { category: 'test2', description: 'second' }, + ]; + return defaultValue; + }); + (processItem as Mock).mockResolvedValue({ matched: ['test1', 'test2'], fallback: false }); + + const result = await node.execute.call(mockExecuteFunction); + + expect(result[0][0]).not.toBe(result[1][0]); + expect(result[0][0].json).not.toBe(result[1][0].json); + expect(result[0][0].json).toEqual(result[1][0].json); + }); + + it('routes only the categories the model matched', async () => { + mockExecuteFunction.getNodeParameter.mockImplementation((param, _itemIndex, defaultValue) => { + if (param === 'inputText') return 'Test input'; + if (param === 'categories.categories') + return [ + { category: 'test1', description: 'first' }, + { category: 'test2', description: 'second' }, + ]; + return defaultValue; + }); + (processItem as Mock).mockResolvedValue({ matched: ['test2'], fallback: false }); + + const result = await node.execute.call(mockExecuteFunction); + + expect(result[0]).toHaveLength(0); + expect(result[1]).toHaveLength(1); + }); + + it('carries the rest of the item onto the branch', async () => { + mockExecuteFunction.getInputData.mockReturnValue([ + { json: { item: 1 }, binary: { file: { data: 'x', mimeType: 'text/plain' } } }, + ]); + (processItem as Mock).mockResolvedValue({ matched: ['test'], fallback: false }); + + const result = await node.execute.call(mockExecuteFunction); + + expect(result[0][0].binary).toEqual({ file: { data: 'x', mimeType: 'text/plain' } }); + }); + + it('leaves the input items alone', async () => { + const input = [{ json: { item: 1 } }]; + mockExecuteFunction.getInputData.mockReturnValue(input); + (processItem as Mock).mockResolvedValue({ matched: ['test'], fallback: false }); + + await node.execute.call(mockExecuteFunction); + + expect(input).toEqual([{ json: { item: 1 } }]); }); it('should handle multiple input items', async () => { @@ -85,8 +158,8 @@ describe('TextClassifier Node', () => { ]); (processItem as Mock) - .mockResolvedValueOnce({ test1: true, test2: false }) - .mockResolvedValueOnce({ test1: false, test2: true }); + .mockResolvedValueOnce({ matched: ['test1'], fallback: false }) + .mockResolvedValueOnce({ matched: ['test2'], fallback: false }); const result = await node.execute.call(mockExecuteFunction); @@ -113,20 +186,43 @@ describe('TextClassifier Node', () => { ]); (processItem as Mock) - .mockResolvedValueOnce({ test: true }) - .mockResolvedValueOnce({ test: true }) - .mockResolvedValueOnce({ test: true }) - .mockResolvedValueOnce({ test: true }); + .mockResolvedValueOnce({ matched: ['test'], fallback: false }) + .mockResolvedValueOnce({ matched: ['test'], fallback: false }) + .mockResolvedValueOnce({ matched: ['test'], fallback: false }) + .mockResolvedValueOnce({ matched: ['test'], fallback: false }); const result = await node.execute.call(mockExecuteFunction); expect(processItem).toHaveBeenCalledTimes(4); expect(result[0]).toHaveLength(4); expect(result[0]).toEqual([ + { json: { item: 1 }, pairedItem: { item: 0 } }, + { json: { item: 2 }, pairedItem: { item: 1 } }, + { json: { item: 3 }, pairedItem: { item: 2 } }, + { json: { item: 4 }, pairedItem: { item: 3 } }, + ]); + }); + + // Every other test here leaves batchSize at its default of 5, so they all take the batch path. + it('routes the same way with batching off', async () => { + mockExecuteFunction.getNodeParameter.mockImplementation((param, _itemIndex, defaultValue) => { + if (param === 'inputText') return 'Test input'; + if (param === 'categories.categories') + return [{ category: 'test', description: 'test category' }]; + if (param === 'options.batching.batchSize') return 1; + return defaultValue; + }); + mockExecuteFunction.getInputData.mockReturnValue([ { json: { item: 1 } }, { json: { item: 2 } }, - { json: { item: 3 } }, - { json: { item: 4 } }, + ]); + (processItem as Mock).mockResolvedValue({ matched: ['test'], fallback: false }); + + const result = await node.execute.call(mockExecuteFunction); + + expect(result[0]).toEqual([ + { json: { item: 1 }, pairedItem: { item: 0 } }, + { json: { item: 2 }, pairedItem: { item: 1 } }, ]); }); @@ -149,7 +245,7 @@ describe('TextClassifier Node', () => { { json: { item: 6 } }, ]); - (processItem as Mock).mockResolvedValue({ test: true }); + (processItem as Mock).mockResolvedValue({ matched: ['test'], fallback: false }); await node.execute.call(mockExecuteFunction); @@ -174,9 +270,9 @@ describe('TextClassifier Node', () => { ]); (processItem as Mock) - .mockResolvedValueOnce({ test: true }) + .mockResolvedValueOnce({ matched: ['test'], fallback: false }) .mockRejectedValueOnce(new Error('Batch error')) - .mockResolvedValueOnce({ test: true }); + .mockResolvedValueOnce({ matched: ['test'], fallback: false }); mockExecuteFunction.continueOnFail.mockReturnValue(true); @@ -186,6 +282,160 @@ describe('TextClassifier Node', () => { expect(result[0][1].json).toHaveProperty('error', 'Batch error'); }); + describe('confidence scores', () => { + const withCategories = ( + categories: Array<{ category: string; description: string }>, + options: Record = {}, + ) => { + mockExecuteFunction.getNodeParameter.mockImplementation( + (param, _itemIndex, defaultValue) => { + if (param === 'inputText') return 'Test input'; + if (param === 'categories.categories') return categories; + if (param === 'options') return { includeConfidenceScores: true, ...options }; + return defaultValue; + }, + ); + }; + const twoCategories = [ + { category: 'Billing', description: 'first' }, + { category: 'Urgent', description: 'second' }, + ]; + + it.each([ + ['asks the model for scores when the option is on', true], + ['leaves them out when it is off', false], + ])('%s', async (_name, on) => { + withCategories(twoCategories, { includeConfidenceScores: on }); + (processItem as Mock).mockResolvedValue({ matched: [], fallback: false }); + + await node.execute.call(mockExecuteFunction); + + const schema = fromZodSchema.mock.calls.at(-1)?.[0] as { shape: Record }; + expect('confidence' in schema.shape).toBe(on); + }); + + it('adds nothing while the option is off', async () => { + (processItem as Mock).mockResolvedValue({ + matched: ['test'], + fallback: false, + scores: { test: 0.9 }, + }); + + const result = await node.execute.call(mockExecuteFunction); + + expect(result[0][0].json).toEqual({ testValue: 'none' }); + }); + + it.each<[string, Record, ClassificationResult, number, IDataObject]>([ + [ + 'the score for its own category', + {}, + { + matched: ['Billing', 'Urgent'], + fallback: false, + scores: { Billing: 0.92, Urgent: 0.61 }, + }, + 0, + { category: 'Billing', confidence: 0.92, scores: { Billing: 0.92, Urgent: 0.61 } }, + ], + [ + 'the sibling branch a score of its own', + {}, + { + matched: ['Billing', 'Urgent'], + fallback: false, + scores: { Billing: 0.92, Urgent: 0.61 }, + }, + 1, + { category: 'Urgent', confidence: 0.61, scores: { Billing: 0.92, Urgent: 0.61 } }, + ], + [ + 'the Other branch the fallback score, and no score of its own', + { fallback: 'other' }, + { matched: [], fallback: true, scores: { Billing: 0.1, Urgent: 0.05, fallback: 0.8 } }, + 2, + { category: 'Other', confidence: 0.8, scores: { Billing: 0.1, Urgent: 0.05 } }, + ], + [ + 'a score of zero, which is an answer and not a gap', + {}, + { matched: ['Billing'], fallback: false, scores: { Billing: 0, Urgent: 0 } }, + 0, + { category: 'Billing', confidence: 0, scores: { Billing: 0, Urgent: 0 } }, + ], + [ + 'only the category when no score is usable', + {}, + { matched: ['Billing'], fallback: false }, + 0, + { category: 'Billing' }, + ], + [ + 'only the category when every score belongs to the fallback', + { fallback: 'other' }, + { matched: ['Billing'], fallback: false, scores: { fallback: 0.4 } }, + 0, + { category: 'Billing' }, + ], + ])('gives %s', async (_name, options, classified, branch, expected) => { + withCategories(twoCategories, options); + mockExecuteFunction.getInputData.mockReturnValue([{ json: { id: 7 } }]); + (processItem as Mock).mockResolvedValue(classified); + + const result = await node.execute.call(mockExecuteFunction); + const { id, classification } = result[branch][0].json as { + id: number; + classification: IDataObject; + }; + + expect(id).toBe(7); + expect(classification).toEqual(expected); + // `toEqual` ignores a key set to undefined, so absence needs its own assertion. + expect(Object.keys(classification)).toEqual(Object.keys(expected)); + }); + + it('gives each branch its own score map', async () => { + withCategories(twoCategories); + mockExecuteFunction.getInputData.mockReturnValue([{ json: { id: 7 } }]); + (processItem as Mock).mockResolvedValue({ + matched: ['Billing', 'Urgent'], + fallback: false, + scores: { Billing: 0.92, Urgent: 0.61 }, + }); + + const result = await node.execute.call(mockExecuteFunction); + const scoresOf = (branch: number) => + (result[branch][0].json.classification as IDataObject).scores as IDataObject; + + scoresOf(0).Billing = 'mutated'; + + expect(scoresOf(1)).toEqual({ Billing: 0.92, Urgent: 0.61 }); + }); + + it('refuses a category named after the key the scores use', async () => { + withCategories([{ category: 'confidence', description: 'clashes' }]); + (processItem as Mock).mockResolvedValue({ matched: [], fallback: false }); + + await expect(node.execute.call(mockExecuteFunction)).rejects.toThrow( + 'The category name "confidence" is reserved when confidence scores are on', + ); + }); + + it('allows that category while the option is off', async () => { + mockExecuteFunction.getNodeParameter.mockImplementation( + (param, _itemIndex, defaultValue) => { + if (param === 'inputText') return 'Test input'; + if (param === 'categories.categories') + return [{ category: 'confidence', description: 'clashes' }]; + return defaultValue; + }, + ); + (processItem as Mock).mockResolvedValue({ matched: ['confidence'], fallback: false }); + + await expect(node.execute.call(mockExecuteFunction)).resolves.toHaveLength(1); + }); + }); + it('should throw error when continueOnFail is false', async () => { mockExecuteFunction.continueOnFail.mockReturnValue(false); (processItem as Mock).mockRejectedValue(new Error('Test error')); diff --git a/packages/@n8n/nodes-langchain/nodes/chains/TextClassifier/test/classification.test.ts b/packages/@n8n/nodes-langchain/nodes/chains/TextClassifier/test/classification.test.ts new file mode 100644 index 00000000000..87d60344c17 --- /dev/null +++ b/packages/@n8n/nodes-langchain/nodes/chains/TextClassifier/test/classification.test.ts @@ -0,0 +1,194 @@ +import { + buildClassificationSchema, + findReservedCategory, + toClassificationResult, + type Category, +} from '../classification'; + +const CATEGORIES: Category[] = [ + { category: 'Billing', description: 'Payments and refunds' }, + { category: 'Technical', description: 'Bugs and errors' }, +]; + +describe('buildClassificationSchema', () => { + it('asks for one boolean per category', () => { + const schema = buildClassificationSchema(CATEGORIES, false); + + expect(Object.keys(schema.shape)).toEqual(['Billing', 'Technical']); + expect(schema.parse({ Billing: true, Technical: false })).toEqual({ + Billing: true, + Technical: false, + }); + }); + + it('adds the fallback key only when the Other branch is on', () => { + expect(Object.keys(buildClassificationSchema(CATEGORIES, true).shape)).toContain('fallback'); + expect(Object.keys(buildClassificationSchema(CATEGORIES, false).shape)).not.toContain( + 'fallback', + ); + }); + + it('asks for the scores only when they were requested', () => { + expect(Object.keys(buildClassificationSchema(CATEGORIES, false, true).shape)).toEqual([ + 'Billing', + 'Technical', + 'confidence', + ]); + expect(Object.keys(buildClassificationSchema(CATEGORIES, false).shape)).not.toContain( + 'confidence', + ); + }); + + it('asks for a score on the fallback answer too', () => { + const parsed = buildClassificationSchema(CATEGORIES, true, true).parse({ + Billing: false, + Technical: false, + fallback: true, + confidence: { Billing: 0.1, Technical: 0.1, fallback: 0.8 }, + }); + + expect(parsed.confidence).toEqual({ Billing: 0.1, Technical: 0.1, fallback: 0.8 }); + }); + + // Auto-fixing is on by default, so a failed parse costs a repair call. + it.each([ + ['a word', { Billing: true, Technical: false, confidence: { Billing: 'high' } }], + ['the wrong type', { Billing: true, Technical: false, confidence: 'high' }], + ['nothing at all', { Billing: true, Technical: false }], + ])('still parses when the model answers the scores with %s', (_name, answer) => { + expect(() => buildClassificationSchema(CATEGORIES, false, true).parse(answer)).not.toThrow(); + }); + + it('keeps the scores either side of one it cannot read', () => { + const parsed = buildClassificationSchema(CATEGORIES, false, true).parse({ + Billing: true, + Technical: false, + confidence: { Billing: 'high', Technical: 0.2 }, + }); + + expect(parsed.confidence).toEqual({ Technical: 0.2 }); + }); + + it.each([ + ['a number as a string', '0.8', 0.8], + ['a mirrored boolean', true, undefined], + ['an empty string', '', undefined], + ])('reads %s', (_name, given, expected) => { + const parsed = buildClassificationSchema(CATEGORIES, false, true).parse({ + Billing: true, + Technical: false, + confidence: { Billing: given }, + }); + + expect(parsed.confidence?.Billing).toBe(expected); + }); + + it('tells the model what the scores mean and not to flatten them', () => { + const parsed = buildClassificationSchema(CATEGORIES, true, true); + const map = parsed.shape.confidence; + + expect(map.description).toContain('0.0 to 1.0'); + expect(map.description).toContain('never all be high or all be the same'); + }); + + it('names the category in the instruction the model reads', () => { + const { description } = buildClassificationSchema(CATEGORIES, false).shape.Billing; + + expect(description).toContain('Billing'); + expect(description).toContain('Payments and refunds'); + }); +}); + +describe('findReservedCategory', () => { + it('names a category that would take the key the scores need', () => { + expect(findReservedCategory([{ category: 'confidence', description: '' }])).toBe('confidence'); + }); + + it('is silent when no category clashes', () => { + expect(findReservedCategory(CATEGORIES)).toBeUndefined(); + }); +}); + +describe('toClassificationResult', () => { + it('lists the categories the model marked true', () => { + expect(toClassificationResult({ Billing: true, Technical: false }, CATEGORIES)).toEqual({ + matched: ['Billing'], + fallback: false, + }); + }); + + it('reads the fallback key', () => { + expect( + toClassificationResult({ Billing: false, Technical: false, fallback: true }, CATEGORIES) + .fallback, + ).toBe(true); + }); + + it.each([ + ['an object', { matched: true, confidence: 0.9 }], + ['a string', 'true'], + ['a number', 1], + ])('does not count %s as a match', (_name, value) => { + expect(toClassificationResult({ Billing: value }, CATEGORIES).matched).toEqual([]); + }); + + it.each([ + ['the model answered with nothing', undefined], + ['the answer is not an object', 'Billing'], + ])('matches nothing when %s', (_name, raw) => { + expect(toClassificationResult(raw, CATEGORIES)).toEqual({ matched: [], fallback: false }); + }); + + it('reads the score for each decision', () => { + const result = toClassificationResult( + { Billing: true, Technical: false, confidence: { Billing: 0.92, Technical: 0.1 } }, + CATEGORIES, + ); + + expect(result.scores).toEqual({ Billing: 0.92, Technical: 0.1 }); + }); + + it('holds a score the model gave for a category it rejected', () => { + const result = toClassificationResult( + { Billing: false, Technical: false, confidence: { Billing: 0.2 } }, + CATEGORIES, + ); + + expect(result).toEqual({ matched: [], fallback: false, scores: { Billing: 0.2 } }); + }); + + it.each([ + ['above the range', 1.4, 1], + ['below the range', -2, 0], + ['at the top', 1, 1], + ])('clamps a score %s', (_name, given, expected) => { + expect(toClassificationResult({ confidence: { Billing: given } }, CATEGORIES).scores).toEqual({ + Billing: expected, + }); + }); + + it.each([ + ['a word', { Billing: 'high' }], + ['null', { Billing: null }], + ['not a number', { Billing: Number.NaN }], + ])('drops a score that is %s', (_name, confidence) => { + expect(toClassificationResult({ confidence }, CATEGORIES).scores).toBeUndefined(); + }); + + it('keeps a score of zero', () => { + expect(toClassificationResult({ confidence: { Billing: 0 } }, CATEGORIES).scores).toEqual({ + Billing: 0, + }); + }); + + it('reports no scores at all when none were asked for', () => { + expect(toClassificationResult({ Billing: true }, CATEGORIES)).not.toHaveProperty('scores'); + }); + + it('keeps the order the user defined', () => { + expect(toClassificationResult({ Technical: true, Billing: true }, CATEGORIES).matched).toEqual([ + 'Billing', + 'Technical', + ]); + }); +}); diff --git a/packages/@n8n/nodes-langchain/nodes/chains/TextClassifier/test/processItem.contentBlocks.test.ts b/packages/@n8n/nodes-langchain/nodes/chains/TextClassifier/test/processItem.contentBlocks.test.ts index 3705b56c34d..22438c0c95b 100644 --- a/packages/@n8n/nodes-langchain/nodes/chains/TextClassifier/test/processItem.contentBlocks.test.ts +++ b/packages/@n8n/nodes-langchain/nodes/chains/TextClassifier/test/processItem.contentBlocks.test.ts @@ -55,7 +55,6 @@ describe('processItem with content-block model output', () => { const output = await processItem( ctx, 0, - { json: {} }, llm, parser, categories, @@ -63,6 +62,6 @@ describe('processItem with content-block model output', () => { undefined, ); - expect(output).toEqual({ Billing: true, Technical: false }); + expect(output).toEqual({ matched: ['Billing'], fallback: false }); }); }); diff --git a/packages/@n8n/nodes-langchain/nodes/chains/TextClassifier/test/processItem.test.ts b/packages/@n8n/nodes-langchain/nodes/chains/TextClassifier/test/processItem.test.ts index 88beeada6b8..16f020c61ac 100644 --- a/packages/@n8n/nodes-langchain/nodes/chains/TextClassifier/test/processItem.test.ts +++ b/packages/@n8n/nodes-langchain/nodes/chains/TextClassifier/test/processItem.test.ts @@ -51,7 +51,6 @@ describe('processItem', () => { processItem( mockContext, 0, - { json: {} }, fakeLLM, { getFormatInstructions: () => 'format instructions' } as any, [{ category: 'test', description: 'test category' }], @@ -87,7 +86,6 @@ describe('processItem', () => { const result = await processItem( mockContext, 0, - { json: {} }, fakeLLM, mockParser as any, [{ category: 'test', description: 'test category' }], @@ -95,7 +93,7 @@ describe('processItem', () => { undefined, ); - expect(result).toEqual({ test: true }); + expect(result).toEqual({ matched: ['test'], fallback: false }); expect(mockContext.getNodeParameter).toHaveBeenCalledWith('inputText', 0); expect(mockContext.getNodeParameter).toHaveBeenCalledWith( 'options.systemPromptTemplate', @@ -135,7 +133,6 @@ describe('processItem', () => { await processItem( mockContext, 0, - { json: {} }, fakeLLM, mockParser as any, [{ category: 'test', description: 'test category' }], @@ -177,7 +174,6 @@ describe('processItem', () => { await processItem( mockContext, 0, - { json: {} }, fakeLLM, mockParser as any, [{ category: 'test', description: 'test category' }], diff --git a/packages/@n8n/nodes-langchain/nodes/llms/LmChatGoogleGemini/LmChatGoogleGemini.node.ts b/packages/@n8n/nodes-langchain/nodes/llms/LmChatGoogleGemini/LmChatGoogleGemini.node.ts index 124af810dec..04f915e1f7f 100644 --- a/packages/@n8n/nodes-langchain/nodes/llms/LmChatGoogleGemini/LmChatGoogleGemini.node.ts +++ b/packages/@n8n/nodes-langchain/nodes/llms/LmChatGoogleGemini/LmChatGoogleGemini.node.ts @@ -18,7 +18,11 @@ import { N8nLlmTracing, getConnectionHintNoticeField, } from '@n8n/ai-utilities'; -import { shouldIncludeGoogleModel } from '@n8n/ai-utilities/model-discovery'; +import { + getGoogleModelLabel, + pinPrioritizedModels, + shouldIncludeGoogleModel, +} from '@n8n/ai-utilities/model-discovery'; import { MODEL_SELECTION_HINT } from '@utils/model-builder-hints'; @@ -37,6 +41,30 @@ async function filterChatModels( ); } +/** Show models under the name the API reports, sorted by it, with prioritized models first. */ +async function labelModels( + this: IExecuteSingleFunctions, + items: INodeExecutionData[], +): Promise { + const labelled = items.map((item) => { + // `displayName` and `priority` only carry the API's values to here; options do not keep them. + const { displayName, priority, ...option } = item.json; + const json = + typeof option.value === 'string' + ? { + ...option, + name: getGoogleModelLabel( + option.value, + typeof displayName === 'string' ? displayName : undefined, + ), + } + : option; + return { item: { ...item, json }, priority }; + }); + labelled.sort((a, b) => String(a.item.json.name).localeCompare(String(b.item.json.name))); + return pinPrioritizedModels(labelled, (entry) => entry.priority).map((entry) => entry.item); +} + function errorDescriptionMapper(error: NodeError) { if (error.description?.includes('properties: should be non-empty for OBJECT type')) { return 'Google Gemini requires at least one dynamic parameter when using tools'; @@ -78,14 +106,11 @@ const modelRLC: INodeProperties = { name: '={{$responseItem.name}}', value: '={{$responseItem.name}}', description: '={{$responseItem.description}}', + displayName: '={{$responseItem.displayName}}', + priority: '={{$responseItem.priority}}', }, }, - { - type: 'sort', - properties: { - key: 'name', - }, - }, + labelModels, ], }, }, @@ -133,14 +158,11 @@ const modelRLCV2: INodeProperties = { name: '={{$responseItem.name}}', value: '={{$responseItem.name}}', description: '={{$responseItem.description}}', + displayName: '={{$responseItem.displayName}}', + priority: '={{$responseItem.priority}}', }, }, - { - type: 'sort', - properties: { - key: 'name', - }, - }, + labelModels, ], }, }, diff --git a/packages/@n8n/nodes-langchain/nodes/llms/LmChatGoogleGemini/test/LmChatGoogleGemini.test.ts b/packages/@n8n/nodes-langchain/nodes/llms/LmChatGoogleGemini/test/LmChatGoogleGemini.test.ts index 43cd059e456..928f5f29f2d 100644 --- a/packages/@n8n/nodes-langchain/nodes/llms/LmChatGoogleGemini/test/LmChatGoogleGemini.test.ts +++ b/packages/@n8n/nodes-langchain/nodes/llms/LmChatGoogleGemini/test/LmChatGoogleGemini.test.ts @@ -1,3 +1,5 @@ +import type { IExecuteSingleFunctions, INodeExecutionData, PostReceiveAction } from 'n8n-workflow'; + import { LmChatGoogleGemini } from '../LmChatGoogleGemini.node'; describe('LmChatGoogleGemini', () => { @@ -23,4 +25,72 @@ describe('LmChatGoogleGemini', () => { expect(hint).not.toMatch(/searchModels|explore-resources|nodes\(/); } }); + + it('should label, sort and pin models in every version', async () => { + const modelProperties = new LmChatGoogleGemini().description.properties.filter( + (p) => p.name === 'modelName', + ); + const options: INodeExecutionData[] = [ + { + json: { + name: 'models/gemini-zeta', + value: 'models/gemini-zeta', + displayName: '', + priority: '', + }, + }, + { + json: { + name: 'models/gemini-featured', + value: 'models/gemini-featured', + displayName: 'Gemini Featured', + priority: 10, + }, + }, + { json: { name: 'models/gemini-2.5-pro', value: 'models/gemini-2.5-pro' } }, + { + json: { + name: 'models/gemini-api-named', + value: 'models/gemini-api-named', + displayName: 'Gemini Api Named', + }, + }, + ]; + + expect(modelProperties).toHaveLength(3); + for (const property of modelProperties) { + const postReceive = property.typeOptions?.loadOptions?.routing?.output + ?.postReceive as PostReceiveAction[]; + const labelModels = postReceive.at(-1); + if (typeof labelModels !== 'function') throw new Error('Expected a postReceive function'); + + const result = await labelModels.call({} as IExecuteSingleFunctions, options, {} as never); + + // The API's displayName labels a model, else its id. A priority pins a model. + expect(result.map((option) => option.json)).toEqual([ + { name: 'Gemini Featured', value: 'models/gemini-featured' }, + { name: 'Gemini Api Named', value: 'models/gemini-api-named' }, + { name: 'models/gemini-2.5-pro', value: 'models/gemini-2.5-pro' }, + { name: 'models/gemini-zeta', value: 'models/gemini-zeta' }, + ]); + } + }); + + it('should leave the label of an option without a string value alone', async () => { + const property = new LmChatGoogleGemini().description.properties.find( + (p) => p.name === 'modelName', + ); + const postReceive = property?.typeOptions?.loadOptions?.routing?.output + ?.postReceive as PostReceiveAction[]; + const labelModels = postReceive.at(-1); + if (typeof labelModels !== 'function') throw new Error('Expected a postReceive function'); + + const result = await labelModels.call( + {} as IExecuteSingleFunctions, + [{ json: { name: 'Unknown', value: 42, displayName: 'Ignored' } }], + {} as never, + ); + + expect(result.map((option) => option.json)).toEqual([{ name: 'Unknown', value: 42 }]); + }); }); diff --git a/packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/protocol/MessageFormatter.ts b/packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/protocol/MessageFormatter.ts index e73a73fc4db..6ae61c64c97 100644 --- a/packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/protocol/MessageFormatter.ts +++ b/packages/@n8n/nodes-langchain/nodes/mcp/McpTrigger/protocol/MessageFormatter.ts @@ -1,5 +1,7 @@ import type { CredentialCheckResult } from 'n8n-workflow'; +import { isToolErrorResult } from '@utils/tool-error-result'; + import type { McpToolResult } from './types'; /** @@ -40,29 +42,8 @@ export class MessageFormatter { return isError ? { isError: true, content } : { content }; } - /** - * Detect whether a tool result represents an error. - * - * In direct mode, N8nTool catches errors and returns `e.toString()` producing - * strings like `"NodeApiError: Bad request"`. ToolHttpRequest catches HTTP errors - * and returns `"There was an error: \"...\"" or `"HTTP 401 There was an error: \"...\""`. - * - * In queue mode, the job processor wraps errors as `{ error: { message, name } }`. - */ static isErrorResult(result: unknown): boolean { - if (typeof result === 'object' && result !== null && 'error' in result) { - const { error } = result as { error: unknown }; - return ( - typeof error === 'object' && - error !== null && - 'message' in error && - typeof (error as { message: unknown }).message === 'string' - ); - } - if (typeof result === 'string') { - return /^(\w+Error: |HTTP \d{3} There was an error: |There was an error: )/.test(result); - } - return false; + return isToolErrorResult(result); } static formatError(error: Error): McpToolResult { diff --git a/packages/@n8n/nodes-langchain/nodes/trigger/ChatTrigger/ChatTrigger.node.ts b/packages/@n8n/nodes-langchain/nodes/trigger/ChatTrigger/ChatTrigger.node.ts index 331c585d79a..2c07a7253b7 100644 --- a/packages/@n8n/nodes-langchain/nodes/trigger/ChatTrigger/ChatTrigger.node.ts +++ b/packages/@n8n/nodes-langchain/nodes/trigger/ChatTrigger/ChatTrigger.node.ts @@ -1098,6 +1098,10 @@ export class ChatTrigger extends Node { // By header as well as by the iframe's attribute, so the document has no // origin even if the attribute is ever stripped. res.setHeader('Content-Security-Policy', `sandbox ${CHAT_FRAME_SANDBOX}`); + } else { + // The webhook route sandboxes every response. This page keeps its origin, + // because the widget keeps the session in `localStorage`. + res.removeHeader('Content-Security-Policy'); } const page = createPage({ diff --git a/packages/@n8n/nodes-langchain/nodes/trigger/ChatTrigger/__test__/ChatTrigger.node.test.ts b/packages/@n8n/nodes-langchain/nodes/trigger/ChatTrigger/__test__/ChatTrigger.node.test.ts index 51f1ed98758..6ee3e008814 100644 --- a/packages/@n8n/nodes-langchain/nodes/trigger/ChatTrigger/__test__/ChatTrigger.node.test.ts +++ b/packages/@n8n/nodes-langchain/nodes/trigger/ChatTrigger/__test__/ChatTrigger.node.test.ts @@ -984,6 +984,17 @@ describe('ChatTrigger Node', () => { expect(renderedView().sandbox).not.toContain('allow-popups-to-escape-sandbox'); }); + it('removes the route sandbox from the public chat page', async () => { + await renderSetupPage('none'); + + expect(mockResponse.removeHeader).toHaveBeenCalledWith('Content-Security-Policy'); + expect(mockResponse.setHeader).not.toHaveBeenCalledWith( + 'Content-Security-Policy', + expect.anything(), + ); + expect(renderedPage()).toContain('createChat'); + }); + it('renders the author chat for the frame own request', async () => { mockRequest.query = { n8nShellInner: '1' }; mockRequest.headers = { @@ -998,6 +1009,7 @@ describe('ChatTrigger Node', () => { 'Content-Security-Policy', 'sandbox allow-scripts allow-forms allow-modals allow-popups', ); + expect(mockResponse.removeHeader).not.toHaveBeenCalled(); expect(renderedPage()).toContain('createChat'); // Identity injected server-side, and a header token for the messages that follow. expect(renderedPage()).toContain('"email":"visitor@example.com"'); diff --git a/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreMongoDBAtlas/VectorStoreMongoDBAtlas.node.test.ts b/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreMongoDBAtlas/VectorStoreMongoDBAtlas.node.test.ts index ec48bbde6be..79bb26eecab 100644 --- a/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreMongoDBAtlas/VectorStoreMongoDBAtlas.node.test.ts +++ b/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreMongoDBAtlas/VectorStoreMongoDBAtlas.node.test.ts @@ -1,5 +1,6 @@ import { MongoClient } from 'mongodb'; import type { ILoadOptionsFunctions, ISupplyDataFunctions } from 'n8n-workflow'; +import { NodeOperationError } from 'n8n-workflow'; import { mock } from 'vitest-mock-extended'; import { @@ -144,6 +145,30 @@ describe('VectorStoreMongoDBAtlas', () => { expect(mockClient.connect).toHaveBeenCalledTimes(1); expect(client).toBe(mockClient); }); + it('should not include the connection string in the error when the client cannot be created', async () => { + MockMongoClient.mockImplementation(function () { + throw new Error( + 'Protocol and host list are required in "mongodb://testuser:secret-pass@?x:27017"', + ); + }); + mockContext.getCredentials.mockResolvedValue({ + configurationType: 'values', + host: '?x', + user: 'testuser', + password: 'secret-pass', + port: 27017, + database: 'testdb', + }); + + const error = await createMongoClient(mockContext, 1.1).catch((e: unknown) => e); + + expect(error).toBeInstanceOf(NodeOperationError); + expect((error as Error).message).toBe( + 'MongoDB connection error: Protocol and host list are required in "mongodb://[REDACTED]"', + ); + expect(JSON.stringify(error)).not.toContain('secret-pass'); + expect((error as Error).stack).not.toContain('secret-pass'); + }); }); describe('.getCollections', () => { diff --git a/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreMongoDBAtlas/VectorStoreMongoDBAtlas.node.ts b/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreMongoDBAtlas/VectorStoreMongoDBAtlas.node.ts index 7c9a0134dea..d6774b61683 100644 --- a/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreMongoDBAtlas/VectorStoreMongoDBAtlas.node.ts +++ b/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreMongoDBAtlas/VectorStoreMongoDBAtlas.node.ts @@ -11,7 +11,10 @@ import { } from 'n8n-workflow'; import { metadataFilterField, createVectorStoreNode } from '@n8n/ai-utilities'; -import { validateAndResolveMongoCredentials } from 'n8n-nodes-base/dist/nodes/MongoDb/GenericFunctions'; +import { + sanitizeMongoUriInMessage, + validateAndResolveMongoCredentials, +} from 'n8n-nodes-base/dist/nodes/MongoDb/GenericFunctions'; /** * Constants for the name of the credentials and Node parameters. @@ -169,15 +172,22 @@ export async function createMongoClient( const node = context.getNode(); const { connectionString } = validateAndResolveMongoCredentials(node, credentials); - const client = new MongoClient(connectionString, { - appName: 'devrel.integration.n8n_vector_integ', - driverInfo: { - name: 'n8n_vector', - version: version.toString(), - }, - }); - await client.connect(); - return client; + try { + const client = new MongoClient(connectionString, { + appName: 'devrel.integration.n8n_vector_integ', + driverInfo: { + name: 'n8n_vector', + version: version.toString(), + }, + }); + await client.connect(); + return client; + } catch (error) { + throw new NodeOperationError( + node, + `MongoDB connection error: ${sanitizeMongoUriInMessage(error, connectionString)}`, + ); + } } /** diff --git a/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreOracleDB/VectorStoreOracleDB.node.test.ts b/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreOracleDB/VectorStoreOracleDB.node.test.ts index 3ba380b489f..a684256e819 100644 --- a/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreOracleDB/VectorStoreOracleDB.node.test.ts +++ b/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreOracleDB/VectorStoreOracleDB.node.test.ts @@ -4,7 +4,7 @@ import type { Embeddings } from '@langchain/core/embeddings'; import type { VectorStore } from '@langchain/core/vectorstores'; import type { VectorStoreNodeConstructorArgs } from '@n8n/ai-utilities'; import { ConnectionPoolManager } from 'n8n-nodes-base/dist/utils/connection-pool-manager'; -import type { IExecuteFunctions } from 'n8n-workflow'; +import type { IExecuteFunctions, INode } from 'n8n-workflow'; import type { Pool } from 'oracledb'; import type { Mocked } from 'vitest'; @@ -323,9 +323,12 @@ vi.mock('@n8n/ai-utilities', () => { import { VectorStoreOracleDB } from './VectorStoreOracleDB.node'; describe('VectorStoreOracleDB.node', () => { + const node = { name: 'Oracle Database Vector Store', type: 'vectorStoreOracleDBVector' } as INode; + const context = { getNodeParameter: vi.fn(), getCredentials: vi.fn(), + getNode: vi.fn(() => node), logger: { debug: vi.fn(), error: vi.fn(), @@ -594,4 +597,104 @@ describe('VectorStoreOracleDB.node', () => { expect(connectionCloseMocks[1]).toHaveBeenCalledTimes(1); expect(poolCloseMocks[0]).not.toHaveBeenCalled(); }); + + describe('parameter validation', () => { + const withTableName = (tableName: string) => (name: string) => { + if (name === 'tableName') return tableName; + if (name === 'options.distanceStrategy') return DistanceStrategyMock.DOT_PRODUCT; + return undefined; + }; + + it('rejects a metadata filter name that is not a plain identifier', async () => { + const node = createNode(); + + await expect( + node.getVectorStoreClient(context, { "userId'": 'alice' } as OracleFilter, embeddings, 0), + ).rejects.toThrow('Invalid metadata filter key'); + expect(initializeSpy).not.toHaveBeenCalled(); + }); + + it('rejects a metadata filter name supplied at search time', async () => { + const node = createNode(); + const vectorStore = await node.getVectorStoreClient(context, undefined, embeddings, 0); + + await expect( + vectorStore.similaritySearchVectorWithScore([0.1], 3, { + 'userId?(@ == "bob")': 'alice', + } as OracleFilter), + ).rejects.toThrow('Invalid metadata filter key'); + expect(similaritySearchSpy).not.toHaveBeenCalled(); + }); + + it('rejects a metadata filter name nested under $and at search time', async () => { + const node = createNode(); + const vectorStore = await node.getVectorStoreClient(context, undefined, embeddings, 0); + + await expect( + vectorStore.similaritySearchVectorWithScore([0.1], 3, { + $and: [{ project: 'n8n' }, { 'a.b': 'x' }], + } as OracleFilter), + ).rejects.toThrow('Invalid metadata filter key'); + expect(similaritySearchSpy).not.toHaveBeenCalled(); + }); + + it('accepts a filter whose names are plain identifiers', async () => { + const node = createNode(); + const filter = { userId: 'alice', user_id: 'alice' } as OracleFilter; + + const vectorStore = await node.getVectorStoreClient(context, filter, embeddings, 0); + await vectorStore.similaritySearchVectorWithScore([0.1], 3, undefined); + + expect(similaritySearchSpy).toHaveBeenCalledWith([0.1], 3, filter); + }); + + it('rejects a table name that is not a plain identifier', async () => { + const node = createNode(); + context.getNodeParameter.mockImplementation(withTableName('n8n_vectors; SELECT 1')); + + await expect(node.getVectorStoreClient(context, undefined, embeddings, 0)).rejects.toThrow( + 'Invalid table name', + ); + + context.getNodeParameter.mockImplementation(defaultGetNodeParameter); + }); + + it('rejects a table name that is not a plain identifier when inserting', async () => { + const node = createNode(); + context.getNodeParameter.mockImplementation(withTableName('n8n_vectors; SELECT 1')); + + await expect(node.populateVectorStore(context, embeddings, documents, 0)).rejects.toThrow( + 'Invalid table name', + ); + expect(fromDocumentsSpy).not.toHaveBeenCalled(); + + context.getNodeParameter.mockImplementation(defaultGetNodeParameter); + }); + + it('accepts a schema-qualified table name', async () => { + const node = createNode(); + context.getNodeParameter.mockImplementation(withTableName('app.n8n_vectors')); + + await node.getVectorStoreClient(context, undefined, embeddings, 0); + + const lastCall = initializeSpy.mock.calls.at(-1); + if (!lastCall) throw new Error('initializeSpy should have been called'); + expect(lastCall[1]?.tableName).toBe('app.n8n_vectors'); + + context.getNodeParameter.mockImplementation(defaultGetNodeParameter); + }); + + it('falls back to the default table name when the parameter resolves to empty', async () => { + const node = createNode(); + context.getNodeParameter.mockImplementation(withTableName('')); + + await node.getVectorStoreClient(context, undefined, embeddings, 0); + + const lastCall = initializeSpy.mock.calls.at(-1); + if (!lastCall) throw new Error('initializeSpy should have been called'); + expect(lastCall[1]?.tableName).toBe('n8n_vectors'); + + context.getNodeParameter.mockImplementation(defaultGetNodeParameter); + }); + }); }); diff --git a/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreOracleDB/VectorStoreOracleDB.node.ts b/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreOracleDB/VectorStoreOracleDB.node.ts index c3f62415fb1..a56bfd33432 100644 --- a/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreOracleDB/VectorStoreOracleDB.node.ts +++ b/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStoreOracleDB/VectorStoreOracleDB.node.ts @@ -4,9 +4,15 @@ import { createVectorStoreNode, metadataFilterField } from '@n8n/ai-utilities'; import { DistanceStrategy, OracleVS, type OracleDBVSArgs } from '@oracle/langchain-oracledb'; import type { OracleDBNodeCredentials } from 'n8n-nodes-base/dist/nodes/Oracle/Sql/helpers/interfaces'; import { configureOracleDB } from 'n8n-nodes-base/dist/nodes/Oracle/Sql/transport'; -import type { IExecuteFunctions, INodeProperties, ISupplyDataFunctions } from 'n8n-workflow'; +import type { INode, IExecuteFunctions, INodeProperties, ISupplyDataFunctions } from 'n8n-workflow'; +import { NodeOperationError } from 'n8n-workflow'; import type oracledb from 'oracledb'; +import { + findUnsupportedJsonPathFilterKey, + isSafeQualifiedSqlIdentifier, +} from '@utils/sqlIdentifier'; + const sharedFields: INodeProperties[] = [ { displayName: 'Table Name', @@ -20,6 +26,40 @@ const sharedFields: INodeProperties[] = [ const DEFAULT_INITIALIZATION_TEXT = 'n8n vector store initialization text'; +const DEFAULT_TABLE_NAME = 'n8n_vectors'; + +/** Reads the Table Name, falling back to the default when an expression resolves to empty. */ +function getTableName( + context: IExecuteFunctions | ISupplyDataFunctions, + itemIndex: number, +): string { + const tableName = + (context.getNodeParameter('tableName', itemIndex, '', { extractValue: true }) as string) || + DEFAULT_TABLE_NAME; + + if (!isSafeQualifiedSqlIdentifier(tableName)) { + throw new NodeOperationError(context.getNode(), `Invalid table name \"${tableName}\"`, { + itemIndex, + description: + 'The table name must be a plain name, or a schema and name separated by a dot. Letters, digits and underscores only.', + }); + } + + return tableName; +} + +/** Rejects a metadata filter the Oracle store cannot resolve into a SQL/JSON path. */ +function assertSupportedFilter(node: INode, filter: unknown, itemIndex?: number): void { + const unsupported = findUnsupportedJsonPathFilterKey(filter); + if (unsupported === undefined) return; + + throw new NodeOperationError(node, `Invalid metadata filter key \"${unsupported}\"`, { + itemIndex, + description: + 'A metadata filter name must start with a letter or underscore and contain only letters, digits and underscores.', + }); +} + const NO_ROWS_FOUND_ERROR_MESSAGE = 'No rows found.'; const isNoRowsFoundError = (error: unknown): error is Error => @@ -146,11 +186,15 @@ const createLazyOraclePool = ( * with any ad-hoc filter provided at runtime. */ class ExtendedOracleDBVectorStore extends OracleVS { + n8nNode!: INode; + static async initialize( embeddings: EmbeddingsInterface, - args: OracleDBVSArgs, + args: OracleDBVSArgs & { n8nNode: INode }, ): Promise { - const oracleDBVectorStore = new this(embeddings, args); + const { n8nNode, ...rest } = args; + const oracleDBVectorStore = new this(embeddings, rest); + oracleDBVectorStore.n8nNode = n8nNode; await oracleDBVectorStore.initialize(); return oracleDBVectorStore; @@ -162,6 +206,9 @@ class ExtendedOracleDBVectorStore extends OracleVS { filter?: OracleVS['FilterType'], ) { const mergedFilter = mergeFilters(this.filter, filter); + // Checked here as well as at construction, because load and both + // retrieve-as-tool modes supply the filter at search time. + assertSupportedFilter(this.n8nNode, mergedFilter); try { return await super.similaritySearchVectorWithScore(query, k, mergedFilter); @@ -199,17 +246,17 @@ export class VectorStoreOracleDB extends createVectorStoreNode { - const tableName = context.getNodeParameter('tableName', itemIndex, '', { - extractValue: true, - }) as string; + const tableName = getTableName(context, itemIndex); + assertSupportedFilter(context.getNode(), filter, itemIndex); const credentials = (await context.getCredentials('oracleDBApi')) as OracleDBNodeCredentials; const client = createLazyOraclePool(context, credentials); const query = DEFAULT_INITIALIZATION_TEXT; - const config: OracleDBVSArgs = { + const config: OracleDBVSArgs & { n8nNode: INode } = { client, tableName, query, filter: filter as ExtendedOracleDBVectorStore['FilterType'] | undefined, + n8nNode: context.getNode(), }; config.distanceStrategy = context.getNodeParameter( @@ -227,9 +274,7 @@ export class VectorStoreOracleDB extends createVectorStoreNode>>, itemIndex: number, ): Promise { - const tableName = context.getNodeParameter('tableName', itemIndex, '', { - extractValue: true, - }) as string; + const tableName = getTableName(context, itemIndex); const credentials = (await context.getCredentials('oracleDBApi')) as OracleDBNodeCredentials; const client = createLazyOraclePool(context, credentials); const query = DEFAULT_INITIALIZATION_TEXT; diff --git a/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStorePGVector/VectorStorePGVector.node.test.ts b/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStorePGVector/VectorStorePGVector.node.test.ts index 41c6707173c..b470a2b304f 100644 --- a/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStorePGVector/VectorStorePGVector.node.test.ts +++ b/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStorePGVector/VectorStorePGVector.node.test.ts @@ -1,22 +1,31 @@ import type { Embeddings } from '@langchain/core/embeddings'; -import type { INode } from 'n8n-workflow'; +import type { VectorStoreNodeConstructorArgs } from '@n8n/ai-utilities'; +import { configurePostgres } from 'n8n-nodes-base/dist/nodes/Postgres/transport/index'; +import type { INode, ISupplyDataFunctions } from 'n8n-workflow'; import type pg from 'pg'; import { escapeQualifiedSqlIdentifier, escapeSqlIdentifier } from '@utils/sqlIdentifier'; -// Keep the module import light: the node body calls createVectorStoreNode and -// configurePostgres at load time, neither of which is needed to exercise the -// ExtendedPGVectorStore identifier handling. +// Keep the node factory light and use a mock pool for initialization tests. vi.mock('@n8n/ai-utilities', () => ({ metadataFilterField: {}, - createVectorStoreNode: () => class {}, + createVectorStoreNode: ( + config: Pick< + VectorStoreNodeConstructorArgs, + 'getVectorStoreClient' | 'populateVectorStore' + >, + ) => + class { + getVectorStoreClient = config.getVectorStoreClient; + populateVectorStore = config.populateVectorStore; + }, })); vi.mock('n8n-nodes-base/dist/nodes/Postgres/transport/index', () => ({ configurePostgres: vi.fn(), })); -import { ExtendedPGVectorStore } from './VectorStorePGVector.node'; +import { ExtendedPGVectorStore, VectorStorePGVector } from './VectorStorePGVector.node'; const embeddings = {} as unknown as Embeddings; const node = { name: 'Postgres PGVector Store' } as unknown as INode; @@ -39,6 +48,30 @@ function createStore(args: { return store; } +function createNodeContext(skipInitializationCheck: boolean, rejectExtensionCreation: boolean) { + const query = vi.fn(async (sql: string) => { + if (rejectExtensionCreation && sql.startsWith('CREATE EXTENSION')) { + throw new Error('permission denied to create extension "vector"'); + } + return { rows: [] }; + }); + const client = { release: vi.fn() }; + const pool = { query, connect: vi.fn().mockResolvedValue(client) } as unknown as pg.Pool; + vi.mocked(configurePostgres).mockResolvedValue({ db: { $pool: pool } } as never); + + const context = { + getNode: () => node, + getCredentials: vi.fn().mockResolvedValue({}), + getNodeParameter: vi.fn((name: string, _itemIndex: number, fallback?: unknown) => { + if (name === 'tableName') return 'n8n_vectors'; + if (name === 'options.skipInitializationCheck') return skipInitializationCheck; + return fallback; + }), + } as unknown as ISupplyDataFunctions; + + return { context, query, client }; +} + describe('ExtendedPGVectorStore', () => { const maliciousName = 'x"; DROP TABLE victim; --'; @@ -120,3 +153,61 @@ describe('ExtendedPGVectorStore', () => { }); }); }); + +describe('VectorStorePGVector initialization', () => { + const vectorStoreNode = new VectorStorePGVector() as unknown as Pick< + VectorStoreNodeConstructorArgs, + 'getVectorStoreClient' | 'populateVectorStore' + >; + const nodeEmbeddings = { + embedDocuments: vi.fn().mockResolvedValue([[0.1, 0.2]]), + } as unknown as Embeddings; + + it('initializes the table when the default option is used', async () => { + const { context, query, client } = createNodeContext(false, false); + + const store = await vectorStoreNode.getVectorStoreClient(context, undefined, nodeEmbeddings, 0); + store.client?.release(); + + expect(query).toHaveBeenCalledWith('CREATE EXTENSION IF NOT EXISTS vector;'); + expect(query).toHaveBeenCalledTimes(2); + expect(client.release).toHaveBeenCalledOnce(); + }); + + // NODE-6101: A preconfigured database must work without initialization privileges. + it.each(['insert', 'retrieve'] as const)( + 'uses existing tables without initialization in %s mode', + async (mode) => { + const { context, query, client } = createNodeContext(true, true); + + if (mode === 'insert') { + await vectorStoreNode.populateVectorStore( + context, + nodeEmbeddings, + [{ pageContent: 'text', metadata: {} }], + 0, + ); + expect(query).toHaveBeenCalledWith( + expect.stringContaining('INSERT INTO'), + expect.any(Array), + ); + } else { + const store = await vectorStoreNode.getVectorStoreClient( + context, + undefined, + nodeEmbeddings, + 0, + ); + try { + await store.similaritySearchVectorWithScore([0.1, 0.2], 1); + } finally { + store.client?.release(); + } + expect(query).toHaveBeenCalledWith(expect.stringContaining('SELECT'), expect.any(Array)); + } + + expect(query).toHaveBeenCalledTimes(1); + expect(client.release).toHaveBeenCalledOnce(); + }, + ); +}); diff --git a/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStorePGVector/VectorStorePGVector.node.ts b/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStorePGVector/VectorStorePGVector.node.ts index d8f0b2cb4cf..12eaa01f0da 100644 --- a/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStorePGVector/VectorStorePGVector.node.ts +++ b/packages/@n8n/nodes-langchain/nodes/vector_store/VectorStorePGVector/VectorStorePGVector.node.ts @@ -164,6 +164,14 @@ const distanceStrategyField: INodeProperties = { ], }; +const skipInitializationCheckField: INodeProperties = { + displayName: 'Skip Table Initialization', + name: 'skipInitializationCheck', + type: 'boolean', + default: false, + description: 'Whether to skip creating the vector extension and tables when they already exist', +}; + const insertFields: INodeProperties[] = [ { displayName: 'Options', @@ -171,7 +179,7 @@ const insertFields: INodeProperties[] = [ type: 'collection', placeholder: 'Add Option', default: {}, - options: [collectionField, columnNamesField], + options: [collectionField, columnNamesField, skipInitializationCheckField], }, ]; @@ -182,7 +190,13 @@ const retrieveFields: INodeProperties[] = [ type: 'collection', placeholder: 'Add Option', default: {}, - options: [distanceStrategyField, collectionField, columnNamesField, metadataFilterField], + options: [ + distanceStrategyField, + collectionField, + columnNamesField, + metadataFilterField, + skipInitializationCheckField, + ], }, ]; @@ -247,7 +261,15 @@ async function buildPgVectorStoreConfig( const pgConf = await configurePostgres.call(context, credentials as PostgresNodeCredentials); const pool = pgConf.db.$pool as unknown as pg.Pool; - const config: PGVectorStoreArgs = { pool, tableName }; + const config: PGVectorStoreArgs = { + pool, + tableName, + skipInitializationCheck: context.getNodeParameter( + 'options.skipInitializationCheck', + itemIndex, + false, + ) as boolean, + }; const collectionOptions = context.getNodeParameter( 'options.collection.values', diff --git a/packages/@n8n/nodes-langchain/nodes/vendors/Databricks/DatabricksAiAgent.node.ts b/packages/@n8n/nodes-langchain/nodes/vendors/Databricks/DatabricksAiAgent.node.ts index 11d30e2d872..a4a5be661f7 100644 --- a/packages/@n8n/nodes-langchain/nodes/vendors/Databricks/DatabricksAiAgent.node.ts +++ b/packages/@n8n/nodes-langchain/nodes/vendors/Databricks/DatabricksAiAgent.node.ts @@ -157,6 +157,8 @@ export class DatabricksAiAgent implements INodeType { }, ], properties: [ + // Use the current list, not AgentV2's deprecated one. #22435 removed the + // Guardrails source from new agent versions, and this node has no legacy workflows. promptTypeOptions, { ...textFromPreviousNode, @@ -173,12 +175,42 @@ export class DatabricksAiAgent implements INodeType { default: false, noDataExpression: true, }, + { + displayName: `Connect an output parser on the canvas to specify the output format you require`, + name: 'notice', + type: 'notice', + default: '', + displayOptions: { + show: { + hasOutputParser: [true], + }, + }, + }, + // Verbatim from AgentV2 so the parity test can compare the whole object. + // The version gate is inert on a 2.2-only node. { displayName: 'Enable Fallback Model', name: 'needsFallback', type: 'boolean', default: false, noDataExpression: true, + displayOptions: { + show: { + '@version': [{ _cnd: { gte: 2.1 } }], + }, + }, + }, + { + displayName: + 'Connect an additional language model on the canvas to use it as a fallback if the main model fails', + name: 'fallbackNotice', + type: 'notice', + default: '', + displayOptions: { + show: { + needsFallback: [true], + }, + }, }, exportTracesField, experimentField, diff --git a/packages/@n8n/nodes-langchain/nodes/vendors/Databricks/__tests__/DatabricksAiAgent.node.test.ts b/packages/@n8n/nodes-langchain/nodes/vendors/Databricks/__tests__/DatabricksAiAgent.node.test.ts new file mode 100644 index 00000000000..879fd6f76d7 --- /dev/null +++ b/packages/@n8n/nodes-langchain/nodes/vendors/Databricks/__tests__/DatabricksAiAgent.node.test.ts @@ -0,0 +1,29 @@ +import { promptTypeOptions } from '@utils/descriptions'; + +import { Agent } from '../../../agents/Agent/Agent.node'; +import { DatabricksAiAgent } from '../DatabricksAiAgent.node'; + +// The Databricks AI Agent is AI Agent 2.2 plus trace export. These are the only +// differences the panel may have: the trace fields on one side and, on the +// other, the deprecated Guardrails prompt source that #22435 removed from new +// agent versions. +const DATABRICKS_ONLY = ['exportTraces', 'experiment']; + +describe('DatabricksAiAgent', () => { + const agentProps = new Agent().nodeVersions[2.2].description.properties.filter( + (p) => p.disabledOptions?.show?.promptType?.[0] !== 'guardrails', + ); + const databricksProps = new DatabricksAiAgent().description.properties.filter( + (p) => !DATABRICKS_ONLY.includes(p.name), + ); + + it('shows the AI Agent 2.2 properties after the prompt source, in the same order', () => { + expect(databricksProps.slice(1)).toEqual(agentProps.slice(1)); + }); + + it('uses the current prompt source list without the Guardrails option', () => { + expect(databricksProps[0]).toEqual(promptTypeOptions); + const values = databricksProps[0].options?.map((o) => ('value' in o ? o.value : undefined)); + expect(values).not.toContain('guardrails'); + }); +}); diff --git a/packages/@n8n/nodes-langchain/nodes/vendors/Databricks/mlflow/__tests__/span-collector.test.ts b/packages/@n8n/nodes-langchain/nodes/vendors/Databricks/mlflow/__tests__/span-collector.test.ts index 6aa0de85909..77a9ab2841c 100644 --- a/packages/@n8n/nodes-langchain/nodes/vendors/Databricks/mlflow/__tests__/span-collector.test.ts +++ b/packages/@n8n/nodes-langchain/nodes/vendors/Databricks/mlflow/__tests__/span-collector.test.ts @@ -333,7 +333,9 @@ describe('MlflowSpanCollector', () => { collector.handleToolError(new Error(`workspace rejected ${token}`), 'tool'); - expect(collector.finish()!.spans[1].status.message).not.toContain(token); + const status = collector.finish()!.spans[1].status; + expect(status.code).toBe('ERROR'); + expect(status.message).not.toContain(token); }); it('handles a thrown non-Error value', () => { @@ -345,6 +347,45 @@ describe('MlflowSpanCollector', () => { expect(collector.finish()!.spans[1].status.message).toBe('plain string'); }); + + it.each([ + ['ToolCode / ToolWorkflow', 'There was an error: "clock service unavailable [line 1]"'], + ['ToolHttpRequest', 'HTTP 401 There was an error: "Unauthorized"'], + ])('marks the tool span ERROR when a %s node returned an error string', (_label, text) => { + const collector = new MlflowSpanCollector(); + collector.handleChainStart(AGENT_EXECUTOR, {}, 'root', undefined); + collector.handleToolStart(SEARCH_TOOL, 'x', 'tool', 'root'); + collector.handleToolEnd(text, 'tool'); + collector.handleChainEnd({ output: 'done' }, 'root'); + + const trace = collector.finish()!; + expect(trace.spans[1].status).toEqual({ code: 'ERROR', message: text }); + expect(outputsOf(trace.spans[1])).toBe(text); + expect(trace.state).toBe('OK'); + }); + + it('keeps a tool answer that mentions an error OK', () => { + const collector = new MlflowSpanCollector(); + collector.handleChainStart(AGENT_EXECUTOR, {}, 'root', undefined); + collector.handleToolStart(SEARCH_TOOL, 'x', 'tool', 'root'); + + collector.handleToolEnd('The error rate is 2%', 'tool'); + + expect(collector.finish()!.spans[1].status).toEqual({ code: 'OK' }); + }); + + it('scrubs a token from a tool error string', () => { + const token = ['dapi', '0123456789abcdef0123456789abcdef'].join(''); + const collector = new MlflowSpanCollector(); + collector.handleChainStart(AGENT_EXECUTOR, {}, 'root', undefined); + collector.handleToolStart(SEARCH_TOOL, 'x', 'tool', 'root'); + + collector.handleToolEnd(`There was an error: "rejected ${token}"`, 'tool'); + + const status = collector.finish()!.spans[1].status; + expect(status.code).toBe('ERROR'); + expect(status.message).not.toContain(token); + }); }); describe('content handling', () => { @@ -479,7 +520,7 @@ describe('MlflowSpanCollector', () => { it('ignores an end event for a run it never saw start', () => { const collector = collectRun(); - expect(() => collector.handleToolEnd('late', 'unknown')).not.toThrow(); + expect(() => collector.handleToolEnd('There was an error: "late"', 'unknown')).not.toThrow(); expect(collector.finish()!.spans).toHaveLength(3); }); diff --git a/packages/@n8n/nodes-langchain/nodes/vendors/Databricks/mlflow/span-collector.ts b/packages/@n8n/nodes-langchain/nodes/vendors/Databricks/mlflow/span-collector.ts index eceeeedca9e..fb561c0880c 100644 --- a/packages/@n8n/nodes-langchain/nodes/vendors/Databricks/mlflow/span-collector.ts +++ b/packages/@n8n/nodes-langchain/nodes/vendors/Databricks/mlflow/span-collector.ts @@ -9,6 +9,8 @@ import { sanitizeErrorDetail } from '@n8n/utils/redaction/sanitize-error-detail' import { scrubSecretsInText } from '@n8n/utils/scrub-secrets'; import { randomBytes } from 'node:crypto'; +import { isToolErrorResult } from '@utils/tool-error-result'; + import type { MlflowSpan, MlflowSpanType, CollectedTrace, TokenUsage } from './types'; import { MLFLOW_ATTRIBUTE, MLFLOW_MESSAGE_FORMAT, MLFLOW_SPAN_TYPE } from './types'; @@ -505,6 +507,9 @@ export class MlflowSpanCollector extends BaseCallbackHandler { handleToolEnd(output: unknown, runId: string): void { this.endSpan(runId, output); + // Tool nodes return errors to the model as a string so it can recover. + // LangChain then fires handleToolEnd, not handleToolError. + if (typeof output === 'string' && isToolErrorResult(output)) this.failSpan(runId, output); } handleToolError(error: Error, runId: string): void { diff --git a/packages/@n8n/nodes-langchain/nodes/vendors/GoogleGemini/methods/listSearch.test.ts b/packages/@n8n/nodes-langchain/nodes/vendors/GoogleGemini/methods/listSearch.test.ts index de0a20d05b0..0332137afd7 100644 --- a/packages/@n8n/nodes-langchain/nodes/vendors/GoogleGemini/methods/listSearch.test.ts +++ b/packages/@n8n/nodes-langchain/nodes/vendors/GoogleGemini/methods/listSearch.test.ts @@ -101,6 +101,44 @@ describe('GoogleGemini -> listSearch', () => { ], }); }); + + it('should label, sort and pin models', async () => { + apiRequestMock.mockResolvedValue({ + models: [ + { name: 'models/gemini-zeta' }, + { name: 'models/gemini-featured', displayName: 'Gemini Featured', priority: 10 }, + { name: 'models/gemini-2.5-pro' }, + { name: 'models/gemini-api-named', displayName: 'Gemini Api Named' }, + ], + }); + + const result = await modelSearch.call(mockExecuteFunctions); + + // The API's displayName labels a model, else its id. A priority pins a model. + expect(result).toEqual({ + results: [ + { name: 'Gemini Featured', value: 'models/gemini-featured' }, + { name: 'Gemini Api Named', value: 'models/gemini-api-named' }, + { name: 'models/gemini-2.5-pro', value: 'models/gemini-2.5-pro' }, + { name: 'models/gemini-zeta', value: 'models/gemini-zeta' }, + ], + }); + }); + + it('should match the filter against the label and the id', async () => { + apiRequestMock.mockResolvedValue({ + models: [ + { name: 'models/gemini-zeta' }, + { name: 'models/gemini-2.5-pro', displayName: 'Gemini 2.5 Pro' }, + ], + }); + + const byName = await modelSearch.call(mockExecuteFunctions, '2.5 Pro'); + const byId = await modelSearch.call(mockExecuteFunctions, 'gemini-zeta'); + + expect(byName.results).toEqual([{ name: 'Gemini 2.5 Pro', value: 'models/gemini-2.5-pro' }]); + expect(byId.results).toEqual([{ name: 'models/gemini-zeta', value: 'models/gemini-zeta' }]); + }); }); describe('audioModelSearch', () => { @@ -115,14 +153,14 @@ describe('GoogleGemini -> listSearch', () => { name: 'models/gemini-2.5-flash', value: 'models/gemini-2.5-flash', }, - { - name: 'models/gemma-3-1b-it', - value: 'models/gemma-3-1b-it', - }, { name: 'models/gemini-2.5-flash-preview-native-audio-dialog', value: 'models/gemini-2.5-flash-preview-native-audio-dialog', }, + { + name: 'models/gemma-3-1b-it', + value: 'models/gemma-3-1b-it', + }, ], }); }); @@ -140,10 +178,6 @@ describe('GoogleGemini -> listSearch', () => { name: 'models/gemini-2.0-flash-exp-image-generation', value: 'models/gemini-2.0-flash-exp-image-generation', }, - { - name: 'models/imagen-3.0-generate-002', - value: 'models/imagen-3.0-generate-002', - }, { // eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased name: 'models/gemini-2.5-flash-image (Nano Banana)', @@ -159,15 +193,19 @@ describe('GoogleGemini -> listSearch', () => { name: 'models/gemini-3.1-flash-image-preview (Nano Banana 2)', value: 'models/gemini-3.1-flash-image-preview', }, + { + // eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased + name: 'models/gemini-3.1-flash-lite-image (Nano Banana 2 Lite)', + value: 'models/gemini-3.1-flash-lite-image', + }, { // eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased name: 'models/gemini-nano-banana-2.1 (Nano Banana 2.1)', value: 'models/gemini-nano-banana-2.1', }, { - // eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased - name: 'models/gemini-3.1-flash-lite-image (Nano Banana 2 Lite)', - value: 'models/gemini-3.1-flash-lite-image', + name: 'models/imagen-3.0-generate-002', + value: 'models/imagen-3.0-generate-002', }, ], }); @@ -189,6 +227,26 @@ describe('GoogleGemini -> listSearch', () => { }); }); + describe('imageModelSearch with names from the API', () => { + it('should match the filter against the id when the API names the model', async () => { + apiRequestMock.mockResolvedValue({ + models: [{ name: 'models/gemini-2.5-flash-image', displayName: 'Gemini 2.5 Flash Image' }], + }); + + const result = await imageGenerationModelSearch.call( + mockExecuteFunctions, + 'gemini-2.5-flash-image', + ); + + expect(result.results).toEqual([ + { + name: 'Gemini 2.5 Flash Image (Nano Banana)', + value: 'models/gemini-2.5-flash-image', + }, + ]); + }); + }); + describe('imageEditModelSearch', () => { it('should return image edit models', async () => { apiRequestMock.mockResolvedValue(mockResponse); @@ -214,13 +272,13 @@ describe('GoogleGemini -> listSearch', () => { }, { // eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased - name: 'models/gemini-nano-banana-2.1 (Nano Banana 2.1)', - value: 'models/gemini-nano-banana-2.1', + name: 'models/gemini-3.1-flash-lite-image (Nano Banana 2 Lite)', + value: 'models/gemini-3.1-flash-lite-image', }, { // eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased - name: 'models/gemini-3.1-flash-lite-image (Nano Banana 2 Lite)', - value: 'models/gemini-3.1-flash-lite-image', + name: 'models/gemini-nano-banana-2.1 (Nano Banana 2.1)', + value: 'models/gemini-nano-banana-2.1', }, ], }); diff --git a/packages/@n8n/nodes-langchain/nodes/vendors/GoogleGemini/methods/listSearch.ts b/packages/@n8n/nodes-langchain/nodes/vendors/GoogleGemini/methods/listSearch.ts index 70ebd266fec..f716d74480d 100644 --- a/packages/@n8n/nodes-langchain/nodes/vendors/GoogleGemini/methods/listSearch.ts +++ b/packages/@n8n/nodes-langchain/nodes/vendors/GoogleGemini/methods/listSearch.ts @@ -1,3 +1,8 @@ +import { + getGoogleModelLabel, + parseGoogleModels, + pinPrioritizedModels, +} from '@n8n/ai-utilities/model-discovery'; import type { ILoadOptionsFunctions, INodeListSearchResult } from 'n8n-workflow'; import { apiRequest } from '../transport'; @@ -12,21 +17,29 @@ async function baseModelSearch( modelFilter: (model: string) => boolean, filter?: string, ): Promise { - const response = (await apiRequest.call(this, 'GET', '/v1beta/models', { + const response: unknown = await apiRequest.call(this, 'GET', '/v1beta/models', { qs: { pageSize: 1000, }, - })) as { - models: Array<{ name: string }>; - }; + }); - let models = response.models.filter((model) => modelFilter(model.name)); + let entries = parseGoogleModels(response) + .filter((model) => modelFilter(model.name)) + .map((model) => ({ + result: { name: getGoogleModelLabel(model.name, model.displayName), value: model.name }, + priority: model.priority, + })); if (filter) { - models = models.filter((model) => model.name.toLowerCase().includes(filter.toLowerCase())); + const query = filter.toLowerCase(); + entries = entries.filter( + ({ result }) => + result.name.toLowerCase().includes(query) || result.value.toLowerCase().includes(query), + ); } + entries.sort((a, b) => a.result.name.localeCompare(b.result.name)); return { - results: models.map((model) => ({ name: model.name, value: model.name })), + results: pinPrioritizedModels(entries, (entry) => entry.priority).map((entry) => entry.result), }; } @@ -71,24 +84,25 @@ export async function imageGenerationModelSearch( ): Promise { const rawResult = await baseModelSearch.call(this, isImageModel); let results = rawResult.results.map((r) => { - if (r.name.includes('gemini-nano-banana-2.1')) { + const modelId = String(r.value); + if (modelId.includes('gemini-nano-banana-2.1')) { return { name: `${r.name} (Nano Banana 2.1)`, value: r.value }; } // The Lite id also contains "gemini-3.1-flash-image". Match it first. - if (r.name.includes('gemini-3.1-flash-lite-image')) { + if (modelId.includes('gemini-3.1-flash-lite-image')) { return { name: `${r.name} (Nano Banana 2 Lite)`, value: r.value }; } - if (r.name.includes('gemini-3.1-flash-image')) { + if (modelId.includes('gemini-3.1-flash-image')) { return { name: `${r.name} (Nano Banana 2)`, value: r.value }; } - if (r.name.includes('gemini-2.5-flash-image')) { + if (modelId.includes('gemini-2.5-flash-image')) { return { name: `${r.name} (Nano Banana)`, value: r.value }; } - if (r.name.includes('gemini-3-pro-image')) { + if (modelId.includes('gemini-3-pro-image')) { return { name: `${r.name} (Nano Banana Pro)`, value: r.value }; } @@ -97,7 +111,11 @@ export async function imageGenerationModelSearch( if (filter) { const filterLowerCase = filter.toLowerCase(); - results = results.filter((r) => r.name.toLowerCase().includes(filterLowerCase)); + results = results.filter( + (r) => + r.name.toLowerCase().includes(filterLowerCase) || + String(r.value).toLowerCase().includes(filterLowerCase), + ); } return { diff --git a/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/helpers/interfaces.ts b/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/helpers/interfaces.ts index 3bf4878b463..7117fcf631e 100644 --- a/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/helpers/interfaces.ts +++ b/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/helpers/interfaces.ts @@ -84,6 +84,14 @@ export type ChatCompletion = { system_fingerprint: string; }; +/** + * Response shape of the `/images/generations` and `/images/edits` endpoints, including + * the `usage` block the images API returns. Note that it reports `input_tokens` / + * `output_tokens`, unlike the Chat Completions naming (`prompt_tokens` / + * `completion_tokens`) used by `ChatCompletion` above. + */ +export type ImageResponse = OpenAIClient.Images.ImagesResponse; + export type ThreadMessage = { id: string; object: string; diff --git a/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/helpers/token-usage.test.ts b/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/helpers/token-usage.test.ts new file mode 100644 index 00000000000..afe1ad2f88f --- /dev/null +++ b/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/helpers/token-usage.test.ts @@ -0,0 +1,127 @@ +import type { IExecuteFunctions, ITaskMetadata } from 'n8n-workflow'; + +import { accumulateImageTokenUsage } from './token-usage'; + +type TokenUsage = NonNullable; + +/** + * Deliberately exercises the real `accumulateTokenUsage` rather than mocking it, so the + * assertions are about what actually reaches the execution metadata. + */ +const makeContext = (previous?: TokenUsage) => { + const setMetadata = vi.fn(); + const context = { + getExecuteData: vi.fn().mockReturnValue(previous ? { metadata: { tokenUsage: previous } } : {}), + setMetadata, + } as unknown as IExecuteFunctions; + + return { context, setMetadata }; +}; + +const storedUsage = (setMetadata: ReturnType): TokenUsage => + (setMetadata.mock.calls[0][0] as ITaskMetadata).tokenUsage as TokenUsage; + +describe('accumulateImageTokenUsage', () => { + it('should report both counts when the API returns them', () => { + const { context, setMetadata } = makeContext(); + + accumulateImageTokenUsage(context, { input_tokens: 350, output_tokens: 4160 }); + + expect(setMetadata).toHaveBeenCalledTimes(1); + expect(storedUsage(setMetadata)).toEqual({ inputTokens: 350, outputTokens: 4160 }); + }); + + it('should add to a total already accumulated earlier in the execution', () => { + const { context, setMetadata } = makeContext({ inputTokens: 100, outputTokens: 200 }); + + accumulateImageTokenUsage(context, { input_tokens: 350, output_tokens: 4160 }); + + expect(storedUsage(setMetadata)).toEqual({ inputTokens: 450, outputTokens: 4360 }); + }); + + it('should report nothing when the response has no usage block', () => { + const { context, setMetadata } = makeContext(); + + accumulateImageTokenUsage(context, undefined); + + expect(setMetadata).not.toHaveBeenCalled(); + }); + + it('should report nothing when a proxy returns an empty usage block', () => { + const { context, setMetadata } = makeContext(); + + accumulateImageTokenUsage(context, {}); + + expect(setMetadata).not.toHaveBeenCalled(); + }); + + it('should report nothing when usage carries only unrelated fields', () => { + const { context, setMetadata } = makeContext(); + + accumulateImageTokenUsage(context, { total_tokens: 1610 } as never); + + expect(setMetadata).not.toHaveBeenCalled(); + }); + + it('should still report the one count a partial usage block does provide', () => { + const { context, setMetadata } = makeContext(); + + accumulateImageTokenUsage(context, { input_tokens: 350 }); + + expect(storedUsage(setMetadata)).toEqual({ inputTokens: 350, outputTokens: 0 }); + }); + + it.each([ + ['string counts', { input_tokens: '350', output_tokens: '4160' }], + ['null counts', { input_tokens: null, output_tokens: null }], + ['NaN counts', { input_tokens: NaN, output_tokens: NaN }], + ['infinite counts', { input_tokens: Infinity, output_tokens: -Infinity }], + ['negative counts', { input_tokens: -350, output_tokens: -4160 }], + ['fractional counts', { input_tokens: 350.5, output_tokens: 4160.5 }], + ['counts beyond the safe integer range', { input_tokens: 2 ** 53, output_tokens: 2 ** 53 }], + ])('should ignore %s', (_label, usage) => { + const { context, setMetadata } = makeContext(); + + accumulateImageTokenUsage(context, usage as never); + + expect(setMetadata).not.toHaveBeenCalled(); + }); + + it('should never reduce a total already accumulated', () => { + const { context, setMetadata } = makeContext({ inputTokens: 100, outputTokens: 200 }); + + accumulateImageTokenUsage(context, { input_tokens: -350, output_tokens: -4160 } as never); + + expect(setMetadata).not.toHaveBeenCalled(); + }); + + it('should never store NaN, which would persist for the rest of the execution', () => { + const malformed = [ + undefined, + {}, + { total_tokens: 1610 }, + { input_tokens: undefined, output_tokens: undefined }, + { input_tokens: null, output_tokens: null }, + { input_tokens: NaN, output_tokens: NaN }, + { input_tokens: '350', output_tokens: '4160' }, + { input_tokens: -350, output_tokens: -4160 }, + { input_tokens: 350.5, output_tokens: 4160.5 }, + { input_tokens: 350 }, + { output_tokens: 4160 }, + ]; + + for (const usage of malformed) { + const { context, setMetadata } = makeContext({ inputTokens: 100, outputTokens: 200 }); + + accumulateImageTokenUsage(context, usage as never); + + if (setMetadata.mock.calls.length === 0) continue; + + const { inputTokens, outputTokens } = storedUsage(setMetadata); + expect(Number.isFinite(inputTokens)).toBe(true); + expect(Number.isFinite(outputTokens)).toBe(true); + expect(inputTokens).toBeGreaterThanOrEqual(100); + expect(outputTokens).toBeGreaterThanOrEqual(200); + } + }); +}); diff --git a/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/helpers/token-usage.ts b/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/helpers/token-usage.ts new file mode 100644 index 00000000000..d364428f5c1 --- /dev/null +++ b/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/helpers/token-usage.ts @@ -0,0 +1,48 @@ +import type { IExecuteFunctions } from 'n8n-workflow'; +import { accumulateTokenUsage } from 'n8n-workflow'; + +/** + * Token usage as the image and responses endpoints report it. Upstream both types + * declare these counts as required numbers, but an OpenAI-compatible proxy can answer + * with a partial or malformed `usage` block, so they are treated as untrusted here. + */ +type ImageTokenUsage = { + input_tokens?: number; + output_tokens?: number; +}; + +/** + * Accepts only what a token count can actually be: a non-negative integer. Nothing is + * coerced, so `null`, `undefined`, numeric strings, `NaN` and the infinities are all + * rejected — as are negative counts, which would otherwise *subtract* from the running + * total, and fractional ones, which are not a possible number of tokens. + */ +const asTokenCount = (value: unknown): number | undefined => + typeof value === 'number' && Number.isSafeInteger(value) && value >= 0 ? value : undefined; + +/** + * Reports token usage for an image operation, ignoring any count the API did not + * actually return as a number. + * + * `accumulateTokenUsage` adds to the running total with `??`, which only guards against + * `null`/`undefined`. Passing it a missing count would therefore store `NaN`, and since + * `NaN` is not nullish every later accumulation in the same execution would stay `NaN` + * too — leaving the whole run without usable token metrics (`NaN` also serializes to + * `null`). Guarding at the call site keeps one malformed response from poisoning the + * totals for every other node in the execution. + */ +export function accumulateImageTokenUsage( + context: IExecuteFunctions, + usage: ImageTokenUsage | undefined, +): void { + if (!usage) return; + + const inputTokens = asTokenCount(usage.input_tokens); + const outputTokens = asTokenCount(usage.output_tokens); + + // Nothing usable at all: report nothing rather than a confident zero, which is how + // a response without a `usage` block already behaves. + if (inputTokens === undefined && outputTokens === undefined) return; + + accumulateTokenUsage(context, inputTokens ?? 0, outputTokens ?? 0); +} diff --git a/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/test/v2/actions/image/analyze.test.ts b/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/test/v2/actions/image/analyze.test.ts index 58fb4a968a1..6f98426ec91 100644 --- a/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/test/v2/actions/image/analyze.test.ts +++ b/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/test/v2/actions/image/analyze.test.ts @@ -10,6 +10,15 @@ import { execute } from '../../../../v2/actions/image/analyze.operation'; vi.mock('../../../../helpers/binary-data'); vi.mock('../../../../transport'); +const { accumulateTokenUsageMock } = vi.hoisted(() => ({ + accumulateTokenUsageMock: vi.fn(), +})); + +vi.mock('n8n-workflow', async (importOriginal) => ({ + ...(await importOriginal()), + accumulateTokenUsage: accumulateTokenUsageMock, +})); + describe('Image Analyze Operation', () => { let mockExecuteFunctions: Mocked; let mockNode: INode; @@ -919,4 +928,63 @@ describe('Image Analyze Operation', () => { }); }); }); + + describe('token usage reporting', () => { + beforeEach(() => { + mockExecuteFunctions.getNodeParameter.mockImplementation((paramName: string) => { + const params = { + modelId: 'gpt-4o', + text: "What's in this image?", + inputType: 'url', + imageUrls: 'https://example.com/image1.jpg', + simplify: true, + options: {}, + }; + return params[paramName as keyof typeof params]; + }); + }); + + const baseResponse = { + id: 'response-123', + status: 'completed', + output: [ + { + type: 'message', + role: 'assistant', + content: [{ type: 'output_text', text: 'A mountain lake.' }], + }, + ], + }; + + it('should report token usage when the API returns a usage object', async () => { + apiRequestSpy.mockResolvedValue({ + ...baseResponse, + usage: { input_tokens: 1120, output_tokens: 96, total_tokens: 1216 }, + } as ChatResponse); + + await execute.call(mockExecuteFunctions, 0); + + expect(accumulateTokenUsageMock).toHaveBeenCalledTimes(1); + expect(accumulateTokenUsageMock).toHaveBeenCalledWith(mockExecuteFunctions, 1120, 96); + }); + + it('should not report token usage when the API omits it', async () => { + apiRequestSpy.mockResolvedValue(baseResponse as ChatResponse); + + await execute.call(mockExecuteFunctions, 0); + + expect(accumulateTokenUsageMock).not.toHaveBeenCalled(); + }); + + it('should not report token usage when a proxy returns usage without the counts', async () => { + apiRequestSpy.mockResolvedValue({ + ...baseResponse, + usage: { total_tokens: 1216 }, + } as unknown as ChatResponse); + + await execute.call(mockExecuteFunctions, 0); + + expect(accumulateTokenUsageMock).not.toHaveBeenCalled(); + }); + }); }); diff --git a/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/test/v2/actions/image/edit.operation.test.ts b/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/test/v2/actions/image/edit.operation.test.ts index cf851f8fcde..8d3bf13fea5 100644 --- a/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/test/v2/actions/image/edit.operation.test.ts +++ b/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/test/v2/actions/image/edit.operation.test.ts @@ -26,6 +26,15 @@ vi.mock('form-data', () => { return { default: MockFormData }; }); +const { accumulateTokenUsageMock } = vi.hoisted(() => ({ + accumulateTokenUsageMock: vi.fn(), +})); + +vi.mock('n8n-workflow', async (importOriginal) => ({ + ...(await importOriginal()), + accumulateTokenUsage: accumulateTokenUsageMock, +})); + describe('Image Edit Operation', () => { let mockExecuteFunctions: Mocked; let mockNode: INode; @@ -736,4 +745,95 @@ describe('Image Edit Operation', () => { expect(getBinaryDataFileSpy).toHaveBeenNthCalledWith(2, mockExecuteFunctions, 0, 'image2'); }); }); + + describe('token usage reporting', () => { + const mockBinaryFile = { + fileContent: Buffer.from('mock-image-data'), + contentType: 'image/png', + filename: 'data.png', + }; + + const mockEditedBinaryData = { + data: 'base64encodedimagedata', + mimeType: 'image/png', + fileName: 'data', + }; + + beforeEach(() => { + mockExecuteFunctions.getNodeParameter.mockImplementation((paramName: string) => { + const params = { + model: 'gpt-image-1', + prompt: 'Add a rainbow to this landscape', + images: { + values: [{ binaryPropertyName: 'data' }], + }, + n: 1, + size: '1024x1024', + quality: 'auto', + options: {}, + }; + return params[paramName as keyof typeof params]; + }); + + getBinaryDataFileSpy.mockResolvedValue(mockBinaryFile); + (mockExecuteFunctions.helpers.binaryToBuffer as Mock).mockResolvedValue( + mockBinaryFile.fileContent, + ); + (mockExecuteFunctions.helpers.prepareBinaryData as Mock).mockResolvedValue( + mockEditedBinaryData, + ); + }); + + it('should report token usage when the API returns a usage object', async () => { + apiRequestSpy.mockResolvedValue({ + data: [{ b64_json: 'base64encodedimagedata' }], + usage: { + input_tokens: 350, + output_tokens: 4160, + total_tokens: 4510, + input_tokens_details: { text_tokens: 27, image_tokens: 323 }, + }, + }); + + await execute.call(mockExecuteFunctions, 0); + + expect(accumulateTokenUsageMock).toHaveBeenCalledTimes(1); + expect(accumulateTokenUsageMock).toHaveBeenCalledWith(mockExecuteFunctions, 350, 4160); + }); + + it('should not report token usage when the API omits it, and still return the image', async () => { + apiRequestSpy.mockResolvedValue({ + data: [{ b64_json: 'base64encodedimagedata' }], + }); + + const result = await execute.call(mockExecuteFunctions, 0); + + expect(accumulateTokenUsageMock).not.toHaveBeenCalled(); + expect(result).toEqual([ + { + json: expect.objectContaining({ data: undefined }), + binary: { data: mockEditedBinaryData }, + pairedItem: { item: 0 }, + }, + ]); + }); + + it('should not report token usage when a proxy returns usage without the counts', async () => { + apiRequestSpy.mockResolvedValue({ + data: [{ b64_json: 'base64encodedimagedata' }], + usage: { total_tokens: 4510 }, + }); + + const result = await execute.call(mockExecuteFunctions, 0); + + expect(accumulateTokenUsageMock).not.toHaveBeenCalled(); + expect(result).toEqual([ + { + json: expect.objectContaining({ data: undefined }), + binary: { data: mockEditedBinaryData }, + pairedItem: { item: 0 }, + }, + ]); + }); + }); }); diff --git a/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/test/v2/actions/image/generate.operation.test.ts b/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/test/v2/actions/image/generate.operation.test.ts index 8f62613311e..420c62c36ad 100644 --- a/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/test/v2/actions/image/generate.operation.test.ts +++ b/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/test/v2/actions/image/generate.operation.test.ts @@ -7,6 +7,15 @@ import type { Mocked } from 'vitest'; vi.mock('../../../../transport'); +const { accumulateTokenUsageMock } = vi.hoisted(() => ({ + accumulateTokenUsageMock: vi.fn(), +})); + +vi.mock('n8n-workflow', async (importOriginal) => ({ + ...(await importOriginal()), + accumulateTokenUsage: accumulateTokenUsageMock, +})); + describe('Image Generate Operation', () => { let mockExecuteFunctions: Mocked; let mockNode: INode; @@ -264,4 +273,60 @@ describe('Image Generate Operation', () => { ); }); }); + + describe('token usage reporting', () => { + beforeEach(() => { + mockNode = makeNode(2.2); + mockExecuteFunctions.getNode.mockReturnValue(mockNode); + mockExecuteFunctions.getNodeParameter.mockImplementation( + (paramName: string, _i: unknown, _default: unknown, opts?: { extractValue?: boolean }) => { + if (paramName === 'modelId' && opts?.extractValue) return 'gpt-image-1'; + const params = { prompt: 'a cute cat', options: {} }; + return params[paramName as keyof typeof params]; + }, + ); + }); + + it('should report token usage when the API returns a usage object', async () => { + apiRequestSpy.mockResolvedValue({ + ...b64Response, + usage: { input_tokens: 42, output_tokens: 1568, total_tokens: 1610 }, + }); + + await execute.call(mockExecuteFunctions, 0); + + expect(accumulateTokenUsageMock).toHaveBeenCalledTimes(1); + expect(accumulateTokenUsageMock).toHaveBeenCalledWith(mockExecuteFunctions, 42, 1568); + }); + + it('should not report token usage when the API omits it, and still return the image', async () => { + apiRequestSpy.mockResolvedValue(b64Response); + + const result = await execute.call(mockExecuteFunctions, 0); + + expect(accumulateTokenUsageMock).not.toHaveBeenCalled(); + expect(result).toEqual([ + { + json: expect.objectContaining({ data: undefined }), + binary: { data: mockBinaryData }, + pairedItem: { item: 0 }, + }, + ]); + }); + + it('should not report token usage when a proxy returns usage without the counts', async () => { + apiRequestSpy.mockResolvedValue({ ...b64Response, usage: { total_tokens: 1610 } }); + + const result = await execute.call(mockExecuteFunctions, 0); + + expect(accumulateTokenUsageMock).not.toHaveBeenCalled(); + expect(result).toEqual([ + { + json: expect.objectContaining({ data: undefined }), + binary: { data: mockBinaryData }, + pairedItem: { item: 0 }, + }, + ]); + }); + }); }); diff --git a/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/test/v2/actions/text/response.operation.test.ts b/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/test/v2/actions/text/response.operation.test.ts index a815792e1e3..bf2b48e7407 100644 --- a/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/test/v2/actions/text/response.operation.test.ts +++ b/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/test/v2/actions/text/response.operation.test.ts @@ -1,8 +1,10 @@ import type { Tool } from '@langchain/classic/tools'; +import { createToolFromNode } from '@n8n/ai-utilities'; import type { IExecuteFunctions, INode } from 'n8n-workflow'; import { NodeOperationError } from 'n8n-workflow'; import type { Mocked, MockedFunction } from 'vitest'; import { mock, mockDeep } from 'vitest-mock-extended'; +import { z } from 'zod'; import { getConnectedTools } from '@utils/helpers'; @@ -264,6 +266,122 @@ describe('OpenAI Response Operation', () => { }); describe('Tool Calls', () => { + const createPgVectorTool = () => + createToolFromNode(mockNode, { + name: 'pgvector_search', + description: 'Search documents', + // NODE-5496: PGVector retrieve-as-tool requires an input object. + extraArgs: [{ key: 'input', description: 'Query to search for. Required' }], + func: vi.fn().mockResolvedValue('Matched document'), + }); + + it('should invoke a PGVector-style tool with a query object', async () => { + const tool = createPgVectorTool(); + + await expect(tool.invoke({ input: 'find documents' })).resolves.toBe('Matched document'); + }); + + it('should pass a query object to a PGVector-style tool from a function call', async () => { + const tool = createPgVectorTool(); + const initialResponse = { + id: 'resp_123', + status: 'completed', + output: [ + { + type: 'function_call', + call_id: 'call_123', + name: tool.name, + arguments: JSON.stringify({ input: 'find documents' }), + }, + ], + }; + const finalResponse = { + id: 'resp_456', + status: 'completed', + output: [ + { + type: 'message', + role: 'assistant', + content: [{ type: 'output_text', text: 'Found documents' }], + }, + ], + }; + + mockGetConnectedTools.mockResolvedValue([tool as Tool]); + mockCreateRequest.mockResolvedValue({ model: 'gpt-4o', input: [] }); + mockApiRequest.mockResolvedValue(finalResponse).mockResolvedValueOnce(initialResponse); + + await expect(execute.call(mockExecuteFunctions, 0)).resolves.toEqual([ + { json: finalResponse, pairedItem: { item: 0 } }, + ]); + expect(mockApiRequest).toHaveBeenCalledTimes(2); + expect(mockApiRequest).toHaveBeenNthCalledWith(2, 'POST', '/responses', { + body: expect.objectContaining({ + input: expect.arrayContaining([ + { type: 'function_call_output', call_id: 'call_123', output: 'Matched document' }, + ]), + }), + }); + }); + + it('should pass parsed data to the connected tool', async () => { + const tool = { + name: 'search', + schema: z.object({ input: z.string() }).transform(({ input }) => ({ input: input.trim() })), + invoke: vi.fn().mockResolvedValue('Matched document'), + } as unknown as Tool; + mockGetConnectedTools.mockResolvedValue([tool]); + mockCreateRequest.mockResolvedValue({ model: 'gpt-4o', input: [] }); + mockApiRequest + .mockResolvedValueOnce({ + id: 'resp_123', + status: 'completed', + output: [ + { + type: 'function_call', + call_id: 'call_123', + name: tool.name, + arguments: JSON.stringify({ input: ' find documents ' }), + }, + ], + }) + .mockResolvedValueOnce({ id: 'resp_456', status: 'completed', output: [] }); + + await execute.call(mockExecuteFunctions, 0); + + expect(tool.invoke).toHaveBeenCalledWith({ input: 'find documents' }); + }); + + it.each([ + ['missing', undefined], + ['raw', { type: 'object', properties: { input: { type: 'string' } } }], + ])('should report an unsupported %s tool schema', async (_kind, schema) => { + const tool = { name: 'search', schema, invoke: vi.fn() } as unknown as Tool; + mockGetConnectedTools.mockResolvedValue([tool]); + mockCreateRequest.mockResolvedValue({ model: 'gpt-4o', input: [] }); + mockApiRequest.mockResolvedValueOnce({ + id: 'resp_123', + status: 'completed', + output: [ + { + type: 'function_call', + call_id: 'call_123', + name: tool.name, + arguments: JSON.stringify({ input: 'find documents' }), + }, + ], + }); + + await expect(execute.call(mockExecuteFunctions, 0)).rejects.toMatchObject({ + name: 'NodeOperationError', + message: + 'The connected tool "search" has an unsupported input schema. Connect a tool with a Zod input schema.', + context: { itemIndex: 0 }, + }); + expect(tool.invoke).not.toHaveBeenCalled(); + expect(mockApiRequest).toHaveBeenCalledTimes(1); + }); + it('should execute tool calls with external tools', async () => { const mockTool = { name: 'test_tool', @@ -272,7 +390,7 @@ describe('OpenAI Response Operation', () => { typeName: 'ZodObject', _def: { typeName: 'ZodObject', shape: () => ({}) }, parse: vi.fn(), - safeParse: vi.fn(), + safeParse: vi.fn().mockReturnValue({ success: false }), }, call: vi.fn(), description: 'Test tool', @@ -332,7 +450,7 @@ describe('OpenAI Response Operation', () => { typeName: 'ZodObject', _def: { typeName: 'ZodObject', shape: () => ({}) }, parse: vi.fn(), - safeParse: vi.fn(), + safeParse: vi.fn().mockReturnValue({ success: false }), }, call: vi.fn(), description: 'Test tool', @@ -391,7 +509,7 @@ describe('OpenAI Response Operation', () => { typeName: 'ZodObject', _def: { typeName: 'ZodObject', shape: () => ({}) }, parse: vi.fn(), - safeParse: vi.fn(), + safeParse: vi.fn().mockReturnValue({ success: false }), }, call: vi.fn(), description: 'Test tool', @@ -437,7 +555,7 @@ describe('OpenAI Response Operation', () => { typeName: 'ZodObject', _def: { typeName: 'ZodObject', shape: () => ({}) }, parse: vi.fn(), - safeParse: vi.fn(), + safeParse: vi.fn().mockReturnValue({ success: false }), }, call: vi.fn(), description: 'Test tool', @@ -478,7 +596,7 @@ describe('OpenAI Response Operation', () => { typeName: 'ZodObject', _def: { typeName: 'ZodObject', shape: () => ({}) }, parse: vi.fn(), - safeParse: vi.fn(), + safeParse: vi.fn().mockReturnValue({ success: false }), }, call: vi.fn(), description: 'Test tool', @@ -565,7 +683,7 @@ describe('OpenAI Response Operation', () => { typeName: 'ZodObject', _def: { typeName: 'ZodObject', shape: () => ({}) }, parse: vi.fn(), - safeParse: vi.fn(), + safeParse: vi.fn().mockReturnValue({ success: false }), }, call: vi.fn(), description: 'Test tool', @@ -803,7 +921,7 @@ describe('OpenAI Response Operation', () => { typeName: 'ZodObject', _def: { typeName: 'ZodObject', shape: () => ({}) }, parse: vi.fn(), - safeParse: vi.fn(), + safeParse: vi.fn().mockReturnValue({ success: false }), }, call: vi.fn(), description: 'Test tool', @@ -840,7 +958,7 @@ describe('OpenAI Response Operation', () => { typeName: 'ZodObject', _def: { typeName: 'ZodObject', shape: () => ({}) }, parse: vi.fn(), - safeParse: vi.fn(), + safeParse: vi.fn().mockReturnValue({ success: false }), }, call: vi.fn(), description: 'Test tool', diff --git a/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/image/analyze.operation.ts b/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/image/analyze.operation.ts index 270224bb981..950d2f99c81 100644 --- a/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/image/analyze.operation.ts +++ b/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v2/actions/image/analyze.operation.ts @@ -8,6 +8,7 @@ import { NodeOperationError, updateDisplayOptions } from 'n8n-workflow'; import type { ResponseInputImage } from 'openai/resources/responses/responses'; import type { ChatContent, ChatResponse, ChatResponseRequest } from '../../../helpers/interfaces'; +import { accumulateImageTokenUsage } from '../../../helpers/token-usage'; import { apiRequest } from '../../../transport'; import { modelRLC } from '../descriptions'; import { getBinaryDataFile } from '../../../helpers/binary-data'; @@ -196,6 +197,8 @@ export async function execute(this: IExecuteFunctions, i: number): Promise ({ json: entry, @@ -122,7 +130,7 @@ export async function execute(this: IExecuteFunctions, i: number): Promise { name: 'hitl_tool', }); }); + + it('should mark a step that still carries HITL metadata as denied', () => { + const hitlAction = { + actionType: 'ExecutionNodeAction' as const, + nodeName: 'HITL Node', + input: { id: 'call_123', input: { query: 'test' } }, + type: NodeConnectionTypes.AiTool, + id: 'call_123', + metadata: { + itemIndex: 0, + hitl: { + toolName: 'hitl_tool', + gatedToolNodeName: 'Gated Tool', + originalInput: { query: 'test' }, + }, + }, + }; + const plainAction = { + actionType: 'ExecutionNodeAction' as const, + nodeName: 'Calculator', + input: { id: 'call_456', input: '1+1' }, + type: NodeConnectionTypes.AiTool, + id: 'call_456', + metadata: { itemIndex: 0 }, + }; + const data = { + data: { ai_tool: [[{ json: { output: 'done' } }]] }, + executionTime: 0, + startTime: 0, + executionIndex: 0, + source: [], + }; + const response: EngineResponse = { + actionResponses: [ + { action: hitlAction, data }, + { action: plainAction, data }, + ], + metadata: {}, + }; + + const result = buildSteps(response, itemIndex); + + expect(result).toHaveLength(2); + expect(result[0].action.hitlDenied).toBe(true); + expect(result[1].action).not.toHaveProperty('hitlDenied'); + }); + + it('should mark a step whose tool run failed as errored', () => { + const action = (id: string, nodeName: string) => ({ + actionType: 'ExecutionNodeAction' as const, + nodeName, + input: { id, input: { query: 'test' } }, + type: NodeConnectionTypes.AiTool, + id, + metadata: { itemIndex: 0 }, + }); + const base = { executionTime: 0, startTime: 0, executionIndex: 0, source: [] }; + const response: EngineResponse = { + actionResponses: [ + { + action: action('call_123', 'Genie'), + data: { + ...base, + data: {}, + error: { message: 'Space not found', name: 'NodeOperationError' } as any, + }, + }, + { + action: action('call_456', 'Calculator'), + data: { ...base, data: { ai_tool: [[{ json: { output: '2' } }]] } }, + }, + ], + metadata: {}, + }; + + const result = buildSteps(response, itemIndex); + + expect(result).toHaveLength(2); + expect(result[0].action.errored).toBe(true); + expect(result[0].observation).toContain('Space not found'); + expect(result[1].action).not.toHaveProperty('errored'); + }); }); describe('Tool input extraction', () => { diff --git a/packages/@n8n/nodes-langchain/utils/agent-execution/types.ts b/packages/@n8n/nodes-langchain/utils/agent-execution/types.ts index b9a48357ccb..2acbf3d764d 100644 --- a/packages/@n8n/nodes-langchain/utils/agent-execution/types.ts +++ b/packages/@n8n/nodes-langchain/utils/agent-execution/types.ts @@ -35,6 +35,10 @@ export type ToolCallData = { messageLog?: AIMessage[]; toolCallId: IDataObject | GenericValue | GenericValue[] | IDataObject[]; type: string | number | true | object; + /** True when the user denied this call in a Human-in-the-Loop node, so the tool never ran */ + hitlDenied?: boolean; + /** True when the tool run failed, so the observation is an error and not a result */ + errored?: boolean; }; observation: string; }; diff --git a/packages/@n8n/nodes-langchain/utils/sqlIdentifier.test.ts b/packages/@n8n/nodes-langchain/utils/sqlIdentifier.test.ts index 037d8151e89..f797e1b56db 100644 --- a/packages/@n8n/nodes-langchain/utils/sqlIdentifier.test.ts +++ b/packages/@n8n/nodes-langchain/utils/sqlIdentifier.test.ts @@ -2,6 +2,7 @@ import { escapeQualifiedSqlIdentifier, escapeSqlIdentifier, findUnsafeMetadataFilterKey, + findUnsupportedJsonPathFilterKey, isSafeQualifiedSqlIdentifier, isSafeSqlIdentifier, } from './sqlIdentifier'; @@ -97,4 +98,56 @@ describe('sqlIdentifier', () => { expect(findUnsafeMetadataFilterKey({ ok: '1', 'a\\b': '2' })).toBe('a\\b'); }); }); + + describe('findUnsupportedJsonPathFilterKey', () => { + it.each([ + ['a plain name', { userId: 'alice' }], + ['an underscored name', { user_id: 'alice' }], + ['a leading underscore', { _internal: true }], + ['mixed case', { UserID: 'alice' }], + ['trailing digits', { field2: 'x' }], + ['several names at once', { project: 'n8n', category: 'movies', author: 'a' }], + ['an array value', { author: ['a', 'b'] }], + ['an operator in value position', { rating: { $gte: 4.5 } }], + ['an operator the store does not know', { nested: { flag: true } }], + ['names nested under $and', { $and: [{ project: 'n8n' }, { language: 'en' }] }], + ['names nested under $or', { $or: [{ project: 'n8n' }] }], + ['no filter at all', undefined], + ])('accepts %s', (_name, filter) => { + expect(findUnsupportedJsonPathFilterKey(filter)).toBeUndefined(); + }); + + it.each([ + ['a quote', "x'"], + ['a backslash', 'a\\b'], + ['a double quote', 'a"b'], + ['a path predicate', 'userId?(@ == "bob")'], + ['a dot', 'user.id'], + ['a hyphen', 'file-name'], + ['a space', 'my key'], + ['a dollar sign', 'a$b'], + ['a leading digit', '1field'], + ['an empty name', ''], + ])('rejects %s', (_name, key) => { + expect(findUnsupportedJsonPathFilterKey({ [key]: 'value' })).toBe(key); + }); + + it('reports a name nested under $and', () => { + const filter = { $and: [{ project: 'n8n' }, { "x'": 'alice' }] }; + + expect(findUnsupportedJsonPathFilterKey(filter)).toBe("x'"); + }); + + it('reports a name nested under $or inside $and', () => { + const filter = { $and: [{ $or: [{ ok: 1 }, { 'a.b': 2 }] }] }; + + expect(findUnsupportedJsonPathFilterKey(filter)).toBe('a.b'); + }); + + it('reports the first unsupported name when several are present', () => { + const filter = { good: 1, "bad'one": 2, 'bad.two': 3 }; + + expect(findUnsupportedJsonPathFilterKey(filter)).toBe("bad'one"); + }); + }); }); diff --git a/packages/@n8n/nodes-langchain/utils/sqlIdentifier.ts b/packages/@n8n/nodes-langchain/utils/sqlIdentifier.ts index e58ee0d4905..0a8df0aed1d 100644 --- a/packages/@n8n/nodes-langchain/utils/sqlIdentifier.ts +++ b/packages/@n8n/nodes-langchain/utils/sqlIdentifier.ts @@ -1,3 +1,4 @@ +import { isRecord } from '@n8n/utils/is-record'; import pg from 'pg'; /** @@ -64,3 +65,39 @@ export function findUnsafeMetadataFilterKey( if (!filter) return undefined; return Object.keys(filter).find((key) => key.includes("'") || key.includes('\\')); } + +/** + * Matches a field name that Oracle accepts as an unquoted SQL/JSON path step. + * Oracle documents the unquoted form as a leading letter followed by letters and + * digits; underscore is allowed here because it is inert in both the path + * grammar and the surrounding string literal, and is common in existing keys. + */ +const SAFE_JSON_PATH_FIELD = /^[A-Za-z_][A-Za-z0-9_]*$/; + +/** + * Returns the first metadata-filter key that the Oracle store cannot resolve as + * an unquoted SQL/JSON path step, or undefined when every key is usable. + * + * Walks `$and` and `$or` because the store expands them before building the + * path, so a nested key reaches the same place a top-level one does. + */ +export function findUnsupportedJsonPathFilterKey(filter: unknown): string | undefined { + if (!isRecord(filter)) return undefined; + + for (const [key, value] of Object.entries(filter)) { + if (key === '$and' || key === '$or') { + if (!Array.isArray(value)) continue; + for (const condition of value) { + const unsupported = findUnsupportedJsonPathFilterKey(condition); + if (unsupported !== undefined) return unsupported; + } + continue; + } + + // Only the field name reaches the path. Operator names in value position + // are matched against a fixed set by the store, and values are bound. + if (!SAFE_JSON_PATH_FIELD.test(key)) return key; + } + + return undefined; +} diff --git a/packages/@n8n/nodes-langchain/utils/tool-error-result.ts b/packages/@n8n/nodes-langchain/utils/tool-error-result.ts new file mode 100644 index 00000000000..f757263cdd0 --- /dev/null +++ b/packages/@n8n/nodes-langchain/utils/tool-error-result.ts @@ -0,0 +1,21 @@ +import { isRecord } from '@n8n/utils/is-record'; + +/** + * Detect whether a tool result represents an error. + * + * In direct mode, N8nTool catches errors and returns `e.toString()` producing + * strings like `"NodeApiError: Bad request"`. ToolCode, ToolWorkflow and + * ToolHttpRequest catch their own errors and return `"There was an error: \"...\""`; + * ToolHttpRequest may prefix it with the status, `"HTTP 401 There was an error: \"...\""`. + * + * In queue mode, the job processor wraps errors as `{ error: { message, name } }`. + */ +export function isToolErrorResult(result: unknown): boolean { + if (isRecord(result) && 'error' in result) { + return isRecord(result.error) && typeof result.error.message === 'string'; + } + if (typeof result === 'string') { + return /^(\w+Error: |HTTP \d{3} There was an error: |There was an error: )/.test(result); + } + return false; +} diff --git a/packages/@n8n/permissions/package.json b/packages/@n8n/permissions/package.json index d925c93bfb0..b77ae5b947d 100644 --- a/packages/@n8n/permissions/package.json +++ b/packages/@n8n/permissions/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/permissions", - "version": "0.80.0", + "version": "0.81.0", "scripts": { "clean": "rimraf dist .turbo", "dev": "pnpm watch", diff --git a/packages/@n8n/permissions/src/__tests__/__snapshots__/scope-information.test.ts.snap b/packages/@n8n/permissions/src/__tests__/__snapshots__/scope-information.test.ts.snap index d7b31ad2522..e36a73f45f2 100644 --- a/packages/@n8n/permissions/src/__tests__/__snapshots__/scope-information.test.ts.snap +++ b/packages/@n8n/permissions/src/__tests__/__snapshots__/scope-information.test.ts.snap @@ -23,6 +23,16 @@ exports[`Scope Information > ensure scopes are defined correctly 1`] = ` "projectAiPreference:update", "projectAiPreference:delete", "projectAiPreference:list", + "skill:create", + "skill:read", + "skill:update", + "skill:delete", + "skill:list", + "projectSkill:create", + "projectSkill:read", + "projectSkill:update", + "projectSkill:delete", + "projectSkill:list", "annotationTag:create", "annotationTag:read", "annotationTag:update", @@ -204,5 +214,10 @@ exports[`Scope Information > ensure scopes are defined correctly 1`] = ` "roleMappingRule:delete", "roleMappingRule:list", "otel:manage", + "trustedSource:create", + "trustedSource:read", + "trustedSource:update", + "trustedSource:delete", + "trustedSource:list", ] `; diff --git a/packages/@n8n/permissions/src/constants.ee.ts b/packages/@n8n/permissions/src/constants.ee.ts index 0485a35b3e4..b74f4f13b4c 100644 --- a/packages/@n8n/permissions/src/constants.ee.ts +++ b/packages/@n8n/permissions/src/constants.ee.ts @@ -7,6 +7,10 @@ export const RESOURCES = { // `projectAiPreference`: rows of a project. A user's own rows need no scope. aiPreference: [...DEFAULT_OPERATIONS] as const, projectAiPreference: [...DEFAULT_OPERATIONS] as const, + // Skills. `skill`: instance skills. `projectSkill`: the skills of a project and of + // its agents. + skill: [...DEFAULT_OPERATIONS] as const, + projectSkill: [...DEFAULT_OPERATIONS] as const, annotationTag: [...DEFAULT_OPERATIONS] as const, auditLogs: ['manage'] as const, banner: ['dismiss'] as const, @@ -101,6 +105,7 @@ export const RESOURCES = { instanceAi: ['message', 'manage', 'gateway', 'eval'] as const, roleMappingRule: [...DEFAULT_OPERATIONS] as const, otel: ['manage'] as const, + trustedSource: [...DEFAULT_OPERATIONS] as const, } as const; export const API_KEY_RESOURCES = { diff --git a/packages/@n8n/permissions/src/roles/__tests__/skill-scope.test.ts b/packages/@n8n/permissions/src/roles/__tests__/skill-scope.test.ts new file mode 100644 index 00000000000..e8b1de2986a --- /dev/null +++ b/packages/@n8n/permissions/src/roles/__tests__/skill-scope.test.ts @@ -0,0 +1,100 @@ +import { RESOURCES } from '@/constants.ee'; +import { + GLOBAL_CUSTOM_ROLE_SCOPE_GROUPS, + PROJECT_CUSTOM_ROLE_OPERATIONS, +} from '@/roles/custom-role-scopes.ee'; +import { + GLOBAL_ADMIN_SCOPES, + GLOBAL_CHAT_USER_SCOPES, + GLOBAL_MEMBER_SCOPES, + GLOBAL_OWNER_SCOPES, +} from '@/roles/scopes/global-scopes.ee'; +import { + PERSONAL_PROJECT_OWNER_SCOPES, + PROJECT_EDITOR_SCOPES, + PROJECT_VIEWER_SCOPES, + REGULAR_PROJECT_ADMIN_SCOPES, +} from '@/roles/scopes/project-scopes.ee'; +import { scopeInformation } from '@/scope-information'; + +/** + * Skill scopes follow the AI preference split. `skill` covers instance skills. + * `projectSkill` covers the skills of one project and of its agents. Every user may read + * instance skills. + */ +describe('skill scopes', () => { + const write = ['create', 'update', 'delete']; + + it('offer the default operations on both resources', () => { + for (const resource of ['skill', 'projectSkill'] as const) { + expect(RESOURCES[resource]).toEqual( + expect.arrayContaining(['create', 'read', 'update', 'delete', 'list']), + ); + } + }); + + it('are granted in full to owners and admins, who manage instance skills', () => { + for (const scopes of [GLOBAL_OWNER_SCOPES, GLOBAL_ADMIN_SCOPES]) { + expect(scopes).toEqual( + expect.arrayContaining([ + ...['create', 'read', 'update', 'delete', 'list'].map((op) => `skill:${op}`), + ...['create', 'read', 'update', 'delete', 'list'].map((op) => `projectSkill:${op}`), + ]), + ); + } + }); + + it('are withheld from members and chat users, whose own skills need no scope', () => { + for (const scopes of [GLOBAL_MEMBER_SCOPES, GLOBAL_CHAT_USER_SCOPES]) { + expect( + scopes.filter((scope) => scope.startsWith('skill:') || scope.startsWith('projectSkill:')), + ).toEqual([]); + } + }); + + it('let project admins, personal owners and editors manage project skills', () => { + for (const scopes of [ + REGULAR_PROJECT_ADMIN_SCOPES, + PERSONAL_PROJECT_OWNER_SCOPES, + PROJECT_EDITOR_SCOPES, + ]) { + expect(scopes).toEqual( + expect.arrayContaining( + ['create', 'read', 'update', 'delete', 'list'].map((op) => `projectSkill:${op}`), + ), + ); + } + }); + + it('let project viewers only read and list project skills', () => { + expect(PROJECT_VIEWER_SCOPES).toEqual( + expect.arrayContaining(['projectSkill:read', 'projectSkill:list']), + ); + expect( + PROJECT_VIEWER_SCOPES.filter((scope) => write.some((op) => scope === `projectSkill:${op}`)), + ).toEqual([]); + }); + + it('can be given to custom roles, so a role without them cannot manage skills', () => { + expect(GLOBAL_CUSTOM_ROLE_SCOPE_GROUPS.settings.Manage).toEqual( + expect.arrayContaining(['skill:create', 'skill:read', 'skill:update', 'skill:delete']), + ); + expect(PROJECT_CUSTOM_ROLE_OPERATIONS.projectSkill).toEqual( + expect.arrayContaining(['read', 'update', 'create', 'delete']), + ); + }); + + it('are described, so the custom-role picker can label them', () => { + for (const scope of [ + 'skill:read', + 'skill:update', + 'projectSkill:read', + 'projectSkill:update', + ] as const) { + expect(scopeInformation[scope]).toEqual({ + displayName: expect.any(String), + description: expect.any(String), + }); + } + }); +}); diff --git a/packages/@n8n/permissions/src/roles/custom-role-scopes.ee.ts b/packages/@n8n/permissions/src/roles/custom-role-scopes.ee.ts index b5329b85d45..2048f374e8f 100644 --- a/packages/@n8n/permissions/src/roles/custom-role-scopes.ee.ts +++ b/packages/@n8n/permissions/src/roles/custom-role-scopes.ee.ts @@ -61,6 +61,7 @@ export const PROJECT_CUSTOM_ROLE_OPERATIONS = { ], projectVariable: ['read', 'update', 'create', 'delete'], projectAiPreference: ['read', 'update', 'create', 'delete'], + projectSkill: ['read', 'update', 'create', 'delete'], } as const satisfies { [R in keyof typeof RESOURCES]?: ReadonlyArray<(typeof RESOURCES)[R][number]>; }; @@ -113,6 +114,11 @@ export const GLOBAL_CUSTOM_ROLE_SCOPE_GROUPS = { 'aiPreference:update', 'aiPreference:delete', 'aiPreference:list', + 'skill:create', // Context (instance skills) + 'skill:read', + 'skill:update', + 'skill:delete', + 'skill:list', 'chatHub:manage', // Chat 'aiAssistant:manage', // n8n Assistant 'instanceAi:manage', diff --git a/packages/@n8n/permissions/src/roles/scopes/global-scopes.ee.ts b/packages/@n8n/permissions/src/roles/scopes/global-scopes.ee.ts index 70fa88a20b2..660f1c3118d 100644 --- a/packages/@n8n/permissions/src/roles/scopes/global-scopes.ee.ts +++ b/packages/@n8n/permissions/src/roles/scopes/global-scopes.ee.ts @@ -109,6 +109,16 @@ export const GLOBAL_OWNER_SCOPES: Scope[] = [ 'projectAiPreference:update', 'projectAiPreference:delete', 'projectAiPreference:list', + 'skill:create', + 'skill:read', + 'skill:update', + 'skill:delete', + 'skill:list', + 'projectSkill:create', + 'projectSkill:read', + 'projectSkill:update', + 'projectSkill:delete', + 'projectSkill:list', 'workflow:create', 'workflow:read', 'workflow:export', @@ -192,6 +202,11 @@ export const GLOBAL_OWNER_SCOPES: Scope[] = [ 'roleMappingRule:delete', 'roleMappingRule:list', 'otel:manage', + 'trustedSource:create', + 'trustedSource:read', + 'trustedSource:update', + 'trustedSource:delete', + 'trustedSource:list', ]; export const GLOBAL_ADMIN_SCOPES = GLOBAL_OWNER_SCOPES.concat(); @@ -227,6 +242,7 @@ export const GLOBAL_MEMBER_SCOPES: Scope[] = [ 'credentialResolver:list', 'instanceAi:message', 'instanceAi:gateway', + 'trustedSource:list', ]; export const GLOBAL_CHAT_USER_SCOPES: Scope[] = [ diff --git a/packages/@n8n/permissions/src/roles/scopes/project-scopes.ee.ts b/packages/@n8n/permissions/src/roles/scopes/project-scopes.ee.ts index ea1e7cf11c7..747ccc57517 100644 --- a/packages/@n8n/permissions/src/roles/scopes/project-scopes.ee.ts +++ b/packages/@n8n/permissions/src/roles/scopes/project-scopes.ee.ts @@ -85,6 +85,11 @@ export const REGULAR_PROJECT_ADMIN_SCOPES: Scope[] = [ 'projectAiPreference:create', 'projectAiPreference:update', 'projectAiPreference:delete', + 'projectSkill:list', + 'projectSkill:read', + 'projectSkill:create', + 'projectSkill:update', + 'projectSkill:delete', ]; export const PERSONAL_PROJECT_OWNER_SCOPES: Scope[] = [ @@ -146,6 +151,11 @@ export const PERSONAL_PROJECT_OWNER_SCOPES: Scope[] = [ 'projectAiPreference:create', 'projectAiPreference:update', 'projectAiPreference:delete', + 'projectSkill:list', + 'projectSkill:read', + 'projectSkill:create', + 'projectSkill:update', + 'projectSkill:delete', ]; export const PROJECT_EDITOR_SCOPES: Scope[] = [ @@ -208,6 +218,11 @@ export const PROJECT_EDITOR_SCOPES: Scope[] = [ 'projectAiPreference:create', 'projectAiPreference:update', 'projectAiPreference:delete', + 'projectSkill:list', + 'projectSkill:read', + 'projectSkill:create', + 'projectSkill:update', + 'projectSkill:delete', ]; export const PROJECT_VIEWER_SCOPES: Scope[] = [ @@ -236,6 +251,8 @@ export const PROJECT_VIEWER_SCOPES: Scope[] = [ 'projectVariable:read', 'projectAiPreference:list', 'projectAiPreference:read', + 'projectSkill:list', + 'projectSkill:read', ]; export const PROJECT_CHAT_USER_SCOPES: Scope[] = ['agent:execute', 'workflow:execute-chat']; diff --git a/packages/@n8n/permissions/src/scope-information.ts b/packages/@n8n/permissions/src/scope-information.ts index eadd6f66a40..58fc6d52dd8 100644 --- a/packages/@n8n/permissions/src/scope-information.ts +++ b/packages/@n8n/permissions/src/scope-information.ts @@ -27,6 +27,22 @@ export const scopeInformation: Partial> = { description: 'Allows reading the AI preferences saved for the instance, the user, and their projects.', }, + 'skill:read': { + displayName: 'Read Skills', + description: 'Allows reading instance skills.', + }, + 'skill:update': { + displayName: 'Update Skills', + description: 'Allows editing and saving instance skills.', + }, + 'projectSkill:read': { + displayName: 'Read Project Skills', + description: 'Allows reading the skills of a project.', + }, + 'projectSkill:update': { + displayName: 'Update Project Skills', + description: 'Allows editing and saving the skills of a project.', + }, 'agent:create': { displayName: 'Create Agent', description: 'Allows creating new agents in a project.', diff --git a/packages/@n8n/permissions/src/utilities/__tests__/get-resource-permissions.test.ts b/packages/@n8n/permissions/src/utilities/__tests__/get-resource-permissions.test.ts index 133c1a8b896..8def00c65db 100644 --- a/packages/@n8n/permissions/src/utilities/__tests__/get-resource-permissions.test.ts +++ b/packages/@n8n/permissions/src/utilities/__tests__/get-resource-permissions.test.ts @@ -10,6 +10,8 @@ describe('permissions', () => { aiAssistant: {}, aiPreference: {}, projectAiPreference: {}, + skill: {}, + projectSkill: {}, annotationTag: {}, auditLogs: {}, banner: {}, @@ -58,6 +60,7 @@ describe('permissions', () => { roleMappingRule: {}, otel: {}, scim: {}, + trustedSource: {}, }); }); it('getResourcePermissions', () => { @@ -101,6 +104,8 @@ describe('permissions', () => { aiAssistant: {}, aiPreference: {}, projectAiPreference: {}, + skill: {}, + projectSkill: {}, annotationTag: {}, auditLogs: {}, banner: {}, @@ -193,6 +198,7 @@ describe('permissions', () => { roleMappingRule: {}, otel: {}, scim: {}, + trustedSource: {}, }; expect(getResourcePermissions(scopes)).toEqual(permissionRecord); diff --git a/packages/@n8n/scan-community-package/package.json b/packages/@n8n/scan-community-package/package.json index 4a8438c8a44..3fe381d2400 100644 --- a/packages/@n8n/scan-community-package/package.json +++ b/packages/@n8n/scan-community-package/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/scan-community-package", - "version": "0.38.0", + "version": "0.39.0", "description": "Static code analyser for n8n community packages", "license": "LicenseRef-n8n-sustainable-use", "bin": "scanner/cli.mjs", diff --git a/packages/@n8n/scheduler/README.md b/packages/@n8n/scheduler/README.md index 5c76a1ab4a1..f0cbcf55931 100644 --- a/packages/@n8n/scheduler/README.md +++ b/packages/@n8n/scheduler/README.md @@ -50,9 +50,10 @@ functions and configuration, and the scheduler composes its algorithms over them test in isolation with a fake store. The work is split into a few focused submodules, described below. -Everything sits behind the `N8N_SCHEDULER_ENABLED` flag (off by default). Turning -it off reverts n8n to its previous in-memory scheduling, which is the rollback -path during rollout. +Everything sits behind the `N8N_SCHEDULER_ENABLED` flag (on by default). Schedule +Trigger nodes move to the durable scheduler only while the workflow publication +service is also on. Turning the flag off reverts n8n to its previous in-memory +scheduling. ## The moving parts diff --git a/packages/@n8n/scheduler/package.json b/packages/@n8n/scheduler/package.json index 961df54180d..41da4534ba8 100644 --- a/packages/@n8n/scheduler/package.json +++ b/packages/@n8n/scheduler/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/scheduler", - "version": "1.12.0", + "version": "1.13.0", "scripts": { "clean": "rimraf dist .turbo", "dev": "pnpm watch", diff --git a/packages/@n8n/task-runner/package.json b/packages/@n8n/task-runner/package.json index fa1cc353ed6..a81e37e3519 100644 --- a/packages/@n8n/task-runner/package.json +++ b/packages/@n8n/task-runner/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/task-runner", - "version": "2.43.0", + "version": "2.44.0", "scripts": { "clean": "rimraf dist .turbo", "start": "node dist/start.js", diff --git a/packages/@n8n/task-runner/src/js-task-runner/__tests__/js-task-runner.test.ts b/packages/@n8n/task-runner/src/js-task-runner/__tests__/js-task-runner.test.ts index 3df9108a406..98bc2814460 100644 --- a/packages/@n8n/task-runner/src/js-task-runner/__tests__/js-task-runner.test.ts +++ b/packages/@n8n/task-runner/src/js-task-runner/__tests__/js-task-runner.test.ts @@ -193,6 +193,34 @@ describe('JsTaskRunner', () => { expect(outcome.result).toEqual([wrapIntoJson({ allZeros: true })]); }); + it('should give small buffers their own backing memory', async () => { + const outcome = await executeForAllItems({ + code: ` + const fromString = Buffer.from('.'); + const fromArray = Buffer.from([1, 2]); + return [{ json: { + fromString: fromString.buffer.byteLength, + fromArray: fromArray.buffer.byteLength, + } }] + `, + inputItems: [{ a: 1 }], + }); + + expect(outcome.result).toEqual([wrapIntoJson({ fromString: 1, fromArray: 2 })]); + }); + + it('should prevent guest code from re-enabling the buffer pool', async () => { + const outcome = await executeForAllItems({ + code: ` + Buffer.poolSize = 8192; + return [{ json: { poolSize: Buffer.poolSize } }] + `, + inputItems: [{ a: 1 }], + }); + + expect(outcome.result).toEqual([wrapIntoJson({ poolSize: 0 })]); + }); + it('should support Buffer.from and Buffer.concat', async () => { const outcome = await executeForAllItems({ code: ` diff --git a/packages/@n8n/task-runner/src/js-task-runner/js-task-runner.ts b/packages/@n8n/task-runner/src/js-task-runner/js-task-runner.ts index fbfbd168d25..19b10e99104 100644 --- a/packages/@n8n/task-runner/src/js-task-runner/js-task-runner.ts +++ b/packages/@n8n/task-runner/src/js-task-runner/js-task-runner.ts @@ -186,6 +186,9 @@ export class JsTaskRunner extends TaskRunner { const safeAlloc = Buffer.alloc.bind(Buffer); Buffer.allocUnsafe = safeAlloc; Buffer.allocUnsafeSlow = safeAlloc; + // Disable the shared buffer pool so small buffers get their own backing memory. + // Use defineProperty so the value is read-only: sandboxed code must not re-enable the pool. + Object.defineProperty(Buffer, 'poolSize', { value: 0, writable: false, configurable: false }); if (process.env.NODE_ENV !== 'test') { freezeGlobals(); diff --git a/packages/@n8n/telemetry/package.json b/packages/@n8n/telemetry/package.json index e4e08b9de6c..ab6bcba0e53 100644 --- a/packages/@n8n/telemetry/package.json +++ b/packages/@n8n/telemetry/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/telemetry", - "version": "1.11.0", + "version": "1.12.0", "scripts": { "clean": "rimraf dist .turbo", "dev": "pnpm watch", diff --git a/packages/@n8n/telemetry/src/events/agents.ts b/packages/@n8n/telemetry/src/events/agents.ts index 4c6cef4470e..63ac3fe2ed0 100644 --- a/packages/@n8n/telemetry/src/events/agents.ts +++ b/packages/@n8n/telemetry/src/events/agents.ts @@ -193,6 +193,38 @@ const agentPublish = { }; export const AGENTS_TELEMETRY = defineTelemetryEvents({ + AGENT_TEAMS_SETUP_STEP: { + name: 'Agent Teams setup step', + description: + "One step of the recommended Microsoft Teams setup finished or failed. Tells us which rung of the bot ladder people actually land on, which is the question the ladder exists to answer: n8n can only create the bot when the tenant has an Azure subscription, and a Microsoft 365 tenant does not come with one. `outcome: 'failed'` carries a `reason` naming the wall that was hit, never the message.", + properties: z.object({ + agent_id: z.string(), + project_id: z.string(), + user_id: z.string(), + step: z + .enum(['connect', 'create_app', 'create_bot', 'availability', 'install']) + .describe('Which step of the recommended setup this reports'), + outcome: z.enum(['succeeded', 'failed']), + bot_route: z + .enum(['provisioned', 'manual']) + .optional() + .describe( + "Only on the bot step. 'provisioned' means n8n created it through Azure; 'manual' means the user was sent to make it themselves.", + ), + install_route: z + .enum(['published', 'submitted', 'upload']) + .optional() + .describe( + "Only on the install step. 'submitted' means the account could not publish directly and the app went in for review.", + ), + reason: z + .string() + .optional() + .describe( + 'A fixed code for why the step failed, such as blocked_by_policy or cannot_register_apps. Never a message, which could carry tenant detail.', + ), + }), + }, USER_RESPONDED_TO_AGENT_TOOL_APPROVAL: { name: 'User responded to agent tool approval', description: @@ -390,6 +422,16 @@ export const AGENTS_TELEMETRY = defineTelemetryEvents({ event_version: z.literal('1'), }), }, + USER_DISMISSED_AGENT_PUBLISHED_MODAL: { + name: 'User dismissed agent published modal', + description: + 'The user closed the "Agent published" confirmation modal shown after a successful agent publish. `dont_show_again` reports the state of the "Don\'t show again" checkbox at dismissal; when checked, the modal is not shown on later publishes.', + properties: z.object({ + agent_id: z.string(), + dont_show_again: z.boolean(), + session_id: sessionId.optional(), + }), + }, INSTANCE_AI_OPENED_FROM_AGENT_PREVIEW: { name: 'Instance AI opened from agent preview', description: diff --git a/packages/@n8n/telemetry/src/events/credentials.ts b/packages/@n8n/telemetry/src/events/credentials.ts index 14054e553bd..0e1f45692c2 100644 --- a/packages/@n8n/telemetry/src/events/credentials.ts +++ b/packages/@n8n/telemetry/src/events/credentials.ts @@ -111,4 +111,14 @@ export const CREDENTIALS_TELEMETRY = defineTelemetryEvents({ ), }), }, + USER_OPENED_CREDENTIAL_SHARING_FROM_REDACTED_DATA: { + name: 'User opened credential sharing from redacted data', + description: + 'A user who can share a credential but cannot use it clicked the link on redacted execution data that opens its sharing tab. Fires once per click.', + properties: z.object({ + credential_id: z.string(), + workflow_id: z.string(), + execution_id: z.string().optional(), + }), + }, }); diff --git a/packages/@n8n/telemetry/src/events/expressions.ts b/packages/@n8n/telemetry/src/events/expressions.ts new file mode 100644 index 00000000000..c91535f1a5b --- /dev/null +++ b/packages/@n8n/telemetry/src/events/expressions.ts @@ -0,0 +1,57 @@ +import { z } from 'zod/v4'; + +import { defineTelemetryEvents } from '../define'; + +const mismatchOutcome = z.enum(['different', 'legacy_ok_quickjs_error', 'legacy_error_quickjs_ok']); + +export const EXPRESSIONS_TELEMETRY = defineTelemetryEvents({ + EXPRESSION_ENGINE_SHADOW_RUN_REPORTED: { + name: 'Expression engine shadow run reported', + // Experiment cleanup: remove with quickjsExpressionShadow (126_quickjs_expression_shadow). + description: + 'The editor evaluated a sample of expressions with the QuickJS engine next to the legacy engine, and reported the aggregated comparison. Sent every few minutes while the shadow run has new data, and when the tab is hidden. It never carries expression text or values.', + properties: z.object({ + init_status: z + .enum(['ready', 'failed']) + .describe('Whether the QuickJS shadow engine started'), + init_duration_ms: z.number().describe('Time to load and start the QuickJS shadow engine'), + sample_rate: z.number().describe('One in this many legacy evaluations also runs in QuickJS'), + timeout_ms: z.number().describe('QuickJS timeout for one shadow evaluation'), + evaluations: z + .number() + .describe('Distinct expressions compared in this report, up to 5000; repeats count once'), + same: z.number(), + different: z.number(), + unchecked: z + .number() + .describe( + 'Both engines succeeded, but the values were not compared: the expression is non-deterministic or the value is too large', + ), + legacy_ok_quickjs_error: z.number(), + legacy_error_quickjs_ok: z.number(), + both_error: z.number(), + quickjs_timeouts: z + .number() + .describe( + 'Sampled runs where QuickJS hit its timeout. Every run counts, not once per expression', + ), + latency_bucket_bounds_ms: z + .array(z.number()) + .describe('Upper bounds of the latency buckets; the last bucket has no upper bound'), + legacy_latency_buckets: z.array(z.number()), + quickjs_latency_buckets: z.array(z.number()), + mismatches: z + .array( + z.object({ + outcome: mismatchOutcome, + skeleton: z.string().describe('The expression without field names, strings or numbers'), + legacy_type: z.string(), + quickjs_type: z.string(), + error_class: z.string().optional(), + count: z.number(), + }), + ) + .describe('Distinct mismatch shapes, capped per report'), + }), + }, +}); diff --git a/packages/@n8n/telemetry/src/events/instance.ts b/packages/@n8n/telemetry/src/events/instance.ts index a30b37330a6..96d4963986a 100644 --- a/packages/@n8n/telemetry/src/events/instance.ts +++ b/packages/@n8n/telemetry/src/events/instance.ts @@ -44,7 +44,6 @@ export const INSTANCE_TELEMETRY = defineTelemetryEvents({ }), workflow_history: z.object({ compaction_optimizing_time_window_hours: z.number(), - compaction_trim_on_start_up: z.boolean(), compaction_trimming_time_window_days: z.number(), }), n8n_deployment_type: z.string(), diff --git a/packages/@n8n/telemetry/src/telemetry-events.ts b/packages/@n8n/telemetry/src/telemetry-events.ts index e31b96aa5ac..8706158832d 100644 --- a/packages/@n8n/telemetry/src/telemetry-events.ts +++ b/packages/@n8n/telemetry/src/telemetry-events.ts @@ -2,6 +2,7 @@ import type { TelemetryEventRegistry } from './define'; import { AGENTS_TELEMETRY } from './events/agents'; import { CONTEXT_TELEMETRY } from './events/context'; import { CREDENTIALS_TELEMETRY } from './events/credentials'; +import { EXPRESSIONS_TELEMETRY } from './events/expressions'; import { INSTANCE_TELEMETRY } from './events/instance'; import { INSTANCE_AI_TELEMETRY } from './events/instance-ai'; import { MCP_TELEMETRY } from './events/mcp'; @@ -18,6 +19,7 @@ export const TELEMETRY_EVENT = { AGENTS: AGENTS_TELEMETRY, CREDENTIALS: CREDENTIALS_TELEMETRY, CONTEXT: CONTEXT_TELEMETRY, + EXPRESSIONS: EXPRESSIONS_TELEMETRY, INSTANCE: INSTANCE_TELEMETRY, INSTANCE_AI: INSTANCE_AI_TELEMETRY, MCP: MCP_TELEMETRY, diff --git a/packages/@n8n/tournament/src/ExpressionSplitter.ts b/packages/@n8n/tournament/src/ExpressionSplitter.ts index 10970b0564f..0c27b0f09e9 100644 --- a/packages/@n8n/tournament/src/ExpressionSplitter.ts +++ b/packages/@n8n/tournament/src/ExpressionSplitter.ts @@ -17,7 +17,7 @@ const OPEN_BRACKET = /(?\{\{)/; const CLOSE_BRACKET = /(?\}\})/; export const escapeCode = (text: string): string => { - return text.replace('\\}}', '}}'); + return text.replace(/\\\}\}/g, '}}'); }; const normalizeBackslashes = (text: string): string => { @@ -99,7 +99,7 @@ export const splitExpression = (expression: string): ExpressionChunk[] => { // Expressions only have closing brackets escaped const escapeTmplExpression = (part: string) => { - return part.replace('}}', '\\}}'); + return part.replace(/\}\}/g, '\\}}'); }; export const joinExpression = (parts: ExpressionChunk[]): string => { diff --git a/packages/@n8n/tournament/test/Expression.test.ts b/packages/@n8n/tournament/test/Expression.test.ts index b336b133334..3430933695c 100644 --- a/packages/@n8n/tournament/test/Expression.test.ts +++ b/packages/@n8n/tournament/test/Expression.test.ts @@ -14,4 +14,8 @@ describe('Expression', () => { evaluator.execute('{{ import("").then(fs => fs.writeFileSync("/tmp/flag", "flag")) }}', {}), ).toThrow('Imports are not supported'); }); + + test('Should unescape every escaped closing bracket', () => { + expect(evaluator.execute('{{ [{ a: { b: 1 \\}}, { a: { b: 2 \\}}][1].a.b }}', {})).toBe(2); + }); }); diff --git a/packages/@n8n/tournament/test/ExpressionSplitter.test.ts b/packages/@n8n/tournament/test/ExpressionSplitter.test.ts index 82db09dd4ae..93bc646e926 100644 --- a/packages/@n8n/tournament/test/ExpressionSplitter.test.ts +++ b/packages/@n8n/tournament/test/ExpressionSplitter.test.ts @@ -43,6 +43,13 @@ describe('tmpl Expression Parser', () => { ]); }); + test('Multiple escaped closing brackets', () => { + expect(splitExpression('{{ [{ a: { b: 1 \\}}, { a: { b: 2 \\}}] }}')).toEqual([ + { type: 'text', text: '' }, + { type: 'code', text: ' [{ a: { b: 1 }}, { a: { b: 2 }}] ', hasClosingBrackets: true }, + ]); + }); + test('Escaped backslashes before double opening curly braces', () => { const expr = 'C:\\\\Users\\\\Administrator\\\\Desktop\\\\abc\\\\{{ $json.files[0].fileName }}'; @@ -92,5 +99,14 @@ describe('tmpl Expression Parser', () => { 'test {{ code.test("\\}}") }}', ); }); + + test('Multiple escaped closing brackets', () => { + expect( + joinExpression([ + { type: 'text', text: '' }, + { type: 'code', text: ' [{ a: { b: 1 }}, { a: { b: 2 }}] ', hasClosingBrackets: true }, + ]), + ).toEqual('{{ [{ a: { b: 1 \\}}, { a: { b: 2 \\}}] }}'); + }); }); }); diff --git a/packages/@n8n/utils/package.json b/packages/@n8n/utils/package.json index 921065975b3..9bf1ebe4103 100644 --- a/packages/@n8n/utils/package.json +++ b/packages/@n8n/utils/package.json @@ -1,7 +1,7 @@ { "name": "@n8n/utils", "type": "module", - "version": "1.50.0", + "version": "1.51.0", "files": [ "dist" ], diff --git a/packages/@n8n/workflow-sdk/package.json b/packages/@n8n/workflow-sdk/package.json index c1b89414b2c..fb82e25e54b 100644 --- a/packages/@n8n/workflow-sdk/package.json +++ b/packages/@n8n/workflow-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/workflow-sdk", - "version": "0.36.0", + "version": "0.37.0", "description": "TypeScript SDK for programmatically creating n8n workflows", "exports": { ".": { diff --git a/packages/@n8n/workflow-sdk/src/generate-types/generate-types.test.ts b/packages/@n8n/workflow-sdk/src/generate-types/generate-types.test.ts index 24ef4090e5b..a7e8914e727 100644 --- a/packages/@n8n/workflow-sdk/src/generate-types/generate-types.test.ts +++ b/packages/@n8n/workflow-sdk/src/generate-types/generate-types.test.ts @@ -4470,6 +4470,179 @@ describe('generate-types', () => { expect(content).toContain('output?: Items'); }); + describe('parameter variants', () => { + const combo = { resource: 'ticket', operation: 'get' }; + const plainSchema = { type: 'object', properties: { From: { type: 'string' } } }; + const rawVariant = { + resource: 'ticket', + operation: 'get', + variant: 'simple-false', + schema: { type: 'object', properties: { text: { type: 'string' } } }, + }; + const nodeWithSimple: NodeTypeDescription = { + ...mockFreshserviceNode, + properties: [ + ...mockFreshserviceNode.properties, + { + displayName: 'Simplify', + name: 'simple', + type: 'boolean', + default: true, + displayOptions: { show: { resource: ['ticket'], operation: ['get'] } }, + }, + ], + }; + + const generate = (variants: Array, node = nodeWithSimple) => + generateTypes.generateDiscriminatorFile( + node, + 1, + combo, + generateTypes.getPropertiesForCombination(node, combo), + plainSchema, + 6, + variants, + ); + + it('emits an output type for each variant and keeps the plain one for the default', () => { + const content = generate([rawVariant]); + + expect(content).toContain('export type FreshserviceV1TicketGetOutput = {'); + expect(content).toContain('From?: string;'); + expect(content).toContain('export type FreshserviceV1TicketGetSimpleFalseOutput = {'); + expect(content).toContain('text?: string;'); + }); + + it('emits one node type for each parameter value, narrowing the parameter', () => { + const content = generate([rawVariant]); + + expect(content).toContain('export type FreshserviceV1TicketGetSimpleTrueNode = {'); + expect(content).toContain( + 'config: NodeConfig', + ); + expect(content).toContain('output?: Items;'); + expect(content).toContain('export type FreshserviceV1TicketGetSimpleFalseNode = {'); + expect(content).toContain( + 'config: NodeConfig', + ); + expect(content).toContain('output?: Items;'); + }); + + it('returns either output when the parameter is an expression', () => { + const content = generate([rawVariant]); + + expect(content).toContain('export type FreshserviceV1TicketGetSimpleExpressionNode = {'); + expect(content).toContain( + 'config: NodeConfig }>', + ); + expect(content).toContain( + 'output?: Items;', + ); + }); + + it('exports the node type as a union of the parameter variants', () => { + const content = generate([rawVariant]); + + expect(content).toMatch( + /export type FreshserviceV1TicketGetNode =\s+\| FreshserviceV1TicketGetSimpleTrueNode\s+\| FreshserviceV1TicketGetSimpleFalseNode\s+\| FreshserviceV1TicketGetSimpleExpressionNode;/, + ); + }); + + it('ignores a variant whose parameter the node does not have', () => { + const content = generate( + [{ ...rawVariant, variant: 'unknown-false' }], + mockFreshserviceNode, + ); + + expect(content).toContain('export type FreshserviceV1TicketGetNode = {'); + expect(content).not.toContain('SimpleFalse'); + }); + + describe('options parameters', () => { + const nodeWithOptions = ( + values: Array, + ): NodeTypeDescription => ({ + ...mockFreshserviceNode, + properties: [ + ...mockFreshserviceNode.properties, + { + displayName: 'Format', + name: 'format', + type: 'options', + default: values[0], + options: values.map((value) => ({ name: String(value), value })), + displayOptions: { show: { resource: ['ticket'], operation: ['get'] } }, + }, + ], + }); + const modeVariant = (value: string) => ({ + ...rawVariant, + variant: `format-${value}`, + }); + + it('keeps the numeric type of numeric option values', () => { + const content = generate([modeVariant('1')], nodeWithOptions([0, 1])); + + expect(content).toContain('{ format?: 0 }'); + expect(content).toContain('{ format: 1 }'); + expect(content).toContain('{ format: Expression }'); + expect(content).not.toContain("'1'"); + }); + + it('keeps string option values as string literals', () => { + const content = generate([modeVariant('slow')], nodeWithOptions(['fast', 'slow'])); + + expect(content).toContain("{ format?: 'fast' }"); + expect(content).toContain("{ format: 'slow' }"); + expect(content).toContain('{ format: Expression }'); + }); + + it('ignores a variant whose value is not a number for numeric options', () => { + const content = generate([modeVariant('slow')], nodeWithOptions([0, 1])); + + expect(content).toContain('export type FreshserviceV1TicketGetNode = {'); + expect(content).not.toContain('FormatSlow'); + }); + + it('ignores a variant whose value would not be a safe type literal', () => { + const content = generate([modeVariant("x'y")], nodeWithOptions(['fast', "x'y"])); + + expect(content).toContain('export type FreshserviceV1TicketGetNode = {'); + }); + + it('gives negative and positive numeric values different type names', () => { + const content = generate( + [modeVariant('-1'), modeVariant('1')], + nodeWithOptions([0, -1, 1]), + ); + + expect(content).toContain('{ format: -1 }'); + expect(content).toContain('{ format: 1 }'); + expect(content.match(/export type FreshserviceV1TicketGetFormat1Node =/g)).toHaveLength( + 1, + ); + expect(content).toContain('export type FreshserviceV1TicketGetFormatMinus1Node ='); + }); + + it('ignores the variants when two values would get the same type name', () => { + const content = generate( + [modeVariant('a-b'), modeVariant('a_b')], + nodeWithOptions(['fast', 'a-b', 'a_b']), + ); + + expect(content).toContain('export type FreshserviceV1TicketGetNode = {'); + }); + + it('types the variants of a boolean-valued options parameter', () => { + const content = generate([modeVariant('false')], nodeWithOptions([true, false])); + + expect(content).toContain('{ format?: true }'); + expect(content).toContain('{ format: false }'); + expect(content).toContain('{ format: Expression }'); + }); + }); + }); + it('should inline credentials interface when node has credentials', () => { const combo = { resource: 'ticket', operation: 'get' }; const props = generateTypes.getPropertiesForCombination(mockFreshserviceNode, combo); @@ -5625,6 +5798,61 @@ describe('generate-types', () => { }); }); + describe('jsonSchemaToTypeScript with additionalProperties', () => { + it('adds an index signature when an object has properties and an additionalProperties schema', () => { + const result = generateTypes.jsonSchemaToTypeScript({ + type: 'object', + properties: { id: { type: 'string' } }, + additionalProperties: { type: ['number', 'null'] }, + }); + + expect(result).toContain('id?: string;'); + expect(result).toContain('[key: string]: number | null | string | undefined;'); + }); + + it('keeps the declared property types in the index signature union once', () => { + const result = generateTypes.jsonSchemaToTypeScript({ + type: 'object', + properties: { id: { type: 'string' }, name: { type: 'string' } }, + additionalProperties: { type: 'string' }, + }); + + expect(result).toContain('[key: string]: string | undefined;'); + }); + + it('keeps nested object types intact in the index signature union', () => { + const result = generateTypes.jsonSchemaToTypeScript({ + type: 'object', + properties: { date: { type: 'object', properties: { end: { type: ['string', 'null'] } } } }, + additionalProperties: { type: ['string', 'null'] }, + }); + + expect(result).toContain('end?: string | null;'); + expect(result).toMatch( + /\[key: string\]: string \| null \| \{[\s\S]*end\?: string \| null;[\s\S]*\} \| undefined;/, + ); + }); + + it('does not add an index signature for additionalProperties: true', () => { + const result = generateTypes.jsonSchemaToTypeScript({ + type: 'object', + properties: { id: { type: 'string' } }, + additionalProperties: true, + }); + + expect(result).not.toContain('[key: string]'); + }); + + it('still emits a Record when an object has only additionalProperties', () => { + const result = generateTypes.jsonSchemaToTypeScript({ + type: 'object', + additionalProperties: { type: 'number' }, + }); + + expect(result).toBe('Record'); + }); + }); + describe('discoverSchemasForNode', () => { // Use real filesystem with temp directories under NODES_BASE_DIST const NODES_BASE_DIST = path.resolve(__dirname, '../../../../nodes-base/dist/nodes'); @@ -5678,6 +5906,39 @@ describe('generate-types', () => { } }); + it('discovers .-.json files as variants, not as operations', () => { + const nodeName = '__TestParameterVariants__'; + const plain = { type: 'object', properties: { From: { type: 'string' } } }; + const raw = { type: 'object', properties: { text: { type: 'string' } } }; + + try { + createTestSchemaDir(nodeName, 'v1.0.0', { + 'message/get.json': JSON.stringify(plain), + 'message/get.simple-false.json': JSON.stringify(raw), + }); + + const result = generateTypes.discoverSchemasForNode( + `n8n-nodes-base.${nodeName}`, + 1, + nodeName, + ); + + expect(result).toHaveLength(2); + expect(result).toContainEqual({ resource: 'message', operation: 'get', schema: plain }); + expect(result).toContainEqual({ + resource: 'message', + operation: 'get', + variant: 'simple-false', + schema: raw, + }); + expect(generateTypes.findSchemaForOperation(result, 'message', 'get')?.schema).toEqual( + plain, + ); + } finally { + cleanupTestDir(nodeName); + } + }); + it('exact-matches fractional typeVersions against minor-versioned dirs', () => { const nodeName = '__TestMinorVersionExact__'; const schema = { type: 'object', properties: { id: { type: 'string' } } }; diff --git a/packages/@n8n/workflow-sdk/src/generate-types/generate-types.ts b/packages/@n8n/workflow-sdk/src/generate-types/generate-types.ts index d0c3835078d..3d3f31f3efe 100644 --- a/packages/@n8n/workflow-sdk/src/generate-types/generate-types.ts +++ b/packages/@n8n/workflow-sdk/src/generate-types/generate-types.ts @@ -411,6 +411,11 @@ export interface VersionGroup { export interface OutputSchema { resource: string; operation: string; + /** + * `-` for a `.-.json` file: the shape + * returned when the node parameter has that value. Absent for the plain file. + */ + variant?: string; schema: JsonSchema; } @@ -843,9 +848,11 @@ function collectSchemasFromVersionDir( for (const opEntry of operations) { if (!opEntry.isFile() || !opEntry.name.endsWith('.json')) continue; - const operationName = opEntry.name.replace('.json', ''); - if (seen.has(`${entry.name}/${operationName}`)) continue; + const fileKey = opEntry.name.replace('.json', ''); + if (seen.has(`${entry.name}/${fileKey}`)) continue; const schemaPath = path.join(resourceDir, opEntry.name); + // `..json` is a parameter-dependent shape of the operation. + const [operationName, variant] = splitOperationVariant(fileKey); try { const schemaContent = fs.readFileSync(schemaPath, 'utf-8'); @@ -853,9 +860,10 @@ function collectSchemasFromVersionDir( schemas.push({ resource: entry.name, operation: operationName, + ...(variant ? { variant } : {}), schema, }); - seen.add(`${entry.name}/${operationName}`); + seen.add(`${entry.name}/${fileKey}`); } catch { // Skip invalid JSON files } @@ -980,6 +988,19 @@ function orderedVersionDirectories(schemaDir: string, version: number): string[] } } +/** + * The type of an index signature that sits next to declared properties. It must + * accept the declared property types too, and `undefined` for optional ones. + */ +function indexSignatureType( + additionalType: string, + declaredTypes: string[], + hasOptional: boolean, +): string { + const members = [additionalType, ...declaredTypes, ...(hasOptional ? ['undefined'] : [])]; + return [...new Set(members)].join(' | '); +} + /** * Convert a JSON Schema to TypeScript type string * @@ -1049,12 +1070,21 @@ export function jsonSchemaToTypeScript(schema: JsonSchema, indent = 0): string { case 'object': if (schema.properties && Object.keys(schema.properties).length > 0) { const required = new Set(schema.required ?? []); + const declaredTypes: string[] = []; const props = Object.entries(schema.properties).map(([key, propSchema]) => { const optional = required.has(key) ? '' : '?'; const quotedKey = needsQuoting(key) ? `'${key}'` : key; const propType = jsonSchemaToTypeScript(propSchema, indent + 1); + declaredTypes.push(propType); return `${nextIndent}${quotedKey}${optional}: ${propType};`; }); + if (typeof schema.additionalProperties === 'object') { + const additionalType = jsonSchemaToTypeScript(schema.additionalProperties, indent + 1); + const hasOptional = Object.keys(schema.properties).some((key) => !required.has(key)); + props.push( + `${nextIndent}[key: string]: ${indexSignatureType(additionalType, declaredTypes, hasOptional)};`, + ); + } return `{\n${props.join('\n')}\n${indentStr}}`; } if (schema.additionalProperties) { @@ -1083,7 +1113,31 @@ export function findSchemaForOperation( operation: string, ): OutputSchema | undefined { return schemas.find( - (s) => s.resource.toLowerCase() === resource.toLowerCase() && s.operation === operation, + (s) => + !s.variant && + s.resource.toLowerCase() === resource.toLowerCase() && + s.operation === operation, + ); +} + +/** `get.simple-false` → `['get', 'simple-false']`; a name without a dot has no variant. */ +function splitOperationVariant(fileKey: string): [string, string | undefined] { + const dot = fileKey.indexOf('.'); + if (dot <= 0) return [fileKey, undefined]; + return [fileKey.slice(0, dot), fileKey.slice(dot + 1)]; +} + +/** The parameter-dependent shapes of one operation (`.-.json`). */ +export function findVariantSchemasForOperation( + schemas: OutputSchema[], + resource: string, + operation: string, +): OutputSchema[] { + return schemas.filter( + (s) => + s.variant !== undefined && + s.resource.toLowerCase() === resource.toLowerCase() && + s.operation === operation, ); } @@ -2983,6 +3037,156 @@ export function generateSharedFile( return lines.join('\n'); } +/** + * The parameter that selects between several output shapes of one operation, + * with the shape for each of its values. + */ +type ParameterValueType = 'boolean' | 'number' | 'string'; + +interface ParameterVariants { + param: string; + /** Primitive type of the parameter values: it decides the literal and expression types. */ + valueType: ParameterValueType; + /** The value used when the parameter is absent. The plain schema describes it. */ + defaultValue: string; + others: Array<{ value: string; schema: JsonSchema }>; +} + +/** `simple-false` → parameter `simple`, value `false`. */ +function parseParameterVariant(variant: string): { param: string; value: string } | undefined { + const separator = variant.indexOf('-'); + if (separator <= 0) return undefined; + return { param: variant.slice(0, separator), value: variant.slice(separator + 1) }; +} + +/** + * Turn the variant schemas of an operation into one `ParameterVariants`, or + * undefined when they cannot be typed: no plain schema, several parameters, + * a parameter the node does not have, or no default to attach the plain schema to. + */ +function resolveParameterVariants( + props: NodeProperty[], + variantSchemas: OutputSchema[], +): ParameterVariants | undefined { + const parsed = variantSchemas.map((s) => ({ + ...parseParameterVariant(s.variant ?? ''), + schema: s.schema, + })); + const param = parsed[0]?.param; + if (!param || parsed.some((entry) => entry.param !== param || entry.value === undefined)) { + return undefined; + } + + const property = props.find((p) => p.name === param); + const valueType = property ? getParameterValueType(property) : undefined; + if (!property || !valueType) return undefined; + + const defaultValue = String(property.default); + const others = parsed.map((entry) => ({ value: entry.value!, schema: entry.schema })); + if ( + others.some((entry) => entry.value === defaultValue || !isTypeSafeValue(valueType, entry.value)) + ) { + return undefined; + } + + const suffixes = [defaultValue, ...others.map((entry) => entry.value)].map((value) => + parameterValueSuffix(valueType, value), + ); + if (new Set(suffixes).size !== suffixes.length) return undefined; + + return { + param, + valueType, + defaultValue, + others: others.sort((a, b) => a.value.localeCompare(b.value)), + }; +} + +/** The value type of a boolean parameter, or of an options parameter whose default is a string, number or boolean. */ +function getParameterValueType(property: NodeProperty): ParameterValueType | undefined { + if (property.type === 'boolean') { + return typeof property.default === 'boolean' ? 'boolean' : undefined; + } + if (property.type !== 'options') return undefined; + if (typeof property.default === 'number') return 'number'; + if (typeof property.default === 'boolean') return 'boolean'; + return typeof property.default === 'string' ? 'string' : undefined; +} + +/** + * The part of a type name that stands for a parameter value. Signs and decimal + * points get words, because `toPascalCase` drops them and `-1` and `1` would + * share a name. + */ +function parameterValueSuffix(valueType: ParameterValueType, value: string): string { + if (valueType === 'number') return value.replace('-', 'Minus').replace('.', 'Point'); + return toPascalCase(value); +} + +/** A value comes from a file name, so it must be a valid literal of its type and safe to emit. */ +function isTypeSafeValue(valueType: ParameterValueType, value: string): boolean { + if (valueType === 'boolean') return value === 'true' || value === 'false'; + if (valueType === 'number') + return Number.isFinite(Number(value)) && String(Number(value)) === value; + return /^[\w-]+$/.test(value); +} + +/** `true` / `'raw'` — the TypeScript literal for a parameter value. */ +function parameterValueLiteral(variants: ParameterVariants, value: string): string { + return variants.valueType === 'string' ? `'${value}'` : value; +} + +/** + * Emit the output types and node types of an operation whose output shape + * depends on one parameter: a node type for each value, plus one for an + * expression (which can be either), and a union of them under `nodeTypeName`. + */ +function generateParameterVariantTypes( + variants: ParameterVariants, + names: { base: string; output: string; node: string }, + nodeBody: (typeName: string, paramsConstraint: string, outputType: string) => string[], +): string[] { + const { param, defaultValue, others } = variants; + const suffixOf = (value: string) => + `${toPascalCase(param)}${parameterValueSuffix(variants.valueType, value)}`; + const outputOf = (value: string) => `${names.base}${suffixOf(value)}Output`; + const nodeOf = (value: string) => `${names.base}${suffixOf(value)}Node`; + const lines: string[] = []; + + for (const { value, schema: variantSchema } of others) { + lines.push(`export type ${outputOf(value)} = ${jsonSchemaToTypeScript(variantSchema)};`, ''); + } + + const members = [ + { + node: nodeOf(defaultValue), + constraint: `${param}?: ${parameterValueLiteral(variants, defaultValue)}`, + output: names.output, + }, + ...others.map(({ value }) => ({ + node: nodeOf(value), + constraint: `${param}: ${parameterValueLiteral(variants, value)}`, + output: outputOf(value), + })), + ]; + const allOutputs = members.map((member) => member.output).join(' | '); + members.push({ + node: `${names.base}${toPascalCase(param)}ExpressionNode`, + constraint: `${param}: Expression<${variants.valueType}>`, + output: allOutputs, + }); + + for (const member of members) { + lines.push(...nodeBody(member.node, `{ ${member.constraint} }`, member.output), ''); + } + lines.push(`export type ${names.node} =`); + members.forEach((member, index) => { + lines.push(`${INDENT}| ${member.node}${index === members.length - 1 ? ';' : ''}`); + }); + + return lines; +} + /** * Generate a discriminator file for a single resource/operation (or mode, etc.) combination * @@ -3000,6 +3204,7 @@ export function generateDiscriminatorFile( props: NodeProperty[], schema?: JsonSchema, _importDepth: number = 5, + variantSchemas: OutputSchema[] = [], ): string { const prefix = getPackagePrefix(node.name); const nodeName = prefix + toPascalCase(getNodeBaseName(node.name)); @@ -3147,26 +3352,44 @@ export function generateDiscriminatorFile( } } - lines.push(`export type ${nodeTypeName} = {`); - lines.push(`${INDENT}type: '${node.name}';`); - lines.push(`${INDENT}version: ${version};`); - if (isTrigger) { - lines.push(`${INDENT}isTrigger: true;`); - } // Include subnodes in config if AI inputs exist // subnodes field is required if any AI input type is required const hasRequiredSubnodes = aiInputTypes.some((input) => input.required); - const configType = buildNodeConfigType(configName, { - credentialsTypeName: - node.credentials && node.credentials.length > 0 ? 'Credentials' : undefined, - subnodeConfigTypeName: subnodeConfigTypeName ?? undefined, - subnodesRequired: hasRequiredSubnodes, - }); - lines.push(`${INDENT}config: ${configType};`); - if (schema) { - lines.push(`${INDENT}output?: Items<${outputTypeName}>;`); + const nodeBody = (typeName: string, paramsConstraint?: string, outputType?: string) => { + const paramsType = paramsConstraint ? `${configName} & ${paramsConstraint}` : configName; + const configType = buildNodeConfigType(paramsType, { + credentialsTypeName: + node.credentials && node.credentials.length > 0 ? 'Credentials' : undefined, + subnodeConfigTypeName: subnodeConfigTypeName ?? undefined, + subnodesRequired: hasRequiredSubnodes, + }); + return [ + `export type ${typeName} = {`, + `${INDENT}type: '${node.name}';`, + `${INDENT}version: ${version};`, + ...(isTrigger ? [`${INDENT}isTrigger: true;`] : []), + `${INDENT}config: ${configType};`, + ...(outputType ? [`${INDENT}output?: Items<${outputType}>;`] : []), + '};', + ]; + }; + + const variants = schema ? resolveParameterVariants(props, variantSchemas) : undefined; + if (variants) { + lines.push( + ...generateParameterVariantTypes( + variants, + { + base: `${nodeName}${versionSuffix}${comboSuffix}`, + output: outputTypeName, + node: nodeTypeName, + }, + nodeBody, + ), + ); + } else { + lines.push(...nodeBody(nodeTypeName, undefined, schema ? outputTypeName : undefined)); } - lines.push('};'); return lines.join('\n'); } @@ -3363,6 +3586,7 @@ export function planSplitVersionFiles( props, matchingSchema?.schema, 6, + findVariantSchemasForOperation(outputSchemas, resource, operation), ); files.set(filePath, content); } diff --git a/packages/@n8n/workflow-sdk/src/mock-data/ai-root-shapes.ts b/packages/@n8n/workflow-sdk/src/mock-data/ai-root-shapes.ts index be47b995bf1..874acebdc93 100644 --- a/packages/@n8n/workflow-sdk/src/mock-data/ai-root-shapes.ts +++ b/packages/@n8n/workflow-sdk/src/mock-data/ai-root-shapes.ts @@ -6,6 +6,7 @@ */ export const AGENT_NODE_TYPE = '@n8n/n8n-nodes-langchain.agent'; +export const TEXT_CLASSIFIER_NODE_TYPE = '@n8n/n8n-nodes-langchain.textClassifier'; /** * Vendor API nodes (OpenAI, Anthropic, …): AI roots for detection purposes, @@ -29,7 +30,7 @@ const AI_ROOT_NODE_TYPES = new Set([ '@n8n/n8n-nodes-langchain.chainRetrievalQa', '@n8n/n8n-nodes-langchain.chainSummarization', '@n8n/n8n-nodes-langchain.informationExtractor', - '@n8n/n8n-nodes-langchain.textClassifier', + TEXT_CLASSIFIER_NODE_TYPE, '@n8n/n8n-nodes-langchain.sentimentAnalysis', ...VENDOR_AI_ROOT_NODE_TYPES, ]); @@ -38,19 +39,26 @@ export function isAiRootNodeType(nodeType: string): boolean { return AI_ROOT_NODE_TYPES.has(nodeType); } +export interface AiRootShapeOptions { + classifierReportsConfidence?: boolean; +} + /** * Per-root-type pinned item shape for the roots whose shape can't live in a - * `__schema__` file at all: textClassifier is a pure input passthrough and - * vendor nodes emit their API response. Every other root's shape (including - * the parser-conditional Agent/ChainLlm variants) ships as + * `__schema__` file at all: textClassifier passes its input through, adding a + * `classification` object only when its options ask for one, and vendor nodes + * emit their API response. Every other root's shape (including the + * parser-conditional Agent/ChainLlm variants) ships as * `__schema__/v/output[.with-parser].json` in nodes-langchain — the prompt * embeds those via the schema lookup and only falls back to this prose when * no schema resolves (missing/stale package build). */ -export function describeAiRootShape(nodeType: string): string { +export function describeAiRootShape(nodeType: string, options?: AiRootShapeOptions): string { switch (nodeType) { - case '@n8n/n8n-nodes-langchain.textClassifier': - return 'the INPUT item passed through UNCHANGED (this node routes items to a category branch without reshaping them) — emit a plausible input item, no classification wrapper key.'; + case TEXT_CLASSIFIER_NODE_TYPE: + return options?.classifierReportsConfidence + ? 'the INPUT item passed through unchanged, plus a `classification` object holding `category` (the branch name), `confidence` (0-1), and `scores` (0-1 for every category) — the node routes items and adds only that one key.' + : 'the INPUT item passed through UNCHANGED (this node routes items to a category branch without reshaping them) — emit a plausible input item, no classification wrapper key.'; default: if (VENDOR_AI_ROOT_NODE_TYPES.has(nodeType)) { return "a plausible vendor API response for the node's configured resource and operation — there is NO `output` wrapper key; mirror the vendor's response fields."; diff --git a/packages/@n8n/workflow-sdk/src/mock-data/context.ts b/packages/@n8n/workflow-sdk/src/mock-data/context.ts index a3f06e9ff6e..19161e20166 100644 --- a/packages/@n8n/workflow-sdk/src/mock-data/context.ts +++ b/packages/@n8n/workflow-sdk/src/mock-data/context.ts @@ -1,6 +1,7 @@ +import { isRecord } from '@n8n/utils/is-record'; import { DATA_TABLE_SYSTEM_COLUMNS } from 'n8n-workflow'; -import { findEnvelopeKey } from './ai-root-shapes'; +import { findEnvelopeKey, TEXT_CLASSIFIER_NODE_TYPE } from './ai-root-shapes'; import { readDataTableReadParameters } from './data-table-read'; import type { DataTableColumnInfo, @@ -45,6 +46,7 @@ export function buildSchemaContexts( resource, operation, hasOutputParser: node.name ? outputParserTargets?.has(node.name) === true : false, + parameters: params, }); const nodeName = node.name ?? node.type; @@ -61,10 +63,19 @@ export function buildSchemaContexts( dataTableColumns: columns, dataTableRead: readDataTableReadParameters(node), declaredFields: buildDeclaredFieldContract(node.type, schema, outputParser, columns), + classifierReportsConfidence: classifierReportsConfidence(node.type, params), }; }); } +function classifierReportsConfidence( + nodeType: string, + params: Record | undefined, +): boolean { + if (nodeType !== TEXT_CLASSIFIER_NODE_TYPE) return false; + return isRecord(params?.options) && params.options.includeConfidenceScores === true; +} + /** * Envelope key the parsed fields sit under, if any. Shared with the prompt * builder so the shape asked for and the shape enforced can't drift: the diff --git a/packages/@n8n/workflow-sdk/src/mock-data/mock-data.test.ts b/packages/@n8n/workflow-sdk/src/mock-data/mock-data.test.ts index 7986f8f2d53..469002dccd9 100644 --- a/packages/@n8n/workflow-sdk/src/mock-data/mock-data.test.ts +++ b/packages/@n8n/workflow-sdk/src/mock-data/mock-data.test.ts @@ -88,6 +88,7 @@ describe('buildSchemaContexts', () => { resource: 'row', operation: 'get', hasOutputParser: false, + parameters: workflow.nodes[0].parameters, }); expect(contexts[0].schema).toEqual({ type: 'object', properties: { id: {} } }); }); @@ -747,6 +748,38 @@ describe('ai-root shapes', () => { ); }); + it('describes the classifier by what its options ask for', async () => { + const { describeAiRootShape } = await import('./ai-root-shapes.js'); + const classifier = '@n8n/n8n-nodes-langchain.textClassifier'; + + const on = describeAiRootShape(classifier, { classifierReportsConfidence: true }); + const off = describeAiRootShape(classifier, { classifierReportsConfidence: false }); + + expect(on).not.toBe(off); + expect(off).toBe(describeAiRootShape(classifier)); + expect(on).toContain('`classification` object'); + expect(off).toContain('no classification wrapper key'); + }); + + it('carries the classifier option into the rendered prompt section', async () => { + const { buildSchemaContexts } = await import('./context.js'); + const { buildNodeSchemaSection } = await import('./prompt.js'); + const node = (options: Record) => ({ + id: 'classifier-1', + name: 'Classifier', + type: '@n8n/n8n-nodes-langchain.textClassifier', + typeVersion: 1.1, + position: [0, 0] as [number, number], + parameters: { options }, + }); + + const [on] = buildSchemaContexts([node({ includeConfidenceScores: true })]); + const [off] = buildSchemaContexts([node({})]); + + expect(buildNodeSchemaSection(on).join('\n')).toContain('`classification` object'); + expect(buildNodeSchemaSection(off).join('\n')).toContain('no classification wrapper key'); + }); + it('derives the structured envelope key from a with-parser schema', async () => { const { findEnvelopeKey } = await import('./ai-root-shapes.js'); diff --git a/packages/@n8n/workflow-sdk/src/mock-data/prompt.ts b/packages/@n8n/workflow-sdk/src/mock-data/prompt.ts index a4418fa7ee2..7f0d07f851c 100644 --- a/packages/@n8n/workflow-sdk/src/mock-data/prompt.ts +++ b/packages/@n8n/workflow-sdk/src/mock-data/prompt.ts @@ -14,7 +14,7 @@ RULES: 4. When no schema is provided, generate a realistic response based on the node type, resource, and operation. 5. Use realistic but clearly fake values (e.g., "jane@example.com", "proj_abc123"). 6. Dates and timestamps MUST be derived from the "## Date anchors" block at the end of the prompt — never from training data. Workflows compare pinned data against the real execution clock ($now, Date.now()); values months in the past get silently filtered out, and HTTP mocks generated later use the same anchors, so stale years make "stored matches current" comparisons impossible. When the data description mentions a relative window ("last 24 hours", "past 2 weeks"), place timestamps safely INSIDE it, never on the boundary. -7. AI root nodes (Agent/Chain) have NODE-TYPE-SPECIFIC output shapes — follow each node's schema or "AI ROOT OUTPUT SHAPE" instruction exactly and never invent a different envelope key. Summary: agent wraps in { "output": ... } (a parsed object matching the parser schema when one is attached, otherwise a plain text string — never a JSON-encoded string); chainLlm uses { "text": "" } without a parser, or { "output": } like agent when a parser is attached; chainRetrievalQa uses { "response": "" }; chainSummarization uses { "output": { "output_text": "" } }; informationExtractor wraps the extracted fields in { "output": }; textClassifier passes the input item through unchanged; sentimentAnalysis is the input item plus a "sentimentAnalysis" object. +7. AI root nodes (Agent/Chain) have NODE-TYPE-SPECIFIC output shapes — follow each node's schema or "AI ROOT OUTPUT SHAPE" instruction exactly and never invent a different envelope key. Summary: agent wraps in { "output": ... } (a parsed object matching the parser schema when one is attached, otherwise a plain text string — never a JSON-encoded string); chainLlm uses { "text": "" } without a parser, or { "output": } like agent when a parser is attached; chainRetrievalQa uses { "response": "" }; chainSummarization uses { "output": { "output_text": "" } }; informationExtractor wraps the extracted fields in { "output": }; textClassifier passes the input item through unchanged, unless its own AI ROOT OUTPUT SHAPE line says it adds a "classification" object; sentimentAnalysis is the input item plus a "sentimentAnalysis" object. 8. CRITICAL: If a "Test Scenario" section is provided, it is the authoritative test state and OVERRIDES everything else, including the general data context and your own sense of realism. When it describes stored/previous records (e.g. "the store already holds a record with status X"), exact values, counts, literal substrings, or that stored data matches current data, reproduce those constraints EXACTLY — never substitute more "interesting" or more typical data. A boring no-change/empty/matching case is usually the point of the test. 9. Return ONLY a valid JSON object, no explanation or markdown fencing. 10. CRITICAL: You MUST generate data for EVERY node listed in "Nodes Requiring Mock Data". Never skip a node, even if the test scenario describes an empty or error response. An empty response is still valid data — represent it as an empty array [], never as [{}].`; @@ -42,7 +42,11 @@ export function buildNodeSchemaSection(ctx: NodeSchemaContext): string[] { // covered by the schema section below; the prose is for shapes that can't // be files (see `describeAiRootShape`) and the no-schema fallback. if (!ctx.schema) { - lines.push(`- AI ROOT OUTPUT SHAPE: every item MUST be ${describeAiRootShape(ctx.nodeType)}`); + lines.push( + `- AI ROOT OUTPUT SHAPE: every item MUST be ${describeAiRootShape(ctx.nodeType, { + classifierReportsConfidence: ctx.classifierReportsConfidence, + })}`, + ); } if (ctx.outputParser?.schemaText) { const envelopeKey = resolveEnvelopeKey(ctx.nodeType, ctx.schema); diff --git a/packages/@n8n/workflow-sdk/src/mock-data/types.ts b/packages/@n8n/workflow-sdk/src/mock-data/types.ts index 3afcd5412ec..f3a031a68e9 100644 --- a/packages/@n8n/workflow-sdk/src/mock-data/types.ts +++ b/packages/@n8n/workflow-sdk/src/mock-data/types.ts @@ -23,6 +23,8 @@ export type OutputSchemaLookup = (node: { operation?: string; /** Node has an `ai_outputParser` attached — resolves the `with-parser` layout variant. */ hasOutputParser?: boolean; + /** The node's parameters — pick a shape variant such as `simple: false`. */ + parameters?: Record; }) => Record | undefined; /** Structured-output-parser info for an AI root node (Agent/Chain). */ @@ -70,6 +72,7 @@ export interface NodeSchemaContext { /** The filter a Data Table `get` node applies; the pinned rows are its output, not the table. */ dataTableRead?: DataTableReadParameters; declaredFields?: DeclaredFieldContract; + classifierReportsConfidence?: boolean; } export interface PinDataGenerationInstructions { diff --git a/packages/@n8n/workflow-sdk/src/prompts/node-guidance/parameter-guides/gmail.test.ts b/packages/@n8n/workflow-sdk/src/prompts/node-guidance/parameter-guides/gmail.test.ts new file mode 100644 index 00000000000..ca4440ecc92 --- /dev/null +++ b/packages/@n8n/workflow-sdk/src/prompts/node-guidance/parameter-guides/gmail.test.ts @@ -0,0 +1,13 @@ +import { GMAIL_GUIDE } from './gmail'; + +describe('GMAIL_GUIDE', () => { + it('names the real Simplify parameter, `simple`, and not `simplify`', () => { + expect(GMAIL_GUIDE.content).toContain('**simple: false**'); + expect(GMAIL_GUIDE.content).toContain('**simple: true**'); + expect(GMAIL_GUIDE.content).not.toMatch(/\bsimplify\b\s*(:|to\b)/i); + }); + + it('does not give the message output shape as the shape of a thread', () => { + expect(GMAIL_GUIDE.content).toContain('thread:get'); + }); +}); diff --git a/packages/@n8n/workflow-sdk/src/prompts/node-guidance/parameter-guides/gmail.ts b/packages/@n8n/workflow-sdk/src/prompts/node-guidance/parameter-guides/gmail.ts index cd5a3c0279e..fe456c36d5f 100644 --- a/packages/@n8n/workflow-sdk/src/prompts/node-guidance/parameter-guides/gmail.ts +++ b/packages/@n8n/workflow-sdk/src/prompts/node-guidance/parameter-guides/gmail.ts @@ -14,15 +14,21 @@ export const GMAIL_GUIDE: NodeTypeGuide = { - **authentication**: OAuth2 or Service Account #### Simplify Option (CRITICAL) -- **simplify: false** - Returns FULL email with body, attachments, headers -- **simplify: true** - Returns LIMITED data (subject, snippet only, NO body) +The parameter is named **simple**, not "simplify". Default: true. +- **simple: false** - Returns the FULL parsed email with body, attachments and headers. The sender is the object \`$json.from\`: read the address with \`$json.from.value[0].address\`. The body is in \`$json.text\` and \`$json.html\`. +- **simple: true** - Returns a LIMITED flat item (subject, snippet, labels, NO body). The sender is the string \`$json.From\`, for example "Sara Chen ". -ALWAYS set simplify to FALSE when: -- Workflow needs to analyze email content/body -- AI Agent will process or summarize emails -- Email content is used for decision making +Read the sender from the field that matches the setting. \`$json.From\` is undefined when simple is false. + +These shapes are for the **message** operations. For **thread:get**, both settings flatten the headers, so \`$json.From\` works. With simple false, thread:get returns the Gmail API payload: the body is encoded in base64url in \`payload.parts[].body.data\` (look through nested parts), and there is no \`$json.from\`, \`$json.text\` or \`$json.html\`. + +Set simple to false only when: +- Workflow needs the email body to analyze or summarize it +- AI Agent will process the email text - Attachments need to be accessed +Keep simple true when the workflow only filters or routes by sender, subject or labels. + #### Gmail Filter Queries For Gmail Trigger nodes, use comprehensive search filters with OR operators: - Multiple keywords: "subject:(delivery OR shipment OR package OR tracking)" @@ -40,7 +46,7 @@ NOT just: "subject:delivery" (misses many relevant emails) - Configure to, subject, and message fields 2. **Reading Emails for AI Analysis**: - - Set simplify to false (required for full email body) + - Set simple to false (required for full email body) and read the sender from \`$json.from.value[0].address\` - Configure appropriate filter query - Pass full email data to AI Agent diff --git a/packages/cli/docs/adr/ADR-20261012-require-create-and-execute-scopes-for-standalone-node-runs.md b/packages/cli/docs/adr/ADR-20261012-require-create-and-execute-scopes-for-standalone-node-runs.md new file mode 100644 index 00000000000..2174bd52bf6 --- /dev/null +++ b/packages/cli/docs/adr/ADR-20261012-require-create-and-execute-scopes-for-standalone-node-runs.md @@ -0,0 +1,59 @@ +# Require create and execute scopes for standalone node runs + +Date: 2026-10-12 + +Status: Active + +Decision Owner: Assistant + +Source: https://linear.app/n8n/issue/AST-1705 + +## Context + +The n8n Assistant can run one node standalone. The caller supplies the node type, the node +parameters, the credentials, and the input items. The service puts the node in a temporary +workflow in the target project, runs it, and deletes the workflow. + +`workflow:execute` lets a user run a workflow that already exists. The manual run endpoint +loads the workflow from the database and ignores a definition in the request body. A user +who has `workflow:execute` but not `workflow:create` or `workflow:update` can only run +workflows that someone else wrote. + +A standalone node run does not run a stored workflow. The caller writes the node, so the +run is workflow authoring and execution in one step. + +## Decision + +A standalone node run requires both `workflow:create` and `workflow:execute` in the target +project. The user must hold both scopes. One of the two is not sufficient. + +The main reason: the caller defines the node. That is the same power as creating a workflow +and running it. The required scopes match those two actions. + +The check runs before the service resolves the node or reads a credential. + +## Alternatives Considered + +1. **Keep `workflow:execute` alone.** We rejected it because it lets a role that cannot + author workflows run any node with any parameters. That breaks the contract of an + execute-only role. +2. **Require `workflow:update` with `workflow:execute`.** We rejected it because + `workflow:update` applies to a workflow that exists, and this technically creates a new + workflow it runs. + +## Consequences + +1. A custom role that has `workflow:execute` but not `workflow:create` cannot use standalone + node runs. Such a user can still run stored workflows through the Assistant. +2. The built-in project roles do not change in behavior. Each role that has + `workflow:execute` also has `workflow:create`. A personal project owner has both scopes. +3. Any new path that runs a caller-defined node or workflow must require `workflow:create` + with `workflow:execute`. + +## Links + +RFC: - + +Documentation: - + +Related ADRs: - diff --git a/packages/cli/eslint.config.mjs b/packages/cli/eslint.config.mjs index 485177e5e32..9694876946d 100644 --- a/packages/cli/eslint.config.mjs +++ b/packages/cli/eslint.config.mjs @@ -90,10 +90,6 @@ export default defineConfig( rule: 'no-repository-in-public-api-handler', message: 'Call a service instead of reaching the repository.', }, - { - rule: 'require-public-api-controller', - message: 'Migrate to `@PublicApiController`.', - }, { rule: 'no-unsealed-workflow-entity-write', message: 'Route the write through a token-gated `WorkflowRepository` method.', @@ -153,25 +149,6 @@ export default defineConfig( 'n8n-local-rules/no-repository-in-public-api-handler': 'error', }, }, - { - // Public API guardrail: new endpoints must be `@PublicApiController` classes, not `export =` tuples. - files: [ - './src/public-api/v1/handlers/**/*.handler.ts', - './src/public-api/v1/handlers/**/*.handler.ee.ts', - ], - rules: { - 'n8n-local-rules/require-public-api-controller': 'error', - }, - }, - { - // Ratchet allowlist: legacy `export =` handler tuples pending migration to - // `@PublicApiController` classes (API-70). NEVER add to this list — a new tuple handler - // must fail CI. Entries are removed as each handler becomes a controller. - files: ['./src/public-api/v1/handlers/n8n-packages/n8n-packages.handler.ts'], - rules: { - 'n8n-local-rules/require-public-api-controller': 'off', - }, - }, { files: ['./src/**/*.ts'], ignores: ['./src/modules/engine-v2/**/*.ts'], @@ -231,8 +208,6 @@ export default defineConfig( // JwtService itself: verifying tokens signed by a foreign key, which JwtService cannot // verify. Do NOT add a file for any other reason. files: [ - // Owns the signing key and derives every audience from a purpose. - './src/services/jwt.service.ts', // Verifies subject tokens with a foreign key from the trusted-key store, // against the audience that key is registered for. './src/modules/token-exchange/services/token-exchange.service.ts', diff --git a/packages/cli/oxlint.config.mts b/packages/cli/oxlint.config.mts index 1b284b8f210..ee6775d55fc 100644 --- a/packages/cli/oxlint.config.mts +++ b/packages/cli/oxlint.config.mts @@ -89,10 +89,6 @@ export default defineConfig({ rule: 'no-repository-in-public-api-handler', message: 'Call a service instead of reaching the repository.', }, - { - rule: 'require-public-api-controller', - message: 'Migrate to `@PublicApiController`.', - }, { rule: 'no-unsealed-workflow-entity-write', message: 'Route the write through a token-gated `WorkflowRepository` method.', @@ -146,25 +142,6 @@ export default defineConfig({ 'n8n-local-rules/no-repository-in-public-api-handler': 'error', }, }, - { - // Public API guardrail: new endpoints must be `@PublicApiController` classes, not `export =` tuples. - files: [ - './src/public-api/v1/handlers/**/*.handler.ts', - './src/public-api/v1/handlers/**/*.handler.ee.ts', - ], - rules: { - 'n8n-local-rules/require-public-api-controller': 'error', - }, - }, - { - // Ratchet allowlist: legacy `export =` handler tuples pending migration to - // `@PublicApiController` classes (API-70). NEVER add to this list — a new tuple handler - // must fail CI. Entries are removed as each handler becomes a controller. - files: ['./src/public-api/v1/handlers/n8n-packages/n8n-packages.handler.ts'], - rules: { - 'n8n-local-rules/require-public-api-controller': 'off', - }, - }, { files: ['./src/**/*.ts'], excludeFiles: ['./src/modules/engine-v2/**/*.ts'], @@ -233,8 +210,6 @@ export default defineConfig({ // JwtService itself: verifying tokens signed by a foreign key, which JwtService cannot // verify. Do NOT add a file for any other reason. files: [ - // Owns the signing key and derives every audience from a purpose. - './src/services/jwt.service.ts', // Verifies subject tokens with a foreign key from the trusted-key store, // against the audience that key is registered for. './src/modules/token-exchange/services/token-exchange.service.ts', diff --git a/packages/cli/package.json b/packages/cli/package.json index 1298cad3b4a..9e79111724c 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "n8n", - "version": "2.43.0", + "version": "2.44.0", "private": true, "description": "n8n Workflow Automation Tool", "main": "dist/index", @@ -134,7 +134,6 @@ "@1password/connect": "1.4.2", "@ai-sdk/anthropic": "catalog:", "@ai-sdk/openai-compatible": "catalog:", - "@apidevtools/json-schema-ref-parser": "12.0.2", "@asteasolutions/zod-to-openapi": "catalog:", "@aws-sdk/client-secrets-manager": "3.808.0", "@azure/identity": "catalog:", @@ -161,6 +160,7 @@ "@n8n/api-types": "workspace:*", "@n8n/backend-common": "workspace:*", "@n8n/backend-module-insights": "workspace:*", + "@n8n/backend-module-quick-connect": "workspace:*", "@n8n/backend-network": "workspace:*", "@n8n/backend-services": "workspace:*", "@n8n/blob-storage": "workspace:*", @@ -221,7 +221,6 @@ "dotenv": "catalog:", "express": "catalog:", "express-handlebars": "8.0.1", - "express-openapi-validator": "5.5.3", "express-prom-bundle": "8.0.0", "express-rate-limit": "7.5.0", "fast-glob": "catalog:", diff --git a/packages/cli/scripts/build.mjs b/packages/cli/scripts/build.mjs index 3a532751098..6821da832b8 100644 --- a/packages/cli/scripts/build.mjs +++ b/packages/cli/scripts/build.mjs @@ -75,40 +75,30 @@ function copySwaggerTheme() { shell.cp('-r', swaggerTheme.source, swaggerTheme.destination); } -// Builds the v1 spec from two sources: -// - the hand-written routes (eov) at `openapi.yml` -// - the full `@PublicApiController` decorated routes at `openapi.decorator-routes.generated.yml` +// Builds the v1 spec. The generated root lists every `@PublicApiController` operation. The build +// bundles it, then puts its paths and components into the hand-written envelope (`openapi.yml`). async function buildPublicApiSpec() { const v1Dir = path.resolve(ROOT_DIR, 'src', 'public-api', 'v1'); - const { generateDocs, mergeDecoratorDocument, DECORATOR_ROOT_FILENAME } = - await loadOpenApiGenerator(); + const { generateDocs, assembleSpec, DECORATOR_ROOT_FILENAME } = await loadOpenApiGenerator(); - // 1. Generate decorated route OpenAPI specs from source. + // 1. Generate the operation fragments and the root from source. generateDocs(v1Dir); - // 2. Bundle both sources in one redocly process. With several inputs, redocly - // writes each bundle into the output directory under its source file name. + // 2. Bundle the generated root, resolving its $refs to the fragment files. const v1DistDir = path.resolve(ROOT_DIR, 'dist', 'public-api', 'v1'); - bundleSpecs( - [path.join(v1Dir, SPEC_FILENAME), path.join(v1Dir, DECORATOR_ROOT_FILENAME)], - v1DistDir, - ); + const generatedDistSpec = path.join(v1DistDir, DECORATOR_ROOT_FILENAME); + bundleSpec(path.join(v1Dir, DECORATOR_ROOT_FILENAME), generatedDistSpec); - const eovDistSpec = path.join(v1DistDir, SPEC_FILENAME); - const decoratorDistSpec = path.join(v1DistDir, DECORATOR_ROOT_FILENAME); - - // 3. Merge the two specs into a single OpenAPI document, writing back to the eov spec path. - const eovDoc = parseYaml(readFileSync(eovDistSpec, 'utf8')); - const decoratorDoc = parseYaml(readFileSync(decoratorDistSpec, 'utf8')); - - // 4. Merge the two specs and write back to the eov spec path. + // 3. Assemble the published spec from the envelope and the bundled root. + const envelope = parseYaml(readFileSync(path.join(v1Dir, SPEC_FILENAME), 'utf8')); + const generated = parseYaml(readFileSync(generatedDistSpec, 'utf8')); writeFileSync( - eovDistSpec, - stringifyYaml(mergeDecoratorDocument(eovDoc, decoratorDoc), YAML_STRINGIFY_OPTS), + path.join(v1DistDir, SPEC_FILENAME), + stringifyYaml(assembleSpec(envelope, generated), YAML_STRINGIFY_OPTS), ); - // 5. Cleanup the decorator spec. - rmSync(decoratorDistSpec); + // 4. Remove the bundled root. Only the assembled spec is published. + rmSync(generatedDistSpec); } // Imports the already-compiled generator from dist rather than the .ts source — by the time @@ -129,7 +119,7 @@ async function loadOpenApiGenerator() { } const generator = await import(pathToFileURL(generatorPath).href); - for (const name of ['generateDocs', 'mergeDecoratorDocument', 'DECORATOR_ROOT_FILENAME']) { + for (const name of ['generateDocs', 'assembleSpec', 'DECORATOR_ROOT_FILENAME']) { if (generator[name] === undefined) { throw new Error( `OpenAPI doc generator at ${generatorPath} is missing export '${name}' — its contract may have changed.`, @@ -139,25 +129,19 @@ async function loadOpenApiGenerator() { return generator; } -// Bundles specs through redocly, resolving all $refs. Each source becomes one file in `distDir`. -function bundleSpecs(sourcePaths, distDir) { - const distPaths = sourcePaths.map((sourcePath) => path.join(distDir, path.basename(sourcePath))); +// Bundles a spec through redocly, resolving all $refs, and writes it to `distPath`. +function bundleSpec(sourcePath, distPath) { // Remove old output, so that the check below cannot pass on a stale file. - for (const distPath of distPaths) rmSync(distPath, { force: true }); + rmSync(distPath, { force: true }); - const sources = sourcePaths.map((sourcePath) => `"${sourcePath}"`).join(' '); - const result = shell.exec(`pnpm openapi bundle ${sources} --output "${distDir}"`, { + const result = shell.exec(`pnpm openapi bundle "${sourcePath}" --output "${distPath}"`, { silent: true, }); if (result.code !== 0) { - throw new Error( - `redocly failed to bundle ${sourcePaths.join(', ')}:\n${result.stderr || result.stdout}`, - ); + throw new Error(`redocly failed to bundle ${sourcePath}:\n${result.stderr || result.stdout}`); } - for (const [i, distPath] of distPaths.entries()) { - if (!existsSync(distPath)) { - throw new Error(`redocly did not write the bundle for ${sourcePaths[i]} to ${distPath}`); - } + if (!existsSync(distPath)) { + throw new Error(`redocly did not write the bundle for ${sourcePath} to ${distPath}`); } } diff --git a/packages/cli/src/__tests__/abstract-server.test.ts b/packages/cli/src/__tests__/abstract-server.test.ts index 321bf20f4e1..deb112bb591 100644 --- a/packages/cli/src/__tests__/abstract-server.test.ts +++ b/packages/cli/src/__tests__/abstract-server.test.ts @@ -7,6 +7,16 @@ import { mock } from 'vitest-mock-extended'; import { AbstractServer } from '@/abstract-server'; import { ExternalHooks } from '@/external-hooks'; +import { LiveWebhooks } from '@/webhooks/live-webhooks'; +import { SlackInteractionWebhooks } from '@/webhooks/slack-interaction-webhooks'; +import { TelegramInteractionWebhooks } from '@/webhooks/telegram-interaction-webhooks'; +import { WaitingForms } from '@/webhooks/waiting-forms'; +import { WaitingWebhooks } from '@/webhooks/waiting-webhooks'; +import { createWebhookHandlerFor } from '@/webhooks/webhook-request-handler'; + +vi.mock('@/webhooks/webhook-request-handler', () => ({ + createWebhookHandlerFor: vi.fn(), +})); const mockServer = mock(); @@ -87,6 +97,21 @@ describe('AbstractServer health endpoints', () => { await testServer.init(); }); + describe('webhook route registration', () => { + it('should register the waiting-forms route with the form sandbox family', async () => { + const waitingForms = mock(); + Container.set(LiveWebhooks, mock()); + Container.set(WaitingForms, waitingForms); + Container.set(WaitingWebhooks, mock()); + Container.set(SlackInteractionWebhooks, mock()); + Container.set(TelegramInteractionWebhooks, mock()); + + await testServer.start(); + + expect(createWebhookHandlerFor).toHaveBeenCalledWith(waitingForms, undefined, 'form'); + }); + }); + describe('/healthz (liveness)', () => { it('should return 200 regardless of fullyReady flag', () => { const res = mock(); diff --git a/packages/cli/src/__tests__/load-nodes-and-credentials.test.ts b/packages/cli/src/__tests__/load-nodes-and-credentials.test.ts index 3058cfaa0d4..dc601b5f12a 100644 --- a/packages/cli/src/__tests__/load-nodes-and-credentials.test.ts +++ b/packages/cli/src/__tests__/load-nodes-and-credentials.test.ts @@ -10,6 +10,7 @@ import { CUSTOM_NODES_PACKAGE_NAME, CustomDirectoryLoader, DirectoryLoader } fro import type { ICredentialType, INodeProperties, + INodeType, INodeTypeDescription, KnownNodesAndCredentials, NodeLoader, @@ -290,6 +291,80 @@ describe('LoadNodesAndCredentials', () => { ).toEqual({ type: 'object' }); }); + describe('parameter variants', () => { + const rawSchema = { type: 'object', title: 'raw' }; + const plainSchema = { type: 'object' }; + const lookupRef = { + type: 'n8n-nodes-base.test', + typeVersion: 1, + resource: 'account', + operation: 'get', + }; + + const provideNode = (nodeType: Partial) => { + const type = { description: { properties: [] }, ...nodeType } as INodeType; + vi.spyOn(instance, 'getNode').mockReturnValue({ sourcePath: 'Test.node.js', type }); + }; + + beforeEach(() => { + const accountDir = join(nodesDir, 'Test', '__schema__', 'v1.0.0', 'account'); + writeFileSync(join(accountDir, 'get.simple-false.json'), JSON.stringify(rawSchema)); + writeFileSync( + join(accountDir, 'get.custom.json'), + JSON.stringify({ type: 'object', title: 'custom' }), + ); + }); + + it('should pick the variant file that matches the node parameters', () => { + provideNode({}); + + expect( + instance.createOutputSchemaLookup()({ ...lookupRef, parameters: { simple: false } }), + ).toEqual(rawSchema); + }); + + it('should use the property default when the parameter is absent', () => { + provideNode({ + description: { + properties: [ + { + name: 'simple', + type: 'boolean', + default: false, + displayOptions: { show: { resource: ['account'], operation: ['get'] } }, + }, + ], + } as unknown as INodeTypeDescription, + }); + + expect(instance.createOutputSchemaLookup()({ ...lookupRef, parameters: {} })).toEqual( + rawSchema, + ); + }); + + it('should use the plain file when the parameter keeps its default', () => { + provideNode({ + description: { + properties: [{ name: 'simple', type: 'boolean', default: true }], + } as unknown as INodeTypeDescription, + }); + + expect(instance.createOutputSchemaLookup()({ ...lookupRef, parameters: {} })).toEqual( + plainSchema, + ); + }); + + it('should still resolve the plain schema when the node cannot be loaded', () => { + vi.spyOn(instance, 'getNode').mockImplementation(() => { + throw new Error('not loadable'); + }); + + expect( + instance.createOutputSchemaLookup()({ ...lookupRef, parameters: { simple: true } }), + ).toEqual(plainSchema); + }); + }); + it('should return undefined for unknown nodes or missing schemas', () => { const lookup = instance.createOutputSchemaLookup(); expect( diff --git a/packages/cli/src/__tests__/manual-execution.service.test.ts b/packages/cli/src/__tests__/manual-execution.service.test.ts index 5adddb7781b..ebffff22233 100644 --- a/packages/cli/src/__tests__/manual-execution.service.test.ts +++ b/packages/cli/src/__tests__/manual-execution.service.test.ts @@ -68,12 +68,9 @@ describe('ManualExecutionService', () => { expect(executionStartNode?.name).toEqual('node2'); }); - it('Should return triggerToStartFrom trigger node', () => { + it.each([true, false])('returns the selected trigger when pinned data is %s', (pinned) => { const data = mock({ - pinData: { - node1: [mock()], - node2: [mock()], - }, + pinData: pinned ? { node3: [mock()] } : undefined, triggerToStartFrom: { name: 'node3' }, }); const workflow = mock({ diff --git a/packages/cli/src/__tests__/output-schema-parameter-defaults.test.ts b/packages/cli/src/__tests__/output-schema-parameter-defaults.test.ts new file mode 100644 index 00000000000..1d9ac7ead3a --- /dev/null +++ b/packages/cli/src/__tests__/output-schema-parameter-defaults.test.ts @@ -0,0 +1,64 @@ +import type { INodeProperties } from 'n8n-workflow'; + +import { getParameterDefaults } from '../output-schema-parameter-defaults'; + +const property = (overrides: Partial & { name: string }): INodeProperties => ({ + displayName: overrides.name, + type: 'boolean', + default: true, + ...overrides, +}); + +describe('getParameterDefaults', () => { + it('returns the default of each property', () => { + const defaults = getParameterDefaults( + [property({ name: 'simple', default: true }), property({ name: 'limit', default: 50 })], + {}, + ); + + expect(defaults).toEqual({ simple: true, limit: 50 }); + }); + + it('returns nothing when the node has no properties', () => { + expect(getParameterDefaults(undefined, {})).toEqual({}); + }); + + it('skips a property that is not shown for the resource and operation', () => { + const defaults = getParameterDefaults( + [ + property({ + name: 'simple', + default: false, + displayOptions: { show: { resource: ['draft'], operation: ['get'] } }, + }), + property({ + name: 'simple', + default: true, + displayOptions: { show: { resource: ['message'], operation: ['get'] } }, + }), + ], + { resource: 'message', operation: 'get' }, + ); + + expect(defaults).toEqual({ simple: true }); + }); + + it('keeps the first default when a name repeats', () => { + const defaults = getParameterDefaults( + [property({ name: 'simple', default: true }), property({ name: 'simple', default: false })], + {}, + ); + + expect(defaults).toEqual({ simple: true }); + }); + + it.each(['constructor', 'toString', '__proto__'])( + 'keeps the default of a property named %s', + (name) => { + const defaults = getParameterDefaults([property({ name, default: false })], {}); + + expect(Object.hasOwn(defaults, name)).toBe(true); + expect(Object.getOwnPropertyDescriptor(defaults, name)?.value).toBe(false); + }, + ); +}); diff --git a/packages/cli/src/__tests__/response-helper.test.ts b/packages/cli/src/__tests__/response-helper.test.ts index 4954207f0bd..e98e910402b 100644 --- a/packages/cli/src/__tests__/response-helper.test.ts +++ b/packages/cli/src/__tests__/response-helper.test.ts @@ -1,4 +1,6 @@ import { mockInstance } from '@n8n/backend-test-utils'; +import { SecurityConfig } from '@n8n/config'; +import { Container } from '@n8n/di'; import type { Request, Response } from 'express'; import { ErrorReporter } from 'n8n-core'; import { UserError } from 'n8n-workflow'; @@ -8,6 +10,7 @@ import { ConflictError, ForbiddenError, InternalServerError, NotFoundError } fro import { LicenseEulaRequiredError } from '@/errors/response-errors/license-eula-required.error'; import { PolicyViolationError } from '@/policy/policy-violation.error'; import { reportError, sendErrorResponse } from '@/response-helper'; +import { setRouteSandboxSetting } from '@/webhooks/webhook-response-headers'; describe('sendErrorResponse', () => { let mockResponse: Response; @@ -56,10 +59,34 @@ describe('sendErrorResponse', () => { ); }); + it('should declare a JSON content type on error responses', () => { + // Simulate an earlier handler having declared an HTML content type. + const res = mock({ + status: vi.fn().mockReturnThis(), + json: vi.fn().mockReturnThis(), + get: vi.fn().mockReturnValue('text/html; charset=utf-8'), + }); + + sendErrorResponse(res, new Error('Regular error')); + + expect(res.setHeader).toHaveBeenCalledWith( + 'Content-Type', + expect.stringContaining('application/json'), + ); + expect(res.status).toHaveBeenCalledWith(500); + expect(res.json).toHaveBeenCalledWith( + expect.objectContaining({ + code: 0, + message: 'Regular error', + }), + ); + }); + describe('form pages', () => { const responseFor = (originalUrl: string) => mock({ req: mock({ originalUrl }), + locals: {}, status: vi.fn().mockReturnThis(), json: vi.fn().mockReturnThis(), render: vi.fn().mockReturnThis(), @@ -88,6 +115,45 @@ describe('sendErrorResponse', () => { expect.stringContaining('sandbox'), ); }); + + describe('when only form sandboxing is disabled', () => { + const securityConfig = Container.get(SecurityConfig); + + beforeEach(() => { + securityConfig.disableFormHtmlSandboxing = true; + }); + + afterEach(() => { + securityConfig.disableFormHtmlSandboxing = false; + }); + + it('should keep the webhook sandbox on a webhook path that looks like a form path', () => { + const res = responseFor('/webhook/n8n-form-demo'); + setRouteSandboxSetting(res, 'webhook'); + + sendErrorResponse(res, new NotFoundError('not found')); + + expect(res.render).toHaveBeenCalledWith('form-trigger-404', { isTestWebhook: false }); + expect(res.setHeader).toHaveBeenCalledWith( + 'Content-Security-Policy', + expect.stringContaining('sandbox'), + ); + expect(res.removeHeader).not.toHaveBeenCalled(); + }); + + it('should not sandbox the form 404 page on a form route', () => { + const res = responseFor('/form/does-not-exist'); + setRouteSandboxSetting(res, 'form'); + + sendErrorResponse(res, new NotFoundError('not found')); + + expect(res.render).toHaveBeenCalledWith('form-trigger-404', { isTestWebhook: false }); + expect(res.setHeader).not.toHaveBeenCalledWith( + 'Content-Security-Policy', + expect.stringContaining('sandbox'), + ); + }); + }); }); }); diff --git a/packages/cli/src/__tests__/utils.test.ts b/packages/cli/src/__tests__/utils.test.ts index 5d448b51653..30e5580d8a8 100644 --- a/packages/cli/src/__tests__/utils.test.ts +++ b/packages/cli/src/__tests__/utils.test.ts @@ -1,7 +1,11 @@ import { generateNanoId } from '@n8n/utils/generate-nano-id'; -import type { INodeType, Workflow } from 'n8n-workflow'; +import type { INode, INodeType, Workflow } from 'n8n-workflow'; +import { CliWorkflowOperationError } from 'n8n-workflow'; +import { mock } from 'vitest-mock-extended'; import { + findCliWorkflowStart, + findSubworkflowStart, shouldAssignExecuteMethod, getAllKeyPaths, isWorkflowIdValid, @@ -12,6 +16,57 @@ import { withExpressionIsolate, } from '../utils'; +describe('workflow start selection', () => { + const manualTrigger = mock({ + name: 'Manual Trigger', + type: 'n8n-nodes-base.manualTrigger', + disabled: false, + }); + const executeWorkflowTrigger = mock({ + name: 'Execute Workflow Trigger', + type: 'n8n-nodes-base.executeWorkflowTrigger', + disabled: false, + }); + const disabledManualTrigger = mock({ + name: 'Disabled Manual Trigger', + type: 'n8n-nodes-base.manualTrigger', + disabled: true, + }); + const disabledExecuteWorkflowTrigger = mock({ + name: 'Disabled Execute Workflow Trigger', + type: 'n8n-nodes-base.executeWorkflowTrigger', + disabled: true, + }); + + it('prefers an enabled subworkflow trigger for CLI execution', () => { + expect(findCliWorkflowStart([manualTrigger, executeWorkflowTrigger])).toBe( + executeWorkflowTrigger, + ); + }); + + it('skips a disabled subworkflow trigger for CLI execution', () => { + expect(findCliWorkflowStart([disabledExecuteWorkflowTrigger, manualTrigger])).toBe( + manualTrigger, + ); + }); + + it('skips a disabled manual trigger for CLI execution', () => { + expect(findCliWorkflowStart([disabledManualTrigger, manualTrigger])).toBe(manualTrigger); + }); + + it('rejects CLI execution when all start nodes are disabled', () => { + expect(() => + findCliWorkflowStart([disabledExecuteWorkflowTrigger, disabledManualTrigger]), + ).toThrow(CliWorkflowOperationError); + }); + + it('keeps disabled subworkflow triggers eligible for subworkflow execution', () => { + expect(findSubworkflowStart([manualTrigger, disabledExecuteWorkflowTrigger])).toBe( + disabledExecuteWorkflowTrigger, + ); + }); +}); + describe('withExpressionIsolate', () => { const acquireIsolate = vi.fn(); const releaseIsolate = vi.fn(); diff --git a/packages/cli/src/__tests__/workflow-execute-additional-data.test.ts b/packages/cli/src/__tests__/workflow-execute-additional-data.test.ts index d746870a2bf..a8b5e28c972 100644 --- a/packages/cli/src/__tests__/workflow-execute-additional-data.test.ts +++ b/packages/cli/src/__tests__/workflow-execute-additional-data.test.ts @@ -379,15 +379,16 @@ describe('WorkflowExecuteAdditionalData', () => { parameters: {}, }, ]; - const subWorkflowData = () => - mock({ + // Plain object: inline code is structure-validated, which a deep mock fails. + const subWorkflowData = (): IWorkflowBase => + ({ id: 'sub-id', name: 'Sub Workflow', nodes: structuredClone(nodes), connections: {}, staticData: {}, settings: {}, - }); + }) as IWorkflowBase; beforeEach(() => { nodeTypes.getByNameAndVersion.mockReturnValue(nodeType); @@ -398,7 +399,7 @@ describe('WorkflowExecuteAdditionalData', () => { it('checks credentials against the triggering user for an inline sub-workflow', async () => { await executeWorkflow( - mock({ id: undefined, code: subWorkflowData() }), + { code: subWorkflowData() }, // `rootExecutionMode` explicit: a deep mock auto-stubs every // property, so leaving it out would hand `??` a truthy proxy. mock({ @@ -415,11 +416,24 @@ describe('WorkflowExecuteAdditionalData', () => { expect(credentialsPermissionChecker.check).not.toHaveBeenCalled(); }); + it('rejects an inline sub-workflow with a non-boolean disabled flag', async () => { + const code = subWorkflowData(); + code.nodes = code.nodes.map((n) => ({ ...n, disabled: 1 as unknown as boolean })); + + await expect( + executeWorkflow({ code }, mock({ userId: 'user-1' }), { + parentWorkflowId: 'parent-1', + executionMode: 'manual', + }), + ).rejects.toThrow('Workflow structure is invalid'); + expect(credentialsPermissionChecker.checkForUser).not.toHaveBeenCalled(); + }); + // A sub-workflow's own WorkflowExecute runs as 'integrated', so the // original mode has to come from the root. it('checks against the triggering user through a nested inline sub-workflow', async () => { await executeWorkflow( - mock({ id: undefined, code: subWorkflowData() }), + { code: subWorkflowData() }, mock({ userId: 'user-1', rootExecutionMode: 'manual', @@ -442,7 +456,7 @@ describe('WorkflowExecuteAdditionalData', () => { // access to it has since changed. it('keeps the project check for an inline sub-workflow in a triggered run', async () => { await executeWorkflow( - mock({ id: undefined, code: subWorkflowData() }), + { code: subWorkflowData() }, mock({ userId: 'publisher-1', rootExecutionMode: undefined, @@ -467,7 +481,7 @@ describe('WorkflowExecuteAdditionalData', () => { 'checks against the acting user for an inline sub-workflow in a %s run', async (executionMode) => { await executeWorkflow( - mock({ id: undefined, code: subWorkflowData() }), + { code: subWorkflowData() }, mock({ userId: 'user-1', rootExecutionMode: undefined, @@ -502,7 +516,7 @@ describe('WorkflowExecuteAdditionalData', () => { it('falls back to the project check for an inline sub-workflow without a triggering user', async () => { const workflowData = subWorkflowData(); await executeWorkflow( - mock({ id: undefined, code: workflowData }), + { code: workflowData }, mock({ userId: undefined }), { parentWorkflowId: 'parent-1', executionMode: 'webhook' }, ); @@ -555,7 +569,7 @@ describe('WorkflowExecuteAdditionalData', () => { it('preserves parent static-data persistence for inline definitions without an id', async () => { await executeWorkflow( - { code: mock({ ...subWorkflowData(), id: undefined }) }, + { code: { ...subWorkflowData(), id: undefined } as unknown as IWorkflowBase }, mock({ userId: undefined }), { parentWorkflowId: 'parent-1', executionMode: 'webhook' }, ); @@ -579,7 +593,7 @@ describe('WorkflowExecuteAdditionalData', () => { it('preserves the triggering user in the sub-workflow additional data for inline sub-workflows so nested inline calls stay scoped to that user', async () => { await executeWorkflow( - mock({ id: undefined, code: subWorkflowData() }), + { code: subWorkflowData() }, mock({ userId: 'user-1' }), mock({ loadedWorkflowData: subWorkflowData(), @@ -721,6 +735,75 @@ describe('WorkflowExecuteAdditionalData', () => { expect(response.dynamicCredentialsResolvedUserId).toBeUndefined(); }); + describe('credentials the sub-workflow references', () => { + beforeEach(() => { + credentialsPermissionChecker.getCredentialIdsForNodes.mockReturnValue(['child-cred']); + }); + + afterEach(() => { + delete process.env.N8N_ENV_FEAT_CRED_SHARING; + }); + + const runSubWorkflow = async () => + await executeWorkflow( + mock(), + mock(), + mock({ + loadedWorkflowData: undefined, + doNotWaitToFinish: false, + }), + ); + + it('reports them to the caller with credential sharing on', async () => { + process.env.N8N_ENV_FEAT_CRED_SHARING = 'true'; + processRunExecutionData.mockReturnValue( + getCancelablePromise(getMockRunWithCredentialFlags({})), + ); + + const response = await runSubWorkflow(); + + expect(response.usedCredentialIds).toEqual(['child-cred']); + }); + + it('rides them on the error when the sub-workflow fails', async () => { + process.env.N8N_ENV_FEAT_CRED_SHARING = 'true'; + processRunExecutionData.mockReturnValue( + getCancelablePromise( + mock({ + data: { + subWorkflowOutput: undefined, + resultData: { + runData: { [LAST_NODE_EXECUTED]: [{ startTime: 100 }] }, + lastNodeExecuted: LAST_NODE_EXECUTED, + error: { message: 'child failed', name: 'NodeOperationError' }, + }, + executionData: { runtimeData: {} }, + }, + finished: false, + mode: 'manual', + startedAt: new Date(), + status: 'error', + waitTill: undefined, + }), + ), + ); + + await expect(runSubWorkflow()).rejects.toMatchObject({ + dynamicCredentialsUsage: { usedCredentialIds: ['child-cred'] }, + }); + }); + + it('reports nothing with credential sharing off', async () => { + processRunExecutionData.mockReturnValue( + getCancelablePromise(getMockRunWithCredentialFlags({})), + ); + + const response = await runSubWorkflow(); + + expect(response.usedCredentialIds).toBeUndefined(); + }); + }); + describe('failed sub-workflow', () => { const getMockFailedRunWithCredentialFlags = ( task: Partial, @@ -1324,22 +1407,22 @@ describe('WorkflowExecuteAdditionalData', () => { }); it('should use provided workflow code when id is not provided', async () => { - const workflowCode = mock({ + const workflowCode = { id: 'code-workflow', name: 'Code Workflow', active: false, nodes: [ - mock({ + { id: 'node1', type: 'n8n-nodes-base.set', name: 'Node 1', typeVersion: 1, parameters: {}, position: [250, 300], - }), + } as INode, ], connections: {}, - }); + } as IWorkflowBase; const result = await getPublishedWorkflowData({ code: workflowCode }, 'parent-workflow-id'); diff --git a/packages/cli/src/__tests__/workflow-helpers.test.ts b/packages/cli/src/__tests__/workflow-helpers.test.ts index a298889f6b5..aedd4e4f41a 100644 --- a/packages/cli/src/__tests__/workflow-helpers.test.ts +++ b/packages/cli/src/__tests__/workflow-helpers.test.ts @@ -16,6 +16,7 @@ import type { import { VariablesService } from '@/environments.ee/variables/variables.service.ee'; import { ExecutionPersistence } from '@/executions/execution-persistence'; +import { CredentialsPermissionChecker } from '@/executions/pre-execution-checks'; import { NodeTypes } from '@/node-types'; import { OwnershipService } from '@/services/ownership.service'; import { @@ -1019,6 +1020,21 @@ describe('updateParentExecutionWithChildResults', () => { }; }; + it('leaves a parent parked at a node boundary alone', async () => { + const executionPersistence = mockInstance(ExecutionPersistence); + const parked = waitingParent(); + parked.data.waitReason = 'suspended'; + executionPersistence.findSingleExecution.mockResolvedValue(parked); + + const resumed = await updateParentExecutionWithChildResults( + PARENT_ID, + childRun('success', 'Last', { data: { main: [[{ json: { out: 1 } }]] } }), + ); + + expect(resumed).toBe(false); + expect(executionPersistence.updateExistingExecution).not.toHaveBeenCalled(); + }); + // Runs the workflow helper against a waiting parent and returns the updated stack entry. async function resumeWith( child: IRun, @@ -1273,6 +1289,104 @@ describe('updateParentExecutionWithChildResults', () => { expect(persisted.data.executionData?.runtimeData?.executedByUserId).toBe('resolved-user'); }); + describe('credentials the sub-workflows reference', () => { + afterEach(() => { + delete process.env.N8N_ENV_FEAT_CRED_SHARING; + }); + + it('stamps them on the waiting task and the resume stash, joining sibling children', async () => { + process.env.N8N_ENV_FEAT_CRED_SHARING = 'true'; + const parent = waitingParent(); + parent.data.resultData = { + runData: { + 'Execute Sub-workflow': [ + { + startTime: 0, + executionTime: 0, + executionIndex: 0, + executionStatus: 'waiting', + source: [], + } as ITaskData, + ], + }, + } as unknown as IExecutionResponse['data']['resultData']; + const executionPersistence = mockInstance(ExecutionPersistence); + executionPersistence.findSingleExecution.mockResolvedValue(parent); + const permissionChecker = mockInstance(CredentialsPermissionChecker); + permissionChecker.getCredentialIdsForNodes + .mockReturnValueOnce(['first-cred']) + .mockReturnValueOnce(['second-cred']); + const childWorkflow = mock({ nodes: [] }); + const child = () => childRun('success', 'Done', { data: { main: [[{ json: { out: 1 } }]] } }); + + await updateParentExecutionWithChildResults(PARENT_ID, child(), undefined, childWorkflow); + await updateParentExecutionWithChildResults(PARENT_ID, child(), undefined, childWorkflow); + + const waitingTask = parent.data.resultData.runData['Execute Sub-workflow'][0]; + expect(waitingTask.usedCredentialIds).toEqual(['first-cred', 'second-cred']); + const entry = parent.data.executionData!.nodeExecutionStack[0] as unknown as StackEntry; + expect(entry.metadata?.dynamicCredentialsUsage?.usedCredentialIds).toEqual([ + 'first-cred', + 'second-cred', + ]); + }); + + it('stamps them when the sub-workflow fails, next to the resume error', async () => { + process.env.N8N_ENV_FEAT_CRED_SHARING = 'true'; + const parent = waitingParent(); + parent.data.resultData = { + runData: { + 'Execute Sub-workflow': [ + { + startTime: 0, + executionTime: 0, + executionIndex: 0, + executionStatus: 'waiting', + source: [], + } as ITaskData, + ], + }, + } as unknown as IExecutionResponse['data']['resultData']; + const executionPersistence = mockInstance(ExecutionPersistence); + executionPersistence.findSingleExecution.mockResolvedValue(parent); + mockInstance(CredentialsPermissionChecker).getCredentialIdsForNodes.mockReturnValue([ + 'child-cred', + ]); + const error = { name: 'NodeOperationError', message: 'ERROR' } as unknown as ExecutionError; + + await updateParentExecutionWithChildResults( + PARENT_ID, + childRun('error', 'Stop and Error', { error }, error), + undefined, + mock({ nodes: [] }), + ); + + const waitingTask = parent.data.resultData.runData['Execute Sub-workflow'][0]; + expect(waitingTask.usedCredentialIds).toEqual(['child-cred']); + const entry = parent.data.executionData!.nodeExecutionStack[0] as unknown as StackEntry; + expect(entry.metadata?.resumeError).toMatchObject({ message: 'ERROR' }); + expect(entry.metadata?.dynamicCredentialsUsage?.usedCredentialIds).toEqual(['child-cred']); + }); + + it('reports nothing with credential sharing off', async () => { + const parent = waitingParent(); + const executionPersistence = mockInstance(ExecutionPersistence); + executionPersistence.findSingleExecution.mockResolvedValue(parent); + const permissionChecker = mockInstance(CredentialsPermissionChecker); + + await updateParentExecutionWithChildResults( + PARENT_ID, + childRun('success', 'Done', { data: { main: [[{ json: { out: 1 } }]] } }), + undefined, + mock({ nodes: [] }), + ); + + expect(permissionChecker.getCredentialIdsForNodes).not.toHaveBeenCalled(); + const entry = parent.data.executionData!.nodeExecutionStack[0] as unknown as StackEntry; + expect(entry.metadata?.dynamicCredentialsUsage?.usedCredentialIds).toBeUndefined(); + }); + }); + // In "run once for each item" mode multiple children update the same waiting // parent. Contract: if any child errored before the parent resumed, the parent // node fails — a later successful sibling must not mask the error. diff --git a/packages/cli/src/abstract-server.ts b/packages/cli/src/abstract-server.ts index 4f003949994..8339890f670 100644 --- a/packages/cli/src/abstract-server.ts +++ b/packages/cli/src/abstract-server.ts @@ -269,7 +269,7 @@ export abstract class AbstractServer { // Register a handler for waiting forms (excluded from metrics to avoid double-counting) this.app.all( `/${this.endpointFormWaiting}/:path{/:suffix}`, - createWebhookHandlerFor(Container.get(WaitingForms)), + createWebhookHandlerFor(Container.get(WaitingForms), undefined, 'form'), ); // Register a handler for waiting webhooks (excluded from metrics to avoid double-counting) diff --git a/packages/cli/src/auth/__tests__/auth-service-browser-id-whitelist.test.ts b/packages/cli/src/auth/__tests__/auth-service-browser-id-whitelist.test.ts index b142f139a5a..853c1f360a8 100644 --- a/packages/cli/src/auth/__tests__/auth-service-browser-id-whitelist.test.ts +++ b/packages/cli/src/auth/__tests__/auth-service-browser-id-whitelist.test.ts @@ -4,8 +4,7 @@ import { mock } from 'vitest-mock-extended'; import { AuthService } from '@/auth/auth.service'; import type { MfaService } from '@/mfa/mfa.service'; -import type { JwtService } from '@/services/jwt.service'; -import type { UrlService } from '@n8n/backend-services'; +import type { JwtService, UrlService } from '@n8n/backend-services'; describe('AuthService Browser ID Whitelist', () => { let authService: AuthService; diff --git a/packages/cli/src/auth/__tests__/auth.service.test.ts b/packages/cli/src/auth/__tests__/auth.service.test.ts index b33bd2a62b1..10d55385ef7 100644 --- a/packages/cli/src/auth/__tests__/auth.service.test.ts +++ b/packages/cli/src/auth/__tests__/auth.service.test.ts @@ -16,8 +16,7 @@ import { AuthService } from '@/auth/auth.service'; import { AUTH_COOKIE_NAME } from '@/constants'; import type { License } from '@/license'; import type { MfaService } from '@/mfa/mfa.service'; -import { JwtService } from '@/services/jwt.service'; -import type { UrlService } from '@n8n/backend-services'; +import { JwtService, type UrlService } from '@n8n/backend-services'; describe('AuthService', () => { const browserId = 'test-browser-id'; diff --git a/packages/cli/src/auth/auth.service.ts b/packages/cli/src/auth/auth.service.ts index 0676855c56d..cddbb094dea 100644 --- a/packages/cli/src/auth/auth.service.ts +++ b/packages/cli/src/auth/auth.service.ts @@ -15,8 +15,7 @@ import { AUTH_COOKIE_NAME, RESPONSE_ERROR_MESSAGES } from '@/constants'; import { AuthError, ForbiddenError } from '@n8n/errors'; import { License } from '@/license'; import { MfaService } from '@/mfa/mfa.service'; -import { JwtService } from '@/services/jwt.service'; -import { UrlService } from '@n8n/backend-services'; +import { JwtService, UrlService } from '@n8n/backend-services'; interface AuthJwtPayload { /** User Id */ diff --git a/packages/cli/src/commands/__tests__/execute-batch.test.ts b/packages/cli/src/commands/__tests__/execute-batch.test.ts index 22e11bfe4c5..8935c1f3e40 100644 --- a/packages/cli/src/commands/__tests__/execute-batch.test.ts +++ b/packages/cli/src/commands/__tests__/execute-batch.test.ts @@ -11,7 +11,7 @@ import { } from '@n8n/db'; import { Container } from '@n8n/di'; import { type SelectQueryBuilder } from '@n8n/typeorm'; -import type { IRun } from 'n8n-workflow'; +import { createEmptyRunExecutionData, type INode, type IRun } from 'n8n-workflow'; import { mock } from 'vitest-mock-extended'; import { ActiveExecutions } from '@/active-executions'; @@ -122,3 +122,47 @@ test('should start a task runner and the policy modules', async () => { test('execute:batch needs the expression engine', () => { expect(new ExecuteBatch().needsExpressionEngine).toBe(true); }); + +test.each([true, false])( + 'starts from the selected trigger when pinned data is %s', + async (pinned) => { + const startingNode = mock({ + name: 'Execute Workflow Trigger', + type: 'n8n-nodes-base.executeWorkflowTrigger', + notes: '', + }); + const workflow = mock({ + id: '123', + nodes: [ + mock({ + name: 'Manual Trigger', + type: 'n8n-nodes-base.manualTrigger', + notes: '', + }), + startingNode, + ], + pinData: pinned ? { [startingNode.name]: [{ json: {} }] } : undefined, + }); + ExecuteBatch.instanceOwner = mock({ id: 'owner-id' }); + ExecuteBatch.cancelled = false; + workflowRunner.run.mockResolvedValue('execution-id'); + activeExecutions.getPostExecutePromise.mockResolvedValue({ + ...mock(), + startedAt: new Date('2026-01-01T00:00:00Z'), + stoppedAt: new Date('2026-01-01T00:00:01Z'), + data: createEmptyRunExecutionData(), + }); + workflowRunner.run.mockClear(); + + const result = await new ExecuteBatch().startThread(workflow); + + expect(result.error).toBeUndefined(); + expect(result.executionStatus).toBe('success'); + expect(workflowRunner.run).toHaveBeenCalledExactlyOnceWith({ + executionMode: 'cli', + triggerToStartFrom: { name: startingNode.name }, + workflowData: workflow, + userId: 'owner-id', + }); + }, +); diff --git a/packages/cli/src/commands/__tests__/execute.disabled-triggers.test.ts b/packages/cli/src/commands/__tests__/execute.disabled-triggers.test.ts new file mode 100644 index 00000000000..dd6f7e2c9fd --- /dev/null +++ b/packages/cli/src/commands/__tests__/execute.disabled-triggers.test.ts @@ -0,0 +1,144 @@ +import { Logger, ModuleRegistry } from '@n8n/backend-common'; +import { EventService } from '@n8n/backend-services'; +import { mockInstance } from '@n8n/backend-test-utils'; +import { GlobalConfig } from '@n8n/config'; +import type { Project, User, WorkflowEntity } from '@n8n/db'; +import { WorkflowRepository } from '@n8n/db'; +import { Container } from '@n8n/di'; +import { ExecutionLifecycleHooks } from 'n8n-core'; +import { ExecuteWorkflowTrigger } from 'n8n-nodes-base/nodes/ExecuteWorkflow/ExecuteWorkflowTrigger/ExecuteWorkflowTrigger.node'; +import { ManualTrigger } from 'n8n-nodes-base/nodes/ManualTrigger/ManualTrigger.node'; +import { NoOp } from 'n8n-nodes-base/nodes/NoOp/NoOp.node'; +import type { + INode, + INodeType, + INodeTypes, + IRun, + IWorkflowExecuteAdditionalData, +} from 'n8n-workflow'; +import { createEmptyRunExecutionData, Workflow } from 'n8n-workflow'; +import { mock } from 'vitest-mock-extended'; + +import { ActiveExecutions } from '@/active-executions'; +import { ManualExecutionService } from '@/manual-execution.service'; +import { OwnershipService } from '@/services/ownership.service'; +import { ShutdownService } from '@/shutdown/shutdown.service'; +import { WorkflowRunner } from '@/workflow-runner'; + +import { Execute } from '../execute'; +import { ExecuteBatch } from '../execute-batch'; + +mockInstance(Logger); +const workflowRepository = mockInstance(WorkflowRepository); +const ownershipService = mockInstance(OwnershipService); +const workflowRunner = mockInstance(WorkflowRunner); +const activeExecutions = mockInstance(ActiveExecutions); +mockInstance(EventService); +mockInstance(ShutdownService); +mockInstance(ModuleRegistry); +mockInstance(GlobalConfig, { + executions: { mode: 'regular' }, + expressionEngine: { engine: 'legacy' }, + generic: { gracefulShutdownTimeout: 30 }, +}); + +test.each(['execute', 'execute-batch'])( + '%s runs the enabled branch when the subworkflow trigger is disabled', + async (command) => { + const nodes = [ + { name: 'Manual Trigger', type: 'n8n-nodes-base.manualTrigger' }, + { + name: 'Execute Workflow Trigger', + type: 'n8n-nodes-base.executeWorkflowTrigger', + disabled: true, + }, + { name: 'Manual Branch', type: 'n8n-nodes-base.noOp' }, + { name: 'Subworkflow Branch', type: 'n8n-nodes-base.noOp' }, + ].map((node, index) => ({ + ...node, + id: `node-${index}`, + typeVersion: 1, + position: [0, 0], + parameters: {}, + notes: '', + })); + const workflowData = mock({ + id: 'workflow-id', + name: 'Disabled trigger workflow', + nodes, + connections: { + 'Manual Trigger': { main: [[{ node: 'Manual Branch', type: 'main', index: 0 }]] }, + 'Execute Workflow Trigger': { + main: [[{ node: 'Subworkflow Branch', type: 'main', index: 0 }]], + }, + }, + settings: { executionOrder: 'v1' }, + pinData: undefined, + }); + const owner = mock({ id: 'owner-id' }); + workflowRepository.findOneBy.mockResolvedValue(workflowData); + ownershipService.getInstanceOwner.mockResolvedValue(owner); + ownershipService.getWorkflowProjectCached.mockResolvedValue( + mock({ id: 'project-id', name: 'Project' }), + ); + workflowRunner.run.mockClear(); + workflowRunner.run.mockResolvedValue('execution-id'); + const completedRun: IRun = { + mode: 'cli', + status: 'success', + storedAt: 'db', + startedAt: new Date('2026-01-01T00:00:00Z'), + stoppedAt: new Date('2026-01-01T00:00:01Z'), + data: createEmptyRunExecutionData(), + }; + activeExecutions.getPostExecutePromise.mockResolvedValue(completedRun); + + if (command === 'execute') { + const cmd = new Execute(); + // @ts-expect-error Read-only property + cmd.flags = { id: workflowData.id }; + await cmd.run(); + } else { + ExecuteBatch.instanceOwner = owner; + ExecuteBatch.cancelled = false; + await new ExecuteBatch().startThread(workflowData); + } + + expect(workflowRunner.run).toHaveBeenCalledTimes(1); + const [runData] = workflowRunner.run.mock.calls[0]; + const nodeTypeRegistry: Record = { + 'n8n-nodes-base.manualTrigger': new ManualTrigger(), + 'n8n-nodes-base.executeWorkflowTrigger': new ExecuteWorkflowTrigger(), + 'n8n-nodes-base.noOp': new NoOp(), + }; + const workflow = new Workflow({ + id: workflowData.id, + nodes: workflowData.nodes, + connections: workflowData.connections, + settings: workflowData.settings, + active: false, + nodeTypes: mock({ + getByNameAndVersion: (name) => nodeTypeRegistry[name], + }), + }); + const additionalData = mock({ + hooks: new ExecutionLifecycleHooks('cli', 'execution-id', workflowData), + currentNodeExecutionIndex: 0, + executionId: 'execution-id', + restartExecutionId: undefined, + encryptedRunnerIdentity: undefined, + }); + + // Run the command payload through the real engine to check which branch executes. + const run = await Container.get(ManualExecutionService).runManually( + runData, + workflow, + additionalData, + 'execution-id', + ); + + expect(run.data.resultData.error).toBeUndefined(); + expect(run.status).toBe('success'); + expect(Object.keys(run.data.resultData.runData)).toEqual(['Manual Trigger', 'Manual Branch']); + }, +); diff --git a/packages/cli/src/commands/__tests__/execute.test.ts b/packages/cli/src/commands/__tests__/execute.test.ts index 72d61484526..371f7a49a81 100644 --- a/packages/cli/src/commands/__tests__/execute.test.ts +++ b/packages/cli/src/commands/__tests__/execute.test.ts @@ -11,7 +11,7 @@ import { } from '@n8n/db'; import { Container } from '@n8n/di'; import { ErrorReporter } from 'n8n-core'; -import type { IRun } from 'n8n-workflow'; +import type { INode, IRun } from 'n8n-workflow'; import { Expression } from 'n8n-workflow'; import { mock } from 'vitest-mock-extended'; @@ -274,3 +274,44 @@ test('exitWithCrash logs the crash message to the console', async () => { test('execute needs the expression engine', () => { expect(new Execute().needsExpressionEngine).toBe(true); }); + +test.each([true, false])( + 'starts from the selected trigger when pinned data is %s', + async (pinned) => { + const startingNode = mock({ + name: 'Execute Workflow Trigger', + type: 'n8n-nodes-base.executeWorkflowTrigger', + }); + const workflow = mock({ + id: '123', + nodes: [ + mock({ name: 'Manual Trigger', type: 'n8n-nodes-base.manualTrigger' }), + startingNode, + ], + pinData: pinned ? { [startingNode.name]: [{ json: {} }] } : undefined, + }); + workflowRepository.findOneBy.mockResolvedValue(workflow); + ownershipService.getInstanceOwner.mockResolvedValue(mock({ id: 'owner-id' })); + ownershipService.getWorkflowProjectCached.mockResolvedValue( + mock({ id: 'project-id', name: 'Project' }), + ); + workflowRunner.run.mockResolvedValue('execution-id'); + activeExecutions.getPostExecutePromise.mockResolvedValue( + mock({ data: { resultData: { error: undefined } } }), + ); + workflowRunner.run.mockClear(); + + const cmd = new Execute(); + // @ts-expect-error Protected property + cmd.flags = { id: workflow.id }; + + await cmd.run(); + + expect(workflowRunner.run).toHaveBeenCalledExactlyOnceWith({ + executionMode: 'cli', + triggerToStartFrom: { name: startingNode.name }, + workflowData: workflow, + userId: 'owner-id', + }); + }, +); diff --git a/packages/cli/src/commands/__tests__/start.test.ts b/packages/cli/src/commands/__tests__/start.test.ts index 85e27aab001..937058c75a3 100644 --- a/packages/cli/src/commands/__tests__/start.test.ts +++ b/packages/cli/src/commands/__tests__/start.test.ts @@ -33,8 +33,7 @@ import { OtelService } from '@/modules/otel/otel.service'; import { NodeTypes } from '@/node-types'; import { PostHogClient } from '@/posthog'; import { PollJobProvider } from '@/scheduling/poll-trigger-node/poll-job-provider'; -import { JwtService } from '@/services/jwt.service'; -import { RoleCacheService } from '@n8n/backend-services'; +import { JwtService, RoleCacheService } from '@n8n/backend-services'; import { ShutdownService } from '@/shutdown/shutdown.service'; import { TaskRunnerModule } from '@/task-runners/task-runner-module'; diff --git a/packages/cli/src/commands/__tests__/webhook.test.ts b/packages/cli/src/commands/__tests__/webhook.test.ts index 35443822c79..6f09b2d9b54 100644 --- a/packages/cli/src/commands/__tests__/webhook.test.ts +++ b/packages/cli/src/commands/__tests__/webhook.test.ts @@ -11,8 +11,7 @@ import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials'; import { PubSubRegistry } from '@/scaling/pubsub/pubsub.registry'; import { Subscriber } from '@/scaling/pubsub/subscriber.service'; import { SystemTaskRunner } from '@/scheduling/system-tasks/system-task-runner'; -import { JwtService } from '@/services/jwt.service'; -import { RedisClientService } from '@n8n/backend-services'; +import { JwtService, RedisClientService } from '@n8n/backend-services'; import { WebhookServer } from '@/webhooks/webhook-server'; import { BaseCommand } from '../base-command'; diff --git a/packages/cli/src/commands/__tests__/worker.test.ts b/packages/cli/src/commands/__tests__/worker.test.ts index 80857b40ec7..b5fe866adfa 100644 --- a/packages/cli/src/commands/__tests__/worker.test.ts +++ b/packages/cli/src/commands/__tests__/worker.test.ts @@ -1,6 +1,6 @@ import type { Logger } from '@n8n/backend-common'; import { uninstallGlobalProxyAgent } from '@n8n/backend-network/testing'; -import type { EventService } from '@n8n/backend-services'; +import { type EventService, JwtService, RedisClientService } from '@n8n/backend-services'; import { mockInstance } from '@n8n/backend-test-utils'; import type { ExecutionsConfig } from '@n8n/config'; import { GlobalConfig } from '@n8n/config'; @@ -34,8 +34,6 @@ import { Subscriber } from '@/scaling/pubsub/subscriber.service'; import { WorkerServer } from '@/scaling/worker-server'; import { WorkerStatusService } from '@/scaling/worker-status.service.ee'; import { SystemTaskRunner } from '@/scheduling/system-tasks/system-task-runner'; -import { JwtService } from '@/services/jwt.service'; -import { RedisClientService } from '@n8n/backend-services'; import { ShutdownService } from '@/shutdown/shutdown.service'; import { TaskRunnerModule } from '@/task-runners/task-runner-module'; diff --git a/packages/cli/src/commands/execute-batch.ts b/packages/cli/src/commands/execute-batch.ts index 0eaaf0dda2f..6f81f31234f 100644 --- a/packages/cli/src/commands/execute-batch.ts +++ b/packages/cli/src/commands/execute-batch.ts @@ -662,7 +662,7 @@ export class ExecuteBatch extends BaseCommand> { const runData: IWorkflowExecutionDataProcess = { executionMode: 'cli', - startNodes: [{ name: startingNode.name, sourceData: null }], + triggerToStartFrom: { name: startingNode.name }, workflowData, userId: ExecuteBatch.instanceOwner.id, }; diff --git a/packages/cli/src/commands/execute.ts b/packages/cli/src/commands/execute.ts index db51dddc440..c3391126cb3 100644 --- a/packages/cli/src/commands/execute.ts +++ b/packages/cli/src/commands/execute.ts @@ -90,7 +90,7 @@ export class Execute extends BaseCommand> { ); const runData: IWorkflowExecutionDataProcess = { executionMode: 'cli', - startNodes: [{ name: startingNode.name, sourceData: null }], + triggerToStartFrom: { name: startingNode.name }, workflowData, userId: user.id, }; diff --git a/packages/cli/src/commands/start.ts b/packages/cli/src/commands/start.ts index c060750046c..3e8d34a1468 100644 --- a/packages/cli/src/commands/start.ts +++ b/packages/cli/src/commands/start.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-unsafe-call */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ -import { EventService, UrlService, RoleCacheService } from '@n8n/backend-services'; +import { EventService, UrlService, RoleCacheService, JwtService } from '@n8n/backend-services'; import { HTML_NONCE_PLACEHOLDER, LICENSE_FEATURES } from '@n8n/constants'; import { AuthRolesService, @@ -39,8 +39,6 @@ import { DurableScheduler } from '@/scheduling/durable-scheduler'; import { PollJobProvider } from '@/scheduling/poll-trigger-node/poll-job-provider'; import { mainSystemTasks } from '@/scheduling/system-tasks/main-system-tasks'; import { Server } from '@/server'; -import { JwtService } from '@/services/jwt.service'; -import { WorkflowHistoryCompactionService } from '@/services/pruning/workflow-history-compaction.service'; import { WaitTracker } from '@/wait-tracker'; @@ -416,8 +414,6 @@ export class Start extends BaseCommand> { await this.server.start(); - Container.get(WorkflowHistoryCompactionService).init(); - // The runner provisions the durable system task jobs, so it must finish // before the scheduler can claim one. await this.initSystemTasks(await mainSystemTasks(this.globalConfig)); diff --git a/packages/cli/src/commands/webhook.ts b/packages/cli/src/commands/webhook.ts index 52d6ab3519f..e03d020887b 100644 --- a/packages/cli/src/commands/webhook.ts +++ b/packages/cli/src/commands/webhook.ts @@ -11,7 +11,7 @@ import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials'; import { Publisher } from '@/scaling/pubsub/publisher.service'; import { PubSubRegistry } from '@/scaling/pubsub/pubsub.registry'; import { Subscriber } from '@/scaling/pubsub/subscriber.service'; -import { JwtService } from '@/services/jwt.service'; +import { JwtService } from '@n8n/backend-services'; import { WebhookServer } from '@/webhooks/webhook-server'; import { BaseCommand } from './base-command'; diff --git a/packages/cli/src/commands/worker.ts b/packages/cli/src/commands/worker.ts index d98ec8fc47c..c03fbbcba4d 100644 --- a/packages/cli/src/commands/worker.ts +++ b/packages/cli/src/commands/worker.ts @@ -21,7 +21,7 @@ import { resolveQueueName, resolveWorkerPoolName } from '@/scaling/queue-name'; import type { ScalingService } from '@/scaling/scaling.service'; import type { WorkerServer, WorkerServerEndpointsConfig } from '@/scaling/worker-server'; import { WorkerStatusService } from '@/scaling/worker-status.service.ee'; -import { JwtService } from '@/services/jwt.service'; +import { JwtService } from '@n8n/backend-services'; import { BaseCommand } from './base-command'; diff --git a/packages/cli/src/controllers/__tests__/users.controller.test.ts b/packages/cli/src/controllers/__tests__/users.controller.test.ts index 94ae053bd01..06fbc3eb282 100644 --- a/packages/cli/src/controllers/__tests__/users.controller.test.ts +++ b/packages/cli/src/controllers/__tests__/users.controller.test.ts @@ -4,8 +4,7 @@ import { mock } from 'vitest-mock-extended'; import { NotFoundError } from '@n8n/errors'; import type { UserRequest } from '@/requests'; -import type { JwtService } from '@/services/jwt.service'; -import type { UrlService } from '@n8n/backend-services'; +import type { JwtService, UrlService } from '@n8n/backend-services'; import type { UserService } from '@/services/user.service'; import { UsersController } from '../users.controller'; diff --git a/packages/cli/src/controllers/e2e.controller.ts b/packages/cli/src/controllers/e2e.controller.ts index 1f362a8d10e..d73a38f5bd5 100644 --- a/packages/cli/src/controllers/e2e.controller.ts +++ b/packages/cli/src/controllers/e2e.controller.ts @@ -146,6 +146,7 @@ export class E2EController { [LICENSE_FEATURES.OTEL_CUSTOM_SPAN_ATTRIBUTES]: false, [LICENSE_FEATURES.WORKER_POOLS]: false, [LICENSE_FEATURES.SCIM]: false, + [LICENSE_FEATURES.TRUSTED_SOURCE_MANAGE]: false, }; private static readonly numericFeaturesDefaults: Record = { diff --git a/packages/cli/src/controllers/oauth/__tests__/oauth2-credential.controller.test.ts b/packages/cli/src/controllers/oauth/__tests__/oauth2-credential.controller.test.ts index 24a6ea872e0..9d42c2e9694 100644 --- a/packages/cli/src/controllers/oauth/__tests__/oauth2-credential.controller.test.ts +++ b/packages/cli/src/controllers/oauth/__tests__/oauth2-credential.controller.test.ts @@ -95,6 +95,57 @@ describe('OAuth2CredentialController', () => { ); }); + /** + * Approving an app for a whole organisation reuses the same reply URL, and + * answers with no code at all. It is a success, not a missing parameter. + */ + it('should render the success page when an administrator approved the app', async () => { + const consentReq = mock(); + consentReq.query = { + admin_consent: 'True', + } as OAuthRequest.OAuth2Credential.Callback['query']; + + await controller.handleCallback(consentReq, res); + + // Its own page: `oauth-callback` would report an unrelated open sign-in + // as connected. + expect(res.render).toHaveBeenCalledWith('admin-consent-callback'); + expect(oauthService.renderCallbackError).not.toHaveBeenCalled(); + }); + + it('should render the error page when an administrator refused the app', async () => { + const consentReq = mock(); + consentReq.query = { + admin_consent: 'True', + error: 'consent_required', + error_description: 'AADSTS65004: The resource owner denied the request.', + } as OAuthRequest.OAuth2Credential.Callback['query']; + + await controller.handleCallback(consentReq, res); + + // The description arrives in the URL, so anyone can set it. It is logged, + // never rendered. + expect(oauthService.renderCallbackError).toHaveBeenCalledWith( + res, + 'The administrator did not approve the requested permissions.', + ); + }); + + it('should render the error page when the refusal carries no error parameter', async () => { + const consentReq = mock(); + consentReq.query = { + admin_consent: 'False', + } as OAuthRequest.OAuth2Credential.Callback['query']; + + await controller.handleCallback(consentReq, res); + + expect(oauthService.renderCallbackError).toHaveBeenCalledWith( + res, + 'The administrator did not approve the requested permissions.', + ); + expect(res.render).not.toHaveBeenCalled(); + }); + it('should exchange the code for a valid token, and save it to DB for static credential', async () => { const { ClientOAuth2 } = await import('@n8n/client-oauth2'); const mockGetToken = vi.fn().mockResolvedValue({ diff --git a/packages/cli/src/controllers/oauth/oauth2-credential.controller.ts b/packages/cli/src/controllers/oauth/oauth2-credential.controller.ts index a623b759f3b..8092a3cf219 100644 --- a/packages/cli/src/controllers/oauth/oauth2-credential.controller.ts +++ b/packages/cli/src/controllers/oauth/oauth2-credential.controller.ts @@ -42,6 +42,31 @@ export class OAuth2CredentialController { try { const { code, state: encodedState } = req.query; if (!code || !encodedState) { + // An administrator approving an app for a whole organisation is sent back + // to the same reply URL, and never with a code: that grant lands on the + // tenant, not on a credential. Without this it reads as a failed sign-in, + // although it succeeded. + if (req.query.admin_consent) { + // `False` is the refusal, and it does not always carry an `error`. + if (req.query.admin_consent === 'False' || req.query.error) { + this.logger.error('Administrator consent was refused', { + error: req.query.error, + errorDescription: req.query.error_description, + }); + // The description arrives in the URL, so it stays out of the page. + return this.oauthService.renderCallbackError( + res, + 'The administrator did not approve the requested permissions.', + ); + } + // Its own page, and a silent one. `oauth-callback` announces success + // on a channel every credential sign-in listens to, and this route + // is unauthenticated and carries no state to tie the grant to a + // credential -- so rendering it would report whichever sign-in + // happened to be open as connected. + return res.render('admin-consent-callback'); + } + return this.oauthService.renderCallbackError( res, 'Insufficient parameters for OAuth2 callback.', diff --git a/packages/cli/src/controllers/users.controller.ts b/packages/cli/src/controllers/users.controller.ts index 3b4a3aab687..af530ad9dd4 100644 --- a/packages/cli/src/controllers/users.controller.ts +++ b/packages/cli/src/controllers/users.controller.ts @@ -32,8 +32,7 @@ import { Response } from 'express'; import { AuthService } from '@/auth/auth.service'; import { ForbiddenError, NotFoundError } from '@n8n/errors'; import { UserRequest } from '@/requests'; -import { JwtService } from '@/services/jwt.service'; -import { UrlService } from '@n8n/backend-services'; +import { JwtService, UrlService } from '@n8n/backend-services'; import { UserService } from '@/services/user.service'; @RestController('/users') diff --git a/packages/cli/src/credentials/__tests__/credential-data-merge.test.ts b/packages/cli/src/credentials/__tests__/credential-data-merge.test.ts new file mode 100644 index 00000000000..d9f139dc6cc --- /dev/null +++ b/packages/cli/src/credentials/__tests__/credential-data-merge.test.ts @@ -0,0 +1,311 @@ +import type { ICredentialDataDecryptedObject } from 'n8n-workflow'; + +import { mergeCredentialData, type CredentialArrayMergeMode } from '../credential-data-merge'; + +const EXPRESSION = '={{ $vars.apiKey }}'; +const OTHER_EXPRESSION = '={{ $vars.otherKey }}'; + +describe('mergeCredentialData', () => { + describe.each(['merge-by-index', 'keep-existing'])( + 'with arrays "%s"', + (arrays) => { + it('replaces an existing plain value with an incoming expression', () => { + const result = mergeCredentialData({ + existing: { apiKey: 'secret' }, + incoming: { apiKey: EXPRESSION }, + arrays, + }); + + expect(result).toEqual({ apiKey: EXPRESSION }); + }); + + it('replaces an existing expression with an incoming expression', () => { + const result = mergeCredentialData({ + existing: { apiKey: OTHER_EXPRESSION }, + incoming: { apiKey: EXPRESSION }, + arrays, + }); + + expect(result).toEqual({ apiKey: EXPRESSION }); + }); + + it('keeps existing-only keys, including oauthTokenData', () => { + const oauthTokenData = { access_token: 'token', refresh_token: 'refresh' }; + + const result = mergeCredentialData({ + existing: { clientId: 'id', oauthTokenData }, + incoming: { clientSecret: EXPRESSION }, + arrays, + }); + + expect(result).toEqual({ clientId: 'id', clientSecret: EXPRESSION, oauthTokenData }); + }); + + it('keeps an existing-only key that shares a name with an inherited property', () => { + const result = mergeCredentialData({ + existing: { toString: 'secret', apiKey: 'key' }, + incoming: { apiKey: EXPRESSION }, + arrays, + }); + + expect(result).toEqual({ toString: 'secret', apiKey: EXPRESSION }); + }); + + it('does not read an inherited property as the existing value', () => { + const result = mergeCredentialData({ + existing: {}, + incoming: { toString: '' }, + arrays, + }); + + expect(result).toEqual({ toString: '' }); + }); + + it('adds an incoming-only key', () => { + const result = mergeCredentialData({ + existing: { apiKey: 'secret' }, + incoming: { domain: EXPRESSION }, + arrays, + }); + + expect(result).toEqual({ apiKey: 'secret', domain: EXPRESSION }); + }); + + it('merges nested objects key by key', () => { + const result = mergeCredentialData({ + existing: { auth: { user: 'admin', password: 'secret', realm: 'local' } }, + incoming: { auth: { user: EXPRESSION, password: '' } }, + arrays, + }); + + expect(result).toEqual({ auth: { user: EXPRESSION, password: 'secret', realm: 'local' } }); + }); + + it('replaces an existing non-object value with an incoming object', () => { + const result = mergeCredentialData({ + existing: { config: 'plain' }, + incoming: { config: { host: EXPRESSION } }, + arrays, + }); + + expect(result).toEqual({ config: { host: EXPRESSION } }); + }); + + it('keeps the existing value when the incoming value is an empty string', () => { + const result = mergeCredentialData({ + existing: { apiKey: 'secret' }, + incoming: { apiKey: '' }, + arrays, + }); + + expect(result).toEqual({ apiKey: 'secret' }); + }); + + it('keeps an empty string when the existing data has no value for the key', () => { + const result = mergeCredentialData({ + existing: {}, + incoming: { apiKey: '' }, + arrays, + }); + + expect(result).toEqual({ apiKey: '' }); + }); + + it('takes incoming numbers and booleans', () => { + const result = mergeCredentialData({ + existing: { port: 3000, ssl: false }, + incoming: { port: 5432, ssl: true }, + arrays, + }); + + expect(result).toEqual({ port: 5432, ssl: true }); + }); + + it('keeps the existing value when the incoming value is null', () => { + const result = mergeCredentialData({ + existing: { apiKey: 'secret' }, + incoming: { apiKey: null } as unknown as ICredentialDataDecryptedObject, + arrays, + }); + + expect(result).toEqual({ apiKey: 'secret' }); + }); + + it('does not mutate the inputs', () => { + const existing: ICredentialDataDecryptedObject = { + apiKey: 'secret', + auth: { user: 'admin' }, + headers: [{ name: 'X-Key', value: 'one' }], + }; + const incoming: ICredentialDataDecryptedObject = { + apiKey: EXPRESSION, + auth: { user: EXPRESSION }, + headers: [{ value: OTHER_EXPRESSION }], + }; + const existingBefore = structuredClone(existing); + const incomingBefore = structuredClone(incoming); + + mergeCredentialData({ existing, incoming, arrays }); + + expect(existing).toEqual(existingBefore); + expect(incoming).toEqual(incomingBefore); + }); + }, + ); + + describe('with arrays "merge-by-index"', () => { + const arrays = 'merge-by-index'; + + it('merges arrays of equal length by index', () => { + const result = mergeCredentialData({ + existing: { + headers: [ + { name: 'X-One', value: 'secret-one' }, + { name: 'X-Two', value: 'secret-two' }, + ], + }, + incoming: { headers: [{ name: '', value: EXPRESSION }, { value: '' }] }, + arrays, + }); + + expect(result).toEqual({ + headers: [ + { name: 'X-One', value: EXPRESSION }, + { name: 'X-Two', value: 'secret-two' }, + ], + }); + }); + + it('replaces an array of different length with the incoming array', () => { + const incomingHeaders = [{ value: EXPRESSION }]; + + const result = mergeCredentialData({ + existing: { + headers: [ + { name: 'X-One', value: 'secret-one' }, + { name: 'X-Two', value: 'secret-two' }, + ], + }, + incoming: { headers: incomingHeaders }, + arrays, + }); + + expect(result).toEqual({ headers: incomingHeaders }); + }); + + it('adds an incoming array when the existing data has none', () => { + const result = mergeCredentialData({ + existing: {}, + incoming: { scopes: [EXPRESSION] }, + arrays, + }); + + expect(result).toEqual({ scopes: [EXPRESSION] }); + }); + + it('applies the mode to arrays nested in objects inside arrays', () => { + const result = mergeCredentialData({ + existing: { groups: [{ tags: ['a', 'b'] }] }, + incoming: { groups: [{ tags: [EXPRESSION, ''] }] }, + arrays, + }); + + expect(result).toEqual({ groups: [{ tags: [EXPRESSION, 'b'] }] }); + }); + + it('adds a new incoming object that merges to no fields', () => { + const result = mergeCredentialData({ + existing: {}, + incoming: { config: { host: null } }, + arrays, + }); + + expect(result).toEqual({ config: {} }); + }); + }); + + describe('with arrays "keep-existing"', () => { + const arrays = 'keep-existing'; + + it('keeps an existing array of equal length as it is', () => { + const existingHeaders = [ + { name: 'X-One', value: 'secret-one' }, + { name: 'X-Two', value: 'secret-two' }, + ]; + + const result = mergeCredentialData({ + existing: { headers: existingHeaders }, + incoming: { headers: [{ value: EXPRESSION }, { value: OTHER_EXPRESSION }] }, + arrays, + }); + + expect(result).toEqual({ headers: existingHeaders }); + }); + + it('keeps an existing array of different length as it is', () => { + const existingHeaders = [ + { name: 'X-One', value: 'secret-one' }, + { name: 'X-Two', value: 'secret-two' }, + ]; + + const result = mergeCredentialData({ + existing: { headers: existingHeaders }, + incoming: { headers: [{ value: EXPRESSION }] }, + arrays, + }); + + expect(result).toEqual({ headers: existingHeaders }); + }); + + it('does not add an incoming array when the existing data has no value for the key', () => { + const result = mergeCredentialData({ + existing: { apiKey: 'secret' }, + incoming: { headers: [{ value: EXPRESSION }] }, + arrays, + }); + + expect(result).toEqual({ apiKey: 'secret' }); + expect(result).not.toHaveProperty('headers'); + }); + + it('keeps an array nested in an object', () => { + const result = mergeCredentialData({ + existing: { config: { host: 'db.local', hosts: ['a', 'b'] } }, + incoming: { config: { host: EXPRESSION, hosts: [EXPRESSION] } }, + arrays, + }); + + expect(result).toEqual({ config: { host: EXPRESSION, hosts: ['a', 'b'] } }); + }); + + it('does not add an array nested in a new incoming object', () => { + const result = mergeCredentialData({ + existing: {}, + incoming: { config: { host: EXPRESSION, hosts: [EXPRESSION] } }, + arrays, + }); + + expect(result).toEqual({ config: { host: EXPRESSION } }); + }); + + it('does not add a new incoming object that holds only arrays', () => { + const result = mergeCredentialData({ + existing: { apiKey: 'secret' }, + incoming: { config: { headers: [EXPRESSION], nested: { hosts: [EXPRESSION] } } }, + arrays, + }); + + expect(result).toEqual({ apiKey: 'secret' }); + }); + + it('keeps an existing object when the incoming object holds only arrays', () => { + const result = mergeCredentialData({ + existing: { config: {} }, + incoming: { config: { headers: [EXPRESSION] } }, + arrays, + }); + + expect(result).toEqual({ config: {} }); + }); + }); +}); diff --git a/packages/cli/src/credentials/__tests__/credential-dependency.service.test.ts b/packages/cli/src/credentials/__tests__/credential-dependency.service.test.ts index e7c04d2d8c2..d880de2c86f 100644 --- a/packages/cli/src/credentials/__tests__/credential-dependency.service.test.ts +++ b/packages/cli/src/credentials/__tests__/credential-dependency.service.test.ts @@ -56,10 +56,10 @@ describe('CredentialDependencyService', () => { entityManager, }); - expect(secretsProviderConnectionRepository.findIdsByProviderKeys).toHaveBeenCalledWith([ - 'vault', - 'awsSecretsManager', - ]); + expect(secretsProviderConnectionRepository.findIdsByProviderKeys).toHaveBeenCalledWith( + ['vault', 'awsSecretsManager'], + entityManager, + ); expect(credentialDependencyRepository.upsertDependenciesForCredential).toHaveBeenCalledWith({ credentialId: 'cred-1', dependencyType: EXTERNAL_SECRET_PROVIDER_DEPENDENCY_TYPE, @@ -78,7 +78,10 @@ describe('CredentialDependencyService', () => { entityManager, }); - expect(secretsProviderConnectionRepository.findIdsByProviderKeys).toHaveBeenCalledWith([]); + expect(secretsProviderConnectionRepository.findIdsByProviderKeys).toHaveBeenCalledWith( + [], + entityManager, + ); expect(credentialDependencyRepository.upsertDependenciesForCredential).toHaveBeenCalledWith({ credentialId: 'cred-1', dependencyType: EXTERNAL_SECRET_PROVIDER_DEPENDENCY_TYPE, @@ -102,10 +105,10 @@ describe('CredentialDependencyService', () => { entityManager, }); - expect(secretsProviderConnectionRepository.findIdsByProviderKeys).toHaveBeenCalledWith([ - 'vault', - 'awsSecretsManager', - ]); + expect(secretsProviderConnectionRepository.findIdsByProviderKeys).toHaveBeenCalledWith( + ['vault', 'awsSecretsManager'], + entityManager, + ); expect(credentialDependencyRepository.syncDependenciesForCredential).toHaveBeenCalledWith({ credentialId: 'cred-1', dependencyType: EXTERNAL_SECRET_PROVIDER_DEPENDENCY_TYPE, @@ -124,7 +127,10 @@ describe('CredentialDependencyService', () => { entityManager, }); - expect(secretsProviderConnectionRepository.findIdsByProviderKeys).toHaveBeenCalledWith([]); + expect(secretsProviderConnectionRepository.findIdsByProviderKeys).toHaveBeenCalledWith( + [], + entityManager, + ); expect(credentialDependencyRepository.syncDependenciesForCredential).toHaveBeenCalledWith({ credentialId: 'cred-1', dependencyType: EXTERNAL_SECRET_PROVIDER_DEPENDENCY_TYPE, diff --git a/packages/cli/src/credentials/__tests__/credentials.service.test.ts b/packages/cli/src/credentials/__tests__/credentials.service.test.ts index a037bd3c88b..3ad9bf297ea 100644 --- a/packages/cli/src/credentials/__tests__/credentials.service.test.ts +++ b/packages/cli/src/credentials/__tests__/credentials.service.test.ts @@ -3678,6 +3678,141 @@ describe('CredentialsService', () => { expect(result).toEqual([]); }); + it('excludes the personal-route credential when excludePersonalRoute is set', async () => { + flags.credSharingEnabled = true; + credentialsFinderService.findCredentialsForUser.mockResolvedValue([ + makePersonalCredential(), + ]); + credentialsRepository.findAllCredentialsForProject.mockResolvedValue([]); + projectService.getProjectRelationsForUser.mockResolvedValue([ + mock({ projectId: 'target-project' }), + ]); + + const result = await service.getCredentialsAUserCanUseInAWorkflow(user, { + projectId: 'target-project', + excludePersonalRoute: true, + }); + + expect(result).toEqual([]); + }); + + it('keeps a project-shared credential when excludePersonalRoute is set', async () => { + flags.credSharingEnabled = true; + credentialsFinderService.findCredentialsForUser.mockResolvedValue([ + makePersonalCredential(), + ]); + credentialsRepository.findAllCredentialsForProject.mockResolvedValue([ + makePersonalCredential(), + ]); + projectService.getProjectRelationsForUser.mockResolvedValue([ + mock({ projectId: 'target-project' }), + ]); + + const result = await service.getCredentialsAUserCanUseInAWorkflow(user, { + projectId: 'target-project', + excludePersonalRoute: true, + }); + + expect(result).toHaveLength(1); + expect(result[0]).toMatchObject({ id: 'cred-personal' }); + }); + + it('keeps the personal credentials of other users that the project owner may use instance-wide, when excludePersonalRoute is set', async () => { + flags.credSharingEnabled = true; + const foreignCredential = makePersonalCredential(); + foreignCredential.shared = [ + { + credentialsId: 'cred-personal', + role: 'credential:owner', + projectId: 'alice-personal-project', + }, + ] as SharedCredentials[]; + credentialsFinderService.findCredentialsForUser.mockResolvedValue([foreignCredential]); + userRepository.findPersonalOwnerForProject.mockResolvedValue(ownerUser); + credentialsRepository.findAllPersonalCredentials.mockResolvedValue([foreignCredential]); + credentialsRepository.findAllCredentialsForProject.mockResolvedValue([]); + projectService.getProjectRelationsForUser.mockResolvedValue([ + mock({ projectId: 'target-project' }), + ]); + + const result = await service.getCredentialsAUserCanUseInAWorkflow(user, { + projectId: 'target-project', + excludePersonalRoute: true, + }); + + expect(result).toHaveLength(1); + expect(result[0]).toMatchObject({ id: 'cred-personal' }); + }); + + it('keeps the personal credentials of other users for a workflow, when excludePersonalRoute is set', async () => { + flags.credSharingEnabled = true; + const foreignCredential = makePersonalCredential(); + foreignCredential.shared = [ + { + credentialsId: 'cred-personal', + role: 'credential:owner', + projectId: 'alice-personal-project', + }, + ] as SharedCredentials[]; + credentialsFinderService.findCredentialsForUser.mockResolvedValue([foreignCredential]); + userRepository.findPersonalOwnerForWorkflow.mockResolvedValue(ownerUser); + credentialsRepository.findAllPersonalCredentials.mockResolvedValue([foreignCredential]); + credentialsRepository.findAllCredentialsForWorkflow.mockResolvedValue([]); + projectService.getProjectRelationsForUser.mockResolvedValue([ + mock({ projectId: 'target-project' }), + ]); + + const result = await service.getCredentialsAUserCanUseInAWorkflow(user, { + workflowId: 'workflow-1', + excludePersonalRoute: true, + }); + + expect(result).toHaveLength(1); + expect(result[0]).toMatchObject({ id: 'cred-personal' }); + }); + + it('keeps the instance-wide personal credentials when excludePersonalRoute is not set', async () => { + flags.credSharingEnabled = true; + const foreignCredential = makePersonalCredential(); + foreignCredential.shared = [ + { + credentialsId: 'cred-personal', + role: 'credential:owner', + projectId: 'alice-personal-project', + }, + ] as SharedCredentials[]; + credentialsFinderService.findCredentialsForUser.mockResolvedValue([foreignCredential]); + userRepository.findPersonalOwnerForProject.mockResolvedValue(ownerUser); + credentialsRepository.findAllPersonalCredentials.mockResolvedValue([foreignCredential]); + projectService.getProjectRelationsForUser.mockResolvedValue([ + mock({ projectId: 'target-project' }), + ]); + + const result = await service.getCredentialsAUserCanUseInAWorkflow(user, { + projectId: 'target-project', + }); + + expect(result).toHaveLength(1); + }); + + it('keeps the instance-wide personal credentials when the flag is off, even with excludePersonalRoute', async () => { + flags.credSharingEnabled = false; + const foreignCredential = makePersonalCredential(); + credentialsFinderService.findCredentialsForUser.mockResolvedValue([foreignCredential]); + userRepository.findPersonalOwnerForProject.mockResolvedValue(ownerUser); + credentialsRepository.findAllPersonalCredentials.mockResolvedValue([foreignCredential]); + projectService.getProjectRelationsForUser.mockResolvedValue([ + mock({ projectId: 'target-project' }), + ]); + + const result = await service.getCredentialsAUserCanUseInAWorkflow(user, { + projectId: 'target-project', + excludePersonalRoute: true, + }); + + expect(result).toHaveLength(1); + }); + it('includes the credential via the personal route for an unsaved workflow (projectId option)', async () => { flags.credSharingEnabled = true; credentialsFinderService.findCredentialsForUser.mockResolvedValue([ diff --git a/packages/cli/src/credentials/__tests__/pending-authorization-cleanup.task.test.ts b/packages/cli/src/credentials/__tests__/pending-authorization-cleanup.task.test.ts index 0dd6dfb6dec..70c2d1da5eb 100644 --- a/packages/cli/src/credentials/__tests__/pending-authorization-cleanup.task.test.ts +++ b/packages/cli/src/credentials/__tests__/pending-authorization-cleanup.task.test.ts @@ -17,10 +17,10 @@ describe('PendingAuthorizationCleanupTask', () => { }); it('runs durably, on any main, and on the fallback timer as soon as a leader takes over', () => { - expect(task().placement).toEqual({ + expect(task().target).toEqual({ scope: 'cluster', - durable: true, - runOnTakeover: true, + scheduler: { retryOnFailure: true }, + leaderTimer: { runOnTakeover: true }, }); }); diff --git a/packages/cli/src/credentials/credential-data-merge.ts b/packages/cli/src/credentials/credential-data-merge.ts new file mode 100644 index 00000000000..8021a0cd5af --- /dev/null +++ b/packages/cli/src/credentials/credential-data-merge.ts @@ -0,0 +1,113 @@ +import { isRecord } from '@n8n/utils/is-record'; +import type { ICredentialDataDecryptedObject, IDataObject } from 'n8n-workflow'; + +import { containsExpression } from '@/utils'; + +/** + * How to merge an incoming array into the existing value. + * - `merge-by-index`: merge item by item when the lengths match, otherwise use the incoming array. + * - `keep-existing`: keep the existing value. Use this when the incoming array is lossy. + */ +export type CredentialArrayMergeMode = 'merge-by-index' | 'keep-existing'; + +function mergeValue( + incoming: unknown, + existing: unknown, + arrays: CredentialArrayMergeMode, +): unknown { + if (typeof incoming === 'string') { + if (containsExpression(incoming)) { + return incoming; + } else if (existing !== undefined && existing !== null) { + // Existing value is preserved if it exists (secret handling) + return existing; + } + + // The incoming field exists as an empty string (key is part of the schema) + // but existing has no value for it. Preserve the empty string so the field + // is not silently dropped from the merged credential. + return ''; + } + + if (typeof incoming === 'number' || typeof incoming === 'boolean') { + return incoming; + } + + if (Array.isArray(incoming)) { + if (arrays === 'keep-existing') return existing; + + // Only merge by index if lengths match, otherwise array structure has changed + // and we can't reliably match items (could be additions/removals/reordering) + if (Array.isArray(existing) && existing.length === incoming.length) { + return incoming.map((item: unknown, index) => mergeValue(item, existing[index], arrays)); + } + + return incoming; + } + + if (isRecord(incoming)) { + // Merge into an empty object when there is nothing to merge into, so the + // array mode also applies to arrays nested in a new object. + const merged = mergeObjects(incoming, isRecord(existing) ? existing : {}, arrays); + + // Only kept arrays were in the new object. Do not add an empty object for them, + // so that a merge which changes nothing gives the existing data back. + if (arrays === 'keep-existing' && !isRecord(existing) && Object.keys(merged).length === 0) { + return existing; + } + + return merged; + } + + // `null` or another value that carries no data: keep what exists. + return existing; +} + +function mergeObjects( + incoming: Record, + existing: Record, + arrays: CredentialArrayMergeMode, +): Record { + const merged: Record = {}; + + for (const [key, incomingValue] of Object.entries(incoming)) { + // Own keys only, so a name such as `toString` does not resolve to an inherited value. + const existingValue = Object.hasOwn(existing, key) ? existing[key] : undefined; + const mergedValue = mergeValue(incomingValue, existingValue, arrays); + + if (mergedValue !== undefined) { + merged[key] = mergedValue; + } + } + + // Keep existing fields the incoming data does not carry. A field left at its default + // value is not persisted, so it never reaches the incoming data; an absent field carries + // the same "no value to give" meaning as a present-but-blank one, which is already + // preserved above. Without this it would be dropped and reset to its default. This also + // covers oauthTokenData, which incoming data never carries. + for (const [key, existingValue] of Object.entries(existing)) { + if (!Object.hasOwn(incoming, key)) { + merged[key] = existingValue; + } + } + + return merged; +} + +/** + * Merges incoming credential data into existing data. Incoming expressions, + * numbers and booleans overwrite existing values. Incoming plain strings do not + * carry secrets, so the existing value stays. Does not mutate the inputs. + */ +export function mergeCredentialData({ + existing, + incoming, + arrays, +}: { + existing: ICredentialDataDecryptedObject; + incoming: IDataObject; + arrays: CredentialArrayMergeMode; +}): ICredentialDataDecryptedObject { + // Every leaf comes from `existing`, `incoming` or is `''`, so the shape stays credential data. + return mergeObjects(incoming, existing, arrays) as ICredentialDataDecryptedObject; +} diff --git a/packages/cli/src/credentials/credential-dependency.service.ts b/packages/cli/src/credentials/credential-dependency.service.ts index 5deb3e1f50e..2b0986999f1 100644 --- a/packages/cli/src/credentials/credential-dependency.service.ts +++ b/packages/cli/src/credentials/credential-dependency.service.ts @@ -41,9 +41,13 @@ export class CredentialDependencyService { async resolveProviderIdsFromCredentialData( decryptedCredentialData: ICredentialDataDecryptedObject, + entityManager?: EntityManager, ): Promise { const providerKeys = [...extractProviderKeysFromCredentialData(decryptedCredentialData)]; - return await this.secretsProviderConnectionRepository.findIdsByProviderKeys(providerKeys); + return await this.secretsProviderConnectionRepository.findIdsByProviderKeys( + providerKeys, + entityManager, + ); } async upsertExternalSecretProviderDependenciesForCredential({ @@ -55,7 +59,10 @@ export class CredentialDependencyService { decryptedCredentialData: ICredentialDataDecryptedObject; entityManager: EntityManager; }): Promise { - const dependencyIds = await this.resolveProviderIdsFromCredentialData(decryptedCredentialData); + const dependencyIds = await this.resolveProviderIdsFromCredentialData( + decryptedCredentialData, + entityManager, + ); await this.credentialDependencyRepository.upsertDependenciesForCredential({ credentialId, dependencyType: EXTERNAL_SECRET_PROVIDER_DEPENDENCY_TYPE, @@ -73,7 +80,10 @@ export class CredentialDependencyService { decryptedCredentialData: ICredentialDataDecryptedObject; entityManager: EntityManager; }): Promise { - const dependencyIds = await this.resolveProviderIdsFromCredentialData(decryptedCredentialData); + const dependencyIds = await this.resolveProviderIdsFromCredentialData( + decryptedCredentialData, + entityManager, + ); await this.credentialDependencyRepository.syncDependenciesForCredential({ credentialId, dependencyType: EXTERNAL_SECRET_PROVIDER_DEPENDENCY_TYPE, diff --git a/packages/cli/src/credentials/credentials.controller.ts b/packages/cli/src/credentials/credentials.controller.ts index b104728eeb4..37fd0ca6afc 100644 --- a/packages/cli/src/credentials/credentials.controller.ts +++ b/packages/cli/src/credentials/credentials.controller.ts @@ -112,10 +112,14 @@ export class CredentialsController { @Get('/for-workflow') async getProjectCredentials(req: CredentialRequest.ForWorkflow) { - const options = z + const { forAgent, ...scope } = z .union([z.object({ workflowId: z.string() }), z.object({ projectId: z.string() })]) + .and(z.object({ forAgent: z.enum(['true', 'false']).optional() })) .parse(req.query); - return await this.credentialsService.getCredentialsAUserCanUseInAWorkflow(req.user, options); + return await this.credentialsService.getCredentialsAUserCanUseInAWorkflow(req.user, { + ...scope, + excludePersonalRoute: forAgent === 'true', + }); } @Get('/new') diff --git a/packages/cli/src/credentials/credentials.service.ts b/packages/cli/src/credentials/credentials.service.ts index 6a34154ad46..3490c5adfb3 100644 --- a/packages/cli/src/credentials/credentials.service.ts +++ b/packages/cli/src/credentials/credentials.service.ts @@ -628,10 +628,17 @@ export class CredentialsService { * @param options.workflowId The workflow that is being edited * @param options.projectId The project owning the workflow This is useful * for workflows that have not been saved yet. + * @param options.excludePersonalRoute Skip the personal route, which lets a + * user bring their own personal credentials into a team project they are a + * member of. Agents set this because they do not support it yet. The + * instance-wide shortcut for owners and admins in their personal project + * stays in place. */ async getCredentialsAUserCanUseInAWorkflow( user: User, - options: { workflowId: string } | { projectId: string }, + options: ({ workflowId: string } | { projectId: string }) & { + excludePersonalRoute?: boolean; + }, ): Promise { // necessary to get the scopes const projectRelations = await this.projectService.getProjectRelationsForUser(user); @@ -648,9 +655,10 @@ export class CredentialsService { : (await this.findAllCredentialIdsForProject(options.projectId)).map((c) => c.id), ); - const personalRouteCredentialIds = isCredSharingEnabled() - ? await this.findPersonalRouteCredentialIds(user, allCredentials, projectRelations, options) - : new Set(); + const personalRouteCredentialIds = + isCredSharingEnabled() && !options.excludePersonalRoute + ? await this.findPersonalRouteCredentialIds(user, allCredentials, projectRelations, options) + : new Set(); // the union of all three is every credential the user can use in this // workflow or project @@ -2047,20 +2055,23 @@ export class CredentialsService { return await this.persistInstanceCredential({ ...dto, isManaged: false }, user, ctx, options); } - /** - * Creates an empty credential placeholder for package import. Skips field - * validation so every known type can be stubbed; the insert still enforces - * `credential:create` on the target project. A supplied `id` preserves source identity. - */ async createStubCredential( - opts: { id?: string; name: string; type: string; projectId: string }, + opts: { + id?: string; + name: string; + type: string; + projectId: string; + data?: ICredentialDataDecryptedObject; + }, user: User, ): Promise { + const data = opts.data ?? {}; + await this.validateStubCredentialData(data, user, opts.projectId); const encryptedCredential = await this.createEncryptedData({ id: opts.id ?? null, name: opts.name, type: opts.type, - data: {}, + data, }); const credentialEntity = this.credentialsRepository.create({ @@ -2075,7 +2086,7 @@ export class CredentialsService { encryptedCredential, user, opts.projectId, - {}, + data, ); } catch (error) { if (error instanceof CredentialIdConflictError) { @@ -2087,11 +2098,22 @@ export class CredentialsService { } } - /** - * Used to check credential data for creating a new credential. - * TODO: consider refactoring enable using this for both creating and updating, right now only used for creation - * (likely only affects the validateExternalSecretsPermissions call) - */ + async validateStubCredentialData( + data: ICredentialDataDecryptedObject, + user: User, + projectId: string, + ): Promise { + await validateExternalSecretsPermissions({ user, projectId, dataToSave: data }); + if (this.externalSecretsConfig.externalSecretsForProjects) { + await validateAccessToReferencedSecretProviders( + projectId, + data, + this.externalSecretsProviderAccessCheckService, + 'create', + ); + } + } + async checkCredentialData( type: string, data: ICredentialDataDecryptedObject, diff --git a/packages/cli/src/credentials/pending-authorization-cleanup.task.ts b/packages/cli/src/credentials/pending-authorization-cleanup.task.ts index b15e6a0ff4b..469c08484d7 100644 --- a/packages/cli/src/credentials/pending-authorization-cleanup.task.ts +++ b/packages/cli/src/credentials/pending-authorization-cleanup.task.ts @@ -1,8 +1,8 @@ import { Logger } from '@n8n/backend-common'; import { Time } from '@n8n/constants'; import { CredentialsRepository } from '@n8n/db'; -import { SystemTask } from '@n8n/decorators'; -import type { SystemTaskEffects, SystemTaskPlacement, SystemTaskSchedule } from '@n8n/decorators'; +import { clusterTarget, SystemTask } from '@n8n/decorators'; +import type { SystemTaskSchedule } from '@n8n/decorators'; /** * Deletes credentials created for an OAuth popup whose authorization never @@ -19,15 +19,14 @@ export class PendingAuthorizationCleanupTask implements SystemTask { intervalSeconds: 1 * Time.hours.toSeconds, }; - /** A row is either past its deadline or not, so a repeated run deletes nothing new. */ - effects: SystemTaskEffects = 'idempotent'; - - placement: SystemTaskPlacement = { - scope: 'cluster', - durable: true, - /** A new leader on the fallback timer sweeps at once instead of waiting an hour. */ - runOnTakeover: true, - }; + readonly target = clusterTarget({ + /** A row is either past its deadline or not, so a repeated run deletes nothing new. */ + scheduler: { retryOnFailure: true }, + leaderTimer: { + /** A new leader on the fallback timer sweeps at once instead of waiting an hour. */ + runOnTakeover: true, + }, + }); constructor( private readonly logger: Logger, diff --git a/packages/cli/src/deprecation/__tests__/deprecation.service.test.ts b/packages/cli/src/deprecation/__tests__/deprecation.service.test.ts index 793ae9798c9..0782bc64848 100644 --- a/packages/cli/src/deprecation/__tests__/deprecation.service.test.ts +++ b/packages/cli/src/deprecation/__tests__/deprecation.service.test.ts @@ -101,10 +101,31 @@ describe('DeprecationService', () => { ['N8N_AI_ALLOW_SENDING_PARAMETER_VALUES', 'true', false], ['N8N_AI_ALLOW_SENDING_PARAMETER_VALUES', 'invalid', false], ['N8N_AI_ALLOW_SENDING_PARAMETER_VALUES', undefined, false], + ['N8N_SCHEDULER_ENABLED', 'true', true], + ['N8N_SCHEDULER_ENABLED', 'false', true], + ['N8N_SCHEDULER_ENABLED', '0', true], + ['N8N_SCHEDULER_ENABLED', undefined, false], + ['N8N_SCHEDULER_TRIGGER_NODE_MODE', 'new', true], + ['N8N_SCHEDULER_TRIGGER_NODE_MODE', 'legacy', true], + ['N8N_SCHEDULER_TRIGGER_NODE_MODE', undefined, false], + ['N8N_ENV_FEAT_SKIP_DURABLE_SCHEDULER', 'true', true], ])('should detect when %s is `%s`', (envVar, value, mustWarn) => { toTest(envVar, value, mustWarn); }); + test.each([ + ['N8N_SCHEDULER_ENABLED', 'true', 'now on by default'], + ['N8N_SCHEDULER_ENABLED', 'false', 'in-memory scheduler is deprecated'], + ['N8N_SCHEDULER_TRIGGER_NODE_MODE', 'new', 'now the default'], + ['N8N_SCHEDULER_TRIGGER_NODE_MODE', 'legacy', '`legacy` mode is deprecated'], + ])('should explain the scheduler default when %s is `%s`', (envVar, value, expected) => { + process.env[envVar] = value; + + deprecationService.warn(); + + expect(logger.warn.mock.lastCall?.[0]).toContain(expected); + }); + // `toTest` treats a blank value as unset, so set it here directly. test('should not warn when N8N_AI_ALLOW_SENDING_PARAMETER_VALUES is blank', () => { process.env.N8N_AI_ALLOW_SENDING_PARAMETER_VALUES = ''; diff --git a/packages/cli/src/deprecation/deprecation.service.ts b/packages/cli/src/deprecation/deprecation.service.ts index c9a0db35e00..6d8ae06588d 100644 --- a/packages/cli/src/deprecation/deprecation.service.ts +++ b/packages/cli/src/deprecation/deprecation.service.ts @@ -127,6 +127,34 @@ export class DeprecationService { checkValue: (value?: string) => value !== undefined && ['false', '0'].includes(value.toLowerCase()), }, + { + envVar: 'N8N_SCHEDULER_ENABLED', + message: `The durable scheduler is now on by default. ${SAFE_TO_REMOVE}`, + checkValue: (value?: string) => + value !== undefined && !['false', '0'].includes(value.toLowerCase()), + }, + { + envVar: 'N8N_SCHEDULER_ENABLED', + message: + 'The in-memory scheduler is deprecated and will be removed in a future version, together with this variable. Remove this variable to run your schedules on the durable scheduler, which is the default. It keeps scheduled runs across restarts and runs each one only once across instances.', + checkValue: (value?: string) => + value !== undefined && ['false', '0'].includes(value.toLowerCase()), + }, + { + envVar: 'N8N_SCHEDULER_TRIGGER_NODE_MODE', + message: `The \`new\` mode is now the default. ${SAFE_TO_REMOVE}`, + checkValue: (value?: string) => value === 'new', + }, + { + envVar: 'N8N_SCHEDULER_TRIGGER_NODE_MODE', + message: + 'The `legacy` mode is deprecated and will be removed in a future version, together with this variable. Today it keeps "every N seconds/minutes" schedules aligned to the clock (on the minute, on the hour). Remove this variable to use the default `new` mode, which spaces runs a steady N apart, timed from when the workflow was activated.', + checkValue: (value?: string) => value === 'legacy', + }, + { + envVar: 'N8N_ENV_FEAT_SKIP_DURABLE_SCHEDULER', + message: `The "Skip Durable Scheduler" option of the Schedule Trigger node no longer exists. Schedule Triggers use the durable scheduler only when the workflow publication service is enabled; otherwise they remain on the in-memory scheduler. To run all schedules on the in-memory scheduler when the workflow publication service is enabled, set N8N_SCHEDULER_ENABLED=false. ${SAFE_TO_REMOVE}`, + }, { envVar: 'EXECUTIONS_PROCESS', message: SAFE_TO_REMOVE, diff --git a/packages/cli/src/errors/__tests__/rest-error-classifier.test.ts b/packages/cli/src/errors/__tests__/rest-error-classifier.test.ts index 1f7188ff9c0..c952d0fab44 100644 --- a/packages/cli/src/errors/__tests__/rest-error-classifier.test.ts +++ b/packages/cli/src/errors/__tests__/rest-error-classifier.test.ts @@ -1,16 +1,5 @@ import { LicenseEulaRequiredError } from '@/errors/response-errors/license-eula-required.error'; import { classifyRestError, RestErrorKind } from '@n8n/backend-services'; -import { - BadRequest, - Forbidden, - InternalServerError, - MethodNotAllowed, - NotAcceptable, - NotFound, - RequestEntityTooLarge, - Unauthorized, - UnsupportedMediaType, -} from 'express-openapi-validator/dist/framework/types'; describe('classifyRestError', () => { it('includes meta for LicenseEulaRequiredError', () => { @@ -27,24 +16,4 @@ describe('classifyRestError', () => { expect(descriptor.meta).toEqual({ eulaUrl }); } }); - - it.each([ - [NotFound, 404], - [NotAcceptable, 406], - [MethodNotAllowed, 405], - [BadRequest, 400], - [RequestEntityTooLarge, 413], - [InternalServerError, 500], - [UnsupportedMediaType, 415], - [Unauthorized, 401], - [Forbidden, 403], - ])('classifies a %s from the CLI validator package', (ErrorClass, status) => { - const error = new ErrorClass({ path: '/x', message: 'validator error' }); - - expect(classifyRestError(error)).toEqual({ - kind: RestErrorKind.httpError, - status, - message: 'validator error', - }); - }); }); diff --git a/packages/cli/src/errors/uninspectable-subworkflow-source.error.ts b/packages/cli/src/errors/uninspectable-subworkflow-source.error.ts new file mode 100644 index 00000000000..ba686feb263 --- /dev/null +++ b/packages/cli/src/errors/uninspectable-subworkflow-source.error.ts @@ -0,0 +1,11 @@ +import type { INode } from 'n8n-workflow'; +import { NodeOperationError } from 'n8n-workflow'; + +export class UninspectableSubworkflowSourceError extends NodeOperationError { + constructor(node: INode) { + super( + node, + `The '${node.name}' node loads its sub-workflow from a source that is resolved only when the workflow runs, so its credential access cannot be checked on save. Use the "Database" or "Define Below" source instead.`, + ); + } +} diff --git a/packages/cli/src/eventbus/event-message-classes/index.ts b/packages/cli/src/eventbus/event-message-classes/index.ts index b4f410da1c6..5538b252956 100644 --- a/packages/cli/src/eventbus/event-message-classes/index.ts +++ b/packages/cli/src/eventbus/event-message-classes/index.ts @@ -171,6 +171,9 @@ export const eventNamesAudit = [ 'n8n.audit.node-type-policy.document.deleted', 'n8n.audit.node-type-policy.attachments.updated', 'n8n.audit.policy.decision.blocked', + 'n8n.audit.trusted-source.created', + 'n8n.audit.trusted-source.updated', + 'n8n.audit.trusted-source.deleted', ] as const; // Instance MCP server events. Kept as their own list and message class because the payload diff --git a/packages/cli/src/eventbus/message-event-bus/__tests__/event-bus-unsent-message-flush.task.test.ts b/packages/cli/src/eventbus/message-event-bus/__tests__/event-bus-unsent-message-flush.task.test.ts index 82aa13cecca..8f2601d9de1 100644 --- a/packages/cli/src/eventbus/message-event-bus/__tests__/event-bus-unsent-message-flush.task.test.ts +++ b/packages/cli/src/eventbus/message-event-bus/__tests__/event-bus-unsent-message-flush.task.test.ts @@ -17,8 +17,7 @@ describe('EventBusUnsentMessageFlushTask', () => { it('should retry in every kind of instance at the configured interval', () => { expect(task.name).toBe('event-bus-unsent-message-flush'); expect(task.schedule).toEqual({ kind: 'interval', intervalSeconds: 30 }); - expect(task.effects).toBe('non-idempotent'); - expect(task.placement).toEqual({ + expect(task.target).toEqual({ scope: 'instance', instanceTypes: ['main', 'worker', 'webhook'], }); diff --git a/packages/cli/src/eventbus/message-event-bus/event-bus-unsent-message-flush.task.ts b/packages/cli/src/eventbus/message-event-bus/event-bus-unsent-message-flush.task.ts index d4b02b6b55e..0e43e474693 100644 --- a/packages/cli/src/eventbus/message-event-bus/event-bus-unsent-message-flush.task.ts +++ b/packages/cli/src/eventbus/message-event-bus/event-bus-unsent-message-flush.task.ts @@ -1,6 +1,6 @@ import { GlobalConfig } from '@n8n/config'; -import { intervalFromMilliseconds, SystemTask } from '@n8n/decorators'; -import type { SystemTaskEffects, SystemTaskPlacement, SystemTaskSchedule } from '@n8n/decorators'; +import { instanceTarget, intervalFromMilliseconds, SystemTask } from '@n8n/decorators'; +import type { SystemTaskSchedule } from '@n8n/decorators'; import { MessageEventBus } from './message-event-bus'; @@ -16,14 +16,8 @@ export class EventBusUnsentMessageFlushTask implements SystemTask { this.globalConfig.eventBus.checkUnsentInterval, ); - /** A destination can receive a message twice if its confirmation is still in flight. */ - readonly effects: SystemTaskEffects = 'non-idempotent'; - /** The unsent messages are in the event log files of this process, so no other instance can send them. */ - readonly placement: SystemTaskPlacement = { - scope: 'instance', - instanceTypes: ['main', 'worker', 'webhook'], - }; + readonly target = instanceTarget(['main', 'worker', 'webhook']); constructor( private readonly globalConfig: GlobalConfig, diff --git a/packages/cli/src/events/__tests__/log-streaming-event-relay.test.ts b/packages/cli/src/events/__tests__/log-streaming-event-relay.test.ts index cc7f90553ba..fbad5cdd861 100644 --- a/packages/cli/src/events/__tests__/log-streaming-event-relay.test.ts +++ b/packages/cli/src/events/__tests__/log-streaming-event-relay.test.ts @@ -72,6 +72,7 @@ describe('LogStreamingEventRelay', () => { workflowIdPolicy: 'new', credentialMatchingMode: 'id-only', credentialMissingMode: 'must-preexist', + credentialConflictPolicy: 'keep-existing', workflowPublishingPolicy: 'preserve-published-state', missingNodeTypeMode: 'fail', projectConflictPolicy: 'merge', @@ -153,6 +154,7 @@ describe('LogStreamingEventRelay', () => { workflowIdPolicy: 'new', credentialMatchingMode: 'id-only', credentialMissingMode: 'must-preexist', + credentialConflictPolicy: 'keep-existing', workflowPublishingPolicy: 'preserve-published-state', missingNodeTypeMode: 'fail', projectConflictPolicy: 'merge', @@ -3543,4 +3545,38 @@ describe('LogStreamingEventRelay', () => { ); }); }); + describe('trusted source events', () => { + it.each([ + ['trusted-source-created', 'n8n.audit.trusted-source.created'], + ['trusted-source-updated', 'n8n.audit.trusted-source.updated'], + ['trusted-source-deleted', 'n8n.audit.trusted-source.deleted'], + ] as const)('should log on `%s` event with redacted user', (eventName, auditEventName) => { + const event = { + user: { + id: 'user-1', + email: 'owner@n8n.io', + firstName: 'Own', + lastName: 'Er', + role: { slug: 'global:owner' }, + }, + sourceId: 'source-1', + issuer: 'https://idp.example.com', + }; + + eventService.emit(eventName, event); + + expect(eventBus.sendAuditEvent).toHaveBeenCalledWith({ + eventName: auditEventName, + payload: { + userId: 'user-1', + _email: 'owner@n8n.io', + _firstName: 'Own', + _lastName: 'Er', + globalRole: 'global:owner', + sourceId: 'source-1', + issuer: 'https://idp.example.com', + }, + }); + }); + }); }); diff --git a/packages/cli/src/events/__tests__/telemetry-event-relay.test.ts b/packages/cli/src/events/__tests__/telemetry-event-relay.test.ts index cdfc0e3cb31..1999302d5b4 100644 --- a/packages/cli/src/events/__tests__/telemetry-event-relay.test.ts +++ b/packages/cli/src/events/__tests__/telemetry-event-relay.test.ts @@ -112,7 +112,6 @@ describe('TelemetryEventRelay', () => { batchSize: 234, optimizingTimeWindowHours: 400, trimmingTimeWindowDays: 600, - trimOnStartUp: false, }, host: 'localhost', generic: { @@ -3421,6 +3420,7 @@ describe('TelemetryEventRelay', () => { workflowIdPolicy: 'new', credentialMatchingMode: 'id-only', credentialMissingMode: 'must-preexist', + credentialConflictPolicy: 'fail', workflowPublishingPolicy: 'preserve-published-state', missingNodeTypeMode: 'fail', projectConflictPolicy: 'merge', @@ -3491,6 +3491,7 @@ describe('TelemetryEventRelay', () => { workflow_id_policy: 'new', credential_matching_mode: 'id-only', credential_missing_mode: 'must-preexist', + credential_conflict_policy: 'fail', workflow_publishing_policy: 'preserve-published-state', missing_node_type_mode: 'fail', project_conflict_policy: 'merge', diff --git a/packages/cli/src/events/maps/relay.event-map.ts b/packages/cli/src/events/maps/relay.event-map.ts index 4a9cb84383f..3f929e55135 100644 --- a/packages/cli/src/events/maps/relay.event-map.ts +++ b/packages/cli/src/events/maps/relay.event-map.ts @@ -1008,6 +1008,24 @@ export type RelayEventMap = { role: string; }; + 'trusted-source-created': { + user: UserLike; + sourceId: string; + issuer: string; + }; + + 'trusted-source-updated': { + user: UserLike; + sourceId: string; + issuer: string; + }; + + 'trusted-source-deleted': { + user: UserLike; + sourceId: string; + issuer: string; + }; + // #endregion // #region Token exchange diff --git a/packages/cli/src/events/relays/log-streaming.event-relay.ts b/packages/cli/src/events/relays/log-streaming.event-relay.ts index fcf449d90a3..676c5d5a474 100644 --- a/packages/cli/src/events/relays/log-streaming.event-relay.ts +++ b/packages/cli/src/events/relays/log-streaming.event-relay.ts @@ -188,6 +188,9 @@ export class LogStreamingEventRelay extends EventRelay { 'role-mapping-rule-updated': (event) => this.roleMappingRuleUpdated(event), 'role-mapping-rule-deleted': (event) => this.roleMappingRuleDeleted(event), 'role-mapping-rules-bulk-deleted': (event) => this.roleMappingRulesBulkDeleted(event), + 'trusted-source-created': (event) => this.trustedSourceCreated(event), + 'trusted-source-updated': (event) => this.trustedSourceUpdated(event), + 'trusted-source-deleted': (event) => this.trustedSourceDeleted(event), 'mcp-oauth-completed': (event) => this.mcpOauthCompleted(event), 'mcp-tool-called': (event) => this.mcpToolCalled(event), 'mcp-access-updated': (event) => this.mcpAccessUpdated(event), @@ -1600,6 +1603,34 @@ export class LogStreamingEventRelay extends EventRelay { // #endregion + // #region Trusted sources + + @Redactable() + private trustedSourceCreated({ user, ...rest }: RelayEventMap['trusted-source-created']) { + void this.eventBus.sendAuditEvent({ + eventName: 'n8n.audit.trusted-source.created', + payload: { ...user, ...rest }, + }); + } + + @Redactable() + private trustedSourceUpdated({ user, ...rest }: RelayEventMap['trusted-source-updated']) { + void this.eventBus.sendAuditEvent({ + eventName: 'n8n.audit.trusted-source.updated', + payload: { ...user, ...rest }, + }); + } + + @Redactable() + private trustedSourceDeleted({ user, ...rest }: RelayEventMap['trusted-source-deleted']) { + void this.eventBus.sendAuditEvent({ + eventName: 'n8n.audit.trusted-source.deleted', + payload: { ...user, ...rest }, + }); + } + + // #endregion + // #region MCP server private mcpOauthCompleted({ diff --git a/packages/cli/src/events/relays/telemetry.event-relay.ts b/packages/cli/src/events/relays/telemetry.event-relay.ts index 5da6164b29b..5dd717b4452 100644 --- a/packages/cli/src/events/relays/telemetry.event-relay.ts +++ b/packages/cli/src/events/relays/telemetry.event-relay.ts @@ -1393,6 +1393,7 @@ export class TelemetryEventRelay extends EventRelay { workflow_id_policy: options.workflowIdPolicy, credential_matching_mode: options.credentialMatchingMode, credential_missing_mode: options.credentialMissingMode, + credential_conflict_policy: options.credentialConflictPolicy, workflow_publishing_policy: options.workflowPublishingPolicy, missing_node_type_mode: options.missingNodeTypeMode, project_conflict_policy: options.projectConflictPolicy, @@ -1854,7 +1855,6 @@ export class TelemetryEventRelay extends EventRelay { workflow_history: { compaction_optimizing_time_window_hours: this.globalConfig.workflowHistoryCompaction.optimizingTimeWindowHours, - compaction_trim_on_start_up: this.globalConfig.workflowHistoryCompaction.trimOnStartUp, compaction_trimming_time_window_days: this.globalConfig.workflowHistoryCompaction.trimmingTimeWindowDays, }, diff --git a/packages/cli/src/executions/pre-execution-checks/__tests__/credentials-permission-checker.test.ts b/packages/cli/src/executions/pre-execution-checks/__tests__/credentials-permission-checker.test.ts index 8d1e382398f..4160cfb32d8 100644 --- a/packages/cli/src/executions/pre-execution-checks/__tests__/credentials-permission-checker.test.ts +++ b/packages/cli/src/executions/pre-execution-checks/__tests__/credentials-permission-checker.test.ts @@ -810,6 +810,77 @@ describe('CredentialsPermissionChecker', () => { }); }); + describe('with a default-valued authentication parameter', () => { + const credentialId = 'password-cred'; + const description = { + credentials: [ + { + name: 'passwordApi', + required: true, + displayOptions: { show: { authentication: ['password'] } }, + }, + { + name: 'tokenApi', + required: true, + displayOptions: { show: { authentication: ['token'] } }, + }, + ], + properties: [ + { + displayName: 'Authentication', + name: 'authentication', + type: 'options', + options: [ + { name: 'Password', value: 'password' }, + { name: 'Token', value: 'token' }, + ], + default: 'password', + }, + ], + }; + + // Saved nodes omit parameters left at their default value + const node: INode = { + id: 'node-6', + name: 'Service', + type: 'n8n-nodes-base.service', + typeVersion: 1, + position: [0, 0], + parameters: { resource: 'entry' }, + credentials: { passwordApi: { id: credentialId, name: 'Password' } }, + }; + + beforeEach(() => { + nodeTypes.getByNameAndVersion.mockReturnValue({ description } as never); + credentialsRepository.findGlobalProjectCredentialIds.mockResolvedValue([]); + }); + + it('should check the credential selected by the default value', async () => { + sharedCredentialsRepository.getFilteredAccessibleCredentials.mockResolvedValue([]); + + await expect(permissionChecker.check(workflowId, [node])).rejects.toThrow( + 'Node "Service" does not have access to the credential', + ); + + expect(sharedCredentialsRepository.getFilteredAccessibleCredentials).toHaveBeenCalledWith( + [teamProject.id], + [credentialId], + ); + }); + + it('should let the run through when the project can use the credential', async () => { + sharedCredentialsRepository.getFilteredAccessibleCredentials.mockResolvedValue([ + credentialId, + ]); + + await expect(permissionChecker.check(workflowId, [node])).resolves.not.toThrow(); + }); + + it('should return the credential id for the node', () => { + expect(permissionChecker.getCredentialIdsForNodes([node])).toEqual([credentialId]); + }); + }); + it('should fall back to checking all credentials if node type cannot be resolved', async () => { nodeTypes.getByNameAndVersion.mockImplementation(() => { throw new Error('Unknown node type'); @@ -874,6 +945,12 @@ describe('CredentialsPermissionChecker', () => { expect(permissionChecker.getCredentialIdsForNodes([disabledNode])).toEqual([]); }); + it.each([1, 'true', {}])('does not skip a node whose disabled flag is %p', (disabled) => { + const flaggedNode = { ...node, disabled } as unknown as INode; + + expect(permissionChecker.getCredentialIdsForNodes([flaggedNode])).toEqual([credentialId]); + }); + it('skips a credential reference with no id instead of throwing', () => { const nodeWithNoId: INode = { ...node, diff --git a/packages/cli/src/executions/pre-execution-checks/credentials-permission-checker.ts b/packages/cli/src/executions/pre-execution-checks/credentials-permission-checker.ts index 785f6e7445e..bcbb5a20ec7 100644 --- a/packages/cli/src/executions/pre-execution-checks/credentials-permission-checker.ts +++ b/packages/cli/src/executions/pre-execution-checks/credentials-permission-checker.ts @@ -480,7 +480,7 @@ export class CredentialsPermissionChecker { getCredentialIdsForNodes(nodes: INode[]): string[] { const ids = new Set(); for (const node of nodes) { - if (node.disabled || !node.credentials) continue; + if (node.disabled === true || !node.credentials) continue; const activeCredTypes = this.getActiveCredentialTypes(node); @@ -495,7 +495,7 @@ export class CredentialsPermissionChecker { private mapCredIdsToNodes(nodes: INode[]) { return nodes.reduce<{ [credentialId: string]: INode[] }>((map, node) => { - if (node.disabled || !node.credentials) return map; + if (node.disabled === true || !node.credentials) return map; const activeCredTypes = this.getActiveCredentialTypes(node); diff --git a/packages/cli/src/license/__tests__/license-renewal.task.test.ts b/packages/cli/src/license/__tests__/license-renewal.task.test.ts index 2dc37957836..5635be643f1 100644 --- a/packages/cli/src/license/__tests__/license-renewal.task.test.ts +++ b/packages/cli/src/license/__tests__/license-renewal.task.test.ts @@ -1,4 +1,3 @@ -import { ScheduledJobMisfirePolicy } from '@n8n/constants'; import { mock } from 'vitest-mock-extended'; import type { License } from '@/license'; @@ -17,10 +16,11 @@ describe('LicenseRenewalTask', () => { it('should declare the SDK renewal check cadence', () => { expect(task.name).toBe('license-renewal'); expect(task.schedule).toEqual({ kind: 'interval', intervalSeconds: 900 }); - expect(task.effects).toBe('non-idempotent'); - expect(task.misfirePolicy).toBe(ScheduledJobMisfirePolicy.Coalesce); - expect(task.misfireGraceSeconds).toBe(300); - expect(task.placement).toEqual({ scope: 'cluster', durable: true, runOnTakeover: true }); + expect(task.target).toEqual({ + scope: 'cluster', + scheduler: { retryOnFailure: false, missedAfterSeconds: 300, catchUp: true }, + leaderTimer: { runOnTakeover: true }, + }); }); it('should run one renewal pass', async () => { diff --git a/packages/cli/src/license/license-renewal.task.ts b/packages/cli/src/license/license-renewal.task.ts index 6a08b426e03..7a666abb9c4 100644 --- a/packages/cli/src/license/license-renewal.task.ts +++ b/packages/cli/src/license/license-renewal.task.ts @@ -1,6 +1,6 @@ -import { ScheduledJobMisfirePolicy, Time } from '@n8n/constants'; -import { intervalFromMilliseconds, SystemTask } from '@n8n/decorators'; -import type { SystemTaskEffects, SystemTaskPlacement, SystemTaskSchedule } from '@n8n/decorators'; +import { Time } from '@n8n/constants'; +import { clusterTarget, intervalFromMilliseconds, SystemTask } from '@n8n/decorators'; +import type { SystemTaskSchedule } from '@n8n/decorators'; import { AUTORENEWAL_INTERVAL } from '@n8n_io/license-sdk'; import { License } from '@/license'; @@ -15,21 +15,20 @@ export class LicenseRenewalTask implements SystemTask { readonly schedule: SystemTaskSchedule = intervalFromMilliseconds(AUTORENEWAL_INTERVAL); - /** A retry after a failed renewal resends a token the server may have rotated already. */ - readonly effects: SystemTaskEffects = 'non-idempotent'; - - /** A check that missed its grace window still runs once, late. */ - readonly misfirePolicy: ScheduledJobMisfirePolicy = ScheduledJobMisfirePolicy.Coalesce; - - /** Kept well under one interval, so two checks are never claimable at once. */ - readonly misfireGraceSeconds = 5 * Time.minutes.toSeconds; - - readonly placement: SystemTaskPlacement = { - scope: 'cluster', - durable: true, - /** A new leader may inherit a due renewal whose window closes before the next interval. */ - runOnTakeover: true, - }; + readonly target = clusterTarget({ + scheduler: { + /** A retry after a failed renewal resends a token the server may have rotated already. */ + retryOnFailure: false, + /** Kept well under one interval, so two checks are never claimable at once. */ + missedAfterSeconds: 5 * Time.minutes.toSeconds, + /** A check that missed its grace window still runs once, late. */ + catchUp: true, + }, + leaderTimer: { + /** A new leader may inherit a due renewal whose window closes before the next interval. */ + runOnTakeover: true, + }, + }); constructor(private readonly license: License) {} diff --git a/packages/cli/src/load-nodes-and-credentials.ts b/packages/cli/src/load-nodes-and-credentials.ts index f0464b85f46..d14e5ec11df 100644 --- a/packages/cli/src/load-nodes-and-credentials.ts +++ b/packages/cli/src/load-nodes-and-credentials.ts @@ -40,11 +40,17 @@ import type { NodeLoader, } from 'n8n-workflow'; import { ensureError } from '@n8n/utils/errors/ensure-error'; -import { injectDomainRestrictionFields, UnexpectedError, UserError } from 'n8n-workflow'; +import { + injectDomainRestrictionFields, + NodeHelpers, + UnexpectedError, + UserError, +} from 'n8n-workflow'; import path from 'path'; import picocolors from 'picocolors'; import { CUSTOM_API_CALL_KEY, CUSTOM_API_CALL_NAME, CLI_DIR, inE2ETests } from '@/constants'; +import { getParameterDefaults } from '@/output-schema-parameter-defaults'; import { createAiTools, createHitlTools } from '@/tool-generation'; @Service() @@ -310,10 +316,12 @@ export class LoadNodesAndCredentials { * community nodes and production installs alike. */ createOutputSchemaLookup(): OutputSchemaLookup { - return ({ type, typeVersion, resource, operation, hasOutputParser }) => { + return ({ type, typeVersion, resource, operation, hasOutputParser, parameters }) => { const nodePath = this.known.nodes[type]?.sourcePath; if (!nodePath) return undefined; + const nodeType = this.tryGetVersionedNodeType(type, typeVersion); + return loadOutputSchema({ nodeDir: path.dirname(nodePath), version: typeVersion, @@ -321,10 +329,24 @@ export class LoadNodesAndCredentials { operation, versionFallback: true, variant: hasOutputParser ? OUTPUT_PARSER_SCHEMA_VARIANT : undefined, + parameters, + parameterDefaults: getParameterDefaults(nodeType?.description.properties, { + resource, + operation, + }), }); }; } + /** Schema previews are best-effort, so a node that cannot load just has no variants. */ + private tryGetVersionedNodeType(type: string, version: number): INodeType | undefined { + try { + return NodeHelpers.getVersionedNodeType(this.getNode(type).type, version); + } catch { + return undefined; + } + } + getCustomDirectories(): string[] { const customDirectories = [this.instanceSettings.customExtensionDir]; diff --git a/packages/cli/src/middlewares/__tests__/body-parser.test.ts b/packages/cli/src/middlewares/__tests__/body-parser.test.ts index 321508eadae..647e1a6d0cc 100644 --- a/packages/cli/src/middlewares/__tests__/body-parser.test.ts +++ b/packages/cli/src/middlewares/__tests__/body-parser.test.ts @@ -2,9 +2,9 @@ import type { Request, Response } from 'express'; import { mock } from 'vitest-mock-extended'; import { Readable } from 'stream'; -import { BadRequestError } from '@n8n/errors'; +import { BadRequestError, UnprocessableRequestError } from '@n8n/errors'; -import { rawBodyReader } from '../body-parser'; +import { parseBody, rawBodyReader } from '../body-parser'; /** Build a request backed by a real readable stream carrying `payload`. */ const mockRequest = (payload = '', headers: Record = {}) => { @@ -57,3 +57,36 @@ describe('rawBodyReader', () => { }); }); }); + +describe('parseBody', () => { + const xmlRequest = (body: string) => + ({ + contentType: 'text/xml', + encoding: 'utf-8', + rawBody: Buffer.from(body), + readRawBody: async () => {}, + }) as unknown as Request; + + // Bodies over 10,000 chars make xml2js parse in chunks across ticks. + const largeXml = (id: string) => + `${'x'.repeat(1000)}${id}`; + + it('parses concurrent large XML bodies independently', async () => { + const requests = ['a', 'b', 'c'].map((id) => xmlRequest(largeXml(id))); + + await Promise.all(requests.map(parseBody)); + + expect(requests.map((req) => req.body.envelope.body.id)).toEqual(['a', 'b', 'c']); + + const after = xmlRequest('after'); + await parseBody(after); + expect(after.body).toEqual({ root: { id: 'after' } }); + }); + + it('rejects an XML body that fails inside an element handler', async () => { + // An element named `_` collides with the text key and throws while closing the tag. + await expect(parseBody(xmlRequest('<_>x'))).rejects.toThrow( + UnprocessableRequestError, + ); + }); +}); diff --git a/packages/cli/src/middlewares/body-parser.ts b/packages/cli/src/middlewares/body-parser.ts index 609c54b18a2..139f455ea28 100644 --- a/packages/cli/src/middlewares/body-parser.ts +++ b/packages/cli/src/middlewares/body-parser.ts @@ -11,14 +11,17 @@ import { createGunzip, createInflate } from 'zlib'; import { BadRequestError, UnprocessableRequestError } from '@n8n/errors'; -const xmlParser = new XmlParser({ - async: true, - normalize: true, // Trim whitespace inside text nodes - normalizeTags: true, // Transform tags to lowercase - explicitArray: false, // Only put properties in array if length > 1 - tagNameProcessors: [sanitizeXmlName], - attrNameProcessors: [sanitizeXmlName], -}); +// One parser per request: xml2js keeps parse state on the instance, and async +// mode spreads large bodies over several ticks. +const createXmlParser = () => + new XmlParser({ + async: true, + normalize: true, // Trim whitespace inside text nodes + normalizeTags: true, // Transform tags to lowercase + explicitArray: false, // Only put properties in array if length > 1 + tagNameProcessors: [sanitizeXmlName], + attrNameProcessors: [sanitizeXmlName], + }); const payloadSizeMax = Container.get(GlobalConfig).endpoints.payloadSizeMax; @@ -97,7 +100,7 @@ export const parseBody = async (req: Request) => { req.body = jsonParse(stripBom(rawBody.toString(encoding))); } else if (contentType?.endsWith('/xml') || contentType?.endsWith('+xml')) { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - req.body = await xmlParser.parseStringPromise(rawBody.toString(encoding)); + req.body = await createXmlParser().parseStringPromise(rawBody.toString(encoding)); } else if (contentType === 'application/x-www-form-urlencoded') { req.body = parseQueryString(stripBom(rawBody.toString(encoding)), undefined, undefined, { maxKeys: 1000, diff --git a/packages/cli/src/middlewares/list-query/__tests__/list-query.test.ts b/packages/cli/src/middlewares/list-query/__tests__/list-query.test.ts index 2aafe4509dd..41571966b96 100644 --- a/packages/cli/src/middlewares/list-query/__tests__/list-query.test.ts +++ b/packages/cli/src/middlewares/list-query/__tests__/list-query.test.ts @@ -23,7 +23,7 @@ describe('List query middleware', () => { vi.clearAllMocks(); mockReq = { baseUrl: '/rest/workflows' } as ListQuery.Request; - mockRes = { status: () => ({ json: vi.fn() }) } as unknown as Response; + mockRes = { status: () => ({ json: vi.fn() }), setHeader: vi.fn() } as unknown as Response; args = [mockReq, mockRes, nextFn]; sendErrorResponse = vi.spyOn(ResponseHelper, 'sendErrorResponse'); diff --git a/packages/cli/src/middlewares/list-query/dtos/workflow.filter.dto.ts b/packages/cli/src/middlewares/list-query/dtos/workflow.filter.dto.ts index a2103b47909..02d31fe26fd 100644 --- a/packages/cli/src/middlewares/list-query/dtos/workflow.filter.dto.ts +++ b/packages/cli/src/middlewares/list-query/dtos/workflow.filter.dto.ts @@ -76,25 +76,6 @@ export class WorkflowFilter extends BaseFilter { @Expose() executionBlockedBy?: WorkflowExecutionBlockCause[]; - /** - * When `true`, the list is widened to include workflows that the workflow - * identified by `parentWorkflowId` is permitted to call, even if those - * workflows are not directly shared with the requesting user. - */ - @IsBoolean() - @IsOptional() - @Expose() - includeCallableSubworkflows?: boolean; - - /** - * ID of the workflow that will act as the caller. - * Used together with `includeCallableSubworkflows` to evaluate `callerPolicy`. - */ - @IsString() - @IsOptional() - @Expose() - parentWorkflowId?: string; - static async fromString(rawFilter: string) { return await this.toFilter(rawFilter, WorkflowFilter); } diff --git a/packages/cli/src/modules/__tests__/modules.manifest.test.ts b/packages/cli/src/modules/__tests__/modules.manifest.test.ts new file mode 100644 index 00000000000..23cdc2711ff --- /dev/null +++ b/packages/cli/src/modules/__tests__/modules.manifest.test.ts @@ -0,0 +1,23 @@ +import { ControllerRegistryMetadata, ModuleMetadata } from '@n8n/decorators'; +import { Container } from '@n8n/di'; + +describe('packaged module manifest', () => { + it('loads the Quick Connect package only when requested', async () => { + const metadata = Container.get(ModuleMetadata); + const controllers = Container.get(ControllerRegistryMetadata); + expect(metadata.get('quick-connect')).toBeUndefined(); + + const { packagedModules } = await import('../modules.manifest.js'); + + expect(metadata.get('quick-connect')).toBeUndefined(); + expect([...controllers.controllerClasses]).toEqual([]); + const loadQuickConnect = packagedModules['quick-connect']; + expect(loadQuickConnect).toBeTypeOf('function'); + const entrypoint = await loadQuickConnect?.(); + const packagedEntrypoint = await import('@n8n/backend-module-quick-connect/module'); + + expect(entrypoint).toBe(packagedEntrypoint); + expect(metadata.get('quick-connect')).toEqual({ class: packagedEntrypoint.QuickConnectModule }); + expect([...controllers.controllerClasses]).toEqual([]); + }); +}); diff --git a/packages/cli/src/modules/agent-evals/__tests__/agent-eval.service.test.ts b/packages/cli/src/modules/agent-evals/__tests__/agent-eval.service.test.ts index 5c539ac9c4d..c83945583c5 100644 --- a/packages/cli/src/modules/agent-evals/__tests__/agent-eval.service.test.ts +++ b/packages/cli/src/modules/agent-evals/__tests__/agent-eval.service.test.ts @@ -43,6 +43,9 @@ vi.mock('../agent-eval-instructions-rewrite', () => ({ rewriteAgentInstructions: vi.mock('../agent-eval-case-generation.service', () => ({ AgentEvalCaseGenerationService: class AgentEvalCaseGenerationService {}, })); +vi.mock('@/permissions.ee/check-access', () => ({ + userHasScopes: vi.fn().mockResolvedValue(true), +})); const AGENT_ID = 'agent-1'; const PROJECT_ID = 'proj-1'; @@ -132,6 +135,7 @@ describe('AgentEvalService', () => { runRepository.findByIdAndAgentId.mockResolvedValue(makeRun()); runRepository.findAndCountByDatasetIdAndAgentId.mockResolvedValue([[], 0]); resultRepository.findAndCountByRunId.mockResolvedValue([[], 0]); + vi.mocked(userHasScopes).mockReset().mockResolvedValue(true); resultRepository.findById.mockResolvedValue(makeResult()); service = new AgentEvalService( @@ -181,7 +185,10 @@ describe('AgentEvalService', () => { ['previewRun', async () => await service.previewRun(user, AGENT_ID, PROJECT_ID, {})], ['startRun', async () => await service.startRun(user, AGENT_ID, PROJECT_ID, 'ds-1', {})], ['listRuns', async () => await service.listRuns(AGENT_ID, PROJECT_ID, 'ds-1', PAGE)], - ['getRunDetail', async () => await service.getRunDetail(AGENT_ID, PROJECT_ID, 'run-1', PAGE)], + [ + 'getRunDetail', + async () => await service.getRunDetail(user, AGENT_ID, PROJECT_ID, 'run-1', PAGE), + ], ['getRunSummary', async () => await service.getRunSummary(AGENT_ID, PROJECT_ID, 'run-1')], ['cancelRun', async () => await service.cancelRun(AGENT_ID, PROJECT_ID, 'run-1')], [ @@ -255,9 +262,9 @@ describe('AgentEvalService', () => { it('404s a run belonging to another agent, and reads no results for it', async () => { runRepository.findByIdAndAgentId.mockResolvedValue(null); - await expect(service.getRunDetail(AGENT_ID, PROJECT_ID, 'run-other', PAGE)).rejects.toThrow( - NotFoundError, - ); + await expect( + service.getRunDetail(user, AGENT_ID, PROJECT_ID, 'run-other', PAGE), + ).rejects.toThrow(NotFoundError); expect(resultRepository.findAndCountByRunId).not.toHaveBeenCalled(); }); @@ -956,6 +963,77 @@ describe('AgentEvalService', () => { createdById: 'user-1', }); }); + + it('checks the creating user can read the referenced data table', async () => { + datasetRepository.createDataset.mockResolvedValue(makeDataset()); + + await service.createDataset(user, AGENT_ID, PROJECT_ID, { + name: 'cases', + agentId: AGENT_ID, + datasetSource: 'data_table', + datasetRef: { dataTableId: 'dt-1' }, + }); + + expect(userHasScopes).toHaveBeenCalledWith(user, ['dataTable:readRow'], false, { + dataTableId: 'dt-1', + }); + }); + + it('refuses a data table the creating user cannot read', async () => { + vi.mocked(userHasScopes).mockResolvedValue(false); + + await expect( + service.createDataset(user, AGENT_ID, PROJECT_ID, { + name: 'cases', + agentId: AGENT_ID, + datasetSource: 'data_table', + datasetRef: { dataTableId: 'dt-other' }, + }), + ).rejects.toThrow(ForbiddenError); + expect(datasetRepository.createDataset).not.toHaveBeenCalled(); + }); + }); + + // Results hold copies of the source rows, and the table can live in another + // project than the agent, so `agent:read` alone must not open them. + describe('getRunDetail data table access', () => { + it('checks the reader can read the run dataset’s data table', async () => { + await service.getRunDetail(user, AGENT_ID, PROJECT_ID, 'run-1', PAGE); + + expect(datasetRepository.findByIdAndAgentId).toHaveBeenCalledWith('ds-1', AGENT_ID); + expect(userHasScopes).toHaveBeenCalledWith(user, ['dataTable:readRow'], false, { + dataTableId: 'dt-1', + }); + }); + + it('refuses a reader without access to the data table, and reads no results', async () => { + vi.mocked(userHasScopes).mockResolvedValue(false); + + await expect(service.getRunDetail(user, AGENT_ID, PROJECT_ID, 'run-1', PAGE)).rejects.toThrow( + ForbiddenError, + ); + expect(resultRepository.findAndCountByRunId).not.toHaveBeenCalled(); + }); + + it('reads no results when the run’s dataset does not resolve', async () => { + datasetRepository.findByIdAndAgentId.mockResolvedValue(null); + + await expect(service.getRunDetail(user, AGENT_ID, PROJECT_ID, 'run-1', PAGE)).rejects.toThrow( + NotFoundError, + ); + expect(resultRepository.findAndCountByRunId).not.toHaveBeenCalled(); + }); + + it('refuses a data-table dataset whose ref carries no table id', async () => { + datasetRepository.findByIdAndAgentId.mockResolvedValue( + makeDataset({ datasetRef: { credentialId: 'c-1', spreadsheetId: 's-1', sheetName: 'S' } }), + ); + + await expect(service.getRunDetail(user, AGENT_ID, PROJECT_ID, 'run-1', PAGE)).rejects.toThrow( + /without a table id/, + ); + expect(resultRepository.findAndCountByRunId).not.toHaveBeenCalled(); + }); }); describe('deleteDataset', () => { @@ -1039,7 +1117,7 @@ describe('AgentEvalService', () => { describe('response mapping', () => { it('serializes dates as ISO strings and keeps run coordination columns off the wire', async () => { - const detail = await service.getRunDetail(AGENT_ID, PROJECT_ID, 'run-1', PAGE); + const detail = await service.getRunDetail(user, AGENT_ID, PROJECT_ID, 'run-1', PAGE); expect(detail.runAt).toBe('2026-01-03T00:00:00.000Z'); expect(detail.createdAt).toBe('2026-01-03T00:00:00.000Z'); @@ -1106,7 +1184,7 @@ describe('AgentEvalService', () => { 1, ]); - const detail = await service.getRunDetail(AGENT_ID, PROJECT_ID, 'run-1', PAGE); + const detail = await service.getRunDetail(user, AGENT_ID, PROJECT_ID, 'run-1', PAGE); expect(detail.results.data).toHaveLength(1); expect(detail.results.data[0]).toMatchObject({ @@ -1138,7 +1216,7 @@ describe('AgentEvalService', () => { it('passes the run-detail window to the repository and reports the case total', async () => { resultRepository.findAndCountByRunId.mockResolvedValue([[], 500]); - const detail = await service.getRunDetail(AGENT_ID, PROJECT_ID, 'run-1', { + const detail = await service.getRunDetail(user, AGENT_ID, PROJECT_ID, 'run-1', { take: 25, skip: 50, }); diff --git a/packages/cli/src/modules/agent-evals/__tests__/agent-evals.controller.test.ts b/packages/cli/src/modules/agent-evals/__tests__/agent-evals.controller.test.ts index 3f58ed59bac..9906c8655ba 100644 --- a/packages/cli/src/modules/agent-evals/__tests__/agent-evals.controller.test.ts +++ b/packages/cli/src/modules/agent-evals/__tests__/agent-evals.controller.test.ts @@ -485,7 +485,7 @@ describe('AgentEvalsController', () => { await controller.getRun(runReq(), undefined, query); - expect(service.getRunDetail).toHaveBeenCalledWith(AGENT_ID, PROJECT_ID, 'run-1', { + expect(service.getRunDetail).toHaveBeenCalledWith(user, AGENT_ID, PROJECT_ID, 'run-1', { take: 25, skip: 50, }); @@ -507,7 +507,7 @@ describe('AgentEvalsController', () => { it('defaults the run-detail window wider than the shared list default', async () => { await controller.getRun(runReq(), undefined, AgentEvalRunDetailQueryDto.parse({})); - expect(service.getRunDetail).toHaveBeenCalledWith(AGENT_ID, PROJECT_ID, 'run-1', { + expect(service.getRunDetail).toHaveBeenCalledWith(user, AGENT_ID, PROJECT_ID, 'run-1', { take: AGENT_EVAL_RESULTS_DEFAULT_TAKE, skip: 0, }); diff --git a/packages/cli/src/modules/agent-evals/agent-eval.service.ts b/packages/cli/src/modules/agent-evals/agent-eval.service.ts index dc2f6124f39..b3ff8f2e415 100644 --- a/packages/cli/src/modules/agent-evals/agent-eval.service.ts +++ b/packages/cli/src/modules/agent-evals/agent-eval.service.ts @@ -27,6 +27,7 @@ import { AgentEvalRunRepository, } from '@n8n/db'; import { Service } from '@n8n/di'; +import { UnexpectedError } from 'n8n-workflow'; import pLimit from 'p-limit'; import { BadRequestError, ForbiddenError, NotFoundError, OperationalError } from '@n8n/errors'; @@ -110,6 +111,10 @@ export class AgentEvalService { ); } + if (payload.datasetSource === 'data_table') { + await this.assertDataTableReadable(user, payload.datasetRef.dataTableId); + } + const dataset = await this.datasetRepository.createDataset({ name: payload.name, description: payload.description ?? null, @@ -323,8 +328,13 @@ export class AgentEvalService { return { count, data: runs.map(toRunRecord) }; } - /** A run with a page of its per-case results — the "open a run" view. */ + /** + * A run with a page of its per-case results — the "open a run" view. Results + * hold copies of the source rows, so the reader needs the same table access + * the runner required of whoever started the run. + */ async getRunDetail( + user: User, agentId: string, projectId: string, runId: string, @@ -332,6 +342,7 @@ export class AgentEvalService { ): Promise { await this.assertAgentInProject(agentId, projectId); const run = await this.resolveRun(agentId, runId); + await this.assertDatasetSourceReadable(user, await this.resolveDataset(agentId, run.datasetId)); const [results, count] = await this.resultRepository.findAndCountByRunId(runId, page); return { ...toRunRecord(run), results: { count, data: results.map(toResultRecord) } }; } @@ -541,6 +552,24 @@ export class AgentEvalService { return dataset; } + // The table may live in another project than the agent, so `@ProjectScope` on + // the agent's project says nothing about it. Only data-table datasets are + // runnable today, so no other source has stored rows to protect. + private async assertDatasetSourceReadable(user: User, dataset: AgentEvalDataset): Promise { + if (dataset.datasetSource !== 'data_table') return; + if (!('dataTableId' in dataset.datasetRef)) { + throw new UnexpectedError( + `Agent eval dataset ${dataset.id} has a 'data_table' source without a table id.`, + ); + } + await this.assertDataTableReadable(user, dataset.datasetRef.dataTableId); + } + + private async assertDataTableReadable(user: User, dataTableId: string): Promise { + const allowed = await userHasScopes(user, ['dataTable:readRow'], false, { dataTableId }); + if (!allowed) throw new ForbiddenError('You do not have access to this dataset.'); + } + private async resolveRun(agentId: string, runId: string): Promise { const run = await this.runRepository.findByIdAndAgentId(runId, agentId); if (!run) throw new NotFoundError(`Agent eval run ${runId} not found.`); diff --git a/packages/cli/src/modules/agent-evals/agent-evals.controller.ts b/packages/cli/src/modules/agent-evals/agent-evals.controller.ts index da24502fe09..5d970aa4f38 100644 --- a/packages/cli/src/modules/agent-evals/agent-evals.controller.ts +++ b/packages/cli/src/modules/agent-evals/agent-evals.controller.ts @@ -255,7 +255,7 @@ export class AgentEvalsController { ): Promise { await this.flagGate.assertEnabled(req.user); const { agentId, projectId, runId } = req.params; - return await this.service.getRunDetail(agentId, projectId, runId, query); + return await this.service.getRunDetail(req.user, agentId, projectId, runId, query); } /** Counts only — cheap enough for the UI to poll while a run is in flight. */ diff --git a/packages/cli/src/modules/agents/AGENTS.md b/packages/cli/src/modules/agents/AGENTS.md index 101b8f28202..2daf326dfe2 100644 --- a/packages/cli/src/modules/agents/AGENTS.md +++ b/packages/cli/src/modules/agents/AGENTS.md @@ -9,7 +9,14 @@ Guidance for the agents module (`packages/cli/src/modules/agents`). See the [cli ## Skill refs -- `agents.schema` and `agent_history.schema` hold a `StoredAgentConfig`. It has no readable `skills` key. -- Read and write the skill refs of a draft or a published version only through `AgentSkillRefsService`. +- The PostHog flag `125_context_skills` (`SKILLS_FLAG`) selects where skills live. `SkillsHubRollout` reads it for the instance once, when the agents module starts, and keeps the value for the life of the process; a change needs a restart. `AgentSkillRefsService.usesSkillsHub` and the `/skills` routes read `SkillsHubRollout`. Turn it on locally with `N8N_FEATURE_FLAG_OVERRIDES`. There are no double writes: data written with one setting is not visible with the other. +- Hub on: skills live in the skills hub (`skill`, `skill_version`, `skill_file`). A draft keeps its skill refs in `agent_skill_dependency`, in attach order (`createdAt`). A published version keeps its pins in `agent_version_skill_dependency`, in the same order. +- Hub on: a skill that an agent page creates is available to the project, to that agent only (`skill.agentId`), or to the instance (`availableTo` on the create request, default `project`). A duplicate of an agent gets its own copy of each agent-only skill. +- Hub off: the refs are the `skills` key of `agents.schema` and `agent_history.schema`, and the bodies are the `agents.skills` and `agent_history.skills` columns, as before the skills hub. A ref with `enabled: false` is hidden, and its body stays in the column. +- Only `AgentSkillRefsService` reads the `skills` key of a `StoredAgentConfig`. +- Read and write the skill refs, and read the skill bodies, only through `AgentSkillRefsService`. A draft runs the latest saved version of each skill, or its pin (`versionId`). A published version runs its pins. - Compose the JSON document (`AgentJsonConfig`) with `toAgentDocument` or `composeJsonConfig` only where code needs the document: REST, MCP, the agent builder tools, publish, runtime reconstruction, sub-agent resolution, telemetry, config hashes and create with a config. Compute `configHash` on the composed document. Split an inbound document with `fromAgentDocument`. -- A write that changes the skill refs of an existing draft calls `saveAgentDraftFenced` and then `replaceDraftRefs` with the same `ctx`, in one `TransactionRunner.run`. Agent creation calls `insertNew` and then `replaceDraftRefs` in one transaction. +- A write that changes the skill refs of an existing draft calls `saveAgentDraftFenced` and then `replaceDraftRefs` with the same `ctx`, in one `TransactionRunner.run`. Agent creation calls `insertNew` and then `createDraftRefs` in one transaction. Revert calls `restoreDraftRefs`. Publish calls `versionSnapshot` before it writes the `agent_history` row and `pinVersion` after. +- With the flag on, `SkillsHubStartupCopy` copies inline skills into the hub on every main at startup; each agent's copy holds its row, so mains do not copy twice. Each inline skill becomes an agent skill. A published version is copied while it pins nothing; a draft is copied while the agent has no hub rows. It reuses content by hash and never writes the legacy columns, so it can run again safely. With the flag off, the leader logs the agents whose hub draft runs other content than their inline skills. +- Publish writes the legacy columns in full with either setting: the refs in `agent_history.schema.skills` and the bodies in `agent_history.skills`. With the hub on, the bodies are the versions the draft runs, so a published agent keeps running after the flag is turned off. +- Inline agents (`InlineAgentPayload`) embed their skills and never call the skill service. diff --git a/packages/cli/src/modules/agents/__tests__/agent-channel-media-retention.task.test.ts b/packages/cli/src/modules/agents/__tests__/agent-channel-media-retention.task.test.ts new file mode 100644 index 00000000000..ccbe594f859 --- /dev/null +++ b/packages/cli/src/modules/agents/__tests__/agent-channel-media-retention.task.test.ts @@ -0,0 +1,190 @@ +import type { AgentIntegrationConfig } from '@n8n/api-types'; +import type { Logger } from '@n8n/backend-common'; +import { mock } from 'vitest-mock-extended'; + +import type { AgentChatAttachmentService } from '../agent-chat-attachment.service'; +import { AgentChannelMediaRetentionTask } from '../agent-channel-media-retention.task'; +import type { AgentRepository } from '../repositories/agent.repository'; + +const DAY_MS = 24 * 60 * 60 * 1000; +const NOW = new Date('2026-06-15T12:00:00.000Z'); + +const whatsApp = (settings?: Record) => + ({ type: 'whatsapp', credentialId: 'cred-1', settings }) as AgentIntegrationConfig; + +describe('AgentChannelMediaRetentionTask', () => { + let agentRepository: ReturnType>; + let attachmentService: ReturnType>; + let logger: ReturnType>; + let task: AgentChannelMediaRetentionTask; + const signal = new AbortController().signal; + + beforeEach(() => { + vi.useFakeTimers({ now: NOW }); + agentRepository = mock(); + attachmentService = mock(); + attachmentService.deleteFromSourceCreatedBefore.mockResolvedValue(0); + logger = mock(); + task = new AgentChannelMediaRetentionTask(agentRepository, attachmentService, logger); + }); + + afterEach(() => { + vi.useRealTimers(); + }); + + it('declares an hourly cluster-wide cadence', () => { + expect(task.name).toBe('agent-channel-media-retention'); + expect(task.schedule).toEqual({ kind: 'interval', intervalSeconds: 3600 }); + expect(task.target).toEqual({ + scope: 'cluster', + scheduler: { retryOnFailure: true }, + leaderTimer: { runOnTakeover: true, retryDelaySeconds: 60 }, + }); + }); + + it('looks up only agents with a WhatsApp channel', async () => { + agentRepository.findWithIntegrationType.mockResolvedValue([]); + + await task.run(signal); + + expect(agentRepository.findWithIntegrationType).toHaveBeenCalledWith('whatsapp'); + expect(attachmentService.deleteFromSourceCreatedBefore).not.toHaveBeenCalled(); + }); + + it("deletes each agent's WhatsApp media older than its retention setting", async () => { + agentRepository.findWithIntegrationType.mockResolvedValue([ + { id: 'agent-1', integrations: [whatsApp({ mediaRetentionDays: 7 })] }, + { id: 'agent-2', integrations: [whatsApp({ mediaRetentionDays: 365 })] }, + ]); + + await task.run(signal); + + expect(attachmentService.deleteFromSourceCreatedBefore).toHaveBeenCalledTimes(2); + expect(attachmentService.deleteFromSourceCreatedBefore).toHaveBeenCalledWith( + { agentId: 'agent-1', source: 'whatsapp' }, + new Date(NOW.getTime() - 7 * DAY_MS), + signal, + ); + expect(attachmentService.deleteFromSourceCreatedBefore).toHaveBeenCalledWith( + { agentId: 'agent-2', source: 'whatsapp' }, + new Date(NOW.getTime() - 365 * DAY_MS), + signal, + ); + }); + + it('keeps media for 30 days when the channel has no retention setting', async () => { + agentRepository.findWithIntegrationType.mockResolvedValue([ + { id: 'agent-1', integrations: [whatsApp()] }, + ]); + + await task.run(signal); + + expect(attachmentService.deleteFromSourceCreatedBefore).toHaveBeenCalledWith( + { agentId: 'agent-1', source: 'whatsapp' }, + new Date(NOW.getTime() - 30 * DAY_MS), + signal, + ); + }); + + it('uses the WhatsApp channel when the agent has other channels too', async () => { + agentRepository.findWithIntegrationType.mockResolvedValue([ + { + id: 'agent-1', + integrations: [ + { type: 'telegram', credentialId: 'cred-2' } as AgentIntegrationConfig, + whatsApp({ mediaRetentionDays: 3 }), + ], + }, + ]); + + await task.run(signal); + + expect(attachmentService.deleteFromSourceCreatedBefore).toHaveBeenCalledExactlyOnceWith( + { agentId: 'agent-1', source: 'whatsapp' }, + new Date(NOW.getTime() - 3 * DAY_MS), + signal, + ); + }); + + it('skips an agent that no longer has a WhatsApp channel', async () => { + agentRepository.findWithIntegrationType.mockResolvedValue([ + { + id: 'agent-1', + integrations: [{ type: 'telegram', credentialId: 'cred-2' } as AgentIntegrationConfig], + }, + ]); + + await task.run(signal); + + expect(attachmentService.deleteFromSourceCreatedBefore).not.toHaveBeenCalled(); + }); + + it('skips an agent whose integrations are null', async () => { + agentRepository.findWithIntegrationType.mockResolvedValue([ + { id: 'agent-1', integrations: null } as never, + ]); + + await task.run(signal); + + expect(attachmentService.deleteFromSourceCreatedBefore).not.toHaveBeenCalled(); + }); + + it('stops before the next agent when the signal aborts', async () => { + const controller = new AbortController(); + agentRepository.findWithIntegrationType.mockResolvedValue([ + { id: 'agent-1', integrations: [whatsApp()] }, + { id: 'agent-2', integrations: [whatsApp()] }, + ]); + attachmentService.deleteFromSourceCreatedBefore.mockImplementationOnce(async () => { + controller.abort(); + return 0; + }); + + await task.run(controller.signal); + + expect(attachmentService.deleteFromSourceCreatedBefore).toHaveBeenCalledExactlyOnceWith( + { agentId: 'agent-1', source: 'whatsapp' }, + expect.any(Date), + controller.signal, + ); + }); + + it('logs a failure and continues with the next agent', async () => { + const error = new Error('storage down'); + agentRepository.findWithIntegrationType.mockResolvedValue([ + { id: 'agent-1', integrations: [whatsApp()] }, + { id: 'agent-2', integrations: [whatsApp()] }, + ]); + attachmentService.deleteFromSourceCreatedBefore.mockRejectedValueOnce(error); + + await task.run(signal); + + expect(attachmentService.deleteFromSourceCreatedBefore).toHaveBeenCalledTimes(2); + expect(attachmentService.deleteFromSourceCreatedBefore).toHaveBeenLastCalledWith( + { agentId: 'agent-2', source: 'whatsapp' }, + expect.any(Date), + signal, + ); + expect(logger.warn).toHaveBeenCalledExactlyOnceWith(expect.any(String), { + agentId: 'agent-1', + error, + }); + }); + + it('logs the count only when it deletes media', async () => { + agentRepository.findWithIntegrationType.mockResolvedValue([ + { id: 'agent-1', integrations: [whatsApp()] }, + { id: 'agent-2', integrations: [whatsApp()] }, + ]); + attachmentService.deleteFromSourceCreatedBefore + .mockResolvedValueOnce(4) + .mockResolvedValueOnce(0); + + await task.run(signal); + + expect(logger.debug).toHaveBeenCalledExactlyOnceWith(expect.any(String), { + agentId: 'agent-1', + deleted: 4, + }); + }); +}); diff --git a/packages/cli/src/modules/agents/__tests__/agent-chat-attachment.repository.test.ts b/packages/cli/src/modules/agents/__tests__/agent-chat-attachment.repository.test.ts new file mode 100644 index 00000000000..9230a152508 --- /dev/null +++ b/packages/cli/src/modules/agents/__tests__/agent-chat-attachment.repository.test.ts @@ -0,0 +1,39 @@ +import { LessThan } from '@n8n/typeorm'; + +import { mockEntityManager } from '@test/mocking'; + +import { AgentChatAttachment } from '../entities/agent-chat-attachment.entity'; +import { AgentChatAttachmentRepository } from '../repositories/agent-chat-attachment.repository'; + +const entityManager = mockEntityManager(AgentChatAttachment); +const mockDataSource = { manager: entityManager }; + +describe('AgentChatAttachmentRepository', () => { + let repository: AgentChatAttachmentRepository; + + beforeEach(() => { + vi.clearAllMocks(); + repository = new AgentChatAttachmentRepository(mockDataSource as never); + }); + + describe('findFromSourceCreatedBefore', () => { + it('finds the oldest attachments from the source before the cutoff, up to the limit', async () => { + const attachments = [new AgentChatAttachment()]; + const find = vi.spyOn(repository, 'find').mockResolvedValue(attachments); + const before = new Date('2026-06-01T00:00:00.000Z'); + + const result = await repository.findFromSourceCreatedBefore( + { agentId: 'agent-1', source: 'whatsapp' }, + before, + 50, + ); + + expect(find).toHaveBeenCalledWith({ + where: { agentId: 'agent-1', source: 'whatsapp', createdAt: LessThan(before) }, + order: { createdAt: 'ASC' }, + take: 50, + }); + expect(result).toBe(attachments); + }); + }); +}); diff --git a/packages/cli/src/modules/agents/__tests__/agent-chat-attachment.service.test.ts b/packages/cli/src/modules/agents/__tests__/agent-chat-attachment.service.test.ts index fe7b6903874..3c26b77c6ff 100644 --- a/packages/cli/src/modules/agents/__tests__/agent-chat-attachment.service.test.ts +++ b/packages/cli/src/modules/agents/__tests__/agent-chat-attachment.service.test.ts @@ -262,4 +262,104 @@ describe('AgentChatAttachmentService', () => { expect(repository.delete).not.toHaveBeenCalled(); }); }); + + describe('deleteFromSourceCreatedBefore', () => { + const BATCH_SIZE = 500; + const scope = { agentId: 'agent-1', source: 'whatsapp' }; + const before = new Date('2026-01-01T00:00:00.000Z'); + + const attachments = (count: number, prefix: string) => + Array.from({ length: count }, (_, i) => ({ + id: `${prefix}-${i}`, + binaryDataId: `filesystem-v2:${prefix}-${i}`, + })) as AgentChatAttachment[]; + + beforeEach(() => { + binaryDataService.deleteManyByBinaryDataId.mockResolvedValue(undefined as never); + }); + + it('deletes in batches until a batch is smaller than the batch size', async () => { + repository.findFromSourceCreatedBefore + .mockResolvedValueOnce(attachments(BATCH_SIZE, 'a')) + .mockResolvedValueOnce(attachments(BATCH_SIZE, 'b')) + .mockResolvedValueOnce(attachments(3, 'c')); + + const deleted = await service.deleteFromSourceCreatedBefore(scope, before); + + expect(deleted).toBe(BATCH_SIZE * 2 + 3); + expect(repository.findFromSourceCreatedBefore).toHaveBeenCalledTimes(3); + expect(repository.findFromSourceCreatedBefore).toHaveBeenCalledWith( + scope, + before, + BATCH_SIZE, + ); + expect(repository.delete).toHaveBeenCalledTimes(3); + expect(repository.delete).toHaveBeenLastCalledWith(['c-0', 'c-1', 'c-2']); + expect(binaryDataService.deleteManyByBinaryDataId).toHaveBeenLastCalledWith([ + 'filesystem-v2:c-0', + 'filesystem-v2:c-1', + 'filesystem-v2:c-2', + ]); + }); + + it('queries again after a full batch and stops at an empty one', async () => { + repository.findFromSourceCreatedBefore + .mockResolvedValueOnce(attachments(BATCH_SIZE, 'a')) + .mockResolvedValueOnce([]); + + expect(await service.deleteFromSourceCreatedBefore(scope, before)).toBe(BATCH_SIZE); + expect(repository.findFromSourceCreatedBefore).toHaveBeenCalledTimes(2); + expect(repository.delete).toHaveBeenCalledTimes(1); + }); + + it('returns 0 and deletes nothing when no file is overdue', async () => { + repository.findFromSourceCreatedBefore.mockResolvedValueOnce([]); + + expect(await service.deleteFromSourceCreatedBefore(scope, before)).toBe(0); + expect(repository.findFromSourceCreatedBefore).toHaveBeenCalledTimes(1); + expect(repository.delete).not.toHaveBeenCalled(); + expect(binaryDataService.deleteManyByBinaryDataId).not.toHaveBeenCalled(); + }); + + it('deletes the bytes before the rows', async () => { + repository.findFromSourceCreatedBefore.mockResolvedValueOnce(attachments(2, 'a')); + + await service.deleteFromSourceCreatedBefore(scope, before); + + expect(binaryDataService.deleteManyByBinaryDataId.mock.invocationCallOrder[0]).toBeLessThan( + repository.delete.mock.invocationCallOrder[0], + ); + }); + + it('keeps the rows and throws when the bytes cannot be deleted', async () => { + repository.findFromSourceCreatedBefore.mockResolvedValueOnce(attachments(2, 'a')); + binaryDataService.deleteManyByBinaryDataId.mockRejectedValueOnce(new Error('storage down')); + + await expect(service.deleteFromSourceCreatedBefore(scope, before)).rejects.toThrow( + 'storage down', + ); + expect(repository.delete).not.toHaveBeenCalled(); + }); + + it('stops between batches when the signal aborts', async () => { + const controller = new AbortController(); + repository.findFromSourceCreatedBefore.mockImplementationOnce(async () => { + controller.abort(); + return attachments(BATCH_SIZE, 'a'); + }); + + const deleted = await service.deleteFromSourceCreatedBefore(scope, before, controller.signal); + + expect(deleted).toBe(BATCH_SIZE); + expect(repository.findFromSourceCreatedBefore).toHaveBeenCalledTimes(1); + }); + + it('deletes nothing when the signal is already aborted', async () => { + const controller = new AbortController(); + controller.abort(); + + expect(await service.deleteFromSourceCreatedBefore(scope, before, controller.signal)).toBe(0); + expect(repository.findFromSourceCreatedBefore).not.toHaveBeenCalled(); + }); + }); }); diff --git a/packages/cli/src/modules/agents/__tests__/agent-chat.controller.test.ts b/packages/cli/src/modules/agents/__tests__/agent-chat.controller.test.ts index 36df90dec46..5a7d480ba0a 100644 --- a/packages/cli/src/modules/agents/__tests__/agent-chat.controller.test.ts +++ b/packages/cli/src/modules/agents/__tests__/agent-chat.controller.test.ts @@ -781,7 +781,7 @@ describe('AgentChatController budget notice', () => { it('emits a budget-notice event when the resumed preview run reports one', async () => { const { controller, agentExecutionOrchestratorService } = makeController(); agentExecutionOrchestratorService.resumeForChat.mockImplementation(async function* (config) { - config.onBudgetNotice?.(); + config.onBudgetNotice?.({ code: 'budget.alert' }); yield { type: 'finish', finishReason: 'stop' }; }); @@ -798,6 +798,31 @@ describe('AgentChatController budget notice', () => { .map((line) => JSON.parse(line.slice(6).trim()) as { type: string }); expect(events).toContainEqual({ type: 'budget-notice', code: 'budget.alert' }); }); + + it('forwards a child budget stop code and owner on the budget-notice event', async () => { + const { controller, agentExecutionOrchestratorService } = makeController(); + agentExecutionOrchestratorService.resumeForChat.mockImplementation(async function* (config) { + config.onBudgetNotice?.({ code: 'budget.monthly', agentId: 'agent-2' }); + yield { type: 'finish', finishReason: 'stop' }; + }); + + const writes: string[] = []; + await controller.chatResume( + { params: { projectId: 'project-1' }, user: { id: 'user-1' } } as never, + makeSseResponse(writes), + 'agent-1', + { runId: 'run-1', toolCallId: 'tc-1', resumeData: { approved: true } } as never, + ); + + const events = writes + .filter((line) => line.startsWith('data: ')) + .map((line) => JSON.parse(line.slice(6).trim()) as { type: string }); + expect(events).toContainEqual({ + type: 'budget-notice', + code: 'budget.monthly', + agentId: 'agent-2', + }); + }); }); describe('AgentChatController HITL cancellation', () => { diff --git a/packages/cli/src/modules/agents/__tests__/agent-checkpoint-pruning.task.test.ts b/packages/cli/src/modules/agents/__tests__/agent-checkpoint-pruning.task.test.ts index 1db7f467984..2019b0d34b9 100644 --- a/packages/cli/src/modules/agents/__tests__/agent-checkpoint-pruning.task.test.ts +++ b/packages/cli/src/modules/agents/__tests__/agent-checkpoint-pruning.task.test.ts @@ -18,9 +18,11 @@ describe('AgentCheckpointPruningTask', () => { it('should declare an hourly prune cadence', () => { expect(task.name).toBe('agent-checkpoint-pruning'); expect(task.schedule).toEqual({ kind: 'interval', intervalSeconds: 3600 }); - expect(task.effects).toBe('idempotent'); - expect(task.placement).toEqual({ scope: 'cluster', durable: true, runOnTakeover: true }); - expect(task.retryDelaySeconds).toBe(30); + expect(task.target).toEqual({ + scope: 'cluster', + scheduler: { retryOnFailure: true, timeoutSeconds: 600 }, + leaderTimer: { runOnTakeover: true, retryDelaySeconds: 30 }, + }); }); it.each([ @@ -34,7 +36,8 @@ describe('AgentCheckpointPruningTask', () => { const database = mock({ type, postgresdb: { statementTimeoutMs } }); expect( - new AgentCheckpointPruningTask(database, checkpointStorage, backgroundJobs).timeoutSeconds, + new AgentCheckpointPruningTask(database, checkpointStorage, backgroundJobs).target.scheduler + .timeoutSeconds, ).toBe(timeoutSeconds); }, ); diff --git a/packages/cli/src/modules/agents/__tests__/agent-config.service.test.ts b/packages/cli/src/modules/agents/__tests__/agent-config.service.test.ts index a2af2573935..929a472aabd 100644 --- a/packages/cli/src/modules/agents/__tests__/agent-config.service.test.ts +++ b/packages/cli/src/modules/agents/__tests__/agent-config.service.test.ts @@ -21,7 +21,6 @@ import { AgentModificationTelemetryService } from '../agent-modification-telemet import { AgentSaveCompletionService } from '../agent-save-completion.service'; import { AgentRuntimeCacheService } from '../agent-runtime-cache.service'; import { AgentSetupCompletionService } from '../agent-setup-completion.service'; -import type { AgentSkillsService } from '../agent-skills.service'; import type { AgentUpdateBroadcaster } from '../agent-update-broadcaster'; import type { AgentValidationService } from '../agent-validation.service'; import type { Agent } from '../entities/agent.entity'; @@ -34,7 +33,6 @@ import type { AgentPolicyService } from '../agent-policy.service'; import { composeStoredJsonConfig, createAgentSkillRefsService, - storedSkillRefs, type AgentFixtureOverrides, } from './test-utils/stored-agent-config'; @@ -63,7 +61,6 @@ function makeAgent(overrides: AgentFixtureOverrides = {}): Agent { activeVersionId: null, schema: baseConfig, tools: {}, - skills: {}, integrations: [], setupCompletedAt: null, updatedAt: new Date('2025-01-01T00:00:00Z'), @@ -83,7 +80,7 @@ const byUser = fencedOn(makeAgent()); function makeService() { const agentRepository = mock(); const agentTaskRepository = mock(); - const agentSkillsService = mock(); + const skillRefs = createAgentSkillRefsService(); const runtimeCacheService = mock(); const credentialsService = mock(); const workflowRepository = mock(); @@ -105,12 +102,6 @@ function makeService() { credentialsService.getCredentialsAUserCanUseInAWorkflow.mockResolvedValue([]); agentTaskRepository.findByAgentId.mockResolvedValue([]); workflowRepository.findManyByAgentToolReferences.mockResolvedValue([]); - agentSkillsService.removeUnreferencedSkills.mockImplementation((agent, config) => { - const ids = new Set((config.skills ?? []).map((skill) => skill.id)); - agent.skills = Object.fromEntries( - Object.entries(agent.skills ?? {}).filter(([id]) => ids.has(id)), - ); - }); const transactionRunner = mock(); transactionRunner.run.mockImplementation(async (ctx, fn) => await fn(ctx)); @@ -119,7 +110,6 @@ function makeService() { mockLogger(), agentRepository, agentTaskRepository, - agentSkillsService, new AgentConfigPreparationService( credentialsService, workflowRepository, @@ -133,7 +123,7 @@ function makeService() { new AgentModificationTelemetryService(telemetry), ), agentPolicyService, - createAgentSkillRefsService(agentRepository), + skillRefs, ); return { @@ -141,7 +131,7 @@ function makeService() { agentPolicyService, agentRepository, agentTaskRepository, - agentSkillsService, + skillRefs, runtimeCacheService, credentialsService, workflowRepository, @@ -335,7 +325,7 @@ describe('AgentConfigService', () => { projectId, agentId, expect.objectContaining({ tools: [expect.objectContaining(dateTimeTool)] }), - baseConfig, + { ...baseConfig, skills: [] }, { kind: 'user', user }, ); }); @@ -676,8 +666,8 @@ describe('AgentConfigService', () => { expect(saved.schema).toHaveProperty('description', ''); }); - it('deletes the resources of omitted tools, skills, and tasks when clearOmittedOptionalFields is set', async () => { - const { service, agentRepository, agentTaskRepository } = makeService(); + it('deletes the resources of omitted tools and tasks and detaches omitted skills when clearOmittedOptionalFields is set', async () => { + const { service, agentRepository, agentTaskRepository, skillRefs } = makeService(); const agent = makeAgent({ schema: { ...baseConfig, @@ -686,7 +676,6 @@ describe('AgentConfigService', () => { tasks: [{ type: 'task', id: 'task-1', enabled: true }], } as unknown as AgentJsonConfig, tools: storedCustomTool, - skills: { 'skill-1': { name: 'Skill' } } as unknown as Agent['skills'], }); agentRepository.findByIdAndProjectId.mockResolvedValue(agent); agentTaskRepository.findByAgentId.mockResolvedValue([{ id: 'task-1' }] as never); @@ -698,12 +687,12 @@ describe('AgentConfigService', () => { const saved = agentRepository.saveDraftFenced.mock.calls.at(-1)?.[0] as Agent; expect(saved.tools).toEqual({}); - expect(saved.skills).toEqual({}); + expect(skillRefs.replaceDraftRefs).toHaveBeenCalledWith(saved, undefined, {}); expect(agentTaskRepository.deleteForAgent).toHaveBeenCalledWith(agentId, ['task-1'], {}); }); it('keeps the resources of omitted tools, skills, and tasks by default', async () => { - const { service, agentRepository, agentTaskRepository } = makeService(); + const { service, agentRepository, agentTaskRepository, skillRefs } = makeService(); const agent = makeAgent({ schema: { ...baseConfig, @@ -711,7 +700,6 @@ describe('AgentConfigService', () => { skills: [{ type: 'skill', id: 'skill-1' }], } as unknown as AgentJsonConfig, tools: storedCustomTool, - skills: { 'skill-1': { name: 'Skill' } } as unknown as Agent['skills'], }); agentRepository.findByIdAndProjectId.mockResolvedValue(agent); @@ -719,7 +707,11 @@ describe('AgentConfigService', () => { const saved = agentRepository.saveDraftFenced.mock.calls.at(-1)?.[0] as Agent; expect(saved.tools).toEqual(storedCustomTool); - expect(Object.keys(saved.skills ?? {})).toEqual(['skill-1']); + expect(skillRefs.replaceDraftRefs).toHaveBeenCalledWith( + saved, + [{ type: 'skill', id: 'skill-1' }], + {}, + ); expect(agentTaskRepository.deleteForAgent).not.toHaveBeenCalled(); }); @@ -739,6 +731,7 @@ describe('AgentConfigService', () => { expect(credentialsService.getCredentialsAUserCanUseInAWorkflow).toHaveBeenCalledWith(user, { projectId, + excludePersonalRoute: true, }); expect(credentialsService.findAllCredentialIdsForProject).not.toHaveBeenCalled(); const saved = agentRepository.saveDraftFenced.mock.calls.at(-1)?.[0] as Agent; @@ -819,14 +812,29 @@ describe('AgentConfigService', () => { ]); }); + it('drops the inline body of a removed skill ref while the skills hub is off', async () => { + const { service, agentRepository, skillRefs } = makeService(); + Object.assign(skillRefs, { usesSkillsHub: false }); + const kept = { name: 'Kept', description: 'Kept', instructions: 'Keep.' }; + const agent = makeAgent({ + skills: { kept, removed: { name: 'Removed', description: 'Removed', instructions: 'Go.' } }, + }); + agentRepository.findByIdAndProjectId.mockResolvedValue(agent); + + await service.updateConfig( + agentId, + projectId, + { ...baseConfig, skills: [{ type: 'skill', id: 'kept' }] }, + user, + byUser, + ); + + expect(agentRepository.saveDraftFenced.mock.calls[0][0].skills).toEqual({ kept }); + }); + it('removes config refs and stored bodies that no longer have matching definitions', async () => { - const { - service, - agentRepository, - agentTaskRepository, - agentSkillsService, - runtimeCacheService, - } = makeService(); + const { service, agentRepository, agentTaskRepository, skillRefs, runtimeCacheService } = + makeService(); const agent = makeAgent({ tools: { tool_1: { @@ -838,9 +846,6 @@ describe('AgentConfigService', () => { descriptor: { name: 'tool_2', description: 'b', inputSchema: {} }, }, } as unknown as Agent['tools'], - skills: { - 'skill-1': { name: 'Skill', description: 'desc', instructions: 'Use it' }, - }, }); agentRepository.findByIdAndProjectId.mockResolvedValue(agent); agentTaskRepository.findByAgentId.mockResolvedValue([ @@ -860,10 +865,9 @@ describe('AgentConfigService', () => { { type: 'custom', id: 'disabled_missing_tool', enabled: false }, ], skills: [ - { type: 'skill', id: 'skill-1', enabled: false }, + { type: 'skill', id: 'skill-1' }, { type: 'skill', id: 'missing-skill' }, { type: 'skill', id: 'toString' }, - { type: 'skill', id: 'disabled-missing-skill', enabled: false }, ], tasks: [ { type: 'task', id: 'task-1', enabled: true }, @@ -879,14 +883,20 @@ describe('AgentConfigService', () => { { type: 'custom', id: 'tool_1', enabled: false, requireApproval: true }, { type: 'custom', id: 'disabled_missing_tool', enabled: false }, ]); - expect(saved.schema?.skills).toEqual([ - { type: 'skill', id: 'skill-1', enabled: false }, - { type: 'skill', id: 'disabled-missing-skill', enabled: false }, - ]); + // The skill refs seam checks skill refs against the skills hub. + expect(saved.schema).not.toHaveProperty('skills'); + expect(skillRefs.replaceDraftRefs).toHaveBeenCalledWith( + saved, + [ + { type: 'skill', id: 'skill-1' }, + { type: 'skill', id: 'missing-skill' }, + { type: 'skill', id: 'toString' }, + ], + {}, + ); expect(saved.schema?.tasks).toEqual([{ type: 'task', id: 'task-1', enabled: true }]); expect(Object.keys(saved.tools)).toEqual(['tool_1']); expect(agentTaskRepository.deleteForAgent).toHaveBeenCalledWith(agentId, ['task-2'], {}); - expect(agentSkillsService.removeUnreferencedSkills).toHaveBeenCalled(); expect(runtimeCacheService.clearRuntimes).toHaveBeenCalledWith(agentId); }); @@ -895,7 +905,6 @@ describe('AgentConfigService', () => { const config: AgentJsonConfig = { ...baseConfig, tools: [{ type: 'custom', id: 'missing_tool', enabled: false, requireApproval: true }], - skills: [{ type: 'skill', id: 'missing_skill', enabled: false }], subAgents: { agents: [{ agentId: 'missing-agent', enabled: false, useWhen: 'Review' }] }, }; const agent = makeAgent({ schema: config }); @@ -905,7 +914,6 @@ describe('AgentConfigService', () => { const activated: AgentJsonConfig = { ...config, tools: [{ type: 'custom', id: 'missing_tool', enabled: true, requireApproval: true }], - skills: [{ type: 'skill', id: 'missing_skill', enabled: true }], subAgents: { agents: [{ agentId: 'missing-agent', enabled: true, useWhen: 'Review' }] }, }; @@ -1269,21 +1277,18 @@ describe('AgentConfigService', () => { }); describe('skill refs round trip', () => { + const pinId = '6f1c1c5e-1b7a-4d55-9d4e-3c2e8f6a9b10'; const skillRefs = [ { type: 'skill' as const, id: 'zeta' }, - { type: 'skill' as const, id: 'alpha', enabled: false }, - { type: 'skill' as const, id: 'mid', enabled: true }, + { type: 'skill' as const, id: 'alpha', versionId: pinId }, + { type: 'skill' as const, id: 'mid' }, ]; - const skillBody = { name: 'Skill', description: 'A skill', instructions: 'Do it.' }; function makeAgentWithSkillRefs() { - return makeAgent({ - schema: { ...baseConfig, skills: skillRefs }, - skills: { zeta: skillBody, mid: { ...skillBody, name: 'Mid' } }, - }); + return makeAgent({ schema: { ...baseConfig, skills: skillRefs } }); } - it('returns the stored skill refs from getConfig in order, with the enabled flags', async () => { + it('returns the skill refs of the draft from getConfig in order, with the pins', async () => { const { service, agentRepository } = makeService(); agentRepository.findByIdAndProjectId.mockResolvedValue(makeAgentWithSkillRefs()); @@ -1293,7 +1298,7 @@ describe('AgentConfigService', () => { }); it('saves the refs of a config that getConfig returned without a change', async () => { - const { service, agentRepository } = makeService(); + const { service, agentRepository, skillRefs: refsService } = makeService(); const agent = makeAgentWithSkillRefs(); agentRepository.findByIdAndProjectId.mockResolvedValue(agent); const config = await service.getConfig(agentId, projectId); @@ -1309,27 +1314,45 @@ describe('AgentConfigService', () => { expect(await service.getConfig(agentId, projectId)).toEqual(config); // The fenced save and the skill refs write share one transaction. const [[, saveCtx]] = agentRepository.saveDraftFenced.mock.calls; - const [[written, refsCtx]] = agentRepository.updateDraftSchema.mock.calls; + const [[written, refs, refsCtx]] = refsService.replaceDraftRefs.mock.calls; expect(refsCtx).toBe(saveCtx); - expect(storedSkillRefs(written)).toEqual(skillRefs); + expect(written).toBe(agent); + expect(refs).toEqual(skillRefs); + // The stored config holds no skill refs. + expect(agent.schema).not.toHaveProperty('skills'); }); - it('saves new refs in the order of the submitted config', async () => { - const { service, agentRepository } = makeService(); + it('passes the submitted refs to the skill refs seam', async () => { + const { service, agentRepository, skillRefs: refsService } = makeService(); agentRepository.findByIdAndProjectId.mockResolvedValue(makeAgentWithSkillRefs()); const config = await service.getConfig(agentId, projectId); - const reordered = [skillRefs[2], { ...skillRefs[0], enabled: false }, skillRefs[1]]; + const next = [skillRefs[2], { type: 'skill' as const, id: 'new' }]; + + await service.updateConfig(agentId, projectId, { ...config, skills: next }, user, { + baseConfigHash: getAgentConfigHash(config), + modifiedBy: 'user', + }); + + expect(refsService.replaceDraftRefs).toHaveBeenCalledWith(expect.anything(), next, {}); + }); + + it('validates, saves and reports the effective refs, without the stale ids', async () => { + const { service, agentRepository, skillRefs: refsService } = makeService(); + agentRepository.findByIdAndProjectId.mockResolvedValue(makeAgentWithSkillRefs()); + const config = await service.getConfig(agentId, projectId); + const kept = [skillRefs[2]]; + refsService.effectiveDraftRefs.mockResolvedValue(kept); const result = await service.updateConfig( agentId, projectId, - { ...config, skills: reordered }, + { ...config, skills: [skillRefs[2], { type: 'skill' as const, id: 'stale' }] }, user, { baseConfigHash: getAgentConfigHash(config), modifiedBy: 'user' }, ); - expect(result.config.skills).toEqual(reordered); - expect((await service.getConfig(agentId, projectId)).skills).toEqual(reordered); + expect(refsService.replaceDraftRefs).toHaveBeenCalledWith(expect.anything(), kept, {}); + expect(result.config.skills).toEqual(kept); }); }); @@ -1367,7 +1390,6 @@ describe('AgentConfigService', () => { it('counts the stored skill refs in the modification event', async () => { const { service, agentRepository, telemetry } = makeService(); - const skillBody = { name: 'Skill', description: 'A skill', instructions: 'Do it.' }; const agent = makeAgent({ schema: { ...baseConfig, @@ -1376,7 +1398,6 @@ describe('AgentConfigService', () => { { type: 'skill', id: 'billing' }, ], }, - skills: { refunds: skillBody, billing: skillBody }, }); agentRepository.findByIdAndProjectId.mockResolvedValue(agent); const config = composeStoredJsonConfig(agent); diff --git a/packages/cli/src/modules/agents/__tests__/agent-custom-tools.service.test.ts b/packages/cli/src/modules/agents/__tests__/agent-custom-tools.service.test.ts index 90b87a3bfdd..971bd680c06 100644 --- a/packages/cli/src/modules/agents/__tests__/agent-custom-tools.service.test.ts +++ b/packages/cli/src/modules/agents/__tests__/agent-custom-tools.service.test.ts @@ -71,7 +71,7 @@ function makeService() { agentUpdateBroadcaster, modificationTelemetry, ), - createAgentSkillRefsService(agentRepository), + createAgentSkillRefsService(), ); return { diff --git a/packages/cli/src/modules/agents/__tests__/agent-document.test.ts b/packages/cli/src/modules/agents/__tests__/agent-document.test.ts index 4d7e0e9c967..432f9b569b7 100644 --- a/packages/cli/src/modules/agents/__tests__/agent-document.test.ts +++ b/packages/cli/src/modules/agents/__tests__/agent-document.test.ts @@ -14,7 +14,7 @@ const document: AgentJsonConfig = { tools: [{ type: 'custom', id: 'lookup' }], skills: [ { type: 'skill', id: 'refunds' }, - { type: 'skill', id: 'billing', enabled: false }, + { type: 'skill', id: 'billing', versionId: '0b2c6f1e-7d3a-4c1b-9f2e-5a6b7c8d9e0f' }, { type: 'skill', id: 'apology' }, ], tasks: [{ type: 'task', id: 'daily', enabled: true }], @@ -30,12 +30,12 @@ describe('toAgentDocument / fromAgentDocument', () => { expect(toAgentDocument(config, skillRefs)).toEqual(document); }); - it('keeps the ref order and the enabled flags', () => { + it('keeps the ref order and the pins', () => { const { config, skillRefs } = fromAgentDocument(document); expect(toAgentDocument(config, skillRefs).skills).toEqual([ { type: 'skill', id: 'refunds' }, - { type: 'skill', id: 'billing', enabled: false }, + { type: 'skill', id: 'billing', versionId: '0b2c6f1e-7d3a-4c1b-9f2e-5a6b7c8d9e0f' }, { type: 'skill', id: 'apology' }, ]); }); @@ -69,11 +69,11 @@ describe('toAgentDocument / fromAgentDocument', () => { }); describe('config hash of a stored agent', () => { - // The value that master computes for this agent, before the skill refs seam. - // Clients send this hash back as the base hash of a save, so it must not change. - const MASTER_CONFIG_HASH = '04622862951435434cad418aeb1f64a5aa9152535af3f93e68d7730c94cb4dfa'; + // Clients send this hash back as the base hash of a save, so an accidental change to + // how skill refs compose must fail here. + const CONFIG_HASH = '1c29b5f1b9a64d762f735e1c218b23da83416ee305dca842f807019a6b4ba752'; - it('composes the same document and hash as before the seam', async () => { + it('composes the same document and hash from the stored config and its refs', async () => { const { integrations, ...schema } = document; const agent = { id: 'agent-1', schema: storedAgentConfig(schema), integrations } as Agent; @@ -81,6 +81,6 @@ describe('config hash of a stored agent', () => { const composed = composeJsonConfig(agent, skillRefs); expect(composed).toEqual(document); - expect(getAgentConfigHash(composed)).toBe(MASTER_CONFIG_HASH); + expect(getAgentConfigHash(composed)).toBe(CONFIG_HASH); }); }); diff --git a/packages/cli/src/modules/agents/__tests__/agent-execution-orchestrator.service.test.ts b/packages/cli/src/modules/agents/__tests__/agent-execution-orchestrator.service.test.ts index b9946bdb221..d986ae8b7f8 100644 --- a/packages/cli/src/modules/agents/__tests__/agent-execution-orchestrator.service.test.ts +++ b/packages/cli/src/modules/agents/__tests__/agent-execution-orchestrator.service.test.ts @@ -295,7 +295,7 @@ function makeService(sandboxEnabled = false) { backgroundJobRepository, backgroundJobs, settingsService, - createAgentSkillRefsService(agentRepository), + createAgentSkillRefsService(), ); return { diff --git a/packages/cli/src/modules/agents/__tests__/agent-integration-persistence.service.test.ts b/packages/cli/src/modules/agents/__tests__/agent-integration-persistence.service.test.ts index 71560e3e395..24b3a8c9c3c 100644 --- a/packages/cli/src/modules/agents/__tests__/agent-integration-persistence.service.test.ts +++ b/packages/cli/src/modules/agents/__tests__/agent-integration-persistence.service.test.ts @@ -102,7 +102,7 @@ function setup(options: SetupOptions = {}) { new AgentModificationTelemetryService(telemetry), credentialsService, setupCompletionService, - createAgentSkillRefsService(agentRepository), + createAgentSkillRefsService(), ), agent, row, @@ -673,6 +673,7 @@ describe('AgentIntegrationPersistenceService', () => { expect(credentialsService.getCredentialsAUserCanUseInAWorkflow).toHaveBeenCalledWith(user, { projectId, + excludePersonalRoute: true, }); expect(emitSetupCompleted).toHaveBeenCalledOnce(); expect(agentRepository.updateIntegrations.mock.invocationCallOrder[0]).toBeLessThan( diff --git a/packages/cli/src/modules/agents/__tests__/agent-interrupted-execution-sweep.task.test.ts b/packages/cli/src/modules/agents/__tests__/agent-interrupted-execution-sweep.task.test.ts index 7a10ebca83b..9610ee34efe 100644 --- a/packages/cli/src/modules/agents/__tests__/agent-interrupted-execution-sweep.task.test.ts +++ b/packages/cli/src/modules/agents/__tests__/agent-interrupted-execution-sweep.task.test.ts @@ -11,15 +11,17 @@ describe('AgentInterruptedExecutionSweepTask', () => { it('declares the liveness grace as a durable cluster cadence', () => { expect(task.name).toBe('agent-interrupted-execution-sweep'); expect(task.schedule).toEqual({ kind: 'interval', intervalSeconds: 120 }); - expect(task.effects).toBe('idempotent'); - expect(task.placement).toEqual({ scope: 'cluster', durable: true, runOnTakeover: true }); - expect(task.retryDelaySeconds).toBeUndefined(); + expect(task.target).toEqual({ + scope: 'cluster', + scheduler: { retryOnFailure: true }, + leaderTimer: { runOnTakeover: true }, + }); }); it('hands the signal to the sweeper', async () => { const { signal } = new AbortController(); - await task.run(signal, { durable: true }); + await task.run(signal); expect(sweeper.sweep).toHaveBeenCalledWith(signal); }); diff --git a/packages/cli/src/modules/agents/__tests__/agent-message-queue-consumer.service.test.ts b/packages/cli/src/modules/agents/__tests__/agent-message-queue-consumer.service.test.ts index 68398374d57..2bf38c8a226 100644 --- a/packages/cli/src/modules/agents/__tests__/agent-message-queue-consumer.service.test.ts +++ b/packages/cli/src/modules/agents/__tests__/agent-message-queue-consumer.service.test.ts @@ -186,7 +186,7 @@ describe('AgentMessageQueueConsumer', () => { repository.findThreadIds.mockResolvedValue(['session']); queue.claimNext.mockResolvedValueOnce(item).mockResolvedValue(null); testRuns.executePreparedDraftRun.mockImplementation(async (input) => { - input.onBudgetNotice?.(); + input.onBudgetNotice?.({ code: 'budget.alert' }); return { status: 'completed', response: '', diff --git a/packages/cli/src/modules/agents/__tests__/agent-model-catalog.service.test.ts b/packages/cli/src/modules/agents/__tests__/agent-model-catalog.service.test.ts index 81ebf44fa92..fca9eb4e70e 100644 --- a/packages/cli/src/modules/agents/__tests__/agent-model-catalog.service.test.ts +++ b/packages/cli/src/modules/agents/__tests__/agent-model-catalog.service.test.ts @@ -300,6 +300,79 @@ describe('AgentModelCatalogService', () => { expect(result.models.map((m) => m.id)).toEqual(['claude-sonnet-4-6']); }); + it('keeps the gateway label of a google model missing from the catalog', async () => { + const { service, lookupService } = makeService(); + lookupService.lookup.mockResolvedValue({ + status: 'success', + policy: 'managed', + models: [{ name: 'Gemini Brand New', value: 'models/gemini-brand-new' }], + }); + + const result = await service.getProviderModels( + user, + 'project-1', + 'google', + AI_GATEWAY_MANAGED_TAG, + ); + + expect(result.models).toEqual([ + expect.objectContaining({ id: 'gemini-brand-new', name: 'Gemini Brand New' }), + ]); + }); + + it('prefers the gateway name over the catalog name and keeps its priority for a managed model', async () => { + const { service, lookupService } = makeService(); + lookupService.lookup.mockResolvedValue({ + status: 'success', + policy: 'managed', + models: [ + { name: 'Gemini 2.5 Flash (Gateway)', value: 'models/gemini-2.5-flash', priority: 10 }, + { name: 'models/gemini-2.5-flash-lite', value: 'models/gemini-2.5-flash-lite' }, + ], + }); + + const result = await service.getProviderModels( + user, + 'project-1', + 'google', + AI_GATEWAY_MANAGED_TAG, + ); + + expect(result.models).toEqual([ + expect.objectContaining({ + id: 'gemini-2.5-flash', + name: 'Gemini 2.5 Flash (Gateway)', + reasoning: true, + priority: 10, + }), + expect.objectContaining({ id: 'gemini-2.5-flash-lite', name: 'gemini-2.5-flash-lite' }), + ]); + }); + + it('falls back to the catalog name or the id when the gateway reports no name', async () => { + const { service, lookupService } = makeService(); + lookupService.lookup.mockResolvedValue({ + status: 'success', + policy: 'managed', + models: [ + { name: '', value: 'models/gemini-2.5-flash' }, + { name: '', value: 'models/gemini-brand-new', priority: 5 }, + ], + }); + + const result = await service.getProviderModels( + user, + 'project-1', + 'google', + AI_GATEWAY_MANAGED_TAG, + ); + + expect(result.models).toEqual([ + expect.objectContaining({ id: 'gemini-2.5-flash', name: 'Gemini 2.5 Flash' }), + { id: 'gemini-brand-new', name: 'gemini-brand-new', toolCall: true, priority: 5 }, + ]); + }); + it('strips the "models/" prefix from google model ids before matching', async () => { const { service, lookupService } = makeService(); lookupService.lookup.mockResolvedValue({ diff --git a/packages/cli/src/modules/agents/__tests__/agent-publish.service.test.ts b/packages/cli/src/modules/agents/__tests__/agent-publish.service.test.ts index 6cf1fa4d14b..9d7e8b860d8 100644 --- a/packages/cli/src/modules/agents/__tests__/agent-publish.service.test.ts +++ b/packages/cli/src/modules/agents/__tests__/agent-publish.service.test.ts @@ -6,6 +6,7 @@ import type { User, TransactionRunner, OperationContext, Transaction } from '@n8 import { Container } from '@n8n/di'; import { TELEMETRY_EVENT } from '@n8n/telemetry'; import { QueryFailedError } from '@n8n/typeorm'; +import { UserError } from 'n8n-workflow'; import { mock } from 'vitest-mock-extended'; import type { CredentialsService } from '@/credentials/credentials.service'; @@ -16,6 +17,7 @@ import type { AgentCustomToolsService } from '../agent-custom-tools.service'; import { AgentSaveCompletionService } from '../agent-save-completion.service'; import { AgentDefinitionService } from '../agent-definition.service'; import { AgentPublishService } from '../agent-publish.service'; +import { withoutLegacySkillRefs } from '../json-config/agent-document'; import { AgentRuntimeCacheService } from '../agent-runtime-cache.service'; import { AgentModificationTelemetryService } from '../agent-modification-telemetry.service'; import { AgentSetupCompletionService } from '../agent-setup-completion.service'; @@ -33,7 +35,7 @@ import type { AgentRepository } from '../repositories/agent.repository'; import type { AgentPolicyService } from '../agent-policy.service'; import { type AgentFixtureOverrides, - AgentHistoryFixtureOverrides, + type AgentHistoryFixtureOverrides, createAgentSkillRefsService, storedSkillRefs, } from './test-utils/stored-agent-config'; @@ -139,6 +141,7 @@ function makeService() { Container.set(ChatIntegrationService, chatIntegrationService); Container.set(AgentTaskService, taskService); + const skillRefs = createAgentSkillRefsService(); const service = new AgentPublishService( mockLogger(), agentRepository, @@ -164,14 +167,15 @@ function makeService() { taskSnapshotRepository, agentRepository, transactionRunner, - createAgentSkillRefsService(agentRepository), + skillRefs, ), agentPolicyService, - createAgentSkillRefsService(agentRepository), + skillRefs, ); return { service, + skillRefs, agentPolicyService, agentUpdateBroadcaster, agentRepository, @@ -501,12 +505,9 @@ describe('AgentPublishService', () => { eventService, agentUpdateBroadcaster, ctx, + skillRefs, } = makeService(); const configuredTools = { tool: { descriptor: { name: 'tool' } } }; - const configuredSkills = { - skill: { name: 'Skill', description: 'desc', instructions: 'Use it' }, - disabled_skill: { name: 'Disabled skill', description: 'desc', instructions: 'Keep it' }, - }; const integrations = [ { type: 'slack', credentialId: 'slack-1' }, { @@ -519,14 +520,9 @@ describe('AgentPublishService', () => { schema: { ...schema, tools: [{ type: 'custom', id: 'tool' }], - skills: [ - { type: 'skill', id: 'skill' }, - { type: 'skill', id: 'disabled_skill', enabled: false }, - { type: 'skill', id: 'missing_skill', enabled: false }, - ], + skills: [{ type: 'skill', id: 'skill' }], tasks: [{ type: 'task', id: 'task-1', enabled: true }], }, - skills: configuredSkills, integrations: [...integrations, { type: 'n8n_chat', credentialId: '' }], }); const draftValidation = { status: 'valid' as const, issues: [] }; @@ -559,13 +555,23 @@ describe('AgentPublishService', () => { { versionId, agentId, - schema: { ...agent.schema, integrations: [{ type: 'n8n_chat', credentialId: '' }] }, + // The legacy columns keep the refs and bodies, so a rollback can run this version. + schema: { + ...withoutLegacySkillRefs(agent.schema!), + skills: storedSkillRefs(agent), + integrations: [{ type: 'n8n_chat', credentialId: '' }], + }, tools: configuredTools, - skills: configuredSkills, + skills: {}, publishedBy: user, }, ctx, ); + expect(skillRefs.pinVersion).toHaveBeenCalledWith( + versionId, + await skillRefs.versionSnapshot.mock.results[0].value, + ctx, + ); expect(taskSnapshotRepository.saveForVersion).toHaveBeenCalledWith( [expect.objectContaining({ versionId, taskId: 'task-1', objective: 'Summarize messages' })], ctx, @@ -644,8 +650,8 @@ describe('AgentPublishService', () => { expect(telemetry.track).not.toHaveBeenCalled(); }); - it('rejects publishing when a configured skill body is missing', async () => { - const { service, agentRepository, runtimeCacheService } = makeService(); + it('rejects publishing when a skill cannot be pinned', async () => { + const { service, agentRepository, runtimeCacheService, skillRefs } = makeService(); const agent = makeAgent({ schema: { ...schema, @@ -653,9 +659,12 @@ describe('AgentPublishService', () => { }, }); agentRepository.findByIdAndProjectId.mockResolvedValue(agent); + skillRefs.versionSnapshot.mockRejectedValue( + new UserError('Cannot publish agent with missing skills: missing_skill'), + ); await expect(service.publishAgent(agentId, projectId, user, byUser)).rejects.toThrow( - 'Cannot publish agent with missing skill bodies: missing_skill', + 'Cannot publish agent with missing skills: missing_skill', ); expect(agent.activeVersionId).toBeNull(); @@ -793,7 +802,8 @@ describe('AgentPublishService', () => { }); it('reverts draft fields and task bodies from the active published snapshot', async () => { - const { service, agentRepository, taskSnapshotRepository, agentTaskRepository } = makeService(); + const { service, agentRepository, taskSnapshotRepository, agentTaskRepository, skillRefs } = + makeService(); const activeVersion = makeHistory({ versionId: 'published-v1', schema: { @@ -809,12 +819,11 @@ describe('AgentPublishService', () => { }, }, ], - skills: [{ type: 'skill', id: 'skill', enabled: false }], + skills: [{ type: 'skill', id: 'skill' }], subAgents: { agents: [{ agentId: 'agent-2', enabled: false, useWhen: 'Review notes' }] }, tasks: [{ type: 'task', id: 'task-1', enabled: false }], }, tools: { tool: { descriptor: { name: 'published' } } } as unknown as AgentHistory['tools'], - skills: { skill: { name: 'Skill', description: 'desc', instructions: 'Use it' } }, }); const agent = makeAgent({ name: 'Draft Agent', @@ -823,7 +832,6 @@ describe('AgentPublishService', () => { activeVersion, schema: { ...schema, name: 'Draft Agent' }, tools: {}, - skills: {}, }); agentRepository.findByIdAndProjectId.mockResolvedValue(agent); @@ -834,11 +842,20 @@ describe('AgentPublishService', () => { agent, ); - expect(agent.schema).toEqual(activeVersion.schema); + const { skills: publishedSkillRefs, ...publishedConfig } = + activeVersion.schema as AgentJsonConfig; + expect(agent.schema).toEqual(publishedConfig); expect(agent.name).toBe(schema.name); expect(agent.versionId).toBe('published-v1'); expect(agent.tools).toEqual(activeVersion.tools); - expect(agent.skills).toEqual(activeVersion.skills); + // The skill refs are pinned to the versions that the published version ran. + expect(skillRefs.restoreDraftRefs).toHaveBeenCalledWith( + agent, + activeVersion, + publishedSkillRefs, + expect.anything(), + ); + expect(skillRefs.replaceDraftRefs).not.toHaveBeenCalled(); expect(agentTaskRepository.replaceForAgent).toHaveBeenCalledWith( agentId, new Map([['task-1', expect.objectContaining({ objective: 'Summarize messages' })]]), @@ -918,8 +935,14 @@ describe('AgentPublishService', () => { }); it('reports sidecar body-only reverts when schema references are unchanged', async () => { - const { service, agentRepository, taskSnapshotRepository, agentTaskRepository, telemetry } = - makeService(); + const { + service, + agentRepository, + taskSnapshotRepository, + agentTaskRepository, + telemetry, + skillRefs, + } = makeService(); const schemaWithRefs: AgentJsonConfig = { ...schema, tools: [{ type: 'custom', id: 'tool-1' }], @@ -929,23 +952,21 @@ describe('AgentPublishService', () => { const publishedTools = { 'tool-1': { code: 'published', descriptor: { name: 'tool-1' } }, } as unknown as AgentHistory['tools']; - const publishedSkills = { - 'skill-1': { name: 'Skill', description: 'published', instructions: 'Use published' }, - }; const activeVersion = makeHistory({ versionId: 'published-v1', schema: schemaWithRefs, tools: publishedTools, - skills: publishedSkills, }); const agent = makeAgent({ activeVersionId: 'published-v1', activeVersion, schema: schemaWithRefs, tools: { 'tool-1': { code: 'draft', descriptor: { name: 'tool-1' } } } as never, - skills: { - 'skill-1': { name: 'Skill', description: 'draft', instructions: 'Use draft' }, - }, + }); + // The draft follows the latest version; the revert pins the published one. + const pin = '0b2c6f1e-7d3a-4c1b-9f2e-5a6b7c8d9e0f'; + skillRefs.restoreDraftRefs.mockImplementation(async (draft) => { + skillRefs.draftRefs.set(draft.id, [{ type: 'skill', id: 'skill-1', versionId: pin }]); }); agentRepository.findByIdAndProjectId.mockResolvedValue(agent); @@ -969,6 +990,44 @@ describe('AgentPublishService', () => { expect(telemetry.track).toHaveBeenCalledTimes(1); }); + it('reports a skills change when a revert with the hub off keeps the ids and restores other bodies', async () => { + const { + service, + agentRepository, + taskSnapshotRepository, + agentTaskRepository, + telemetry, + skillRefs, + } = makeService(); + Object.assign(skillRefs, { usesSkillsHub: false }); + const refs: AgentJsonConfig['skills'] = [{ type: 'skill', id: 'skill-1' }]; + const activeVersion = makeHistory({ + versionId: 'published-v1', + schema: { ...schema, skills: refs }, + skills: { 'skill-1': { name: 'Notes', description: 'Notes', instructions: 'Published.' } }, + }); + const agent = makeAgent({ + activeVersionId: 'published-v1', + activeVersion, + schema: { ...schema, skills: refs }, + skills: { 'skill-1': { name: 'Notes', description: 'Notes', instructions: 'Draft.' } }, + }); + // As the legacy writer: the refs stay, and the bodies of the version come back. + skillRefs.restoreDraftRefs.mockImplementation(async (draft, version) => { + draft.skills = structuredClone(version.skills ?? {}); + }); + agentRepository.findByIdAndProjectId.mockResolvedValue(agent); + taskSnapshotRepository.findByVersionId.mockResolvedValue([]); + agentTaskRepository.replaceForAgent.mockResolvedValue(false); + + await service.revertToPublishedAgent(agentId, projectId, user, 'user'); + + expect(telemetry.track).toHaveBeenCalledWith( + TELEMETRY_EVENT.AGENTS.USER_MODIFIED_AGENT, + expect.objectContaining({ changed_parts: expect.arrayContaining(['skills']) }), + ); + }); + it('reads the selected version without using draft or active-version bodies', async () => { const { service, @@ -976,6 +1035,7 @@ describe('AgentPublishService', () => { agentHistoryRepository, taskSnapshotRepository, agentTaskRepository, + skillRefs, } = makeService(); const version = makeHistory({ versionId: 'old-version', @@ -985,26 +1045,18 @@ describe('AgentPublishService', () => { tasks: [{ type: 'task', id: 'task-1', enabled: false }], integrations: [{ type: 'n8n_chat', credentialId: '' }], }, - skills: { - skill: { - name: 'Older skill', - description: 'Older description', - instructions: 'Older body', - }, - }, }); + const olderSkill = { + name: 'Older skill', + description: 'Older description', + instructions: 'Older body', + }; + skillRefs.readVersion.mockResolvedValue({ skillRefs: [], skills: { skill: olderSkill } }); const agent = makeAgent({ schema: { ...schema, name: 'Draft agent' }, tools: { draft_tool: { code: 'return 1;', descriptor: mock({ name: 'draft_tool' }) }, }, - skills: { - skill: { - name: 'Draft skill', - description: 'Draft description', - instructions: 'Draft body', - }, - }, activeVersion: makeHistory({ versionId: 'active-version', schema: { ...schema, name: 'Active agent' }, @@ -1025,9 +1077,9 @@ describe('AgentPublishService', () => { ); expect(result.version).toBe(version); expect(result.definition).toEqual({ - schema: version.schema, + schema: { ...version.schema, skills: [] }, tools: {}, - skills: version.skills, + skills: { skill: olderSkill }, tasks: new Map([ [ 'task-1', @@ -1049,21 +1101,19 @@ describe('AgentPublishService', () => { describe('skill refs round trip', () => { const skillRefs = [ { type: 'skill' as const, id: 'zeta' }, - { type: 'skill' as const, id: 'alpha', enabled: false }, - { type: 'skill' as const, id: 'mid', enabled: true }, + { type: 'skill' as const, id: 'mid' }, ]; - const skillBodies = { - zeta: { name: 'Zeta', description: 'desc', instructions: 'Use zeta' }, - mid: { name: 'Mid', description: 'desc', instructions: 'Use mid' }, - }; - it('publishes the draft skill refs into the version', async () => { - const { service, agentRepository, agentHistoryRepository, agentValidationService } = - makeService(); - const agent = makeAgent({ - schema: { ...schema, skills: skillRefs }, - skills: skillBodies, - }); + it('pins the draft skill refs in the publish transaction', async () => { + const { + service, + agentRepository, + agentHistoryRepository, + agentValidationService, + skillRefs: refsService, + ctx, + } = makeService(); + const agent = makeAgent({ schema: { ...schema, skills: skillRefs } }); agentRepository.findByIdAndProjectId.mockResolvedValue(agent); agentValidationService.validateAgentEntityConfiguration.mockResolvedValue({ status: 'valid', @@ -1072,22 +1122,33 @@ describe('AgentPublishService', () => { await service.publishAgent(agentId, projectId, user, byBuilder); - const [[saved]] = agentHistoryRepository.saveVersion.mock.calls; - const version = makeHistory({ versionId: saved.versionId }); - version.schema = saved.schema; - await expect(createAgentSkillRefsService().refsForVersion(version, {})).resolves.toEqual( - skillRefs, + const [[saved, saveCtx]] = agentHistoryRepository.saveVersion.mock.calls; + // The legacy columns keep the refs, so a rollback still finds the published skills. + expect(saved.schema?.skills).toEqual(skillRefs); + expect(refsService.versionSnapshot).toHaveBeenCalledWith(agent, ctx); + expect(refsService.pinVersion).toHaveBeenCalledWith( + saved.versionId, + expect.objectContaining({ pins: expect.any(Map) }), + ctx, + ); + expect(saveCtx).toBe(ctx); + // The pins need the history row. + expect(agentHistoryRepository.saveVersion.mock.invocationCallOrder[0]).toBeLessThan( + refsService.pinVersion.mock.invocationCallOrder[0], ); - expect(saved.skills).toEqual(skillBodies); }); - it('reverts the draft skill refs to the refs of the version', async () => { - const { service, agentRepository, taskSnapshotRepository, agentTaskRepository } = - makeService(); + it('reverts the draft skill refs to the pinned refs of the version', async () => { + const { + service, + agentRepository, + taskSnapshotRepository, + agentTaskRepository, + skillRefs: refsService, + } = makeService(); const activeVersion = makeHistory({ versionId: 'published-v1', schema: { ...schema, skills: skillRefs }, - skills: skillBodies, }); const agent = makeAgent({ versionId: 'draft-v2', @@ -1098,16 +1159,23 @@ describe('AgentPublishService', () => { agentRepository.findByIdAndProjectId.mockResolvedValue(agent); taskSnapshotRepository.findByVersionId.mockResolvedValue([]); agentTaskRepository.replaceForAgent.mockResolvedValue(false); + // The published version ran these skill versions. + refsService.versionPins.set('published-v1', { zeta: 'zeta-v1', mid: 'mid-v3' }); await service.revertToPublishedAgent(agentId, projectId, user, 'user'); - await expect(createAgentSkillRefsService().refsForDraft(agent, {})).resolves.toEqual( - skillRefs, - ); + // The draft gets the refs back, each pinned to the version that was published. + const pinned = [ + { type: 'skill', id: 'zeta', versionId: 'zeta-v1' }, + { type: 'skill', id: 'mid', versionId: 'mid-v3' }, + ]; + await expect(refsService.refsForDraft(agent, {})).resolves.toEqual(pinned); const [[, saveCtx]] = agentRepository.saveDraftFenced.mock.calls; - const [[written, refsCtx]] = agentRepository.updateDraftSchema.mock.calls; + const [[written, version, refs, refsCtx]] = refsService.restoreDraftRefs.mock.calls; expect(refsCtx).toBe(saveCtx); - expect(storedSkillRefs(written)).toEqual(skillRefs); + expect(written).toBe(agent); + expect(version).toBe(activeVersion); + expect(refs).toEqual(skillRefs); }); it('shows the skill refs of a version in its document', async () => { diff --git a/packages/cli/src/modules/agents/__tests__/agent-runnable-state.service.test.ts b/packages/cli/src/modules/agents/__tests__/agent-runnable-state.service.test.ts new file mode 100644 index 00000000000..c0fc0408fb3 --- /dev/null +++ b/packages/cli/src/modules/agents/__tests__/agent-runnable-state.service.test.ts @@ -0,0 +1,41 @@ +import type { User } from '@n8n/db'; +import { mock } from 'vitest-mock-extended'; + +import type { CredentialsService } from '@/credentials/credentials.service'; + +import type { AgentPublishService } from '../agent-publish.service'; +import { AgentRunnableStateService } from '../agent-runnable-state.service'; +import type { AgentSkillRefsService } from '../agent-skill-refs.service'; +import type { AgentValidationService } from '../agent-validation.service'; +import type { Agent } from '../entities/agent.entity'; + +const pinId = '0b2c6f1e-7d3a-4c1b-9f2e-5a6b7c8d9e0f'; + +describe('AgentRunnableStateService', () => { + it('returns the pinned skills that have a newer version', async () => { + const skillRefs = mock(); + const draft = { + skillRefs: [{ type: 'skill' as const, id: 'pinned_older', versionId: pinId }], + skills: { pinned_older: { name: 'Skill', description: 'A skill', instructions: 'Old.' } }, + }; + skillRefs.readDraft.mockResolvedValue(draft); + skillRefs.findOutdatedSkillIds.mockResolvedValue(['pinned_older']); + const publishService = mock(); + publishService.hasPublishHistory.mockResolvedValue(false); + const service = new AgentRunnableStateService( + mock(), + mock(), + publishService, + skillRefs, + ); + const agent = { id: 'agent-1', schema: null, integrations: [] } as unknown as Agent; + + const result = await service.addRunnableState(agent, 'project-1', mock(), { + status: 'valid', + issues: [], + }); + + expect(skillRefs.findOutdatedSkillIds).toHaveBeenCalledWith(draft.skillRefs, draft.skills, {}); + expect(result.outdatedSkillIds).toEqual(['pinned_older']); + }); +}); diff --git a/packages/cli/src/modules/agents/__tests__/agent-runtime-cache.service.test.ts b/packages/cli/src/modules/agents/__tests__/agent-runtime-cache.service.test.ts index 7644d6ca21d..3c723087991 100644 --- a/packages/cli/src/modules/agents/__tests__/agent-runtime-cache.service.test.ts +++ b/packages/cli/src/modules/agents/__tests__/agent-runtime-cache.service.test.ts @@ -68,7 +68,7 @@ function makeService({ reconstructionService, credentialsService, sandboxRuntimeService, - createAgentSkillRefsService(agentRepository), + createAgentSkillRefsService(), ); return { service, agentRepository, publisher, reconstructionService }; @@ -592,7 +592,6 @@ describe('AgentRuntimeCacheService', () => { skills: [], }, tools: { tool: { name: 'Tool' } }, - skills: { skill: { name: 'Skill' } }, publishedById: 'publisher-1', }; const runtime = makeRuntime(); @@ -614,9 +613,9 @@ describe('AgentRuntimeCacheService', () => { agent: expect.objectContaining({ schema: activeVersion.schema, tools: activeVersion.tools, - skills: activeVersion.skills, }), skillRefs: activeVersion.schema.skills, + skills: {}, }, expect.anything(), 'production', @@ -644,7 +643,6 @@ describe('AgentRuntimeCacheService', () => { instructions: 'Published instructions', }, tools: {}, - skills: {}, } as Agent['activeVersion'], }); agentRepository.findByIdAndProjectId.mockResolvedValue(agent); diff --git a/packages/cli/src/modules/agents/__tests__/agent-runtime-reconstruction-integration-tools.test.ts b/packages/cli/src/modules/agents/__tests__/agent-runtime-reconstruction-integration-tools.test.ts index 3013d1447d8..3b32b5e9248 100644 --- a/packages/cli/src/modules/agents/__tests__/agent-runtime-reconstruction-integration-tools.test.ts +++ b/packages/cli/src/modules/agents/__tests__/agent-runtime-reconstruction-integration-tools.test.ts @@ -59,7 +59,6 @@ import { AgentRuntimeReconstructionService } from '../agent-runtime-reconstructi import type { AgentSandboxRuntimeService } from '../agent-sandbox-runtime.service'; import { AgentSaveCompletionService } from '../agent-save-completion.service'; import { AgentDefinitionService } from '../agent-definition.service'; -import { AgentSkillsService } from '../agent-skills.service'; import type { AgentUpdateBroadcaster } from '../agent-update-broadcaster'; import type { AgentTaskService } from '../agent-task.service'; @@ -152,6 +151,7 @@ function makeRuntimeReconstructionService( mock(), mock(), mock(), + mock(), ); } @@ -210,7 +210,6 @@ describe('AgentRuntimeReconstructionService integration tools', () => { let globalConfig: Mocked; let telemetry: Mocked; let runtimeCacheService: AgentRuntimeCacheService; - let agentSkillsService: AgentSkillsService; let agentConfigService: AgentConfigService; let agentCustomToolsService: AgentCustomToolsService; let agentExecutionOrchestratorService: AgentExecutionOrchestratorService; @@ -252,7 +251,7 @@ describe('AgentRuntimeReconstructionService integration tools', () => { isEnabled: () => false, }); - const skillRefs = createAgentSkillRefsService(agentRepository); + const skillRefs = createAgentSkillRefsService(); runtimeCacheService = new AgentRuntimeCacheService( logger, agentRepository, @@ -280,18 +279,10 @@ describe('AgentRuntimeReconstructionService integration tools', () => { transactionRunner, skillRefs, ); - agentSkillsService = new AgentSkillsService( - logger, - agentRepository, - saveCompletion, - skillRefs, - transactionRunner, - ); agentConfigService = new AgentConfigService( logger, agentRepository, agentTaskRepository, - agentSkillsService, new AgentConfigPreparationService( credentialsService, mock(), diff --git a/packages/cli/src/modules/agents/__tests__/agent-runtime-reconstruction-subagent-workspace.test.ts b/packages/cli/src/modules/agents/__tests__/agent-runtime-reconstruction-subagent-workspace.test.ts index 709daaf5ac6..78369b51e8d 100644 --- a/packages/cli/src/modules/agents/__tests__/agent-runtime-reconstruction-subagent-workspace.test.ts +++ b/packages/cli/src/modules/agents/__tests__/agent-runtime-reconstruction-subagent-workspace.test.ts @@ -10,6 +10,7 @@ import type { CredentialsFinderService } from '@n8n/backend-services'; import type { EphemeralNodeExecutor } from '@/node-execution'; import type { OauthService } from '@/oauth/oauth.service'; import type { AiService } from '@/services/ai.service'; +import type { CredentialsService } from '@/credentials/credentials.service'; import type { WorkflowFinderService } from '@/workflows/workflow-finder.service'; import type { WorkflowRepository } from '@n8n/db'; @@ -80,6 +81,7 @@ function makeService() { mock(), mock(), mock(), + mock(), ); return { service, workspaceService }; diff --git a/packages/cli/src/modules/agents/__tests__/agent-runtime-reconstruction-tool-filtering.test.ts b/packages/cli/src/modules/agents/__tests__/agent-runtime-reconstruction-tool-filtering.test.ts index ef45e6497e0..76f795f072f 100644 --- a/packages/cli/src/modules/agents/__tests__/agent-runtime-reconstruction-tool-filtering.test.ts +++ b/packages/cli/src/modules/agents/__tests__/agent-runtime-reconstruction-tool-filtering.test.ts @@ -26,6 +26,7 @@ import type { OauthService } from '@/oauth/oauth.service'; import { userHasScopes } from '@/permissions.ee/check-access'; import type { AiService } from '@/services/ai.service'; import { WorkflowRunner } from '@/workflow-runner'; +import type { CredentialsService } from '@/credentials/credentials.service'; import type { WorkflowFinderService } from '@/workflows/workflow-finder.service'; import type { AgentChatAttachmentService } from '../agent-chat-attachment.service'; @@ -130,13 +131,14 @@ function makeAgentEntity(tools: AgentJsonToolConfig[]): AgentRunSource { schema, tools: { custom_tool: { descriptor: { name: 'custom_tool' }, code: '' } }, } as unknown as Agent; - return { agent, skillRefs: undefined }; + return { agent, skillRefs: undefined, skills: {} }; } function makeService(overrides: { credentialsFinderService?: ReturnType>; workflowFinderService?: ReturnType>; workflowRepository?: ReturnType>; + credentialsService?: ReturnType>; }) { const secureRuntime = mock(); secureRuntime.createToolExecutor.mockReturnValue(mock()); @@ -149,6 +151,7 @@ function makeService(overrides: { overrides.credentialsFinderService ?? mock(); const workflowFinderService = overrides.workflowFinderService ?? mock(); const workflowRepository = overrides.workflowRepository ?? mock(); + const credentialsService = overrides.credentialsService ?? mock(); const service = new AgentRuntimeReconstructionService( mock(), @@ -170,6 +173,7 @@ function makeService(overrides: { credentialsFinderService, workflowFinderService, mock(), + credentialsService, ); return { @@ -177,6 +181,7 @@ function makeService(overrides: { credentialsFinderService, workflowFinderService, workflowRepository, + credentialsService, }; } @@ -230,10 +235,10 @@ describe('AgentRuntimeReconstructionService — per-user tool filtering', () => const { service } = makeService({}); const draftRefs: AgentJsonSkillConfig[] = [ { type: 'skill', id: 'zeta' }, - { type: 'skill', id: 'alpha', enabled: false }, + { type: 'skill', id: 'alpha', versionId: '0b2c6f1e-7d3a-4c1b-9f2e-5a6b7c8d9e0f' }, ]; const publishedRefs: AgentJsonSkillConfig[] = [ - { type: 'skill', id: 'mid', enabled: true }, + { type: 'skill', id: 'mid' }, { type: 'skill', id: 'zeta' }, ]; const baseConfig = { @@ -373,6 +378,133 @@ describe('AgentRuntimeReconstructionService — per-user tool filtering', () => expect(toolNamesPassedToBuildFromJson()).toEqual(['Get date']); }); + describe('with personal credentials not supported by agents', () => { + beforeEach(() => { + process.env.N8N_ENV_FEAT_CRED_SHARING = 'true'; + }); + + afterEach(() => { + delete process.env.N8N_ENV_FEAT_CRED_SHARING; + }); + + function makeReadableCredentialFinder() { + const credentialsFinderService = mock(); + credentialsFinderService.findCredentialForUser.mockResolvedValue( + mock({ id: 'cred-1' }), + ); + return credentialsFinderService; + } + + it('drops a node tool whose credential the project list leaves out', async () => { + vi.mocked(userHasScopes).mockResolvedValue(true); + const credentialsService = mock(); + credentialsService.getCredentialsAUserCanUseInAWorkflow.mockResolvedValue([]); + const { service } = makeService({ + credentialsFinderService: makeReadableCredentialFinder(), + credentialsService, + }); + const entity = makeAgentEntity([nodeToolWithCredential, nodeToolWithoutCredential]); + + const result = await service.reconstructFromAgentEntity( + entity, + mock(), + 'production', + undefined, + testUser, + ); + + expect(credentialsService.getCredentialsAUserCanUseInAWorkflow).toHaveBeenCalledWith( + testUser, + { projectId, excludePersonalRoute: true }, + ); + expect(toolNamesPassedToBuildFromJson()).toEqual(['Get date']); + expect(result.userToolAccessSnapshot?.credentialIds).toEqual([]); + }); + + it('keeps a node tool whose credential is in the project list', async () => { + vi.mocked(userHasScopes).mockResolvedValue(true); + const credentialsService = mock(); + credentialsService.getCredentialsAUserCanUseInAWorkflow.mockResolvedValue([ + { id: 'cred-1' }, + ] as never); + const { service } = makeService({ + credentialsFinderService: makeReadableCredentialFinder(), + credentialsService, + }); + const entity = makeAgentEntity([nodeToolWithCredential, nodeToolWithoutCredential]); + + await service.reconstructFromAgentEntity( + entity, + mock(), + 'production', + undefined, + testUser, + ); + + expect(toolNamesPassedToBuildFromJson()).toEqual(['Send Slack message', 'Get date']); + }); + + it('refuses a cached runtime whose credential the project list now leaves out', async () => { + vi.mocked(userHasScopes).mockResolvedValue(true); + const credentialsService = mock(); + credentialsService.getCredentialsAUserCanUseInAWorkflow.mockResolvedValue([]); + const { service } = makeService({ + credentialsFinderService: makeReadableCredentialFinder(), + credentialsService, + }); + + await expect( + service.userStillHasToolAccess( + { credentialIds: ['cred-1'], workflowIds: [] }, + projectId, + testUser, + ), + ).resolves.toBe(false); + }); + + it('accepts a cached runtime whose credential is in the project list', async () => { + vi.mocked(userHasScopes).mockResolvedValue(true); + const credentialsService = mock(); + credentialsService.getCredentialsAUserCanUseInAWorkflow.mockResolvedValue([ + { id: 'cred-1' }, + ] as never); + const { service } = makeService({ + credentialsFinderService: makeReadableCredentialFinder(), + credentialsService, + }); + + await expect( + service.userStillHasToolAccess( + { credentialIds: ['cred-1'], workflowIds: [] }, + projectId, + testUser, + ), + ).resolves.toBe(true); + }); + }); + + it('does not ask for the project credential list when the flag is off', async () => { + vi.mocked(userHasScopes).mockResolvedValue(true); + const credentialsFinderService = mock(); + credentialsFinderService.findCredentialForUser.mockResolvedValue( + mock({ id: 'cred-1' }), + ); + const credentialsService = mock(); + const { service } = makeService({ credentialsFinderService, credentialsService }); + const entity = makeAgentEntity([nodeToolWithCredential]); + + await service.reconstructFromAgentEntity( + entity, + mock(), + 'production', + undefined, + testUser, + ); + + expect(credentialsService.getCredentialsAUserCanUseInAWorkflow).not.toHaveBeenCalled(); + expect(toolNamesPassedToBuildFromJson()).toEqual(['Send Slack message']); + }); + it('skips disabled tools before looking up user access', async () => { vi.mocked(userHasScopes).mockResolvedValue(true); const { service, credentialsFinderService, workflowFinderService, workflowRepository } = diff --git a/packages/cli/src/modules/agents/__tests__/agent-skill-refs.service.test.ts b/packages/cli/src/modules/agents/__tests__/agent-skill-refs.service.test.ts index 1615ec21b19..9b613b5e6e0 100644 --- a/packages/cli/src/modules/agents/__tests__/agent-skill-refs.service.test.ts +++ b/packages/cli/src/modules/agents/__tests__/agent-skill-refs.service.test.ts @@ -1,106 +1,658 @@ -import type { AgentJsonSkillConfig } from '@n8n/api-types'; -import type { OperationContext } from '@n8n/db'; +/* eslint-disable @typescript-eslint/unbound-method -- mock-based tests reference unbound methods */ +import type { AgentJsonSkillConfig, StoredAgentConfig } from '@n8n/api-types'; +import type { OperationContext, User } from '@n8n/db'; +import type { Mocked } from 'vitest'; import { mock } from 'vitest-mock-extended'; +import { userHasScopes } from '@/permissions.ee/check-access'; + import { AgentSkillRefsService } from '../agent-skill-refs.service'; import type { AgentHistory } from '../entities/agent-history.entity'; import type { Agent } from '../entities/agent.entity'; -import { toAgentDocument } from '../json-config/agent-document'; import type { AgentRepository } from '../repositories/agent.repository'; -import { storedAgentConfig } from './test-utils/stored-agent-config'; +import type { SkillFile } from '../entities/skill-file.entity'; +import type { SkillVersion } from '../entities/skill-version.entity'; +import type { Skill } from '../entities/skill.entity'; +import type { ResolvedSkillRow, SkillRepository } from '../repositories/skill.repository'; +import type { SkillService } from '../skills/skill.service'; +import type { SkillsHubRollout } from '../skills/skills-hub-rollout'; -const refs: AgentJsonSkillConfig[] = [ - { type: 'skill', id: 'zeta' }, - { type: 'skill', id: 'alpha', enabled: false }, - { type: 'skill', id: 'mid', enabled: true }, -]; +vi.mock('@/permissions.ee/check-access', () => ({ userHasScopes: vi.fn() })); +const ctx: OperationContext = {}; +const pinId = '0b2c6f1e-7d3a-4c1b-9f2e-5a6b7c8d9e0f'; const baseConfig = { name: 'Agent', model: 'anthropic/claude-sonnet-4-5', instructions: 'Help.' }; +const agent = { id: 'agent-1', projectId: 'project-1', schema: baseConfig } as unknown as Agent; -function makeAgent(schema: Agent['schema']): Agent { - return { id: 'agent-1', schema, updatedAt: new Date('2026-01-01T00:00:00.000Z') } as Agent; +function row(skillId: string, versionId: string, name: string): ResolvedSkillRow { + return { + skill: mock({ id: skillId, agentId: null }), + version: mock({ + id: versionId, + skillId, + name, + description: `${name} description`, + instructions: `${name} instructions`, + }), + files: [] as SkillFile[], + }; } describe('AgentSkillRefsService', () => { - let agentRepository: ReturnType>; + let skillRepository: Mocked; + let skillService: Mocked; + let agentRepository: Mocked; + let rollout: { isEnabled: boolean }; let service: AgentSkillRefsService; - const ctx: OperationContext = {}; beforeEach(() => { + // The module mock outlives each test, so clear the calls of earlier ones. + vi.mocked(userHasScopes).mockClear(); + skillRepository = mock(); + skillService = mock(); agentRepository = mock(); - service = new AgentSkillRefsService(agentRepository); + rollout = { isEnabled: true }; + service = new AgentSkillRefsService( + skillRepository, + skillService, + agentRepository, + rollout as SkillsHubRollout, + ); + skillRepository.findDependencies.mockResolvedValue(new Map()); + skillRepository.findPinned.mockResolvedValue(new Map()); }); describe('refsForDraft', () => { - it('returns the refs of the draft in stored order, with the enabled flags', async () => { - const agent = makeAgent(storedAgentConfig({ ...baseConfig, skills: refs })); + it('returns the dependency rows in attach order, with the pins', async () => { + skillRepository.findDependencies.mockResolvedValue( + new Map([ + [ + 'agent-1', + [ + { skillId: 'zeta', versionId: null }, + { skillId: 'alpha', versionId: pinId }, + ], + ], + ]), + ); - await expect(service.refsForDraft(agent, ctx)).resolves.toEqual(refs); + await expect(service.refsForDraft(agent, ctx)).resolves.toEqual([ + { type: 'skill', id: 'zeta' }, + { type: 'skill', id: 'alpha', versionId: pinId }, + ]); + expect(skillRepository.findDependencies).toHaveBeenCalledWith(['agent-1'], ctx); }); - it('returns undefined when the draft has no skill list', async () => { - await expect( - service.refsForDraft(makeAgent(storedAgentConfig(baseConfig)), ctx), - ).resolves.toBeUndefined(); - await expect(service.refsForDraft(makeAgent(null), ctx)).resolves.toBeUndefined(); - }); - - it('returns an empty list when the draft has an empty skill list', async () => { - const agent = makeAgent(storedAgentConfig({ ...baseConfig, skills: [] })); - + it('returns an empty list when the draft has no skills', async () => { await expect(service.refsForDraft(agent, ctx)).resolves.toEqual([]); }); }); describe('refsForVersion', () => { - it('returns the refs of the published version', async () => { - const version = { - versionId: 'version-1', - schema: storedAgentConfig({ ...baseConfig, skills: refs }), - } as AgentHistory; + it('reads the pinned skill ids in order, without the skill bodies', async () => { + skillRepository.findPinnedSkillIds.mockResolvedValue(['zeta', 'alpha']); - await expect(service.refsForVersion(version, ctx)).resolves.toEqual(refs); + const refs = await service.refsForVersion( + { versionId: 'version-1', schema: null, skills: null }, + ctx, + ); + + expect(refs).toEqual([ + { type: 'skill', id: 'zeta' }, + { type: 'skill', id: 'alpha' }, + ]); + expect(skillRepository.findPinned).not.toHaveBeenCalled(); + }); + }); + + describe('readVersion', () => { + it('returns the pins of the version in order and the pinned bodies', async () => { + skillRepository.findPinned.mockResolvedValue( + new Map([ + ['zeta', row('zeta', 'zeta-v1', 'Zeta')], + ['alpha', row('alpha', 'alpha-v3', 'Alpha')], + ]), + ); + + const result = await service.readVersion( + { versionId: 'version-1', schema: null, skills: null }, + ctx, + ); + + expect(result.skillRefs).toEqual([ + { type: 'skill', id: 'zeta' }, + { type: 'skill', id: 'alpha' }, + ]); + expect(Object.keys(result.skills)).toEqual(['zeta', 'alpha']); + expect(result.skills.alpha).toEqual({ + name: 'Alpha', + description: 'Alpha description', + instructions: 'Alpha instructions', + }); + expect(skillRepository.findPinned).toHaveBeenCalledWith('version-1', ctx); + }); + }); + + describe('skillsForRefs', () => { + it('resolves the latest or the pinned version of each ref', async () => { + const refs: AgentJsonSkillConfig[] = [ + { type: 'skill', id: 'zeta' }, + { type: 'skill', id: 'alpha', versionId: pinId }, + ]; + skillService.resolveForAgentDraft.mockResolvedValue({}); + + await service.skillsForRefs(agent, refs, ctx); + + expect(skillService.resolveForAgentDraft).toHaveBeenCalledWith( + [{ id: 'zeta' }, { id: 'alpha', versionId: pinId }], + ctx, + ); + }); + + it('reads nothing for a draft without skills', async () => { + await expect(service.skillsForRefs(agent, undefined, ctx)).resolves.toEqual({}); + expect(skillService.resolveForAgentDraft).not.toHaveBeenCalled(); + }); + }); + + describe('effectiveDraftRefs', () => { + it('returns the refs the attach check keeps and writes nothing', async () => { + skillService.checkRefs.mockResolvedValue([{ id: 'zeta' }]); + + const refs = await service.effectiveDraftRefs( + agent, + [ + { type: 'skill', id: 'zeta' }, + { type: 'skill', id: 'stale' }, + ], + ctx, + ); + + expect(refs).toEqual([{ type: 'skill', id: 'zeta' }]); + expect(skillRepository.replaceDependencies).not.toHaveBeenCalled(); }); }); describe('replaceDraftRefs', () => { - it('writes the refs and keeps the rest of the config', async () => { - const agent = makeAgent(storedAgentConfig({ ...baseConfig, tasks: [] })); - const next: AgentJsonSkillConfig[] = [{ type: 'skill', id: 'new' }]; + it('checks the refs and writes the dependency rows', async () => { + skillService.checkRefs.mockResolvedValue([{ id: 'zeta' }, { id: 'alpha', versionId: pinId }]); - await service.replaceDraftRefs(agent, next, ctx); + await service.replaceDraftRefs( + agent, + [ + { type: 'skill', id: 'zeta' }, + { type: 'skill', id: 'alpha', versionId: pinId }, + ], + ctx, + ); - expect(agentRepository.updateDraftSchema).toHaveBeenCalledWith(agent, ctx); - await expect(service.refsForDraft(agent, ctx)).resolves.toEqual(next); - expect(agent.schema && toAgentDocument(agent.schema, next)).toEqual({ - ...baseConfig, - tasks: [], - skills: next, - }); + expect(skillService.checkRefs).toHaveBeenCalledWith( + { id: 'agent-1', projectId: 'project-1' }, + [{ id: 'zeta' }, { id: 'alpha', versionId: pinId }], + ctx, + ); + expect(skillRepository.replaceDependencies).toHaveBeenCalledWith( + 'agent-1', + [ + { skillId: 'zeta', versionId: null }, + { skillId: 'alpha', versionId: pinId }, + ], + ctx, + ); }); - it('removes the skill list when the refs are undefined', async () => { - const agent = makeAgent(storedAgentConfig({ ...baseConfig, skills: refs })); + it('removes every row when the refs are undefined', async () => { + skillService.checkRefs.mockResolvedValue([]); await service.replaceDraftRefs(agent, undefined, ctx); - expect(agent.schema).not.toHaveProperty('skills'); - expect(agentRepository.updateDraftSchema).toHaveBeenCalledWith(agent, ctx); - }); - - it('does nothing for an agent without a config and without refs', async () => { - const agent = makeAgent(null); - - await service.replaceDraftRefs(agent, undefined, ctx); - - expect(agentRepository.updateDraftSchema).not.toHaveBeenCalled(); + expect(skillRepository.replaceDependencies).toHaveBeenCalledWith('agent-1', [], ctx); }); it('rejects refs for an agent without a config', async () => { - await expect(service.replaceDraftRefs(makeAgent(null), refs, ctx)).rejects.toThrow( - 'Cannot set skill refs on an agent without a config', + await expect( + service.replaceDraftRefs( + { ...agent, schema: null } as Agent, + [{ type: 'skill', id: 'zeta' }], + ctx, + ), + ).rejects.toThrow('Cannot set skill refs on an agent without a config'); + expect(skillRepository.replaceDependencies).not.toHaveBeenCalled(); + }); + }); + + it('restores the pins of a published version without the attach check', async () => { + skillService.restoreFromVersion.mockResolvedValue([{ id: 'zeta', versionId: pinId }]); + + await service.restoreDraftRefs( + agent, + { versionId: 'version-1', skills: null }, + [{ type: 'skill', id: 'zeta' }], + ctx, + ); + + expect(skillService.restoreFromVersion).toHaveBeenCalledWith( + 'version-1', + [{ id: 'zeta' }], + ctx, + ); + expect(skillService.checkRefs).not.toHaveBeenCalled(); + expect(skillRepository.replaceDependencies).toHaveBeenCalledWith( + 'agent-1', + [{ skillId: 'zeta', versionId: pinId }], + ctx, + ); + }); + + it('removes the pin of one ref and keeps the others', async () => { + skillRepository.findDependencies.mockResolvedValue( + new Map([ + [ + 'agent-1', + [ + { skillId: 'zeta', versionId: pinId }, + { skillId: 'alpha', versionId: 'alpha-pin' }, + ], + ], + ]), + ); + + await service.unpinDraftRef(agent, 'zeta', ctx); + + expect(skillRepository.replaceDependencies).toHaveBeenCalledWith( + 'agent-1', + [ + { skillId: 'zeta', versionId: null }, + { skillId: 'alpha', versionId: 'alpha-pin' }, + ], + ctx, + ); + }); + + describe('findOutdatedSkillIds', () => { + const body = (instructions: string) => ({ + name: 'Skill', + description: 'A skill', + instructions, + }); + + it('lists the pinned skills whose latest text differs from the pinned text', async () => { + skillService.resolveForAgentDraft.mockResolvedValue({ + pinned_older: body('New text.'), + pinned_latest: body('Latest text.'), + }); + + const outdated = await service.findOutdatedSkillIds( + [ + { type: 'skill', id: 'pinned_older', versionId: pinId }, + { type: 'skill', id: 'pinned_latest', versionId: pinId }, + { type: 'skill', id: 'unpinned' }, + ], + { + pinned_older: body('Old text.'), + pinned_latest: body('Latest text.'), + unpinned: body('Latest text.'), + }, + ctx, ); - expect(agentRepository.updateDraftSchema).not.toHaveBeenCalled(); + + expect(outdated).toEqual(['pinned_older']); + expect(skillService.resolveForAgentDraft).toHaveBeenCalledWith( + [{ id: 'pinned_older' }, { id: 'pinned_latest' }], + ctx, + ); + }); + + it('reads nothing when no ref is pinned', async () => { + await expect( + service.findOutdatedSkillIds([{ type: 'skill', id: 'unpinned' }], {}, ctx), + ).resolves.toEqual([]); + expect(skillService.resolveForAgentDraft).not.toHaveBeenCalled(); + }); + }); + + describe('createDraftRefs', () => { + const body = { name: 'New', description: 'New description', instructions: 'Do it.' }; + const user = mock({ id: 'user-1' }); + + beforeEach(() => { + skillService.checkRefs.mockImplementation(async (_agent, refs) => refs); + skillService.create.mockResolvedValue('skill_created'); + vi.mocked(userHasScopes).mockResolvedValue(true); + }); + + it('keeps refs to hub skills and creates agent skills for refs with only a body', async () => { + skillRepository.findByIds.mockResolvedValue([mock({ id: 'shared', agentId: null })]); + + const refs = await service.createDraftRefs( + agent, + [ + { type: 'skill', id: 'shared', versionId: pinId }, + { type: 'skill', id: 'seed_skill' }, + { type: 'skill', id: 'unknown' }, + ], + { shared: body, seed_skill: body }, + user, + ctx, + ); + + expect(skillService.create).toHaveBeenCalledTimes(1); + expect(skillService.create).toHaveBeenCalledWith( + { + target: { projectId: null, agentId: 'agent-1' }, + skill: body, + source: 'agent', + createdById: 'user-1', + }, + ctx, + ); + expect(refs).toEqual([ + { type: 'skill', id: 'shared' }, + { type: 'skill', id: 'skill_created' }, + ]); + // The attach check runs on every ref, so a ref to a skill of another project fails. + expect(skillService.checkRefs).toHaveBeenCalledWith( + { id: 'agent-1', projectId: 'project-1' }, + [{ id: 'shared' }, { id: 'skill_created' }], + ctx, + ); + }); + + it('creates an agent skill without a project skill scope', async () => { + skillRepository.findByIds.mockResolvedValue([]); + vi.mocked(userHasScopes).mockResolvedValue(false); + + await expect( + service.createDraftRefs( + agent, + [{ type: 'skill', id: 'seed_skill' }], + { seed_skill: body }, + user, + ctx, + ), + ).resolves.toEqual([{ type: 'skill', id: 'skill_created' }]); + // The skill is part of the agent, so the agent permission of the caller is enough. + expect(userHasScopes).not.toHaveBeenCalled(); + }); + + it('needs no skill permission for refs to hub skills', async () => { + skillRepository.findByIds.mockResolvedValue([mock({ id: 'shared', agentId: null })]); + vi.mocked(userHasScopes).mockResolvedValue(false); + + await expect( + service.createDraftRefs(agent, [{ type: 'skill', id: 'shared' }], {}, user, ctx), + ).resolves.toEqual([{ type: 'skill', id: 'shared' }]); + expect(userHasScopes).not.toHaveBeenCalled(); + }); + + it('copies a skill of another agent only for the new agent', async () => { + skillRepository.findByIds.mockResolvedValue([ + mock({ id: 'private', agentId: 'agent-source' }), + ]); + skillRepository.findAgents.mockResolvedValue( + new Map([['agent-source', { name: 'Source', projectId: 'project-1' }]]), + ); + skillService.resolveForAgentDraft.mockResolvedValue({ private: body }); + + const refs = await service.createDraftRefs( + agent, + [{ type: 'skill', id: 'private' }], + {}, + user, + ctx, + ); + + expect(skillService.create).toHaveBeenCalledWith( + { + target: { projectId: null, agentId: 'agent-1' }, + skill: body, + source: 'agent', + createdById: 'user-1', + }, + ctx, + ); + expect(refs).toEqual([{ type: 'skill', id: 'skill_created' }]); + }); + + it('does not read or copy an agent skill of another project', async () => { + skillRepository.findByIds.mockResolvedValue([ + mock({ id: 'private', agentId: 'agent-elsewhere' }), + ]); + skillRepository.findAgents.mockResolvedValue( + new Map([['agent-elsewhere', { name: 'Elsewhere', projectId: 'project-2' }]]), + ); + + await service.createDraftRefs(agent, [{ type: 'skill', id: 'private' }], {}, user, ctx); + + expect(skillService.resolveForAgentDraft).not.toHaveBeenCalled(); + expect(skillService.create).not.toHaveBeenCalled(); + // The ref stays a plain ref, so the attach check refuses it. + expect(skillService.checkRefs).toHaveBeenCalledWith( + { id: 'agent-1', projectId: 'project-1' }, + [{ id: 'private' }], + ctx, + ); + }); + + it('creates no skill without a user', async () => { + skillRepository.findByIds.mockResolvedValue([]); + + await expect( + service.createDraftRefs( + agent, + [{ type: 'skill', id: 'seed_skill' }], + { seed_skill: body }, + null, + ctx, + ), + ).resolves.toEqual([]); + expect(skillService.create).not.toHaveBeenCalled(); + }); + }); + + describe('createSkills', () => { + it.each([ + ['project', { projectId: 'project-1', agentId: null }], + ['agent', { projectId: null, agentId: 'agent-1' }], + ['instance', { projectId: null, agentId: null }], + ] as const)('creates a hub skill available to %s', async (availableTo, target) => { + const body = { name: 'New', description: 'New description', instructions: 'Do it.' }; + skillService.create.mockResolvedValue('skill_created'); + + await expect( + service.createSkills(agent, [body], 'user-1', availableTo, ctx), + ).resolves.toEqual(['skill_created']); + expect(skillService.create).toHaveBeenCalledWith( + { target, skill: body, source: 'agent', createdById: 'user-1' }, + ctx, + ); + }); + }); + + describe('setAvailability', () => { + it('moves the skill to the target of the choice, keeping this agent', async () => { + await service.setAvailability(agent, 'skill_a', 'agent', ctx); + + expect(skillService.changeTarget).toHaveBeenCalledWith( + 'skill_a', + { projectId: null, agentId: 'agent-1' }, + 'agent-1', + ctx, + ); + }); + }); + + describe('versionSnapshot and pinVersion', () => { + const notes = { name: 'Notes', description: 'Take notes', instructions: 'Write it down.' }; + + it('writes the refs and the bodies the draft runs to the legacy columns, and pins them', async () => { + skillRepository.findDependencies.mockResolvedValue( + new Map([ + [ + 'agent-1', + [ + { skillId: 'zeta', versionId: null }, + { skillId: 'alpha', versionId: pinId }, + ], + ], + ]), + ); + const versionByRef = new Map([ + ['zeta', 'zeta-v2'], + ['alpha', pinId], + ]); + skillService.snapshotForPublish.mockResolvedValue({ + skills: { zeta: notes, alpha: notes }, + versionByRef, + }); + + const snapshot = await service.versionSnapshot(agent, ctx); + await service.pinVersion('version-1', snapshot, ctx); + + expect(skillService.snapshotForPublish).toHaveBeenCalledWith( + [{ id: 'zeta' }, { id: 'alpha', versionId: pinId }], + ctx, + ); + // A rollback reads these columns, so a published agent keeps its skills. + expect(snapshot.schema?.skills).toEqual([ + { type: 'skill', id: 'zeta' }, + { type: 'skill', id: 'alpha' }, + ]); + expect(snapshot.skills).toEqual({ zeta: notes, alpha: notes }); + expect(skillService.pinForPublish).toHaveBeenCalledWith('version-1', versionByRef, ctx); + }); + + it('rejects a ref that resolves to no version', async () => { + skillRepository.findDependencies.mockResolvedValue( + new Map([['agent-1', [{ skillId: 'zeta', versionId: null }]]]), + ); + skillService.snapshotForPublish.mockResolvedValue({ skills: {}, versionByRef: new Map() }); + + await expect(service.versionSnapshot(agent, ctx)).rejects.toThrow( + 'Cannot publish agent with missing skills: zeta', + ); + }); + + it('writes an empty skill list and pins nothing for a draft without skills', async () => { + const snapshot = await service.versionSnapshot(agent, ctx); + await service.pinVersion('version-1', snapshot, ctx); + + expect(snapshot.schema?.skills).toEqual([]); + expect(snapshot.skills).toEqual({}); + expect(skillService.snapshotForPublish).not.toHaveBeenCalled(); + expect(skillService.pinForPublish).not.toHaveBeenCalled(); + }); + }); + + describe('with the skills hub off', () => { + const notes = { name: 'Notes', description: 'Take notes', instructions: 'Write.' }; + const billing = { name: 'Billing', description: 'Bills', instructions: 'Bill.' }; + const legacyAgent = (skills: unknown[], bodies = { notes, billing }) => + ({ + id: 'agent-1', + projectId: 'project-1', + schema: { ...baseConfig, skills } as unknown as StoredAgentConfig, + skills: { ...bodies }, + }) as unknown as Agent; + + beforeEach(() => { + rollout.isEnabled = false; + }); + + it('reads the refs and bodies from the agent row and hides disabled refs', async () => { + const draft = legacyAgent([ + { type: 'skill', id: 'notes' }, + { type: 'skill', id: 'billing', enabled: false }, + ]); + + await expect(service.readDraft(draft, ctx)).resolves.toEqual({ + skillRefs: [{ type: 'skill', id: 'notes' }], + skills: { notes }, + }); + expect(skillRepository.findDependencies).not.toHaveBeenCalled(); + }); + + it('reads a published version from the agent_history row', async () => { + const version = { + versionId: 'version-1', + schema: { ...baseConfig, skills: [{ type: 'skill', id: 'notes' }] }, + skills: { notes }, + } as unknown as AgentHistory; + + await expect(service.readVersion(version, ctx)).resolves.toEqual({ + skillRefs: [{ type: 'skill', id: 'notes' }], + skills: { notes }, + }); + expect(skillRepository.findPinned).not.toHaveBeenCalled(); + }); + + it('writes the refs to the stored config and drops refs without a body', async () => { + const draft = legacyAgent([{ type: 'skill', id: 'notes' }]); + + await service.replaceDraftRefs( + draft, + [ + { type: 'skill', id: 'billing', versionId: pinId }, + { type: 'skill', id: 'unknown' }, + ], + ctx, + ); + + expect(draft.schema?.skills).toEqual([{ type: 'skill', id: 'billing' }]); + expect(agentRepository.updateDraftSkills).toHaveBeenCalledWith(draft, ctx); + expect(skillService.checkRefs).not.toHaveBeenCalled(); + }); + + it('creates skills as bodies on the agent row', async () => { + const draft = legacyAgent([], {} as never); + + const ids = await service.createSkills(draft, [notes], 'user-1', 'agent', ctx); + + expect(draft.skills).toEqual({ [ids[0]]: notes }); + expect(agentRepository.updateDraftSkills).toHaveBeenCalledWith(draft, ctx); + expect(skillService.create).not.toHaveBeenCalled(); + }); + + it('restores the refs and bodies of a published version', async () => { + const draft = legacyAgent([{ type: 'skill', id: 'billing' }]); + + await service.restoreDraftRefs( + draft, + { versionId: 'version-1', skills: { notes } }, + [{ type: 'skill', id: 'notes' }], + ctx, + ); + + expect(draft.schema?.skills).toEqual([{ type: 'skill', id: 'notes' }]); + expect(draft.skills).toEqual({ notes }); + expect(skillService.restoreFromVersion).not.toHaveBeenCalled(); + }); + + it('copies the refs and bodies into a new published version', async () => { + const draft = legacyAgent([ + { type: 'skill', id: 'notes' }, + { type: 'skill', id: 'billing', enabled: false }, + ]); + + await expect(service.versionSnapshot(draft, ctx)).resolves.toEqual({ + schema: draft.schema, + skills: { notes }, + pins: new Map(), + }); + }); + + it('refuses to publish a ref without a body', async () => { + const draft = legacyAgent([{ type: 'skill', id: 'gone' }]); + + await expect(service.versionSnapshot(draft, ctx)).rejects.toThrow( + 'Cannot publish agent with missing skill bodies: gone', + ); + }); + + it('reports no outdated skills', async () => { + await expect( + service.findOutdatedSkillIds([{ type: 'skill', id: 'notes', versionId: pinId }], {}, ctx), + ).resolves.toEqual([]); }); }); }); diff --git a/packages/cli/src/modules/agents/__tests__/agent-skills.service.test.ts b/packages/cli/src/modules/agents/__tests__/agent-skills.service.test.ts index b9524d7aab7..2d8f213fc9f 100644 --- a/packages/cli/src/modules/agents/__tests__/agent-skills.service.test.ts +++ b/packages/cli/src/modules/agents/__tests__/agent-skills.service.test.ts @@ -1,70 +1,107 @@ /* eslint-disable @typescript-eslint/require-await, @typescript-eslint/unbound-method -- async mock stubs and unbound-method references are acceptable test idioms */ -import type { Mocked } from 'vitest'; +import type { AgentJsonSkillConfig, AgentSkill } from '@n8n/api-types'; import type { EventService } from '@n8n/backend-services'; import { mockLogger } from '@n8n/backend-test-utils'; -import type { TransactionRunner } from '@n8n/db'; +import { GLOBAL_MEMBER_ROLE, type TransactionRunner, type User } from '@n8n/db'; import { Container } from '@n8n/di'; +import { ConflictError, ForbiddenError, NotFoundError } from '@n8n/errors'; +import type { Mocked } from 'vitest'; import { mock } from 'vitest-mock-extended'; -import type { Agent } from '../entities/agent.entity'; -import { AgentRuntimeCacheService } from '../agent-runtime-cache.service'; +import { userHasScopes } from '@/permissions.ee/check-access'; + import type { AgentModificationTelemetryService } from '../agent-modification-telemetry.service'; +import { AgentRuntimeCacheService } from '../agent-runtime-cache.service'; import { AgentSaveCompletionService } from '../agent-save-completion.service'; import { AgentSkillsService } from '../agent-skills.service'; import type { AgentUpdateBroadcaster } from '../agent-update-broadcaster'; +import type { Agent } from '../entities/agent.entity'; +import { composeJsonConfig } from '../json-config/agent-config-composition'; import type { AgentRepository } from '../repositories/agent.repository'; +import type { SkillSaveResult, SkillService } from '../skills/skill.service'; import { getAgentConfigHash, getAgentSkillHash } from '../utils/agent-config-hash'; import { type AgentFixtureOverrides, - composeStoredJsonConfig, + type FakeAgentSkillRefsService, createAgentSkillRefsService, - storedSkillRefs, } from './test-utils/stored-agent-config'; +vi.mock('@/permissions.ee/check-access', () => ({ userHasScopes: vi.fn() })); + const agentId = 'agent-1'; const projectId = 'project-1'; -const telemetryContext = { user: { id: 'user-1' } as never, modifiedBy: 'user' as const }; +const user = { id: 'user-1' } as never; +const context = { user, modifiedBy: 'user' as const, pushRef: 'push-ref-1' }; const versionId = 'v1'; +const pinId = '0b2c6f1e-7d3a-4c1b-9f2e-5a6b7c8d9e0f'; +const baseConfig = { + name: 'Test Agent', + model: 'anthropic/claude-sonnet-4-5', + instructions: 'Be helpful', +}; + +const skill: AgentSkill = { + name: 'Summarize Notes', + description: 'Summarizes a meeting transcript', + instructions: 'Extract decisions and action items.', +}; function makeAgent(overrides: AgentFixtureOverrides = {}): Agent { return { id: agentId, + projectId, versionId, schema: null, activeVersionId: null, activeVersion: null, tools: {}, - skills: {}, updatedAt: new Date(), ...overrides, } as unknown as Agent; } +function saveResult(overrides: Partial = {}): SkillSaveResult { + return { + versionId: 'skill-version-2', + version: 2, + created: true, + skill: { ...skill, instructions: 'New instructions.' }, + followingAgentIds: [], + ...overrides, + }; +} + describe('AgentSkillsService', () => { let service: AgentSkillsService; let agentRepository: Mocked; + let skillService: Mocked; + let skillRefs: FakeAgentSkillRefsService; + let transactionRunner: Mocked; let runtimeCacheService: Mocked; let modificationTelemetry: Mocked; let agentUpdateBroadcaster: Mocked; - const skill = { - name: 'Summarize Notes', - description: 'Summarizes a meeting transcript', - instructions: 'Extract decisions and action items.', - }; + function givenAgent(overrides: AgentFixtureOverrides = {}) { + const agent = makeAgent(overrides); + agentRepository.findByIdAndProjectId.mockResolvedValue(agent); + return agent; + } beforeEach(() => { vi.clearAllMocks(); Container.reset(); agentRepository = mock(); + skillService = mock(); + skillRefs = createAgentSkillRefsService(); runtimeCacheService = mock(); Container.set(AgentRuntimeCacheService, runtimeCacheService); agentRepository.saveDraftFenced.mockResolvedValue(true); modificationTelemetry = mock(); agentUpdateBroadcaster = mock(); - const transactionRunner = mock(); + transactionRunner = mock(); transactionRunner.run.mockImplementation(async (ctx, fn) => await fn(ctx)); + vi.mocked(userHasScopes).mockResolvedValue(true); service = new AgentSkillsService( mockLogger(), agentRepository, @@ -73,579 +110,565 @@ describe('AgentSkillsService', () => { agentUpdateBroadcaster, modificationTelemetry, ), - createAgentSkillRefsService(agentRepository), + skillRefs, + skillService, transactionRunner, ); }); - it('creates a skill without attaching it to the config', async () => { - const agent = makeAgent({ - schema: { - name: 'Test Agent', - model: 'anthropic/claude-sonnet-4-5', - instructions: 'Be helpful', - skills: [], - }, - }); - agentRepository.findByIdAndProjectId.mockResolvedValue(agent); - - const result = await service.createSkill(agentId, projectId, skill, telemetryContext); - - expect(result).toEqual({ - id: expect.stringMatching(/^skill_[A-Za-z0-9]{16}$/), - skill, - skillHash: expect.stringMatching(/^[a-f0-9]{64}$/), - versionId: agent.versionId, - }); - expect(agentRepository.saveDraftFenced.mock.calls[0][0].skills).toEqual({ - [result.id]: skill, - }); - expect(storedSkillRefs(agent)).toEqual([]); - expect(agentRepository.updateDraftSchema).not.toHaveBeenCalled(); - expect(runtimeCacheService.clearRuntimes).toHaveBeenCalledWith(agentId); - }); - - it('stores references without derived metadata when creating a skill', async () => { - const agent = makeAgent({ - schema: { - name: 'Test Agent', - model: 'anthropic/claude-sonnet-4-5', - instructions: 'Be helpful', - }, - }); - agentRepository.findByIdAndProjectId.mockResolvedValue(agent); - - const result = await service.createSkill( - agentId, - projectId, - { - ...skill, - references: [ - { - path: 'references/guide.md', - content: '# Guide', - }, - ], - }, - telemetryContext, - ); - - expect(result.skill.references).toEqual([ - { - path: 'references/guide.md', - content: '# Guide', - }, - ]); - expect(agentRepository.saveDraftFenced).toHaveBeenCalledWith( - expect.objectContaining({ - skills: { - [result.id]: expect.objectContaining({ references: result.skill.references }), - }, - }), - {}, - ); - }); - describe('createAndAttachSkills', () => { - const skillTwo = { - name: 'Draft Follow-up', - description: 'Drafts a follow-up email', - instructions: 'Summarize next steps and send a draft.', - }; + beforeEach(() => { + let next = 0; + skillRefs.createSkills.mockImplementation(async (_agent, skills) => + skills.map(() => `skill_new${++next}`), + ); + }); - const configuredAgent = (overrides: AgentFixtureOverrides = {}) => - makeAgent({ - schema: { - name: 'Test Agent', - model: 'anthropic/claude-sonnet-4-5', - instructions: 'Be helpful', - skills: [], - }, - ...overrides, + it('creates hub skills in the agent project and attaches them in one transaction, in input order', async () => { + skillRefs.bodies.existing = { ...skill, name: 'Existing' }; + const agent = givenAgent({ + schema: { ...baseConfig, skills: [{ type: 'skill', id: 'existing' }] }, }); + const second = { ...skill, name: 'Second Skill' }; - it('creates and attaches multiple skills with one load, save, and cache clear, preserving input order', async () => { - const agent = makeAgent({ - schema: { - name: 'Test Agent', - model: 'anthropic/claude-sonnet-4-5', - instructions: 'Be helpful', - skills: [], - }, - }); - agentRepository.findByIdAndProjectId.mockResolvedValue(agent); - - const { skills: results, configHash } = await service.createAndAttachSkills( + const result = await service.createAndAttachSkills( agentId, projectId, - [skill, skillTwo], - telemetryContext, + [skill, second], + context, ); - expect(results).toHaveLength(2); - expect(results[0].skill).toEqual(skill); - expect(results[1].skill).toEqual(skillTwo); - expect(results[0].id).not.toEqual(results[1].id); - expect(results.map((r) => r.versionId)).toEqual([agent.versionId, agent.versionId]); - - expect(agentRepository.findByIdAndProjectId).toHaveBeenCalledTimes(1); - expect(agentRepository.saveDraftFenced).toHaveBeenCalledTimes(1); - expect(agentRepository.saveDraftFenced.mock.calls[0][0].skills).toEqual({ - [results[0].id]: skill, - [results[1].id]: skillTwo, - }); - expect(storedSkillRefs(agent)).toEqual([ - { type: 'skill', id: results[0].id }, - { type: 'skill', id: results[1].id }, + expect(result.skills.map(({ id, skill: body }) => [id, body.name])).toEqual([ + ['skill_new1', 'Summarize Notes'], + ['skill_new2', 'Second Skill'], ]); - expect(agentRepository.updateDraftSchema).toHaveBeenCalledTimes(1); - expect(agentRepository.updateDraftSchema).toHaveBeenCalledWith(agent, {}); - expect(configHash).toBe(getAgentConfigHash(composeStoredJsonConfig(agent))); + expect(skillRefs.createSkills).toHaveBeenCalledWith( + agent, + [skill, second], + 'user-1', + 'project', + {}, + ); + expect(userHasScopes).toHaveBeenCalledWith(user, ['projectSkill:create'], false, { + projectId, + }); + const refs: AgentJsonSkillConfig[] = [ + { type: 'skill', id: 'existing' }, + { type: 'skill', id: 'skill_new1' }, + { type: 'skill', id: 'skill_new2' }, + ]; + expect(skillRefs.replaceDraftRefs).toHaveBeenCalledWith(agent, refs, {}); + expect(transactionRunner.run).toHaveBeenCalledTimes(1); + expect(agentRepository.saveDraftFenced).toHaveBeenCalledTimes(1); expect(runtimeCacheService.clearRuntimes).toHaveBeenCalledTimes(1); - expect(runtimeCacheService.clearRuntimes).toHaveBeenCalledWith(agentId); + expect(result.configHash).toBe(getAgentConfigHash(composeJsonConfig(agent, refs))); }); - it('rejects the batch without saving when the agent has no config yet', async () => { - agentRepository.findByIdAndProjectId.mockResolvedValue(makeAgent()); + it('keeps allowed tools on the agent row when the skills hub is off', async () => { + Object.assign(skillRefs, { usesSkillsHub: false }); + givenAgent({ schema: baseConfig }); - await expect( - service.createAndAttachSkills(agentId, projectId, [skill], telemetryContext), - ).rejects.toThrow('Agent has no JSON config yet.'); - - expect(agentRepository.saveDraftFenced).not.toHaveBeenCalled(); - }); - - it('rejects an empty batch before loading or writing anything', async () => { - await expect( - service.createAndAttachSkills(agentId, projectId, [], telemetryContext), - ).rejects.toThrow('At least one skill is required.'); - - expect(agentRepository.findByIdAndProjectId).not.toHaveBeenCalled(); - expect(agentRepository.saveDraftFenced).not.toHaveBeenCalled(); - expect(runtimeCacheService.clearRuntimes).not.toHaveBeenCalled(); - }); - - it('rejects the whole batch without saving when a name collides with an existing skill', async () => { - agentRepository.findByIdAndProjectId.mockResolvedValue( - configuredAgent({ skills: { summarize_notes: skill } }), + await service.createAndAttachSkill( + agentId, + projectId, + { ...skill, allowedTools: ['search'] }, + context, ); - await expect( - service.createAndAttachSkills( - agentId, - projectId, - [skillTwo, { ...skill }], - telemetryContext, - ), - ).rejects.toThrow('Agent already has a skill named "Summarize Notes".'); - - expect(agentRepository.saveDraftFenced).not.toHaveBeenCalled(); - expect(runtimeCacheService.clearRuntimes).not.toHaveBeenCalled(); + expect(skillRefs.createSkills).toHaveBeenCalledWith( + expect.anything(), + [{ ...skill, allowedTools: ['search'] }], + 'user-1', + 'project', + {}, + ); }); - it('rejects the whole batch without saving when two items in the batch share a name', async () => { - agentRepository.findByIdAndProjectId.mockResolvedValue(configuredAgent()); + it('drops allowed tools from the stored skill', async () => { + givenAgent({ schema: baseConfig }); - await expect( - service.createAndAttachSkills( - agentId, - projectId, - [skill, { ...skill, name: ' summarize notes ' }], - telemetryContext, - ), - ).rejects.toThrow('Duplicate skill name in batch: "summarize notes".'); + const result = await service.createAndAttachSkill( + agentId, + projectId, + { ...skill, allowedTools: ['search'] }, + context, + ); - expect(agentRepository.saveDraftFenced).not.toHaveBeenCalled(); - expect(runtimeCacheService.clearRuntimes).not.toHaveBeenCalled(); + expect(result.skill).toEqual(skill); + expect(skillRefs.createSkills).toHaveBeenCalledWith( + expect.anything(), + [skill], + 'user-1', + 'project', + {}, + ); }); - it('rejects the whole batch without saving when one item is invalid', async () => { - agentRepository.findByIdAndProjectId.mockResolvedValue(configuredAgent()); + it('refuses an instance skill without the global skill create permission', async () => { + givenAgent({ schema: baseConfig }); + + const member = mock({ id: 'user-1', role: GLOBAL_MEMBER_ROLE }); + + await expect( + service.createAndAttachSkill( + agentId, + projectId, + skill, + { ...context, user: member }, + 'instance', + ), + ).rejects.toThrow('You are not allowed to create skills for the whole instance.'); + expect(skillRefs.createSkills).not.toHaveBeenCalled(); + }); + + it('rejects the batch without writing when the agent has no config yet', async () => { + givenAgent(); + + await expect( + service.createAndAttachSkills(agentId, projectId, [skill], context), + ).rejects.toThrow('Agent has no JSON config yet.'); + expect(skillRefs.createSkills).not.toHaveBeenCalled(); + }); + + it('rejects an empty batch before loading anything', async () => { + await expect(service.createAndAttachSkills(agentId, projectId, [], context)).rejects.toThrow( + 'At least one skill is required.', + ); + expect(agentRepository.findByIdAndProjectId).not.toHaveBeenCalled(); + }); + + it('rejects a user who may not create skills in the project', async () => { + givenAgent({ schema: baseConfig }); + vi.mocked(userHasScopes).mockResolvedValue(false); + + await expect( + service.createAndAttachSkills(agentId, projectId, [skill], context), + ).rejects.toThrow(ForbiddenError); + expect(skillRefs.createSkills).not.toHaveBeenCalled(); + }); + + it('creates a skill for this agent only without a project skill scope', async () => { + givenAgent({ schema: baseConfig }); + vi.mocked(userHasScopes).mockResolvedValue(false); + skillRefs.createSkills.mockResolvedValue(['skill_new']); + + await service.createAndAttachSkill(agentId, projectId, skill, context, 'agent'); + + expect(userHasScopes).not.toHaveBeenCalled(); + expect(skillRefs.createSkills).toHaveBeenCalledWith( + expect.anything(), + [skill], + 'user-1', + 'agent', + {}, + ); + }); + + it('rejects a name that is hard to tell apart from a skill of the agent', async () => { + skillRefs.bodies.existing = skill; + givenAgent({ schema: { ...baseConfig, skills: [{ type: 'skill', id: 'existing' }] } }); await expect( service.createAndAttachSkills( agentId, projectId, - [skill, { ...skillTwo, name: '' }], - telemetryContext, + [{ ...skill, name: ' summarize-notes ' }], + context, + ), + ).rejects.toThrow('Agent already has a skill with a name like "summarize-notes".'); + expect(skillRefs.createSkills).not.toHaveBeenCalled(); + expect(agentRepository.saveDraftFenced).not.toHaveBeenCalled(); + }); + + it('rejects two names in one batch that are hard to tell apart', async () => { + givenAgent({ schema: baseConfig }); + + await expect( + service.createAndAttachSkills( + agentId, + projectId, + [skill, { ...skill, name: 'summarize_notes' }], + context, + ), + ).rejects.toThrow( + 'The new skills "Summarize Notes", "summarize_notes" are hard to tell apart.', + ); + expect(skillRefs.createSkills).not.toHaveBeenCalled(); + }); + + it('rejects the whole batch when one item is invalid', async () => { + givenAgent({ schema: baseConfig }); + + await expect( + service.createAndAttachSkills( + agentId, + projectId, + [skill, { ...skill, name: 'Other', instructions: '' }], + context, ), ).rejects.toThrow('Invalid agent skill'); - - expect(agentRepository.saveDraftFenced).not.toHaveBeenCalled(); - expect(runtimeCacheService.clearRuntimes).not.toHaveBeenCalled(); + expect(skillRefs.createSkills).not.toHaveBeenCalled(); }); }); - it('creates and attaches a skill on the agent when requested', async () => { - const agent = makeAgent({ - schema: { - name: 'Test Agent', - model: 'anthropic/claude-sonnet-4-5', - instructions: 'Be helpful', - skills: [], - }, + it('lists and updates every body on the agent row while the skills hub is off', async () => { + Object.assign(skillRefs, { usesSkillsHub: false }); + // `old` has no ref, as after a ref was switched off or removed on master. + const agent = givenAgent({ + schema: { ...baseConfig, skills: [{ type: 'skill', id: 'skill_a' }] }, + skills: { skill_a: skill, old: { ...skill, name: 'Old' } }, }); - agentRepository.findByIdAndProjectId.mockResolvedValue(agent); - const result = await service.createAndAttachSkill(agentId, projectId, skill, telemetryContext); - - expect(agentRepository.saveDraftFenced.mock.calls[0][0].skills).toEqual({ - [result.id]: skill, + await expect(service.listSkills(agentId, projectId)).resolves.toEqual(agent.skills); + await expect(service.getSkill(agentId, projectId, 'old')).resolves.toMatchObject({ + name: 'Old', }); - expect(storedSkillRefs(agent)).toEqual([{ type: 'skill', id: result.id }]); - expect(runtimeCacheService.clearRuntimes).toHaveBeenCalledWith(agentId); + await service.updateSkill(agentId, projectId, 'old', { instructions: 'Updated.' }, context); + expect(agent.skills.old).toMatchObject({ name: 'Old', instructions: 'Updated.' }); }); - it('loads one skill from the agent', async () => { - agentRepository.findByIdAndProjectId.mockResolvedValue( - makeAgent({ skills: { summarize_notes: skill } }), - ); - - await expect(service.getSkill(agentId, projectId, 'summarize_notes')).resolves.toEqual(skill); - expect(runtimeCacheService.clearRuntimes).not.toHaveBeenCalled(); - }); - - it('updates an existing skill on the agent and preserves omitted references', async () => { - const skillWithReferences = { - ...skill, - references: [ - { - path: 'references/guide.md', - content: '# Guide', - }, - ], - }; - const agent = makeAgent({ + it('refuses a rename onto the name of an unreferenced body while the skills hub is off', async () => { + Object.assign(skillRefs, { usesSkillsHub: false }); + givenAgent({ + schema: { ...baseConfig, skills: [{ type: 'skill', id: 'skill_a' }] }, skills: { - summarize_notes: skillWithReferences, + skill_a: skill, + old: { ...skill, name: 'Old' }, + older: { ...skill, name: 'Older' }, }, }); - agentRepository.findByIdAndProjectId.mockResolvedValue(agent); - - const result = await service.updateSkill( - agentId, - projectId, - 'summarize_notes', - { - description: 'Summarizes support notes', - }, - { ...telemetryContext, pushRef: 'writer-push-ref' }, - getAgentSkillHash(skillWithReferences), - ); - - expect(result).toEqual({ - id: 'summarize_notes', - skill: { - ...skill, - description: 'Summarizes support notes', - references: [ - { - path: 'references/guide.md', - content: '# Guide', - }, - ], - }, - skillHash: expect.stringMatching(/^[a-f0-9]{64}$/), - versionId: agent.versionId, - }); - expect(agentRepository.saveDraftFenced.mock.calls[0][0].skills).toEqual({ - summarize_notes: result.skill, - }); - expect(runtimeCacheService.clearRuntimes).toHaveBeenCalledWith(agentId); - expect(agentUpdateBroadcaster.notify).toHaveBeenCalledWith( - { projectId, agentId, source: 'user' }, - 'writer-push-ref', - ); - }); - - it('rejects an update based on a stale skill without mutating the agent', async () => { - const agent = makeAgent({ skills: { summarize_notes: skill } }); - agentRepository.findByIdAndProjectId.mockResolvedValue(agent); await expect( - service.updateSkill( - agentId, - projectId, - 'summarize_notes', - { instructions: 'Replace newer work' }, - telemetryContext, - 'stale-hash', - ), - ).rejects.toThrow('Skill was changed elsewhere; reload to get the latest version'); - - expect(agent.skills?.summarize_notes).toBe(skill); - expect(agentRepository.saveDraftFenced).not.toHaveBeenCalled(); - expect(runtimeCacheService.clearRuntimes).not.toHaveBeenCalled(); - expect(modificationTelemetry.record).not.toHaveBeenCalled(); - expect(agentUpdateBroadcaster.notify).not.toHaveBeenCalled(); + service.updateSkill(agentId, projectId, 'old', { name: 'older' }, context), + ).rejects.toThrow('Agent already has a skill with a name like "older".'); }); - describe('instructionEdits', () => { - const editableSkill = { - ...skill, - instructions: '## Steps\n1. Extract decisions.\n2. Extract action items.\n', - }; + it('lists the skills the draft runs', async () => { + skillRefs.bodies.skill_a = skill; + givenAgent({ schema: { ...baseConfig, skills: [{ type: 'skill', id: 'skill_a' }] } }); - it('applies the edits to the stored instructions', async () => { - agentRepository.findByIdAndProjectId.mockResolvedValue( - makeAgent({ skills: { summarize_notes: editableSkill } }), + await expect(service.listSkills(agentId, projectId)).resolves.toEqual({ skill_a: skill }); + await expect(service.getSkill(agentId, projectId, 'skill_a')).resolves.toEqual(skill); + await expect(service.getSkill(agentId, projectId, 'toString')).rejects.toThrow(NotFoundError); + }); + + describe('updateSkill', () => { + beforeEach(() => { + skillRefs.bodies.skill_a = skill; + skillService.save.mockResolvedValue(saveResult()); + }); + + it('changes where the skill can be added without saving a new version', async () => { + const agent = givenAgent({ + schema: { ...baseConfig, skills: [{ type: 'skill', id: 'skill_a' }] }, + skills: { skill_a: skill }, + }); + skillRefs.availabilityOf.mockResolvedValue('project'); + + await service.updateSkill( + agentId, + projectId, + 'skill_a', + {}, + context, + undefined, + undefined, + 'agent', ); + expect(skillService.assertCanEdit).toHaveBeenCalledWith(user, ['skill_a']); + expect(skillRefs.setAvailability).toHaveBeenCalledWith(agent, 'skill_a', 'agent', {}); + expect(skillService.save).not.toHaveBeenCalled(); + }); + + it('writes nothing when the skill keeps where it can be added', async () => { + givenAgent({ schema: { ...baseConfig, skills: [{ type: 'skill', id: 'skill_a' }] } }); + skillRefs.availabilityOf.mockResolvedValue('agent'); + + await service.updateSkill( + agentId, + projectId, + 'skill_a', + {}, + context, + undefined, + undefined, + 'agent', + ); + + expect(skillRefs.setAvailability).not.toHaveBeenCalled(); + expect(skillService.save).not.toHaveBeenCalled(); + }); + + it('sets and clears allowed tools on the agent row when the skills hub is off', async () => { + Object.assign(skillRefs, { usesSkillsHub: false }); + const agent = givenAgent({ + schema: { ...baseConfig, skills: [{ type: 'skill', id: 'skill_a' }] }, + skills: { skill_a: skill }, + }); + + await service.updateSkill( + agentId, + projectId, + 'skill_a', + { allowedTools: ['search'] }, + context, + getAgentSkillHash(skill), + ); + expect(agent.skills.skill_a).toEqual({ ...skill, allowedTools: ['search'] }); + + await service.updateSkill(agentId, projectId, 'skill_a', { allowedTools: [] }, context); + expect(agent.skills.skill_a).toEqual(skill); + }); + + it('updates the body on the agent row when the skills hub is off', async () => { + Object.assign(skillRefs, { usesSkillsHub: false }); + const agent = givenAgent({ + schema: { ...baseConfig, skills: [{ type: 'skill', id: 'skill_a' }] }, + skills: { skill_a: skill }, + }); + const result = await service.updateSkill( agentId, projectId, - 'summarize_notes', - { description: 'Summarizes support notes' }, - telemetryContext, - getAgentSkillHash(editableSkill), - [{ oldText: '2. Extract action items.', newText: '2. Extract action items with owners.' }], + 'skill_a', + { instructions: 'New instructions.' }, + context, + getAgentSkillHash(skill), ); - expect(result.skill).toEqual({ - ...editableSkill, - description: 'Summarizes support notes', - instructions: '## Steps\n1. Extract decisions.\n2. Extract action items with owners.\n', + expect(agent.skills.skill_a).toEqual({ ...skill, instructions: 'New instructions.' }); + expect(agentRepository.saveDraftFenced).toHaveBeenCalledWith(agent, {}); + expect(result.skill.instructions).toBe('New instructions.'); + expect(skillService.assertCanEdit).not.toHaveBeenCalled(); + expect(skillService.save).not.toHaveBeenCalled(); + }); + + it('saves the next version with the skill edit permission, then refreshes the agents that follow it', async () => { + const agent = givenAgent({ + schema: { ...baseConfig, skills: [{ type: 'skill', id: 'skill_a' }] }, + skills: { skill_a: skill }, }); - expect(agentRepository.saveDraftFenced.mock.calls[0][0].skills).toEqual({ - summarize_notes: result.skill, - }); - }); + const fresh = { ...agent, versionId: 'v2' } as Agent; + agentRepository.findByIdAndProjectId + .mockResolvedValueOnce(agent) + .mockResolvedValueOnce(fresh); + skillService.save.mockResolvedValue(saveResult({ followingAgentIds: [agentId, 'agent-2'] })); - it('rejects an edit that does not match and saves nothing', async () => { - agentRepository.findByIdAndProjectId.mockResolvedValue( - makeAgent({ skills: { summarize_notes: editableSkill } }), - ); - - await expect( - service.updateSkill( - agentId, - projectId, - 'summarize_notes', - {}, - telemetryContext, - getAgentSkillHash(editableSkill), - [{ oldText: 'Extract risks.', newText: 'x' }], - ), - ).rejects.toThrow('instructionEdits[0]: oldText matches 0 places'); - expect(agentRepository.saveDraftFenced).not.toHaveBeenCalled(); - }); - - it('checks the base hash before it applies the edits', async () => { - agentRepository.findByIdAndProjectId.mockResolvedValue( - makeAgent({ skills: { summarize_notes: editableSkill } }), - ); - - await expect( - service.updateSkill( - agentId, - projectId, - 'summarize_notes', - {}, - telemetryContext, - 'stale-hash', - [{ oldText: 'Extract risks.', newText: 'x' }], - ), - ).rejects.toThrow('Skill was changed elsewhere'); - }); - - it('rejects instructions and instructionEdits together', async () => { - agentRepository.findByIdAndProjectId.mockResolvedValue( - makeAgent({ skills: { summarize_notes: editableSkill } }), - ); - - await expect( - service.updateSkill( - agentId, - projectId, - 'summarize_notes', - { instructions: 'New body' }, - telemetryContext, - undefined, - [{ oldText: 'Extract decisions.', newText: 'x' }], - ), - ).rejects.toThrow('Pass either instructions or instructionEdits, not both.'); - expect(agentRepository.saveDraftFenced).not.toHaveBeenCalled(); - }); - }); - - it('removes optional list fields when an update clears them', async () => { - const agent = makeAgent({ - skills: { - summarize_notes: { - ...skill, - allowedTools: ['load_workflow'], - references: [ - { - path: 'references/guide.md', - content: '# Guide', - }, - ], - }, - }, - }); - agentRepository.findByIdAndProjectId.mockResolvedValue(agent); - - const result = await service.updateSkill( - agentId, - projectId, - 'summarize_notes', - { - allowedTools: undefined, - references: [], - }, - telemetryContext, - ); - - expect(result.skill).not.toHaveProperty('allowedTools'); - expect(result.skill).not.toHaveProperty('references'); - expect(agentRepository.saveDraftFenced).toHaveBeenCalledWith( - expect.objectContaining({ - skills: { - summarize_notes: skill, - }, - }), - {}, - ); - }); - - it('rejects creating a skill with a duplicate name', async () => { - agentRepository.findByIdAndProjectId.mockResolvedValue( - makeAgent({ - skills: { summarize_notes: skill }, - schema: { - name: 'Test Agent', - model: 'anthropic/claude-sonnet-4-5', - instructions: 'Be helpful', - }, - }), - ); - - await expect( - service.createAndAttachSkill(agentId, projectId, skill, telemetryContext), - ).rejects.toThrow('Agent already has a skill named "Summarize Notes".'); - }); - - it('rejects renaming a skill to another existing skill name', async () => { - agentRepository.findByIdAndProjectId.mockResolvedValue( - makeAgent({ - skills: { - summarize_notes: skill, - other_skill: { name: 'Other Skill', description: 'desc', instructions: 'Use it' }, - }, - }), - ); - - await expect( - service.updateSkill( + const result = await service.updateSkill( agentId, projectId, - 'summarize_notes', - { name: 'Other Skill' }, - telemetryContext, - ), - ).rejects.toThrow('Agent already has a skill named "Other Skill".'); + 'skill_a', + { instructions: 'New instructions.', allowedTools: ['search'] }, + context, + getAgentSkillHash(skill), + ); + + expect(skillService.assertCanEdit).toHaveBeenCalledWith(user, ['skill_a']); + expect(skillService.save).toHaveBeenCalledWith( + 'skill_a', + { + name: skill.name, + description: skill.description, + instructions: 'New instructions.', + references: [], + baseSkillHash: getAgentSkillHash(skill), + }, + 'user-1', + {}, + ); + // The other agents get a refresh after the commit. This agent gets the save completion. + expect(skillService.refreshFollowingAgents).toHaveBeenCalledWith(['agent-2'], 'push-ref-1'); + expect(runtimeCacheService.clearRuntimes).toHaveBeenCalledWith(agentId); + expect(agentUpdateBroadcaster.notify).toHaveBeenCalledWith( + { projectId, agentId, source: 'user' }, + 'push-ref-1', + ); + expect(agentRepository.saveDraftFenced).not.toHaveBeenCalled(); + expect(result).toEqual({ + id: 'skill_a', + skill: { ...skill, instructions: 'New instructions.' }, + skillHash: getAgentSkillHash({ ...skill, instructions: 'New instructions.' }), + versionId: 'v2', + }); + }); + + it('clears the pin of this agent when the pin is the latest version', async () => { + const agent = givenAgent({ + schema: { ...baseConfig, skills: [{ type: 'skill', id: 'skill_a', versionId: pinId }] }, + }); + + await service.updateSkill( + agentId, + projectId, + 'skill_a', + { instructions: 'New instructions.' }, + context, + getAgentSkillHash(skill), + ); + + expect(agentRepository.saveDraftFenced).toHaveBeenCalledWith(agent, {}); + expect(skillRefs.unpinDraftRef).toHaveBeenCalledWith(agent, 'skill_a', {}); + await expect(skillRefs.refsForDraft(agent, {})).resolves.toEqual([ + { type: 'skill', id: 'skill_a' }, + ]); + expect(skillService.save).toHaveBeenCalledWith( + 'skill_a', + expect.objectContaining({ baseSkillHash: getAgentSkillHash(skill) }), + 'user-1', + {}, + ); + }); + + it('refuses to edit a pin to an older version', async () => { + givenAgent({ + schema: { ...baseConfig, skills: [{ type: 'skill', id: 'skill_a', versionId: pinId }] }, + }); + const olderSkill = { ...skill, instructions: 'Older instructions.' }; + skillRefs.skillsForRefs.mockResolvedValueOnce({ skill_a: olderSkill }); + + await expect( + service.updateSkill( + agentId, + projectId, + 'skill_a', + { instructions: 'New instructions.' }, + context, + getAgentSkillHash(olderSkill), + ), + ).rejects.toThrow( + 'This agent uses an older version of this skill. Use the latest version first, then edit the skill. To use the latest version, remove versionId from the skill ref in the agent config.', + ); + expect(skillRefs.unpinDraftRef).not.toHaveBeenCalled(); + expect(skillService.save).not.toHaveBeenCalled(); + }); + + it('rejects a stale base hash without saving', async () => { + givenAgent({ schema: { ...baseConfig, skills: [{ type: 'skill', id: 'skill_a' }] } }); + + await expect( + service.updateSkill( + agentId, + projectId, + 'skill_a', + { instructions: 'New instructions.' }, + context, + 'stale', + ), + ).rejects.toThrow(ConflictError); + expect(skillService.save).not.toHaveBeenCalled(); + }); + + it('rejects a user who may use but not edit the skill', async () => { + givenAgent({ schema: { ...baseConfig, skills: [{ type: 'skill', id: 'skill_a' }] } }); + skillService.assertCanEdit.mockRejectedValue(new ForbiddenError('You can use but not edit')); + + await expect( + service.updateSkill(agentId, projectId, 'skill_a', { instructions: 'New.' }, context), + ).rejects.toThrow(ForbiddenError); + expect(skillService.save).not.toHaveBeenCalled(); + }); + + it('rejects a skill that is not attached to the agent', async () => { + givenAgent({ schema: baseConfig }); + + await expect( + service.updateSkill(agentId, projectId, 'skill_a', { instructions: 'New.' }, context), + ).rejects.toThrow(NotFoundError); + }); + + it('saves nothing when the update does not change the skill', async () => { + givenAgent({ schema: { ...baseConfig, skills: [{ type: 'skill', id: 'skill_a' }] } }); + + const result = await service.updateSkill( + agentId, + projectId, + 'skill_a', + { name: skill.name }, + context, + ); + + expect(result).toEqual({ + id: 'skill_a', + skill, + skillHash: getAgentSkillHash(skill), + versionId, + }); + expect(skillService.assertCanEdit).not.toHaveBeenCalled(); + expect(skillService.save).not.toHaveBeenCalled(); + expect(modificationTelemetry.record).not.toHaveBeenCalled(); + }); + + it('applies instruction edits to the version this agent shows', async () => { + givenAgent({ schema: { ...baseConfig, skills: [{ type: 'skill', id: 'skill_a' }] } }); + + await service.updateSkill( + agentId, + projectId, + 'skill_a', + {}, + context, + getAgentSkillHash(skill), + [{ oldText: 'action items', newText: 'owners' }], + ); + + expect(skillService.save).toHaveBeenCalledWith( + 'skill_a', + expect.objectContaining({ instructions: 'Extract decisions and owners.' }), + 'user-1', + {}, + ); + }); + + it('removes the references when an update clears them', async () => { + skillRefs.bodies.skill_a = { + ...skill, + references: [{ path: 'references/a.md', content: 'A' }], + }; + givenAgent({ schema: { ...baseConfig, skills: [{ type: 'skill', id: 'skill_a' }] } }); + + await service.updateSkill(agentId, projectId, 'skill_a', { references: [] }, context); + + expect(skillService.save).toHaveBeenCalledWith( + 'skill_a', + expect.objectContaining({ references: [] }), + 'user-1', + {}, + ); + }); }); - it('deletes a skill and removes its config ref', async () => { - const agent = makeAgent({ - skills: { summarize_notes: skill }, - schema: { - name: 'Test Agent', - model: 'anthropic/claude-sonnet-4-5', - instructions: 'Be helpful', - tools: [{ type: 'custom', id: 'custom_tool' }], - skills: [{ type: 'skill', id: 'summarize_notes' }], - }, + describe('deleteSkill', () => { + it('detaches the skill and keeps the hub skill', async () => { + const agent = givenAgent({ + schema: { + ...baseConfig, + skills: [ + { type: 'skill', id: 'skill_a' }, + { type: 'skill', id: 'skill_b' }, + ], + }, + }); + + await service.deleteSkill(agentId, projectId, 'skill_a', context); + + expect(skillRefs.replaceDraftRefs).toHaveBeenCalledWith( + agent, + [{ type: 'skill', id: 'skill_b' }], + {}, + ); + expect(agentRepository.saveDraftFenced).toHaveBeenCalledWith(agent, {}); + expect(skillService.deleteSkill).not.toHaveBeenCalled(); + expect(runtimeCacheService.clearRuntimes).toHaveBeenCalledWith(agentId); }); - agentRepository.findByIdAndProjectId.mockResolvedValue(agent); - await service.deleteSkill(agentId, projectId, 'summarize_notes', telemetryContext); + it('rejects a skill that is not attached to the agent', async () => { + givenAgent({ schema: baseConfig }); - expect(agentRepository.saveDraftFenced.mock.calls[0][0].skills).toEqual({}); - expect(agent.schema?.tools).toEqual([{ type: 'custom', id: 'custom_tool' }]); - expect(storedSkillRefs(agent)).toEqual([]); - expect(agentRepository.updateDraftSchema).toHaveBeenCalledTimes(1); - expect(runtimeCacheService.clearRuntimes).toHaveBeenCalledWith(agentId); - }); - - it('does not add a skills key when it deletes a skill from a config without one', async () => { - const agent = makeAgent({ - skills: { summarize_notes: skill }, - schema: { - name: 'Test Agent', - model: 'anthropic/claude-sonnet-4-5', - instructions: 'Be helpful', - }, + await expect(service.deleteSkill(agentId, projectId, 'skill_a', context)).rejects.toThrow( + NotFoundError, + ); + expect(agentRepository.saveDraftFenced).not.toHaveBeenCalled(); }); - agentRepository.findByIdAndProjectId.mockResolvedValue(agent); - - await service.deleteSkill(agentId, projectId, 'summarize_notes', telemetryContext); - - expect(agentRepository.saveDraftFenced.mock.calls[0][0].skills).toEqual({}); - expect(agentRepository.updateDraftSchema).not.toHaveBeenCalled(); - expect(agent.schema).not.toHaveProperty('skills'); - }); - - it('reports skill body changes through lifecycle telemetry and stays silent on a no-op update', async () => { - const agent = makeAgent({ - schema: { - name: 'Test Agent', - model: 'anthropic/claude-sonnet-4-5', - instructions: 'Be helpful', - skills: [{ type: 'skill', id: 'summarize_notes' }], - }, - skills: { summarize_notes: skill }, - integrations: [], - }); - agentRepository.findByIdAndProjectId.mockResolvedValue(agent); - - await service.updateSkill( - agentId, - projectId, - 'summarize_notes', - { description: 'Updated description' }, - telemetryContext, - ); - - expect(agentRepository.saveDraftFenced).toHaveBeenCalledTimes(1); - expect(agentRepository.updateDraftSchema).not.toHaveBeenCalled(); - expect(storedSkillRefs(agent)).toEqual([{ type: 'skill', id: 'summarize_notes' }]); - expect(modificationTelemetry.record).toHaveBeenCalledWith( - expect.objectContaining({ - by: 'user', - changedParts: ['skills'], - wasUnconfigured: false, - }), - ); - - vi.clearAllMocks(); - agentRepository.findByIdAndProjectId.mockResolvedValue(agent); - await service.updateSkill( - agentId, - projectId, - 'summarize_notes', - { description: 'Updated description' }, - telemetryContext, - ); - expect(agentRepository.saveDraftFenced).not.toHaveBeenCalled(); - expect(modificationTelemetry.record).not.toHaveBeenCalled(); - }); - - it('stays silent when a detached skill is written on an unconfigured agent', async () => { - const agent = makeAgent({ - schema: { name: 'Test Agent', model: '', instructions: '', skills: [] }, - integrations: [], - }); - agentRepository.findByIdAndProjectId.mockResolvedValue(agent); - - await service.createSkill(agentId, projectId, skill, telemetryContext); - - expect(modificationTelemetry.record).toHaveBeenCalledWith( - expect.objectContaining({ - changedParts: ['skills'], - wasUnconfigured: true, - }), - ); - // record itself suppresses blank-to-blank; the service still reports the write. }); }); diff --git a/packages/cli/src/modules/agents/__tests__/agent-task.service.test.ts b/packages/cli/src/modules/agents/__tests__/agent-task.service.test.ts index f804ee9dbab..2fb88fda9e8 100644 --- a/packages/cli/src/modules/agents/__tests__/agent-task.service.test.ts +++ b/packages/cli/src/modules/agents/__tests__/agent-task.service.test.ts @@ -170,7 +170,7 @@ describe('AgentTaskService', () => { ), settingsService, transactionRunner, - createAgentSkillRefsService(agentRepository), + createAgentSkillRefsService(), ); } diff --git a/packages/cli/src/modules/agents/__tests__/agent-teams-integrations.controller.test.ts b/packages/cli/src/modules/agents/__tests__/agent-teams-integrations.controller.test.ts index 9d9c178a07b..d27e508d6ea 100644 --- a/packages/cli/src/modules/agents/__tests__/agent-teams-integrations.controller.test.ts +++ b/packages/cli/src/modules/agents/__tests__/agent-teams-integrations.controller.test.ts @@ -1,13 +1,24 @@ /* eslint-disable @typescript-eslint/unbound-method -- mock-based tests intentionally reference unbound methods */ +import { AgentTeamsPublishDto } from '@n8n/api-types'; +import type { TeamsAzureSubscription, TeamsCatalogState } from '@n8n/api-types'; +import type { User } from '@n8n/db'; import { mock } from 'vitest-mock-extended'; import type { Request, Response } from 'express'; +import type { AuthenticatedRequest } from '@n8n/db'; + import { AgentTeamsIntegrationsController } from '../agent-teams-integrations.controller'; import { expectProjectScopedAgentRoutes, getRoutesByHandlerName, } from './test-utils/controller-route-metadata'; import type { TeamsCredentialCheckService } from '../integrations/platforms/teams/teams-credential-check.service'; +import type { TeamsBotProvisioningService } from '../integrations/platforms/teams/teams-bot-provisioning.service'; +import type { TeamsCatalogService } from '../integrations/platforms/teams/teams-catalog.service'; +import type { TeamsCredentialNotesService } from '../integrations/platforms/teams/teams-credential-notes.service'; +import type { TeamsEntraProvisioningService } from '../integrations/platforms/teams/teams-entra-provisioning.service'; +import type { TeamsSetupTelemetryService } from '../integrations/platforms/teams/teams-setup-telemetry.service'; +import type { TeamsManagedSetupService } from '../integrations/platforms/teams/teams-managed-setup.service'; import type { TeamsSetupService } from '../integrations/platforms/teams/teams-setup.service'; /** Reached by the Azure portal and the browser's save dialog, not by the app. */ @@ -26,6 +37,14 @@ describe('AgentTeamsIntegrationsController', () => { ['getSetupState', 'agent:update'], ['downloadPackage', 'agent:update'], ['checkCredential', 'agent:update'], + ['listAzureSubscriptions', 'agent:update'], + ['provisionBot', 'agent:update'], + ['provisionApp', 'agent:update'], + ['getManagedSetupState', 'agent:update'], + ['createManagerCredential', 'agent:update'], + ['reportManualBotRoute', 'agent:update'], + ['publishApp', 'agent:update'], + ['getCatalogState', 'agent:update'], ])('%s uses %s', (handlerName, scope) => { expect(routes.get(handlerName)?.accessScope?.scope).toBe(scope); }); @@ -39,6 +58,12 @@ describe('AgentTeamsIntegrationsController', () => { controller: new AgentTeamsIntegrationsController( setupService, mock(), + mock(), + mock(), + mock(), + mock(), + mock(), + mock(), ), }; }; @@ -107,4 +132,267 @@ describe('AgentTeamsIntegrationsController', () => { }); }); }); + + /** + * Which rung of the bot ladder people land on is the question the ladder + * exists to answer, and the no-subscription rung is chosen here: the browser + * switches to the manual flow without reporting a step. + */ + describe('the Azure subscription lookup', () => { + const buildController = (subscriptions: TeamsAzureSubscription[]) => { + const botProvisioningService = mock(); + botProvisioningService.listSubscriptions.mockResolvedValue(subscriptions); + const setupTelemetry = mock(); + return { + setupTelemetry, + controller: new AgentTeamsIntegrationsController( + mock(), + mock(), + mock(), + mock(), + botProvisioningService, + mock(), + setupTelemetry, + mock(), + ), + }; + }; + + const request = () => + mock>({ + params: { projectId: 'project-1' }, + query: { managerCredentialId: 'manager-1' }, + user: mock({ id: 'user-1' }), + }); + + /** + * The setup reads this again on every remount and every change of sign-in, + * and a tenant with no Azure subscription is the ordinary case. Reporting + * from here would count the dialog being opened. + */ + it.each([ + ['no subscription', []], + ['one to use', [{ id: 'sub-1', name: 'Production' }]], + ])('records nothing for a lookup that found %s', async (_name, subscriptions) => { + const { controller, setupTelemetry } = buildController(subscriptions); + + // What the route is for, beside what it must not do: the bot step picks + // the subscription to build in out of this answer. + await expect( + controller.listAzureSubscriptions(request(), mock(), 'agent-1'), + ).resolves.toEqual(subscriptions); + + expect(setupTelemetry.succeeded).not.toHaveBeenCalled(); + }); + + // Where the rung is reported instead: the user leaving for the manual bot. + it('records the manual rung when the setup leaves the recommended flow', () => { + const { controller, setupTelemetry } = buildController([]); + + controller.reportManualBotRoute(request(), mock(), 'agent-1'); + + expect(setupTelemetry.succeeded).toHaveBeenCalledWith({ + agentId: 'agent-1', + projectId: 'project-1', + userId: 'user-1', + step: 'create_bot', + botRoute: 'manual', + }); + }); + }); + describe('the package download', () => { + it('records what it handed over, so the settings can tell Teams is behind', async () => { + const setupService = mock(); + const credentialNotes = mock(); + setupService.buildPackage.mockResolvedValue({ + archive: Buffer.from('zip'), + fingerprint: 'fingerprint-1', + credentialId: 'cred-1', + }); + const controller = new AgentTeamsIntegrationsController( + setupService, + mock(), + mock(), + mock(), + mock(), + mock(), + mock(), + credentialNotes, + ); + const user = mock({ id: 'user-1' }); + + await controller.downloadPackage( + mock>({ + params: { projectId: 'project-1' }, + user, + }), + mock(), + 'agent-1', + mock({ credentialId: 'cred-1', settings: undefined }), + ); + + expect(credentialNotes.write).toHaveBeenCalledWith(user, 'cred-1', { + teamsAppFingerprint: 'fingerprint-1', + }); + }); + }); + + /** + * The publish call is where the two routes Microsoft offers are told apart, + * and the route is what the ladder reports. The service answers four states + * and only two of them are routes. + */ + describe('the catalogue publish', () => { + const buildController = () => { + const catalogService = mock(); + const setupTelemetry = mock(); + return { + catalogService, + setupTelemetry, + controller: new AgentTeamsIntegrationsController( + mock(), + mock(), + mock(), + mock(), + mock(), + catalogService, + setupTelemetry, + mock(), + ), + }; + }; + + const request = () => + mock>({ + params: { projectId: 'project-1' }, + user: mock({ id: 'user-1' }), + }); + + const payload = () => + new AgentTeamsPublishDto({ + managerCredentialId: 'manager-1', + credentialId: 'cred-1', + settings: { displayName: 'Support Bot' }, + }); + + it('publishes with the credentials and settings the caller named', async () => { + const { controller, catalogService } = buildController(); + catalogService.publish.mockResolvedValue({ status: 'published', teamsAppId: 'app-1' }); + + await expect( + controller.publishApp(request(), mock(), 'agent-1', payload()), + ).resolves.toEqual({ status: 'published', teamsAppId: 'app-1' }); + + expect(catalogService.publish).toHaveBeenCalledWith({ + user: expect.objectContaining({ id: 'user-1' }), + projectId: 'project-1', + agentId: 'agent-1', + managerCredentialId: 'manager-1', + credentialId: 'cred-1', + settings: { displayName: 'Support Bot' }, + }); + }); + + it.each(['published', 'submitted'] as const)( + 'records %s as the install route', + async (status) => { + const { controller, catalogService, setupTelemetry } = buildController(); + catalogService.publish.mockResolvedValue({ status, teamsAppId: 'app-1' }); + + await controller.publishApp(request(), mock(), 'agent-1', payload()); + + expect(setupTelemetry.succeeded).toHaveBeenCalledWith({ + agentId: 'agent-1', + projectId: 'project-1', + userId: 'user-1', + step: 'install', + installRoute: status, + }); + }, + ); + + // Neither answer took a route: the app is not listed yet, or Microsoft + // refused it. Reporting one here would claim an install that never ran. + it.each(['unknown', 'rejected'] as const)('records no install route for %s', async (status) => { + const { controller, catalogService, setupTelemetry } = buildController(); + catalogService.publish.mockResolvedValue({ status, teamsAppId: null }); + + await controller.publishApp(request(), mock(), 'agent-1', payload()); + + expect(setupTelemetry.succeeded).toHaveBeenCalledWith( + expect.not.objectContaining({ installRoute: expect.anything() }), + ); + }); + + it('records a failed publish and still fails the request', async () => { + const { controller, catalogService, setupTelemetry } = buildController(); + const error = new Error('Microsoft refused the upload'); + catalogService.publish.mockRejectedValue(error); + + await expect( + controller.publishApp(request(), mock(), 'agent-1', payload()), + ).rejects.toThrow(error); + + expect(setupTelemetry.failed).toHaveBeenCalledWith( + { agentId: 'agent-1', projectId: 'project-1', userId: 'user-1', step: 'install' }, + error, + ); + }); + it('reads the catalogue state for the credentials the caller named', async () => { + const { controller, catalogService } = buildController(); + const state: TeamsCatalogState = { status: 'submitted', teamsAppId: 'app-1' }; + catalogService.getState.mockResolvedValue(state); + + const req = mock< + AuthenticatedRequest< + { projectId: string }, + {}, + {}, + { managerCredentialId?: string; credentialId?: string } + > + >({ + params: { projectId: 'project-1' }, + query: { managerCredentialId: 'manager-1', credentialId: 'cred-1' }, + user: mock({ id: 'user-1' }), + }); + + await expect(controller.getCatalogState(req, mock(), 'agent-1')).resolves.toBe( + state, + ); + + expect(catalogService.getState).toHaveBeenCalledWith({ + user: expect.objectContaining({ id: 'user-1' }), + projectId: 'project-1', + agentId: 'agent-1', + managerCredentialId: 'manager-1', + credentialId: 'cred-1', + }); + }); + + // The setup asks for the state before the user signs in, and without a + // manager credential there is nothing to ask Microsoft with. + it('answers unknown without reaching Microsoft when no manager credential is named', async () => { + const { controller, catalogService } = buildController(); + + const req = mock< + AuthenticatedRequest< + { projectId: string }, + {}, + {}, + { managerCredentialId?: string; credentialId?: string } + > + >({ + params: { projectId: 'project-1' }, + query: {}, + user: mock({ id: 'user-1' }), + }); + + await expect(controller.getCatalogState(req, mock(), 'agent-1')).resolves.toEqual({ + status: 'unknown', + teamsAppId: null, + }); + + expect(catalogService.getState).not.toHaveBeenCalled(); + }); + }); }); diff --git a/packages/cli/src/modules/agents/__tests__/agent-validation.service.test.ts b/packages/cli/src/modules/agents/__tests__/agent-validation.service.test.ts index 3ddf90329c2..6d3a38b1ad7 100644 --- a/packages/cli/src/modules/agents/__tests__/agent-validation.service.test.ts +++ b/packages/cli/src/modules/agents/__tests__/agent-validation.service.test.ts @@ -65,6 +65,7 @@ function makeCredentialProvider( } function makeService() { + const skillRefs = createAgentSkillRefsService(); const agentRepository = mock(); agentRepository.hasRevision.mockResolvedValue(true); const agentSkillsService = mock(); @@ -87,14 +88,15 @@ function makeService() { agentTaskSnapshotRepository, agentRepository, mock(), - createAgentSkillRefsService(agentRepository), + skillRefs, ), nodeTypes, workflowRepository, chatIntegrationRegistry, aiGatewayService, - createAgentSkillRefsService(agentRepository), + skillRefs, ), + skillRefs, agentRepository, agentSkillsService, agentTaskRepository, @@ -167,7 +169,6 @@ describe('AgentValidationService — structured issues', () => { }, { type: 'custom', id: 'active_missing' }, ], - skills: [{ type: 'skill', id: 'missing_skill', enabled: false }], subAgents: { agents: [{ agentId: 'missing_subagent', enabled: false }] }, }; agentRepository.findByIdAndProjectId.mockResolvedValue(makeAgent(config)); @@ -202,7 +203,8 @@ describe('AgentValidationService — structured issues', () => { }); for (const ref of config.tools!) ref.enabled = true; - config.skills![0].enabled = true; + // A skill has no on/off state: an attached ref to a missing skill is an issue. + config.skills = [{ type: 'skill', id: 'missing_skill' }]; config.subAgents!.agents![0].enabled = true; const reactivated = await service.validateAgentConfiguration( agentId, @@ -223,6 +225,39 @@ describe('AgentValidationService — structured issues', () => { }, ); + it('warns about skill names that are hard to tell apart without failing validation', async () => { + const { service, agentRepository, skillRefs } = makeService(); + const body = { description: 'A skill', instructions: 'Do it.' }; + skillRefs.bodies.brand = { ...body, name: 'Brand voice' }; + skillRefs.bodies.brand_copy = { ...body, name: 'brand-voice' }; + skillRefs.bodies.pricing = { ...body, name: 'Pricing' }; + agentRepository.findByIdAndProjectId.mockResolvedValue( + makeAgent({ + ...runnableConfig, + skills: [ + { type: 'skill', id: 'brand' }, + { type: 'skill', id: 'pricing' }, + { type: 'skill', id: 'brand_copy' }, + ], + }), + ); + + const result = await service.validateAgentConfiguration( + agentId, + projectId, + makeCredentialProvider([{ id: 'openai-main', type: 'openAiApi' }]), + ); + + expect(result.status).toBe('valid'); + expect(result.warnings).toEqual([ + { + code: 'similar_skill_names', + capability: { kind: 'skill' }, + names: ['Brand voice', 'brand-voice'], + }, + ]); + }); + it('flags a main model credential whose provider does not match the configured model, but not when the model itself is invalid', async () => { const { service, agentRepository } = makeService(); agentRepository.findByIdAndProjectId.mockResolvedValue(makeAgent(runnableConfig)); diff --git a/packages/cli/src/modules/agents/__tests__/agent-whatsapp-integrations.controller.test.ts b/packages/cli/src/modules/agents/__tests__/agent-whatsapp-integrations.controller.test.ts new file mode 100644 index 00000000000..a8f2874d0d3 --- /dev/null +++ b/packages/cli/src/modules/agents/__tests__/agent-whatsapp-integrations.controller.test.ts @@ -0,0 +1,120 @@ +import type { WhatsAppCredentialCheck } from '@n8n/api-types'; +import { NotFoundError } from '@n8n/errors'; +import { mock } from 'vitest-mock-extended'; + +import { AgentWhatsAppIntegrationsController } from '../agent-whatsapp-integrations.controller'; +import type { WhatsAppCredentialCheckService } from '../integrations/platforms/whatsapp/whatsapp-credential-check.service'; +import type { WhatsAppWebhookVerificationStore } from '../integrations/platforms/whatsapp/whatsapp-webhook-verification.store'; +import type { AgentRepository } from '../repositories/agent.repository'; +import { + expectProjectScopedAgentRoutes, + getRoutesByHandlerName, +} from './test-utils/controller-route-metadata'; + +function makeController() { + const credentialCheckService = mock(); + const webhookVerification = mock(); + const agentRepository = mock(); + + return { + controller: new AgentWhatsAppIntegrationsController( + credentialCheckService, + webhookVerification, + agentRepository, + ), + credentialCheckService, + webhookVerification, + agentRepository, + }; +} + +describe('AgentWhatsAppIntegrationsController', () => { + expectProjectScopedAgentRoutes(AgentWhatsAppIntegrationsController); + + const routes = getRoutesByHandlerName(AgentWhatsAppIntegrationsController); + + it.each([ + ['checkCredential', 'agent:update'], + ['webhookStatus', 'agent:read'], + ['resetWebhookStatus', 'agent:update'], + ])('%s uses %s', (handlerName, scope) => { + expect(routes.get(handlerName)?.accessScope?.scope).toBe(scope); + }); + + const user = { id: 'user-1' }; + const request = { params: { projectId: 'project-1' }, user } as never; + + describe('checkCredential', () => { + it('delegates to the credential check with the caller, project and credential', async () => { + const { controller, credentialCheckService } = makeController(); + const check: WhatsAppCredentialCheck = { status: 'failed', reason: 'mismatch' }; + credentialCheckService.check.mockResolvedValue(check); + + const result = await controller.checkCredential(request, undefined as never, 'cred-1'); + + expect(credentialCheckService.check).toHaveBeenCalledWith(user, 'project-1', 'cred-1'); + expect(result).toBe(check); + }); + }); + + describe('webhookStatus', () => { + it('throws NotFoundError when the agent is not in the project', async () => { + const { controller, agentRepository, webhookVerification } = makeController(); + agentRepository.existsBy.mockResolvedValue(false); + + await expect( + controller.webhookStatus(request, undefined as never, 'agent-1'), + ).rejects.toThrow(NotFoundError); + + expect(agentRepository.existsBy).toHaveBeenCalledWith({ + id: 'agent-1', + projectId: 'project-1', + }); + expect(webhookVerification.isVerified).not.toHaveBeenCalled(); + }); + + it.each([true, false])('returns verified %s from the verification store', async (verified) => { + const { controller, agentRepository, webhookVerification } = makeController(); + agentRepository.existsBy.mockResolvedValue(true); + webhookVerification.isVerified.mockResolvedValue(verified); + + const result = await controller.webhookStatus(request, undefined as never, 'agent-1'); + + expect(webhookVerification.isVerified).toHaveBeenCalledWith('agent-1'); + expect(result).toEqual({ verified }); + }); + }); + + describe('resetWebhookStatus', () => { + it('throws NotFoundError when the agent is not in the project', async () => { + const { controller, agentRepository, webhookVerification } = makeController(); + agentRepository.existsBy.mockResolvedValue(false); + + await expect( + controller.resetWebhookStatus(request, undefined as never, 'agent-1'), + ).rejects.toThrow(NotFoundError); + + expect(webhookVerification.reset).not.toHaveBeenCalled(); + }); + + it('resets the recorded handshake and reports it as not verified', async () => { + const { controller, agentRepository, webhookVerification } = makeController(); + agentRepository.existsBy.mockResolvedValue(true); + + const result = await controller.resetWebhookStatus(request, undefined as never, 'agent-1'); + + expect(webhookVerification.reset).toHaveBeenCalledExactlyOnceWith('agent-1'); + expect(result).toEqual({ verified: false }); + }); + + it('fails when the reset fails, so the setup does not trust a stale record', async () => { + const { controller, agentRepository, webhookVerification } = makeController(); + agentRepository.existsBy.mockResolvedValue(true); + webhookVerification.reset.mockRejectedValue(new Error('cache down')); + + await expect( + controller.resetWebhookStatus(request, undefined as never, 'agent-1'), + ).rejects.toThrow('cache down'); + }); + }); +}); diff --git a/packages/cli/src/modules/agents/__tests__/agent-workflow-execution.service.test.ts b/packages/cli/src/modules/agents/__tests__/agent-workflow-execution.service.test.ts index ccfb843eead..d0cb79d3943 100644 --- a/packages/cli/src/modules/agents/__tests__/agent-workflow-execution.service.test.ts +++ b/packages/cli/src/modules/agents/__tests__/agent-workflow-execution.service.test.ts @@ -1,7 +1,7 @@ import type { AgentMessageSteeringService } from '../agent-message-steering.service'; import type { Agent as RuntimeAgent, ExecutionOptions, RunOptions, StreamChunk } from '@n8n/agents'; import type { AgentJsonConfig } from '@n8n/api-types'; -import { mockLogger } from '@n8n/backend-test-utils'; +import { mockInstance, mockLogger } from '@n8n/backend-test-utils'; import type { AiConfig } from '@n8n/config'; import { Container } from '@n8n/di'; import { createDeferredPromise } from '@n8n/utils/promise/deferred-promise'; @@ -11,6 +11,7 @@ import type { ExecuteAgentWorkflowContext, IRunExecutionData } from 'n8n-workflo import type { Mock } from 'vitest'; import { mock } from 'vitest-mock-extended'; import type { AgentsSettingsService } from '../agents-settings.service'; +import { SkillService } from '../skills/skill.service'; import type { CredentialsService } from '@/credentials/credentials.service'; import type { ExecutionLevelTracer } from '@/modules/otel/execution-level-tracer'; @@ -131,6 +132,7 @@ function makeRuntime(chunks: StreamChunk[] = [{ type: 'finish', finishReason: 's } function makeService() { + const skillRefs = createAgentSkillRefsService(); const settingsService = mock(); const agentRepository = mock(); const executionService = mock(); @@ -177,11 +179,12 @@ function makeService() { aiConfigMock, integrationMessageContextService, settingsService, - createAgentSkillRefsService(agentRepository), + skillRefs, ); return { service, + skillRefs, settingsService, agentRepository, executionService, @@ -886,6 +889,49 @@ describe('AgentWorkflowExecutionService', () => { }, }; + it('runs the embedded skills and never calls the skill service', async () => { + const skillService = mockInstance(SkillService); + const { service, reconstructionService, skillRefs } = makeService(); + reconstructionService.reconstructFromResolvedSource.mockResolvedValue( + makeRuntime([{ type: 'finish', finishReason: 'stop' }]), + ); + const embedded = { + name: 'Embedded skill', + description: 'An inline skill', + instructions: 'Use the embedded text.', + }; + + await service.executeInlineForWorkflow( + { + config: { ...inlinePayload.config, skills: [{ type: 'skill', id: 'skill_inline' }] }, + skills: { skill_inline: embedded }, + }, + 'hello', + 'execution-1', + 'thread-1', + projectId, + userId, + 'production', + ); + + expect(reconstructionService.reconstructFromResolvedSource).toHaveBeenCalledWith( + expect.objectContaining({ skills: { skill_inline: embedded } }), + ); + for (const read of [ + skillRefs.refsForDraft, + skillRefs.refsForVersion, + skillRefs.readDraft, + skillRefs.readVersion, + skillRefs.skillsForRefs, + skillService.resolveForAgentDraft, + skillService.resolvePinned, + skillService.checkRefs, + skillService.create, + ]) { + expect(read).not.toHaveBeenCalled(); + } + }); + it('compiles from the embedded config, records no session, and tracks inline telemetry', async () => { const { service, @@ -1229,7 +1275,12 @@ describe('AgentWorkflowExecutionService', () => { url: 'https://mcp.example.com', transport: 'streamableHttp', authentication: 'none', - approval: { mode: 'global' }, + toolPermissions: { + categories: { + read: 'always_allow', + write: 'require_approval', + }, + }, }, ], }, @@ -1499,7 +1550,10 @@ describe('AgentWorkflowExecutionService', () => { { prepareForEval }, ); - expect(prepareForEval).toHaveBeenCalledWith(schema, { hasChatIntegrations: true }); + expect(prepareForEval).toHaveBeenCalledWith( + { ...schema, skills: [] }, + { hasChatIntegrations: true }, + ); const [entity, , , , , passedInstrumentation] = reconstructionService.reconstructFromAgentEntity.mock.calls[0]; expect(entity.agent.schema).toEqual(evalConfig); diff --git a/packages/cli/src/modules/agents/__tests__/agent.repository.test.ts b/packages/cli/src/modules/agents/__tests__/agent.repository.test.ts index abbfe59cd3e..4894d736be3 100644 --- a/packages/cli/src/modules/agents/__tests__/agent.repository.test.ts +++ b/packages/cli/src/modules/agents/__tests__/agent.repository.test.ts @@ -382,6 +382,58 @@ describe('AgentRepository', () => { }); }); + describe('findWithIntegrationType', () => { + const makeQb = (rows: unknown[]) => ({ + select: vi.fn().mockReturnThis(), + where: vi.fn().mockReturnThis(), + getMany: vi.fn().mockResolvedValue(rows), + }); + + it('pre-filters in SQL on the quoted type and selects only id and integrations', async () => { + const mockQb = makeQb([]); + vi.spyOn(repository, 'createQueryBuilder').mockReturnValue(mockQb as never); + + await repository.findWithIntegrationType('whatsapp'); + + expect(mockQb.select).toHaveBeenCalledWith(['agent.id', 'agent.integrations']); + expect(mockQb.where).toHaveBeenCalledWith( + expect.stringContaining('CAST(agent.integrations AS TEXT) LIKE :pattern'), + { pattern: '%"whatsapp"%' }, + ); + }); + + it('escapes LIKE metacharacters in the type', async () => { + const mockQb = makeQb([]); + vi.spyOn(repository, 'createQueryBuilder').mockReturnValue(mockQb as never); + + await repository.findWithIntegrationType('my_type%'); + + expect(mockQb.where).toHaveBeenCalledWith(expect.any(String), { + pattern: '%"my\\_type\\%"%', + }); + }); + + it('keeps only agents with an exactly matching integration type', async () => { + const whatsAppAgent = { + id: 'agent-whatsapp', + integrations: [ + { type: 'telegram', credentialId: 'cred-1' }, + { type: 'whatsapp', credentialId: 'cred-2' }, + ], + } as Agent; + vi.spyOn(repository, 'createQueryBuilder').mockReturnValue( + makeQb([ + whatsAppAgent, + // The SQL pre-filter can match the string in another field. + { id: 'agent-telegram', integrations: [{ type: 'telegram', credentialId: 'whatsapp' }] }, + { id: 'agent-null', integrations: null }, + ]) as never, + ); + + expect(await repository.findWithIntegrationType('whatsapp')).toEqual([whatsAppAgent]); + }); + }); + describe('findByIntegrationCredential', () => { const makeAgent = (id: string, integrations: AgentIntegrationConfig[]) => ({ id, integrations }) as Agent; diff --git a/packages/cli/src/modules/agents/__tests__/agents-builder-tools.service.test.ts b/packages/cli/src/modules/agents/__tests__/agents-builder-tools.service.test.ts index 2033e095905..d9cdb305f27 100644 --- a/packages/cli/src/modules/agents/__tests__/agents-builder-tools.service.test.ts +++ b/packages/cli/src/modules/agents/__tests__/agents-builder-tools.service.test.ts @@ -1742,7 +1742,6 @@ describe('AgentsBuilderToolsService', () => { expect(tool.systemInstruction).toContain('vague or placeholder skill'); expect(tool.systemInstruction).toContain('ask the user clarifying'); expect(tool.systemInstruction).toContain('Gotchas'); - expect(tool.systemInstruction).toContain('exact target-agent tool names'); expect(tool.systemInstruction).toContain('references are not automatically loaded'); expect(tool.systemInstruction).toContain( 'instructions must say exactly when to load each one', @@ -2032,7 +2031,7 @@ describe('AgentsBuilderToolsService', () => { }); }); - it('uses null to remove optional list fields and rejects ambiguous empty arrays', async () => { + it('uses null to remove the references and rejects an ambiguous empty array', async () => { const { service, agentsService } = makeService(); agentsService.updateSkill.mockResolvedValue({ id: 'skill_create_tickets', @@ -2055,7 +2054,7 @@ describe('AgentsBuilderToolsService', () => { { skillId: 'skill_create_tickets', baseSkillHash: 'skill-hash-0', - updates: { allowedTools: null, references: null }, + updates: { references: null }, }, ctx, ); @@ -2064,7 +2063,7 @@ describe('AgentsBuilderToolsService', () => { agentId, projectId, 'skill_create_tickets', - { allowedTools: undefined, references: undefined }, + { references: undefined }, { user, modifiedBy: 'builder' }, 'skill-hash-0', undefined, @@ -2074,9 +2073,13 @@ describe('AgentsBuilderToolsService', () => { safeParse: (input: unknown) => { success: boolean }; }; const baseInput = { skillId: 'skill_create_tickets', baseSkillHash: 'skill-hash-0' }; - expect(inputSchema.safeParse({ ...baseInput, updates: { allowedTools: [] } }).success).toBe( + expect(inputSchema.safeParse({ ...baseInput, updates: { references: [] } }).success).toBe( false, ); + // Skills do not take allowed tools. + expect( + inputSchema.safeParse({ ...baseInput, updates: { allowedTools: ['search'] } }).success, + ).toBe(false); expect(inputSchema.safeParse({ ...baseInput, updates: {} }).success).toBe(false); expect( inputSchema.safeParse({ diff --git a/packages/cli/src/modules/agents/__tests__/agents-credential-provider.test.ts b/packages/cli/src/modules/agents/__tests__/agents-credential-provider.test.ts index e8df1eb7bbf..0ff72b1fcf2 100644 --- a/packages/cli/src/modules/agents/__tests__/agents-credential-provider.test.ts +++ b/packages/cli/src/modules/agents/__tests__/agents-credential-provider.test.ts @@ -69,6 +69,7 @@ describe('AgentsCredentialProvider', () => { ]); expect(credentialsService.getCredentialsAUserCanUseInAWorkflow).toHaveBeenCalledWith(user, { projectId: 'project-1', + excludePersonalRoute: true, }); expect(credentialsService.findAllCredentialIdsForProject).not.toHaveBeenCalled(); }); diff --git a/packages/cli/src/modules/agents/__tests__/agents-list.controller.test.ts b/packages/cli/src/modules/agents/__tests__/agents-list.controller.test.ts index 5eadcbdb795..9217f21b7c4 100644 --- a/packages/cli/src/modules/agents/__tests__/agents-list.controller.test.ts +++ b/packages/cli/src/modules/agents/__tests__/agents-list.controller.test.ts @@ -21,11 +21,11 @@ describe('AgentsListController', () => { const res = mock(); const query = { skip: 0, take: 50, sortBy: 'updatedAt:desc' } as never; - agentsService.findByUserMembershipPaginated.mockResolvedValue(response); + agentsService.findListableByUserPaginated.mockResolvedValue(response); await controller.list(req, res, query); - expect(agentsService.findByUserMembershipPaginated).toHaveBeenCalledWith(user, query); + expect(agentsService.findListableByUserPaginated).toHaveBeenCalledWith(user, query); expect(agentsService.findChatReachableByUserPaginated).not.toHaveBeenCalled(); expect(res.json).toHaveBeenCalledWith(response); }); @@ -35,11 +35,11 @@ describe('AgentsListController', () => { const res = mock(); const query = { skip: 0, take: 10, filter: { query: 'support' } } as never; - agentsService.findByUserMembershipPaginated.mockResolvedValue({ count: 0, data: [] } as never); + agentsService.findListableByUserPaginated.mockResolvedValue({ count: 0, data: [] } as never); await controller.list(req, res, query); - expect(agentsService.findByUserMembershipPaginated).toHaveBeenCalledWith(user, query); + expect(agentsService.findListableByUserPaginated).toHaveBeenCalledWith(user, query); }); it.each([true, false])('serves the chat list when availableInChat is %s', async (value) => { @@ -53,7 +53,7 @@ describe('AgentsListController', () => { await controller.list(req, res, query); expect(agentsService.findChatReachableByUserPaginated).toHaveBeenCalledWith(user, query); - expect(agentsService.findByUserMembershipPaginated).not.toHaveBeenCalled(); + expect(agentsService.findListableByUserPaginated).not.toHaveBeenCalled(); expect(res.json).toHaveBeenCalledWith(response); }); @@ -63,7 +63,7 @@ describe('AgentsListController', () => { const query = { skip: 0, take: 50 } as never; const emptyResponse = { count: 0, data: [] } as never; - agentsService.findByUserMembershipPaginated.mockResolvedValue(emptyResponse); + agentsService.findListableByUserPaginated.mockResolvedValue(emptyResponse); await controller.list(req, res, query); diff --git a/packages/cli/src/modules/agents/__tests__/agents-service-reconstruct-gating.test.ts b/packages/cli/src/modules/agents/__tests__/agents-service-reconstruct-gating.test.ts index 36f50dea0cf..645ade85d2f 100644 --- a/packages/cli/src/modules/agents/__tests__/agents-service-reconstruct-gating.test.ts +++ b/packages/cli/src/modules/agents/__tests__/agents-service-reconstruct-gating.test.ts @@ -26,6 +26,7 @@ import type { CredentialsFinderService } from '@n8n/backend-services'; import type { EphemeralNodeExecutor } from '@/node-execution'; import type { OauthService } from '@/oauth/oauth.service'; import type { AiService } from '@/services/ai.service'; +import type { CredentialsService } from '@/credentials/credentials.service'; import type { WorkflowFinderService } from '@/workflows/workflow-finder.service'; import type { AgentChatAttachmentService } from '../agent-chat-attachment.service'; @@ -141,6 +142,7 @@ function makeReconstructionService( mock(), mock(), mock(), + mock(), ); } @@ -227,6 +229,44 @@ describe('AgentRuntimeReconstructionService.reconstructFromAgentEntity — MCP w expect(buildMcpClientForServerMock.mock.calls[1][0]).toMatchObject({ name: 'fs' }); }); + it.each([ + ['inline', true], + ['top-level', false], + ['sub-agent', false], + ] as const)( + 'marks MCP tool permissions as non-interrupting only for %s runtimes: %s', + async (runtimeProfile, nonInterrupting) => { + const { service, credentialProvider } = setup(); + + await service.reconstructFromResolvedSource({ + config: { + name: 'Agent', + model: 'anthropic/claude-sonnet-4-5', + instructions: 'Help', + mcpServers: [ + { + name: 'github', + url: 'https://api.example.test/mcp', + transport: 'streamableHttp', + authentication: 'none', + }, + ], + }, + memoryOwnerAgentId: 'agent-1', + projectId: 'project-1', + credentialProvider, + toolDescriptors: {}, + toolCodeByName: {}, + skills: {}, + runtimeProfile, + runType: 'production', + }); + + const deps = buildMcpClientForServerMock.mock.calls[0][1] as { nonInterrupting?: boolean }; + expect(deps.nonInterrupting).toBe(nonInterrupting); + }, + ); + it('forwards resolved MCP tool names through eval instrumentation', async () => { const { service, credentialProvider } = setup(); const onMcpToolCallSettled = vi.fn(); diff --git a/packages/cli/src/modules/agents/__tests__/agents.controller.test.ts b/packages/cli/src/modules/agents/__tests__/agents.controller.test.ts index d731df42e82..13add393d2b 100644 --- a/packages/cli/src/modules/agents/__tests__/agents.controller.test.ts +++ b/packages/cli/src/modules/agents/__tests__/agents.controller.test.ts @@ -30,6 +30,7 @@ function makeController({ credentialsService = mock(), agentDefaultModelResolverService = mock(), collaborationService = mock(), + skillRefs = createAgentSkillRefsService(), }: { agentsService?: Mocked< Pick< @@ -42,12 +43,13 @@ function makeController({ credentialsService?: Mocked; agentDefaultModelResolverService?: Mocked; collaborationService?: Mocked; + skillRefs?: ReturnType; } = {}) { const agentRunnableStateService = new AgentRunnableStateService( credentialsService, agentValidationService, agentPublishService, - createAgentSkillRefsService(), + skillRefs, ); return { @@ -264,15 +266,19 @@ describe('AgentsController agent resource', () => { mock>(); const agentPublishService = mock(); const agentValidationService = mock(); + const triage = { + name: 'Triage', + description: 'Triage requests', + instructions: 'Route each request.', + }; agentsService.findById.mockResolvedValue({ id: 'agent-1', projectId: 'project-1', - skills: { - triage: { - name: 'Triage', - description: 'Triage requests', - instructions: 'Route each request.', - }, + schema: { + name: 'Agent', + model: '', + instructions: '', + skills: [{ type: 'skill', id: 'triage' }], }, } as never); agentValidationService.validateLoadedAgentConfiguration.mockResolvedValue({ @@ -285,6 +291,7 @@ describe('AgentsController agent resource', () => { agentsService: agentsService as never, agentPublishService, agentValidationService, + skillRefs: createAgentSkillRefsService({ triage }), }); const result = await controller.get( @@ -302,6 +309,8 @@ describe('AgentsController agent resource', () => { isRunnable: true, }), ); + // The skill bodies come from the skills hub, not from the agent row. + expect(result.skills).toEqual({ triage }); expect(result.skillHashes.triage).toMatch(/^[a-f0-9]{64}$/); expect(agentValidationService.validateLoadedAgentConfiguration).toHaveBeenCalledWith( expect.objectContaining({ id: 'agent-1' }), diff --git a/packages/cli/src/modules/agents/__tests__/agents.module.test.ts b/packages/cli/src/modules/agents/__tests__/agents.module.test.ts index 2f73d8f7594..5e1e7a6b47f 100644 --- a/packages/cli/src/modules/agents/__tests__/agents.module.test.ts +++ b/packages/cli/src/modules/agents/__tests__/agents.module.test.ts @@ -11,6 +11,7 @@ import { FavoriteResourceResolverRegistry } from '@n8n/backend-services'; import { SandboxSettingsService } from '@/services/sandbox-settings.service'; import { AgentUsageProviderProxy } from '@/modules/workflow-index/agent-usage-provider-proxy.service'; +import { AgentChannelMediaRetentionTask } from '../agent-channel-media-retention.task'; import { AgentCheckpointPruningTask } from '../agent-checkpoint-pruning.task'; import { AgentInterruptedExecutionSweepTask } from '../agent-interrupted-execution-sweep.task'; import { AgentsSettingsService } from '../agents-settings.service'; @@ -28,12 +29,14 @@ import { LinearIntegration } from '../integrations/platforms/linear-integration' import { N8nChatIntegration } from '../integrations/platforms/n8n-chat-integration'; import { SlackIntegration } from '../integrations/platforms/slack/slack-integration'; import { TelegramIntegration } from '../integrations/platforms/telegram-integration'; -import { WhatsAppIntegration } from '../integrations/platforms/whatsapp-integration'; +import { WhatsAppIntegration } from '../integrations/platforms/whatsapp/whatsapp-integration'; import { AgentExecutionLogStore } from '../execution-log/agent-execution-log-store'; import { AgentBudgetSpendRepository } from '../repositories/agent-budget-spend.repository'; import { AgentHistoryRepository } from '../repositories/agent-history.repository'; import { AgentCredentialDependencyRepository } from '../repositories/agent-credential-dependency.repository'; import { AgentWorkflowDependencyRepository } from '../repositories/agent-workflow-dependency.repository'; +import { SkillsHubRollout } from '../skills/skills-hub-rollout'; +import { SkillsHubStartupCopy } from '../skills/skills-hub-startup-copy'; import { AgentRepository } from '../repositories/agent.repository'; import { AgentSecureRuntime } from '../runtime/agent-secure-runtime'; @@ -59,6 +62,8 @@ function setUpContainerForInit() { Container.set(AgentSecureRuntime, mock()); Container.set(AgentRepository, mock()); + Container.set(SkillsHubRollout, mock()); + Container.set(SkillsHubStartupCopy, mock()); Container.set(FavoriteResourceResolverRegistry, mock()); Container.set(AgentCredentialDependencyRepository, mock()); Container.set(AgentWorkflowDependencyRepository, mock()); @@ -113,10 +118,11 @@ describe('AgentsModule', () => { }); describe('systemTasks()', () => { - it('registers the pruning and the sweep tasks', async () => { + it('registers the pruning, sweep and media retention tasks', async () => { await expect(module.systemTasks()).resolves.toEqual([ AgentCheckpointPruningTask, AgentInterruptedExecutionSweepTask, + AgentChannelMediaRetentionTask, ]); }); }); diff --git a/packages/cli/src/modules/agents/__tests__/agents.service.test.ts b/packages/cli/src/modules/agents/__tests__/agents.service.test.ts index 16b678bd810..c798ee434be 100644 --- a/packages/cli/src/modules/agents/__tests__/agents.service.test.ts +++ b/packages/cli/src/modules/agents/__tests__/agents.service.test.ts @@ -26,7 +26,7 @@ import type { AgentRepository } from '../repositories/agent.repository'; import type { SubAgentCleanupService } from '../sub-agents/sub-agent-cleanup.service'; import type { CredentialsService } from '@/credentials/credentials.service'; import type { AgentPolicyService } from '../agent-policy.service'; -import { createAgentSkillRefsService, storedSkillRefs } from './test-utils/stored-agent-config'; +import { createAgentSkillRefsService } from './test-utils/stored-agent-config'; const agentId = 'agent-1'; const actor = { kind: 'user', user: { id: 'user-1' } } as const; @@ -56,6 +56,7 @@ function makeAgent(overrides: Partial = {}): Agent { } function makeService() { + const skillRefs = createAgentSkillRefsService(); const agentRepository = mock(); const projectRelationRepository = mock(); const agentKnowledgeService = mock(); @@ -104,12 +105,13 @@ function makeService() { projectScopeService, agentsSettingsService, agentPolicyService, - createAgentSkillRefsService(agentRepository), + skillRefs, transactionRunner, ); return { service, + skillRefs, agentPolicyService, agentRepository, projectRelationRepository, @@ -139,7 +141,7 @@ describe('AgentsService', () => { }); it('creates a draft agent without a default model or credential', async () => { - const { service, agentRepository } = makeService(); + const { service, agentRepository, skillRefs } = makeService(); const saved = makeAgent(); mockCreateReturning(agentRepository, saved); @@ -164,8 +166,7 @@ describe('AgentsService', () => { availableInMCP: false, }); // The skill refs of the new draft go through the skill refs seam. - expect(storedSkillRefs(saved)).toEqual([]); - expect(agentRepository.updateDraftSchema).toHaveBeenCalledWith(saved, expect.anything()); + expect(skillRefs.createDraftRefs).toHaveBeenCalledWith(saved, [], {}, null, expect.anything()); }); it('creates an agent with a resolved default model and credential', async () => { @@ -257,16 +258,19 @@ describe('AgentsService', () => { }); }); - it('seeds skill bodies onto the entity alongside their schema refs', async () => { - const { service, agentRepository } = makeService(); + it('passes seeded skill bodies to the skill refs seam, not to the entity', async () => { + const { service, agentRepository, skillRefs } = makeService(); const saved = makeAgent(); mockCreateReturning(agentRepository, saved); const skills = { skill_abc: { name: 'Triage', description: '', instructions: 'Sort tickets.' }, }; + const skillCreator = mock({ id: 'user-1' }); + await service.create(projectId, 'Support Agent', { actor, + skillCreator, schema: { name: 'Support Agent', model: 'anthropic/claude-sonnet-4-5', @@ -277,18 +281,28 @@ describe('AgentsService', () => { }); const [entity] = agentRepository.create.mock.calls[0]; - expect(entity.skills).toEqual(skills); + expect(entity).not.toHaveProperty('skills'); + expect(skillRefs.createDraftRefs).toHaveBeenCalledWith( + saved, + [{ type: 'skill', id: 'skill_abc' }], + skills, + skillCreator, + expect.anything(), + ); }); - it('stores the skill refs of a seeded config in order, with the enabled flags', async () => { - const { service, agentRepository } = makeService(); + it('stores the skill refs of a seeded config in order', async () => { + const { service, agentRepository, skillRefs: refsService } = makeService(); const saved = makeAgent(); mockCreateReturning(agentRepository, saved); const skillRefs = [ { type: 'skill' as const, id: 'zeta' }, - { type: 'skill' as const, id: 'alpha', enabled: false }, - { type: 'skill' as const, id: 'mid', enabled: true }, + { type: 'skill' as const, id: 'alpha' }, + { type: 'skill' as const, id: 'mid' }, ]; + // Refs to skills that are in the hub stay, also without a user. + const skill = { name: 'Skill', description: 'A skill', instructions: 'Do it.' }; + refsService.bodies = { zeta: skill, alpha: skill, mid: skill }; await service.create(projectId, 'Support Agent', { actor, @@ -302,10 +316,10 @@ describe('AgentsService', () => { const [entity] = agentRepository.create.mock.calls[0]; expect(entity.schema).not.toHaveProperty('skills'); - expect(storedSkillRefs(saved)).toEqual(skillRefs); + await expect(refsService.refsForDraft(saved, {})).resolves.toEqual(skillRefs); // The insert and the skill refs write share one transaction. const [[, insertCtx]] = agentRepository.insertNew.mock.calls; - const [[, refsCtx]] = agentRepository.updateDraftSchema.mock.calls; + const [[, , , , refsCtx]] = refsService.createDraftRefs.mock.calls; expect(refsCtx).toBe(insertCtx); }); @@ -1134,33 +1148,42 @@ describe('AgentsService', () => { }); }); - describe('findByUserMembershipPaginated', () => { + describe('findListableByUserPaginated', () => { const user = { id: 'user-1' } as unknown as User; - it('uses bare project membership and does not consult the scope service', async () => { + it('scopes to agent:list, the scope the project list route requires', async () => { const { service, agentRepository, projectRelationRepository, projectScopeService } = makeService(); - projectRelationRepository.findAllByUser.mockResolvedValue([ - { projectId: 'project-1' }, - { projectId: 'project-2' }, - ] as never); + projectScopeService.getProjectIds.mockResolvedValue(['project-1', 'project-2']); agentRepository.findByProjectIdsPaginated.mockResolvedValue({ count: 0, data: [] }); const options = { skip: 0, take: 10 } as never; - await service.findByUserMembershipPaginated(user, options); + await service.findListableByUserPaginated(user, options); - expect(projectRelationRepository.findAllByUser).toHaveBeenCalledWith('user-1'); - expect(projectScopeService.getProjectIds).not.toHaveBeenCalled(); + expect(projectScopeService.getProjectIds).toHaveBeenCalledWith(user, ['agent:list']); + expect(projectRelationRepository.findAllByUser).not.toHaveBeenCalled(); expect(agentRepository.findByProjectIdsPaginated).toHaveBeenCalledWith( ['project-1', 'project-2'], options, ); }); + + it('passes a null project scope through, so a global role sees every project', async () => { + const { service, agentRepository, projectScopeService } = makeService(); + projectScopeService.getProjectIds.mockResolvedValue(null); + agentRepository.findByProjectIdsPaginated.mockResolvedValue({ count: 0, data: [] }); + const options = { skip: 0, take: 10 } as never; + + await service.findListableByUserPaginated(user, options); + + expect(agentRepository.findByProjectIdsPaginated).toHaveBeenCalledWith(null, options); + }); }); describe('getCapabilitySummary', () => { it('projects model, channels, tools, skills and tasks into per-item labels', async () => { - const { service, agentRepository, agentTaskRepository } = makeService(); + const { service, agentRepository, agentTaskRepository, skillRefs } = makeService(); + skillRefs.bodies.s1 = { name: 'Triage', description: '', instructions: '' }; agentRepository.findByIdAndProjectId.mockResolvedValue( makeAgent({ name: 'Support Agent', @@ -1193,7 +1216,6 @@ describe('AgentsService', () => { { type: 'telegram', credentialId: 'cred-2' }, ], tools: { c1: { code: '', descriptor: { name: 'Refund tool' } } }, - skills: { s1: { name: 'Triage', description: '', instructions: '' } }, } as unknown as Partial), ); agentTaskRepository.findByAgentId.mockResolvedValue([ diff --git a/packages/cli/src/modules/agents/__tests__/budget-guardrail.test.ts b/packages/cli/src/modules/agents/__tests__/budget-guardrail.test.ts index 774292f4804..af159f83b97 100644 --- a/packages/cli/src/modules/agents/__tests__/budget-guardrail.test.ts +++ b/packages/cli/src/modules/agents/__tests__/budget-guardrail.test.ts @@ -144,6 +144,69 @@ describe('withBudgetGuardrail', () => { expect(budgetAlert.notifyMonthlyThreshold).toHaveBeenCalledOnce(); }); + it('installs the notice sink without a hook when no budget bucket is on', () => { + const onNotice = vi.fn(); + const attached = withBudgetGuardrail(base, { + ledger, + sessionId: 'thread-1', + agentId: 'agent-1', + onNotice, + }); + + expect(attached).not.toBe(base); + expect(attached.guardrails?.hooks).toEqual([]); + const sink = attached.guardrails?.onNotice; + expect(sink).toBeDefined(); + sink?.({ code: 'budget.alert', agentId: 'child-1' }); + expect(onNotice).toHaveBeenCalledWith({ code: 'budget.alert', agentId: 'child-1' }); + sink?.({ code: 'pii.block' }); + expect(onNotice).toHaveBeenCalledTimes(1); + }); + + it('exposes a notice sink that forwards budget codes and drops others', () => { + const onNotice = vi.fn(); + const attached = withBudgetGuardrail(base, { + ledger, + budget: { ...saved, enabled: true }, + sessionId: 'thread-1', + agentId: 'agent-1', + onNotice, + }); + + const sink = attached.guardrails?.onNotice; + expect(sink).toBeDefined(); + sink?.({ code: 'budget.session', agentId: 'child-1' }); + expect(onNotice).toHaveBeenCalledWith({ code: 'budget.session', agentId: 'child-1' }); + sink?.({ code: 'pii.block' }); + expect(onNotice).toHaveBeenCalledTimes(1); + }); + + it('adds no sink when no input notice is given', () => { + const attached = withBudgetGuardrail(base, { + ledger, + budget: { ...saved, enabled: true }, + sessionId: 'thread-1', + agentId: 'agent-1', + }); + + expect(attached.guardrails?.onNotice).toBeUndefined(); + }); + + it('keeps an existing guardrails onNotice when no input notice is given', () => { + const existing = vi.fn(); + const attached = withBudgetGuardrail( + { ...base, guardrails: { hooks: [], onNotice: existing } }, + { + ledger, + budget: { ...saved, enabled: true }, + sessionId: 'thread-1', + agentId: 'agent-1', + }, + ); + + expect(attached.guardrails?.onNotice).toBe(existing); + }); + it('emails the saved agent when a workflow run crosses the alert on a telemetry id', async () => { const freshLedger = spendLedger(); const attached = withBudgetGuardrail(base, { diff --git a/packages/cli/src/modules/agents/__tests__/from-json-config.test.ts b/packages/cli/src/modules/agents/__tests__/from-json-config.test.ts index a7524e0097b..e21ffdbce51 100644 --- a/packages/cli/src/modules/agents/__tests__/from-json-config.test.ts +++ b/packages/cli/src/modules/agents/__tests__/from-json-config.test.ts @@ -330,13 +330,39 @@ describe('buildFromJson()', () => { expect(agent.snapshot.tools.some((tool) => tool.name === 'load_skill')).toBe(true); }); + // Agents can no longer disable a skill. The schema strips a stale `enabled: false`, so the + // runtime loads every ref it gets. Disabled refs are detached before they reach it. + it('loads a skill whose ref still says enabled: false', async () => { + const config = AgentJsonConfigSchema.parse( + makeConfig({ + skills: [{ type: 'skill', id: 'summarize_notes', enabled: false } as never], + }), + ); + expect(config.skills).toEqual([{ type: 'skill', id: 'summarize_notes' }]); + + const agent = await buildFromJson( + config, + {}, + { + toolExecutor: makeMockToolExecutor(), + credentialProvider: makeMockCredentialProvider(), + memoryFactory: makeMockMemoryFactory(), + skills: { + summarize_notes: { + name: 'Summarize notes', + description: 'Use for meeting notes and transcripts', + instructions: 'Extract decisions and action items.', + }, + }, + }, + ); + + expect(agent.snapshot.tools.some((tool) => tool.name === 'load_skill')).toBe(true); + }); + it('wires load_skill for attached skills and returns the selected skill body on demand', async () => { const config = makeConfig({ - skills: [ - { type: 'skill', id: 'summarize_notes' }, - { type: 'skill', id: 'unused_skill', enabled: false }, - { type: 'skill', id: 'missing_skill', enabled: false }, - ], + skills: [{ type: 'skill', id: 'summarize_notes' }], }); const agent = await buildFromJson( @@ -2113,38 +2139,27 @@ describe('AgentJsonConfigSchema', () => { expect(() => AgentJsonConfigSchema.parse({ ...base, mcpServers: servers })).toThrow(); }); - it('parses an allow-mode toolFilter', () => { + it('parses MCP tool permissions', () => { const parsed = AgentJsonConfigSchema.parse({ ...base, mcpServers: [ { name: 'github', url: 'https://a.example.test/mcp', - toolFilter: { mode: 'allow', tools: ['search_repositories'] }, + toolPermissions: { + categories: { read: 'always_allow', write: 'require_approval' }, + tools: { delete_repository: 'blocked' }, + }, }, ], }); - expect(parsed.mcpServers?.[0].toolFilter).toEqual({ - mode: 'allow', - tools: ['search_repositories'], + expect(parsed.mcpServers?.[0].toolPermissions).toEqual({ + categories: { read: 'always_allow', write: 'require_approval' }, + tools: { delete_repository: 'blocked' }, }); }); - it('parses approval mode "global"', () => { - const parsed = AgentJsonConfigSchema.parse({ - ...base, - mcpServers: [ - { - name: 'github', - url: 'https://a.example.test/mcp', - approval: { mode: 'global' }, - }, - ], - }); - expect(parsed.mcpServers?.[0].approval).toEqual({ mode: 'global' }); - }); - - it('rejects approval mode "selected" with an empty tools array', () => { + it('rejects an unknown MCP tool permission', () => { expect(() => AgentJsonConfigSchema.parse({ ...base, @@ -2152,7 +2167,9 @@ describe('AgentJsonConfigSchema', () => { { name: 'github', url: 'https://a.example.test/mcp', - approval: { mode: 'selected', tools: [] }, + toolPermissions: { + categories: { read: 'always_allow', write: 'ask' }, + }, }, ], }), diff --git a/packages/cli/src/modules/agents/__tests__/instance-ai-agent-context.adapter.test.ts b/packages/cli/src/modules/agents/__tests__/instance-ai-agent-context.adapter.test.ts index e504acba9bd..c9e6682a1f9 100644 --- a/packages/cli/src/modules/agents/__tests__/instance-ai-agent-context.adapter.test.ts +++ b/packages/cli/src/modules/agents/__tests__/instance-ai-agent-context.adapter.test.ts @@ -12,12 +12,13 @@ import type { AgentExecutionService, ThreadListItem } from '../agent-execution.s import type { AgentIntegrationPersistenceService } from '../agent-integration-persistence.service'; import type { AgentSkillsService } from '../agent-skills.service'; import type { AgentTaskService } from '../agent-task.service'; +import type { AgentsSettingsService } from '../agents-settings.service'; import type { AgentsToolsService } from '../agents-tools.service'; import type { AgentsService } from '../agents.service'; import type { AttachableWorkflowsService } from '../attachable-workflows.service'; import type { Agent } from '../entities/agent.entity'; import { InstanceAiAgentContextAdapterService } from '../instance-ai-agent-context.adapter'; -import { createAgentSkillRefsService } from './test-utils/stored-agent-config'; +import { createAgentSkillRefsService, storedAgentConfig } from './test-utils/stored-agent-config'; vi.mock('@/permissions.ee/check-access', () => ({ userHasScopes: vi.fn() })); @@ -30,6 +31,9 @@ function makeService() { const attachableWorkflowsService = mock(); const mcpRegistryService = mock(); const agentsToolsService = mock(); + const agentSkillRefs = createAgentSkillRefsService(); + const agentsSettingsService = mock(); + agentsSettingsService.assertEnabled.mockResolvedValue(undefined); const service = new InstanceAiAgentContextAdapterService( agentsService, agentSkillsService, @@ -39,7 +43,8 @@ function makeService() { attachableWorkflowsService, mcpRegistryService, agentsToolsService, - createAgentSkillRefsService(), + agentSkillRefs, + agentsSettingsService, ); return { service, @@ -51,6 +56,8 @@ function makeService() { attachableWorkflowsService, mcpRegistryService, agentsToolsService, + agentSkillRefs, + agentsSettingsService, }; } @@ -74,8 +81,22 @@ describe('InstanceAiAgentContextAdapterService', () => { vi.mocked(userHasScopes).mockResolvedValue(true); }); + it('rejects lookups when Agents are turned off', async () => { + const { service, agentsService, agentsSettingsService } = makeService(); + agentsSettingsService.assertEnabled.mockRejectedValue( + new ForbiddenError( + 'Agents are disabled. Ask an instance admin to enable them in Settings > Agents.', + ), + ); + + await expect( + service.createReader(user, 'project-1').lookup({ type: 'config', agentId: 'agent-1' }), + ).rejects.toThrow(UserError); + expect(agentsService.findById).not.toHaveBeenCalled(); + }); + it('labels config as the current draft and includes publication state', async () => { - const { service, agentsService } = makeService(); + const { service, agentsService, agentSkillRefs } = makeService(); agentsService.findById.mockResolvedValue(agent); const result = await service.createReader(user, 'project-1').lookup({ @@ -84,6 +105,8 @@ describe('InstanceAiAgentContextAdapterService', () => { }); expect(agentsService.findById).toHaveBeenCalledWith('agent-1', 'project-1'); + // The config needs the skill refs, not the skill bodies. + expect(agentSkillRefs.skillsForRefs).not.toHaveBeenCalled(); expect(result).toMatchObject({ configState: 'current-draft', config: { name: 'Support Agent', model: '', instructions: 'Help users.' }, @@ -233,6 +256,33 @@ describe('InstanceAiAgentContextAdapterService', () => { await expect(lookup).rejects.toThrow(error.message); }); + it('lists the hub skills attached to the agent', async () => { + const { service, agentsService, agentSkillRefs } = makeService(); + agentSkillRefs.bodies.notes = { + name: 'Notes', + description: 'Take notes', + instructions: 'Write notes.', + }; + agentsService.findById.mockResolvedValue({ + ...agent, + schema: storedAgentConfig({ + name: 'Support Agent', + model: '', + instructions: 'Help users.', + skills: [{ type: 'skill', id: 'notes' }], + }), + } as Agent); + + const result = await service.createReader(user, 'project-1').lookup({ + type: 'skills', + agentId: 'agent-1', + }); + + expect(result).toEqual({ + skills: [{ id: 'notes', name: 'Notes', description: 'Take notes', attached: true }], + }); + }); + it('reads task enabled state from the current Agent config', async () => { const { service, agentsService, agentTaskService } = makeService(); agentsService.findById.mockResolvedValue({ diff --git a/packages/cli/src/modules/agents/__tests__/instance-ai-builder-delegate.adapter.test.ts b/packages/cli/src/modules/agents/__tests__/instance-ai-builder-delegate.adapter.test.ts index 99aa96e5e5f..f5061884273 100644 --- a/packages/cli/src/modules/agents/__tests__/instance-ai-builder-delegate.adapter.test.ts +++ b/packages/cli/src/modules/agents/__tests__/instance-ai-builder-delegate.adapter.test.ts @@ -257,69 +257,66 @@ describe('InstanceAiBuilderDelegateAdapterService', () => { }); describe('resumeBuild', () => { - it.each([true, false])( - 'resumes the saved builder call with Agents enabled %s', - async (enabled) => { - const { - delegate, - agentsBuilderService, - user, - credentialProvider, - credentialService, - settingsRepository, - } = setup(); - vi.spyOn(checkAccess, 'userHasScopes').mockResolvedValue(true); - settingsRepository.findByKeyInContext.mockResolvedValue( - mock({ value: String(enabled) }), - ); - const mcpTools = fakeMcpTools(); + it.each([true])('resumes the saved builder call with Agents enabled %s', async (enabled) => { + const { + delegate, + agentsBuilderService, + user, + credentialProvider, + credentialService, + settingsRepository, + } = setup(); + vi.spyOn(checkAccess, 'userHasScopes').mockResolvedValue(true); + settingsRepository.findByKeyInContext.mockResolvedValue( + mock({ value: String(enabled) }), + ); + const mcpTools = fakeMcpTools(); - const chunks: StreamChunk[] = [ - { type: 'text-delta', id: '1', delta: 'Using ' }, - { type: 'text-delta', id: '2', delta: 'Slack.' }, - ]; - agentsBuilderService.resumeBuild.mockReturnValue(asAsyncGenerator(chunks)); + const chunks: StreamChunk[] = [ + { type: 'text-delta', id: '1', delta: 'Using ' }, + { type: 'text-delta', id: '2', delta: 'Slack.' }, + ]; + agentsBuilderService.resumeBuild.mockReturnValue(asAsyncGenerator(chunks)); - const turn = await delegate.resumeBuild( - 'agent-1', - { runId: 'run-1', toolCallId: 'call-1', resumeData: { approved: true } }, - { - threadId: 'ia-builder:t:agent-1', - hostThreadId: 'thread-1', - runId: 'run-1', - modelConfig: 'anthropic/claude-sonnet-host-resolved', - abortSignal, - mcpTools, - }, - ); + const turn = await delegate.resumeBuild( + 'agent-1', + { runId: 'run-1', toolCallId: 'call-1', resumeData: { approved: true } }, + { + threadId: 'ia-builder:t:agent-1', + hostThreadId: 'thread-1', + runId: 'run-1', + modelConfig: 'anthropic/claude-sonnet-host-resolved', + abortSignal, + mcpTools, + }, + ); - const seen: unknown[] = []; - for await (const chunk of turn.fullStream) seen.push(chunk); + const seen: unknown[] = []; + for await (const chunk of turn.fullStream) seen.push(chunk); - expect(seen).toHaveLength(2); - await expect(turn.text).resolves.toBe('Using Slack.'); - expect(agentsBuilderService.resumeBuild).toHaveBeenCalledWith( - 'agent-1', - 'project-1', - 'run-1', - 'call-1', - { approved: true }, - credentialProvider, - credentialService, - user, - { - threadId: 'ia-builder:t:agent-1', - hostThreadId: 'thread-1', - runId: 'run-1', - modelConfig: 'anthropic/claude-sonnet-host-resolved', - abortSignal, - instructionsAddendum: INSTANCE_AI_BUILDER_ADDENDUM, - mcpTools, - onRequiredArtifact: expect.any(Function), - }, - ); - }, - ); + expect(seen).toHaveLength(2); + await expect(turn.text).resolves.toBe('Using Slack.'); + expect(agentsBuilderService.resumeBuild).toHaveBeenCalledWith( + 'agent-1', + 'project-1', + 'run-1', + 'call-1', + { approved: true }, + credentialProvider, + credentialService, + user, + { + threadId: 'ia-builder:t:agent-1', + hostThreadId: 'thread-1', + runId: 'run-1', + modelConfig: 'anthropic/claude-sonnet-host-resolved', + abortSignal, + instructionsAddendum: INSTANCE_AI_BUILDER_ADDENDUM, + mcpTools, + onRequiredArtifact: expect.any(Function), + }, + ); + }); it('enables deterministic model catalogs when an eval session resumes', async () => { const { delegate, agentsBuilderService } = setup({ useEvalModelCatalog: true }); @@ -372,6 +369,52 @@ describe('InstanceAiBuilderDelegateAdapterService', () => { }); }); + describe('when Agents are turned off after the delegate was created', () => { + function disableAgents(settingsRepository: ReturnType['settingsRepository']) { + settingsRepository.findByKeyInContext.mockResolvedValue(mock({ value: 'false' })); + } + + it('rejects a resumed build', async () => { + const { delegate, agentsBuilderService, settingsRepository } = setup(); + vi.spyOn(checkAccess, 'userHasScopes').mockResolvedValue(true); + disableAgents(settingsRepository); + + await expect( + delegate.resumeBuild( + 'agent-1', + { runId: 'run-1', toolCallId: 'call-1', resumeData: {} }, + { + threadId: 'ia-builder:t:agent-1', + hostThreadId: 'thread-1', + runId: 'run-1', + modelConfig: 'anthropic/claude-sonnet-host-resolved', + abortSignal, + }, + ), + ).rejects.toThrow(ForbiddenError); + expect(agentsBuilderService.resumeBuild).not.toHaveBeenCalled(); + }); + + it('rejects Agent reads', async () => { + const { delegate, agentConfig, settingsRepository } = setup(); + vi.spyOn(checkAccess, 'userHasScopes').mockResolvedValue(true); + disableAgents(settingsRepository); + + await expect(delegate.readAgentArtifact?.('agent-1')).rejects.toThrow(ForbiddenError); + expect(agentConfig.getConfig).not.toHaveBeenCalled(); + }); + + it('still cancels an open builder suspension', async () => { + const { delegate, agentsBuilderService, settingsRepository } = setup(); + vi.spyOn(checkAccess, 'userHasScopes').mockResolvedValue(true); + disableAgents(settingsRepository); + + await delegate.cancelOpenSuspension('agent-1', 'run-1'); + + expect(agentsBuilderService.cancelCheckpoint).toHaveBeenCalledWith('agent-1', 'run-1'); + }); + }); + describe('findOpenSuspensions', () => { function checkpointWith( pendingToolCalls: SerializableAgentState['pendingToolCalls'], diff --git a/packages/cli/src/modules/agents/__tests__/schema-text-serializer.test.ts b/packages/cli/src/modules/agents/__tests__/schema-text-serializer.test.ts index 401dac03b07..98ea471836d 100644 --- a/packages/cli/src/modules/agents/__tests__/schema-text-serializer.test.ts +++ b/packages/cli/src/modules/agents/__tests__/schema-text-serializer.test.ts @@ -1,6 +1,6 @@ import { McpServerConfigSchema } from '@n8n/api-types'; +import { zodSchemaToJsonSchema } from '@n8n/ai-utilities/json-schema'; import type { JSONSchema7 } from 'json-schema'; -import { zodToJsonSchema } from 'zod-to-json-schema'; import { jsonSchemaToCompactText } from '../json-config/schema-text-serializer'; @@ -472,19 +472,15 @@ describe('union types', () => { }); describe('mcp server schema regression', () => { - it('renders authentication and discriminated unions with descriptions', () => { - const schema = zodToJsonSchema(McpServerConfigSchema) as JSONSchema7; + it('renders authentication and tool permissions', () => { + const schema = zodSchemaToJsonSchema(McpServerConfigSchema); const output = jsonSchemaToCompactText(schema); expect(output).toContain( 'authentication?: "none" | "bearerAuth" | "headerAuth" | "multipleHeadersAuth" | "mcpOAuth2Api" | string [pattern: ^(?:oAuth2Api|.*OAuth2(?:Api)?)$] (default: "none") — Auth method. Named variants or an OAuth2 credential type returned by the registry', ); - expect(output).toContain( - 'toolFilter?: one of — Restricts which tools are surfaced. Tools matched by original un-prefixed name', - ); - expect(output).toContain( - 'approval?: one of — Human-in-the-loop approval. Absent = no approval required', - ); + expect(output).toContain('toolPermissions?: object'); + expect(output).toContain('read: "always_allow" | "require_approval" | "blocked" (required)'); expect(output).not.toContain('authentication?: one of '); expect(output).not.toContain('| ?: { }'); }); diff --git a/packages/cli/src/modules/agents/__tests__/skill-content-hash.test.ts b/packages/cli/src/modules/agents/__tests__/skill-content-hash.test.ts new file mode 100644 index 00000000000..e6f2a7dfa4b --- /dev/null +++ b/packages/cli/src/modules/agents/__tests__/skill-content-hash.test.ts @@ -0,0 +1,72 @@ +import { skillContentHash, type SkillContent } from '../skills/skill-content-hash'; + +const content: SkillContent = { + name: 'Brand voice', + description: 'Write in our voice', + instructions: 'Use short sentences.', + frontmatter: { 'allowed-tools': 'Read Bash(git diff:*)' }, + files: [ + { path: 'references/z.md', content: 'z' }, + { path: 'references/a.md', content: 'a' }, + ], +}; + +describe('skillContentHash', () => { + // The data migration (MigrateAgentSkillsToHub.contentHash, CONTEXT-225) must produce the + // same value for the same skill. Its test must pin this input to this literal too. + it('pins the hash that the data migration must also write', () => { + expect(skillContentHash(content)).toBe( + 'fb5a3e8555463ac71ac16733c2b9fdf41d0e15977ac1583646823b0d6d855ab2', + ); + }); + + it('ignores the order of the files', () => { + expect(skillContentHash({ ...content, files: [...content.files].reverse() })).toBe( + skillContentHash(content), + ); + }); + + // A locale-aware sort puts `b.md` first and gives a different hash than the migration. + it('sorts file paths by code unit, so an upper-case path comes first', () => { + const files = [ + { path: 'references/b.md', content: 'b' }, + { path: 'references/B.md', content: 'B' }, + ]; + + expect(skillContentHash({ ...content, files })).toBe( + '030387c0a4c961a2a79c3b896a18fb1b45c883b3ecb57e1a94e25898def497a4', + ); + }); + + it('ignores the order of the frontmatter keys', () => { + expect(skillContentHash({ ...content, frontmatter: { b: '2', a: '1' } })).toBe( + skillContentHash({ ...content, frontmatter: { a: '1', b: '2' } }), + ); + }); + + it('ignores the key order of nested frontmatter maps', () => { + expect( + skillContentHash({ ...content, frontmatter: { metadata: { b: 2, a: [{ y: 1, x: 2 }] } } }), + ).toBe( + skillContentHash({ ...content, frontmatter: { metadata: { a: [{ x: 2, y: 1 }], b: 2 } } }), + ); + }); + + it('keeps the order of frontmatter lists', () => { + expect(skillContentHash({ ...content, frontmatter: { tags: ['a', 'b'] } })).not.toBe( + skillContentHash({ ...content, frontmatter: { tags: ['b', 'a'] } }), + ); + }); + + it('changes when the name changes', () => { + expect(skillContentHash({ ...content, name: 'Brand tone' })).not.toBe( + skillContentHash(content), + ); + }); + + it('changes when a file changes', () => { + const files = [{ path: 'references/a.md', content: 'changed' }, content.files[0]]; + + expect(skillContentHash({ ...content, files })).not.toBe(skillContentHash(content)); + }); +}); diff --git a/packages/cli/src/modules/agents/__tests__/skill-names.test.ts b/packages/cli/src/modules/agents/__tests__/skill-names.test.ts new file mode 100644 index 00000000000..a0158e4ef7b --- /dev/null +++ b/packages/cli/src/modules/agents/__tests__/skill-names.test.ts @@ -0,0 +1,67 @@ +import { + findIntroducedNameClashes, + findNameClashGroups, + renameIntroducesClash, + skillNameKey, +} from '../skills/skill-names'; + +describe('skillNameKey', () => { + it.each([ + ['Brand voice', 'brand-voice'], + ['Brand voice', 'brand_voice'], + ['Brand voice', ' BRAND voice '], + ['Brand voice', 'brand -_ voice'], + ])('treats "%s" and "%s" as the same name', (left, right) => { + expect(skillNameKey(left)).toBe(skillNameKey(right)); + }); + + it('keeps other characters apart', () => { + expect(skillNameKey('Brand voice')).not.toBe(skillNameKey('Brand voices')); + expect(skillNameKey('brand.voice')).not.toBe(skillNameKey('brand voice')); + }); +}); + +describe('findIntroducedNameClashes', () => { + it('returns an added name that clashes with an existing name', () => { + expect(findIntroducedNameClashes(['Brand voice'], ['brand-voice', 'Pricing'])).toEqual([ + 'brand-voice', + ]); + }); + + it('returns an added name that clashes with another added name', () => { + expect(findIntroducedNameClashes([], ['Pricing', 'pricing'])).toEqual(['pricing']); + }); + + it('ignores clashes among the existing names', () => { + expect(findIntroducedNameClashes(['Pricing', 'pricing'], ['Brand voice'])).toEqual([]); + }); +}); + +describe('renameIntroducesClash', () => { + it('is true when the new name clashes with another skill of the agent', () => { + expect(renameIntroducesClash(['Pricing'], 'Prices', 'pricing')).toBe(true); + }); + + it('is false when the new name differs from the old one only in case or separators', () => { + expect(renameIntroducesClash(['brand-voice'], 'Brand voice', 'brand_voice')).toBe(false); + }); + + it('is false when no other skill has a similar name', () => { + expect(renameIntroducesClash(['Pricing'], 'Brand voice', 'Tone')).toBe(false); + }); +}); + +describe('findNameClashGroups', () => { + it('groups the names that clash, as written', () => { + expect( + findNameClashGroups(['Brand voice', 'Pricing', 'brand-voice', 'pricing', 'Tone']), + ).toEqual([ + ['Brand voice', 'brand-voice'], + ['Pricing', 'pricing'], + ]); + }); + + it('returns no group when all names differ', () => { + expect(findNameClashGroups(['Brand voice', 'Pricing'])).toEqual([]); + }); +}); diff --git a/packages/cli/src/modules/agents/__tests__/skill.service.test.ts b/packages/cli/src/modules/agents/__tests__/skill.service.test.ts new file mode 100644 index 00000000000..309c8e59dc3 --- /dev/null +++ b/packages/cli/src/modules/agents/__tests__/skill.service.test.ts @@ -0,0 +1,933 @@ +/* eslint-disable @typescript-eslint/unbound-method -- mock-based tests reference unbound methods */ +import type { ProjectScopeService } from '@n8n/backend-services'; +import type { OperationContext, TransactionRunner, User } from '@n8n/db'; +import { ConflictError, ForbiddenError, NotFoundError, UserError } from '@n8n/errors'; +import { hasGlobalScope } from '@n8n/permissions'; +import { mock } from 'vitest-mock-extended'; + +import { userHasScopes } from '@/permissions.ee/check-access'; + +import type { AgentUpdateBroadcaster } from '../agent-update-broadcaster'; +import type { SkillFile } from '../entities/skill-file.entity'; +import type { SkillVersion } from '../entities/skill-version.entity'; +import type { Skill } from '../entities/skill.entity'; +import type { AgentRepository } from '../repositories/agent.repository'; +import type { ResolvedSkillRow, SkillRepository } from '../repositories/skill.repository'; +import { skillContentHash } from '../skills/skill-content-hash'; +import { getAgentSkillHash } from '../utils/agent-config-hash'; +import { SkillService, toAgentSkill, toSkillContent } from '../skills/skill.service'; + +const clearRuntimes = vi.fn(); +vi.mock('../agent-runtime-cache.service', () => ({ AgentRuntimeCacheService: class {} })); +vi.mock('@n8n/di', async (importOriginal) => { + const actual = await importOriginal(); + return { + ...actual, + Container: { ...actual.Container, get: vi.fn(() => ({ clearRuntimes })) }, + }; +}); +vi.mock('@/permissions.ee/check-access', () => ({ userHasScopes: vi.fn() })); +vi.mock('@n8n/permissions', async (importOriginal) => ({ + ...(await importOriginal()), + hasGlobalScope: vi.fn(), +})); + +const PROJECT = 'project-1'; + +async function expectError( + promise: Promise, + errorClass: new (...args: never[]) => Error, + message: string, +) { + const error: unknown = await promise.then( + () => undefined, + (caught: unknown) => caught, + ); + expect(error).toBeInstanceOf(errorClass); + expect(error).toHaveProperty('message', message); +} +const TX_CTX = { trx: {} } as OperationContext; + +function skillRow(id: string, target: Partial> = {}): Skill { + return mock({ id, projectId: target.projectId ?? null, agentId: target.agentId ?? null }); +} + +function versionRow( + skill: Skill, + version: number, + overrides: Partial = {}, + files: Array<{ path: string; content: string }> = [], +): ResolvedSkillRow { + const base = { + name: 'Brand voice', + description: 'Write in our voice', + instructions: 'Use short sentences.', + frontmatter: null, + ...overrides, + }; + const contentHash = + overrides.contentHash ?? + skillContentHash({ + name: base.name, + description: base.description, + instructions: base.instructions, + frontmatter: base.frontmatter, + files, + }); + return { + skill, + version: mock({ + id: `${skill.id}-v${version}`, + skillId: skill.id, + version, + ...base, + contentHash, + }), + files: files.map((file) => mock(file)), + }; +} + +describe('SkillService', () => { + const skills = mock(); + const agents = mock(); + const txRunner = mock(); + const broadcaster = mock(); + const projectScope = mock(); + const service = new SkillService(mock(), skills, agents, txRunner, broadcaster, projectScope); + const user = mock({ id: 'user-1' }); + + beforeEach(() => { + vi.resetAllMocks(); + txRunner.run.mockImplementation(async (_ctx, fn) => await fn(TX_CTX)); + skills.findLatestSaved.mockResolvedValue(new Map()); + skills.findVersionsByIds.mockResolvedValue(new Map()); + skills.findDependencies.mockResolvedValue(new Map()); + skills.findByIds.mockResolvedValue([]); + skills.findFollowingAgents.mockResolvedValue([]); + skills.findFollowingAgentIds.mockResolvedValue([]); + agents.markDraftChangedIfInSync.mockResolvedValue([]); + agents.findProjectIdsByIds.mockResolvedValue([]); + }); + + describe('conversions', () => { + it('ignores allowed tools on write', () => { + expect( + toSkillContent({ + name: 'n', + description: 'd', + instructions: 'i', + allowedTools: ['Read', 'Grep'], + references: [{ path: 'references/a.md', content: 'a' }], + }), + ).toEqual({ + name: 'n', + description: 'd', + instructions: 'i', + frontmatter: null, + files: [{ path: 'references/a.md', content: 'a' }], + }); + }); + + it('keeps the frontmatter as given and reads no allowed tools from it', () => { + const row = versionRow(skillRow('skill_a'), 1, { + frontmatter: { 'allowed-tools': 'Read Grep', license: 'MIT' }, + }); + + expect(toSkillContent(toAgentSkill(row), row.version.frontmatter).frontmatter).toEqual({ + 'allowed-tools': 'Read Grep', + license: 'MIT', + }); + expect(toAgentSkill(row)).toEqual({ + name: 'Brand voice', + description: 'Write in our voice', + instructions: 'Use short sentences.', + }); + }); + }); + + describe('resolveForAgentDraft', () => { + it('runs the latest saved version for a following ref', async () => { + const skill = skillRow('skill_a'); + skills.findLatestSaved.mockResolvedValue( + new Map([['skill_a', versionRow(skill, 2, { instructions: 'v2' })]]), + ); + + const resolved = await service.resolveForAgentDraft([{ id: 'skill_a' }]); + + expect(resolved.skill_a.instructions).toBe('v2'); + }); + + it('runs the pinned version for a ref with versionId', async () => { + const skill = skillRow('skill_a'); + const v1 = versionRow(skill, 1, { instructions: 'v1' }); + skills.findLatestSaved.mockResolvedValue( + new Map([['skill_a', versionRow(skill, 2, { instructions: 'v2' })]]), + ); + skills.findVersionsByIds.mockResolvedValue(new Map([[v1.version.id, v1]])); + + const resolved = await service.resolveForAgentDraft([ + { id: 'skill_a', versionId: v1.version.id }, + ]); + + expect(resolved.skill_a.instructions).toBe('v1'); + }); + + it('falls back to the latest version when the pin belongs to another skill', async () => { + const foreign = versionRow(skillRow('skill_b'), 1, { instructions: 'other skill' }); + skills.findLatestSaved.mockResolvedValue( + new Map([['skill_a', versionRow(skillRow('skill_a'), 2, { instructions: 'v2' })]]), + ); + skills.findVersionsByIds.mockResolvedValue(new Map([[foreign.version.id, foreign]])); + + const resolved = await service.resolveForAgentDraft([ + { id: 'skill_a', versionId: foreign.version.id }, + ]); + + expect(resolved.skill_a.instructions).toBe('v2'); + }); + + it('leaves out a ref to a missing skill', async () => { + expect(await service.resolveForAgentDraft([{ id: 'skill_gone' }])).toEqual({}); + }); + }); + + describe('resolvePinned', () => { + it('returns the pinned versions keyed by skill id', async () => { + skills.findPinned.mockResolvedValue( + new Map([['skill_a', versionRow(skillRow('skill_a'), 1, { instructions: 'v1' })]]), + ); + + const resolved = await service.resolvePinned('agent-version-1'); + + expect(resolved).toEqual({ skill_a: expect.objectContaining({ instructions: 'v1' }) }); + }); + }); + + describe('create', () => { + it('creates the skill with an id in the agent skill format', async () => { + const id = await service.create({ + target: { projectId: PROJECT, agentId: null }, + skill: { name: 'n', description: 'd', instructions: 'i' }, + source: 'ui', + createdById: user.id, + }); + + expect(id).toMatch(/^skill_[A-Za-z0-9]{16}$/); + expect(skills.createSkill).toHaveBeenCalledWith( + { id, target: { projectId: PROJECT, agentId: null }, source: 'ui', createdById: user.id }, + expect.objectContaining({ name: 'n', frontmatter: null }), + expect.anything(), + ); + }); + + it('refuses blank instructions', async () => { + await expect( + service.create({ + target: { projectId: PROJECT, agentId: null }, + skill: { name: 'n', description: 'd', instructions: ' ' }, + source: 'ui', + createdById: user.id, + }), + ).rejects.toThrow(UserError); + expect(skills.createSkill).not.toHaveBeenCalled(); + }); + }); + + describe('save', () => { + const skill = skillRow('skill_a', { projectId: PROJECT }); + + /** Mocks the latest version and returns its hash, the base an editor sends back. */ + function givenLatest(latest: ResolvedSkillRow): string { + skills.findLatestSaved.mockImplementation(async (ids) => { + const rows = new Map(); + if (ids.includes('skill_a')) rows.set('skill_a', latest); + return rows; + }); + skills.nextVersionNumber.mockResolvedValue(3); + skills.insertSavedVersion.mockResolvedValue('new-version-id'); + return getAgentSkillHash(toAgentSkill(latest)); + } + + it('creates nothing when the content matches the latest version', async () => { + const baseSkillHash = givenLatest(versionRow(skill, 2)); + + const result = await service.save( + 'skill_a', + { baseSkillHash, instructions: 'Use short sentences.' }, + user.id, + ); + + expect(result).toMatchObject({ versionId: 'skill_a-v2', version: 2, created: false }); + expect(skills.insertSavedVersion).not.toHaveBeenCalled(); + expect(agents.markDraftChangedIfInSync).not.toHaveBeenCalled(); + }); + + it('saves changed content as the next version under an edit lock', async () => { + const baseSkillHash = givenLatest(versionRow(skill, 2)); + + const result = await service.save( + 'skill_a', + { + baseSkillHash, + instructions: 'new', + references: [{ path: 'references/a.md', content: 'a' }], + }, + user.id, + ); + + expect(result).toMatchObject({ versionId: 'new-version-id', version: 3, created: true }); + expect(result.skill).toMatchObject({ name: 'Brand voice', instructions: 'new' }); + expect(skills.lockForEdit).toHaveBeenCalledWith(['skill_a'], TX_CTX); + expect(skills.insertSavedVersion).toHaveBeenCalledWith( + 'skill_a', + 3, + expect.objectContaining({ + name: 'Brand voice', + instructions: 'new', + files: [{ path: 'references/a.md', content: 'a' }], + }), + user.id, + TX_CTX, + ); + }); + + it('removes references set to an empty list', async () => { + const baseSkillHash = givenLatest( + versionRow(skill, 2, {}, [{ path: 'references/a.md', content: 'a' }]), + ); + + const result = await service.save('skill_a', { baseSkillHash, references: [] }, user.id); + + expect(result.skill).not.toHaveProperty('references'); + }); + + it('ignores allowed tools in the update', async () => { + const baseSkillHash = givenLatest( + versionRow(skill, 2, { frontmatter: { 'allowed-tools': 'Read' } }), + ); + + const result = await service.save( + 'skill_a', + { baseSkillHash, instructions: 'new', allowedTools: ['Bash'] }, + user.id, + ); + + expect(result.skill).not.toHaveProperty('allowedTools'); + expect(skills.insertSavedVersion).toHaveBeenCalledWith( + 'skill_a', + 3, + expect.objectContaining({ frontmatter: { 'allowed-tools': 'Read' } }), + user.id, + TX_CTX, + ); + }); + + it('keeps frontmatter keys the editor does not know', async () => { + const baseSkillHash = givenLatest( + versionRow(skill, 2, { frontmatter: { license: 'MIT', 'allowed-tools': 'Read' } }), + ); + + await service.save('skill_a', { baseSkillHash, instructions: 'new' }, user.id); + + expect(skills.insertSavedVersion).toHaveBeenCalledWith( + 'skill_a', + 3, + expect.objectContaining({ frontmatter: { license: 'MIT', 'allowed-tools': 'Read' } }), + user.id, + TX_CTX, + ); + }); + + it('accepts the hash of the latest version as the base', async () => { + const latest = versionRow(skill, 2); + const baseSkillHash = givenLatest(latest); + + const result = await service.save('skill_a', { instructions: 'new', baseSkillHash }, user.id); + + expect(result.created).toBe(true); + }); + + // The check runs under the edit lock, so two saves from the same base cannot both pass. + it('refuses a stale base hash after taking the edit lock', async () => { + givenLatest(versionRow(skill, 2)); + + await expect( + service.save('skill_a', { instructions: 'new', baseSkillHash: 'stale' }, user.id), + ).rejects.toThrow(ConflictError); + expect(skills.lockForEdit.mock.invocationCallOrder[0]).toBeLessThan( + skills.findLatestSaved.mock.invocationCallOrder[0], + ); + expect(skills.insertSavedVersion).not.toHaveBeenCalled(); + }); + + it('refuses blank instructions', async () => { + const baseSkillHash = givenLatest(versionRow(skill, 2)); + + await expect( + service.save('skill_a', { baseSkillHash, instructions: ' ' }, user.id), + ).rejects.toThrow(UserError); + }); + + it('marks the following agents in the same transaction', async () => { + const baseSkillHash = givenLatest(versionRow(skill, 2)); + skills.findFollowingAgentIds.mockResolvedValue(['agent-1', 'agent-2']); + + await service.save('skill_a', { baseSkillHash, instructions: 'new' }, user.id); + + expect(skills.findFollowingAgentIds).toHaveBeenCalledWith(['skill_a'], TX_CTX); + expect(agents.markDraftChangedIfInSync).toHaveBeenCalledWith(['agent-1', 'agent-2'], TX_CTX); + }); + + it('clears the runtime and pushes an update for every following agent after the commit', async () => { + const baseSkillHash = givenLatest(versionRow(skill, 2)); + skills.findFollowingAgentIds.mockResolvedValue(['agent-1', 'agent-2']); + // agent-2 already had unpublished changes, so only agent-1 is marked. + agents.markDraftChangedIfInSync.mockResolvedValue(['agent-1']); + agents.findProjectIdsByIds.mockResolvedValue([ + { id: 'agent-1', projectId: PROJECT }, + { id: 'agent-2', projectId: PROJECT }, + ]); + + await service.save('skill_a', { baseSkillHash, instructions: 'new' }, user.id); + + expect(clearRuntimes.mock.calls).toEqual([['agent-1'], ['agent-2']]); + expect(broadcaster.notify).toHaveBeenCalledTimes(2); + expect(broadcaster.notify).toHaveBeenCalledWith( + { projectId: PROJECT, agentId: 'agent-2', source: 'user' }, + undefined, + ); + }); + + it('sends no update push to the tab that saved', async () => { + const baseSkillHash = givenLatest(versionRow(skill, 2)); + skills.findFollowingAgentIds.mockResolvedValue(['agent-1']); + agents.findProjectIdsByIds.mockResolvedValue([{ id: 'agent-1', projectId: PROJECT }]); + + await service.save( + 'skill_a', + { baseSkillHash, instructions: 'new' }, + user.id, + {}, + 'push-ref-1', + ); + + expect(broadcaster.notify).toHaveBeenCalledWith( + { projectId: PROJECT, agentId: 'agent-1', source: 'user' }, + 'push-ref-1', + ); + }); + + it("leaves the refresh to the caller when it runs in the caller's transaction", async () => { + const baseSkillHash = givenLatest(versionRow(skill, 2)); + skills.findFollowingAgentIds.mockResolvedValue(['agent-1']); + + const result = await service.save( + 'skill_a', + { baseSkillHash, instructions: 'new' }, + user.id, + TX_CTX, + ); + + expect(result.followingAgentIds).toEqual(['agent-1']); + expect(clearRuntimes).not.toHaveBeenCalled(); + expect(broadcaster.notify).not.toHaveBeenCalled(); + }); + + it('rejects a rename that clashes on a following agent', async () => { + skills.nextVersionNumber.mockResolvedValue(3); + skills.findFollowingAgents.mockResolvedValue([{ id: 'agent-1', name: 'Sales bot' }]); + skills.findDependencies.mockResolvedValue( + new Map([ + [ + 'agent-1', + [ + { skillId: 'skill_a', versionId: null }, + { skillId: 'skill_b', versionId: null }, + ], + ], + ]), + ); + skills.findLatestSaved.mockImplementation( + async (ids) => + new Map( + ids.map((id) => [ + id, + versionRow(skillRow(id), 2, { name: id === 'skill_b' ? 'Pricing' : 'Brand voice' }), + ]), + ), + ); + + const baseSkillHash = getAgentSkillHash( + toAgentSkill(versionRow(skillRow('skill_a'), 2, { name: 'Brand voice' })), + ); + + await expectError( + service.save('skill_a', { baseSkillHash, name: 'pricing' }, user.id), + UserError, + 'Cannot rename to "pricing": Sales bot already uses a skill with a name like that.', + ); + expect(skills.insertSavedVersion).not.toHaveBeenCalled(); + }); + + it('allows a rename that clashes on no agent', async () => { + const baseSkillHash = givenLatest(versionRow(skill, 2)); + + await expect( + service.save('skill_a', { baseSkillHash, name: 'Tone' }, user.id), + ).resolves.toMatchObject({ + created: true, + }); + }); + + it('throws NotFoundError for a missing skill', async () => { + await expect( + service.save('skill_gone', { name: 'x', baseSkillHash: 'any' }, user.id), + ).rejects.toThrow(NotFoundError); + }); + }); + + describe('changeTarget', () => { + it('moves a skill that only the given agent uses, under the edit lock', async () => { + skills.findUsingAgentIds.mockResolvedValue(['agent-1']); + + await service.changeTarget('skill_a', { projectId: null, agentId: 'agent-1' }, 'agent-1'); + + expect(skills.lockForEdit).toHaveBeenCalledWith(['skill_a'], TX_CTX); + expect(skills.lockForEdit.mock.invocationCallOrder[0]).toBeLessThan( + skills.findUsingAgentIds.mock.invocationCallOrder[0], + ); + expect(skills.updateTarget).toHaveBeenCalledWith( + 'skill_a', + { projectId: null, agentId: 'agent-1' }, + TX_CTX, + ); + }); + + it('refuses to move a skill that another agent uses', async () => { + skills.findUsingAgentIds.mockResolvedValue(['agent-1', 'agent-2']); + + await expect( + service.changeTarget('skill_a', { projectId: null, agentId: null }, 'agent-1'), + ).rejects.toThrow('Other agents use this skill.'); + expect(skills.updateTarget).not.toHaveBeenCalled(); + }); + }); + + describe('publish', () => { + it('locks the skills and pins the version each ref resolves to', async () => { + const a = skillRow('skill_a'); + const b = skillRow('skill_b'); + const pinnedB = versionRow(b, 1); + skills.findLatestSaved.mockResolvedValue( + new Map([ + ['skill_a', versionRow(a, 3)], + ['skill_b', versionRow(b, 2)], + ]), + ); + skills.findVersionsByIds.mockResolvedValue(new Map([[pinnedB.version.id, pinnedB]])); + + const snapshot = await service.snapshotForPublish( + [{ id: 'skill_a' }, { id: 'skill_b', versionId: pinnedB.version.id }], + TX_CTX, + ); + await service.pinForPublish('agent-version-1', snapshot.versionByRef, TX_CTX); + + expect(skills.lockForPublish).toHaveBeenCalledWith(['skill_a', 'skill_b'], TX_CTX); + expect(Object.keys(snapshot.skills)).toEqual(['skill_a', 'skill_b']); + expect(skills.insertPins).toHaveBeenCalledWith( + [ + { + agentVersionId: 'agent-version-1', + skillId: 'skill_a', + skillVersionId: 'skill_a-v3', + }, + { + agentVersionId: 'agent-version-1', + skillId: 'skill_b', + skillVersionId: 'skill_b-v1', + }, + ], + TX_CTX, + ); + expect(skills.insertSavedVersion).not.toHaveBeenCalled(); + }); + }); + + describe('restoreFromVersion', () => { + it('pins each ref to the version that agent version used and writes no skill', async () => { + const v1 = versionRow(skillRow('skill_a'), 1); + skills.findPinned.mockResolvedValue(new Map([['skill_a', v1]])); + + const refs = await service.restoreFromVersion('agent-version-1', [ + { id: 'skill_a' }, + { id: 'skill_unpinned', versionId: 'stale' }, + ]); + + expect(refs).toEqual([{ id: 'skill_a', versionId: 'skill_a-v1' }, { id: 'skill_unpinned' }]); + expect(skills.insertSavedVersion).not.toHaveBeenCalled(); + }); + }); + + describe('isAttachable', () => { + const agent = { id: 'agent-1', projectId: PROJECT }; + + it.each([ + ['an instance skill', {}, true], + ['a skill of the agent project', { projectId: PROJECT }, true], + ['a skill of another project', { projectId: 'project-2' }, false], + ['a skill of this agent', { agentId: 'agent-1' }, true], + ['a skill of another agent', { agentId: 'agent-2' }, false], + ])('is %s attachable: %s', (_label, target, expected) => { + expect(service.isAttachable(skillRow('skill_a', target), agent)).toBe(expected); + }); + }); + + describe('checkRefs', () => { + const agent = { id: 'agent-1', projectId: PROJECT }; + + function givenAgentRefs(refs: Array<{ skillId: string; versionId?: string }>) { + skills.findDependencies.mockResolvedValue( + new Map([['agent-1', refs.map((ref) => ({ versionId: null, ...ref }))]]), + ); + } + + beforeEach(() => givenAgentRefs([{ skillId: 'skill_old' }])); + + function givenSkills(rows: Array<{ skill: Skill; name: string }>) { + skills.findByIds.mockResolvedValue(rows.map((row) => row.skill)); + skills.findLatestSaved.mockImplementation( + async (ids) => + new Map( + rows + .filter((row) => ids.includes(row.skill.id)) + .map((row) => [row.skill.id, versionRow(row.skill, 1, { name: row.name })]), + ), + ); + } + + it("reads the agent's current refs from its dependency rows", async () => { + await service.checkRefs(agent, []); + + expect(skills.findDependencies).toHaveBeenCalledWith(['agent-1'], {}); + }); + + it('keeps a new ref to an attachable skill', async () => { + givenSkills([ + { skill: skillRow('skill_old', { projectId: PROJECT }), name: 'Pricing' }, + { skill: skillRow('skill_new'), name: 'Tone' }, + ]); + + const refs = await service.checkRefs(agent, [{ id: 'skill_old' }, { id: 'skill_new' }]); + + expect(refs).toEqual([{ id: 'skill_old' }, { id: 'skill_new' }]); + }); + + it('holds a shared lock on newly attached skills in the caller transaction', async () => { + givenSkills([ + { skill: skillRow('skill_old', { projectId: PROJECT }), name: 'Pricing' }, + { skill: skillRow('skill_new'), name: 'Tone' }, + ]); + + await service.checkRefs(agent, [{ id: 'skill_old' }, { id: 'skill_new' }], TX_CTX); + + expect(skills.lockForPublish).toHaveBeenCalledWith(['skill_new'], TX_CTX); + }); + + it('compares the name of the version a pinned ref runs, not the latest name', async () => { + const old = skillRow('skill_old', { projectId: PROJECT }); + givenAgentRefs([{ skillId: 'skill_old', versionId: 'skill_old-v1' }]); + givenSkills([ + { skill: old, name: 'Tone' }, + { skill: skillRow('skill_new'), name: 'tone' }, + ]); + // The agent runs v1, which is still called "Pricing". + skills.findVersionsByIds.mockResolvedValue( + new Map([['skill_old-v1', versionRow(old, 1, { name: 'Pricing' })]]), + ); + + await expect( + service.checkRefs(agent, [ + { id: 'skill_old', versionId: 'skill_old-v1' }, + { id: 'skill_new' }, + ]), + ).resolves.toEqual([{ id: 'skill_old', versionId: 'skill_old-v1' }, { id: 'skill_new' }]); + }); + + it('drops a new ref to a missing skill', async () => { + givenSkills([{ skill: skillRow('skill_old', { projectId: PROJECT }), name: 'Pricing' }]); + + const refs = await service.checkRefs(agent, [{ id: 'skill_old' }, { id: 'skill_gone' }]); + + expect(refs).toEqual([{ id: 'skill_old' }]); + }); + + it('keeps a ref the agent already had even when its skill is gone', async () => { + const refs = await service.checkRefs(agent, [{ id: 'skill_old' }]); + + expect(refs).toEqual([{ id: 'skill_old' }]); + }); + + it.each([ + ['a skill of another agent', { agentId: 'agent-2' }], + ['a skill of another project', { projectId: 'project-2' }], + ])('rejects a new ref to %s', async (_label, target) => { + givenSkills([{ skill: skillRow('skill_new', target), name: 'Tone' }]); + + await expectError( + service.checkRefs(agent, [{ id: 'skill_new' }]), + UserError, + 'Skill "Tone" (skill_new) is not available to this agent. An agent can use the skills of its own project, its own skills and instance skills.', + ); + }); + + it('rejects a new ref whose name clashes with a skill of the agent', async () => { + givenSkills([ + { skill: skillRow('skill_old', { projectId: PROJECT }), name: 'Brand voice' }, + { skill: skillRow('skill_new'), name: 'brand-voice' }, + ]); + + await expectError( + service.checkRefs(agent, [{ id: 'skill_old' }, { id: 'skill_new' }]), + UserError, + 'This agent already has a skill with a name like "brand-voice". Rename one of them, or detach the other skill first.', + ); + }); + + it('keeps a clash the agent already had', async () => { + givenAgentRefs([{ skillId: 'skill_a' }, { skillId: 'skill_b' }]); + givenSkills([ + { skill: skillRow('skill_a', { projectId: PROJECT }), name: 'Pricing' }, + { skill: skillRow('skill_b', { projectId: PROJECT }), name: 'pricing' }, + ]); + + const refs = await service.checkRefs(agent, [{ id: 'skill_a' }, { id: 'skill_b' }]); + + expect(refs).toHaveLength(2); + }); + + it('keeps a pin the agent already had and drops a pin it did not have', async () => { + givenAgentRefs([{ skillId: 'skill_a', versionId: 'v1' }, { skillId: 'skill_b' }]); + givenSkills([ + { skill: skillRow('skill_a', { projectId: PROJECT }), name: 'Pricing' }, + { skill: skillRow('skill_b', { projectId: PROJECT }), name: 'Tone' }, + ]); + + const refs = await service.checkRefs(agent, [ + { id: 'skill_a', versionId: 'v1' }, + { id: 'skill_b', versionId: 'v9' }, + ]); + + expect(refs).toEqual([{ id: 'skill_a', versionId: 'v1' }, { id: 'skill_b' }]); + }); + + it('lets a save clear a pin', async () => { + givenAgentRefs([{ skillId: 'skill_a', versionId: 'v1' }]); + givenSkills([{ skill: skillRow('skill_a', { projectId: PROJECT }), name: 'Pricing' }]); + + expect(await service.checkRefs(agent, [{ id: 'skill_a' }])).toEqual([{ id: 'skill_a' }]); + }); + }); + + describe('canEdit', () => { + it('checks projectSkill:update on the project of a project skill', async () => { + vi.mocked(userHasScopes).mockResolvedValue(true); + + expect(await service.canEdit(user, skillRow('skill_a', { projectId: PROJECT }))).toBe(true); + expect(userHasScopes).toHaveBeenCalledWith(user, ['projectSkill:update'], false, { + projectId: PROJECT, + }); + }); + + it('checks projectSkill:update on the project of the agent of an agent skill', async () => { + vi.mocked(userHasScopes).mockResolvedValue(true); + skills.findAgents.mockResolvedValue( + new Map([['agent-1', { name: 'Support bot', projectId: PROJECT }]]), + ); + + expect(await service.canEdit(user, skillRow('skill_a', { agentId: 'agent-1' }))).toBe(true); + expect(skills.findAgents).toHaveBeenCalledWith(['agent-1'], {}); + expect(userHasScopes).toHaveBeenCalledWith(user, ['projectSkill:update'], false, { + projectId: PROJECT, + }); + }); + + it('needs skill:update for an instance skill', async () => { + vi.mocked(hasGlobalScope).mockReturnValue(true); + + expect(await service.canEdit(user, skillRow('skill_a'))).toBe(true); + expect(hasGlobalScope).toHaveBeenCalledWith(user, 'skill:update'); + }); + + it('refuses an instance skill without skill:update', async () => { + vi.mocked(hasGlobalScope).mockReturnValue(false); + + expect(await service.canEdit(user, skillRow('skill_a'))).toBe(false); + }); + }); + + describe('canAccess', () => { + it('lets every user read an instance skill', async () => { + vi.mocked(hasGlobalScope).mockReturnValue(false); + + expect(await service.canAccess(user, skillRow('skill_a'), 'read')).toBe(true); + }); + + it('needs skill:read for an agent skill whose agent is gone', async () => { + vi.mocked(hasGlobalScope).mockReturnValue(false); + skills.findAgents.mockResolvedValue(new Map()); + + expect(await service.canAccess(user, skillRow('skill_a', { agentId: 'gone' }), 'read')).toBe( + false, + ); + expect(hasGlobalScope).toHaveBeenCalledWith(user, 'skill:read'); + }); + + it('checks the scope of the operation on the project of a project skill', async () => { + vi.mocked(userHasScopes).mockResolvedValue(false); + + expect( + await service.canAccess(user, skillRow('skill_a', { projectId: PROJECT }), 'delete'), + ).toBe(false); + expect(userHasScopes).toHaveBeenCalledWith(user, ['projectSkill:delete'], false, { + projectId: PROJECT, + }); + }); + + it('needs skill:delete to delete an instance skill', async () => { + vi.mocked(hasGlobalScope).mockReturnValue(true); + + expect(await service.canAccess(user, skillRow('skill_a'), 'delete')).toBe(true); + expect(hasGlobalScope).toHaveBeenCalledWith(user, 'skill:delete'); + }); + }); + + describe('accessCheck', () => { + it('reads the projects of the operation once and checks project skills against them', async () => { + projectScope.getProjectIds.mockResolvedValue([PROJECT]); + vi.mocked(hasGlobalScope).mockReturnValue(false); + + const canUpdate = await service.accessCheck(user, 'update'); + + expect(canUpdate(skillRow('skill_a', { projectId: PROJECT }), PROJECT)).toBe(true); + expect(canUpdate(skillRow('skill_b', { projectId: 'other-project' }), 'other-project')).toBe( + false, + ); + // An agent skill is checked against the project of its agent. + expect(canUpdate(skillRow('skill_c', { agentId: 'agent-1' }), PROJECT)).toBe(true); + expect(projectScope.getProjectIds).toHaveBeenCalledTimes(1); + expect(projectScope.getProjectIds).toHaveBeenCalledWith(user, ['projectSkill:update']); + expect(userHasScopes).not.toHaveBeenCalled(); + }); + + it('allows every project skill when the global role grants the scope', async () => { + projectScope.getProjectIds.mockResolvedValue(null); + + const canDelete = await service.accessCheck(user, 'delete'); + + expect(canDelete(skillRow('skill_a', { projectId: 'any-project' }), 'any-project')).toBe( + true, + ); + }); + + it('applies the canAccess rules to instance skills', async () => { + projectScope.getProjectIds.mockResolvedValue([]); + vi.mocked(hasGlobalScope).mockReturnValue(false); + + const canUpdate = await service.accessCheck(user, 'update'); + const canRead = await service.accessCheck(user, 'read'); + + expect(canUpdate(skillRow('skill_c'), null)).toBe(false); + expect(canRead(skillRow('skill_c'), null)).toBe(true); + }); + }); + + describe('assertCanEdit', () => { + it('names the skills the user cannot edit', async () => { + vi.mocked(hasGlobalScope).mockReturnValue(false); + skills.findByIds.mockResolvedValue([skillRow('skill_a')]); + skills.findLatestSaved.mockResolvedValue( + new Map([['skill_a', versionRow(skillRow('skill_a'), 1, { name: 'Tone' })]]), + ); + + await expectError( + service.assertCanEdit(user, ['skill_a']), + ForbiddenError, + 'You can use but not edit "Tone" (skill_a). Ask someone who can edit this skill, or detach it from this agent.', + ); + }); + }); + + describe('deleteSkill', () => { + it('deletes a skill nobody uses, under an edit lock', async () => { + skills.findByIds.mockResolvedValue([skillRow('skill_a')]); + skills.findUsage.mockResolvedValue({ drafts: [], pins: [], hiddenAgents: 0 }); + + await service.deleteSkill('skill_a'); + + expect(skills.findUsage).toHaveBeenCalledWith('skill_a', 'all', TX_CTX); + expect(skills.lockForEdit).toHaveBeenCalledWith(['skill_a'], TX_CTX); + expect(skills.deleteSkill).toHaveBeenCalledWith('skill_a', TX_CTX); + }); + + it('refuses while agents use the skill and names them', async () => { + skills.findByIds.mockResolvedValue([skillRow('skill_a')]); + skills.findLatestSaved.mockResolvedValue( + new Map([['skill_a', versionRow(skillRow('skill_a'), 2)]]), + ); + skills.findUsage.mockResolvedValue({ + drafts: [{ agentId: 'agent-1', agentName: 'Support bot', projectId: PROJECT }], + pins: [ + { agentId: 'agent-2', agentName: 'Sales bot', projectId: PROJECT, version: 2 }, + { agentId: 'agent-3', agentName: 'Old bot', projectId: PROJECT, version: null }, + ], + hiddenAgents: 0, + }); + + await expectError( + service.deleteSkill('skill_a'), + ConflictError, + 'Skill "Brand voice" is used by Support bot (draft), Sales bot (published v2), Old bot (older published version) and cannot be deleted.', + ); + expect(skills.deleteSkill).not.toHaveBeenCalled(); + }); + + it('names only the agents of the given projects and counts the others', async () => { + skills.findByIds.mockResolvedValue([skillRow('skill_a')]); + skills.findLatestSaved.mockResolvedValue( + new Map([['skill_a', versionRow(skillRow('skill_a'), 2)]]), + ); + skills.findUsage.mockResolvedValue({ + drafts: [{ agentId: 'agent-1', agentName: 'Support bot', projectId: PROJECT }], + pins: [], + hiddenAgents: 2, + }); + + await expectError( + service.deleteSkill('skill_a', [PROJECT]), + ConflictError, + 'Skill "Brand voice" is used by Support bot (draft), 2 agents in other projects and cannot be deleted.', + ); + expect(skills.findUsage).toHaveBeenCalledWith('skill_a', [PROJECT], TX_CTX); + expect(skills.deleteSkill).not.toHaveBeenCalled(); + }); + + it('refuses when only agents the caller cannot read use the skill', async () => { + skills.findByIds.mockResolvedValue([skillRow('skill_a')]); + skills.findLatestSaved.mockResolvedValue( + new Map([['skill_a', versionRow(skillRow('skill_a'), 2)]]), + ); + skills.findUsage.mockResolvedValue({ drafts: [], pins: [], hiddenAgents: 1 }); + + await expectError( + service.deleteSkill('skill_a', []), + ConflictError, + 'Skill "Brand voice" is used by 1 agent in other projects and cannot be deleted.', + ); + expect(skills.deleteSkill).not.toHaveBeenCalled(); + }); + + it('throws NotFoundError for a missing skill', async () => { + await expect(service.deleteSkill('skill_gone')).rejects.toThrow(NotFoundError); + }); + }); +}); diff --git a/packages/cli/src/modules/agents/__tests__/skills-api.service.test.ts b/packages/cli/src/modules/agents/__tests__/skills-api.service.test.ts new file mode 100644 index 00000000000..d902cc1025d --- /dev/null +++ b/packages/cli/src/modules/agents/__tests__/skills-api.service.test.ts @@ -0,0 +1,486 @@ +/* eslint-disable @typescript-eslint/unbound-method -- mock-based tests reference unbound methods */ +import type { CreateSkillDto, ListSkillsQueryDto, SaveSkillDto } from '@n8n/api-types'; +import type { ProjectScopeService } from '@n8n/backend-services'; +import type { User } from '@n8n/db'; +import { ForbiddenError, NotFoundError, UserError } from '@n8n/errors'; +import { hasGlobalScope } from '@n8n/permissions'; +import { mock } from 'vitest-mock-extended'; + +import { userHasScopes } from '@/permissions.ee/check-access'; + +import type { SkillFile } from '../entities/skill-file.entity'; +import type { SkillVersion } from '../entities/skill-version.entity'; +import type { Skill } from '../entities/skill.entity'; +import type { ResolvedSkillRow, SkillRepository } from '../repositories/skill.repository'; +import { SkillsApiService } from '../skills/skills-api.service'; +import type { SkillService } from '../skills/skill.service'; +import { getAgentSkillHash } from '../utils/agent-config-hash'; + +vi.mock('@/permissions.ee/check-access', () => ({ userHasScopes: vi.fn() })); +vi.mock('@n8n/permissions', async (importOriginal) => ({ + ...(await importOriginal()), + hasGlobalScope: vi.fn(), +})); + +const user = mock({ id: 'user-1' }); +const DATE = new Date('2026-10-01T00:00:00.000Z'); + +function skill(id: string, target: Partial> = {}): Skill { + return mock({ + id, + projectId: target.projectId ?? null, + agentId: target.agentId ?? null, + source: 'ui', + createdAt: DATE, + updatedAt: DATE, + }); +} + +function row( + owner: Skill, + version: number, + fields: { name?: string; instructions?: string } = {}, +): ResolvedSkillRow { + const name = fields.name ?? NAMES[owner.id] ?? 'Skill'; + return { + skill: owner, + version: mock({ + id: `${owner.id}-v${version}`, + skillId: owner.id, + version, + name, + description: `${name} desc`, + instructions: fields.instructions ?? 'Do it.', + frontmatter: null, + contentHash: 'hash', + }), + files: [] as SkillFile[], + }; +} + +const NAMES: Record = { + skill_a: 'Brand voice', + skill_b: 'Cite sources', + skill_c: 'Triage rules', +}; + +const query = (overrides: Partial = {}) => + ({ skip: 0, ...overrides }) as ListSkillsQueryDto; + +describe('SkillsApiService', () => { + const repository = mock(); + const skillService = mock(); + const projectScopeService = mock(); + const service = new SkillsApiService(skillService, repository, projectScopeService); + let visible: Skill[]; + + beforeEach(() => { + vi.resetAllMocks(); + visible = Object.keys(NAMES).map((id) => skill(id)); + projectScopeService.getProjectIds.mockResolvedValue(['project-1']); + vi.mocked(hasGlobalScope).mockReturnValue(false); + repository.findVisiblePage.mockImplementation(async () => ({ + skills: visible, + count: visible.length, + })); + repository.findByIds.mockImplementation(async (ids) => + visible.filter((s) => ids.includes(s.id)), + ); + repository.findLatestSummaries.mockImplementation( + async (ids) => + new Map( + visible + .filter((s) => ids.includes(s.id)) + .map(({ id }) => { + const { name, description } = row(skill(id), 2).version; + return [id, { name, description, version: 2 }] as const; + }), + ), + ); + repository.findLatestSaved.mockImplementation( + async (ids) => + new Map(visible.filter((s) => ids.includes(s.id)).map((s) => [s.id, row(s, 2)] as const)), + ); + repository.countUsingAgents.mockResolvedValue(new Map()); + repository.findProjectNames.mockImplementation( + async (ids) => new Map(ids.map((id) => [id, 'Team'] as const)), + ); + repository.findUsage.mockResolvedValue({ drafts: [], pins: [], hiddenAgents: 0 }); + repository.findAgents.mockImplementation( + async (ids) => + new Map( + ids + .filter((id) => id === 'agent-1') + .map((id) => [id, { name: 'Support bot', projectId: 'project-1' }] as const), + ), + ); + skillService.canAccess.mockResolvedValue(true); + skillService.accessCheck.mockResolvedValue(() => true); + }); + + describe('list', () => { + it('passes the filters and the page to the repository', async () => { + const result = await service.list( + user, + query({ scope: 'project', projectId: 'project-1', search: 'rules', skip: 10, take: 5 }), + ); + + expect(repository.findVisiblePage).toHaveBeenCalledWith( + { projectIds: ['project-1'] }, + { scope: 'project', projectId: 'project-1', search: 'rules', skip: 10, take: 5 }, + ); + expect(result.count).toBe(3); + }); + + it('passes the agent that attaches skills, with its project', async () => { + await service.list(user, query({ attachableTo: 'agent-1', search: 'voice' })); + + expect(repository.findVisiblePage).toHaveBeenCalledWith( + expect.anything(), + expect.objectContaining({ + attachableTo: { agentId: 'agent-1', projectId: 'project-1' }, + search: 'voice', + }), + ); + }); + + it('refuses attachableTo for an unknown agent', async () => { + await expect(service.list(user, query({ attachableTo: 'agent-gone' }))).rejects.toThrow( + NotFoundError, + ); + expect(repository.findVisiblePage).not.toHaveBeenCalled(); + }); + + it.each([{ scope: 'agent' as const }, { projectId: 'project-1' }])( + 'refuses attachableTo together with %o', + async (filter) => { + await expect( + service.list(user, query({ attachableTo: 'agent-1', ...filter })), + ).rejects.toThrow(UserError); + expect(repository.findVisiblePage).not.toHaveBeenCalled(); + }, + ); + + it('shapes only the page into list items, from summaries', async () => { + visible = [skill('skill_b')]; + repository.findVisiblePage.mockResolvedValue({ skills: visible, count: 3 }); + + const result = await service.list(user, query({ skip: 1, take: 1 })); + + expect(result).toMatchObject({ count: 3, data: [{ id: 'skill_b', name: 'Cite sources' }] }); + // Summaries carry no instructions or files. + expect(repository.findLatestSummaries).toHaveBeenCalledWith(['skill_b']); + expect(repository.findLatestSaved).not.toHaveBeenCalled(); + }); + + it('asks for the projects the user may list skills of', async () => { + await service.list(user, query()); + + expect(projectScopeService.getProjectIds).toHaveBeenCalledWith(user, ['projectSkill:list']); + }); + + it('widens the list for a user with global scopes', async () => { + projectScopeService.getProjectIds.mockResolvedValue(null); + + await service.list(user, query()); + + expect(repository.findVisiblePage).toHaveBeenCalledWith( + { projectIds: 'all' }, + expect.anything(), + ); + }); + + it('describes each skill', async () => { + visible = [skill('skill_a', { projectId: 'project-1' })]; + repository.countUsingAgents.mockResolvedValue(new Map([['skill_a', 2]])); + repository.findProjectNames.mockResolvedValue(new Map([['project-1', 'Team']])); + skillService.accessCheck.mockImplementation(async (_user, op) => () => op === 'update'); + + const [item] = (await service.list(user, query())).data; + + expect(item).toEqual({ + id: 'skill_a', + name: 'Brand voice', + description: 'Brand voice desc', + scope: 'project', + projectId: 'project-1', + projectName: 'Team', + agentId: null, + agentName: null, + source: 'ui', + latestVersion: 2, + usedByAgents: 2, + canEdit: true, + canDelete: false, + createdAt: DATE.toISOString(), + updatedAt: DATE.toISOString(), + }); + }); + + it('describes an agent skill with its agent and the project of the agent', async () => { + visible = [skill('skill_a', { agentId: 'agent-1' })]; + repository.findProjectNames.mockResolvedValue(new Map([['project-1', 'Team']])); + const check = vi.fn().mockReturnValue(true); + skillService.accessCheck.mockResolvedValue(check); + + const [item] = (await service.list(user, query())).data; + + expect(item).toMatchObject({ + scope: 'agent', + projectId: 'project-1', + projectName: 'Team', + agentId: 'agent-1', + agentName: 'Support bot', + }); + // Permissions come from the agent's project. + expect(check).toHaveBeenCalledWith(visible[0], 'project-1'); + }); + + it('checks edit and delete once for the page, not once per skill', async () => { + await service.list(user, query()); + + expect(skillService.accessCheck).toHaveBeenCalledTimes(2); + expect(skillService.accessCheck).toHaveBeenCalledWith(user, 'update'); + expect(skillService.accessCheck).toHaveBeenCalledWith(user, 'delete'); + expect(skillService.canAccess).not.toHaveBeenCalled(); + }); + }); + + describe('get', () => { + it('returns the latest version, its hash and the usage', async () => { + const usage = { + drafts: [{ agentId: 'agent-1', agentName: 'Support', projectId: 'project-1' }], + pins: [], + hiddenAgents: 1, + }; + repository.findUsage.mockResolvedValue(usage); + const latest = row(visible[0], 3, { instructions: 'saved' }); + repository.findLatestSaved.mockResolvedValue(new Map([['skill_a', latest]])); + repository.findLatestSummaries.mockResolvedValue( + new Map([ + [ + 'skill_a', + { name: latest.version.name, description: latest.version.description, version: 3 }, + ], + ]), + ); + + const detail = await service.get(user, 'skill_a'); + + expect(detail.skill.instructions).toBe('saved'); + expect(detail.latestVersion).toBe(3); + expect(detail.skillHash).toBe(getAgentSkillHash(detail.skill)); + expect(detail.usedBy).toEqual(usage); + }); + + it('limits the usage to the agents the user may read', async () => { + await service.get(user, 'skill_a'); + + expect(projectScopeService.getProjectIds).toHaveBeenCalledWith(user, ['agent:read']); + expect(repository.findUsage).toHaveBeenCalledWith('skill_a', ['project-1']); + }); + + it('shows the agents of every project to a user with the global agent scope', async () => { + projectScopeService.getProjectIds.mockResolvedValue(null); + + await service.get(user, 'skill_a'); + + expect(repository.findUsage).toHaveBeenCalledWith('skill_a', 'all'); + }); + + it('answers a skill the user cannot see like a missing one', async () => { + skillService.canAccess.mockResolvedValue(false); + + await expect(service.get(user, 'skill_a')).rejects.toThrow(NotFoundError); + await expect(service.get(user, 'skill_gone')).rejects.toThrow(NotFoundError); + expect(skillService.canAccess).toHaveBeenCalledWith(user, visible[0], 'read'); + }); + }); + + describe('create', () => { + const body = { name: 'Tone', description: 'How we sound', instructions: 'Be kind.' }; + const payload = (overrides: Partial) => + ({ scope: 'instance', skill: body, ...overrides }) as CreateSkillDto; + + beforeEach(() => { + skillService.create.mockImplementation(async () => { + visible.push(skill('skill_new')); + return 'skill_new'; + }); + }); + + // A custom role can hold projectSkill:create without projectSkill:read. + it('returns the new skill to a creator who may not read it afterwards', async () => { + vi.mocked(userHasScopes).mockResolvedValue(true); + skillService.canAccess.mockResolvedValue(false); + skillService.accessCheck.mockResolvedValue(() => false); + + const detail = await service.create( + user, + payload({ scope: 'project', projectId: 'project-1' }), + ); + + expect(detail).toMatchObject({ id: 'skill_new', name: 'Skill', canEdit: false }); + }); + + it('creates an agent skill with projectSkill:create on the project of the agent', async () => { + vi.mocked(userHasScopes).mockResolvedValue(true); + + const detail = await service.create(user, payload({ scope: 'agent', agentId: 'agent-1' })); + + expect(userHasScopes).toHaveBeenCalledWith(user, ['projectSkill:create'], false, { + projectId: 'project-1', + }); + expect(skillService.create).toHaveBeenCalledWith({ + target: { projectId: null, agentId: 'agent-1' }, + skill: body, + source: 'ui', + createdById: user.id, + }); + expect(detail.id).toBe('skill_new'); + }); + + it('refuses an agent skill for an agent that does not exist', async () => { + vi.mocked(userHasScopes).mockResolvedValue(true); + + await expect( + service.create(user, payload({ scope: 'agent', agentId: 'agent-gone' })), + ).rejects.toThrow(NotFoundError); + expect(skillService.create).not.toHaveBeenCalled(); + }); + + it('creates a project skill with projectSkill:create, also in a personal project', async () => { + vi.mocked(userHasScopes).mockResolvedValue(true); + + await service.create(user, payload({ scope: 'project', projectId: 'personal-1' })); + + expect(userHasScopes).toHaveBeenCalledWith(user, ['projectSkill:create'], false, { + projectId: 'personal-1', + }); + expect(skillService.create).toHaveBeenCalledWith( + expect.objectContaining({ target: { projectId: 'personal-1', agentId: null } }), + ); + }); + + it('creates an instance skill with skill:create', async () => { + vi.mocked(hasGlobalScope).mockReturnValue(true); + + await service.create(user, payload({ scope: 'instance' })); + + expect(hasGlobalScope).toHaveBeenCalledWith(user, 'skill:create'); + expect(skillService.create).toHaveBeenCalledWith( + expect.objectContaining({ target: { projectId: null, agentId: null } }), + ); + }); + + it.each([ + ['project', {}, UserError], + ['project', { projectId: 'project-1', agentId: 'agent-1' }, UserError], + ['agent', {}, UserError], + ['agent', { agentId: 'agent-1', projectId: 'project-1' }, UserError], + ['agent', { agentId: 'agent-1' }, ForbiddenError], + ['instance', { projectId: 'project-1' }, UserError], + ['instance', { agentId: 'agent-1' }, UserError], + ['instance', {}, ForbiddenError], + ['project', { projectId: 'project-1' }, ForbiddenError], + ] as const)('refuses scope %s with %o', async (scope, extra, errorClass) => { + vi.mocked(userHasScopes).mockResolvedValue(false); + + await expect(service.create(user, payload({ scope, ...extra }))).rejects.toThrow(errorClass); + expect(skillService.create).not.toHaveBeenCalled(); + }); + + // A global projectSkill:create passes the scope check for any project id. + it('refuses a project skill for a project that does not exist', async () => { + vi.mocked(userHasScopes).mockResolvedValue(true); + repository.findProjectNames.mockResolvedValue(new Map()); + + await expect( + service.create(user, payload({ scope: 'project', projectId: 'project-gone' })), + ).rejects.toThrow(NotFoundError); + expect(repository.findProjectNames).toHaveBeenCalledWith(['project-gone']); + expect(skillService.create).not.toHaveBeenCalled(); + }); + }); + + describe('update', () => { + const update = (fields: Partial) => fields as SaveSkillDto; + const saved = { + versionId: 'v3', + version: 3, + created: true, + skill: { name: 'Brand voice', description: 'd', instructions: 'New.' }, + followingAgentIds: ['agent-1'], + }; + + it('saves the update for a user who may edit the skill', async () => { + skillService.save.mockResolvedValue(saved); + + const result = await service.update( + user, + 'skill_a', + update({ instructions: 'New.', baseSkillHash: 'base' }), + ); + + expect(skillService.save).toHaveBeenCalledWith( + 'skill_a', + { instructions: 'New.', baseSkillHash: 'base' }, + user.id, + ); + expect(skillService.canAccess).toHaveBeenCalledWith(user, visible[0], 'update'); + const { followingAgentIds: _following, ...response } = saved; + expect(result).toEqual({ + id: 'skill_a', + ...response, + skillHash: getAgentSkillHash(saved.skill), + }); + }); + + it('refuses a user who may not edit the skill', async () => { + skillService.canAccess.mockImplementation(async (_user, _skill, op) => op === 'read'); + + await expect( + service.update(user, 'skill_a', update({ instructions: 'New.' })), + ).rejects.toThrow(ForbiddenError); + expect(skillService.save).not.toHaveBeenCalled(); + }); + + it('answers a skill the user cannot see like a missing one', async () => { + skillService.canAccess.mockResolvedValue(false); + + await expect( + service.update(user, 'skill_a', update({ instructions: 'New.' })), + ).rejects.toThrow(NotFoundError); + }); + }); + + describe('delete', () => { + it('deletes for a user with the delete permission', async () => { + await service.delete(user, 'skill_a'); + + expect(skillService.canAccess).toHaveBeenCalledWith(user, visible[0], 'delete'); + expect(skillService.deleteSkill).toHaveBeenCalledWith('skill_a', ['project-1']); + }); + + it('names the agents of the projects the user may read in a conflict', async () => { + await service.delete(user, 'skill_a'); + + expect(projectScopeService.getProjectIds).toHaveBeenCalledWith(user, ['agent:read']); + }); + + it('names every agent for a user with the global agent scope', async () => { + projectScopeService.getProjectIds.mockResolvedValue(null); + + await service.delete(user, 'skill_a'); + + expect(skillService.deleteSkill).toHaveBeenCalledWith('skill_a', 'all'); + }); + + it('refuses a user without it', async () => { + skillService.canAccess.mockImplementation(async (_user, _skill, op) => op === 'read'); + + await expect(service.delete(user, 'skill_a')).rejects.toThrow(ForbiddenError); + expect(skillService.deleteSkill).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/packages/cli/src/modules/agents/__tests__/skills-hub-rollout.test.ts b/packages/cli/src/modules/agents/__tests__/skills-hub-rollout.test.ts new file mode 100644 index 00000000000..19f72720758 --- /dev/null +++ b/packages/cli/src/modules/agents/__tests__/skills-hub-rollout.test.ts @@ -0,0 +1,45 @@ +import { SKILLS_FLAG } from '@n8n/api-types'; +import type { Logger } from '@n8n/backend-common'; +import { mock } from 'vitest-mock-extended'; + +import type { PostHogClient } from '@/posthog'; + +import { SkillsHubRollout } from '../skills/skills-hub-rollout'; + +describe('SkillsHubRollout', () => { + const postHog = mock(); + let rollout: SkillsHubRollout; + + beforeEach(() => { + vi.resetAllMocks(); + rollout = new SkillsHubRollout(postHog, mock()); + }); + + it('is off until the flag is read', () => { + expect(rollout.isEnabled).toBe(false); + }); + + it('reads the flag for the instance once and keeps the value', async () => { + postHog.getFeatureFlagForInstance.mockResolvedValue(true); + + await rollout.init(); + postHog.getFeatureFlagForInstance.mockResolvedValue(false); + + expect(rollout.isEnabled).toBe(true); + expect(postHog.getFeatureFlagForInstance).toHaveBeenCalledTimes(1); + expect(postHog.getFeatureFlagForInstance).toHaveBeenCalledWith(SKILLS_FLAG); + expect(postHog.getFeatureFlags).not.toHaveBeenCalled(); + }); + + it.each([ + ['missing', undefined], + ['false', false], + ['a variant string', 'test'], + ])('stays off when the flag is %s', async (_label, value) => { + postHog.getFeatureFlagForInstance.mockResolvedValue(value); + + await rollout.init(); + + expect(rollout.isEnabled).toBe(false); + }); +}); diff --git a/packages/cli/src/modules/agents/__tests__/skills.controller.test.ts b/packages/cli/src/modules/agents/__tests__/skills.controller.test.ts new file mode 100644 index 00000000000..26dac7815e0 --- /dev/null +++ b/packages/cli/src/modules/agents/__tests__/skills.controller.test.ts @@ -0,0 +1,28 @@ +import { ControllerRegistryMetadata } from '@n8n/decorators'; +import { Container } from '@n8n/di'; + +import { SkillsController } from '../skills.controller'; + +/** + * The skills routes carry no scope decorator: `SkillsApiService` checks each skill row. + * A new route must add that check on purpose, so the set of routes is pinned here. + */ +const ROW_CHECKED_HANDLERS = ['create', 'delete', 'get', 'list', 'update']; + +describe('SkillsController routes', () => { + const metadata = Container.get(ControllerRegistryMetadata).getControllerMetadata( + SkillsController as never, + ); + + it('has only the routes that check access for each skill', () => { + expect([...metadata.routes.keys()].sort()).toEqual(ROW_CHECKED_HANDLERS); + }); + + it.each(ROW_CHECKED_HANDLERS)('%s needs a login and carries no route scope', (handlerName) => { + const route = metadata.routes.get(handlerName); + + expect(route?.accessScope).toBeUndefined(); + expect(route?.skipAuth).toBe(false); + expect(route?.allowUnauthenticated).toBe(false); + }); +}); diff --git a/packages/cli/src/modules/agents/__tests__/test-utils/skills-hub-flag.ts b/packages/cli/src/modules/agents/__tests__/test-utils/skills-hub-flag.ts new file mode 100644 index 00000000000..b31cf7ae25b --- /dev/null +++ b/packages/cli/src/modules/agents/__tests__/test-utils/skills-hub-flag.ts @@ -0,0 +1,14 @@ +import { Container } from '@n8n/di'; + +import { PostHogClient } from '@/posthog'; + +import { SkillsHubRollout } from '../../skills/skills-hub-rollout'; + +/** + * Sets the `125_context_skills` flag for the instance and reads it again, as a restart + * does. Tests that need the skills hub on or off call it instead of a config value. + */ +export async function setSkillsHubFlag(enabled: boolean): Promise { + vi.spyOn(Container.get(PostHogClient), 'getFeatureFlagForInstance').mockResolvedValue(enabled); + await Container.get(SkillsHubRollout).init(); +} diff --git a/packages/cli/src/modules/agents/__tests__/test-utils/stored-agent-config.ts b/packages/cli/src/modules/agents/__tests__/test-utils/stored-agent-config.ts index 01c2c551481..c6253de24b5 100644 --- a/packages/cli/src/modules/agents/__tests__/test-utils/stored-agent-config.ts +++ b/packages/cli/src/modules/agents/__tests__/test-utils/stored-agent-config.ts @@ -1,27 +1,125 @@ -import type { AgentJsonConfig, StoredAgentConfig } from '@n8n/api-types'; +import type { + AgentJsonConfig, + AgentJsonSkillConfig, + AgentSkill, + StoredAgentConfig, +} from '@n8n/api-types'; import { mock } from 'vitest-mock-extended'; -import { AgentSkillRefsService } from '../../agent-skill-refs.service'; +import type { AgentSkillRefsService } from '../../agent-skill-refs.service'; import type { AgentHistory } from '../../entities/agent-history.entity'; import type { Agent } from '../../entities/agent.entity'; import { composeJsonConfig } from '../../json-config/agent-config-composition'; -import type { AgentSkillRefs } from '../../json-config/agent-document'; -import type { AgentRepository } from '../../repositories/agent.repository'; +import { withoutLegacySkillRefs, type AgentSkillRefs } from '../../json-config/agent-document'; import type { AgentRunSource } from '../../utils/agent-published-snapshot'; /** - * A JSON document as the agent `schema` column stores it: the skill refs stay - * in the `skills` key, where the skill refs seam reads them. + * A JSON document as a stored config fixture. The fake skill refs seam of + * `createAgentSkillRefsService` reads the `skills` key of the fixture as the + * skill refs, so a caller test declares the refs in one place. The real seam + * reads the refs from the skills hub tables. */ export function storedAgentConfig(document: AgentJsonConfig): StoredAgentConfig { return document as unknown as StoredAgentConfig; } -/** The skill refs seam over a mocked repository. */ +export type FakeAgentSkillRefsService = ReturnType> & { + /** Skill bodies of the fake skills hub, keyed by skill id. */ + bodies: Record; + /** Draft refs written through the fake seam, keyed by agent id. */ + draftRefs: Map; + /** + * The skill version each published agent version pins, keyed by agent version id and + * then skill id. A revert pins the restored refs to these versions, as the real seam does. + */ + versionPins: Map>; +}; + +/** + * An in-memory skill refs seam for tests of its callers. A draft without + * written refs reads the refs of its `storedAgentConfig` fixture. Skill bodies + * come from `bodies`. + */ export function createAgentSkillRefsService( - agentRepository: AgentRepository = mock(), -): AgentSkillRefsService { - return new AgentSkillRefsService(agentRepository); + bodies: Record = {}, +): FakeAgentSkillRefsService { + const draftRefs = new Map(); + const versionPins = new Map>(); + const service = Object.assign(mock(), { + bodies, + draftRefs, + versionPins, + usesSkillsHub: true, + }); + const readDraftRefs = (agent: Pick): AgentJsonSkillConfig[] => + draftRefs.get(agent.id) ?? storedSkillRefs(agent); + const pickBodies = (refs: AgentSkillRefs) => + Object.fromEntries( + (refs ?? []).flatMap((ref) => + Object.hasOwn(service.bodies, ref.id) ? [[ref.id, service.bodies[ref.id]]] : [], + ), + ); + const writeRefs = (agent: Pick, refs: AgentSkillRefs) => { + draftRefs.set(agent.id, refs ?? []); + }; + + service.refsForDraft.mockImplementation(async (agent) => readDraftRefs(agent)); + const pinnedRefs = (versionId: string, refs: AgentJsonSkillConfig[]) => { + const pins = versionPins.get(versionId) ?? {}; + return refs.map(({ versionId: _dropped, ...ref }) => + Object.hasOwn(pins, ref.id) ? { ...ref, versionId: pins[ref.id] } : ref, + ); + }; + + // A published version's refs carry no `versionId`: its pins live in their own table. + service.refsForVersion.mockImplementation(async (version) => storedSkillRefs(version)); + service.readDraft.mockImplementation(async (agent) => { + const skillRefs = readDraftRefs(agent); + return { skillRefs, skills: pickBodies(skillRefs) }; + }); + service.readVersion.mockImplementation(async (version) => { + const skillRefs = storedSkillRefs(version); + return { skillRefs, skills: pickBodies(skillRefs) }; + }); + service.skillsForRefs.mockImplementation(async (_agent, refs) => pickBodies(refs)); + service.effectiveDraftRefs.mockImplementation(async (_agent, refs) => refs); + service.replaceDraftRefs.mockImplementation(async (agent, refs) => writeRefs(agent, refs)); + service.restoreDraftRefs.mockImplementation(async (agent, version, refs) => + writeRefs(agent, pinnedRefs(version.versionId, refs ?? [])), + ); + // A ref to a skill of the fake hub stays. A ref with only a body needs a creator, as + // in the real seam; the fake keeps its id instead of minting a new one. + service.createDraftRefs.mockImplementation(async (agent, refs, _bodies, creator) => { + writeRefs( + agent, + (refs ?? []).filter((ref) => Object.hasOwn(service.bodies, ref.id) || creator !== null), + ); + return readDraftRefs(agent); + }); + service.unpinDraftRef.mockImplementation(async (agent, skillId) => + writeRefs( + agent, + readDraftRefs(agent).map((ref) => + ref.id === skillId ? { type: ref.type, id: ref.id } : ref, + ), + ), + ); + // As the real seam: the legacy columns get the refs and bodies the draft runs. + service.versionSnapshot.mockImplementation(async (agent) => { + if (!agent.schema) return { schema: null, skills: null, pins: new Map() }; + const skillRefs = readDraftRefs(agent); + return { + schema: { + ...withoutLegacySkillRefs(agent.schema), + skills: skillRefs.map(({ id }) => ({ type: 'skill', id })), + } as unknown as StoredAgentConfig, + skills: pickBodies(skillRefs), + pins: new Map(skillRefs.map((ref) => [ref.id, ref.versionId ?? `${ref.id}-latest`])), + }; + }); + service.pinVersion.mockResolvedValue(undefined); + service.findOutdatedSkillIds.mockResolvedValue([]); + return service; } /** Fixture overrides, with `schema` given as a JSON document. */ @@ -33,20 +131,30 @@ export type AgentFixtureOverrides = WithDocumentSchema; export type AgentHistoryFixtureOverrides = WithDocumentSchema; -/** The skill refs that a `storedAgentConfig` fixture holds. */ -export function storedSkillRefs(agent: Pick): AgentSkillRefs { - const document = agent.schema as unknown as AgentJsonConfig | null; - return document?.skills; +/** The skill refs that a `storedAgentConfig` fixture holds, as the seam reads them: a list. */ +export function storedSkillRefs(source: object): AgentJsonSkillConfig[] { + if (!('schema' in source)) return []; + const document = source.schema as AgentJsonConfig | null; + return document?.skills ?? []; } -/** `composeJsonConfig` with the skill refs that a `storedAgentConfig` fixture holds. */ +/** + * `composeJsonConfig` with the skill refs that a `storedAgentConfig` fixture + * holds. Like the skill refs seam, a fixture without refs gives an empty list. + */ export function composeStoredJsonConfig( agent: Pick, ): AgentJsonConfig | null { return composeJsonConfig(agent, storedSkillRefs(agent)); } -/** A run source for an agent fixture, with the skill refs that its stored config holds. */ -export function storedRunSource(agent: Agent): AgentRunSource { - return { agent, skillRefs: storedSkillRefs(agent) }; +/** + * A run source for an agent fixture, with the skill refs that its stored + * config holds and the given skill bodies. + */ +export function storedRunSource( + agent: Agent, + skills: Record = {}, +): AgentRunSource { + return { agent, skillRefs: storedSkillRefs(agent), skills }; } diff --git a/packages/cli/src/modules/agents/adapters/agents-credential-provider.ts b/packages/cli/src/modules/agents/adapters/agents-credential-provider.ts index c4af819b241..1f1701e7a80 100644 --- a/packages/cli/src/modules/agents/adapters/agents-credential-provider.ts +++ b/packages/cli/src/modules/agents/adapters/agents-credential-provider.ts @@ -136,6 +136,7 @@ export class AgentsCredentialProvider // used to limit available credentials to the user's access when calling agent builder return await this.credentialsService.getCredentialsAUserCanUseInAWorkflow(this.user, { projectId: this.projectId, + excludePersonalRoute: true, }); } diff --git a/packages/cli/src/modules/agents/agent-channel-media-retention.task.ts b/packages/cli/src/modules/agents/agent-channel-media-retention.task.ts new file mode 100644 index 00000000000..d59c15e0414 --- /dev/null +++ b/packages/cli/src/modules/agents/agent-channel-media-retention.task.ts @@ -0,0 +1,63 @@ +import { resolveWhatsAppSettings } from '@n8n/api-types'; +import { Logger } from '@n8n/backend-common'; +import { Time } from '@n8n/constants'; +import { clusterTarget, intervalFromSeconds, SystemTask } from '@n8n/decorators'; +import type { SystemTaskSchedule } from '@n8n/decorators'; + +import { AgentChatAttachmentService } from './agent-chat-attachment.service'; +import { AgentRepository } from './repositories/agent.repository'; + +/** + * Deletes the media that customers sent to a WhatsApp channel once it is older + * than the channel's retention setting. Media from a channel that was later + * removed stays until its thread or agent is deleted. + */ +@SystemTask() +export class AgentChannelMediaRetentionTask implements SystemTask { + readonly name = 'agent-channel-media-retention'; + + readonly schedule: SystemTaskSchedule = intervalFromSeconds(Time.hours.toSeconds); + + // Deleting media that is already gone does nothing, so a retry is safe. + readonly target = clusterTarget({ + scheduler: { retryOnFailure: true }, + leaderTimer: { runOnTakeover: true, retryDelaySeconds: 60 }, + }); + + constructor( + private readonly agentRepository: AgentRepository, + private readonly attachmentService: AgentChatAttachmentService, + private readonly logger: Logger, + ) {} + + async run(signal: AbortSignal): Promise { + const agents = await this.agentRepository.findWithIntegrationType('whatsapp'); + for (const agent of agents) { + if (signal.aborted) return; + const integration = agent.integrations?.find((i) => i.type === 'whatsapp'); + if (integration?.type !== 'whatsapp') continue; + + const { mediaRetentionDays } = resolveWhatsAppSettings(integration.settings); + const before = new Date(Date.now() - mediaRetentionDays * Time.days.toMilliseconds); + // One agent's storage failure must not skip the rest; its rows stay for the next run. + try { + const deleted = await this.attachmentService.deleteFromSourceCreatedBefore( + { agentId: agent.id, source: 'whatsapp' }, + before, + signal, + ); + if (deleted > 0) { + this.logger.debug('[AgentChannelMediaRetention] Deleted expired WhatsApp media', { + agentId: agent.id, + deleted, + }); + } + } catch (error) { + this.logger.warn('[AgentChannelMediaRetention] Failed to delete expired WhatsApp media', { + agentId: agent.id, + error, + }); + } + } + } +} diff --git a/packages/cli/src/modules/agents/agent-chat-attachment.service.ts b/packages/cli/src/modules/agents/agent-chat-attachment.service.ts index d82a4ce9342..e2fbb0fbb90 100644 --- a/packages/cli/src/modules/agents/agent-chat-attachment.service.ts +++ b/packages/cli/src/modules/agents/agent-chat-attachment.service.ts @@ -22,6 +22,8 @@ import { threadBelongsTo } from './utils/agent-thread-access'; // (see `packages/@n8n/db/src/entities/binary-data-file.ts`) is a compile error. const ATTACHMENT_SOURCE_TYPE: SourceType = 'agent_chat_attachment'; +const RETENTION_BATCH_SIZE = 500; + export interface StoreInboundAttachmentParams { /** Null for inline agents, which have no `agents` row. */ agentId: string | null; @@ -160,6 +162,34 @@ export class AgentChatAttachmentService { await this.deleteAttachments(await this.repository.findBy({ agentId }), { agentId }); } + /** + * Deletes the files an agent received from one channel before `before`, in + * batches, so a large backlog does not load into memory at once. Deletes + * bytes before rows so a storage failure leaves the rows for the next run. + */ + async deleteFromSourceCreatedBefore( + scope: { agentId: string; source: string }, + before: Date, + signal?: AbortSignal, + ): Promise { + let deleted = 0; + while (!signal?.aborted) { + const batch = await this.repository.findFromSourceCreatedBefore( + scope, + before, + RETENTION_BATCH_SIZE, + ); + if (batch.length === 0) break; + await this.binaryDataService.deleteManyByBinaryDataId( + batch.map((attachment) => attachment.binaryDataId), + ); + await this.repository.delete(batch.map((attachment) => attachment.id)); + deleted += batch.length; + if (batch.length < RETENTION_BATCH_SIZE) break; + } + return deleted; + } + async deleteStoredData( binaryDataIds: string[], logContext: Record, diff --git a/packages/cli/src/modules/agents/agent-chat.controller.ts b/packages/cli/src/modules/agents/agent-chat.controller.ts index f57c7b0b54a..a7b032a5951 100644 --- a/packages/cli/src/modules/agents/agent-chat.controller.ts +++ b/packages/cli/src/modules/agents/agent-chat.controller.ts @@ -432,7 +432,7 @@ export class AgentChatController { chatSurface: 'preview', errorMode: 'forward', onChunk, - onBudgetNotice: () => send({ type: 'budget-notice', code: 'budget.alert' }), + onBudgetNotice: (notice) => send({ type: 'budget-notice', ...notice }), onExecutionStarted, abortSignal, }); diff --git a/packages/cli/src/modules/agents/agent-checkpoint-pruning.task.ts b/packages/cli/src/modules/agents/agent-checkpoint-pruning.task.ts index a3b13b810b4..0a453ce9f5d 100644 --- a/packages/cli/src/modules/agents/agent-checkpoint-pruning.task.ts +++ b/packages/cli/src/modules/agents/agent-checkpoint-pruning.task.ts @@ -1,7 +1,7 @@ import { DatabaseConfig, statementTimeoutSeconds } from '@n8n/config'; import { Time } from '@n8n/constants'; -import { intervalFromSeconds, SystemTask, timeoutAfterLimit } from '@n8n/decorators'; -import type { SystemTaskEffects, SystemTaskPlacement, SystemTaskSchedule } from '@n8n/decorators'; +import { clusterTarget, intervalFromSeconds, SystemTask, timeoutAfterLimit } from '@n8n/decorators'; +import type { SystemTaskSchedule } from '@n8n/decorators'; import { N8NCheckpointStorage } from './integrations/n8n-checkpoint-storage'; import { AgentBackgroundJobService } from './background/agent-background-job.service'; @@ -16,23 +16,22 @@ export class AgentCheckpointPruningTask implements SystemTask { readonly schedule: SystemTaskSchedule = intervalFromSeconds(Time.hours.toSeconds); - readonly effects: SystemTaskEffects = 'idempotent'; - - readonly placement: SystemTaskPlacement = { - scope: 'cluster', - durable: true, - runOnTakeover: true, - }; - - readonly retryDelaySeconds = 30; - - // The checkpoint step is one UPDATE that ignores the signal. A timeout that - // stops the run before the UPDATE ends lets the next run start a second one, - // so it waits for the statement timeout first. - readonly timeoutSeconds = timeoutAfterLimit( - statementTimeoutSeconds(this.databaseConfig), - 5 * Time.minutes.toSeconds, - ); + readonly target = clusterTarget({ + scheduler: { + retryOnFailure: true, + // The checkpoint step is one UPDATE that ignores the signal. A timeout that + // stops the run before the UPDATE ends lets the next run start a second one, + // so it waits for the statement timeout first. + timeoutSeconds: timeoutAfterLimit( + statementTimeoutSeconds(this.databaseConfig), + 5 * Time.minutes.toSeconds, + ), + }, + leaderTimer: { + runOnTakeover: true, + retryDelaySeconds: 30, + }, + }); constructor( private readonly databaseConfig: DatabaseConfig, diff --git a/packages/cli/src/modules/agents/agent-config.service.ts b/packages/cli/src/modules/agents/agent-config.service.ts index 6f3b6bb7070..49be52d14f4 100644 --- a/packages/cli/src/modules/agents/agent-config.service.ts +++ b/packages/cli/src/modules/agents/agent-config.service.ts @@ -22,7 +22,6 @@ import { AgentPolicyService } from './agent-policy.service'; import { AgentSaveCompletionService } from './agent-save-completion.service'; import { AgentSetupCompletionService } from './agent-setup-completion.service'; import { AgentSkillRefsService } from './agent-skill-refs.service'; -import { AgentSkillsService } from './agent-skills.service'; import type { Agent } from './entities/agent.entity'; import { syncAgentIntegrations } from './integrations/integrations-sync'; import { composeJsonConfig, decomposeJsonConfig } from './json-config/agent-config-composition'; @@ -63,7 +62,6 @@ export class AgentConfigService { private readonly logger: Logger, private readonly agentRepository: AgentRepository, private readonly agentTaskRepository: AgentTaskRepository, - private readonly agentSkillsService: AgentSkillsService, private readonly configPreparation: AgentConfigPreparationService, private readonly setupCompletionService: AgentSetupCompletionService, private readonly transactionRunner: TransactionRunner, @@ -144,6 +142,14 @@ export class AgentConfigService { config, clearOmitted, ); + if (replacement.nextSchema.skills !== undefined) { + // Validate, store and report the refs that are saved, not the submitted ones. + replacement.nextSchema.skills = await this.agentSkillRefs.effectiveDraftRefs( + entity, + replacement.nextSchema.skills, + {}, + ); + } await this.agentPolicyService.enforceSave( projectId, agentId, @@ -260,8 +266,13 @@ export class AgentConfigService { if (writesField(config, 'tools', clearOmitted)) { this.removeUnreferencedCustomTools(entity, config); } - if (writesField(config, 'skills', clearOmitted)) { - this.agentSkillsService.removeUnreferencedSkills(entity, config); + // With the hub off, bodies live on the agent row: drop the ones no ref keeps, as on + // master. With the hub on, a detached skill stays in the hub. + if (!this.agentSkillRefs.usesSkillsHub && writesField(config, 'skills', clearOmitted)) { + const referenced = new Set((config.skills ?? []).map((ref) => ref.id)); + entity.skills = Object.fromEntries( + Object.entries(entity.skills ?? {}).filter(([id]) => referenced.has(id)), + ); } } @@ -359,7 +370,6 @@ export class AgentConfigService { : []; pruneMissingConfigReferences(config, previousSchema, { tools: entity.tools ?? {}, - skills: entity.skills ?? {}, taskIds: new Set(existingTaskIds), }); const resolvedSubAgents = await this.reconcileSubAgentReferences(config, entity); diff --git a/packages/cli/src/modules/agents/agent-definition.service.ts b/packages/cli/src/modules/agents/agent-definition.service.ts index 2f92766fd96..fa4e3aa146d 100644 --- a/packages/cli/src/modules/agents/agent-definition.service.ts +++ b/packages/cli/src/modules/agents/agent-definition.service.ts @@ -40,29 +40,34 @@ export class AgentDefinitionService { const skillRefs = pending ? pending.skillRefs : await this.agentSkillRefs.refsForDraft(agent, ctx); + const skills = await this.agentSkillRefs.skillsForRefs(agent, skillRefs, ctx); return { - ...getAgentDefinitionContent(agent, skillRefs), + ...getAgentDefinitionContent(agent, skillRefs, skills), tasks: new Map(tasks.map((task) => [task.id, getAgentTaskBody(task)])), }; } async readVersion(version: AgentHistory, ctx: OperationContext = {}): Promise { const tasks = await this.taskSnapshotRepository.findByVersionId(version.versionId, ctx); - const skillRefs = await this.agentSkillRefs.refsForVersion(version, ctx); + const { skillRefs, skills } = await this.agentSkillRefs.readVersion(version, ctx); return { - ...getAgentDefinitionContent(version, skillRefs), + ...getAgentDefinitionContent(version, skillRefs, skills), tasks: new Map(tasks.map((task) => [task.taskId, getAgentTaskBody(task)])), }; } /** * Replace the draft atomically. Return whether task bodies changed. - * The caller sets the version and integrations. + * The caller sets the version and integrations. The skill bodies of the + * definition are not written: skills live in the skills hub. With + * `skillPinsFrom`, each skill ref is pinned to the version that this + * published version ran (revert). */ async replaceDraft( agent: Agent, definition: AgentDefinition, ctx: OperationContext = {}, + skillPinsFrom?: Pick, ): Promise { // Preserve workflow input names in the JSON configuration. const document = structuredClone(definition.schema); @@ -72,10 +77,13 @@ export class AgentDefinitionService { return await this.transactionRunner.run(ctx, async (txCtx) => { agent.schema = config; agent.tools = deepCopy(definition.tools); - agent.skills = deepCopy(definition.skills); if (agent.schema) agent.name = agent.schema.name; await saveAgentDraftFenced(this.agentRepository, agent, txCtx); - await this.agentSkillRefs.replaceDraftRefs(agent, skillRefs, txCtx); + if (skillPinsFrom) { + await this.agentSkillRefs.restoreDraftRefs(agent, skillPinsFrom, skillRefs, txCtx); + } else { + await this.agentSkillRefs.replaceDraftRefs(agent, skillRefs, txCtx); + } return await this.taskRepository.replaceForAgent(agent.id, definition.tasks, txCtx); }); } diff --git a/packages/cli/src/modules/agents/agent-execution-orchestrator.service.ts b/packages/cli/src/modules/agents/agent-execution-orchestrator.service.ts index 65022daf9c2..13021e94f3b 100644 --- a/packages/cli/src/modules/agents/agent-execution-orchestrator.service.ts +++ b/packages/cli/src/modules/agents/agent-execution-orchestrator.service.ts @@ -4,6 +4,7 @@ import type { AgentMessageAuthor, AgentChatMessagesResponse, BudgetGuardrailConfig, + AgentBudgetNotice, } from '@n8n/api-types'; import { N8N_CHAT_INTEGRATION_TYPE } from '@n8n/api-types'; import { Logger } from '@n8n/backend-common'; @@ -126,7 +127,7 @@ export interface ExecuteForChatConfig extends ChatExecutionInput, ChatExecutionC */ previewChat?: boolean; /** Preview chat sends the approaching-budget card. The run continues. */ - onBudgetNotice?: () => void; + onBudgetNotice?: (notice: AgentBudgetNotice) => void; abortSignal?: AbortSignal; } @@ -186,7 +187,7 @@ export interface ResumeForChatConfig extends ChatExecutionCallbacks { /** The chat surface this resume runs under. Undefined for integrations. */ chatSurface?: AgentChatSurface; /** Preview chat sends the approaching-budget card. The run continues. */ - onBudgetNotice?: () => void; + onBudgetNotice?: (notice: AgentBudgetNotice) => void; /** Allows an automatic preview resume to overlap its predecessor's finalization. */ automaticPreviewContinuation?: boolean; abortSignal?: AbortSignal; @@ -250,7 +251,7 @@ export interface StreamChatResponseConfig extends ChatExecutionInput, ChatExecut /** The chat surface this turn runs under. Undefined for integrations and tasks. */ chatSurface?: AgentChatSurface; /** Preview chat sends the approaching-budget card. The run continues. */ - onBudgetNotice?: () => void; + onBudgetNotice?: (notice: AgentBudgetNotice) => void; abortSignal?: AbortSignal; sandboxPrincipalHash: AgentSandboxPrincipalHash; /** Hide the internal wake instruction from the execution transcript. */ diff --git a/packages/cli/src/modules/agents/agent-integration-management.service.ts b/packages/cli/src/modules/agents/agent-integration-management.service.ts index 2d3828a8fef..f30eccb1211 100644 --- a/packages/cli/src/modules/agents/agent-integration-management.service.ts +++ b/packages/cli/src/modules/agents/agent-integration-management.service.ts @@ -444,7 +444,7 @@ export class AgentIntegrationManagementService { const usableCredentials = await this.credentialsService.getCredentialsAUserCanUseInAWorkflow( user, - { projectId: agent.projectId }, + { projectId: agent.projectId, excludePersonalRoute: true }, ); const credential = usableCredentials.find((item) => item.id === integration.credentialId); if (!credential) { diff --git a/packages/cli/src/modules/agents/agent-interrupted-execution-sweep.task.ts b/packages/cli/src/modules/agents/agent-interrupted-execution-sweep.task.ts index 5abaf0805e0..f694b1e3884 100644 --- a/packages/cli/src/modules/agents/agent-interrupted-execution-sweep.task.ts +++ b/packages/cli/src/modules/agents/agent-interrupted-execution-sweep.task.ts @@ -1,5 +1,5 @@ -import { intervalFromSeconds, SystemTask } from '@n8n/decorators'; -import type { SystemTaskEffects, SystemTaskPlacement, SystemTaskSchedule } from '@n8n/decorators'; +import { clusterTarget, intervalFromSeconds, SystemTask } from '@n8n/decorators'; +import type { SystemTaskSchedule } from '@n8n/decorators'; import { AgentInterruptedExecutionSweeper } from './agent-interrupted-execution-sweeper'; @@ -15,13 +15,10 @@ export class AgentInterruptedExecutionSweepTask implements SystemTask { AgentInterruptedExecutionSweeper.LIVENESS_GRACE_SECONDS, ); - readonly effects: SystemTaskEffects = 'idempotent'; - - readonly placement: SystemTaskPlacement = { - scope: 'cluster', - durable: true, - runOnTakeover: true, - }; + readonly target = clusterTarget({ + scheduler: { retryOnFailure: true }, + leaderTimer: { runOnTakeover: true }, + }); constructor(private readonly sweeper: AgentInterruptedExecutionSweeper) {} diff --git a/packages/cli/src/modules/agents/agent-message-queue-consumer.service.ts b/packages/cli/src/modules/agents/agent-message-queue-consumer.service.ts index 027e7cfe94c..a2f4f51f853 100644 --- a/packages/cli/src/modules/agents/agent-message-queue-consumer.service.ts +++ b/packages/cli/src/modules/agents/agent-message-queue-consumer.service.ts @@ -243,7 +243,7 @@ export class AgentMessageQueueConsumer { abortSignal: signal, errorMode: 'forward', onChunk: (chunk) => emitChunkEvents(chunk, send), - onBudgetNotice: () => send({ type: 'budget-notice', code: 'budget.alert' }), + onBudgetNotice: (notice) => send({ type: 'budget-notice', ...notice }), }); if (result.status === 'completed') send({ type: 'done', sessionId: thread.id, executionId: admission.executionId }); diff --git a/packages/cli/src/modules/agents/agent-model-catalog.service.ts b/packages/cli/src/modules/agents/agent-model-catalog.service.ts index 00f835c8e6f..a1946fed69a 100644 --- a/packages/cli/src/modules/agents/agent-model-catalog.service.ts +++ b/packages/cli/src/modules/agents/agent-model-catalog.service.ts @@ -138,13 +138,13 @@ export class AgentModelCatalogService { return liveModels.map((live) => { const id = normalizeProviderModelId(provider, live.value); const catalogMatch = catalogModels[id] ?? catalogModels[stripSnapshotSuffix(id)]; + // The gateway names the models it serves; a name that only repeats the id does not count. + const liveName = normalizeProviderModelId(provider, live.name); + const gatewayName = liveName && liveName !== id ? liveName : undefined; + const priority = live.priority !== undefined ? { priority: live.priority } : {}; return catalogMatch - ? { ...catalogMatch, id } - : { - id, - name: normalizeProviderModelId(provider, live.name) || id, - toolCall: true, - }; + ? { ...catalogMatch, id, ...(gatewayName ? { name: gatewayName } : {}), ...priority } + : { id, name: gatewayName ?? id, toolCall: true, ...priority }; }); } diff --git a/packages/cli/src/modules/agents/agent-publish.service.ts b/packages/cli/src/modules/agents/agent-publish.service.ts index 1ddf720d4d2..d5dce3b726d 100644 --- a/packages/cli/src/modules/agents/agent-publish.service.ts +++ b/packages/cli/src/modules/agents/agent-publish.service.ts @@ -4,7 +4,6 @@ import { isDraftIntegration, type AgentConfigValidationResponse, type AgentJsonConfig, - type AgentSkill, type AgentVersionListItemDto, type StoredAgentConfig, } from '@n8n/api-types'; @@ -19,12 +18,11 @@ import { import { Container, Service } from '@n8n/di'; import { TELEMETRY_EVENT } from '@n8n/telemetry'; import isEqual from 'lodash/isEqual'; -import { deepCopy, UserError } from 'n8n-workflow'; +import { UserError } from 'n8n-workflow'; import { v4 as uuid } from 'uuid'; import { CredentialsService } from '@/credentials/credentials.service'; import { ConflictError, NotFoundError } from '@n8n/errors'; -import { getMissingSkillIds } from '@/modules/agents/utils/agent-missing-skill-ids'; import { Telemetry } from '@/telemetry'; import { AgentsCredentialProvider } from './adapters/agents-credential-provider'; @@ -48,7 +46,7 @@ import type { AgentHistory } from './entities/agent-history.entity'; import { AgentTask } from './entities/agent-task.entity'; import type { Agent } from './entities/agent.entity'; import { ChatIntegrationService } from './integrations/chat-integration.service'; -import { toAgentDocument, type AgentSkillRefs } from './json-config/agent-document'; +import { toAgentDocument } from './json-config/agent-document'; import { AgentHistoryRepository } from './repositories/agent-history.repository'; import { AgentTaskSnapshotRepository } from './repositories/agent-task-snapshot.repository'; import { AgentTaskRepository } from './repositories/agent-task.repository'; @@ -442,20 +440,28 @@ export class AgentPublishService { ): Promise { await this.enforceRevertPolicy(agent, context.user, version.schema); - const previousSchema = agent.schema - ? toAgentDocument(agent.schema, await this.agentSkillRefs.refsForDraft(agent, {})) - : null; + const previousSkillRefs = await this.agentSkillRefs.refsForDraft(agent, {}); + // With the hub on, the refs carry their pins. With it off, a revert can keep the ids + // and change the bodies, so compare the bodies too. + const previousSkills = structuredClone(agent.skills ?? {}); + const previousSchema = agent.schema ? toAgentDocument(agent.schema, previousSkillRefs) : null; const previousTools = agent.tools ?? {}; - const previousSkills = agent.skills ?? {}; - const { tasksChanged, nextSchema } = await this.transactionRunner.run({}, async (ctx) => { - const definition = await this.definitionService.readVersion(version, ctx); - definition.schema = draftSchemaFromVersion(definition.schema); - agent.versionId = nextVersionId; - return { - tasksChanged: await this.definitionService.replaceDraft(agent, definition, ctx), - nextSchema: definition.schema, - }; - }); + const { tasksChanged, nextSchema, nextSkillRefs } = await this.transactionRunner.run( + {}, + async (ctx) => { + const definition = await this.definitionService.readVersion(version, ctx); + definition.schema = draftSchemaFromVersion(definition.schema); + agent.versionId = nextVersionId; + // Each skill ref is pinned to the version that the published version ran. + // No skill row is written, so this needs no skill permission. + const changed = await this.definitionService.replaceDraft(agent, definition, ctx, version); + return { + tasksChanged: changed, + nextSchema: definition.schema, + nextSkillRefs: await this.agentSkillRefs.refsForDraft(agent, ctx), + }; + }, + ); const integrations = agent.integrations ?? []; await this.saveCompletion.configurationSaved( { @@ -466,7 +472,9 @@ export class AgentPublishService { by: context.modifiedBy, changedParts: diffAgentConfigParts(previousSchema, nextSchema, integrations, integrations, { tools: !isEqual(previousTools, agent.tools), - skills: !isEqual(previousSkills, agent.skills), + skills: + !isEqual(previousSkillRefs, nextSkillRefs) || + (!this.agentSkillRefs.usesSkillsHub && !isEqual(previousSkills, agent.skills ?? {})), tasks: tasksChanged, }), wasUnconfigured: false, @@ -566,27 +574,6 @@ export class AgentPublishService { ); } - private pickConfiguredSkillBodies( - config: StoredAgentConfig | null, - skillRefs: AgentSkillRefs, - skills: Record, - ): Record | null { - if (!config) return null; - - const missing = getMissingSkillIds(skillRefs, skills); - if (missing.length > 0) { - throw new UserError(`Cannot publish agent with missing skill bodies: ${missing.join(', ')}`); - } - - const snapshot: Record = {}; - for (const ref of skillRefs ?? []) { - const skill = skills[ref.id]; - if (skill) snapshot[ref.id] = deepCopy(skill); - } - - return snapshot; - } - private async readPublishTargetDocument( agent: Agent, targetHistory: AgentHistory | undefined, @@ -711,27 +698,30 @@ export class AgentPublishService { user: User, versionId: string, ) { - const skillRefs = await this.agentSkillRefs.refsForDraft(agent, ctx); try { - return await this.agentHistoryRepository.saveVersion( + const snapshot = await this.agentSkillRefs.versionSnapshot(agent, ctx); + const { schema, skills } = snapshot; + const history = await this.agentHistoryRepository.saveVersion( { versionId, agentId: agent.id, - // The stored config carries the skill refs of the draft into the version. - schema: agent.schema + schema: schema ? { - ...agent.schema, + ...schema, integrations: (agent.integrations ?? []).filter( (integration) => integration.type === N8N_CHAT_INTEGRATION_TYPE, ), } : null, tools: this.customToolsService.snapshotConfiguredTools(agent.schema, agent.tools ?? {}), - skills: this.pickConfiguredSkillBodies(agent.schema, skillRefs, agent.skills ?? {}), + skills, publishedBy: user, }, ctx, ); + // The skill pins need the `agent_history` row. + await this.agentSkillRefs.pinVersion(versionId, snapshot, ctx); + return history; } catch (error) { // Concurrent publishes of one draft can collide before they reach the revision fence. if (isUniqueConstraintError(error)) { diff --git a/packages/cli/src/modules/agents/agent-runnable-state.service.ts b/packages/cli/src/modules/agents/agent-runnable-state.service.ts index 74962cbc7c3..4376ded6e7c 100644 --- a/packages/cli/src/modules/agents/agent-runnable-state.service.ts +++ b/packages/cli/src/modules/agents/agent-runnable-state.service.ts @@ -1,3 +1,4 @@ +import type { AgentSkill } from '@n8n/api-types'; import type { User } from '@n8n/db'; import { Service } from '@n8n/di'; @@ -42,23 +43,28 @@ export class AgentRunnableStateService { isRunnable: boolean; hasPublishHistory: boolean; configHash: string | null; + skills: Record; skillHashes: Record; + outdatedSkillIds: string[]; } > { + // The skill bodies the draft runs, from the skills hub, keyed by skill id. + const { skillRefs, skills } = await this.agentSkillRefs.readDraft(agent, {}); // Base hashes for the optimistic-concurrency checks on config and skill writes. - const configHash = getAgentConfigHash( - composeJsonConfig(agent, await this.agentSkillRefs.refsForDraft(agent, {})), - ); + const configHash = getAgentConfigHash(composeJsonConfig(agent, skillRefs)); const skillHashes = Object.fromEntries( - Object.entries(agent.skills ?? {}).map(([id, skill]) => [id, getAgentSkillHash(skill)]), + Object.entries(skills).map(([id, skill]) => [id, getAgentSkillHash(skill)]), ); + const outdatedSkillIds = await this.agentSkillRefs.findOutdatedSkillIds(skillRefs, skills, {}); if (draftValidation) { const hasPublishHistory = await this.agentPublishService.hasPublishHistory(agent.id); return Object.assign(agent, { isRunnable: true, hasPublishHistory, configHash, + skills, skillHashes, + outdatedSkillIds, }); } @@ -82,7 +88,9 @@ export class AgentRunnableStateService { isRunnable: validation.status === 'valid', hasPublishHistory, configHash, + skills, skillHashes, + outdatedSkillIds, }); } } diff --git a/packages/cli/src/modules/agents/agent-runtime-reconstruction.service.ts b/packages/cli/src/modules/agents/agent-runtime-reconstruction.service.ts index ae822a7817c..41e9a4dfd8f 100644 --- a/packages/cli/src/modules/agents/agent-runtime-reconstruction.service.ts +++ b/packages/cli/src/modules/agents/agent-runtime-reconstruction.service.ts @@ -37,6 +37,8 @@ import { nanoid } from 'nanoid'; import { ActiveExecutions } from '@/active-executions'; import { N8N_VERSION } from '@/constants'; import { CredentialsFinderService } from '@n8n/backend-services'; +import { isCredSharingEnabled } from '@/constants/credential-sharing'; +import { CredentialsService } from '@/credentials/credentials.service'; import { SubworkflowPolicyChecker } from '@/executions/pre-execution-checks'; import type { AgentRunTelemetryType } from '@/interfaces'; import { EphemeralNodeExecutor } from '@/node-execution'; @@ -288,10 +290,11 @@ export class AgentRuntimeReconstructionService { private readonly credentialsFinderService: CredentialsFinderService, private readonly workflowFinderService: WorkflowFinderService, private readonly agentChatAttachmentService: AgentChatAttachmentService, + private readonly credentialsService: CredentialsService, ) {} async reconstructFromAgentEntity( - { agent: agentEntity, skillRefs }: AgentRunSource, + { agent: agentEntity, skillRefs, skills }: AgentRunSource, credentialProvider: CredentialProvider, runType: AgentRunTelemetryType, integrationType?: string, @@ -335,7 +338,7 @@ export class AgentRuntimeReconstructionService { unavailableTools = filtered.unavailable; } - const { toolDescriptors, toolCodeByName } = getAgentRuntimeAssets(agentEntity); + const { toolDescriptors, toolCodeByName } = getAgentRuntimeAssets(agentEntity, skills); const subAgentDelegation = await this.createSubAgentDelegationConfig( config, agentEntity.projectId, @@ -348,7 +351,7 @@ export class AgentRuntimeReconstructionService { credentialProvider, toolDescriptors, toolCodeByName, - skills: agentEntity.skills ?? {}, + skills, runtimeProfile: 'top-level', supportsHitl, runType, @@ -392,6 +395,10 @@ export class AgentRuntimeReconstructionService { unavailable: UnavailableTool[]; }> { const canExecute = await userHasScopes(user, ['workflow:execute'], false, { projectId }); + // Load once per pass, and only when a node tool uses credentials. + let usableIdsLoad: Promise | undefined> | undefined; + const loadUsableIds = async () => + await (usableIdsLoad ??= this.loadAgentUsableCredentialIds(projectId, user)); const filtered: AgentJsonToolConfig[] = []; const unavailable: UnavailableTool[] = []; const grantedCredentialIds = new Set(); @@ -404,7 +411,7 @@ export class AgentRuntimeReconstructionService { filtered.push(ref); continue; } - const access = await this.checkToolAccess(ref, projectId, user, canExecute); + const access = await this.checkToolAccess(ref, projectId, user, canExecute, loadUsableIds); if (access && 'reason' in access) { unavailable.push(access); continue; @@ -430,11 +437,26 @@ export class AgentRuntimeReconstructionService { }; } + /** Returns the credential IDs agents can use, or `undefined` when no restriction applies. */ + private async loadAgentUsableCredentialIds( + projectId: string, + user: User, + ): Promise | undefined> { + if (!isCredSharingEnabled()) return undefined; + + const usable = await this.credentialsService.getCredentialsAUserCanUseInAWorkflow(user, { + projectId, + excludePersonalRoute: true, + }); + return new Set(usable.map((credential) => credential.id)); + } + private async checkToolAccess( ref: Exclude, projectId: string, user: User, canExecute: boolean, + loadUsableIds: () => Promise | undefined>, ): Promise { const denied = (message: string): UnavailableTool => ({ toolName: toolRefName(ref), @@ -459,6 +481,10 @@ export class AgentRuntimeReconstructionService { if (credentials.some((credential) => credential === null)) { return denied('The user cannot read a credential the tool uses'); } + const usableIds = credentialIds.length > 0 ? await loadUsableIds() : undefined; + if (usableIds && !credentialIds.every((id) => usableIds.has(id))) { + return denied('The tool uses a personal credential that agents cannot use yet'); + } return { credentialIds, workflowIds: [] }; } @@ -496,6 +522,10 @@ export class AgentRuntimeReconstructionService { ), ); if (credentials.some((credential) => credential === null)) return false; + if (snapshot.credentialIds.length > 0) { + const usableIds = await this.loadAgentUsableCredentialIds(projectId, user); + if (usableIds && !snapshot.credentialIds.every((id) => usableIds.has(id))) return false; + } const workflows = await Promise.all( snapshot.workflowIds.map( @@ -680,10 +710,13 @@ export class AgentRuntimeReconstructionService { aiMcpFetch: ReturnType, mcpServerAttributions: Map, ) { - const { credentialProvider, projectId, memoryOwnerAgentId, instrumentation } = options; + const { credentialProvider, projectId, memoryOwnerAgentId, instrumentation, runtimeProfile } = + options; return async (server: AgentJsonMcpServerConfig) => await buildMcpClientForServer(server, { credentialProvider, + // Inline agents have no checkpoint storage, and their schema rejects approval policies. + nonInterrupting: runtimeProfile === 'inline', oauthService: this.oauthService, projectId, proxyFetch: aiMcpFetch, diff --git a/packages/cli/src/modules/agents/agent-skill-refs.service.ts b/packages/cli/src/modules/agents/agent-skill-refs.service.ts index 5c4233f3877..4b5a1f72777 100644 --- a/packages/cli/src/modules/agents/agent-skill-refs.service.ts +++ b/packages/cli/src/modules/agents/agent-skill-refs.service.ts @@ -1,76 +1,518 @@ import type { AgentJsonSkillConfig, - OpaqueStoredSkillRefs, + AgentSkill, + AgentSkillAvailability, StoredAgentConfig, } from '@n8n/api-types'; -import type { OperationContext } from '@n8n/db'; +import type { OperationContext, User } from '@n8n/db'; import { Service } from '@n8n/di'; -import { UnexpectedError } from 'n8n-workflow'; +import { deepCopy, UnexpectedError, UserError } from 'n8n-workflow'; import type { AgentHistory } from './entities/agent-history.entity'; import type { Agent } from './entities/agent.entity'; -import type { AgentSkillRefs } from './json-config/agent-document'; +import { withoutLegacySkillRefs, type AgentSkillRefs } from './json-config/agent-document'; import { AgentRepository } from './repositories/agent.repository'; +import { SkillRepository } from './repositories/skill.repository'; +import { SkillService, toAgentSkill, type SkillRef } from './skills/skill.service'; +import { SkillsHubRollout } from './skills/skills-hub-rollout'; +import { getAgentSkillHash } from './utils/agent-config-hash'; +import { getMissingSkillIds } from './utils/agent-missing-skill-ids'; +import { generateAgentResourceId } from './utils/agent-resource-id'; + +/** The `agent_history` skill columns of one publish, and the hub versions to pin. */ +export type PublishSnapshot = { + schema: StoredAgentConfig | null; + skills: Record | null; + /** Hub skill version id for each skill ref, in draft order. Empty with the hub off. */ + pins: Map; +}; + +/** Skill refs and the skill bodies they resolve to, keyed by skill id. */ +export interface AgentSkillsSnapshot { + skillRefs: AgentJsonSkillConfig[]; + skills: Record; +} /** * The one seam for the skill refs of an agent draft and of a published agent - * version. All other code reads and writes skill refs through this service. + * version, and for the skill bodies they resolve to. All other code reads and + * writes skill refs through this service. * - * The refs are kept in the legacy `skills` key of the stored `schema` JSON - * (`agents.schema`, `agent_history.schema`). Only this file reads or writes - * that key. + * With the skills hub on (the `125_context_skills` flag), the refs of a draft are the + * `agent_skill_dependency` rows and the refs of a published version are the + * `agent_version_skill_dependency` pins, in attach order. The skill bodies come + * from the skills hub. + * + * With the skills hub off, the refs are the `skills` key of the stored `schema` + * and the bodies are the `skills` column, as before the skills hub. A ref with + * `enabled: false` is hidden. Its body stays in the `skills` column. */ @Service() export class AgentSkillRefsService { - constructor(private readonly agentRepository: AgentRepository) {} + constructor( + private readonly skillRepository: SkillRepository, + private readonly skillService: SkillService, + private readonly agentRepository: AgentRepository, + private readonly rollout: SkillsHubRollout, + ) {} - /** Skill refs of the agent draft, in document order. */ - async refsForDraft( - agent: Pick, - _ctx: OperationContext, - ): Promise { - return readLegacySkillRefs(agent.schema); + get usesSkillsHub(): boolean { + return this.rollout.isEnabled; } - /** Skill refs of one published agent version, in document order. */ + /** Skill refs of the agent draft, in attach order. A pinned ref has `versionId`. */ + async refsForDraft( + agent: Pick, + ctx: OperationContext, + ): Promise { + if (!this.usesSkillsHub) return readLegacyRefs(agent.schema); + const rows = (await this.skillRepository.findDependencies([agent.id], ctx)).get(agent.id) ?? []; + return toSkillRefs( + rows.map(({ skillId, versionId }) => ({ id: skillId, ...(versionId ? { versionId } : {}) })), + ); + } + + /** + * Skill refs of one published agent version, in the order of the draft at + * publish. Every ref of a version is pinned, so the refs carry no `versionId`. + */ async refsForVersion( - version: Pick, - _ctx: OperationContext, - ): Promise { - return readLegacySkillRefs(version.schema); + version: Pick, + ctx: OperationContext, + ): Promise { + if (!this.usesSkillsHub) return readLegacyRefs(version.schema); + const skillIds = await this.skillRepository.findPinnedSkillIds(version.versionId, ctx); + return toSkillRefs(skillIds.map((id) => ({ id }))); + } + + /** The refs of the agent draft and the skill bodies the draft runs. */ + async readDraft( + agent: Pick, + ctx: OperationContext, + ): Promise { + const skillRefs = await this.refsForDraft(agent, ctx); + return { skillRefs, skills: await this.skillsForRefs(agent, skillRefs, ctx) }; + } + + /** The refs of one published agent version and the pinned skill bodies. */ + async readVersion( + version: Pick, + ctx: OperationContext, + ): Promise { + if (!this.usesSkillsHub) { + const skillRefs = readLegacyRefs(version.schema); + return { skillRefs, skills: pickBodies(version.skills ?? {}, skillRefs) }; + } + const pinned = await this.skillRepository.findPinned(version.versionId, ctx); + const skillRefs = toSkillRefs([...pinned.keys()].map((id) => ({ id }))); + const skills = Object.fromEntries( + [...pinned].map(([skillId, row]) => [skillId, toAgentSkill(row)]), + ); + return { skillRefs, skills }; + } + + /** + * The skill bodies that these draft refs run, keyed by skill id: the pinned + * version of a ref with `versionId`, else the latest saved version. + */ + async skillsForRefs( + agent: Pick, + skillRefs: AgentSkillRefs, + ctx: OperationContext, + ): Promise> { + if (!skillRefs?.length) return {}; + if (!this.usesSkillsHub) return pickBodies(agent.skills ?? {}, skillRefs); + return await this.skillService.resolveForAgentDraft(toServiceRefs(skillRefs), ctx); + } + + async findOutdatedSkillIds( + skillRefs: AgentJsonSkillConfig[], + skills: Record, + ctx: OperationContext, + ): Promise { + if (!this.usesSkillsHub) return []; + const pinnedSkillIds = skillRefs.flatMap((ref) => (ref.versionId ? [ref.id] : [])); + const latestSkills = await this.skillsForRefs( + { skills: {} }, + pinnedSkillIds.map((id) => ({ type: 'skill', id })), + ctx, + ); + return pinnedSkillIds.filter((id) => { + const latest = latestSkills[id]; + const pinned = skills[id]; + return ( + latest !== undefined && + pinned !== undefined && + getAgentSkillHash(latest) !== getAgentSkillHash(pinned) + ); + }); + } + + /** + * The refs that `replaceDraftRefs` would keep, without writing them: unknown ids + * are dropped, and a new ref that the agent may not attach throws. Callers use it + * to validate and report the refs that are saved, not the submitted ones. + */ + async effectiveDraftRefs( + agent: Pick, + refs: AgentJsonSkillConfig[], + ctx: OperationContext, + ): Promise { + if (!this.usesSkillsHub) { + const existingIds = new Set(readLegacyRefs(agent.schema).map((ref) => ref.id)); + return refs.filter( + (ref) => existingIds.has(ref.id) || Object.hasOwn(agent.skills ?? {}, ref.id), + ); + } + const checked = await this.skillService.checkRefs( + { id: agent.id, projectId: agent.projectId }, + toServiceRefs(refs), + ctx, + ); + return toSkillRefs(checked); } /** * Replace the skill refs of the agent draft. Call it in the same transaction * as `saveAgentDraftFenced`, with the same `ctx`, after the fenced save. - * The agent must have a config when `refs` is set. + * A new ref must be attachable to the agent and must not clash by name. A ref + * keeps its pin only when the draft already has that pin. */ - async replaceDraftRefs(agent: Agent, refs: AgentSkillRefs, ctx: OperationContext): Promise { - if (!agent.schema) { - if (refs === undefined) return; + async replaceDraftRefs( + agent: Pick, + refs: AgentSkillRefs, + ctx: OperationContext, + ): Promise { + if (!agent.schema && refs?.length) { throw new UnexpectedError('Cannot set skill refs on an agent without a config'); } - agent.schema = withLegacySkillRefs(agent.schema, refs); - await this.agentRepository.updateDraftSchema(agent, ctx); + if (!this.usesSkillsHub) { + if (!agent.schema) return; + const existingIds = new Set(readLegacyRefs(agent.schema).map((ref) => ref.id)); + const kept = (refs ?? []).filter( + (ref) => existingIds.has(ref.id) || Object.hasOwn(agent.skills ?? {}, ref.id), + ); + await this.writeLegacyDraft(agent, agent.schema, kept, agent.skills ?? {}, ctx); + return; + } + const checked = await this.skillService.checkRefs( + { id: agent.id, projectId: agent.projectId }, + toServiceRefs(refs ?? []), + ctx, + ); + await this.writeDependencies(agent.id, checked, ctx); + } + + /** + * Revert: set the refs of the agent draft to the refs of a published version, + * each pinned to the version that the published version ran. This writes no + * skill row and needs no skill permission. + */ + async restoreDraftRefs( + agent: Pick, + version: Pick, + refs: AgentSkillRefs, + ctx: OperationContext, + ): Promise { + if (!this.usesSkillsHub) { + if (!agent.schema) return; + await this.writeLegacyDraft( + agent, + agent.schema, + refs ?? [], + deepCopy(version.skills ?? {}), + ctx, + ); + return; + } + const restored = await this.skillService.restoreFromVersion( + version.versionId, + toServiceRefs(refs ?? []), + ctx, + ); + await this.writeDependencies(agent.id, restored, ctx); + } + + /** + * Remove the pin of one draft ref, so the draft follows the latest saved + * version of the skill. A save of the skill from this agent calls it. + */ + async unpinDraftRef( + agent: Pick, + skillId: string, + ctx: OperationContext, + ): Promise { + const refs = await this.refsForDraft(agent, ctx); + await this.writeDependencies( + agent.id, + refs.map(({ id, versionId }) => (id === skillId || !versionId ? { id } : { id, versionId })), + ctx, + ); + } + + /** + * Create with a config (duplicate, import, eval seeding). A ref to a hub + * skill stays a ref. A ref to an agent skill of another agent in the same + * project gets a copy. A ref with a body but no hub skill gets a new agent + * skill. Both new skills belong to this agent only, so deleting the agent + * deletes them. A new skill gets a new id, and the ref points to it. A ref + * with neither is dropped, and so is a ref with only a body when no user + * creates the skill. The new skills need no skill scope: they are part of the + * agent, and the caller already checked the agent permission. Returns the refs + * that the draft now has. + */ + async createDraftRefs( + agent: Pick, + refs: AgentSkillRefs, + bodies: Record, + creator: User | null, + ctx: OperationContext, + ): Promise { + if (!refs?.length) return []; + if (!this.usesSkillsHub) { + if (!agent.schema) return []; + const kept = refs.filter((ref) => Object.hasOwn(bodies, ref.id)); + await this.writeLegacyDraft(agent, agent.schema, kept, pickBodies(bodies, kept), ctx); + return readLegacyRefs(agent.schema); + } + const found = new Map( + ( + await this.skillRepository.findByIds( + refs.map((ref) => ref.id), + ctx, + ) + ).map((skill) => [skill.id, skill]), + ); + // Copy only the agent skills of agents in this project (a duplicate). Any other + // agent skill stays a plain ref, so `checkRefs` refuses it without reading its body. + const otherAgents = await this.skillRepository.findAgents( + [...found.values()].flatMap((skill) => + skill.agentId && skill.agentId !== agent.id ? [skill.agentId] : [], + ), + ctx, + ); + const otherAgentSkillIds = refs.flatMap((ref) => { + const skill = found.get(ref.id); + if (!skill?.agentId || skill.agentId === agent.id) return []; + return otherAgents.get(skill.agentId)?.projectId === agent.projectId ? [ref.id] : []; + }); + const otherAgentBodies = + otherAgentSkillIds.length > 0 + ? await this.skillService.resolveForAgentDraft( + otherAgentSkillIds.map((id) => ({ id })), + ctx, + ) + : {}; + const next: AgentJsonSkillConfig[] = []; + for (const ref of refs) { + const skill = found.get(ref.id); + const copiesAgentSkill = otherAgentSkillIds.includes(ref.id); + if (skill && !copiesAgentSkill) { + next.push({ type: 'skill', id: ref.id }); + continue; + } + const source = copiesAgentSkill ? otherAgentBodies : bodies; + const body = Object.hasOwn(source, ref.id) ? source[ref.id] : undefined; + // The new skill belongs to this agent only, so creating the agent is enough. + if (!body || creator === null) continue; + const id = await this.skillService.create( + { + // An inline body or a copy becomes a skill of this agent only, as the startup + // copy does. It takes its project from the agent, and goes with the agent. + target: { projectId: null, agentId: agent.id }, + skill: body, + source: 'agent', + createdById: creator.id, + }, + ctx, + ); + next.push({ type: 'skill', id }); + } + await this.replaceDraftRefs(agent, next, ctx); + return toSkillRefs(next); + } + + async createSkills( + agent: Pick, + skills: AgentSkill[], + creatorId: string, + availableTo: AgentSkillAvailability, + ctx: OperationContext, + ): Promise { + if (!this.usesSkillsHub) { + const bodies = { ...(agent.skills ?? {}) }; + const ids = skills.map((skill) => { + const id = generateAgentResourceId('skill', Object.keys(bodies)); + bodies[id] = skill; + return id; + }); + agent.skills = bodies; + await this.agentRepository.updateDraftSkills(agent, ctx); + return ids; + } + const ids: string[] = []; + for (const skill of skills) { + ids.push( + await this.skillService.create( + { + target: targetFor(agent, availableTo), + skill, + source: 'agent', + createdById: creatorId, + }, + ctx, + ), + ); + } + return ids; + } + + /** + * What a publish writes to `agent_history`. Both settings write the legacy columns in + * full: the skill refs in `schema.skills` and their bodies in `skills`. With the skills + * hub on, the bodies are the versions the draft runs, so a published agent keeps + * running after the flag is turned off. `pins` are the hub versions to pin once the + * `agent_history` row exists (see `pinVersion`); empty with the hub off. Call it in + * the publish transaction: it takes the publish lock on the skills. + */ + async versionSnapshot( + agent: Pick, + ctx: OperationContext, + ): Promise { + if (!agent.schema) return { schema: null, skills: null, pins: new Map() }; + if (!this.usesSkillsHub) { + const skillRefs = readLegacyRefs(agent.schema); + const skills = pickBodies(agent.skills ?? {}, skillRefs); + const missing = getMissingSkillIds(skillRefs, skills); + if (missing.length > 0) { + throw new UserError( + `Cannot publish agent with missing skill bodies: ${missing.join(', ')}`, + ); + } + return { schema: agent.schema, skills: deepCopy(skills), pins: new Map() }; + } + const refs = await this.refsForDraft(agent, ctx); + if (refs.length === 0) { + return { + schema: { + ...withoutLegacySkillRefs(agent.schema), + skills: [], + } as unknown as StoredAgentConfig, + skills: {}, + pins: new Map(), + }; + } + const { skills, versionByRef } = await this.skillService.snapshotForPublish( + toServiceRefs(refs), + ctx, + ); + const missing = refs.filter((ref) => !versionByRef.has(ref.id)).map((ref) => ref.id); + if (missing.length > 0) { + throw new UserError(`Cannot publish agent with missing skills: ${missing.join(', ')}`); + } + const schema = { + ...withoutLegacySkillRefs(agent.schema), + skills: refs.map(({ id }) => ({ type: 'skill', id })), + } as unknown as StoredAgentConfig; + return { schema, skills, pins: versionByRef }; + } + + /** + * Publish: pin each draft ref to the saved version it runs now. Call it in + * the publish transaction, after the `agent_history` row exists. + */ + /** Publish, after the `agent_history` row exists: pin the versions of `versionSnapshot`. */ + async pinVersion( + agentVersionId: string, + snapshot: PublishSnapshot, + ctx: OperationContext, + ): Promise { + if (snapshot.pins.size === 0) return; + await this.skillService.pinForPublish(agentVersionId, snapshot.pins, ctx); + } + + async availabilityOf( + skillId: string, + ctx: OperationContext, + ): Promise { + const [skill] = await this.skillRepository.findByIds([skillId], ctx); + if (!skill) return undefined; + if (skill.agentId) return 'agent'; + return skill.projectId ? 'project' : 'instance'; + } + + async setAvailability( + agent: Pick, + skillId: string, + availableTo: AgentSkillAvailability, + ctx: OperationContext, + ): Promise { + await this.skillService.changeTarget(skillId, targetFor(agent, availableTo), agent.id, ctx); + } + + private async writeLegacyDraft( + agent: Pick, + schema: StoredAgentConfig, + refs: AgentJsonSkillConfig[], + skills: Record, + ctx: OperationContext, + ): Promise { + const { skills: _previous, ...rest } = schema; + agent.schema = { + ...rest, + skills: refs.map(({ id }) => ({ type: 'skill', id })), + } as unknown as StoredAgentConfig; + agent.skills = skills; + await this.agentRepository.updateDraftSkills(agent, ctx); + } + + private async writeDependencies( + agentId: string, + refs: SkillRef[], + ctx: OperationContext, + ): Promise { + await this.skillRepository.replaceDependencies( + agentId, + refs.map((ref) => ({ skillId: ref.id, versionId: ref.versionId ?? null })), + ctx, + ); } } -/** - * The stored refs passed the config schema check when they were written, so - * an array check is sufficient here. - */ -function isLegacySkillRefList( - value: unknown, -): value is AgentJsonSkillConfig[] & OpaqueStoredSkillRefs { - return Array.isArray(value); +function targetFor(agent: Pick, availableTo: AgentSkillAvailability) { + return { + projectId: availableTo === 'project' ? agent.projectId : null, + agentId: availableTo === 'agent' ? agent.id : null, + }; } -function readLegacySkillRefs(schema: StoredAgentConfig | null): AgentSkillRefs { +function readLegacyRefs(schema: StoredAgentConfig | null): AgentJsonSkillConfig[] { const value: unknown = schema?.skills; - return isLegacySkillRefList(value) ? value : undefined; + if (!Array.isArray(value)) return []; + return value.flatMap((ref: { id?: unknown; enabled?: unknown }) => + typeof ref?.id === 'string' && ref.enabled !== false + ? [{ type: 'skill' as const, id: ref.id }] + : [], + ); } -function withLegacySkillRefs(schema: StoredAgentConfig, refs: AgentSkillRefs): StoredAgentConfig { - const { skills: _previous, ...rest } = schema; - return isLegacySkillRefList(refs) ? { ...rest, skills: refs } : rest; +function pickBodies( + bodies: Record, + refs: AgentJsonSkillConfig[], +): Record { + return Object.fromEntries( + refs.flatMap((ref) => (Object.hasOwn(bodies, ref.id) ? [[ref.id, bodies[ref.id]]] : [])), + ); +} + +function toServiceRefs(refs: AgentJsonSkillConfig[]): SkillRef[] { + return refs.map(({ id, versionId }) => (versionId ? { id, versionId } : { id })); +} + +function toSkillRefs(refs: Array<{ id: string; versionId?: string }>): AgentJsonSkillConfig[] { + return refs.map(({ id, versionId }) => ({ + type: 'skill' as const, + id, + ...(versionId ? { versionId } : {}), + })); } diff --git a/packages/cli/src/modules/agents/agent-skills.service.ts b/packages/cli/src/modules/agents/agent-skills.service.ts index 23935e0a786..a8c43d341f3 100644 --- a/packages/cli/src/modules/agents/agent-skills.service.ts +++ b/packages/cli/src/modules/agents/agent-skills.service.ts @@ -1,39 +1,47 @@ import { agentSkillSchema, - type AgentJsonConfig, type AgentJsonSkillConfig, + type AgentSkillAvailability, type AgentSkill, type AgentSkillMutationResponse, } from '@n8n/api-types'; import { Logger } from '@n8n/backend-common'; -import { TransactionRunner } from '@n8n/db'; +import { TransactionRunner, type User } from '@n8n/db'; import { Service } from '@n8n/di'; import isEqual from 'lodash/isEqual'; import { UserError } from 'n8n-workflow'; -import { ConflictError, NotFoundError } from '@n8n/errors'; +import { ConflictError, ForbiddenError, NotFoundError } from '@n8n/errors'; +import { hasGlobalScope } from '@n8n/permissions'; +import { userHasScopes } from '@/permissions.ee/check-access'; import { type AgentMutationTelemetryContext, buildAgentMutationEvent, captureAgentMutation, - type AgentMutationSnapshot, } from './agent-modification-telemetry.service'; import { AgentSaveCompletionService } from './agent-save-completion.service'; import { AgentSkillRefsService } from './agent-skill-refs.service'; -import { markAgentDraftDirty, saveAgentDraftFenced } from './utils/agent-draft.utils'; -import { Agent } from './entities/agent.entity'; -import { AgentRepository } from './repositories/agent.repository'; -import { getAgentOrThrow } from './utils/get-agent-or-throw'; -import { getAgentConfigHash, getAgentSkillHash } from './utils/agent-config-hash'; +import type { Agent } from './entities/agent.entity'; import { composeJsonConfig } from './json-config/agent-config-composition'; import type { AgentSkillRefs } from './json-config/agent-document'; -import { generateAgentResourceId } from './utils/agent-resource-id'; +import { AgentRepository } from './repositories/agent.repository'; +import { findIntroducedNameClashes, findNameClashGroups } from './skills/skill-names'; +import { SkillService } from './skills/skill.service'; +import { getAgentConfigHash, getAgentSkillHash } from './utils/agent-config-hash'; +import { markAgentDraftDirty, saveAgentDraftFenced } from './utils/agent-draft.utils'; +import { getAgentOrThrow } from './utils/get-agent-or-throw'; import { applySkillInstructionEdits, type SkillInstructionEdit, } from './utils/skill-instruction-edits'; +/** + * Skill writes from one agent: the builder, the agent builder tools and MCP. + * The skills live in the skills hub. Create makes a hub skill in the agent's + * project and attaches it. Update saves the next version of the hub skill. + * Delete detaches the skill from the agent and keeps the hub skill. + */ @Service() export class AgentSkillsService { constructor( @@ -41,9 +49,11 @@ export class AgentSkillsService { private readonly agentRepository: AgentRepository, private readonly saveCompletion: AgentSaveCompletionService, private readonly agentSkillRefs: AgentSkillRefsService, + private readonly skillService: SkillService, private readonly transactionRunner: TransactionRunner, ) {} + /** The skills of the agent draft, keyed by skill id: the versions that the draft runs. */ async listSkills(agentId: string, projectId: string): Promise> { const entity = await getAgentOrThrow( this.agentRepository, @@ -51,33 +61,24 @@ export class AgentSkillsService { projectId, 'Agent not found', ); - - return entity.skills ?? {}; + // With the hub off, list every body on the agent row, as on master. + if (!this.agentSkillRefs.usesSkillsHub) return entity.skills ?? {}; + return (await this.agentSkillRefs.readDraft(entity, {})).skills; } async getSkill(agentId: string, projectId: string, skillId: string): Promise { const skills = await this.listSkills(agentId, projectId); - const skill = skills[skillId]; + const skill = Object.hasOwn(skills, skillId) ? skills[skillId] : undefined; if (!skill) throw new NotFoundError('Skill not found'); return skill; } - async createSkill( - agentId: string, - projectId: string, - skill: AgentSkill, - context: AgentMutationTelemetryContext, - ): Promise { - const { results } = await this.createSkillsBatch(agentId, projectId, [skill], false, context); - return results[0]; - } - /** - * Create multiple skill bodies and attach a config ref for each one, in one - * load/save/cache-clear. All-or-nothing: every skill is validated (including - * name uniqueness against existing skills and within the batch) before any - * mutation. + * Create skills in the skills hub and attach them to the agent, in one + * transaction. All-or-nothing: every skill is validated, and its name is + * checked against the agent's skills and the rest of the batch, before any + * write. */ async createAndAttachSkills( agentId: string, @@ -89,7 +90,6 @@ export class AgentSkillsService { agentId, projectId, skills, - true, context, ); return { @@ -103,22 +103,24 @@ export class AgentSkillsService { projectId: string, skill: AgentSkill, context: AgentMutationTelemetryContext, + availableTo: AgentSkillAvailability = 'project', ): Promise { - const { results } = await this.createSkillsBatch(agentId, projectId, [skill], true, context); + const { results } = await this.createSkillsBatch( + agentId, + projectId, + [skill], + context, + availableTo, + ); return results[0]; } - /** - * Shared implementation behind `createSkill`, `createAndAttachSkills`, and - * `createAndAttachSkill`. Rejects an empty batch before touching the - * repository. Saves once and clears the runtime cache once. - */ private async createSkillsBatch( agentId: string, projectId: string, skills: AgentSkill[], - attach: boolean, context: AgentMutationTelemetryContext, + availableTo: AgentSkillAvailability = 'project', ): Promise<{ results: AgentSkillMutationResponse[]; saved: Agent; skillRefs: AgentSkillRefs }> { if (skills.length === 0) { throw new UserError('At least one skill is required.'); @@ -130,48 +132,68 @@ export class AgentSkillsService { projectId, 'Agent not found', ); - if (attach && !entity.schema) throw new UserError('Agent has no JSON config yet.'); + if (!entity.schema) throw new UserError('Agent has no JSON config yet.'); - for (const skill of skills) { - this.validateSkill(skill); - } - this.assertBatchSkillNamesAreUnique(entity.skills ?? {}, skills); - - const previousSkillRefs = await this.agentSkillRefs.refsForDraft(entity, {}); - const previous = captureAgentMutation(entity, previousSkillRefs); - - const results = skills.map((skill) => ({ id: this.addSkill(entity, skill), skill })); - let skillRefs = previousSkillRefs; - if (attach) { - for (const { id } of results) skillRefs = this.attachSkillRef(skillRefs, id); + // With the hub off, skills keep `allowedTools` as on master. Hub skills ignore it. + const bodies = skills.map((skill) => { + const validated = this.validateSkill(skill); + return this.agentSkillRefs.usesSkillsHub ? toStoredSkill(validated) : validated; + }); + if (this.agentSkillRefs.usesSkillsHub) { + await this.assertCanCreateSkills(context.user, entity.projectId, availableTo); } - const saved = await this.saveSkillChanges( - entity, - projectId, - context, - previous, - previousSkillRefs, - attach ? { refs: skillRefs } : undefined, - ); + const previous = await this.agentSkillRefs.readDraft(entity, {}); + this.assertNoNameClashes(previous.skills, bodies); + const snapshot = captureAgentMutation(entity, previous.skillRefs); - this.logger.debug(attach ? 'Created and attached agent skill' : 'Created agent skills', { - agentId, - projectId, - skillIds: results.map((r) => r.id), + markAgentDraftDirty(entity); + const { ids, skillRefs } = await this.transactionRunner.run({}, async (ctx) => { + await saveAgentDraftFenced(this.agentRepository, entity, ctx); + const created = await this.agentSkillRefs.createSkills( + entity, + bodies, + context.user.id, + availableTo, + ctx, + ); + const nextRefs: AgentJsonSkillConfig[] = [ + ...(previous.skillRefs ?? []), + ...created.map((id) => ({ type: 'skill' as const, id })), + ]; + await this.agentSkillRefs.replaceDraftRefs(entity, nextRefs, ctx); + return { + ids: created, + skillRefs: await this.agentSkillRefs.refsForDraft(entity, ctx), + }; }); + await this.saveCompletion.bodySaved( + buildAgentMutationEvent(entity, skillRefs, projectId, context, snapshot, { skills: true }), + context.pushRef, + ); + + this.logger.debug('Created and attached agent skills', { agentId, projectId, skillIds: ids }); + return { - results: results.map((r) => ({ - ...r, - skillHash: getAgentSkillHash(r.skill), - versionId: saved.versionId, + results: ids.map((id, index) => ({ + id, + skill: bodies[index], + skillHash: getAgentSkillHash(bodies[index]), + versionId: entity.versionId, })), - saved, + saved: entity, skillRefs, }; } + /** + * Save the next version of a skill of this agent. The user needs the edit + * permission of the skill itself. Every agent that follows the skill runs + * the new version and shows unpublished changes. A ref of this agent that + * pins the latest version loses its pin, so this agent runs the new version + * too. A ref that pins an older version cannot be edited. + */ async updateSkill( agentId: string, projectId: string, @@ -180,6 +202,7 @@ export class AgentSkillsService { context: AgentMutationTelemetryContext, baseSkillHash?: string, instructionEdits?: SkillInstructionEdit[], + availableTo?: AgentSkillAvailability, ): Promise { const entity = await getAgentOrThrow( this.agentRepository, @@ -188,53 +211,126 @@ export class AgentSkillsService { 'Agent not found', ); - const existing = entity.skills?.[skillId]; + const skillRefs = (await this.agentSkillRefs.refsForDraft(entity, {})) ?? []; + const ref = skillRefs.find((candidate) => candidate.id === skillId); + const existing = !this.agentSkillRefs.usesSkillsHub + ? // With the hub off, any body on the agent row counts, with or without a ref, as on master. + legacyBody(entity, skillId) + : ref && (await this.agentSkillRefs.skillsForRefs(entity, [ref], {}))[skillId]; if (!existing) throw new NotFoundError('Skill not found'); if (baseSkillHash !== undefined && baseSkillHash !== getAgentSkillHash(existing)) { throw new ConflictError('Skill was changed elsewhere; reload to get the latest version'); } - const updated = { ...existing, ...updates }; + // With the hub off, an update still sets or clears `allowedTools`, as on master. + const { allowedTools, ...changes } = updates; + const updated: AgentSkill = { ...existing, ...changes }; + if (!this.agentSkillRefs.usesSkillsHub && 'allowedTools' in updates) { + if (allowedTools?.length) updated.allowedTools = allowedTools; + else delete updated.allowedTools; + } if (instructionEdits?.length) { if (updates.instructions !== undefined) { throw new UserError('Pass either instructions or instructionEdits, not both.'); } updated.instructions = applySkillInstructionEdits(existing.instructions, instructionEdits); } - if ('allowedTools' in updates && !updates.allowedTools?.length) delete updated.allowedTools; if ('references' in updates && !updates.references?.length) delete updated.references; this.validateSkill(updated); - this.assertSkillNameIsUnique(entity.skills ?? {}, updated.name, skillId); + + const nextAvailability = await this.availabilityChange(skillId, availableTo); + if (nextAvailability) { + await this.skillService.assertCanEdit(context.user, [skillId]); + await this.assertCanCreateSkills(context.user, entity.projectId, nextAvailability); + } if (isEqual(existing, updated)) { + if (nextAvailability) { + await this.agentSkillRefs.setAvailability(entity, skillId, nextAvailability, {}); + } return { id: skillId, - skill: updated, - skillHash: getAgentSkillHash(updated), + skill: existing, + skillHash: getAgentSkillHash(existing), versionId: entity.versionId, }; } - const skillRefs = await this.agentSkillRefs.refsForDraft(entity, {}); - const previous = captureAgentMutation(entity, skillRefs); + if (!this.agentSkillRefs.usesSkillsHub) { + return await this.updateLegacySkill(entity, skillRefs, skillId, updated, projectId, context); + } - entity.skills = { - ...(entity.skills ?? {}), - [skillId]: updated, - }; + const pinned = ref?.versionId !== undefined; + if (pinned) { + const latest = ( + await this.agentSkillRefs.skillsForRefs(entity, [{ type: 'skill', id: skillId }], {}) + )[skillId]; + if (!latest || getAgentSkillHash(latest) !== getAgentSkillHash(existing)) { + throw new UserError( + 'This agent uses an older version of this skill. Use the latest version first, then edit the skill. To use the latest version, remove versionId from the skill ref in the agent config.', + ); + } + } + await this.skillService.assertCanEdit(context.user, [skillId]); + const snapshot = captureAgentMutation(entity, skillRefs); - const saved = await this.saveSkillChanges(entity, projectId, context, previous, skillRefs); + if (pinned) markAgentDraftDirty(entity); + const saved = await this.transactionRunner.run({}, async (ctx) => { + if (nextAvailability) { + await this.agentSkillRefs.setAvailability(entity, skillId, nextAvailability, ctx); + } + if (pinned) { + await saveAgentDraftFenced(this.agentRepository, entity, ctx); + await this.agentSkillRefs.unpinDraftRef(entity, skillId, ctx); + } + return await this.skillService.save( + skillId, + { + name: updated.name, + description: updated.description, + instructions: updated.instructions, + references: updated.references ?? [], + baseSkillHash: getAgentSkillHash(existing), + }, + context.user.id, + ctx, + ); + }); - this.logger.debug('Updated agent skill', { agentId, projectId, skillId }); + await this.skillService.refreshFollowingAgents( + saved.followingAgentIds.filter((id) => id !== entity.id), + context.pushRef, + ); + const fresh = (await this.agentRepository.findByIdAndProjectId(entity.id, projectId)) ?? entity; + await this.saveCompletion.bodySaved( + buildAgentMutationEvent( + fresh, + await this.agentSkillRefs.refsForDraft(fresh, {}), + projectId, + context, + snapshot, + { skills: true }, + ), + context.pushRef, + ); + + this.logger.debug('Updated agent skill', { + agentId, + projectId, + skillId, + version: saved.version, + created: saved.created, + }); return { id: skillId, - skill: updated, - skillHash: getAgentSkillHash(updated), - versionId: saved.versionId, + skill: saved.skill, + skillHash: getAgentSkillHash(saved.skill), + versionId: fresh.versionId, }; } + /** Detach a skill from the agent. The skill stays in the skills hub. */ async deleteSkill( agentId: string, projectId: string, @@ -248,132 +344,126 @@ export class AgentSkillsService { 'Agent not found', ); - const skills = { ...(entity.skills ?? {}) }; - if (!skills[skillId]) throw new NotFoundError('Skill not found'); - const previousSkillRefs = await this.agentSkillRefs.refsForDraft(entity, {}); - const previous = captureAgentMutation(entity, previousSkillRefs); - - delete skills[skillId]; - entity.skills = skills; - - // A config without a skill list keeps no skill list after a delete. - await this.saveSkillChanges( - entity, - projectId, - context, - previous, - previousSkillRefs, - previousSkillRefs - ? { refs: previousSkillRefs.filter((ref) => ref.id !== skillId) } - : undefined, - ); - - this.logger.debug('Deleted agent skill', { agentId, projectId, skillId }); - } - - removeUnreferencedSkills(entity: Agent, config: AgentJsonConfig): void { - const referencedSkillIds = new Set((config.skills ?? []).map((t) => t.id)); - const orphanSkillIds = Object.keys(entity.skills ?? {}).filter( - (id) => !referencedSkillIds.has(id), - ); - if (orphanSkillIds.length === 0) return; - - const skills = { ...(entity.skills ?? {}) }; - for (const id of orphanSkillIds) { - delete skills[id]; + if (!previousSkillRefs?.some((ref) => ref.id === skillId)) { + throw new NotFoundError('Skill not found'); } - entity.skills = skills; + const snapshot = captureAgentMutation(entity, previousSkillRefs); + + markAgentDraftDirty(entity); + const skillRefs = await this.transactionRunner.run({}, async (ctx) => { + await saveAgentDraftFenced(this.agentRepository, entity, ctx); + await this.agentSkillRefs.replaceDraftRefs( + entity, + previousSkillRefs.filter((ref) => ref.id !== skillId), + ctx, + ); + return await this.agentSkillRefs.refsForDraft(entity, ctx); + }); + await this.saveCompletion.bodySaved( + buildAgentMutationEvent(entity, skillRefs, projectId, context, snapshot, { skills: true }), + context.pushRef, + ); + + this.logger.debug('Detached agent skill', { agentId, projectId, skillId }); } - private validateSkill(skill: AgentSkill): void { + private async availabilityChange( + skillId: string, + availableTo: AgentSkillAvailability | undefined, + ): Promise { + if (availableTo === undefined || !this.agentSkillRefs.usesSkillsHub) return undefined; + const current = await this.agentSkillRefs.availabilityOf(skillId, {}); + return current === availableTo ? undefined : availableTo; + } + + private async updateLegacySkill( + entity: Agent, + skillRefs: AgentJsonSkillConfig[], + skillId: string, + updated: AgentSkill, + projectId: string, + context: AgentMutationTelemetryContext, + ): Promise { + // Every body on the agent row counts, with or without a ref, as on master. + const { [skillId]: _self, ...others } = entity.skills ?? {}; + this.assertNoNameClashes(others, [updated]); + const snapshot = captureAgentMutation(entity, skillRefs); + entity.skills = { ...entity.skills, [skillId]: updated }; + markAgentDraftDirty(entity); + await this.transactionRunner.run({}, async (ctx) => { + await saveAgentDraftFenced(this.agentRepository, entity, ctx); + }); + await this.saveCompletion.bodySaved( + buildAgentMutationEvent(entity, skillRefs, projectId, context, snapshot, { skills: true }), + context.pushRef, + ); + this.logger.debug('Updated agent skill', { agentId: entity.id, projectId, skillId }); + return { + id: skillId, + skill: updated, + skillHash: getAgentSkillHash(updated), + versionId: entity.versionId, + }; + } + + private validateSkill(skill: AgentSkill): AgentSkill { const result = agentSkillSchema.safeParse(skill); if (!result.success) { throw new UserError( `Invalid agent skill: ${result.error.issues[0]?.message ?? 'Invalid skill'}`, ); } + return result.data; } - private addSkill(entity: Agent, skill: AgentSkill): string { - const skillId = generateAgentResourceId('skill', Object.keys(entity.skills ?? {})); - - entity.skills = { - ...(entity.skills ?? {}), - [skillId]: skill, - }; - - return skillId; - } - - private assertSkillNameIsUnique( - existing: Record, - name: string, - currentSkillId?: string, - ): void { - const normalizedName = this.normalizeSkillName(name); - const duplicate = Object.entries(existing ?? {}).find( - ([id, skill]) => - id !== currentSkillId && this.normalizeSkillName(skill.name) === normalizedName, - ); - if (duplicate) { - throw new UserError(`Agent already has a skill named "${name.trim()}".`); - } - } - - private normalizeSkillName(name: string): string { - return name.trim().toLowerCase(); - } - - private assertBatchSkillNamesAreUnique( - existing: Record, - skills: AgentSkill[], - ): void { - const seenNames = new Set(); - for (const skill of skills) { - this.assertSkillNameIsUnique(existing, skill.name); - const normalizedName = this.normalizeSkillName(skill.name); - if (seenNames.has(normalizedName)) { - throw new UserError(`Duplicate skill name in batch: "${skill.name.trim()}".`); - } - seenNames.add(normalizedName); - } - } - - private attachSkillRef(skillRefs: AgentSkillRefs, skillId: string): AgentJsonSkillConfig[] { - return [ - ...(skillRefs ?? []).filter((ref) => ref.id !== skillId), - { type: 'skill', id: skillId }, - ]; - } - - /** - * Write the skill refs only when the caller gives `nextSkillRefs`. - * Without `nextSkillRefs`, the refs stay as `currentSkillRefs`. - */ - private async saveSkillChanges( - entity: Agent, + private async assertCanCreateSkills( + user: User, projectId: string, - context: AgentMutationTelemetryContext, - previous: AgentMutationSnapshot, - currentSkillRefs: AgentSkillRefs, - nextSkillRefs?: { refs: AgentSkillRefs }, - ): Promise { - markAgentDraftDirty(entity); - const saved = await this.transactionRunner.run({}, async (ctx) => { - await saveAgentDraftFenced(this.agentRepository, entity, ctx); - if (nextSkillRefs) { - await this.agentSkillRefs.replaceDraftRefs(entity, nextSkillRefs.refs, ctx); + availableTo: AgentSkillAvailability, + ): Promise { + // A skill of one agent is part of that agent: the agent permission is enough. + if (availableTo === 'agent') return; + if (availableTo === 'instance') { + if (!hasGlobalScope(user, 'skill:create')) { + throw new ForbiddenError('You are not allowed to create skills for the whole instance.'); } - return entity; - }); - const savedSkillRefs = nextSkillRefs ? nextSkillRefs.refs : currentSkillRefs; - await this.saveCompletion.bodySaved( - buildAgentMutationEvent(saved, savedSkillRefs, projectId, context, previous, { - skills: true, - }), - context.pushRef, - ); - return saved; + return; + } + if (!(await userHasScopes(user, ['projectSkill:create'], false, { projectId }))) { + throw new ForbiddenError('You are not allowed to create skills for this project.'); + } + } + + /** New names must be easy to tell apart from the agent's skills and from each other. */ + private assertNoNameClashes(existing: Record, added: AgentSkill[]): void { + const quote = (names: string[]) => names.map((name) => name.trim()).join('", "'); + const existingNames = Object.values(existing).map((skill) => skill.name); + const clashes = added + .map((skill) => skill.name) + .filter((name) => findIntroducedNameClashes(existingNames, [name]).length > 0); + if (clashes.length > 0) { + throw new UserError(`Agent already has a skill with a name like "${quote(clashes)}".`); + } + // Two new skills of one batch can also clash with each other. + const inBatch = findNameClashGroups(added.map((skill) => skill.name)); + if (inBatch.length > 0) { + throw new UserError(`The new skills "${quote(inBatch[0])}" are hard to tell apart.`); + } } } + +function legacyBody(agent: Pick, skillId: string): AgentSkill | undefined { + const skills = agent.skills ?? {}; + return Object.hasOwn(skills, skillId) ? skills[skillId] : undefined; +} + +/** The fields a skill version stores. Skills ignore `allowedTools`. */ +function toStoredSkill(skill: AgentSkill): AgentSkill { + return { + name: skill.name, + description: skill.description, + instructions: skill.instructions, + ...(skill.references?.length ? { references: skill.references } : {}), + }; +} diff --git a/packages/cli/src/modules/agents/agent-teams-integrations.controller.ts b/packages/cli/src/modules/agents/agent-teams-integrations.controller.ts index 8203a6ee740..5bf2c5a7d73 100644 --- a/packages/cli/src/modules/agents/agent-teams-integrations.controller.ts +++ b/packages/cli/src/modules/agents/agent-teams-integrations.controller.ts @@ -1,12 +1,34 @@ -import { AgentTeamsPackageDto } from '@n8n/api-types'; -import type { TeamsAgentSetupState, TeamsCredentialCheck } from '@n8n/api-types'; +import { + AgentTeamsPackageDto, + AgentTeamsProvisionAppDto, + AgentTeamsProvisionBotDto, + AgentTeamsPublishDto, +} from '@n8n/api-types'; +import type { + CreateTeamsManagerCredentialResponse, + TeamsAgentSetupState, + TeamsCredentialCheck, + TeamsFileAccessCheck, + TeamsManagedSetupState, + TeamsAzureSubscription, + TeamsCatalogState, + TeamsProvisionedAppSummary, + TeamsProvisionedBotSummary, +} from '@n8n/api-types'; import { Time } from '@n8n/constants'; import type { AuthenticatedRequest } from '@n8n/db'; import type { CorsOptions } from '@n8n/decorators'; import { Body, Get, Options, Param, Post, ProjectScope, RestController } from '@n8n/decorators'; +import { BadRequestError } from '@n8n/errors'; import type { Request, Response } from 'express'; import { TeamsCredentialCheckService } from './integrations/platforms/teams/teams-credential-check.service'; +import { TeamsBotProvisioningService } from './integrations/platforms/teams/teams-bot-provisioning.service'; +import { TeamsCatalogService } from './integrations/platforms/teams/teams-catalog.service'; +import { TeamsCredentialNotesService } from './integrations/platforms/teams/teams-credential-notes.service'; +import { TeamsEntraProvisioningService } from './integrations/platforms/teams/teams-entra-provisioning.service'; +import { TeamsSetupTelemetryService } from './integrations/platforms/teams/teams-setup-telemetry.service'; +import { TeamsManagedSetupService } from './integrations/platforms/teams/teams-managed-setup.service'; import { TeamsSetupService } from './integrations/platforms/teams/teams-setup.service'; /** @@ -26,8 +48,242 @@ export class AgentTeamsIntegrationsController { constructor( private readonly setupService: TeamsSetupService, private readonly credentialCheckService: TeamsCredentialCheckService, + private readonly managedSetupService: TeamsManagedSetupService, + private readonly entraProvisioningService: TeamsEntraProvisioningService, + private readonly botProvisioningService: TeamsBotProvisioningService, + private readonly catalogService: TeamsCatalogService, + private readonly setupTelemetry: TeamsSetupTelemetryService, + private readonly credentialNotes: TeamsCredentialNotesService, ) {} + /** + * Publishes the app to the organisation, or submits it for review when the + * account may not publish directly. Which of the two happened is in the + * state this returns. + */ + @Post('/:agentId/integrations/teams/publish') + @ProjectScope('agent:update') + async publishApp( + req: AuthenticatedRequest<{ projectId: string }>, + _res: Response, + @Param('agentId') agentId: string, + @Body payload: AgentTeamsPublishDto, + ): Promise { + const report = { + agentId, + projectId: req.params.projectId, + userId: req.user.id, + step: 'install' as const, + }; + try { + const state = await this.catalogService.publish({ + user: req.user, + projectId: req.params.projectId, + agentId, + managerCredentialId: payload.managerCredentialId, + credentialId: payload.credentialId, + settings: payload.settings, + }); + // Which route the account actually got is the answer the publish call + // gives back. Only two of its four answers are routes, though: an app + // Microsoft has not listed yet, or has rejected, took neither. + this.setupTelemetry.succeeded({ + ...report, + ...(state.status === 'published' || state.status === 'submitted' + ? { installRoute: state.status } + : {}), + }); + return state; + } catch (error) { + this.setupTelemetry.failed(report, error); + throw error; + } + } + + @Get('/:agentId/integrations/teams/catalog') + @ProjectScope('agent:update') + async getCatalogState( + req: AuthenticatedRequest< + { projectId: string }, + {}, + {}, + { managerCredentialId?: string; credentialId?: string } + >, + _res: Response, + @Param('agentId') agentId: string, + ): Promise { + const managerCredentialId = req.query.managerCredentialId; + if (typeof managerCredentialId !== 'string' || managerCredentialId.length === 0) { + return { status: 'unknown', teamsAppId: null }; + } + const credentialId = req.query.credentialId; + return await this.catalogService.getState({ + user: req.user, + projectId: req.params.projectId, + agentId, + managerCredentialId, + ...(typeof credentialId === 'string' && credentialId.length > 0 ? { credentialId } : {}), + }); + } + + /** + * An empty list is the ordinary answer for a Microsoft 365 tenant, which + * comes with no Azure subscription. The setup then offers the next option + * rather than treating it as a failure. + */ + @Get('/:agentId/integrations/teams/azure-subscriptions') + @ProjectScope('agent:update') + async listAzureSubscriptions( + req: AuthenticatedRequest<{ projectId: string }, {}, {}, { managerCredentialId?: string }>, + _res: Response, + @Param('agentId') _agentId: string, + ): Promise { + const managerCredentialId = req.query.managerCredentialId; + // An empty answer here means "no Azure subscription", which sends the user + // down the manual ladder. A missing credential is a caller bug, not that. + if (typeof managerCredentialId !== 'string' || managerCredentialId.length === 0) { + throw new BadRequestError('Sign in with Microsoft before looking for a subscription.'); + } + return await this.botProvisioningService.listSubscriptions({ + user: req.user, + managerCredentialId, + }); + } + + /** + * The rung the whole ladder exists to measure, reported where the user takes + * it. The lookup above cannot report it: it answers again on every remount + * and every change of sign-in, and a tenant with no Azure subscription is the + * ordinary case, so it would count the dialog being opened. Leaving the + * recommended flow is an act, and it happens once. + */ + @Post('/:agentId/integrations/teams/manual-bot-route') + @ProjectScope('agent:update') + reportManualBotRoute( + req: AuthenticatedRequest<{ projectId: string }>, + _res: Response, + @Param('agentId') agentId: string, + ): void { + this.setupTelemetry.succeeded({ + agentId, + projectId: req.params.projectId, + userId: req.user.id, + step: 'create_bot', + botRoute: 'manual', + }); + } + + @Post('/:agentId/integrations/teams/provision-bot') + @ProjectScope('agent:update') + async provisionBot( + req: AuthenticatedRequest<{ projectId: string }>, + _res: Response, + @Param('agentId') agentId: string, + @Body payload: AgentTeamsProvisionBotDto, + ): Promise { + const projectId = req.params.projectId; + const report = { + agentId, + projectId, + userId: req.user.id, + step: 'create_bot' as const, + botRoute: 'provisioned' as const, + }; + try { + // Inside the try: a credential that has gone is a way this step fails, + // and reading it outside would leave that failure unrecorded. + const identity = await this.setupService.botIdentityFor( + req.user, + { projectId, agentId }, + payload.credentialId, + ); + const summary = await this.botProvisioningService.provisionBot({ + user: req.user, + projectId, + agentId, + agentName: identity.agentName, + credentialId: payload.credentialId, + managerCredentialId: payload.managerCredentialId, + subscriptionId: payload.subscriptionId, + msaAppId: identity.clientId, + msaAppTenantId: identity.tenantId, + messagingEndpoint: identity.messagingEndpoint, + }); + this.setupTelemetry.succeeded(report); + return summary; + } catch (error) { + this.setupTelemetry.failed(report, error); + throw error; + } + } + + /** + * Registers the customer's Entra app and writes the channel credential from + * it, so the user never sees a client secret. + */ + @Post('/:agentId/integrations/teams/provision-app') + @ProjectScope('agent:update') + async provisionApp( + req: AuthenticatedRequest<{ projectId: string }>, + _res: Response, + @Param('agentId') agentId: string, + @Body payload: AgentTeamsProvisionAppDto, + ): Promise { + const report = { + agentId, + projectId: req.params.projectId, + userId: req.user.id, + step: 'create_app' as const, + }; + try { + const summary = await this.entraProvisioningService.provision({ + user: req.user, + projectId: req.params.projectId, + agentId, + agentName: await this.setupService.agentNameFor(req.params.projectId, agentId), + managerCredentialId: payload.managerCredentialId, + }); + this.setupTelemetry.succeeded(report); + return summary; + } catch (error) { + this.setupTelemetry.failed(report, error); + throw error; + } + } + + /** + * Whether the recommended setup can run here, and which Microsoft sign-ins + * the project already has. Returns `managedSetupAvailable: false` rather + * than failing, so the frontend can simply not offer the mode. + */ + @Get('/:agentId/integrations/teams/managed-setup') + @ProjectScope('agent:update') + async getManagedSetupState( + req: AuthenticatedRequest<{ projectId: string }>, + _res: Response, + @Param('agentId') agentId: string, + ): Promise { + return await this.managedSetupService.getSetupState({ + projectId: req.params.projectId, + agentId, + user: req.user, + }); + } + + @Post('/:agentId/integrations/teams/manager-credential') + @ProjectScope('agent:update') + async createManagerCredential( + req: AuthenticatedRequest<{ projectId: string }>, + _res: Response, + @Param('agentId') agentId: string, + ): Promise { + return await this.managedSetupService.createManagerCredential({ + projectId: req.params.projectId, + agentId, + user: req.user, + }); + } + /** * Proves the credential can reach Microsoft before the channel is connected. * Connecting a credential that cannot mint a token leaves a channel that @@ -43,6 +299,20 @@ export class AgentTeamsIntegrationsController { return await this.credentialCheckService.check(req.user, req.params.projectId, credentialId); } + @Get('/:agentId/integrations/teams/file-access/:credentialId') + @ProjectScope('agent:update') + async checkFileAccess( + req: AuthenticatedRequest<{ projectId: string }>, + _res: Response, + @Param('credentialId') credentialId: string, + ): Promise { + return await this.credentialCheckService.checkFileAccess( + req.user, + req.params.projectId, + credentialId, + ); + } + @Get('/:agentId/integrations/teams/setup') @ProjectScope('agent:update') async getSetupState( @@ -70,12 +340,14 @@ export class AgentTeamsIntegrationsController { @Param('agentId') agentId: string, @Body payload: AgentTeamsPackageDto, ): Promise { - const archive = await this.setupService.buildPackage( + const { archive, fingerprint, credentialId } = await this.setupService.buildPackage( req.user, { projectId: req.params.projectId, agentId }, payload.credentialId, payload.settings, ); + // The settings compare against this to say Teams holds an older version. + await this.credentialNotes.write(req.user, credentialId, { teamsAppFingerprint: fingerprint }); res.setHeader('Content-Type', 'application/zip'); res.setHeader('Content-Disposition', 'attachment; filename="n8n-agent-teams-app.zip"'); diff --git a/packages/cli/src/modules/agents/agent-validation.service.ts b/packages/cli/src/modules/agents/agent-validation.service.ts index 5134d2c087d..3d56ef80715 100644 --- a/packages/cli/src/modules/agents/agent-validation.service.ts +++ b/packages/cli/src/modules/agents/agent-validation.service.ts @@ -13,6 +13,7 @@ import { type AgentConfigValidationIssue, type AgentConfigValidationIssueCode, type AgentConfigValidationResponse, + type AgentConfigValidationWarning, type AgentIntegrationConfig, type AgentTaskConfig, type AgentJsonConfig, @@ -50,6 +51,7 @@ import { AgentRepository } from './repositories/agent.repository'; import { findWorkflowToolWorkflows } from './tools/workflow-tool-workflow-resolver'; import { extractAgentWorkflowRefs } from './utils/extract-agent-workflow-refs'; import { findHttpRequestToolUrlFromAiViolations } from './utils/node-tool-validation'; +import { findNameClashGroups } from './skills/skill-names'; type AgentValidationScope = 'runtime' | 'publish'; @@ -206,10 +208,11 @@ export class AgentValidationService { credentialProvider: CredentialProvider, scope: AgentValidationScope = 'publish', ): Promise { + const skills = await this.agentSkillRefs.skillsForRefs(agent, skillRefs, {}); return await this.validateDefinition( agent.id, projectId, - { ...getAgentDefinitionContent(agent, skillRefs), tasks }, + { ...getAgentDefinitionContent(agent, skillRefs, skills), tasks }, agent.integrations ?? [], credentialProvider, scope, @@ -272,7 +275,27 @@ export class AgentValidationService { } const issues = await this.collectIssues({ ...ctx, config: ctx.config }, scope); - return { status: issues.length === 0 ? 'valid' : 'invalid', issues }; + const warnings = this.collectSkillNameWarnings(ctx.config, ctx.skills); + return { + status: issues.length === 0 ? 'valid' : 'invalid', + issues, + ...(warnings.length > 0 ? { warnings } : {}), + }; + } + + /** Skill names that are hard to tell apart confuse the model, but do not block a run. */ + private collectSkillNameWarnings( + config: AgentJsonConfig, + skills: Record, + ): AgentConfigValidationWarning[] { + const names = (config.skills ?? []).flatMap((ref) => + Object.hasOwn(skills, ref.id) ? [skills[ref.id].name] : [], + ); + return findNameClashGroups(names).map((group) => ({ + code: 'similar_skill_names', + capability: { kind: 'skill' }, + names: group, + })); } private missingConfigIssues(): AgentConfigValidationIssue[] { diff --git a/packages/cli/src/modules/agents/agent-whatsapp-integrations.controller.ts b/packages/cli/src/modules/agents/agent-whatsapp-integrations.controller.ts new file mode 100644 index 00000000000..23f7a46c299 --- /dev/null +++ b/packages/cli/src/modules/agents/agent-whatsapp-integrations.controller.ts @@ -0,0 +1,67 @@ +import type { WhatsAppCredentialCheck, WhatsAppWebhookStatus } from '@n8n/api-types'; +import type { AuthenticatedRequest } from '@n8n/db'; +import { Delete, Get, Param, Post, ProjectScope, RestController } from '@n8n/decorators'; +import { NotFoundError } from '@n8n/errors'; +import type { Response } from 'express'; + +import { WhatsAppCredentialCheckService } from './integrations/platforms/whatsapp/whatsapp-credential-check.service'; +import { WhatsAppWebhookVerificationStore } from './integrations/platforms/whatsapp/whatsapp-webhook-verification.store'; +import { AgentRepository } from './repositories/agent.repository'; + +@RestController('/projects/:projectId/agents/v2') +export class AgentWhatsAppIntegrationsController { + constructor( + private readonly credentialCheckService: WhatsAppCredentialCheckService, + private readonly webhookVerification: WhatsAppWebhookVerificationStore, + private readonly agentRepository: AgentRepository, + ) {} + + /** + * Proves the credential works with Meta before the channel is connected, and + * returns the business profile that customers see. + */ + @Post('/:agentId/integrations/whatsapp/check/:credentialId') + @ProjectScope('agent:update') + async checkCredential( + req: AuthenticatedRequest<{ projectId: string }>, + _res: Response, + @Param('credentialId') credentialId: string, + ): Promise { + return await this.credentialCheckService.check(req.user, req.params.projectId, credentialId); + } + + /** Polled by the setup until Meta completes the webhook handshake. */ + @Get('/:agentId/integrations/whatsapp/webhook-status') + @ProjectScope('agent:read') + async webhookStatus( + req: AuthenticatedRequest<{ projectId: string }>, + _res: Response, + @Param('agentId') agentId: string, + ): Promise { + await this.assertAgentExists(req.params.projectId, agentId); + return { verified: await this.webhookVerification.isVerified(agentId) }; + } + + /** + * Forgets an earlier handshake before the setup asks for a new one. The + * handshake does not say which Meta app sent it, so without this a record + * from a replaced credential's app would confirm the step. + */ + @Delete('/:agentId/integrations/whatsapp/webhook-status') + @ProjectScope('agent:update') + async resetWebhookStatus( + req: AuthenticatedRequest<{ projectId: string }>, + _res: Response, + @Param('agentId') agentId: string, + ): Promise { + await this.assertAgentExists(req.params.projectId, agentId); + await this.webhookVerification.reset(agentId); + return { verified: false }; + } + + /** Checks the agent exists without loading its config, because the status is polled. */ + private async assertAgentExists(projectId: string, agentId: string): Promise { + const exists = await this.agentRepository.existsBy({ id: agentId, projectId }); + if (!exists) throw new NotFoundError(`Agent "${agentId}" not found`); + } +} diff --git a/packages/cli/src/modules/agents/agent-workflow-execution.service.ts b/packages/cli/src/modules/agents/agent-workflow-execution.service.ts index 396ee8ad52b..d85a3018808 100644 --- a/packages/cli/src/modules/agents/agent-workflow-execution.service.ts +++ b/packages/cli/src/modules/agents/agent-workflow-execution.service.ts @@ -777,7 +777,7 @@ export class AgentWorkflowExecutionService { const prepared = fromAgentDocument(config); agent.schema = prepared.config; agent.integrations = []; - return { runSource: { agent, skillRefs: prepared.skillRefs }, instrumentation }; + return { runSource: { ...runSource, agent, skillRefs: prepared.skillRefs }, instrumentation }; } private async streamCompiledWorkflowAgent( diff --git a/packages/cli/src/modules/agents/agents-list.controller.ts b/packages/cli/src/modules/agents/agents-list.controller.ts index 5c1f7e712de..42615872d5a 100644 --- a/packages/cli/src/modules/agents/agents-list.controller.ts +++ b/packages/cli/src/modules/agents/agents-list.controller.ts @@ -11,8 +11,8 @@ import { parseThreadListLimit } from './utils/parse-thread-list-limit'; * Global (cross-project) agents list endpoint. * * It serves two audiences, and `availableInChat` picks between them: - * - the overview page, which wants every agent in the user's projects and the - * full entity to render its cards; + * - the overview page, which wants every agent in the projects where the user + * holds `agent:list` and the full entity to render its cards; * - the n8n chat page, which wants the agents whose published config carries * the n8n Chat channel, scoped to `agent:execute` and answered with the * narrow `AgentChatListItem` so a chat-only member gets no config. @@ -30,7 +30,7 @@ export class AgentsListController { async list(req: AuthenticatedRequest, res: Response, @Query query: ListAgentsQueryDto) { res.json( query.filter?.availableInChat === undefined - ? await this.agentsService.findByUserMembershipPaginated(req.user, query) + ? await this.agentsService.findListableByUserPaginated(req.user, query) : await this.agentsService.findChatReachableByUserPaginated(req.user, query), ); } diff --git a/packages/cli/src/modules/agents/agents-skills.controller.ts b/packages/cli/src/modules/agents/agents-skills.controller.ts index 708805f7f67..0f257dcc80a 100644 --- a/packages/cli/src/modules/agents/agents-skills.controller.ts +++ b/packages/cli/src/modules/agents/agents-skills.controller.ts @@ -1,4 +1,4 @@ -import { CreateAgentSkillDto, UpdateAgentSkillDto } from '@n8n/api-types'; +import { CreateAgentSkillDto, UpdateAttachedAgentSkillDto } from '@n8n/api-types'; import type { AuthenticatedRequest } from '@n8n/db'; import { Body, @@ -58,11 +58,18 @@ export class AgentsSkillsController { agentId, 'create skill for', ); - return await this.agentSkillsService.createAndAttachSkill(agentId, projectId, payload, { - user: req.user, - modifiedBy: 'user', - pushRef: req.headers?.['push-ref'], - }); + const { availableTo, ...skill } = payload; + return await this.agentSkillsService.createAndAttachSkill( + agentId, + projectId, + skill, + { + user: req.user, + modifiedBy: 'user', + pushRef: req.headers?.['push-ref'], + }, + availableTo, + ); } @Patch('/:agentId/skills/:skillId') @@ -72,10 +79,10 @@ export class AgentsSkillsController { _res: Response, @Param('agentId') agentId: string, @Param('skillId') skillId: string, - @Body payload: UpdateAgentSkillDto, + @Body payload: UpdateAttachedAgentSkillDto, ) { const { projectId } = req.params; - const { baseSkillHash, ...updates } = payload; + const { baseSkillHash, availableTo, ...updates } = payload; const clientId = req.headers?.['push-ref']; await this.collaborationService.validateAgentWriteLock( req.user.id, @@ -95,6 +102,8 @@ export class AgentsSkillsController { pushRef: req.headers?.['push-ref'], }, baseSkillHash, + undefined, + availableTo, ); } diff --git a/packages/cli/src/modules/agents/agents.module.ts b/packages/cli/src/modules/agents/agents.module.ts index a0631c17c91..6f40e7ad225 100644 --- a/packages/cli/src/modules/agents/agents.module.ts +++ b/packages/cli/src/modules/agents/agents.module.ts @@ -11,6 +11,13 @@ export class AgentsModule implements ModuleInterface { const { SandboxSettingsService } = await import('@/services/sandbox-settings.service.js'); Container.get(SandboxSettingsService).registerCredentialUses(); + // Read the skills hub flag once, before anything reads or writes agent skills. With + // the flag on, each main copies inline agent skills into the hub before agents run. + const { SkillsHubRollout } = await import('./skills/skills-hub-rollout.js'); + await Container.get(SkillsHubRollout).init(); + const { SkillsHubStartupCopy } = await import('./skills/skills-hub-startup-copy.js'); + await Container.get(SkillsHubStartupCopy).runOnStartup(); + // Imported for its `@OnLifecycleEvent` registration, which happens at // class-decoration time — nothing else references this service. await import('./agent-workflow-tool-resume.service.js'); @@ -21,12 +28,14 @@ export class AgentsModule implements ModuleInterface { await import('./agents-settings.controller.js'); await import('./agents-config.controller.js'); await import('./agents-skills.controller.js'); + await import('./skills.controller.js'); await import('./agent-knowledge.controller.js'); await import('./agent-publish.controller.js'); await import('./agent-chat.controller.js'); await import('./agent-integrations.controller.js'); await import('./agent-slack-integrations.controller.js'); await import('./agent-teams-integrations.controller.js'); + await import('./agent-whatsapp-integrations.controller.js'); await import('./agent-vector-stores.controller.js'); await import('./agent-tasks.controller.js'); await import('./agent-sandbox.controller.js'); @@ -93,7 +102,7 @@ export class AgentsModule implements ModuleInterface { const { LinearIntegration } = await import('./integrations/platforms/linear-integration.js'); const { DiscordIntegration } = await import('./integrations/platforms/discord-integration.js'); const { WhatsAppIntegration } = await import( - './integrations/platforms/whatsapp-integration.js' + './integrations/platforms/whatsapp/whatsapp-integration.js' ); const { TeamsIntegration } = await import( './integrations/platforms/teams/teams-integration.js' @@ -205,7 +214,14 @@ export class AgentsModule implements ModuleInterface { const { AgentInterruptedExecutionSweepTask } = await import( './agent-interrupted-execution-sweep.task.js' ); - return [AgentCheckpointPruningTask, AgentInterruptedExecutionSweepTask]; + const { AgentChannelMediaRetentionTask } = await import( + './agent-channel-media-retention.task.js' + ); + return [ + AgentCheckpointPruningTask, + AgentInterruptedExecutionSweepTask, + AgentChannelMediaRetentionTask, + ]; } async settings() { @@ -213,6 +229,7 @@ export class AgentsModule implements ModuleInterface { const { AgentsSettingsService } = await import('./agents-settings.service.js'); const { AiService } = await import('@/services/ai.service.js'); const { SandboxSettingsService } = await import('@/services/sandbox-settings.service.js'); + const { SkillsHubRollout } = await import('./skills/skills-hub-rollout.js'); const aiService = Container.get(AiService); const proxyEnabled = aiService.isProxyEnabled(); return { @@ -220,6 +237,7 @@ export class AgentsModule implements ModuleInterface { modules: [...config.modules], knowledgeBaseEnabled: Container.get(SandboxSettingsService).isAgentSandboxEnabled(), proxyEnabled, + skillsHubEnabled: Container.get(SkillsHubRollout).isEnabled, }; } @@ -274,6 +292,13 @@ export class AgentsModule implements ModuleInterface { const { AgentMemoryEntrySourceEntity } = await import( './entities/agent-memory-entry-source.entity.js' ); + const { Skill } = await import('./entities/skill.entity.js'); + const { SkillVersion } = await import('./entities/skill-version.entity.js'); + const { SkillFile } = await import('./entities/skill-file.entity.js'); + const { AgentSkillDependency } = await import('./entities/agent-skill-dependency.entity.js'); + const { AgentVersionSkillDependency } = await import( + './entities/agent-version-skill-dependency.entity.js' + ); return [ Agent, @@ -308,6 +333,11 @@ export class AgentsModule implements ModuleInterface { AgentMemoryEntryCandidateEntity, AgentMemoryEntryLockEntity, AgentMemoryEntrySourceEntity, + Skill, + SkillVersion, + SkillFile, + AgentSkillDependency, + AgentVersionSkillDependency, ]; } diff --git a/packages/cli/src/modules/agents/agents.service.ts b/packages/cli/src/modules/agents/agents.service.ts index 2ac96c69da0..83291e5b795 100644 --- a/packages/cli/src/modules/agents/agents.service.ts +++ b/packages/cli/src/modules/agents/agents.service.ts @@ -73,7 +73,12 @@ type CreateAgentOptions = { /** Create with this config instead of the empty draft, so eval thread seeding * can recreate an already-built agent in one insert. */ schema?: AgentJsonConfig; + /** Skill bodies keyed by the ref ids of `schema`. A ref to a skills hub skill + * stays a ref; a ref with only a body gets a new hub skill in this project. */ skills?: Record; + /** Creates the hub skills of refs with only a body when `user` is not set. + * Without either, those refs are dropped. */ + skillCreator?: User; /** Opaque custom tool bodies keyed by id (passthrough from the duplicate path; * validated when the source agent was authored). */ tools?: Record; @@ -148,6 +153,7 @@ export class AgentsService { defaultModel, schema, skills, + skillCreator, tools, user, }: CreateAgentOptions, @@ -167,7 +173,6 @@ export class AgentsService { projectId, schema: storedConfig, ...(integrations.length > 0 ? { integrations } : {}), - ...(skills ? { skills } : {}), ...(tools ? { tools: tools as Agent['tools'] } : {}), versionId: uuid(), availableInMCP, @@ -179,7 +184,13 @@ export class AgentsService { // client-minted id names instead of letting the primary key reject it. await this.transactionRunner.run({}, async (ctx) => { await this.agentRepository.insertNew(agent, ctx); - await this.agentSkillRefs.replaceDraftRefs(agent, skillRefs, ctx); + await this.agentSkillRefs.createDraftRefs( + agent, + skillRefs, + skills ?? {}, + user ?? skillCreator ?? null, + ctx, + ); }); saved = agent; } catch (error) { @@ -285,10 +296,10 @@ export class AgentsService { const mcpServers = (schema?.mcpServers ?? []).map((server) => ({ name: server.name })); - const skillRefs = await this.agentSkillRefs.refsForDraft(entity, {}); - const skills = (skillRefs ?? []).map((skill) => ({ + const draftSkills = await this.agentSkillRefs.readDraft(entity, {}); + const skills = (draftSkills.skillRefs ?? []).map((skill) => ({ id: skill.id, - name: entity.skills[skill.id]?.name ?? skill.id, + name: draftSkills.skills[skill.id]?.name ?? skill.id, })); const tasks = await this.getCapabilityTasks(entity); @@ -459,13 +470,12 @@ export class AgentsService { return await this.agentExecutionService.findN8nChatThreadForAgents(user.id, agentIds, threadId); } - /** The agents overview list: every project the user belongs to, no scope check. */ - async findByUserMembershipPaginated( + /** The agents overview list: every project where the user holds `agent:list`. */ + async findListableByUserPaginated( user: User, options: ListAgentsQueryDto, ): Promise { - const projectRelations = await this.projectRelationRepository.findAllByUser(user.id); - const projectIds = projectRelations.map((pr) => pr.projectId); + const projectIds = await this.projectScopeService.getProjectIds(user, ['agent:list']); return await this.agentRepository.findByProjectIdsPaginated(projectIds, options); } diff --git a/packages/cli/src/modules/agents/background/__tests__/sub-agent-background-runner.test.ts b/packages/cli/src/modules/agents/background/__tests__/sub-agent-background-runner.test.ts index b77df9c3ff9..145ff8579e1 100644 --- a/packages/cli/src/modules/agents/background/__tests__/sub-agent-background-runner.test.ts +++ b/packages/cli/src/modules/agents/background/__tests__/sub-agent-background-runner.test.ts @@ -437,6 +437,34 @@ describe('spawn', () => { ); }); + it('settles a guardrail-stopped run as failed with the stop reason', async () => { + const { backgroundRunner, runner, jobService, context } = setup(); + runner.run.mockResolvedValue( + completedRunResult({ + status: 'failed', + result: { + runId: 'run-1', + messages: [], + finishReason: 'guardrail', + guardrail: { code: 'budget.session' }, + getState: () => ({}), + }, + } as unknown as Partial), + ); + + await backgroundRunner.spawn(request, context); + await flushDetachedRun(); + + expect(jobService.settle).toHaveBeenCalledWith( + expect.any(String), + { + status: 'failed', + error: 'The sub-agent run was stopped: the session cost cap is spent.', + }, + { status: 'running', timeoutAt: expect.any(Date) }, + ); + }); + it.each(['suspended', 'paused'] as const)( 'stops the execution timer without completing a %s child', async (status) => { diff --git a/packages/cli/src/modules/agents/budget-guardrail.ts b/packages/cli/src/modules/agents/budget-guardrail.ts index 1dcc79e041a..28d47d2b47c 100644 --- a/packages/cli/src/modules/agents/budget-guardrail.ts +++ b/packages/cli/src/modules/agents/budget-guardrail.ts @@ -1,12 +1,17 @@ import { createBudgetGuardrail, type ExecutionOptions, + type GuardrailsOptions, type RunOptions, type SpendEntry, type SpendLedger, type SpendTotal, } from '@n8n/agents'; -import type { BudgetGuardrailConfig } from '@n8n/api-types'; +import { + isAgentBudgetNoticeCode, + type AgentBudgetNotice, + type BudgetGuardrailConfig, +} from '@n8n/api-types'; import { Logger } from '@n8n/backend-common'; import { Container, Service } from '@n8n/di'; @@ -130,7 +135,7 @@ export interface BudgetAttachInput { */ useRootSessionCap?: boolean; /** Preview chat shows the approaching card. Cloud also emails the project owner. */ - onNotice?: (notice: { code: 'budget.alert' }) => void; + onNotice?: (notice: AgentBudgetNotice) => void; } interface ResolvedBudgetLimits { @@ -228,13 +233,53 @@ function hasId(value: string | undefined): value is string { return value !== undefined && value.length > 0; } -/** Appends the budget hook when a bucket is on. Leaves the options unchanged otherwise. */ +/** + * Adapts the budget notice callback to the SDK's guardrail notice sink, so a + * delegated run can forward it to its own children. Drops non-budget codes. + */ +function toGuardrailNoticeSink(input: BudgetAttachInput): GuardrailsOptions['onNotice'] { + if (!input.onNotice) return undefined; + return (notice) => { + if (!isAgentBudgetNoticeCode(notice.code)) return; + input.onNotice?.({ + code: notice.code, + ...(notice.agentId !== undefined ? { agentId: notice.agentId } : {}), + }); + }; +} + +/** + * Appends hooks and the notice sink to the run's guardrail options, preserving + * the existing agent and thread scope. An input sink wins over a stored one. + */ +function attachGuardrails( + options: T, + hooks: GuardrailsOptions['hooks'], + onNotice: GuardrailsOptions['onNotice'], +): T { + const existing = options.guardrails; + const notice = onNotice ?? existing?.onNotice; + return { + ...options, + guardrails: { + hooks: [...(existing?.hooks ?? []), ...hooks], + ...(existing?.agentId !== undefined ? { agentId: existing.agentId } : {}), + ...(existing?.threadId !== undefined ? { threadId: existing.threadId } : {}), + ...(notice !== undefined ? { onNotice: notice } : {}), + }, + }; +} + +/** + * Appends the budget hook when a bucket is on. + */ export function withBudgetGuardrail( options: T, input: BudgetAttachInput, ): T { const limits = resolveBudgetLimits(input); - if (!limits) return options; + const sink = toGuardrailNoticeSink(input); + if (!limits) return sink ? attachGuardrails(options, [], sink) : options; const ledger = input.ledger ?? Container.get(AgentSpendLedger); const onNotice = monthlyAlertNotice(input, limits.alertThresholdPercent); @@ -243,13 +288,5 @@ export function withBudgetGuardrail( ...limits, ...(onNotice ? { onNotice } : {}), }); - const existing = options.guardrails; - return { - ...options, - guardrails: { - hooks: [...(existing?.hooks ?? []), hook], - ...(existing?.agentId !== undefined ? { agentId: existing.agentId } : {}), - ...(existing?.threadId !== undefined ? { threadId: existing.threadId } : {}), - }, - }; + return attachGuardrails(options, [hook], sink); } diff --git a/packages/cli/src/modules/agents/builder/__tests__/agents-builder.service.session.test.ts b/packages/cli/src/modules/agents/builder/__tests__/agents-builder.service.session.test.ts index 752fae4e1db..b9cd50d3d32 100644 --- a/packages/cli/src/modules/agents/builder/__tests__/agents-builder.service.session.test.ts +++ b/packages/cli/src/modules/agents/builder/__tests__/agents-builder.service.session.test.ts @@ -125,11 +125,6 @@ const agentsSdkMocks = vi.hoisted(() => { function createObservationLogReflectFn(model: unknown, options: unknown) { return { model, options, kind: 'reflect' }; } - - function createPlannerTodosTool(): BuiltTool { - return { name: 'write_todos', description: 'planner todos tool' } as BuiltTool; - } - return { streamCalls, resumeCalls, @@ -147,7 +142,6 @@ const agentsSdkMocks = vi.hoisted(() => { MockMemory, createObservationLogObserveFn, createObservationLogReflectFn, - createPlannerTodosTool, }; }); @@ -157,7 +151,6 @@ vi.mock('@n8n/agents', async (importOriginal) => ({ Memory: agentsSdkMocks.MockMemory, createObservationLogObserveFn: agentsSdkMocks.createObservationLogObserveFn, createObservationLogReflectFn: agentsSdkMocks.createObservationLogReflectFn, - createPlannerTodosTool: agentsSdkMocks.createPlannerTodosTool, })); // Avoid a real `models.dev` catalog fetch — irrelevant to thread isolation and @@ -406,6 +399,7 @@ describe('AgentsBuilderService session isolation', () => { expect(agentsSdkMocks.registeredToolNames).toEqual( expect.arrayContaining(['resolve_llm', 'agent-context', 'ask_credential']), ); + expect(agentsSdkMocks.registeredToolNames).not.toContain('write_todos'); }); it('registers the parent MCP tools for an initial builder turn', async () => { diff --git a/packages/cli/src/modules/agents/builder/__tests__/builder-model-live-lookup.service.test.ts b/packages/cli/src/modules/agents/builder/__tests__/builder-model-live-lookup.service.test.ts index d9b2f440e7a..d99ace86cd1 100644 --- a/packages/cli/src/modules/agents/builder/__tests__/builder-model-live-lookup.service.test.ts +++ b/packages/cli/src/modules/agents/builder/__tests__/builder-model-live-lookup.service.test.ts @@ -262,6 +262,36 @@ describe('BuilderModelLiveLookupService', () => { }); }); + it('passes a priority from Gateway credits discovery on to the model choice', async () => { + const { service, aiGatewayService } = makeService(); + aiGatewayService.getCredentialTypeForProvider.mockResolvedValue('googlePalmApi'); + aiGatewayService.getSyntheticCredential.mockResolvedValue({ + apiKey: 'gateway-jwt', + host: 'https://gw.example/v1/gateway/google', + }); + listModelsForProvider.mockResolvedValue([ + { id: 'models/gemini-featured', name: 'Gemini Featured', priority: 10 }, + { id: 'models/gemini-2.5-pro', name: 'Gemini 2.5 Pro' }, + ]); + + const result = await service.lookup( + user, + projectId, + AI_GATEWAY_MANAGED_TAG, + 'googlePalmApi', + 'google', + ); + + expect(result).toEqual({ + status: 'success', + policy: 'managed', + models: [ + { name: 'Gemini Featured', value: 'models/gemini-featured', priority: 10 }, + { name: 'Gemini 2.5 Pro', value: 'models/gemini-2.5-pro' }, + ], + }); + }); + it('keeps list compatible with successful and unavailable lookups', async () => { const { service } = makeService(); const models = [{ name: 'GPT-5', value: 'gpt-5' }]; @@ -299,6 +329,7 @@ describe('BuilderModelLiveLookupService', () => { expect(result).toEqual([{ name: 'Claude Sonnet 4.6', value: 'claude-sonnet-4-6' }]); expect(credentialsService.getCredentialsAUserCanUseInAWorkflow).toHaveBeenCalledWith(user, { projectId, + excludePersonalRoute: true, }); // Credential fields are mapped for the provider (anthropic: apiKey + url→baseURL). expect(listModelsForProvider).toHaveBeenCalledWith( diff --git a/packages/cli/src/modules/agents/builder/__tests__/external-services.skill.test.ts b/packages/cli/src/modules/agents/builder/__tests__/external-services.skill.test.ts new file mode 100644 index 00000000000..ae333a06866 --- /dev/null +++ b/packages/cli/src/modules/agents/builder/__tests__/external-services.skill.test.ts @@ -0,0 +1,19 @@ +import { externalServicesSkill } from '../skills/external-services.skill'; + +describe('externalServicesSkill', () => { + it('encodes MCP tool exposure restrictions as an allowlist', () => { + const instructions = externalServicesSkill().instructions; + + expect(instructions).toContain( + 'Omit `toolPermissions` unless the user explicitly asks to require approval,\n' + + ' block a tool or category, or restrict which tools are exposed.', + ); + expect(instructions).toContain( + 'Treat requests to expose or allow only named tools as an allowlist.', + ); + expect(instructions).toContain( + '`toolPermissions.categories.write` to `"blocked"`, then add each selected\n' + + ' tool to `toolPermissions.tools` as an `"always_allow"` override.', + ); + }); +}); diff --git a/packages/cli/src/modules/agents/builder/__tests__/verify-mcp-server.tool.test.ts b/packages/cli/src/modules/agents/builder/__tests__/verify-mcp-server.tool.test.ts index 43dde950728..926f1900da4 100644 --- a/packages/cli/src/modules/agents/builder/__tests__/verify-mcp-server.tool.test.ts +++ b/packages/cli/src/modules/agents/builder/__tests__/verify-mcp-server.tool.test.ts @@ -95,8 +95,39 @@ describe('buildVerifyMcpServerTool', () => { expect(result).toEqual({ ok: true, tools: [ - { name: 'echo', description: 'Echo the input' }, - { name: 'add', description: 'Add two numbers' }, + { name: 'echo', description: 'Echo the input', category: 'write' }, + { name: 'add', description: 'Add two numbers', category: 'write' }, + ], + }); + }); + + it('classifies tools from their MCP annotations', async () => { + const mcpClient = makeMcpClient({ + listTools: vi.fn().mockResolvedValue([ + { + name: 'ambiguous_lookup', + description: 'Inspect data', + mcpAnnotations: { readOnlyHint: true }, + }, + { + name: 'search_records', + description: 'Mutate data', + mcpAnnotations: { destructiveHint: true }, + }, + ]), + }); + buildMcpClientForServerMock.mockResolvedValue(mcpClient); + + const result = await buildVerifyMcpServerTool(makeDeps()).handler!( + { name: 'my-server', url: 'https://example.test/mcp' }, + {} as never, + ); + + expect(result).toEqual({ + ok: true, + tools: [ + { name: 'ambiguous_lookup', description: 'Inspect data', category: 'read' }, + { name: 'search_records', description: 'Mutate data', category: 'write' }, ], }); }); @@ -121,7 +152,7 @@ describe('buildVerifyMcpServerTool', () => { expect(result).toEqual({ ok: true, - tools: [{ name: 'list_issues', description: 'List issues' }], + tools: [{ name: 'list_issues', description: 'List issues', category: 'read' }], }); }); @@ -139,7 +170,7 @@ describe('buildVerifyMcpServerTool', () => { expect(result).toEqual({ ok: true, - tools: [{ name: 'silent-tool', description: '' }], + tools: [{ name: 'silent-tool', description: '', category: 'write' }], }); }); @@ -211,6 +242,25 @@ describe('buildVerifyMcpServerTool', () => { expect(result).toEqual({ ok: false, error: 'connection timeout' }); }); + it('returns the recorded connection failure instead of a false success', async () => { + const mcpClient = makeMcpClient({ + getConnectionFailures: vi + .fn() + .mockReturnValue([{ server: 'my-server', error: 'authentication failed' }]), + }); + buildMcpClientForServerMock.mockResolvedValue(mcpClient); + + const result = await buildVerifyMcpServerTool(makeDeps()).handler!( + { name: 'my-server', url: 'https://example.test/mcp' }, + {} as never, + ); + + expect(result).toEqual({ + ok: false, + error: 'MCP server "my-server" connection failed: authentication failed', + }); + }); + it('returns { ok: false, error } with stringified non-Error rejections', async () => { const mcpClient = makeMcpClient({ listTools: vi.fn().mockRejectedValue('plain string error'), @@ -398,7 +448,7 @@ describe('buildVerifyMcpServerTool', () => { expect(applyCredentialToMcpServer).toHaveBeenCalledWith('notion', 'cred-42'); expect(result).toEqual({ ok: true, - tools: [{ name: 'echo', description: 'Echo the input' }], + tools: [{ name: 'echo', description: 'Echo the input', category: 'write' }], credentialApplied: true, configMutated: true, agentId: 'agent-1', @@ -431,7 +481,7 @@ describe('buildVerifyMcpServerTool', () => { expect(result).toEqual({ ok: true, - tools: [{ name: 'echo', description: 'Echo the input' }], + tools: [{ name: 'echo', description: 'Echo the input', category: 'write' }], }); }); @@ -459,7 +509,7 @@ describe('buildVerifyMcpServerTool', () => { expect(result).toEqual({ ok: true, - tools: [{ name: 'echo', description: 'Echo the input' }], + tools: [{ name: 'echo', description: 'Echo the input', category: 'write' }], credentialApplied: false, }); }); diff --git a/packages/cli/src/modules/agents/builder/agents-builder-prompts.ts b/packages/cli/src/modules/agents/builder/agents-builder-prompts.ts index 4eaa2c19bb5..3043e3f93b8 100644 --- a/packages/cli/src/modules/agents/builder/agents-builder-prompts.ts +++ b/packages/cli/src/modules/agents/builder/agents-builder-prompts.ts @@ -126,7 +126,7 @@ mutation, batching what you can) and follow-up turns where the user asked to do setup in chat. - \`finish_setup\`: use ONCE, only in the trailing step of an initial build - when only blocked tasks remain — the model choice and every open decision + when only pending setup remains — the model choice and every open decision as \`questions\`, one \`credentialRequests\` entry per credential slot, and one \`channels\` entry per drafted channel integration. It shows the setup cards back-to-back without returning control to you between them — @@ -245,35 +245,54 @@ item.`; export const WORKFLOW_SECTION = `\ ## Workflow -1. For every request that builds or changes the agent, call \`write_todos\` - with the full plan first — even short ones. Mark tasks that cannot - proceed without user input as \`blocked\`, stating exactly what is - missing. -2. For fresh agents, call \`agent-context({ type: "config" })\` first. If \`model\` and \`credential\` are - already set (the system auto-selected a sensible default at creation), keep - them and mention the choice as changeable in your summary — do not call - \`resolve_llm\`. If \`model\` is empty, call \`resolve_llm\` once, silently. If it - resolves — including an auto-picked provider or newly provisioned free OpenAI - credits — use the result and mention the choice in your summary. If it - reports missing or ambiguous credentials, mark the model - task \`blocked\` and keep building: write the config with \`model: ""\` and - no \`credential\`. -3. Draft lightweight target-agent \`instructions\` containing its identity, - overall purpose, and universal rules, then write the config early; never +1. For every request that builds or changes the agent, plan the full build + before your first tool call, even for short requests. The plan names every + config change, tool, skill, task, and integration that the agent's + functions need. It also lists the pending setup: each item that cannot + proceed without user input, with exactly what is missing. Do not write the + plan out. Keep to it until every item is done or pending. +2. For fresh agents, start with one discovery response. Call these tools in + parallel in that response: \`agent-context({ type: "config" })\`, + \`load_skill\` for each runtime skill the plan needs, and the discovery + lookups the plan names — \`agent-context({ type: "integrations" })\` for a + chat channel, and one \`agent-context({ type: "integrations", queries })\` + call for each callable service. A discovery lookup does not need the skill + text first. +3. In the next response, call \`get_node_types\` for the node results you will + use, and resolve the model in the same response. If \`model\` and + \`credential\` are already set (the system auto-selected a sensible default + at creation), keep them and mention the choice as changeable in your + summary — do not call \`resolve_llm\`. If \`model\` is empty, call + \`resolve_llm\` once, silently. If it resolves — including an auto-picked + provider or newly provisioned free OpenAI credits — use the result and + mention the choice in your summary. If it reports missing or ambiguous + credentials, add the model choice to the pending setup and keep building: + write the config with \`model: ""\` and no \`credential\`. +4. Write the config once, with everything discovery found: the name, + lightweight target-agent \`instructions\` (identity, overall purpose, and + universal rules), the model, the node tools, and the drafts for setup the + user must finish (channel integrations, MCP servers, empty credential + slots). Do not write a partial config and patch it in the next step. Never write empty placeholders, and never wait for setup answers before writing instructions, tools, skills, or tasks. -4. Load relevant runtime skills before specialized discovery or asset work. -5. Perform discovery and create or update the tools, focused skills, and tasks - required by the target agent's functions, whether or not the user named - those artifact types explicitly. +5. Create or update the focused skills and tasks required by the target + agent's functions, whether or not the user named those artifact types + explicitly. Use \`patch_config\` only for changes that discovery could not + know before the config write. 6. Follow Config Freshness for every config mutation: chain each write from the \`configHash\` your previous write returned. 7. When both skill and task batches are fully specified, call \`create_skills\` and \`create_tasks\` in the same assistant response. Do not combine either with an interactive tool or \`write_config\`/\`patch_config\` in that response. -8. When only blocked tasks remain, call \`finish_setup\` once with every - pending item, per the Initial Build section, then resolve its results and - finish the plan. Base any follow-up patch on the \`config\` and +8. When only pending setup remains, call \`finish_setup\` once with every + pending item, per the Initial Build section. Before that call, check the + plan: every item that does not need user input must be done. The + \`finish_setup\` input is your record of the pending items. After it + returns, resolve each item from its results and finish every build step + that waited on that input. Outside an initial build, if pending setup + remains at the end of the turn, end with a summary of what is missing, and + finish those items in later turns as the user gives the input. Base any + follow-up patch on the \`config\` and \`configHash\` that \`finish_setup\` returns (or on your last \`configHash\` when it showed no card and returned none); do not read the config again. 9. After setup is complete and the agent is runnable, call \`call_agent\` once @@ -290,20 +309,22 @@ export const FEW_SHOT_FLOWS_SECTION = `\ ## Example flows ### New agent: "Build me an agent teammates can @mention in Slack to triage messages" -1. \`write_todos\` with the plan. \`agent-context({ type: "config" })\` first — if a model and - credential are already set (system auto-selected default), keep them and - mention the choice as changeable; otherwise \`resolve_llm({})\` once, - silently; if it reports missing credentials, mark the model task \`blocked\`. -2. \`write_config(...)\` with the \`configHash\` from step 1, the name and - instructions, and the model and credential only if \`resolve_llm\` ran — - or \`model: ""\` and no \`credential\` while the model task is blocked. - Omit fields that are already stored and unchanged. -3. Load \`agent-builder-external-services\` and call \`agent-context({ type: "integrations" })\`. -4. \`patch_config(...)\` with the \`configHash\` that \`write_config\` returned, - adding the returned Slack type to \`/integrations/-\` with \`credentialId: ""\`. -5. \`finish_setup({ channels: [{ integrationType: "slack" }] })\` — include - \`questions: []\` only if the model task is blocked; when - \`resolve_llm\` already resolved in step 1, pass only the channel. For a +1. In one response, in parallel: \`agent-context({ type: "config" })\`, + \`load_skill\` for \`agent-builder-external-services\`, and + \`agent-context({ type: "integrations" })\`. +2. If a model and credential are already set (system auto-selected default), + keep them and mention the choice as changeable; otherwise + \`resolve_llm({})\` once, silently; if it reports missing credentials, add + the model choice to the pending setup. +3. \`write_config(...)\` with the \`configHash\` from step 1, the name and + instructions, the returned Slack type in \`integrations\` with + \`credentialId: ""\`, and the model and credential only if + \`resolve_llm\` ran — or \`model: ""\` and no \`credential\` while the + model choice is pending. Omit fields that are already stored and unchanged. +4. \`finish_setup({ channels: [{ integrationType: "slack" }] })\` — include + \`questions: []\` only if the model choice is pending; when + the model is already set or \`resolve_llm\` resolved it in step 2, pass + only the channel. For a model answer, call \`resolve_llm\` with it, then \`patch_config(...)\` with the \`configHash\` that \`finish_setup\` returned, replacing \`/model\` and \`/credential\`. The channel @@ -314,18 +335,16 @@ export const FEW_SHOT_FLOWS_SECTION = `\ the agent panel. ### New agent: "Use Anthropic via OpenRouter" -1. \`write_todos\` with the plan. -2. \`resolve_llm({ provider: "openrouter" })\`. -3. \`agent-context({ type: "config" })\`. -4. \`write_config(...)\` with \`model: "openrouter/{resolvedModel}"\`, +1. \`resolve_llm({ provider: "openrouter" })\`. +2. \`agent-context({ type: "config" })\`. +3. \`write_config(...)\` with \`model: "openrouter/{resolvedModel}"\`, \`credential\`, and requested instructions. ### Change the existing model -1. \`write_todos\` with the plan. -2. \`ask_questions({ ... })\` for the new model choice, then +1. \`ask_questions({ ... })\` for the new model choice, then \`resolve_llm({ provider, model })\`. -3. \`agent-context({ type: "config" })\`. -4. \`patch_config(...)\` replacing \`/model\` and \`/credential\`. +2. \`agent-context({ type: "config" })\`. +3. \`patch_config(...)\` replacing \`/model\` and \`/credential\`. ### Add an explicitly requested n8n node tool to an existing agent 1. Load \`agent-builder-node-tools\`, then call \`search_nodes\` and diff --git a/packages/cli/src/modules/agents/builder/agents-builder-tools.service.ts b/packages/cli/src/modules/agents/builder/agents-builder-tools.service.ts index dd644645de7..4f2e1004330 100644 --- a/packages/cli/src/modules/agents/builder/agents-builder-tools.service.ts +++ b/packages/cli/src/modules/agents/builder/agents-builder-tools.service.ts @@ -194,9 +194,6 @@ const createSkillInputSchema = z name: agentSkillSchema.shape.name.describe('Human-readable skill name'), description: agentSkillSchema.shape.description.describe(SKILL_DESCRIPTION_RULE), instructions: agentSkillSchema.shape.instructions.describe(SKILL_BODY_GUIDANCE), - allowedTools: agentSkillSchema.shape.allowedTools - .optional() - .describe('Exact target-agent tool names this skill is allowed to use.'), references: agentSkillSchema.shape.references .optional() .describe( @@ -235,7 +232,6 @@ const updateSkillFieldsSchema = z 'Targeted replacements in the current instructions, applied in order. Prefer this to ' + '`instructions` for a partial change. Do not pass both.', ), - allowedTools: agentSkillSchema.shape.allowedTools.unwrap().min(1).nullable().optional(), references: agentSkillSchema.shape.references .unwrap() .refine((references) => references.length > 0, 'Pass null to clear references.') @@ -260,7 +256,7 @@ const updateSkillInputSchema = z 'skillHash from the immediately preceding agent-context with type "skill" result for this skill.', ), updates: updateSkillFieldsSchema.describe( - 'Only the fields to change. Pass null for allowedTools or references to remove that field; empty arrays are invalid.', + 'Only the fields to change. Pass null for references to remove them; an empty array is invalid.', ), }) .strict(); @@ -1146,8 +1142,10 @@ export class AgentsBuilderToolsService { 'Update selected fields of an existing target-agent skill in place, preserving its id and ' + 'agent config reference. Requires baseSkillHash from the immediately preceding agent-context with type "skill" ' + 'result. To change part of the body, pass instructionEdits with oldText/newText pairs ' + - 'instead of rewriting instructions. Pass null for allowedTools to remove the tool restriction, ' + - 'or null for references to remove all references; empty arrays are invalid. Returns ' + + 'instead of rewriting instructions. Pass null for references to remove all references; an ' + + 'empty array is invalid. The skill is shared: the update saves its next version, and every ' + + 'agent draft that follows the latest version runs that version. Published versions keep ' + + 'the version they pinned. Returns ' + '{ ok: true, id, name, configMutated: true, agentId } or { ok: false, errors }. A failed edit ' + 'saves nothing: fix oldText so it matches exactly one place and retry with the same ' + 'baseSkillHash. On a stale skill error, ' + @@ -1157,10 +1155,9 @@ export class AgentsBuilderToolsService { .handler(async ({ skillId, baseSkillHash, updates }: UpdateSkillInput) => { const editorLock = await this.getEditorLockFailure(agentId); if (editorLock) return editorLock; - const { allowedTools, references, instructionEdits, ...requiredUpdates } = updates; + const { references, instructionEdits, ...requiredUpdates } = updates; const normalizedUpdates = { ...requiredUpdates, - ...(allowedTools !== undefined ? { allowedTools: allowedTools ?? undefined } : {}), ...(references !== undefined ? { references: references ?? undefined } : {}), }; @@ -1211,7 +1208,7 @@ export class AgentsBuilderToolsService { 'applicable section filled in with concrete, specific content. If you do not have enough domain ' + "detail to write a genuinely useful skill, derive it from the user's goal as stated assumptions " + 'listed in your summary; ask the user clarifying questions only when even a reasonable ' + - 'assumption is impossible. Use allowedTools only with exact target-agent tool names. Use references ' + + 'assumption is impossible. Use references ' + 'only for markdown supporting files under the references/ directory — references are not ' + 'automatically loaded, so instructions must say exactly when to load each one by path; scripts and ' + 'non-markdown linked files are not supported. Do not invent tool names or reference paths. Batch ' + diff --git a/packages/cli/src/modules/agents/builder/agents-builder.service.ts b/packages/cli/src/modules/agents/builder/agents-builder.service.ts index ac8ba06cbea..e374e60e0c9 100644 --- a/packages/cli/src/modules/agents/builder/agents-builder.service.ts +++ b/packages/cli/src/modules/agents/builder/agents-builder.service.ts @@ -38,10 +38,6 @@ import { getModelRecommendationsSection } from './agents-builder-model-recommend import { buildBuilderPrompt, buildBuilderSessionContext } from './agents-builder-prompts'; import { AgentsBuilderToolsService, type BuilderTools } from './agents-builder-tools.service'; import { BuilderCheckpointUnavailableError } from './errors'; -import { - BUILDER_PLANNER_TODOS_DESCRIPTION, - BUILDER_PLANNER_TODOS_SYSTEM_INSTRUCTION, -} from './prompts/planner-todos.prompt'; import { getBuilderRuntimeSkills } from './skills'; import { N8NCheckpointStorage } from '../integrations/n8n-checkpoint-storage'; import { N8nMemory } from '../integrations/n8n-memory'; @@ -376,16 +372,10 @@ export class AgentsBuilderService { agentId: string, session: InstanceAiBuilderSessionOptions, ): Promise { - const { createPlannerTodosTool } = await import('@n8n/agents'); - const plannerTodosTool = createPlannerTodosTool({ - description: BUILDER_PLANNER_TODOS_DESCRIPTION, - systemInstruction: BUILDER_PLANNER_TODOS_SYSTEM_INSTRUCTION, - }); const reportRequiredArtifactTool = await this.createRequiredArtifactTool(session); const builderTools = [ ...tools.json, ...tools.shared, - plannerTodosTool, ...(reportRequiredArtifactTool ? [reportRequiredArtifactTool] : []), ]; const claimedToolNames = new Set(builderTools.map((tool) => tool.name)); diff --git a/packages/cli/src/modules/agents/builder/builder-model-live-lookup.service.ts b/packages/cli/src/modules/agents/builder/builder-model-live-lookup.service.ts index 51b768d58e8..d14aec96cce 100644 --- a/packages/cli/src/modules/agents/builder/builder-model-live-lookup.service.ts +++ b/packages/cli/src/modules/agents/builder/builder-model-live-lookup.service.ts @@ -89,7 +89,7 @@ export class BuilderModelLiveLookupService { const usableCredentials = await this.credentialsService.getCredentialsAUserCanUseInAWorkflow( user, - { projectId }, + { projectId, excludePersonalRoute: true }, ); const usable = usableCredentials.find((c) => c.id === credentialId); if (!usable || usable.type !== credentialType) { @@ -190,7 +190,11 @@ export class BuilderModelLiveLookupService { return { status: 'success', - models: models.map((model) => ({ name: model.name, value: model.id })), + models: models.map((model) => ({ + name: model.name, + value: model.id, + ...(model.priority !== undefined ? { priority: model.priority } : {}), + })), policy, }; } catch (error) { diff --git a/packages/cli/src/modules/agents/builder/interactive/finish-setup.tool.ts b/packages/cli/src/modules/agents/builder/interactive/finish-setup.tool.ts index f2eddc01a93..e814fb03dcd 100644 --- a/packages/cli/src/modules/agents/builder/interactive/finish-setup.tool.ts +++ b/packages/cli/src/modules/agents/builder/interactive/finish-setup.tool.ts @@ -439,7 +439,7 @@ export function buildFinishSetupTool(deps: FinishSetupToolDeps): BuiltTool { 'Collect everything still needed to finish the initial build in ONE guided flow: open ' + 'questions (including the model choice), credential slots, and chat-channel ' + 'setup. Call it at most once, only in the trailing step of an initial build ' + - 'when only blocked tasks remain, and never together with another interactive tool. ' + + 'when only pending setup remains, and never together with another interactive tool. ' + 'It shows setup cards back-to-back without returning control between them: questions, ' + 'then credentials, then one card per requested channel. Channel cards always run last ' + 'after every credential phase, including when earlier setup was skipped or dismissed. Pass ' + diff --git a/packages/cli/src/modules/agents/builder/model-lookup.types.ts b/packages/cli/src/modules/agents/builder/model-lookup.types.ts index 2909c140bed..9ba0e4ac3ee 100644 --- a/packages/cli/src/modules/agents/builder/model-lookup.types.ts +++ b/packages/cli/src/modules/agents/builder/model-lookup.types.ts @@ -1,4 +1,6 @@ export interface ModelChoice { name: string; value: string; + /** Pickers list models with a priority first, highest first. Only the AI Gateway reports one. */ + priority?: number; } diff --git a/packages/cli/src/modules/agents/builder/prompts/config-mutation.prompt.ts b/packages/cli/src/modules/agents/builder/prompts/config-mutation.prompt.ts index f9ce7fa94b2..f968c142b36 100644 --- a/packages/cli/src/modules/agents/builder/prompts/config-mutation.prompt.ts +++ b/packages/cli/src/modules/agents/builder/prompts/config-mutation.prompt.ts @@ -74,6 +74,9 @@ Use \`patch_config\` with: - To attach an existing, unattached skill: if \`skills\` exists, append to \`/skills/-\`; if \`skills\` is missing, add \`/skills\` with an array. - Ref shape: \`{ "type": "skill", "id": "" }\`. +- A ref with \`versionId\` pins that saved version of the skill. To use the latest + version, remove \`versionId\` from the ref with \`patch_config\`. Do not remove + the skill and add it again. #### Remove An Existing Chat Integration diff --git a/packages/cli/src/modules/agents/builder/prompts/initial-build.prompt.ts b/packages/cli/src/modules/agents/builder/prompts/initial-build.prompt.ts index 9c80bed53b4..1576eed180c 100644 --- a/packages/cli/src/modules/agents/builder/prompts/initial-build.prompt.ts +++ b/packages/cli/src/modules/agents/builder/prompts/initial-build.prompt.ts @@ -49,14 +49,15 @@ During an initial build: \`credential\` omitted (skip verification), node tools with credential slots omitted. Leave Episodic Memory disabled while its credential is missing. -- Mark setup-dependent plan tasks \`blocked\`, stating exactly what is missing. -- When only blocked tasks remain, call \`finish_setup\` ONCE with everything +- Add each setup-dependent item to the pending setup, stating exactly what is + missing. Keep building everything that does not depend on it. +- When only pending setup remains, call \`finish_setup\` ONCE with everything pending: the model choice and open decisions as \`questions\`, one \`credentialRequests\` entry per credential slot, and one \`channels\` entry per drafted channel integration — it configures or skips each channel itself, always as the last cards in the flow. Resolve its results — \`resolve_llm\` with the model answer, patch returned credential ids into the config, - verify MCP servers — and finish the plan. + verify MCP servers — and finish every build step that waited on that setup. - Do not call \`configure_channel\` again after \`finish_setup\` handles a channel card. - After \`finish_setup\`, end your reply with a short setup checklist for skipped or dismissed setup that remains unresolved — one line per item naming diff --git a/packages/cli/src/modules/agents/builder/prompts/llm-selection.prompt.ts b/packages/cli/src/modules/agents/builder/prompts/llm-selection.prompt.ts index 98dd824bace..91b2fbb0efd 100644 --- a/packages/cli/src/modules/agents/builder/prompts/llm-selection.prompt.ts +++ b/packages/cli/src/modules/agents/builder/prompts/llm-selection.prompt.ts @@ -15,7 +15,7 @@ Use this to resolve the target agent's main \`model\` and \`credential\`. 2. If \`resolve_llm\` succeeds, persist \`model = "{provider}/{model}"\` and \`credential = credentialId\`. If the result has \`claimedFreeOpenAiCredits: true\`, tell the user you set them up with free OpenAI credits. If the result's \`credentialName\` is "Gateway credits" (its \`credentialId\` is the managed tag), persist it like any credential and tell the user the model runs on Gateway credits — never surface the internal "n8n Connect" or "AI Gateway" names. If it has \`autoPicked: true\`, tell the user which provider and model you picked and that they can ask to change it — do not ask for confirmation and do not raise a trailing model question. 3. If the user asks to pick, change, confirm, or configure a model or main credential, ask via \`ask_questions\`; do not ask in prose. - Exception — when the user explicitly asks to use Gateway credits for the main model, do NOT ask: call \`resolve_llm\` with \`useGatewayCredits: true\` (and \`provider\` when the user named one). It resolves Gateway credits for that provider even if the user already has their own credential for it; persist the result (\`credentialName\` "Gateway credits") and tell the user the model runs on Gateway credits. If it returns \`gateway_credits_unsupported_provider\`, tell the user Gateway credits do not cover that provider and offer their own credential; if \`ambiguous_gateway_credits_provider\`, ask which provider via \`ask_questions\` using the returned \`providers\`; if \`gateway_credits_unavailable\`, tell the user Gateway credits are not available on this instance and resolve their own credential instead. On \`unknown_model\`, retry with a value from the returned \`availableModels\` or surface those options. -4. During an initial build, if \`resolve_llm\` reports missing or ambiguous credentials/provider, do not ask: mark the model task \`blocked\`, keep building with \`model: ""\` and no \`credential\`, and include the model choice as a question in the trailing \`finish_setup\` call — for ambiguity between multiple credentials of one provider, use the credential names from the resolve_llm result as the question's options — when it resolves, call \`resolve_llm\` with the answer (pass \`credentialId\` when the user picked a specific credential) and patch \`/model\` and \`/credential\` — base the patch on the \`config\` and \`configHash\` that \`finish_setup\` returned, and check that config first, since the user may have already set the model in the panel. For a model change on an existing agent, ask immediately instead, and never write \`model: ""\` over an existing model — keep the current model and credential until the new one is resolved. +4. During an initial build, if \`resolve_llm\` reports missing or ambiguous credentials/provider, do not ask: add the model choice to the pending setup, keep building with \`model: ""\` and no \`credential\`, and include the model choice as a question in the trailing \`finish_setup\` call — for ambiguity between multiple credentials of one provider, use the credential names from the resolve_llm result as the question's options — when it resolves, call \`resolve_llm\` with the answer (pass \`credentialId\` when the user picked a specific credential) and patch \`/model\` and \`/credential\` — base the patch on the \`config\` and \`configHash\` that \`finish_setup\` returned, and check that config first, since the user may have already set the model in the panel. For a model change on an existing agent, ask immediately instead, and never write \`model: ""\` over an existing model — keep the current model and credential until the new one is resolved. 5. If \`resolve_llm\` reports \`unknown_model\`, retry with a plausible value from the returned \`availableModels\` or ask via \`ask_questions\`. This can happen on the default no-model path too, when the credential cannot reach the provider's default model — the returned \`availableModels\` is that credential's live list, so pick from it rather than guessing or reusing the id you just tried. That list is capped — when \`availableModelsTruncated: true\` it is only a sample of \`totalAvailableModels\`, so ask via \`ask_questions\` instead of assuming the model the user wants is absent. If it reports \`model_lookup_failed\` (the provider's model list could not be fetched, e.g. a transient error — possible even on the default no-model path), retry \`resolve_llm\`; do not guess a model. 6. If \`call_agent\` fails with \`code: "invalid_model"\`, the provider rejected the model id, not the credential. Do not tell the user to check, revoke, or regenerate their API key. Call \`resolve_llm\` for that provider again, persist a model from its result, and retry the test run. 7. If the model is still unresolved when the user asks to run or publish the agent, leave the draft with \`model: ""\`, do not guess a model, and tell the user the agent needs a model and credential first — in the panel or here in chat. If they dismiss a model-change question on an existing agent, keep the current model and credential unchanged. diff --git a/packages/cli/src/modules/agents/builder/prompts/planner-todos.prompt.ts b/packages/cli/src/modules/agents/builder/prompts/planner-todos.prompt.ts deleted file mode 100644 index a9591463313..00000000000 --- a/packages/cli/src/modules/agents/builder/prompts/planner-todos.prompt.ts +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Builder-specific model-visible text for the SDK's `createPlannerTodosTool`. - * The SDK ships domain-neutral defaults; these strings keep the agent - * builder's `write_todos` tool description/instructions unchanged from - * before the SDK text was made generic. - */ -export const BUILDER_PLANNER_TODOS_DESCRIPTION = - 'Create or update a structured task list for the current build. Use it to decompose the work, ' + - 'track progress, and record which tasks are blocked on user input. Use it for every build or ' + - 'change request. This tool only updates the task list; it does not perform work or ask the user.'; - -export const BUILDER_PLANNER_TODOS_SYSTEM_INSTRUCTION = [ - 'write_todos maintains your plan for the current build. It never asks the user or performs work itself.', - 'WHEN TO USE write_todos:', - '- Every request that builds or changes the agent, before other tool calls.', - '- You need to track progress or record tasks blocked on user input.', - 'WHEN NOT TO USE write_todos:', - '- Purely conversational replies with no build work.', - 'HOW TO USE write_todos:', - '- Write concrete, self-contained tasks; mark the first active task in_progress immediately.', - '- Mark a task blocked when it cannot proceed without user input, and state exactly what input is missing in the task content.', - '- Marking a task blocked IS the action for now. Do not ask the user about it while any non-blocked task remains; continue with unblocked tasks.', - '- When only blocked tasks remain: during an initial build, follow the Initial Build rules (call finish_setup); otherwise end your turn with a summary of what is missing, and unblock and finish the tasks in later turns as the user provides input.', - '- Update task status as soon as work completes; do not batch completions at the end.', - '- Do not call write_todos multiple times in parallel; send one full list update at a time.', -].join('\n'); diff --git a/packages/cli/src/modules/agents/builder/skills/external-services.skill.ts b/packages/cli/src/modules/agents/builder/skills/external-services.skill.ts index 0bf63639c50..0df7d9bb633 100644 --- a/packages/cli/src/modules/agents/builder/skills/external-services.skill.ts +++ b/packages/cli/src/modules/agents/builder/skills/external-services.skill.ts @@ -133,10 +133,13 @@ The \`integrations\` array controls how the target agent is triggered. agent; do not follow up with \`patch_config\`/\`write_config\` to write the credential. - ${INITIAL_BUILD_NOTE} Instead of \`configure_channel\`: after - \`agent-context({ type: "integrations" })\` returns the matching type, - \`patch_config\` (with the \`configHash\` from your latest config read or write) adding \`{ "type": "", "credentialId": "" }\` - to \`/integrations/-\` (include a minimal valid draft \`settings\` object for - telegram) so the channel appears in the agent panel as needing setup. Pass + \`agent-context({ type: "integrations" })\` returns the matching type, add + \`{ "type": "", "credentialId": "" }\` to \`integrations\` + in your single initial config write (include a minimal valid draft + \`settings\` object for telegram) so the channel appears in the agent panel + as needing setup. If the config is already written, \`patch_config\` (with + the \`configHash\` from your latest config read or write) adding it to + \`/integrations/-\` instead. Pass the same \`integrationType\` in the trailing \`finish_setup\` call's \`channels\` array — its card configures or skips the channel itself. Do not call \`configure_channel\` again after \`finish_setup\` handles the card. If @@ -227,8 +230,10 @@ Follow these steps for the selected MCP result: credential is already persisted. ${INITIAL_BUILD_NOTE} For MCP that means: pick the best candidate as an -assumption (above), then \`patch_config\` (with the \`configHash\` from your latest config read or write) a draft -\`/mcpServers/-\` entry using \`name\`, \`url\`, \`transport\`, +assumption (above), then add a draft \`mcpServers\` entry to your single +initial config write (or \`patch_config\` it to \`/mcpServers/-\`, with the +\`configHash\` from your latest config read or write, if the config is +already written) using \`name\`, \`url\`, \`transport\`, \`authentication\`, and \`metadata.nodeTypeName\` from \`selectedResult\` with \`credential\` omitted, and skip \`verify_mcp_server\` — there is nothing to authenticate yet. Include the credential in the trailing \`finish_setup\` call; @@ -248,15 +253,24 @@ ${mcpServerSchemaText} ### Tool exposure and approval -- Expose every available MCP tool by default: omit \`toolFilter\` unless the user - explicitly asks to restrict which tools are exposed. Do not infer an allowlist - from the requested capability. -- For an explicit filter or selected approval list, use only exact, unprefixed - \`name\` values from \`selectedResult.tools\` or a successful - \`verify_mcp_server\` result. -- Never prepend the server name. Never invent MCP tool names. \`toolFilter.tools\` - and \`approval.tools\` match original MCP names; the SDK adds the server prefix - only when exposing tools to the model. +- Omit \`toolPermissions\` unless the user explicitly asks to require approval, + block a tool or category, or restrict which tools are exposed. Omission + allows all MCP tools without approval. +- Treat requests to expose or allow only named tools as an allowlist. Set both + \`toolPermissions.categories.read\` and + \`toolPermissions.categories.write\` to \`"blocked"\`, then add each selected + tool to \`toolPermissions.tools\` as an \`"always_allow"\` override. +- For other permission controls, set both + \`toolPermissions.categories.read\` and + \`toolPermissions.categories.write\`. Use \`"always_allow"\` for categories + the user did not restrict. +- Use \`"require_approval"\` when the user asks to approve a category or tool + before execution. Use \`"blocked"\` when the user asks to hide or disable it. +- Use category policies for broad read/write rules. Add \`toolPermissions.tools\` + overrides only for exceptions to those category rules. +- For an exact tool override, use only an unprefixed \`name\` from + \`selectedResult.tools\` or a successful \`verify_mcp_server\` result. Never + prepend the server name and never invent MCP tool names. ### Credential flow @@ -300,7 +314,8 @@ setup later: - Either case: skip \`verify_mcp_server\` (there is nothing to authenticate or connect to), then \`agent-context({ type: "config" })\` and \`patch_config\` the entry, preserving every other known field — \`name\`, \`transport\`, \`authentication\`, an - already-selected credential, and registry \`metadata\`. + already-selected credential, registry \`metadata\`, and any explicitly + configured \`toolPermissions\`. ### Selecting credentials @@ -333,6 +348,8 @@ Auth, or None) via \`${ASK_QUESTIONS_TOOL_NAME}\`. Then map to: entry so the UI can render the correct server form. - A registry match proves server availability, not support for the requested capability; use the verified live tool list for that decision. +- Describe an MCP server only by its name, or by text the user or the registry + gave. If you cannot identify it, do not state what it does. ## Verify diff --git a/packages/cli/src/modules/agents/builder/skills/node-tools.skill.ts b/packages/cli/src/modules/agents/builder/skills/node-tools.skill.ts index 78ea6f669f3..a85cdc0d870 100644 --- a/packages/cli/src/modules/agents/builder/skills/node-tools.skill.ts +++ b/packages/cli/src/modules/agents/builder/skills/node-tools.skill.ts @@ -48,8 +48,8 @@ specific-page fetching, use only \`n8n-nodes-base.httpRequestTool\`. Use only an exact URL explicitly supplied by the user for \`n8n-nodes-base.httpRequestTool\`. If the user has not supplied one, you MUST -ask which URL the tool should fetch. During an initial build, mark this setup -as blocked and include the URL question in the single trailing \`finish_setup\` +ask which URL the tool should fetch. During an initial build, add this to the +pending setup and include the URL question in the single trailing \`finish_setup\` call; add the tool with the returned URL after the user answers. On later turns, call \`${ASK_QUESTIONS_TOOL_NAME}\` and wait for the answer before mutating the config. Do not search for, derive, infer, guess, or invent a URL diff --git a/packages/cli/src/modules/agents/builder/skills/target-skills.skill.ts b/packages/cli/src/modules/agents/builder/skills/target-skills.skill.ts index e6569370164..f5c3dd260ef 100644 --- a/packages/cli/src/modules/agents/builder/skills/target-skills.skill.ts +++ b/packages/cli/src/modules/agents/builder/skills/target-skills.skill.ts @@ -68,9 +68,9 @@ applicable sections are filled with real content (the actual steps, rules, examples, and edge cases). Derive missing domain detail from the user's stated goal as stated assumptions, and list them in your summary. Use \`ask_questions\` only when even a reasonable assumption is impossible — never -during an initial build: mark the task \`blocked\` instead, per the Initial -Build rules in your system prompt. Never create a placeholder or vague -skill. +during an initial build: add the open decision to the pending setup +instead, per the Initial Build rules in your system prompt. Never create a +placeholder or vague skill. ## Workflow @@ -94,9 +94,9 @@ skill. when you rewrite most of the body. If an edit fails, nothing changed: fix \`oldText\` so it matches exactly one place and retry with the same \`baseSkillHash\`. - Do not create a replacement skill. Pass \`null\` for \`allowedTools\` to remove the tool - restriction or for \`references\` to remove all references; do not pass empty - arrays. When replacing \`references\`, first read the content of every existing + Do not create a replacement skill. Pass \`null\` for \`references\` to remove + all references; do not pass an empty array. The skill can be shared with other + agents: an update saves its next version for every agent that uses it. When replacing \`references\`, first read the content of every existing reference that must be preserved, because the field is replaced as a whole. - Only call \`create_skills\` when no attached skill owns the capability. Fill the domain detail you need, deriving missing detail from the goal as stated @@ -118,8 +118,6 @@ skill. ## Extended fields -- Use \`allowedTools\` only for exact tool names already attached to the target - agent that this skill may use. - Add \`references\` for longer markdown-only supporting files under \`references/...\`, such as rubrics, examples, policies, templates, or checklists. References are not automatically loaded when the skill loads. diff --git a/packages/cli/src/modules/agents/builder/skills/target-tasks.skill.ts b/packages/cli/src/modules/agents/builder/skills/target-tasks.skill.ts index c52b0541f9e..6bbba6f9c29 100644 --- a/packages/cli/src/modules/agents/builder/skills/target-tasks.skill.ts +++ b/packages/cli/src/modules/agents/builder/skills/target-tasks.skill.ts @@ -74,9 +74,9 @@ BOTH of these are true for it: as an assumption. Use \`ask_questions\` only when even a reasonable assumption is impossible — -never during an initial build: mark the task \`blocked\` instead, per the -Initial Build rules in your system prompt. Never create a placeholder or -"refine-it-later" task. +never during an initial build: add the open decision to the pending setup +instead, per the Initial Build rules in your system prompt. Never create a +placeholder or "refine-it-later" task. ## Workflow diff --git a/packages/cli/src/modules/agents/builder/verify-mcp-server.tool.ts b/packages/cli/src/modules/agents/builder/verify-mcp-server.tool.ts index 35f0086f768..63e1c3c4ea0 100644 --- a/packages/cli/src/modules/agents/builder/verify-mcp-server.tool.ts +++ b/packages/cli/src/modules/agents/builder/verify-mcp-server.tool.ts @@ -1,5 +1,6 @@ import type { BuiltTool, CredentialProvider, McpClient, ToolContext } from '@n8n/agents'; import { Tool } from '@n8n/agents/tool'; +import { classifyMcpTool } from '@n8n/ai-utilities/agent-config'; import { type AgentJsonConfig, McpAuthenticationSchemaTypes, @@ -81,9 +82,9 @@ async function listToolsWithinDeadline( * builder can have in hand before writing the config. The credential field is * optional here so the tool can also be used to test unauthenticated servers. * - * `toolFilter` and `approval` are intentionally excluded — they have no bearing - * on whether the underlying transport connects, and simplifying the input keeps - * the LLM context small. + * Tool permissions are intentionally excluded. They have no bearing on whether + * the underlying transport connects, and simplifying the input keeps the LLM + * context small. */ const verifyMcpServerInputSchema = z.object({ name: z @@ -126,7 +127,7 @@ export function buildVerifyMcpServerTool(deps: VerifyMcpServerDeps): BuiltTool { .description( 'Test connectivity to an MCP server before adding it to the agent config. ' + 'Establishes a temporary connection, lists the available tools, then closes the connection. ' + - 'Returns { ok: true, tools: [{ name, description }] } on success, or ' + + 'Returns { ok: true, tools: [{ name, description, category }] } on success, or ' + '{ ok: false, error: string } on failure. ' + 'Tool names are the original MCP names without the model-facing server prefix. ' + 'When a credential is provided and a matching mcpServers entry already exists, ' + @@ -149,6 +150,9 @@ export function buildVerifyMcpServerTool(deps: VerifyMcpServerDeps): BuiltTool { authentication: input.authentication, credential: input.credential, metadata: input.metadata, + toolPermissions: { + categories: { read: 'always_allow', write: 'always_allow' }, + }, connectionTimeoutMs: timeoutMs, }, deps, @@ -168,6 +172,10 @@ export function buildVerifyMcpServerTool(deps: VerifyMcpServerDeps): BuiltTool { const mappedTools = tools.map((t) => ({ name: t.mcpToolName ?? t.name, description: t.description ?? '', + category: classifyMcpTool({ + name: t.mcpToolName ?? t.name, + annotations: t.mcpAnnotations, + }), })); if (input.credential && deps.applyCredentialToMcpServer) { diff --git a/packages/cli/src/modules/agents/entities/agent-skill-dependency.entity.ts b/packages/cli/src/modules/agents/entities/agent-skill-dependency.entity.ts new file mode 100644 index 00000000000..c96ae5149d3 --- /dev/null +++ b/packages/cli/src/modules/agents/entities/agent-skill-dependency.entity.ts @@ -0,0 +1,20 @@ +import { WithCreatedAt } from '@n8n/db'; +import { Column, Entity, Index, PrimaryColumn } from '@n8n/typeorm'; + +/** + * Mirrors the skill refs of an agent draft, disabled refs included. A row with a + * `skillVersionId` is pinned: that draft reads that saved version instead of the + * skill's latest saved version, so a new Save does not reach it. + */ +@Entity({ name: 'agent_skill_dependency' }) +export class AgentSkillDependency extends WithCreatedAt { + @PrimaryColumn({ type: 'varchar', length: 36 }) + agentId: string; + + @Index() + @PrimaryColumn({ type: 'varchar', length: 36 }) + skillId: string; + + @Column({ type: 'uuid', nullable: true }) + skillVersionId: string | null; +} diff --git a/packages/cli/src/modules/agents/entities/agent-version-skill-dependency.entity.ts b/packages/cli/src/modules/agents/entities/agent-version-skill-dependency.entity.ts new file mode 100644 index 00000000000..a85d4b2e5b4 --- /dev/null +++ b/packages/cli/src/modules/agents/entities/agent-version-skill-dependency.entity.ts @@ -0,0 +1,17 @@ +import { WithCreatedAt } from '@n8n/db'; +import { Column, Entity, Index, PrimaryColumn } from '@n8n/typeorm'; + +/** Pins one skill version to one published agent version. */ +@Entity({ name: 'agent_version_skill_dependency' }) +export class AgentVersionSkillDependency extends WithCreatedAt { + @PrimaryColumn({ type: 'varchar', length: 36 }) + agentVersionId: string; + + @Index() + @PrimaryColumn({ type: 'varchar', length: 36 }) + skillId: string; + + @Index() + @Column({ type: 'uuid' }) + skillVersionId: string; +} diff --git a/packages/cli/src/modules/agents/entities/skill-file.entity.ts b/packages/cli/src/modules/agents/entities/skill-file.entity.ts new file mode 100644 index 00000000000..e103e37f5b1 --- /dev/null +++ b/packages/cli/src/modules/agents/entities/skill-file.entity.ts @@ -0,0 +1,15 @@ +import { WithTimestamps } from '@n8n/db'; +import { Column, Entity, PrimaryColumn } from '@n8n/typeorm'; + +/** A file that belongs to one skill version. Only `references/*.md` in v1. */ +@Entity({ name: 'skill_file' }) +export class SkillFile extends WithTimestamps { + @PrimaryColumn({ type: 'uuid' }) + skillVersionId: string; + + @PrimaryColumn({ type: 'varchar', length: 512 }) + path: string; + + @Column({ type: 'text' }) + content: string; +} diff --git a/packages/cli/src/modules/agents/entities/skill-version.entity.ts b/packages/cli/src/modules/agents/entities/skill-version.entity.ts new file mode 100644 index 00000000000..01990da668f --- /dev/null +++ b/packages/cli/src/modules/agents/entities/skill-version.entity.ts @@ -0,0 +1,49 @@ +import { JsonColumn, WithTimestamps } from '@n8n/db'; +import { Check, Column, Entity, Index, PrimaryColumn } from '@n8n/typeorm'; + +/** + * SKILL.md frontmatter fields other than name and description, e.g. `allowed-tools`, + * stored as given. The standard allows objects and lists, so values are not narrowed. + */ +export type SkillFrontmatter = Record; + +/** + * One saved version of a skill. A Save that changes the content adds the next number; + * a version never changes. Agents read the latest one unless a revert pinned an older one. + */ +@Entity({ name: 'skill_version' }) +@Index(['skillId', 'version'], { unique: true }) +@Check('"version" > 0') +export class SkillVersion extends WithTimestamps { + @PrimaryColumn({ type: 'uuid' }) + id: string; + + @Column({ type: 'varchar', length: 36 }) + skillId: string; + + @Column({ type: 'int' }) + version: number; + + /** Free-text name, as it was when this version was saved. */ + @Column({ type: 'varchar', length: 128 }) + name: string; + + @Column({ type: 'varchar', length: 1024 }) + description: string; + + @Column({ type: 'text' }) + instructions: string; + + @JsonColumn({ nullable: true }) + frontmatter: SkillFrontmatter | null; + + /** + * sha256 of name, description, instructions, frontmatter and files (see + * `skillContentHash`). Save creates no version when the content matches the latest one. + */ + @Column({ type: 'varchar', length: 64 }) + contentHash: string; + + @Column({ type: 'uuid', nullable: true }) + createdById: string | null; +} diff --git a/packages/cli/src/modules/agents/entities/skill.entity.ts b/packages/cli/src/modules/agents/entities/skill.entity.ts new file mode 100644 index 00000000000..d7e8d96560b --- /dev/null +++ b/packages/cli/src/modules/agents/entities/skill.entity.ts @@ -0,0 +1,31 @@ +import { WithTimestamps } from '@n8n/db'; +import { Column, Entity, Index, PrimaryColumn } from '@n8n/typeorm'; + +/** How a skill was created: `ui` in the skills hub, `agent` from the agent builder or the migration. */ +export type SkillSource = 'ui' | 'agent'; + +/** + * A skill in the skills hub, identified by its id only. One target: `projectId` (a team + * or personal project, used by its agents), `agentId` (only that agent can use it; the + * project is the agent's), or neither (the instance). + * The name and content live in `SkillVersion` rows. + */ +@Entity({ name: 'skill' }) +export class Skill extends WithTimestamps { + @PrimaryColumn({ type: 'varchar', length: 36 }) + id: string; + + @Index() + @Column({ type: 'varchar', length: 36, nullable: true }) + projectId: string | null; + + @Index() + @Column({ type: 'varchar', length: 36, nullable: true }) + agentId: string | null; + + @Column({ type: 'varchar', length: 16 }) + source: SkillSource; + + @Column({ type: 'uuid', nullable: true }) + createdById: string | null; +} diff --git a/packages/cli/src/modules/agents/instance-ai-agent-context.adapter.ts b/packages/cli/src/modules/agents/instance-ai-agent-context.adapter.ts index 3264d563a23..bac0eff0858 100644 --- a/packages/cli/src/modules/agents/instance-ai-agent-context.adapter.ts +++ b/packages/cli/src/modules/agents/instance-ai-agent-context.adapter.ts @@ -23,6 +23,7 @@ import { listAgentTasks, readAgentSkill } from './agent-context-readers'; import { AgentIntegrationPersistenceService } from './agent-integration-persistence.service'; import { AgentSkillsService } from './agent-skills.service'; import { AgentTaskService } from './agent-task.service'; +import { AgentsSettingsService } from './agents-settings.service'; import { AgentsToolsService } from './agents-tools.service'; import { AgentsService } from './agents.service'; import { AttachableWorkflowsService } from './attachable-workflows.service'; @@ -86,12 +87,17 @@ export class InstanceAiAgentContextAdapterService { private readonly mcpRegistryService: McpRegistryService, private readonly agentsToolsService: AgentsToolsService, private readonly agentSkillRefs: AgentSkillRefsService, + private readonly agentsSettingsService: AgentsSettingsService, ) {} createReader(user: User, projectId: string): InstanceAiAgentContextReader { let canReadAgents: Promise | undefined; return { lookup: async (input) => { + // Checked on every lookup, so a run loses access as soon as Agents are turned off. + await this.agentsSettingsService.assertEnabled().catch((error: unknown) => { + throw error instanceof ForbiddenError ? new UserError(error.message) : error; + }); canReadAgents ??= userHasScopes(user, ['agent:read'], false, { projectId }); if (!(await canReadAgents)) { throw new UserError("You don't have permission to read Agents in this project."); @@ -165,7 +171,9 @@ export class InstanceAiAgentContextAdapterService { const agent = await this.agentsService.findById(input.agentId, projectId); if (!agent) throw new UserError('Agent not found.'); - const config = composeJsonConfig(agent, await this.agentSkillRefs.refsForDraft(agent, {})); + // Refs only: the skill bodies are read in the `skills` case, which needs them. + const skillRefs = await this.agentSkillRefs.refsForDraft(agent, {}); + const config = composeJsonConfig(agent, skillRefs); switch (input.type) { case 'config': @@ -183,12 +191,14 @@ export class InstanceAiAgentContextAdapterService { configHash: getAgentConfigHash(config), }; case 'skills': { + // The skills hub keeps no skill on an agent that is not attached. + const skills = await this.agentSkillRefs.skillsForRefs(agent, skillRefs, {}); return { - skills: Object.entries(agent.skills ?? {}).map(([id, skill]) => ({ + skills: Object.entries(skills).map(([id, skill]) => ({ id, name: skill.name, description: skill.description, - attached: (config?.skills ?? []).some((ref) => ref.id === id), + attached: true, })), }; } diff --git a/packages/cli/src/modules/agents/instance-ai-builder-delegate.adapter.ts b/packages/cli/src/modules/agents/instance-ai-builder-delegate.adapter.ts index 3e3ee50de37..3c7143d9e94 100644 --- a/packages/cli/src/modules/agents/instance-ai-builder-delegate.adapter.ts +++ b/packages/cli/src/modules/agents/instance-ai-builder-delegate.adapter.ts @@ -145,11 +145,17 @@ export class InstanceAiBuilderDelegateAdapterService { throw new ForbiddenError('You do not have permission to access agents in this project.'); } }; + // Checked on every call, not when the delegate is created: a run that started + // before an admin turned Agents off must lose access at its next step. + const assertAccess = async (...scopes: Scope[]): Promise => { + await this.agentsSettingsService.assertEnabled(); + await assertProjectScope(...scopes); + }; return { createAgent: async (name, options) => { // Adopting also needs `agent:update` — see the port's `adoptOnCollision` docs. - await assertProjectScope( + await assertAccess( ...(options?.adoptOnCollision ? (['agent:create', 'agent:update'] as const) : (['agent:create'] as const)), @@ -163,8 +169,7 @@ export class InstanceAiBuilderDelegateAdapterService { }, streamBuild: async (agentId, message, session) => { - await this.agentsSettingsService.assertEnabled(); - await assertProjectScope('agent:update'); + await assertAccess('agent:update'); const requiredArtifacts: BuilderRequiredArtifact[] = []; return toBuilderTurnStream( this.agentsBuilderService.buildAgent( @@ -185,7 +190,7 @@ export class InstanceAiBuilderDelegateAdapterService { }, resumeBuild: async (agentId, resume, session) => { - await assertProjectScope('agent:update'); + await assertAccess('agent:update'); const requiredArtifacts: BuilderRequiredArtifact[] = []; return toBuilderTurnStream( this.agentsBuilderService.resumeBuild( @@ -208,7 +213,7 @@ export class InstanceAiBuilderDelegateAdapterService { }, findOpenSuspensions: async (agentId, session) => { - await assertProjectScope('agent:update'); + await assertAccess('agent:update'); const checkpoint = await this.agentsBuilderService.findOpenCheckpointForThread( agentId, session.threadId, @@ -225,11 +230,11 @@ export class InstanceAiBuilderDelegateAdapterService { }, resolveAgentName: async (agentId) => { - await assertProjectScope('agent:read'); + await assertAccess('agent:read'); return (await this.agentsService.findById(agentId, projectId))?.name; }, readAgentArtifact: async (agentId) => { - await assertProjectScope('agent:read'); + await assertAccess('agent:read'); // No JSON config yet (freshly created) is an empty snapshot, not an error. // Anything else propagates: the callers already treat a throw as "no // snapshot", and it gets logged there instead of vanishing here. diff --git a/packages/cli/src/modules/agents/integrations/__tests__/agent-chat-bridge.test.ts b/packages/cli/src/modules/agents/integrations/__tests__/agent-chat-bridge.test.ts index ee7735e2560..f902de7a767 100644 --- a/packages/cli/src/modules/agents/integrations/__tests__/agent-chat-bridge.test.ts +++ b/packages/cli/src/modules/agents/integrations/__tests__/agent-chat-bridge.test.ts @@ -19,6 +19,7 @@ import { AgentChatBridge } from '../agent-chat-bridge'; import { AgentChatIntegration, ChatIntegrationRegistry, + InboundAttachmentAccessError, type AgentChatIntegrationContext, } from '../agent-chat-integration'; import type { ComponentMapper } from '../component-mapper'; @@ -2008,6 +2009,53 @@ describe('AgentChatBridge — consumeStream', () => { } }); + it('stores files the integration fetches from the platform API', async () => { + const agentExecutor = makeAgentExecutor([finishChunk]); + const attachmentService = makeAttachmentService(); + const handlers = makeBridge(agentExecutor, attachmentService); + const thread = makeThread(); + const integrationImpl = registry.get('test-streaming')!; + integrationImpl.fetchInboundAttachments = vi + .fn() + .mockResolvedValue([ + { type: 'file', name: 'shared.png', fetchData: vi.fn().mockResolvedValue(pngBytes) }, + ]); + + try { + await handlers.mention!(thread, { + text: 'look at this', + author: { userId: 'u1', userName: 'user1' }, + }); + + expect(attachmentService.storeInbound).toHaveBeenCalledWith( + expect.objectContaining({ fileName: 'shared.png', mimeType: 'image/png' }), + ); + } finally { + delete integrationImpl.fetchInboundAttachments; + } + }); + + it('still runs the turn when the platform file lookup fails', async () => { + const agentExecutor = makeAgentExecutor([finishChunk]); + const attachmentService = makeAttachmentService(); + const handlers = makeBridge(agentExecutor, attachmentService); + const thread = makeThread(); + const integrationImpl = registry.get('test-streaming')!; + integrationImpl.fetchInboundAttachments = vi.fn().mockRejectedValue(new Error('403')); + + try { + await handlers.mention!(thread, { + text: 'look at this', + author: { userId: 'u1', userName: 'user1' }, + }); + + expect(attachmentService.storeInbound).not.toHaveBeenCalled(); + expect(agentExecutor.executeForChatPublished).toHaveBeenCalled(); + } finally { + delete integrationImpl.fetchInboundAttachments; + } + }); + it('truncates a platform file name to the fileName column width', async () => { const agentExecutor = makeAgentExecutor([finishChunk]); const attachmentService = makeAttachmentService(); @@ -2120,6 +2168,96 @@ describe('AgentChatBridge — consumeStream', () => { expect(config.message).toContain('[Attachment "broken.pdf" could not be processed]'); expect(config.message).toContain('[Attachment "huge.pdf" was skipped: larger than 10 MB]'); }); + + it('adds a note for each attachment and does not download when the channel turns downloads off', async () => { + const agentExecutor = makeAgentExecutor([finishChunk]); + const attachmentService = makeAttachmentService(); + const handlers = makeBridge(agentExecutor, attachmentService); + const integrationImpl = registry.get('test-streaming')!; + const shouldDownloadAttachments = vi.fn().mockReturnValue(false); + // The test integration doesn't implement this optional hook; inject one. + integrationImpl.shouldDownloadAttachments = shouldDownloadAttachments; + const photoFetch = vi.fn().mockResolvedValue(pngBytes); + const unnamedFetch = vi.fn().mockResolvedValue(pngBytes); + + try { + await handlers.mention!(makeThread(), { + text: 'look at these', + author: { userId: 'u1', userName: 'user1' }, + attachments: [ + { type: 'image', name: 'photo.png', mimeType: 'image/png', fetchData: photoFetch }, + { type: 'file', mimeType: 'application/pdf', fetchData: unnamedFetch }, + ], + }); + + expect(shouldDownloadAttachments).toHaveBeenCalledWith(streamingIntegration); + expect(photoFetch).not.toHaveBeenCalled(); + expect(unnamedFetch).not.toHaveBeenCalled(); + expect(attachmentService.storeInbound).not.toHaveBeenCalled(); + const config = agentExecutor.captured[0] as { message: string; attachments?: unknown }; + expect(config.attachments).toBeUndefined(); + expect(config.message).toContain('look at these'); + expect(config.message).toContain( + '[Attachment "photo.png" was not downloaded: media downloads are turned off for this channel]', + ); + expect(config.message).toContain( + '[Attachment "file" was not downloaded: media downloads are turned off for this channel]', + ); + } finally { + delete integrationImpl.shouldDownloadAttachments; + } + }); + + it('downloads attachments when the channel hook allows it', async () => { + const agentExecutor = makeAgentExecutor([finishChunk]); + const attachmentService = makeAttachmentService(); + const handlers = makeBridge(agentExecutor, attachmentService); + const integrationImpl = registry.get('test-streaming')!; + integrationImpl.shouldDownloadAttachments = vi.fn().mockReturnValue(true); + + try { + await handlers.mention!(makeThread(), { + text: 'look at this', + author: { userId: 'u1', userName: 'user1' }, + attachments: [ + { + type: 'image', + name: 'photo.png', + mimeType: 'image/png', + fetchData: vi.fn().mockResolvedValue(pngBytes), + }, + ], + }); + + expect(attachmentService.storeInbound).toHaveBeenCalledTimes(1); + } finally { + delete integrationImpl.shouldDownloadAttachments; + } + }); + + it('passes on why the platform refused a download', async () => { + const agentExecutor = makeAgentExecutor([finishChunk]); + const handlers = makeBridge(agentExecutor, makeAttachmentService()); + + await handlers.mention!(makeThread(), { + text: 'hi', + author: { userId: 'u1', userName: 'user1' }, + attachments: [ + { + type: 'file', + name: 'plan.pdf', + fetchData: vi + .fn() + .mockRejectedValue(new InboundAttachmentAccessError('ask an administrator')), + }, + ], + }); + + const config = agentExecutor.captured[0] as { message: string }; + expect(config.message).toContain( + '[Attachment "plan.pdf" could not be read: ask an administrator]', + ); + }); }); describe('when integration keeps streaming enabled', () => { diff --git a/packages/cli/src/modules/agents/integrations/__tests__/agent-credential-lookup.service.test.ts b/packages/cli/src/modules/agents/integrations/__tests__/agent-credential-lookup.service.test.ts index 0eedafa550f..ff4a7f4f9e3 100644 --- a/packages/cli/src/modules/agents/integrations/__tests__/agent-credential-lookup.service.test.ts +++ b/packages/cli/src/modules/agents/integrations/__tests__/agent-credential-lookup.service.test.ts @@ -1,6 +1,6 @@ import { mock } from 'vitest-mock-extended'; -import type { CredentialsEntity } from '@n8n/db'; +import type { CredentialsEntity, User } from '@n8n/db'; import type { CredentialsService } from '@/credentials/credentials.service'; @@ -74,4 +74,35 @@ describe('AgentCredentialLookupService', () => { expect(await service.decryptForProject(PROJECT_ID, CREDENTIAL_ID, TYPE)).toBeNull(); expect(credentialsService.decrypt).not.toHaveBeenCalled(); }); + + describe('decryptForUser', () => { + const user = mock(); + + beforeEach(() => { + credentialsService.findAllCredentialIdsForProject.mockResolvedValue([ + mock({ id: CREDENTIAL_ID, type: TYPE }), + ]); + }); + + it('asks for the credentials the user can use without the personal route', async () => { + credentialsService.getCredentialsAUserCanUseInAWorkflow.mockResolvedValue([ + { id: CREDENTIAL_ID }, + ] as never); + + expect(await service.decryptForUser(user, PROJECT_ID, CREDENTIAL_ID, TYPE)).toEqual({ + clientId: 'a-client', + }); + expect(credentialsService.getCredentialsAUserCanUseInAWorkflow).toHaveBeenCalledWith(user, { + projectId: PROJECT_ID, + excludePersonalRoute: true, + }); + }); + + it('refuses a credential that is not in the usable list', async () => { + credentialsService.getCredentialsAUserCanUseInAWorkflow.mockResolvedValue([] as never); + + expect(await service.decryptForUser(user, PROJECT_ID, CREDENTIAL_ID, TYPE)).toBeNull(); + expect(credentialsService.decrypt).not.toHaveBeenCalled(); + }); + }); }); diff --git a/packages/cli/src/modules/agents/integrations/__tests__/helpers/whatsapp/replay-test-context.ts b/packages/cli/src/modules/agents/integrations/__tests__/helpers/whatsapp/replay-test-context.ts index 7301014ccab..4d1304e88dc 100644 --- a/packages/cli/src/modules/agents/integrations/__tests__/helpers/whatsapp/replay-test-context.ts +++ b/packages/cli/src/modules/agents/integrations/__tests__/helpers/whatsapp/replay-test-context.ts @@ -18,7 +18,8 @@ import type { IntegrationMessageContext, } from '../../../integration-tools'; import type { AgentRepository } from '../../../../repositories/agent.repository'; -import { WhatsAppIntegration } from '../../../platforms/whatsapp-integration'; +import { WhatsAppIntegration } from '../../../platforms/whatsapp/whatsapp-integration'; +import type { WhatsAppWebhookVerificationStore } from '../../../platforms/whatsapp/whatsapp-webhook-verification.store'; import { createMockAttachmentService, createReplayContextSetup, @@ -138,6 +139,7 @@ export function whatsAppThreadId( export function createWhatsAppIntegration( channelRateLimitGuard = new ChannelRateLimitGuard(), + webhookVerification: WhatsAppWebhookVerificationStore = mock(), ): WhatsAppIntegration { return new WhatsAppIntegration( mock(), @@ -147,6 +149,7 @@ export function createWhatsAppIntegration( hmacSignatureSecret: 'test-hmac-signature-secret', }), channelRateLimitGuard, + webhookVerification, ); } @@ -285,6 +288,7 @@ export async function createWhatsAppReplayContext( integration?: AgentIntegrationConfig; failedApiTypes?: string[]; failureSequence?: WhatsAppFailureSequence; + webhookVerification?: WhatsAppWebhookVerificationStore; } = {}, ): Promise { const stub = installWhatsAppApiStub(options.failedApiTypes, options.failureSequence); @@ -294,7 +298,10 @@ export async function createWhatsAppReplayContext( // agree on one connection's cooldown state, mirroring how DI hands both the // same singleton in production. const channelRateLimitGuard = new ChannelRateLimitGuard(); - const integrationImpl = createWhatsAppIntegration(channelRateLimitGuard); + const integrationImpl = createWhatsAppIntegration( + channelRateLimitGuard, + options.webhookVerification, + ); const integration: AgentIntegrationConfig = options.integration ?? { type: 'whatsapp', credentialId: 'cred-whatsapp', diff --git a/packages/cli/src/modules/agents/integrations/__tests__/slack-app-setup.service.test.ts b/packages/cli/src/modules/agents/integrations/__tests__/slack-app-setup.service.test.ts index 8d1bda575f1..13ae59fb30a 100644 --- a/packages/cli/src/modules/agents/integrations/__tests__/slack-app-setup.service.test.ts +++ b/packages/cli/src/modules/agents/integrations/__tests__/slack-app-setup.service.test.ts @@ -753,6 +753,10 @@ describe('Slack setup services', () => { }, ], }); + expect(credentialsService.getCredentialsAUserCanUseInAWorkflow).toHaveBeenCalledWith(user, { + projectId: 'project-1', + excludePersonalRoute: true, + }); }); it('refreshes the manager token during icon setup and auto-installs the bot credential', async () => { @@ -1222,6 +1226,10 @@ describe('Slack setup services', () => { expect(fetchParams(requestMock, 0).get('app_id')).toBe('A123'); expect(fetchParams(requestMock, 0).get('token')).toBe('xoxp-manager'); expect(credentialsFinderService.findCredentialForUser).toHaveBeenCalledTimes(2); + expect(credentialsService.getCredentialsAUserCanUseInAWorkflow).toHaveBeenCalledWith(user, { + projectId: 'project-1', + excludePersonalRoute: true, + }); }); it('updates the live manifest', async () => { diff --git a/packages/cli/src/modules/agents/integrations/__tests__/teams-integration.test.ts b/packages/cli/src/modules/agents/integrations/__tests__/teams-integration.test.ts index d748f423dfb..8958dd0c1fe 100644 --- a/packages/cli/src/modules/agents/integrations/__tests__/teams-integration.test.ts +++ b/packages/cli/src/modules/agents/integrations/__tests__/teams-integration.test.ts @@ -1,4 +1,6 @@ import type { Logger } from '@n8n/backend-common'; +import type { User } from '@n8n/db'; +import { Container } from '@n8n/di'; import { UserError } from 'n8n-workflow'; import { mock } from 'vitest-mock-extended'; @@ -15,6 +17,7 @@ import { TEAMS_CLIENT_SECRET as CLIENT_SECRET, TEAMS_TENANT_ID as TENANT_ID, } from './helpers/teams/synthetic-fixtures'; +import { TeamsCleanupService } from '../platforms/teams/teams-cleanup.service'; import { TeamsIntegration } from '../platforms/teams/teams-integration'; const createTeamsAdapter = vi.fn(() => ({ name: 'teams' })); @@ -364,4 +367,38 @@ describe('TeamsIntegration', () => { ).toBe(expected); }); }); + + /** + * The hook is the only wiring between integration removal and the cleanup + * service, and the lifecycle tests mock `onRemove` away. + */ + describe('onRemove', () => { + it('asks the cleanup service about this project and credential', async () => { + const user = mock({ id: 'user-1' }); + const warning = { + integrationType: 'teams' as const, + code: 'resources_not_deleted' as const, + action: { type: 'open_url' as const, url: 'https://entra.microsoft.com' }, + details: { appId: 'app-1' }, + }; + const cleanupService = mock(); + cleanupService.describeLeftovers.mockResolvedValue(warning); + Container.set(TeamsCleanupService, cleanupService); + + await expect( + integration.onRemove({ + user, + agentId: AGENT_ID, + projectId: 'project-1', + credentialId: CREDENTIAL_ID, + }), + ).resolves.toEqual(warning); + + expect(cleanupService.describeLeftovers).toHaveBeenCalledWith({ + user, + projectId: 'project-1', + credentialId: CREDENTIAL_ID, + }); + }); + }); }); diff --git a/packages/cli/src/modules/agents/integrations/agent-chat-bridge.ts b/packages/cli/src/modules/agents/integrations/agent-chat-bridge.ts index 24c83c92a27..2c09b0cd603 100644 --- a/packages/cli/src/modules/agents/integrations/agent-chat-bridge.ts +++ b/packages/cli/src/modules/agents/integrations/agent-chat-bridge.ts @@ -47,6 +47,7 @@ import type { } from './agent-chat-integration'; import { ChatIntegrationRegistry, + InboundAttachmentAccessError, onceStatusHandle, postToUserOrThread, } from './agent-chat-integration'; @@ -291,6 +292,7 @@ export class AgentChatBridge { thread, logger: this.logger, agentId: this.agentId, + integration: this.integration, }; const resumeExecutionContext = await this.integrationImpl?.createResumeExecutionContext?.(params); @@ -780,7 +782,7 @@ export class AgentChatBridge { message: Message, options: InboundOptions, ): Promise { - const inbound = await this.readInboundMessage(message); + const inbound = await this.readInboundMessage(thread, message); if (!inbound) return; if (isResetCommand(inbound)) { if (options.allowReset !== false) await this.resetSession(thread); @@ -789,18 +791,42 @@ export class AgentChatBridge { await this.runTurn(thread, message, inbound, options); } - private async readInboundMessage(message: Message): Promise { + private async readInboundMessage( + thread: Thread, + message: Message, + ): Promise { const platformAgentContext = this.getPlatformAgentContext(); const text = this.prepareInboundText( await this.getInboundText(message), platformAgentContext, ).trim(); // `?? []` guards rehydrated/serialized messages that predate the field. - const attachments = message.attachments ?? []; + const attachments = [ + ...(message.attachments ?? []), + ...(await this.fetchInboundAttachments(thread, message)), + ]; if (!text && attachments.length === 0) return null; return { text, attachments }; } + /** + * A failed lookup drops only the extra files: a message with text is still answered. + * It is only logged: the activity does not say whether the message has files + * (a Teams channel message carries no sign of them), so a note to the agent + * would appear on every message, not only on one whose files were lost. + */ + private async fetchInboundAttachments(thread: Thread, message: Message): Promise { + try { + return (await this.integrationImpl?.fetchInboundAttachments?.({ thread, message })) ?? []; + } catch (error) { + this.logger.warn('[AgentChatBridge] Failed to look up message attachments', { + agentId: this.agentId, + error: error instanceof Error ? error.message : String(error), + }); + return []; + } + } + private async runTurn( thread: Thread, message: Message, @@ -959,6 +985,7 @@ export class AgentChatBridge { logger: this.logger, agentId: this.agentId, slackThreadContext: payload.slackThreadContext, + integration, }); statusHandle = onceStatusHandle(context?.statusHandle); } @@ -1049,6 +1076,16 @@ export class AgentChatBridge { return { attachments, attachmentNotes }; } + if (this.integrationImpl?.shouldDownloadAttachments?.(this.integration) === false) { + // The agent still learns that a file arrived, so it can ask for text instead. + for (const attachment of inboundAttachments) { + attachmentNotes.push( + `[Attachment "${attachment.name ?? 'file'}" was not downloaded: media downloads are turned off for this channel]`, + ); + } + return { attachments, attachmentNotes }; + } + const skipped = inboundAttachments.slice(MAX_AGENT_CHAT_ATTACHMENTS_PER_MESSAGE); for (const attachment of skipped) { attachmentNotes.push( @@ -1109,7 +1146,11 @@ export class AgentChatBridge { threadId, error: error instanceof Error ? error.message : String(error), }); - attachmentNotes.push(`[Attachment "${name}" could not be processed]`); + attachmentNotes.push( + error instanceof InboundAttachmentAccessError + ? `[Attachment "${name}" could not be read: ${error.message}]` + : `[Attachment "${name}" could not be processed]`, + ); } } diff --git a/packages/cli/src/modules/agents/integrations/agent-chat-integration.ts b/packages/cli/src/modules/agents/integrations/agent-chat-integration.ts index 7954241285b..592b8d7d1d9 100644 --- a/packages/cli/src/modules/agents/integrations/agent-chat-integration.ts +++ b/packages/cli/src/modules/agents/integrations/agent-chat-integration.ts @@ -5,8 +5,8 @@ import { } from '@n8n/api-types'; import type { User } from '@n8n/db'; import { Service } from '@n8n/di'; -import type { Thread, Author, Message } from 'chat'; -import type { Logger } from 'n8n-workflow'; +import type { Attachment, Thread, Author, Message } from 'chat'; +import { UserError, type Logger } from 'n8n-workflow'; import type { ChatInstance } from './chat-integration.service'; import type { NormalizeComponentsContext, SuspendComponent } from './component-mapper'; @@ -27,6 +27,12 @@ import type { ReplyExpectation, } from './integration-tools'; +/** + * The platform refused an attachment download for a reason the user can fix. + * The message reaches the agent, so it can tell the user what to do. + */ +export class InboundAttachmentAccessError extends UserError {} + /** * Channel identity, without the decrypted credential. Enough for checks that * only read our own state — see {@link AgentChatIntegration.assertStartupPreconditions}. @@ -534,6 +540,15 @@ export abstract class AgentChatIntegration { /** Optional text normalization before the message is handed to the agent. */ prepareInboundText?(text: string, context: PlatformAgentContext): string; + /** + * Files the webhook leaves out but the platform API has. They join the + * message's own attachments. + */ + fetchInboundAttachments?(params: { + thread: Thread; + message: Message; + }): Promise; + /** * Optional per-message reply policy (see `ReplyExpectation`). * Default (no implementation): 'required'. @@ -592,8 +607,16 @@ export abstract class AgentChatIntegration { logger: Logger; agentId: string; slackThreadContext?: BridgeExecutionContext['slackThreadContext']; + /** The channel as stored, for platforms whose status depends on a setting. */ + integration?: AgentIntegrationConfig; }): Promise; + /** + * Whether the bridge downloads and stores the files in an inbound message. + * Without it, every platform downloads them. + */ + shouldDownloadAttachments?(integration: AgentIntegrationConfig): boolean; + /** * Execute a context query that this platform owns (e.g. Linear `get_issue`, * Slack `search_users`). The central executor handles only the cross-platform diff --git a/packages/cli/src/modules/agents/integrations/agent-credential-lookup.service.ts b/packages/cli/src/modules/agents/integrations/agent-credential-lookup.service.ts index 40229cc2886..c7c1652d408 100644 --- a/packages/cli/src/modules/agents/integrations/agent-credential-lookup.service.ts +++ b/packages/cli/src/modules/agents/integrations/agent-credential-lookup.service.ts @@ -29,6 +29,7 @@ export class AgentCredentialLookupService { async decryptForUser(user: User, projectId: string, credentialId: string, expectedType: string) { const usable = await this.credentialsService.getCredentialsAUserCanUseInAWorkflow(user, { projectId, + excludePersonalRoute: true, }); if (!usable.some((item) => item.id === credentialId)) return null; return await this.decryptForProject(projectId, credentialId, expectedType); diff --git a/packages/cli/src/modules/agents/integrations/platforms/__tests__/whatsapp/synthetic-integration.test.ts b/packages/cli/src/modules/agents/integrations/platforms/__tests__/whatsapp/synthetic-integration.test.ts index 7da3138bf28..52caf57295f 100644 --- a/packages/cli/src/modules/agents/integrations/platforms/__tests__/whatsapp/synthetic-integration.test.ts +++ b/packages/cli/src/modules/agents/integrations/platforms/__tests__/whatsapp/synthetic-integration.test.ts @@ -1,4 +1,8 @@ -import { OperationalError, UserError } from 'n8n-workflow'; +import type { User } from '@n8n/db'; +import type { AgentIntegrationConfig } from '@n8n/api-types'; +import type { Thread } from 'chat'; +import { OperationalError, UserError, type Logger } from 'n8n-workflow'; +import { mock } from 'vitest-mock-extended'; import { deriveWhatsAppVerifyToken } from '../../../integration-helpers'; import { encodeIntegrationMessageContext } from '../../../integration-message-context'; @@ -24,6 +28,7 @@ import { whatsAppReplayFixtures, whatsAppWebhook, } from '../../../__tests__/helpers/whatsapp/synthetic-fixtures'; +import type { WhatsAppWebhookVerificationStore } from '../../whatsapp/whatsapp-webhook-verification.store'; // The chat SDK + adapters are ESM-only. Production loads them via esm-loader's // `new Function()` hack to dodge the CJS transform, which can't run under vitest; @@ -352,6 +357,11 @@ describe('WhatsApp Cloud API integration scenarios', () => { }); describe('24-hour customer service window', () => { + // The typing indicator goes out as a read receipt, which Meta allows + // outside the window, so only count the calls that send a message. + const sentMessages = (ctx: { apiCalls: Array<{ body: Record }> }) => + ctx.apiCalls.filter((call) => call.body.status !== 'read'); + it('sends a reply while the customer service window is open', async () => { const fixtures = whatsAppReplayFixtures(); const ctx = await createWhatsAppReplayContext(fixtures); @@ -388,14 +398,14 @@ describe('WhatsApp Cloud API integration scenarios', () => { ); // The bridge's own auto-reply to the message above is already // blocked by the guard (its "last inbound" is the message it is - // replying to), so no send has succeeded yet. - expect(ctx.apiCalls).toHaveLength(0); + // replying to), so no message has been sent yet. + expect(sentMessages(ctx)).toHaveLength(0); const threadId = whatsAppThreadId(fixtures); await expect( ctx.adapter.postMessage(threadId, { markdown: 'Still there?' }), ).rejects.toThrow(UserError); - expect(ctx.apiCalls).toHaveLength(0); + expect(sentMessages(ctx)).toHaveLength(0); } finally { await ctx.shutdown(); } @@ -422,7 +432,7 @@ describe('WhatsApp Cloud API integration scenarios', () => { yield 'Still there?'; })(); await expect(ctx.adapter.stream(threadId, textStream)).rejects.toThrow(UserError); - expect(ctx.apiCalls).toHaveLength(0); + expect(sentMessages(ctx)).toHaveLength(0); } finally { await ctx.shutdown(); } @@ -1059,6 +1069,64 @@ describe('WhatsApp Cloud API integration scenarios', () => { }); }); + describe('onRemove', () => { + it('clears the recorded handshake for the agent', async () => { + const webhookVerification = mock(); + const integration = createWhatsAppIntegration(undefined, webhookVerification); + + const warning = await integration.onRemove({ + agentId: 'agent-1', + projectId: 'project-1', + credentialId: 'cred-whatsapp', + user: mock(), + }); + + expect(warning).toBeUndefined(); + expect(webhookVerification.clear).toHaveBeenCalledExactlyOnceWith('agent-1'); + }); + }); + + describe('handshake answered by a connected channel', () => { + const expectedToken = deriveWhatsAppVerifyToken('test-hmac-signature-secret', 'agent-1'); + const handshake = (token: string) => + new Request( + `https://n8n.example.com/webhooks/whatsapp?hub.mode=subscribe&hub.verify_token=${token}&hub.challenge=12345`, + ); + + it('records the handshake when the token matches', async () => { + const webhookVerification = mock(); + const ctx = await createWhatsAppReplayContext(whatsAppReplayFixtures(), { + webhookVerification, + }); + + try { + const response = await ctx.adapter.handleWebhook(handshake(expectedToken)); + + expect(response.status).toBe(200); + expect(await response.text()).toBe('12345'); + expect(webhookVerification.markVerified).toHaveBeenCalledExactlyOnceWith('agent-1'); + } finally { + await ctx.shutdown(); + } + }); + + it('does not record a rejected handshake', async () => { + const webhookVerification = mock(); + const ctx = await createWhatsAppReplayContext(whatsAppReplayFixtures(), { + webhookVerification, + }); + + try { + const response = await ctx.adapter.handleWebhook(handshake('wrong-token')); + + expect(response.status).toBe(403); + expect(webhookVerification.markVerified).not.toHaveBeenCalled(); + } finally { + await ctx.shutdown(); + } + }); + }); + describe('handleUnauthenticatedWebhook', () => { // createWhatsAppIntegration() wires a fixed 'test-hmac-signature-secret', so // the expected token for 'agent-1' is derivable the same way the real @@ -1066,7 +1134,8 @@ describe('WhatsApp Cloud API integration scenarios', () => { const expectedToken = deriveWhatsAppVerifyToken('test-hmac-signature-secret', 'agent-1'); it("answers Meta's handshake with the raw challenge when the token matches", () => { - const integration = createWhatsAppIntegration(); + const webhookVerification = mock(); + const integration = createWhatsAppIntegration(undefined, webhookVerification); const result = integration.handleUnauthenticatedWebhook({ agentId: 'agent-1', @@ -1081,10 +1150,12 @@ describe('WhatsApp Cloud API integration scenarios', () => { }); expect(result).toEqual({ status: 200, body: '12345', raw: true }); + expect(webhookVerification.markVerified).toHaveBeenCalledExactlyOnceWith('agent-1'); }); it('rejects the handshake when the verify token does not match', () => { - const integration = createWhatsAppIntegration(); + const webhookVerification = mock(); + const integration = createWhatsAppIntegration(undefined, webhookVerification); const result = integration.handleUnauthenticatedWebhook({ agentId: 'agent-1', @@ -1099,6 +1170,7 @@ describe('WhatsApp Cloud API integration scenarios', () => { }); expect(result).toEqual({ status: 403, body: 'Forbidden', raw: true }); + expect(webhookVerification.markVerified).not.toHaveBeenCalled(); }); it('falls through for a non-GET request', () => { @@ -1140,4 +1212,50 @@ describe('WhatsApp Cloud API integration scenarios', () => { expect(result).toBeUndefined(); }); }); + + describe('channel settings', () => { + const whatsAppChannel = (settings?: Record) => + ({ type: 'whatsapp', credentialId: 'cred-1', settings }) as AgentIntegrationConfig; + + const resumeParams = (integration?: AgentIntegrationConfig) => { + const thread = mock>({ id: 'whatsapp:phone-1:user-1' }); + thread.startTyping.mockResolvedValue(undefined); + return { thread, logger: mock(), agentId: 'agent-1', integration }; + }; + + it.each([ + ['no channel is given', undefined], + ['the setting is unset', whatsAppChannel()], + ['the setting is on', whatsAppChannel({ typingIndicator: true })], + ])('shows the typing indicator when %s', async (_label, channel) => { + const integration = createWhatsAppIntegration(); + const params = resumeParams(channel); + + const context = await integration.createResumeExecutionContext(params); + + expect(context.statusHandle).toBeDefined(); + expect(params.thread.startTyping).toHaveBeenCalledTimes(1); + await context.statusHandle?.clearBeforeResponse(); + }); + + it('does not show the typing indicator when the setting is off', async () => { + const integration = createWhatsAppIntegration(); + const params = resumeParams(whatsAppChannel({ typingIndicator: false })); + + const context = await integration.createResumeExecutionContext(params); + + expect(context).toEqual({}); + expect(params.thread.startTyping).not.toHaveBeenCalled(); + }); + + it.each([ + ['the setting is unset', whatsAppChannel(), true], + ['the setting is on', whatsAppChannel({ downloadMedia: true }), true], + ['the setting is off', whatsAppChannel({ downloadMedia: false }), false], + ])('downloads attachments only when allowed (%s)', (_label, channel, expected) => { + const integration = createWhatsAppIntegration(); + + expect(integration.shouldDownloadAttachments(channel)).toBe(expected); + }); + }); }); diff --git a/packages/cli/src/modules/agents/integrations/platforms/__tests__/whatsapp/whatsapp-credential-check.service.test.ts b/packages/cli/src/modules/agents/integrations/platforms/__tests__/whatsapp/whatsapp-credential-check.service.test.ts new file mode 100644 index 00000000000..b8952c57387 --- /dev/null +++ b/packages/cli/src/modules/agents/integrations/platforms/__tests__/whatsapp/whatsapp-credential-check.service.test.ts @@ -0,0 +1,314 @@ +import type { Logger } from '@n8n/backend-common'; +import type { OutboundHttp } from '@n8n/backend-network'; +import type { AgentsConfig } from '@n8n/config'; +import type { User } from '@n8n/db'; +import { NotFoundError } from '@n8n/errors'; +import { createHmac } from 'node:crypto'; +import { mock } from 'vitest-mock-extended'; + +import type { AgentCredentialLookupService } from '../../../agent-credential-lookup.service'; +import { WhatsAppCredentialCheckService } from '../../whatsapp/whatsapp-credential-check.service'; + +const PROJECT_ID = 'project-1'; +const CREDENTIAL_ID = 'cred-1'; +const PHONE_NUMBER_ID = '1234567890'; +const BUSINESS_ACCOUNT_ID = '9876543210'; +const ACCESS_TOKEN = 'an-access-token'; +const APP_SECRET = 'an-app-secret'; +const HOUR_MS = 60 * 60 * 1000; + +const user = mock({ id: 'user-1' }); + +const workingCredential = { + accessToken: ACCESS_TOKEN, + phoneNumberId: PHONE_NUMBER_ID, + businessAccountId: BUSINESS_ACCOUNT_ID, + appSecret: APP_SECRET, +}; + +interface RequestOptions { + url: string; + qs: Record; + headers: Record; +} + +interface GraphReply { + statusCode: number; + body: unknown; +} + +type Route = 'phone' | 'debugToken' | 'phoneNumbers' | 'profile'; + +const ok = (body: unknown): GraphReply => ({ statusCode: 200, body }); + +function routeOf(url: string): Route { + if (url.endsWith('/debug_token')) return 'debugToken'; + if (url.endsWith('/phone_numbers')) return 'phoneNumbers'; + if (url.endsWith('/whatsapp_business_profile')) return 'profile'; + return 'phone'; +} + +describe('WhatsAppCredentialCheckService', () => { + let credentialLookup: ReturnType>; + let request: ReturnType; + let service: WhatsAppCredentialCheckService; + let replies: Record Promise>; + let logger: ReturnType>; + let agentsConfig: AgentsConfig; + + beforeEach(() => { + credentialLookup = mock(); + credentialLookup.decryptForUser.mockResolvedValue(workingCredential); + + replies = { + phone: async () => + ok({ display_phone_number: '+1 555-010-0199', verified_name: 'Acme Corp' }), + debugToken: async () => ok({ data: { expires_at: 0 } }), + phoneNumbers: async () => ok({ data: [{ id: 'other-number' }, { id: PHONE_NUMBER_ID }] }), + profile: async () => + ok({ + data: [ + { + about: 'Short status', + description: 'Longer description', + profile_picture_url: 'https://cdn.example.com/picture.jpg', + }, + ], + }), + }; + request = vi.fn(async (options: RequestOptions) => await replies[routeOf(options.url)]()); + + const outboundHttp = mock(); + outboundHttp.requests.mockReturnValue(mock({ request }) as never); + logger = mock(); + agentsConfig = mock({ whatsAppAllowTemporaryToken: false }); + service = new WhatsAppCredentialCheckService( + credentialLookup, + outboundHttp, + logger, + agentsConfig, + ); + }); + + const check = async () => await service.check(user, PROJECT_ID, CREDENTIAL_ID); + + const callsTo = (route: Route) => + request.mock.calls + .map(([options]) => options as RequestOptions) + .filter((options) => routeOf(options.url) === route); + + it('looks up the credential for the caller with the WhatsApp credential type', async () => { + await check(); + + expect(credentialLookup.decryptForUser).toHaveBeenCalledWith( + user, + PROJECT_ID, + CREDENTIAL_ID, + 'whatsAppBotApi', + ); + }); + + it('throws NotFoundError when the caller cannot use the credential', async () => { + credentialLookup.decryptForUser.mockResolvedValue(null); + + await expect(check()).rejects.toThrow(NotFoundError); + expect(request).not.toHaveBeenCalled(); + }); + + it.each([ + ['access token', 'accessToken'], + ['phone number ID', 'phoneNumberId'], + ['business account ID', 'businessAccountId'], + ['app secret', 'appSecret'], + ])('reports an incomplete credential with no %s without asking Meta', async (_label, field) => { + credentialLookup.decryptForUser.mockResolvedValue({ ...workingCredential, [field]: ' ' }); + + expect(await check()).toEqual({ status: 'failed', reason: 'incomplete' }); + expect(request).not.toHaveBeenCalled(); + }); + + it('sends an appsecret_proof that is the HMAC-SHA256 of the token with the app secret', async () => { + await check(); + + const expectedProof = createHmac('sha256', APP_SECRET).update(ACCESS_TOKEN).digest('hex'); + for (const route of ['phone', 'debugToken', 'phoneNumbers', 'profile'] as const) { + const [options] = callsTo(route); + expect(options.qs.appsecret_proof).toBe(expectedProof); + expect(options.headers.Authorization).toBe(`Bearer ${ACCESS_TOKEN}`); + } + }); + + it('trims credential fields before it uses them', async () => { + credentialLookup.decryptForUser.mockResolvedValue({ + accessToken: ` ${ACCESS_TOKEN} `, + phoneNumberId: ` ${PHONE_NUMBER_ID} `, + businessAccountId: ` ${BUSINESS_ACCOUNT_ID} `, + appSecret: ` ${APP_SECRET} `, + }); + + expect(await check()).toMatchObject({ status: 'ok' }); + const [phone] = callsTo('phone'); + expect(phone.url).toMatch(new RegExp(`/${PHONE_NUMBER_ID}$`)); + expect(phone.qs.appsecret_proof).toBe( + createHmac('sha256', APP_SECRET).update(ACCESS_TOKEN).digest('hex'), + ); + }); + + it('reports a mismatch when Meta refuses the phone number request', async () => { + replies.phone = async () => ({ statusCode: 400, body: { error: { code: 100 } } }); + + expect(await check()).toEqual({ status: 'failed', reason: 'mismatch' }); + expect(callsTo('phoneNumbers')).toHaveLength(0); + }); + + it('reports Meta as unreachable when the phone number request returns a server error', async () => { + replies.phone = async () => ({ statusCode: 503, body: {} }); + + expect(await check()).toEqual({ status: 'failed', reason: 'unreachable' }); + }); + + it('reports Meta as unreachable when the request throws', async () => { + replies.phone = async () => { + throw new Error('ENOTFOUND'); + }; + + expect(await check()).toEqual({ status: 'failed', reason: 'unreachable' }); + }); + + it('logs only a sanitized message when the request throws', async () => { + const proof = createHmac('sha256', APP_SECRET).update(ACCESS_TOKEN).digest('hex'); + replies.phone = async () => { + throw Object.assign( + new Error( + `connect ETIMEDOUT https://graph.facebook.com/v25.0/${PHONE_NUMBER_ID}?appsecret_proof=${proof}`, + ), + { config: { headers: { Authorization: `Bearer ${ACCESS_TOKEN}` } } }, + ); + }; + + await check(); + + const logged = JSON.stringify(logger.debug.mock.calls); + expect(logged).toContain('connect ETIMEDOUT'); + expect(logged).not.toContain(ACCESS_TOKEN); + expect(logged).not.toContain(proof); + }); + + it('reports a temporary token when the token expires within 48 hours', async () => { + const expiresAt = Math.floor((Date.now() + 24 * HOUR_MS) / 1000); + replies.debugToken = async () => ok({ data: { expires_at: expiresAt } }); + + expect(await check()).toEqual({ status: 'failed', reason: 'temporaryToken' }); + }); + + it('passes a token that expires within 48 hours when temporary tokens are allowed', async () => { + agentsConfig.whatsAppAllowTemporaryToken = true; + const expiresAt = Math.floor((Date.now() + 24 * HOUR_MS) / 1000); + replies.debugToken = async () => ok({ data: { expires_at: expiresAt } }); + + expect(await check()).toMatchObject({ status: 'ok' }); + }); + + it('passes a token that expires after 48 hours', async () => { + const expiresAt = Math.floor((Date.now() + 60 * 24 * HOUR_MS) / 1000); + replies.debugToken = async () => ok({ data: { expires_at: expiresAt } }); + + expect(await check()).toMatchObject({ status: 'ok' }); + }); + + it('passes a token that Meta reports never expires', async () => { + replies.debugToken = async () => ok({ data: { expires_at: 0 } }); + + expect(await check()).toMatchObject({ status: 'ok' }); + }); + + it('passes when the token expiry request fails', async () => { + replies.debugToken = async () => { + throw new Error('ECONNRESET'); + }; + + expect(await check()).toMatchObject({ status: 'ok' }); + }); + + it('inspects the token itself in the expiry request', async () => { + await check(); + + const [debugToken] = callsTo('debugToken'); + expect(debugToken.qs.input_token).toBe(ACCESS_TOKEN); + }); + + it('reports a mismatch when the phone number is not in the business account', async () => { + replies.phoneNumbers = async () => ok({ data: [{ id: 'other-number' }] }); + + expect(await check()).toEqual({ status: 'failed', reason: 'mismatch' }); + }); + + it('reports a mismatch when the business account response lists no phone numbers', async () => { + replies.phoneNumbers = async () => ok({}); + + expect(await check()).toEqual({ status: 'failed', reason: 'mismatch' }); + }); + + it('reports a mismatch when Meta refuses the business account request', async () => { + replies.phoneNumbers = async () => ({ statusCode: 403, body: { error: { code: 200 } } }); + + expect(await check()).toEqual({ status: 'failed', reason: 'mismatch' }); + }); + + it('reports Meta as unreachable when the business account request returns a server error', async () => { + replies.phoneNumbers = async () => ({ statusCode: 500, body: {} }); + + expect(await check()).toEqual({ status: 'failed', reason: 'unreachable' }); + }); + + it('returns the business profile when every check passes', async () => { + expect(await check()).toEqual({ + status: 'ok', + profile: { + verifiedName: 'Acme Corp', + displayPhoneNumber: '+1 555-010-0199', + description: 'Longer description', + profilePictureUrl: 'https://cdn.example.com/picture.jpg', + }, + }); + }); + + it('uses the about text when the profile has no description', async () => { + replies.profile = async () => ok({ data: [{ about: 'Short status' }] }); + + expect(await check()).toEqual({ + status: 'ok', + profile: { + verifiedName: 'Acme Corp', + displayPhoneNumber: '+1 555-010-0199', + description: 'Short status', + profilePictureUrl: undefined, + }, + }); + }); + + it.each([ + [ + 'throws', + async () => { + throw new Error('ETIMEDOUT'); + }, + ], + ['is refused', async () => ({ statusCode: 400, body: {} })], + ])( + 'still passes with only the phone details when the profile request %s', + async (_label, reply) => { + replies.profile = reply; + + expect(await check()).toEqual({ + status: 'ok', + profile: { + verifiedName: 'Acme Corp', + displayPhoneNumber: '+1 555-010-0199', + description: undefined, + profilePictureUrl: undefined, + }, + }); + }, + ); +}); diff --git a/packages/cli/src/modules/agents/integrations/platforms/__tests__/whatsapp/whatsapp-webhook-verification.store.test.ts b/packages/cli/src/modules/agents/integrations/platforms/__tests__/whatsapp/whatsapp-webhook-verification.store.test.ts new file mode 100644 index 00000000000..56f51901cd5 --- /dev/null +++ b/packages/cli/src/modules/agents/integrations/platforms/__tests__/whatsapp/whatsapp-webhook-verification.store.test.ts @@ -0,0 +1,91 @@ +import type { Logger } from '@n8n/backend-common'; +import type { CacheService } from '@n8n/backend-services'; +import { mock } from 'vitest-mock-extended'; + +import { WhatsAppWebhookVerificationStore } from '../../whatsapp/whatsapp-webhook-verification.store'; + +const AGENT_ID = 'agent-1'; +const KEY = `agents:whatsapp:webhook-verified:${AGENT_ID}`; +const SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1000; + +describe('WhatsAppWebhookVerificationStore', () => { + let cacheService: ReturnType>; + let logger: ReturnType>; + let store: WhatsAppWebhookVerificationStore; + + beforeEach(() => { + cacheService = mock(); + logger = mock(); + store = new WhatsAppWebhookVerificationStore(cacheService, logger); + }); + + describe('markVerified', () => { + it('records the handshake for seven days', async () => { + await store.markVerified(AGENT_ID); + + expect(cacheService.set).toHaveBeenCalledWith(KEY, true, SEVEN_DAYS_MS); + }); + + it('logs a warning and does not throw when the cache fails', async () => { + cacheService.set.mockRejectedValue(new Error('cache down')); + + await expect(store.markVerified(AGENT_ID)).resolves.toBeUndefined(); + + expect(logger.warn).toHaveBeenCalledWith(expect.any(String), { + agentId: AGENT_ID, + error: 'cache down', + }); + }); + }); + + describe('clear', () => { + it('deletes the handshake record', async () => { + await store.clear(AGENT_ID); + + expect(cacheService.delete).toHaveBeenCalledWith(KEY); + }); + + it('logs a warning and does not throw when the cache fails', async () => { + cacheService.delete.mockRejectedValue('cache down'); + + await expect(store.clear(AGENT_ID)).resolves.toBeUndefined(); + + expect(logger.warn).toHaveBeenCalledWith(expect.any(String), { + agentId: AGENT_ID, + error: 'cache down', + }); + }); + }); + + describe('reset', () => { + it('deletes the handshake record', async () => { + await store.reset(AGENT_ID); + + expect(cacheService.delete).toHaveBeenCalledWith(KEY); + }); + + it('throws when the cache fails', async () => { + cacheService.delete.mockRejectedValue(new Error('cache down')); + + await expect(store.reset(AGENT_ID)).rejects.toThrow('cache down'); + }); + }); + + describe('isVerified', () => { + it('returns true when the cache holds true', async () => { + cacheService.get.mockResolvedValue(true); + + expect(await store.isVerified(AGENT_ID)).toBe(true); + expect(cacheService.get).toHaveBeenCalledWith(KEY); + }); + + it.each([ + ['nothing', undefined], + ['a value that is not true', 'true'], + ])('returns false when the cache holds %s', async (_label, value) => { + cacheService.get.mockResolvedValue(value); + + expect(await store.isVerified(AGENT_ID)).toBe(false); + }); + }); +}); diff --git a/packages/cli/src/modules/agents/integrations/platforms/slack/slack-managed-setup.service.ts b/packages/cli/src/modules/agents/integrations/platforms/slack/slack-managed-setup.service.ts index 315da0ca2a1..7d6520d1ad4 100644 --- a/packages/cli/src/modules/agents/integrations/platforms/slack/slack-managed-setup.service.ts +++ b/packages/cli/src/modules/agents/integrations/platforms/slack/slack-managed-setup.service.ts @@ -185,7 +185,7 @@ export class SlackManagedSetupService { const integrations = agent?.integrations ?? []; const usableCredentials = await this.credentialsService.getCredentialsAUserCanUseInAWorkflow( options.user, - { projectId: options.projectId }, + { projectId: options.projectId, excludePersonalRoute: true }, ); const managerCredentials: SlackManagerCredentialSummary[] = []; @@ -541,7 +541,7 @@ export class SlackManagedSetupService { ): Promise { const usableCredentials = await this.credentialsService.getCredentialsAUserCanUseInAWorkflow( user, - { projectId }, + { projectId, excludePersonalRoute: true }, ); if ( !usableCredentials.some( diff --git a/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-arm-template.service.test.ts b/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-arm-template.service.test.ts index c2743738739..26582dacca9 100644 --- a/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-arm-template.service.test.ts +++ b/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-arm-template.service.test.ts @@ -2,8 +2,7 @@ import { mock } from 'vitest-mock-extended'; import type { GlobalConfig } from '@n8n/config'; import type { InstanceSettings } from 'n8n-core'; -import { JwtService } from '@/services/jwt.service'; -import type { UrlService } from '@n8n/backend-services'; +import { JwtService, type UrlService } from '@n8n/backend-services'; import { TeamsArmTemplateService } from '../teams-arm-template.service'; diff --git a/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-arm.service.test.ts b/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-arm.service.test.ts new file mode 100644 index 00000000000..0a53eb6673f --- /dev/null +++ b/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-arm.service.test.ts @@ -0,0 +1,70 @@ +import type { Logger } from '@n8n/backend-common'; +import type { OutboundHttp } from '@n8n/backend-network'; +import { mock } from 'vitest-mock-extended'; + +import { armNextLinkPath, TeamsArmService } from '../teams-arm.service'; + +describe('TeamsArmService', () => { + let request: ReturnType; + let service: TeamsArmService; + + const sent = () => request.mock.calls[0][0] as Record; + + beforeEach(() => { + request = vi.fn().mockResolvedValue({ statusCode: 200, body: { value: [] } }); + const outboundHttp = mock(); + outboundHttp.requests.mockReturnValue(mock({ request }) as never); + service = new TeamsArmService(outboundHttp, mock()); + }); + + it('signs the call and sends JSON', async () => { + await service.request('a-token', 'PUT', '/subscriptions/sub-1/x', { location: 'global' }); + + expect(sent()).toMatchObject({ + method: 'PUT', + url: 'https://management.azure.com/subscriptions/sub-1/x', + headers: expect.objectContaining({ authorization: 'Bearer a-token' }), + body: '{"location":"global"}', + }); + }); + + it.each([ + [200, true], + [404, false], + [403, false], + ])('reports %i as ok=%s', async (statusCode, ok) => { + request.mockResolvedValue({ statusCode, body: {} }); + + await expect(service.request('a-token', 'GET', '/subscriptions')).resolves.toMatchObject({ + statusCode, + ok, + }); + }); + + /** + * The path is concatenated onto the host, so a value carrying userinfo moves + * the whole request — and with it Azure's bearer token — to another host. + */ + it('refuses to send the token off Azure Resource Manager', async () => { + await expect( + service.request('a-token', 'GET', '@elsewhere.example/subscriptions'), + ).rejects.toThrow(/Refusing/); + expect(request).not.toHaveBeenCalled(); + }); + + describe('armNextLinkPath', () => { + it('reduces an ARM link to the path the client takes', () => { + expect(armNextLinkPath('https://management.azure.com/subscriptions?skipToken=abc')).toBe( + '/subscriptions?skipToken=abc', + ); + }); + + it.each([ + 'https://elsewhere.example/subscriptions', + 'http://management.azure.com/subscriptions', + 'not a url', + ])('drops %s', (link) => { + expect(armNextLinkPath(link)).toBeUndefined(); + }); + }); +}); diff --git a/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-bot-provisioning.service.test.ts b/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-bot-provisioning.service.test.ts new file mode 100644 index 00000000000..a47d6c6d851 --- /dev/null +++ b/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-bot-provisioning.service.test.ts @@ -0,0 +1,580 @@ +import type { Logger } from '@n8n/backend-common'; +import type { CredentialsEntity, User } from '@n8n/db'; +import { mock } from 'vitest-mock-extended'; + +import type { CredentialsFinderService } from '@n8n/backend-services'; +import { BadRequestError } from '@n8n/errors'; + +import type { CredentialsService } from '@/credentials/credentials.service'; + +import type { ArmResponse, TeamsArmService } from '../teams-arm.service'; +import type { TeamsArmTemplateService } from '../teams-arm-template.service'; +import { TeamsBotProvisioningService } from '../teams-bot-provisioning.service'; +import { TeamsCredentialNotesService } from '../teams-credential-notes.service'; +import type { TeamsManagerTokenService } from '../teams-manager-token.service'; + +const user = mock({ id: 'user-1' }); +const SUBSCRIPTION_ID = 'sub-1'; +const BOT_NAME = 'support-bot-abcd1234'; + +const listOptions = { user, managerCredentialId: 'manager-1' }; +const provisionOptions = { + ...listOptions, + projectId: 'project-1', + agentId: 'agent-1', + agentName: 'Support Bot', + credentialId: 'channel-1', + subscriptionId: SUBSCRIPTION_ID, + msaAppId: '1111aaaa-2222-bbbb-4444-555566667777', + msaAppTenantId: '99999999-8888-7777-6666-555555555555', + messagingEndpoint: 'https://n8n.example.com/rest/webhooks/teams', +}; + +const ok = (body: unknown = {}): ArmResponse => ({ statusCode: 200, body, ok: true }); +const failed = (statusCode: number, code?: string): ArmResponse => ({ + statusCode, + body: code ? { error: { code } } : {}, + ok: false, +}); + +describe('TeamsBotProvisioningService', () => { + let arm: ReturnType>; + let tokens: ReturnType>; + let credentialsFinderService: ReturnType>; + let credentialsService: ReturnType>; + let service: TeamsBotProvisioningService; + + /** Paths the bot create and its Teams channel child are PUT to. */ + const botPath = `/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/n8n-agents/providers/Microsoft.BotService/botServices/${BOT_NAME}`; + + const callTo = (fragment: string) => + arm.request.mock.calls.find(([, , path]) => String(path).includes(fragment)); + + /** The bot resource is read before it is written, so the method matters. */ + const putTo = (fragment: string) => + arm.request.mock.calls.find( + ([, method, path]) => method === 'PUT' && String(path).includes(fragment), + ); + + beforeEach(() => { + arm = mock(); + tokens = mock(); + credentialsFinderService = mock(); + credentialsService = mock(); + const armTemplateService = mock(); + armTemplateService.botNameFor.mockReturnValue(BOT_NAME); + + service = new TeamsBotProvisioningService( + arm, + tokens, + armTemplateService, + credentialsFinderService, + new TeamsCredentialNotesService(credentialsFinderService, credentialsService, mock()), + ); + + tokens.acquire.mockResolvedValue('azure-token'); + credentialsFinderService.findCredentialForUser.mockResolvedValue( + mock({ + id: 'manager-1', + type: 'microsoftTeamsManagerOAuth2Api', + }) as never, + ); + arm.request.mockResolvedValue(ok()); + }); + + describe('listSubscriptions', () => { + it('returns the subscriptions the account can use', async () => { + arm.request.mockResolvedValue( + ok({ + value: [ + { subscriptionId: 'sub-1', displayName: 'Production', state: 'Enabled' }, + { subscriptionId: 'sub-2', displayName: 'Sandbox', state: 'Enabled' }, + ], + }), + ); + + await expect(service.listSubscriptions(listOptions)).resolves.toEqual([ + { id: 'sub-1', name: 'Production' }, + { id: 'sub-2', name: 'Sandbox' }, + ]); + }); + + it('leaves out a subscription that is not enabled', async () => { + arm.request.mockResolvedValue( + ok({ + value: [ + { subscriptionId: 'sub-1', displayName: 'Expired', state: 'Disabled' }, + { subscriptionId: 'sub-2', displayName: 'Production', state: 'Enabled' }, + ], + }), + ); + + await expect(service.listSubscriptions(listOptions)).resolves.toEqual([ + { id: 'sub-2', name: 'Production' }, + ]); + }); + + it('reports none for a tenant with no Azure subscription, rather than failing', async () => { + arm.request.mockResolvedValue(ok({ value: [] })); + + await expect(service.listSubscriptions(listOptions)).resolves.toEqual([]); + }); + + /** + * An empty list is how a Microsoft 365 tenant with no Azure at all looks, + * and the step says so and moves on. A refusal is not that, and reporting + * it as one tells the user something untrue about their account. + */ + it('reports a refused listing rather than calling it none', async () => { + arm.request.mockResolvedValue(failed(403, 'AuthorizationFailed')); + + await expect(service.listSubscriptions(listOptions)).rejects.toThrow( + /cannot read the Azure subscriptions/, + ); + }); + + it('follows ARM paging, so a long list is not cut short', async () => { + // The client takes a path and adds the host itself, so the absolute + // `nextLink` only matches if the service reduced it to a path first. + arm.request.mockImplementation(async (_t: string, _m: string, path: string) => + path === '/subscriptions?skipToken=abc' + ? ok({ value: [{ subscriptionId: 'sub-2', displayName: 'Second', state: 'Enabled' }] }) + : ok({ + value: [{ subscriptionId: 'sub-1', displayName: 'First', state: 'Enabled' }], + nextLink: 'https://management.azure.com/subscriptions?skipToken=abc', + }), + ); + + await expect(service.listSubscriptions(listOptions)).resolves.toEqual([ + { id: 'sub-1', name: 'First' }, + { id: 'sub-2', name: 'Second' }, + ]); + }); + + /** + * A page that failed is an unknown list, not a short one. Returning what + * arrived hides the subscription the user came for, or reads as "this + * account has no Azure subscription" and sends them down the manual route. + */ + it('reports a page it could not read, rather than a short list', async () => { + arm.request.mockImplementation(async (_t: string, _m: string, path: string) => + path === '/subscriptions?skipToken=abc' + ? failed(403, 'AuthorizationFailed') + : ok({ + value: [{ subscriptionId: 'sub-1', displayName: 'First', state: 'Enabled' }], + nextLink: 'https://management.azure.com/subscriptions?skipToken=abc', + }), + ); + + await expect(service.listSubscriptions(listOptions)).rejects.toThrow(); + }); + + it('does not follow a nextLink that points off Azure Resource Manager', async () => { + arm.request.mockImplementation(async (_t: string, _m: string, path: string) => + path.startsWith('/subscriptions?api-version') + ? ok({ + value: [{ subscriptionId: 'sub-1', displayName: 'First', state: 'Enabled' }], + nextLink: 'https://example.test/subscriptions?skipToken=abc', + }) + : ok({ value: [{ subscriptionId: 'sub-2', displayName: 'Second', state: 'Enabled' }] }), + ); + + await expect(service.listSubscriptions(listOptions)).resolves.toEqual([ + { id: 'sub-1', name: 'First' }, + ]); + expect(arm.request).toHaveBeenCalledTimes(1); + }); + + it('asks for an Azure token, not a Graph one', async () => { + await service.listSubscriptions(listOptions); + + expect(tokens.acquire).toHaveBeenCalledWith( + expect.anything(), + 'https://management.azure.com', + ); + }); + }); + + describe('provisionBot', () => { + const channelCredential = mock({ + id: 'channel-1', + name: 'Teams', + type: 'microsoftEntraServicePrincipalApi', + }); + + const withChannelCredential = () => + credentialsFinderService.findCredentialForUser.mockImplementation(async (id: string) => + id === 'channel-1' + ? (channelCredential as never) + : (mock({ type: 'microsoftTeamsManagerOAuth2Api' }) as never), + ); + + it('keeps the bot name and subscription on the channel credential', async () => { + withChannelCredential(); + credentialsService.decrypt.mockResolvedValue({ clientId: 'app-1' } as never); + const encrypted = { data: 'encrypted' }; + credentialsService.createEncryptedData.mockResolvedValue(encrypted as never); + const updated = { + clientId: 'app-1', + azureBotName: BOT_NAME, + azureSubscriptionId: SUBSCRIPTION_ID, + }; + + await service.provisionBot(provisionOptions); + + expect(credentialsService.createEncryptedData).toHaveBeenCalledWith( + expect.objectContaining({ id: 'channel-1', data: updated }), + ); + expect(credentialsService.update).toHaveBeenCalledWith( + 'channel-1', + encrypted, + { kind: 'user', user }, + updated, + ); + }); + + it('leaves a credential it could not decrypt untouched', async () => { + withChannelCredential(); + credentialsService.decrypt.mockResolvedValue({} as never); + + await service.provisionBot(provisionOptions); + + expect(credentialsService.update).not.toHaveBeenCalled(); + }); + + it('leaves the credential alone when it already names this bot', async () => { + withChannelCredential(); + credentialsService.decrypt.mockResolvedValue({ + azureBotName: BOT_NAME, + azureSubscriptionId: SUBSCRIPTION_ID, + } as never); + + await service.provisionBot(provisionOptions); + + expect(credentialsService.update).not.toHaveBeenCalled(); + }); + + it('still succeeds when the bot cannot be recorded', async () => { + withChannelCredential(); + credentialsService.decrypt.mockRejectedValue(new Error('boom')); + + await expect(service.provisionBot(provisionOptions)).resolves.toMatchObject({ + botName: BOT_NAME, + }); + }); + + it('creates the bot and turns on its Teams channel', async () => { + const result = await service.provisionBot(provisionOptions); + + expect(putTo(`${botPath}?`)).toBeDefined(); + expect(putTo('/channels/MsTeamsChannel')).toBeDefined(); + expect(result).toEqual({ + botName: BOT_NAME, + resourceGroup: 'n8n-agents', + subscriptionId: SUBSCRIPTION_ID, + }); + }); + + /** + * The bot name comes from the agent, so a re-run lands on the bot made last + * time. Azure fixes a bot's app id at creation, so one left from an earlier + * app registration can never be made to work — and a PUT would not say so. + */ + it('refuses a leftover bot tied to a different app registration', async () => { + arm.request.mockImplementation(async (_t: string, method: string, path: string) => + method === 'GET' && path.includes('botServices') + ? ok({ properties: { msaAppId: 'a-different-app-id' } }) + : ok(), + ); + + await expect(service.provisionBot(provisionOptions)).rejects.toThrow( + /tied to a different app registration/, + ); + }); + + it('reuses the bot it made before, rather than refusing its own work', async () => { + arm.request.mockImplementation(async (_t: string, method: string, path: string) => + method === 'GET' && path.includes('botServices') + ? ok({ properties: { msaAppId: provisionOptions.msaAppId.toUpperCase() } }) + : ok(), + ); + + await expect(service.provisionBot(provisionOptions)).resolves.toMatchObject({ + botName: BOT_NAME, + }); + }); + + /** + * An Azure resource cannot be renamed, and the name is derived from the + * agent's name — so a rename would ask Azure for a second bot on the same + * app registration, which it refuses. The bot is found by the app it signs + * for instead. + */ + it('reuses the bot for this app after the agent was renamed', async () => { + arm.request.mockImplementation(async (_t: string, method: string, path: string) => { + if (method === 'GET' && path.endsWith('botServices?api-version=2022-09-15')) { + return ok({ + value: [ + { name: 'other-bot', properties: { msaAppId: 'someone-elses-app' } }, + { + name: 'the-old-name-abcd1234', + properties: { msaAppId: provisionOptions.msaAppId }, + }, + ], + }); + } + return ok(); + }); + + const result = await service.provisionBot(provisionOptions); + + expect(result.botName).toBe('the-old-name-abcd1234'); + expect(putTo('botServices/the-old-name-abcd1234')).toBeDefined(); + }); + + /** + * A resource group with enough bots pages the list. Missing the bot on a + * later page asks Azure for a second one on the same app registration, + * which it refuses. + */ + it('looks past the first page of bots before deciding to make one', async () => { + arm.request.mockImplementation(async (_t: string, method: string, path: string) => { + if (method === 'GET' && path.endsWith('botServices?api-version=2022-09-15')) { + return ok({ + value: [{ name: 'other-bot', properties: { msaAppId: 'someone-elses-app' } }], + nextLink: 'https://management.azure.com/botServices?skipToken=abc', + }); + } + if (method === 'GET' && path === '/botServices?skipToken=abc') { + return ok({ + value: [ + { + name: 'the-old-name-abcd1234', + properties: { msaAppId: provisionOptions.msaAppId }, + }, + ], + }); + } + return ok(); + }); + + await expect(service.provisionBot(provisionOptions)).resolves.toMatchObject({ + botName: 'the-old-name-abcd1234', + }); + }); + + /** + * Creating a group that is already there asks Azure to move it, and that + * refusal reads as "this account cannot create resources". + */ + it('reports a resource group it could not read, rather than creating over it', async () => { + arm.request.mockImplementation(async (_t: string, method: string, path: string) => + method === 'GET' && path.includes('resourcegroups') + ? failed(403, 'AuthorizationFailed') + : ok(), + ); + + await expect(service.provisionBot(provisionOptions)).rejects.toThrow(/Contributor role/); + expect(putTo('resourcegroups')).toBeUndefined(); + }); + + /** + * A refused later page is an unknown list. Reading it as "no bot" asks + * Azure for a second bot on an app registration that already has one, + * which it refuses -- three steps after the real problem. + */ + it('reports a page of bots it could not read, rather than making a second bot', async () => { + arm.request.mockImplementation(async (_t: string, method: string, path: string) => { + if (method === 'GET' && path.endsWith('botServices?api-version=2022-09-15')) { + return ok({ + value: [], + nextLink: 'https://management.azure.com/botServices?skipToken=abc', + }); + } + if (method === 'GET' && path === '/botServices?skipToken=abc') { + return failed(403, 'AuthorizationFailed'); + } + return ok(); + }); + + await expect(service.provisionBot(provisionOptions)).rejects.toThrow(/Contributor role/); + expect(putTo('botServices/')).toBeUndefined(); + }); + + /** + * Only an absent group means "nothing to reuse". Any other refusal is an + * unknown list, and reading it as "no bot" makes a second bot on an app + * registration that already has one. + */ + it('reports a refused first page of bots, rather than making a second bot', async () => { + arm.request.mockImplementation(async (_t: string, method: string, path: string) => + method === 'GET' && path.endsWith('botServices?api-version=2022-09-15') + ? failed(403, 'AuthorizationFailed') + : ok(), + ); + + await expect(service.provisionBot(provisionOptions)).rejects.toThrow(/Contributor role/); + expect(putTo('botServices/')).toBeUndefined(); + }); + + /** A resource group with no bots yet is the ordinary first run. */ + it('makes a bot when the group has none to reuse', async () => { + arm.request.mockImplementation(async (_t: string, method: string, path: string) => + method === 'GET' && path.endsWith('botServices?api-version=2022-09-15') + ? failed(404) + : ok(), + ); + + await expect(service.provisionBot(provisionOptions)).resolves.toMatchObject({ + botName: BOT_NAME, + }); + }); + + /** A blip reading the group is not a refusal: the create reports its own. */ + it('still tries to create the group when the read did not answer', async () => { + arm.request.mockImplementation(async (_t: string, method: string, path: string) => + method === 'GET' && path.includes('resourcegroups') ? failed(503) : ok(), + ); + + await expect(service.provisionBot(provisionOptions)).resolves.toMatchObject({ + botName: BOT_NAME, + }); + expect(putTo('resourcegroups')).toBeDefined(); + }); + + it('names a new bot after the agent, so the portal shows something readable', async () => { + arm.request.mockImplementation(async (_t: string, method: string, path: string) => + method === 'GET' && path.endsWith('botServices?api-version=2022-09-15') + ? ok({ value: [] }) + : ok(), + ); + + await expect(service.provisionBot(provisionOptions)).resolves.toMatchObject({ + botName: BOT_NAME, + }); + }); + + it('always creates a single-tenant bot', async () => { + await service.provisionBot(provisionOptions); + + const body = putTo(`${botPath}?`)?.[3] as { + properties: { msaAppType: string; msaAppTenantId: string }; + }; + expect(body.properties.msaAppType).toBe('SingleTenant'); + expect(body.properties.msaAppTenantId).toBe(provisionOptions.msaAppTenantId); + }); + + it('points the bot at this instance', async () => { + await service.provisionBot(provisionOptions); + + const body = putTo(`${botPath}?`)?.[3] as { properties: { endpoint: string } }; + expect(body.properties.endpoint).toBe(provisionOptions.messagingEndpoint); + }); + + it('registers the resource provider before creating the bot', async () => { + await service.provisionBot(provisionOptions); + + expect(callTo('/providers/Microsoft.BotService/register')?.[1]).toBe('POST'); + }); + + /** Fixed, not configurable: Azure jargon in a flow that has none. */ + it('always puts the bot in the same resource group', async () => { + await service.provisionBot(provisionOptions); + + expect(callTo('resourceGroups/n8n-agents/providers')).toBeDefined(); + }); + + it('creates the resource group when the subscription has none', async () => { + arm.request.mockImplementation(async (_t: string, method: string, path: string) => + method === 'GET' && path.includes('/resourcegroups/n8n-agents') + ? failed(404, 'ResourceGroupNotFound') + : ok(), + ); + + await service.provisionBot(provisionOptions); + + expect(putTo('/resourcegroups/n8n-agents')).toBeDefined(); + }); + + /** + * Creating it again carries our own location, and ARM will not move a + * group that already exists elsewhere. The refusal then reads as "this + * account cannot create resources", which is a different problem. + */ + it('leaves a resource group this tenant already has where it is', async () => { + await service.provisionBot(provisionOptions); + + expect(putTo('/resourcegroups/n8n-agents')).toBeUndefined(); + }); + + it('names the bot exactly as the Deploy to Azure template would', async () => { + await service.provisionBot(provisionOptions); + + expect(callTo(`botServices/${BOT_NAME}`)).toBeDefined(); + }); + + it('says the account needs Contributor when Azure refuses', async () => { + arm.request.mockImplementation(async (_token: string, _method: string, path: string) => + path.includes('botServices') ? failed(403, 'AuthorizationFailed') : ok(), + ); + + await expect(service.provisionBot(provisionOptions)).rejects.toThrow(/Contributor/); + }); + + it('asks the user to retry while Azure is still enabling Bot Service', async () => { + arm.request.mockImplementation(async (_token: string, _method: string, path: string) => + path.includes('botServices') ? failed(409, 'MissingSubscriptionRegistration') : ok(), + ); + + await expect(service.provisionBot(provisionOptions)).rejects.toThrow(/still enabling/); + }); + + it('reports a bot whose Teams channel could not be turned on', async () => { + arm.request.mockImplementation(async (_token: string, _method: string, path: string) => + path.includes('/channels/MsTeamsChannel') ? failed(500) : ok(), + ); + + await expect(service.provisionBot(provisionOptions)).rejects.toThrow( + /Teams channel could not be turned on/, + ); + }); + + it('refuses an endpoint Azure cannot call back on', async () => { + await expect( + service.provisionBot({ ...provisionOptions, messagingEndpoint: 'http://localhost:5678' }), + ).rejects.toThrow(/HTTPS messaging endpoint/); + expect(arm.request).not.toHaveBeenCalled(); + }); + + it('refuses to run without a Microsoft sign-in', async () => { + credentialsFinderService.findCredentialForUser.mockResolvedValue(null as never); + + await expect(service.provisionBot(provisionOptions)).rejects.toThrow(BadRequestError); + }); + + /** + * The token taken here creates a bot in the customer's subscription. + * Being allowed to see a sign-in is the lower rung, and does not carry + * standing to act with it. + */ + it('refuses a sign-in the user may see but not act with', async () => { + // Answers for reading the credential, refuses for acting with it. + credentialsFinderService.findCredentialForUser.mockImplementation( + async (_id: string, _user: unknown, scopes: string[]) => + (scopes.includes('credential:use') + ? null + : mock({ + id: 'manager-1', + name: 'Microsoft organization', + type: 'microsoftTeamsManagerOAuth2Api', + })) as never, + ); + + await expect(service.provisionBot(provisionOptions)).rejects.toThrow(BadRequestError); + // The token is the first act with the sign-in, and redeeming it rotates + // the refresh token in the customer's directory. Nothing ran. + expect(tokens.acquire).not.toHaveBeenCalled(); + expect(arm.request).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-catalog.service.test.ts b/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-catalog.service.test.ts new file mode 100644 index 00000000000..04221969eef --- /dev/null +++ b/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-catalog.service.test.ts @@ -0,0 +1,586 @@ +import type { Logger } from '@n8n/backend-common'; +import type { CredentialsEntity, User } from '@n8n/db'; +import { mock } from 'vitest-mock-extended'; + +import type { CredentialsFinderService } from '@n8n/backend-services'; +import { BadRequestError } from '@n8n/errors'; + +import type { CredentialsService } from '@/credentials/credentials.service'; + +import { TeamsCatalogService } from '../teams-catalog.service'; +import { TeamsCredentialNotesService } from '../teams-credential-notes.service'; +import type { GraphResponse, TeamsGraphService } from '../teams-graph.service'; +import type { TeamsManagerTokenService } from '../teams-manager-token.service'; +import type { TeamsManifestService } from '../teams-manifest.service'; +import type { TeamsSetupService } from '../teams-setup.service'; + +const user = mock({ id: 'user-1' }); +const EXTERNAL_ID = 'external-1'; +const TEAMS_APP_ID = 'teams-app-1'; +const ARCHIVE = Buffer.from('zip'); + +const scope = { + user, + projectId: 'project-1', + agentId: 'agent-1', + managerCredentialId: 'manager-1', +}; +const publishOptions = { ...scope, credentialId: 'bot-cred-1' }; + +const ok = (body: unknown = {}): GraphResponse => ({ statusCode: 200, body, ok: true }); +const failed = (statusCode: number, code?: string, message?: string): GraphResponse => ({ + statusCode, + body: code ? { error: { code, ...(message ? { message } : {}) } } : {}, + ok: false, +}); + +/** The catalogue listing Graph answers with, for a given review state. */ +const catalogListing = (publishingState: string | null) => + ok({ + value: [ + { + id: TEAMS_APP_ID, + externalId: EXTERNAL_ID, + appDefinitions: publishingState ? [{ publishingState }] : [], + }, + ], + }); + +describe('TeamsCatalogService', () => { + let graph: ReturnType>; + let tokens: ReturnType>; + let setupService: ReturnType>; + let credentialsFinderService: ReturnType>; + let credentialsService: ReturnType>; + let service: TeamsCatalogService; + + /** Makes the channel credential readable, carrying `data`. */ + const withBotCredential = (data: Record) => { + credentialsFinderService.findCredentialForUser.mockImplementation((async (id: string) => + mock({ + id, + type: + id === 'bot-cred-1' + ? 'microsoftEntraServicePrincipalApi' + : 'microsoftTeamsManagerOAuth2Api', + })) as never); + credentialsService.decrypt.mockResolvedValue(data as never); + credentialsService.createEncryptedData.mockResolvedValue({ data: 'encrypted' } as never); + }; + + /** No app in the catalogue yet, unless a test says otherwise. */ + const withCatalog = (response: GraphResponse = ok({ value: [] })) => { + graph.request.mockImplementation(async (_token: string, _method: string, path: string) => { + if (path.startsWith('/appCatalogs/teamsApps?')) return response; + return ok(); + }); + }; + + const zipCallTo = (fragment: string) => + graph.postZip.mock.calls.find(([, path]) => String(path).includes(fragment)); + + const zipCallToExactly = (path: string) => + graph.postZip.mock.calls.find(([, called]) => String(called) === path); + + afterEach(() => { + vi.useRealTimers(); + }); + + beforeEach(() => { + graph = mock(); + tokens = mock(); + setupService = mock(); + credentialsFinderService = mock(); + credentialsService = mock(); + const manifestService = mock(); + manifestService.buildManifestId.mockReturnValue(EXTERNAL_ID); + + service = new TeamsCatalogService( + graph, + tokens, + setupService, + manifestService, + credentialsFinderService, + credentialsService, + mock(), + new TeamsCredentialNotesService(credentialsFinderService, credentialsService, mock()), + ); + + tokens.acquire.mockResolvedValue('graph-token'); + setupService.buildPackage.mockResolvedValue({ + archive: ARCHIVE, + fingerprint: 'fingerprint-1', + credentialId: 'bot-cred-1', + }); + credentialsFinderService.findCredentialForUser.mockResolvedValue( + mock({ + id: 'manager-1', + type: 'microsoftTeamsManagerOAuth2Api', + }) as never, + ); + graph.postZip.mockResolvedValue(ok({ id: TEAMS_APP_ID })); + withCatalog(); + }); + + describe('publish', () => { + it('publishes straight to the organisation for a Teams administrator', async () => { + graph.postZip.mockResolvedValue(ok({ id: TEAMS_APP_ID })); + let listed = false; + graph.request.mockImplementation(async (_t: string, _m: string, path: string) => { + if (!path.startsWith('/appCatalogs/teamsApps?')) return ok(); + const response = listed ? catalogListing('published') : ok({ value: [] }); + listed = true; + return response; + }); + + await expect(service.publish(publishOptions)).resolves.toEqual({ + status: 'published', + teamsAppId: TEAMS_APP_ID, + }); + expect(zipCallTo('requiresReview')).toBeUndefined(); + }); + + it('submits for review when the account may not publish directly', async () => { + let attempt = 0; + graph.postZip.mockImplementation(async () => { + attempt += 1; + return attempt === 1 ? failed(403, 'Forbidden') : ok({ id: TEAMS_APP_ID }); + }); + // Empty before the publish, listed after it — otherwise the service + // takes the update path and never tries a first publish at all. + let listed = false; + graph.request.mockImplementation(async (_t: string, _m: string, path: string) => { + if (!path.startsWith('/appCatalogs/teamsApps?')) return ok(); + const response = listed ? catalogListing('submitted') : ok({ value: [] }); + listed = true; + return response; + }); + + await expect(service.publish(publishOptions)).resolves.toEqual({ + status: 'submitted', + teamsAppId: TEAMS_APP_ID, + }); + expect(zipCallTo('requiresReview=true')).toBeDefined(); + }); + + it('decides the capability from the refusal, not from asking the user', async () => { + await service.publish(publishOptions); + + // The direct attempt always goes first; nothing asks what role the + // signed-in account holds. + expect(graph.postZip.mock.calls[0][1]).toBe('/appCatalogs/teamsApps'); + }); + + it('does not retry for review when the refusal was not about permission', async () => { + graph.postZip.mockResolvedValue(failed(500)); + + await expect(service.publish(publishOptions)).rejects.toThrow( + /would not accept the Teams app/, + ); + expect(graph.postZip).toHaveBeenCalledTimes(1); + }); + + /** + * Microsoft's wording for a rejected package carries request ids and + * backend host names. The log gets it; the user gets something readable. + */ + it('keeps Microsoft internals out of the message the user sees', async () => { + graph.postZip.mockResolvedValue({ + statusCode: 400, + ok: false, + body: { + error: { + code: 'BadRequest', + message: "Failed to parse manifest: 'name.short' is required.", + innerError: { code: 'UnableToParseTeamsAppManifest' }, + }, + }, + }); + + await expect(service.publish(publishOptions)).rejects.toThrow( + /Microsoft would not accept the Teams app/, + ); + await expect(service.publish(publishOptions)).rejects.not.toThrow(/Request Url/); + }); + + /** + * A taken name means a publish already landed, most likely a first attempt + * whose result never came back. Finishing it beats reporting a clash the + * user cannot act on. + */ + it('updates the app it already published when the name is taken', async () => { + // Empty when the publish starts, which is why it creates; present by the + // time the clash sends it looking. + let listed = false; + graph.request.mockImplementation(async (_token: string, _method: string, path: string) => { + if (path.startsWith('/appCatalogs/teamsApps?')) { + const value = listed + ? [{ id: TEAMS_APP_ID, appDefinitions: [{ publishingState: 'published' }] }] + : []; + listed = true; + return ok({ value }); + } + return ok(); + }); + graph.postZip.mockImplementation(async (_token: string, path: string) => + path.includes('/appDefinitions') ? ok({ id: TEAMS_APP_ID }) : failed(409, 'Conflict'), + ); + + await expect(service.publish(publishOptions)).resolves.toEqual({ + status: 'published', + teamsAppId: TEAMS_APP_ID, + }); + expect(zipCallTo('/appDefinitions')).toBeDefined(); + }); + + /** + * The clash Microsoft reports names our own manifest id, so the app is + * this agent's however little the listing knows about it. Telling the + * user to rename the agent would have them rebuild everything over a + * delay that clears itself. + */ + it('does not blame the agent for a clash with its own app', async () => { + graph.postZip.mockResolvedValue( + failed( + 409, + 'Conflict', + `App with same id already exists in the tenant. ExternalId: '${EXTERNAL_ID}', state: Installed`, + ), + ); + // Still not listed, which is why the second publish happened at all. + withCatalog(ok({ value: [] })); + + vi.useFakeTimers(); + // The handler is attached before the clock moves: a promise left + // unwatched across the retries rejects with nobody listening, and + // vitest fails the whole run on that. + const pending = service.publish(publishOptions).catch((error: unknown) => error); + await vi.advanceTimersByTimeAsync(30_000); + + const error = await pending; + expect(error).toBeInstanceOf(Error); + expect((error as Error).message).toMatch(/try again in a few minutes/i); + expect((error as Error).message).not.toMatch(/Rename the agent/); + }); + + /** + * Microsoft words these refusals as it likes, so a message that does not + * name our app proves nothing. The copy has to fit both readings rather + * than send someone to rename an agent whose own earlier publish took the + * name. + */ + it('leaves a taken name it cannot attribute open to either cause', async () => { + graph.postZip.mockResolvedValue(failed(409, 'Conflict')); + + const error = await service.publish(publishOptions).catch((caught: Error) => caught); + + expect((error as Error).message).toMatch(/try again in a few minutes/i); + expect((error as Error).message).toMatch(/rename the agent/i); + }); + + /** + * The catalogue listing is filtered on a value Microsoft indexes after the + * write, so a read taken straight after a create can come back empty. + * Reporting "not listed yet" for an app just created is what sends someone + * round to publish a second one. + */ + it('reports the app it just created, not the listing that lags behind', async () => { + graph.postZip.mockResolvedValue(ok({ id: TEAMS_APP_ID })); + withCatalog(ok({ value: [] })); + + await expect(service.publish(publishOptions)).resolves.toEqual({ + status: 'published', + teamsAppId: TEAMS_APP_ID, + }); + }); + + it('tells the user a refusal may pass, because it is often Microsoft-side', async () => { + graph.postZip.mockResolvedValue(failed(500)); + + await expect(service.publish(publishOptions)).rejects.toThrow(/Try again in a few minutes/); + }); + + it('updates the catalogued app instead of adding a second one', async () => { + withCatalog(catalogListing('published')); + + await service.publish(publishOptions); + + expect(zipCallTo(`/appCatalogs/teamsApps/${TEAMS_APP_ID}/appDefinitions`)).toBeDefined(); + // The create takes the collection path with no query, so an exact match + // is the only one that would catch a second app being added. + expect(zipCallToExactly('/appCatalogs/teamsApps')).toBeUndefined(); + }); + + /** + * Without this a member could publish an app once and never update it: + * only an administrator may change a catalogue entry outright, and the + * review route is the same one the first publish falls back to. + */ + it('sends an update for review when the account may not change the entry', async () => { + withCatalog(catalogListing('published')); + const path = `/appCatalogs/teamsApps/${TEAMS_APP_ID}/appDefinitions`; + graph.postZip.mockImplementation(async (_t: string, called: string) => + called.includes('requiresReview=true') ? ok({ id: TEAMS_APP_ID }) : failed(403), + ); + + await service.publish(publishOptions); + + expect(zipCallTo(`${path}?requiresReview=true`)).toBeDefined(); + }); + + it('says who has to publish when even a review is refused', async () => { + withCatalog(catalogListing('published')); + graph.postZip.mockResolvedValue(failed(403)); + + await expect(service.publish(publishOptions)).rejects.toThrow( + /Teams administrator has to publish/, + ); + }); + + it('builds the package from the settings in the open form', async () => { + const settings = { sessionIdleTimeoutMinutes: 30 }; + + await service.publish({ ...publishOptions, settings }); + + expect(setupService.buildPackage).toHaveBeenCalledWith( + user, + { projectId: 'project-1', agentId: 'agent-1' }, + 'bot-cred-1', + settings, + ); + }); + + it('refuses without a Microsoft sign-in', async () => { + credentialsFinderService.findCredentialForUser.mockResolvedValue(null as never); + + await expect(service.publish(publishOptions)).rejects.toThrow(BadRequestError); + }); + + /** + * Publishing puts an app in front of everyone in the organisation, as the + * account that signed in. Being allowed to see that sign-in is the lower + * rung, and does not carry standing to act with it. + */ + it('refuses a sign-in the user may see but not act with', async () => { + // Answers for reading the credential, refuses for acting with it. + credentialsFinderService.findCredentialForUser.mockImplementation((async ( + id: string, + _user: unknown, + scopes: string[], + ) => + scopes.includes('credential:use') + ? null + : mock({ + id, + type: + id === 'bot-cred-1' + ? 'microsoftEntraServicePrincipalApi' + : 'microsoftTeamsManagerOAuth2Api', + })) as never); + + await expect(service.publish(publishOptions)).rejects.toThrow(BadRequestError); + // The token is the first act with the sign-in, and redeeming it rotates + // the refresh token in the customer's directory. Nothing ran. + expect(tokens.acquire).not.toHaveBeenCalled(); + expect(graph.postZip).not.toHaveBeenCalled(); + }); + + /** + * The listing still shows the definition that was approved before, so + * asking it would report the change as live while it waits for somebody + * to approve it. + */ + it('reports an update sent for review as submitted, not published', async () => { + withCatalog(catalogListing('published')); + graph.postZip.mockImplementation(async (_t: string, path: string) => + path.includes('requiresReview=true') ? ok({ id: TEAMS_APP_ID }) : failed(403, 'Forbidden'), + ); + + await expect(service.publish(publishOptions)).resolves.toMatchObject({ + status: 'submitted', + }); + }); + }); + + describe('getState', () => { + it.each([ + ['published', 'published'], + ['submitted', 'submitted'], + ['rejected', 'rejected'], + ])('reports %s back from Microsoft', async (publishingState, expected) => { + withCatalog(catalogListing(publishingState)); + + await expect(service.getState(scope)).resolves.toEqual({ + status: expected, + teamsAppId: TEAMS_APP_ID, + }); + }); + + it('reports an app that is not listed yet as unknown, never rejected', async () => { + withCatalog(ok({ value: [] })); + + await expect(service.getState(scope)).resolves.toEqual({ + status: 'unknown', + teamsAppId: null, + }); + }); + + it('reports an unrecognised state as unknown', async () => { + withCatalog(catalogListing('somethingNew')); + + await expect(service.getState(scope)).resolves.toMatchObject({ status: 'unknown' }); + }); + + /** + * Microsoft has no route that reads one app back, and the listing does not + * return an app for minutes after a publish -- sometimes for a day. Asked + * in that window it answers the same way it answers about an app nobody + * published, so a setup reopened in it offered to publish a second time. + */ + it('falls back to the publish it recorded when the listing cannot answer', async () => { + withCatalog(ok({ value: [] })); + withBotCredential({ + publishedTeamsAppId: TEAMS_APP_ID, + publishedTeamsAppState: 'published', + publishedTeamsAppAt: new Date().toISOString(), + }); + + await expect(service.getState({ ...scope, credentialId: 'bot-cred-1' })).resolves.toEqual({ + status: 'published', + teamsAppId: TEAMS_APP_ID, + }); + }); + + /** + * The note only stands in for a listing that has not caught up. Past that + * window the catalogue is the better answer: an administrator may have + * removed the app, and a note that never expires reports it published + * for good, with no way to publish it again. + */ + it('stops answering for a publish older than the listing ever lags', async () => { + withCatalog(ok({ value: [] })); + withBotCredential({ + publishedTeamsAppId: TEAMS_APP_ID, + publishedTeamsAppState: 'published', + publishedTeamsAppAt: new Date(Date.now() - 49 * 60 * 60 * 1000).toISOString(), + }); + + await expect(service.getState({ ...scope, credentialId: 'bot-cred-1' })).resolves.toEqual({ + status: 'unknown', + teamsAppId: null, + }); + }); + + /** Written before the window existed, so the catalogue answers instead. */ + it('ignores a note with no timestamp', async () => { + withCatalog(ok({ value: [] })); + withBotCredential({ + publishedTeamsAppId: TEAMS_APP_ID, + publishedTeamsAppState: 'published', + }); + + await expect(service.getState({ ...scope, credentialId: 'bot-cred-1' })).resolves.toEqual({ + status: 'unknown', + teamsAppId: null, + }); + }); + + it('prefers what Microsoft says over what it recorded', async () => { + withCatalog(catalogListing('rejected')); + withBotCredential({ + publishedTeamsAppId: TEAMS_APP_ID, + publishedTeamsAppState: 'published', + publishedTeamsAppAt: new Date().toISOString(), + }); + + await expect(service.getState({ ...scope, credentialId: 'bot-cred-1' })).resolves.toEqual({ + status: 'rejected', + teamsAppId: TEAMS_APP_ID, + }); + }); + + it('finds the app by the id in our own manifest, storing nothing', async () => { + await service.getState(scope); + + const call = graph.request.mock.calls.find(([, , path]) => + String(path).startsWith('/appCatalogs/teamsApps?'), + ); + const filter = new URLSearchParams(String(call?.[2]).split('?')[1]).get('$filter'); + expect(filter).toBe(`externalId eq '${EXTERNAL_ID}'`); + }); + }); + + describe('recording the publish', () => { + it('writes the app it made onto the channel credential', async () => { + withBotCredential({ clientId: 'app-1' }); + graph.postZip.mockResolvedValue(ok({ id: TEAMS_APP_ID })); + + await service.publish({ ...publishOptions, settings: undefined }); + + expect(credentialsService.update).toHaveBeenCalledWith( + 'bot-cred-1', + expect.objectContaining({ data: 'encrypted' }), + { kind: 'user', user }, + expect.objectContaining({ + clientId: 'app-1', + publishedTeamsAppId: TEAMS_APP_ID, + publishedTeamsAppState: 'published', + publishedTeamsAppAt: expect.any(String), + teamsAppFingerprint: 'fingerprint-1', + }), + ); + }); + + it('leaves a credential it could not decrypt untouched', async () => { + withBotCredential({}); + graph.postZip.mockResolvedValue(ok({ id: TEAMS_APP_ID })); + + await service.publish({ ...publishOptions, settings: undefined }); + + expect(credentialsService.update).not.toHaveBeenCalled(); + }); + + it('records what it handed over even before Microsoft lists the app', async () => { + withBotCredential({ clientId: 'app-1' }); + graph.postZip.mockResolvedValue(ok({})); + + await service.publish({ ...publishOptions, settings: undefined }); + + const written = credentialsService.update.mock.calls[0][3] as Record; + expect(written.teamsAppFingerprint).toBe('fingerprint-1'); + expect(written.publishedTeamsAppId).toBeUndefined(); + }); + + /** Microsoft has the app either way, so losing the note must not undo it. */ + it('still reports the publish when the note cannot be written', async () => { + withBotCredential({ clientId: 'app-1' }); + credentialsService.update.mockRejectedValue(new Error('database is locked') as never); + graph.postZip.mockResolvedValue(ok({ id: TEAMS_APP_ID })); + + await expect(service.publish({ ...publishOptions, settings: undefined })).resolves.toEqual({ + status: 'published', + teamsAppId: TEAMS_APP_ID, + }); + }); + }); + + describe('an app still waiting for an administrator', () => { + it('reports submitted without failing, so the channel can still connect', async () => { + withCatalog(catalogListing('submitted')); + + // Nothing here throws or blocks: submitting is about org-wide + // distribution, and the bot already works for anyone who has the app. + await expect(service.getState(scope)).resolves.toEqual({ + status: 'submitted', + teamsAppId: TEAMS_APP_ID, + }); + }); + + it('keeps reporting submitted on a re-check, rather than turning into a failure', async () => { + withCatalog(catalogListing('submitted')); + + await service.getState(scope); + await expect(service.getState(scope)).resolves.toMatchObject({ status: 'submitted' }); + }); + }); +}); diff --git a/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-cleanup.service.test.ts b/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-cleanup.service.test.ts new file mode 100644 index 00000000000..b2bc75e8e7a --- /dev/null +++ b/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-cleanup.service.test.ts @@ -0,0 +1,64 @@ +import type { User } from '@n8n/db'; +import { mock } from 'vitest-mock-extended'; + +import type { AgentCredentialLookupService } from '../../../agent-credential-lookup.service'; +import { TeamsCleanupService } from '../teams-cleanup.service'; + +const user = mock({ id: 'user-1' }); +const ctx = { user, projectId: 'project-1', credentialId: 'bot-cred-1' }; + +describe('TeamsCleanupService', () => { + let credentialLookup: ReturnType>; + let service: TeamsCleanupService; + + beforeEach(() => { + credentialLookup = mock(); + service = new TeamsCleanupService(credentialLookup); + credentialLookup.decryptForUser.mockResolvedValue({ + entraAppObjectId: 'object-1', + clientId: 'app-1', + } as never); + }); + + it('names what was left behind and where to remove it', async () => { + await expect(service.describeLeftovers(ctx)).resolves.toEqual({ + integrationType: 'teams', + code: 'resources_not_deleted', + action: { type: 'open_url', url: expect.stringContaining('entra.microsoft.com') }, + details: { appId: 'app-1' }, + }); + }); + + it('says nothing about a credential the user made themselves', async () => { + credentialLookup.decryptForUser.mockResolvedValue({ clientId: 'app-1' } as never); + + await expect(service.describeLeftovers(ctx)).resolves.toBeUndefined(); + }); + + it('says nothing when the credential cannot be read', async () => { + credentialLookup.decryptForUser.mockResolvedValue(null as never); + + await expect(service.describeLeftovers(ctx)).resolves.toBeUndefined(); + }); + + it('says nothing for a draft channel with no credential', async () => { + await expect(service.describeLeftovers({ ...ctx, credentialId: '' })).resolves.toBeUndefined(); + expect(credentialLookup.decryptForUser).not.toHaveBeenCalled(); + }); + + /** + * A global credential is visible to the project whoever asks, so the read has + * to go through the disconnecting user rather than the project alone. + */ + it('reads the credential as the user who is disconnecting', async () => { + await service.describeLeftovers(ctx); + + expect(credentialLookup.decryptForUser).toHaveBeenCalledWith( + user, + 'project-1', + 'bot-cred-1', + 'microsoftEntraServicePrincipalApi', + ); + expect(credentialLookup.decryptForProject).not.toHaveBeenCalled(); + }); +}); diff --git a/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-credential-check.service.test.ts b/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-credential-check.service.test.ts index cb8f0f80bd7..a3cd90022b3 100644 --- a/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-credential-check.service.test.ts +++ b/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-credential-check.service.test.ts @@ -207,4 +207,53 @@ describe('TeamsCredentialCheckService', () => { 'a-secret', ); }); + + describe('checkFileAccess', () => { + const tokenWithRoles = (roles: string[]) => + [{ alg: 'RS256' }, { roles }] + .map((part) => Buffer.from(JSON.stringify(part)).toString('base64url')) + .concat('signature') + .join('.'); + + it('reports approved when the Graph token carries Files.Read.All', async () => { + withCredential(workingCredential); + request.mockResolvedValue({ + statusCode: 200, + body: { access_token: tokenWithRoles(['Files.Read.All']) }, + }); + + expect(await service.checkFileAccess(user, PROJECT_ID, CREDENTIAL_ID)).toEqual({ + status: 'approved', + }); + const [options] = request.mock.calls[0] as [{ body: string }]; + expect(options.body).toContain('scope=https%3A%2F%2Fgraph.microsoft.com%2F.default'); + }); + + it('reports not approved when the token lacks it', async () => { + withCredential(workingCredential); + request.mockResolvedValue({ statusCode: 200, body: { access_token: tokenWithRoles([]) } }); + + expect(await service.checkFileAccess(user, PROJECT_ID, CREDENTIAL_ID)).toEqual({ + status: 'notApproved', + }); + }); + + it('reports unknown when Microsoft issues no token', async () => { + withCredential(workingCredential); + request.mockResolvedValue({ statusCode: 401, body: {} }); + + expect(await service.checkFileAccess(user, PROJECT_ID, CREDENTIAL_ID)).toEqual({ + status: 'unknown', + }); + }); + + it('reports unknown when Microsoft cannot be reached', async () => { + withCredential(workingCredential); + request.mockRejectedValue(new Error('ECONNRESET')); + + expect(await service.checkFileAccess(user, PROJECT_ID, CREDENTIAL_ID)).toEqual({ + status: 'unknown', + }); + }); + }); }); diff --git a/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-entra-provisioning.service.test.ts b/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-entra-provisioning.service.test.ts new file mode 100644 index 00000000000..a1ba58fa1a4 --- /dev/null +++ b/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-entra-provisioning.service.test.ts @@ -0,0 +1,703 @@ +import type { CredentialsEntity, User } from '@n8n/db'; +import { CREDENTIAL_BLANKING_VALUE } from 'n8n-workflow'; +import { mock } from 'vitest-mock-extended'; + +import type { CredentialsFinderService, UrlService } from '@n8n/backend-services'; +import type { CredentialsService } from '@/credentials/credentials.service'; +import { BadRequestError } from '@n8n/errors'; + +import { TeamsEntraProvisioningService } from '../teams-entra-provisioning.service'; +import type { GraphResponse, TeamsGraphService } from '../teams-graph.service'; +import type { TeamsManagerTokenService } from '../teams-manager-token.service'; + +const user = mock({ id: 'user-1' }); +const OBJECT_ID = 'object-1'; +const APP_ID = '11111111-2222-3333-4444-555555555555'; +const TENANT_ID = '99999999-8888-7777-6666-555555555555'; + +const options = { + user, + projectId: 'project-1', + agentId: 'agent-1', + agentName: 'Support Bot', + managerCredentialId: 'manager-1', +}; + +const ok = (body: unknown): GraphResponse => ({ statusCode: 200, body, ok: true }); +const failed = (statusCode: number, code?: string): GraphResponse => ({ + statusCode, + body: code ? { error: { code } } : {}, + ok: false, +}); + +describe('TeamsEntraProvisioningService', () => { + let graph: ReturnType>; + let tokens: ReturnType>; + let credentialsService: ReturnType>; + let credentialsFinderService: ReturnType>; + let urlService: ReturnType>; + let service: TeamsEntraProvisioningService; + + /** Routes each Graph call by method and path, so tests state only what differs. */ + const routeGraph = (overrides: Record = {}) => { + const routes: Record = { + 'GET /organization?$select=id,displayName': ok({ + value: [{ id: TENANT_ID, displayName: 'Acme Corp' }], + }), + "PATCH /applications(uniqueName='n8n-agent-agent-1')": ok({ + id: OBJECT_ID, + appId: APP_ID, + displayName: 'Support Bot (n8n)', + }), + [`POST /applications/${OBJECT_ID}/addPassword`]: ok({ + secretText: 'a-secret', + endDateTime: '2028-09-17T00:00:00Z', + }), + 'POST /servicePrincipals': ok({ id: 'sp-1' }), + [`GET /applications/${OBJECT_ID}`]: ok({ appId: APP_ID, displayName: 'Support Bot (n8n)' }), + [`GET /applications/${OBJECT_ID}?$select=requiredResourceAccess,web`]: ok({}), + [`PATCH /applications/${OBJECT_ID}`]: ok({}), + ...overrides, + }; + graph.request.mockImplementation( + async (_token: string, method: string, path: string) => + routes[`${method} ${path}`] ?? failed(404), + ); + return routes; + }; + + /** The credential data written for the channel. */ + const writtenCredentialData = () => + credentialsService.createUnmanagedCredential.mock.calls[0][0].data as Record; + + beforeEach(() => { + graph = mock(); + tokens = mock(); + credentialsService = mock(); + credentialsFinderService = mock(); + urlService = mock(); + urlService.getInstanceBaseUrl.mockReturnValue('https://n8n.example.com'); + service = new TeamsEntraProvisioningService( + graph, + tokens, + credentialsService, + credentialsFinderService, + urlService, + ); + + tokens.acquire.mockResolvedValue('graph-token'); + credentialsFinderService.findCredentialForUser.mockResolvedValue( + mock({ + id: 'manager-1', + name: 'Microsoft organization', + type: 'microsoftTeamsManagerOAuth2Api', + }) as never, + ); + credentialsService.decrypt.mockResolvedValue({} as never); + credentialsService.createEncryptedData.mockResolvedValue({ data: 'encrypted' } as never); + credentialsService.getCredentialsAUserCanUseInAWorkflow.mockResolvedValue([] as never); + credentialsService.createUnmanagedCredential.mockResolvedValue( + mock({ id: 'bot-cred-1' }) as never, + ); + routeGraph(); + }); + + it('registers the app, its secret and its service principal', async () => { + const result = await service.provision(options); + + expect(graph.request).toHaveBeenCalledWith( + 'graph-token', + 'PATCH', + "/applications(uniqueName='n8n-agent-agent-1')", + expect.objectContaining({ signInAudience: 'AzureADMyOrg' }), + { Prefer: 'create-if-missing' }, + ); + expect(graph.request).toHaveBeenCalledWith('graph-token', 'POST', '/servicePrincipals', { + appId: APP_ID, + }); + expect(result.appId).toBe(APP_ID); + expect(result.organizationName).toBe('Acme Corp'); + }); + + it('declares the Graph file permission and the address the consent screen returns to', async () => { + const result = await service.provision(options); + + const redirectUri = 'https://n8n.example.com/projects/project-1/agents/agent-1'; + expect(graph.request).toHaveBeenCalledWith( + 'graph-token', + 'PATCH', + `/applications/${OBJECT_ID}`, + { + requiredResourceAccess: [ + { + resourceAppId: '00000003-0000-0000-c000-000000000000', + resourceAccess: [{ id: '01d4889c-1287-42c6-ac1f-5d1e02578ef6', type: 'Role' }], + }, + ], + web: { redirectUris: [redirectUri] }, + }, + ); + const consent = new URL(result.fileAccessConsentUrl!); + expect(consent.pathname).toBe(`/${TENANT_ID}/adminconsent`); + expect(consent.searchParams.get('client_id')).toBe(APP_ID); + expect(consent.searchParams.get('redirect_uri')).toBe(redirectUri); + expect(consent.searchParams.get('state')).toBe('teams-file-access'); + }); + + it("keeps the app's other permissions and return addresses", async () => { + const otherPermission = { id: 'other-role', type: 'Scope' }; + routeGraph({ + [`GET /applications/${OBJECT_ID}?$select=requiredResourceAccess,web`]: ok({ + requiredResourceAccess: [ + { resourceAppId: 'another-api', resourceAccess: [otherPermission] }, + { + resourceAppId: '00000003-0000-0000-c000-000000000000', + resourceAccess: [otherPermission], + }, + ], + web: { redirectUris: ['https://admin.example.com/callback'] }, + }), + }); + + await service.provision(options); + + expect(graph.request).toHaveBeenCalledWith( + 'graph-token', + 'PATCH', + `/applications/${OBJECT_ID}`, + { + requiredResourceAccess: [ + { resourceAppId: 'another-api', resourceAccess: [otherPermission] }, + { + resourceAppId: '00000003-0000-0000-c000-000000000000', + resourceAccess: [ + otherPermission, + { id: '01d4889c-1287-42c6-ac1f-5d1e02578ef6', type: 'Role' }, + ], + }, + ], + web: { + redirectUris: [ + 'https://admin.example.com/callback', + 'https://n8n.example.com/projects/project-1/agents/agent-1', + ], + }, + }, + ); + }); + + it('registers no return address on plain HTTP, which Entra refuses outside localhost', async () => { + urlService.getInstanceBaseUrl.mockReturnValue('http://n8n.internal:5678'); + + const result = await service.provision(options); + + expect(graph.request).toHaveBeenCalledWith( + 'graph-token', + 'PATCH', + `/applications/${OBJECT_ID}`, + expect.not.objectContaining({ web: expect.anything() }), + ); + expect(result.fileAccessConsentUrl).toBeNull(); + }); + + it('still finishes the setup when Microsoft refuses the declaration', async () => { + routeGraph({ [`PATCH /applications/${OBJECT_ID}`]: failed(403) }); + + const result = await service.provision(options); + + expect(result.credentialId).toBe('bot-cred-1'); + expect(result.fileAccessConsentUrl).toBeNull(); + }); + + it('still finishes the setup when Microsoft cannot be reached for the declaration', async () => { + const routes = routeGraph(); + graph.request.mockImplementation(async (_token: string, method: string, path: string) => { + if (method === 'PATCH' && path === `/applications/${OBJECT_ID}`) { + throw new Error('socket hang up'); + } + return routes[`${method} ${path}`] ?? failed(404); + }); + + const result = await service.provision(options); + + expect(result.credentialId).toBe('bot-cred-1'); + expect(result.fileAccessConsentUrl).toBeNull(); + }); + + it('writes the channel credential itself, so the user never handles a secret', async () => { + const result = await service.provision(options); + + expect(writtenCredentialData()).toMatchObject({ + tenantId: TENANT_ID, + clientId: APP_ID, + clientSecret: 'a-secret', + entraAppObjectId: OBJECT_ID, + provisionedForAgentId: 'agent-1', + }); + expect(result.credentialId).toBe('bot-cred-1'); + }); + + it('records when the secret expires', async () => { + const result = await service.provision(options); + + expect(result.secretExpiresAt).toBe('2028-09-17T00:00:00Z'); + expect(writtenCredentialData().secretExpiresAt).toBe('2028-09-17T00:00:00Z'); + }); + + it('links to the app registration in Entra', async () => { + const result = await service.provision(options); + + expect(result.entraAppUrl).toContain(APP_ID); + }); + + it('asks for the longest secret lifetime first', async () => { + await service.provision(options); + + const call = graph.request.mock.calls.find(([, , path]) => + String(path).endsWith('/addPassword'), + ); + const endDateTime = new Date( + String( + (call?.[3] as { passwordCredential: { endDateTime: string } }).passwordCredential + .endDateTime, + ), + ); + const monthsAhead = + (endDateTime.getFullYear() - new Date().getFullYear()) * 12 + + (endDateTime.getMonth() - new Date().getMonth()); + expect(monthsAhead).toBe(24); + }); + + it('steps down to a shorter lifetime when the tenant caps it', async () => { + let attempt = 0; + const routes = routeGraph(); + graph.request.mockImplementation(async (_token: string, method: string, path: string) => { + if (path.endsWith('/addPassword')) { + attempt += 1; + return attempt < 3 + ? failed(400, 'CredentialLifetimePolicyViolation') + : ok({ secretText: 'a-secret', endDateTime: '2027-03-17T00:00:00Z' }); + } + return routes[`${method} ${path}`] ?? failed(404); + }); + + await expect(service.provision(options)).resolves.toMatchObject({ + secretExpiresAt: '2027-03-17T00:00:00Z', + }); + expect(attempt).toBe(3); + }); + + it('sends the user to the manual setup when secrets are refused outright', async () => { + const routes = routeGraph(); + graph.request.mockImplementation(async (_token: string, method: string, path: string) => + path.endsWith('/addPassword') + ? failed(403, 'Authorization_RequestDenied') + : (routes[`${method} ${path}`] ?? failed(404)), + ); + + await expect(service.provision(options)).rejects.toThrow(/manual setup/); + }); + + it('says so when the account may not register applications', async () => { + routeGraph({ + "PATCH /applications(uniqueName='n8n-agent-agent-1')": failed( + 403, + 'Authorization_RequestDenied', + ), + }); + + await expect(service.provision(options)).rejects.toThrow(/not allowed to register/); + }); + + it('refuses a personal Microsoft account', async () => { + routeGraph({ 'GET /organization?$select=id,displayName': ok({ value: [] }) }); + + await expect(service.provision(options)).rejects.toThrow(/work or school account/); + }); + + it('refuses to run without a Microsoft sign-in', async () => { + credentialsFinderService.findCredentialForUser.mockResolvedValue(null as never); + + await expect(service.provision(options)).rejects.toThrow(BadRequestError); + }); + + /** + * The setup acts as this sign-in: it registers an application in the + * customer's directory and mints a secret for it. Being allowed to see a + * credential is the lower rung, and does not carry standing to act with it. + */ + it('refuses a sign-in the user may see but not act with', async () => { + // Someone who may see this sign-in and has not been granted its use: the + // lookup answers for reading it and refuses for acting with it. + credentialsFinderService.findCredentialForUser.mockImplementation( + async (_id: string, _user: unknown, scopes: string[]) => + (scopes.includes('credential:use') + ? null + : mock({ + id: 'manager-1', + name: 'Microsoft organization', + type: 'microsoftTeamsManagerOAuth2Api', + })) as never, + ); + + await expect(service.provision(options)).rejects.toThrow(BadRequestError); + // The token is the first act with the sign-in, and redeeming it rotates + // the refresh token in the customer's directory. Nothing ran. + expect(tokens.acquire).not.toHaveBeenCalled(); + expect(graph.request).not.toHaveBeenCalled(); + }); + + it('remembers which organisation the sign-in belongs to', async () => { + await service.provision(options); + + expect(credentialsService.update).toHaveBeenCalledWith( + 'manager-1', + expect.anything(), + { kind: 'user', user }, + expect.objectContaining({ tenantId: TENANT_ID, organizationName: 'Acme Corp' }), + ); + }); + + describe('keeping the secret out of sight', () => { + it('never returns the secret to the browser', async () => { + const result = await service.provision(options); + + expect(JSON.stringify(result)).not.toContain('a-secret'); + }); + + it('puts the secret only in the credential, which is encrypted', async () => { + await service.provision(options); + + // The one place it appears is the credential payload; nothing else the + // call produces carries it. + expect(writtenCredentialData().clientSecret).toBe('a-secret'); + const graphBodies = JSON.stringify(graph.request.mock.calls.map(([, , , body]) => body)); + expect(graphBodies).not.toContain('a-secret'); + }); + + it('never passes the access token anywhere but the Graph client', async () => { + await service.provision(options); + + expect(graph.request.mock.calls.every(([token]) => token === 'graph-token')).toBe(true); + const result = await service.provision(options); + expect(JSON.stringify(result)).not.toContain('graph-token'); + }); + }); + + /** + * The n8n credential is a shortcut, not the record. Losing it must not strand + * the registration this agent already owns in the customer's directory. + */ + describe('when the n8n credential is gone but the app is not', () => { + it('picks the app back up rather than registering a second one', async () => { + // 204: Microsoft updated the app it already had, and says nothing. + routeGraph({ + "PATCH /applications(uniqueName='n8n-agent-agent-1')": { + statusCode: 204, + body: {}, + ok: true, + }, + 'GET /applications?%24filter=uniqueName+eq+%27n8n-agent-agent-1%27&%24select=id%2CappId%2CdisplayName': + ok({ value: [{ id: OBJECT_ID, appId: APP_ID, displayName: 'Support Bot (n8n)' }] }), + }); + + await expect(service.provision(options)).resolves.toMatchObject({ appId: APP_ID }); + }); + + it('reports it rather than guessing when Microsoft will not say which app', async () => { + routeGraph({ + "PATCH /applications(uniqueName='n8n-agent-agent-1')": { + statusCode: 204, + body: {}, + ok: true, + }, + // Answered, and named nothing. + 'GET /applications?%24filter=uniqueName+eq+%27n8n-agent-agent-1%27&%24select=id%2CappId%2CdisplayName': + ok({ value: [] }), + }); + + await expect(service.provision(options)).rejects.toThrow(/would not say which one/); + }); + + /** + * A refusal is not Microsoft declining to name an app it made, and saying + * so sends the user looking for the wrong thing. + */ + it('reports a refused lookup as a refusal', async () => { + routeGraph({ + "PATCH /applications(uniqueName='n8n-agent-agent-1')": { + statusCode: 204, + body: {}, + ok: true, + }, + 'GET /applications?%24filter=uniqueName+eq+%27n8n-agent-agent-1%27&%24select=id%2CappId%2CdisplayName': + failed(403, 'Authorization_RequestDenied'), + }); + + await expect(service.provision(options)).rejects.toThrow(/not allowed to register/); + }); + }); + + describe('running the setup a second time', () => { + beforeEach(() => { + credentialsService.getCredentialsAUserCanUseInAWorkflow.mockResolvedValue([ + mock({ id: 'bot-cred-1', type: 'microsoftEntraServicePrincipalApi' }), + ] as never); + credentialsFinderService.findCredentialForUser.mockImplementation( + async (id: string) => + mock({ + id, + name: id === 'manager-1' ? 'Microsoft organization' : 'Support Bot (n8n)', + type: + id === 'manager-1' + ? 'microsoftTeamsManagerOAuth2Api' + : 'microsoftEntraServicePrincipalApi', + }) as never, + ); + credentialsService.decrypt.mockImplementation(async (credential: { id: string }) => + credential.id === 'bot-cred-1' + ? ({ entraAppObjectId: OBJECT_ID, provisionedForAgentId: 'agent-1' } as never) + : ({} as never), + ); + }); + + /** + * Losing the credential and running again adds another secret to the app + * that survived. Entra caps how many one may hold, so the dead ones go -- + * and only those, since a live one may belong to another instance. + */ + it('clears secrets that have expired before adding another', async () => { + routeGraph({ + [`GET /applications/${OBJECT_ID}`]: ok({ + appId: APP_ID, + displayName: 'Support Bot (n8n)', + passwordCredentials: [ + { keyId: 'dead-1', endDateTime: '2020-01-01T00:00:00Z' }, + { keyId: 'live-1', endDateTime: '2099-01-01T00:00:00Z' }, + ], + }), + }); + + await service.provision(options); + + expect(graph.request).toHaveBeenCalledWith( + expect.anything(), + 'POST', + `/applications/${OBJECT_ID}/removePassword`, + { keyId: 'dead-1' }, + ); + expect(graph.request).not.toHaveBeenCalledWith( + expect.anything(), + 'POST', + `/applications/${OBJECT_ID}/removePassword`, + { keyId: 'live-1' }, + ); + }); + + /** + * The publish records which app it put in the catalogue on this very + * credential, and that note is the only answer the setup has while + * Microsoft has not listed the app. A re-run must not lose it. + */ + it('keeps what the publish recorded on the credential', async () => { + credentialsService.decrypt.mockImplementation( + async (credential: { id: string }, includeRawData?: boolean) => { + if (credential.id !== 'bot-cred-1') return {} as never; + const data = { + entraAppObjectId: OBJECT_ID, + provisionedForAgentId: 'agent-1', + publishedTeamsAppId: 'teams-app-1', + publishedTeamsAppState: 'published', + privateKey: 'pem-1', + }; + // The real `decrypt` blanks every password field unless the caller + // asks for the raw data, and this one is written straight back. + return ( + includeRawData ? data : { ...data, privateKey: CREDENTIAL_BLANKING_VALUE } + ) as never; + }, + ); + + await service.provision(options); + + expect(credentialsService.createEncryptedData).toHaveBeenCalledWith( + expect.objectContaining({ + data: expect.objectContaining({ + publishedTeamsAppId: 'teams-app-1', + publishedTeamsAppState: 'published', + privateKey: 'pem-1', + }), + }), + ); + }); + + /** + * A re-run against another directory keeps the credential but not what it + * said about a catalogue the new tenant has never seen -- carrying that + * across suppresses the publish that is actually due. + */ + it('drops the publish note when the app lands in another tenant', async () => { + credentialsService.decrypt.mockImplementation( + async (credential: { id: string }) => + (credential.id === 'bot-cred-1' + ? { + entraAppObjectId: OBJECT_ID, + provisionedForAgentId: 'agent-1', + tenantId: 'a-different-tenant', + clientId: APP_ID, + publishedTeamsAppId: 'teams-app-1', + publishedTeamsAppState: 'published', + publishedTeamsAppAt: '2026-10-01T00:00:00Z', + azureBotName: 'support-bot-1', + azureSubscriptionId: 'sub-1', + teamsAppFingerprint: 'fingerprint-1', + } + : {}) as never, + ); + + await service.provision(options); + + // The manager credential is written first; this is about the channel's. + const written = credentialsService.createEncryptedData.mock.calls.find( + ([credential]) => credential.id === 'bot-cred-1', + )?.[0].data as Record; + expect(written.clientId).toBe(APP_ID); + expect(written.azureBotName).toBeUndefined(); + expect(written.azureSubscriptionId).toBeUndefined(); + expect(written.teamsAppFingerprint).toBe('fingerprint-1'); + expect(written.publishedTeamsAppId).toBeUndefined(); + expect(written.publishedTeamsAppState).toBeUndefined(); + expect(written.publishedTeamsAppAt).toBeUndefined(); + expect(written.tenantId).toBe(TENANT_ID); + }); + + it('reuses the app it registered, rather than registering a second one', async () => { + const result = await service.provision(options); + + // The upsert is keyed on a name derived from the agent, so a second run + // lands on the registration the first one made. + expect(graph.request).toHaveBeenCalledWith( + 'graph-token', + 'PATCH', + "/applications(uniqueName='n8n-agent-agent-1')", + expect.anything(), + { Prefer: 'create-if-missing' }, + ); + expect(result.appId).toBe(APP_ID); + }); + + /** + * The agent's own name is the only thing the app is looked up by. A + * credential names which secret may be reused and nothing else, so an + * identifier stored on one cannot send the setup's writes elsewhere. + */ + describe('a credential naming an app the agent does not own', () => { + const FOREIGN_OBJECT_ID = '99999999-9999-9999-9999-999999999999'; + + beforeEach(() => { + // The named app is a real one in the directory, which the sign-in can + // reach: a name that resolves to nothing would prove nothing. + routeGraph({ + [`GET /applications/${FOREIGN_OBJECT_ID}`]: ok({ + appId: 'ffffffff-ffff-ffff-ffff-ffffffffffff', + displayName: 'Finance API', + }), + [`POST /applications/${FOREIGN_OBJECT_ID}/addPassword`]: ok({ + secretText: 'a-foreign-secret', + endDateTime: '2028-09-17T00:00:00Z', + }), + }); + credentialsService.decrypt.mockImplementation(async (credential: { id: string }) => + credential.id === 'bot-cred-1' + ? ({ + entraAppObjectId: FOREIGN_OBJECT_ID, + provisionedForAgentId: 'agent-1', + clientSecret: 'a-stored-secret', + secretExpiresAt: '2099-01-01T00:00:00Z', + } as never) + : ({} as never), + ); + }); + + it('writes to the app its own name resolves to', async () => { + const result = await service.provision(options); + + expect(result.appId).toBe(APP_ID); + for (const method of ['GET', 'POST'] as const) { + expect(graph.request).not.toHaveBeenCalledWith( + expect.anything(), + method, + expect.stringContaining(FOREIGN_OBJECT_ID), + expect.anything(), + expect.anything(), + ); + expect(graph.request).not.toHaveBeenCalledWith( + expect.anything(), + method, + expect.stringContaining(FOREIGN_OBJECT_ID), + expect.anything(), + ); + expect(graph.request).not.toHaveBeenCalledWith( + expect.anything(), + method, + expect.stringContaining(FOREIGN_OBJECT_ID), + ); + } + }); + + it('mints a secret for that app rather than keeping the stored one', async () => { + await service.provision(options); + + expect(graph.request).toHaveBeenCalledWith( + 'graph-token', + 'POST', + `/applications/${OBJECT_ID}/addPassword`, + expect.anything(), + ); + // The stored secret opens some other registration, so it is not what + // the channel is left running on. + expect(credentialsService.update).toHaveBeenCalledWith( + 'bot-cred-1', + expect.anything(), + expect.anything(), + expect.objectContaining({ clientSecret: 'a-secret', entraAppObjectId: OBJECT_ID }), + ); + }); + }); + + it('updates the existing credential instead of creating another', async () => { + const result = await service.provision(options); + + expect(credentialsService.createUnmanagedCredential).not.toHaveBeenCalled(); + expect(result.credentialId).toBe('bot-cred-1'); + }); + + /** + * The credential outlives the app it points at. Someone deleting the + * registration in Entra used to leave the agent stuck: the credential was + * still found, reading the app failed, and no run could ever get past it. + */ + describe('when the app was deleted in the tenant', () => { + beforeEach(() => { + routeGraph({ [`GET /applications/${OBJECT_ID}`]: failed(404) }); + }); + + it('registers a replacement rather than refusing for good', async () => { + await expect(service.provision(options)).resolves.toMatchObject({ + credentialId: 'bot-cred-1', + }); + }); + + it('mints a secret for the replacement, since the old one is for an app that is gone', async () => { + await service.provision(options); + + expect(graph.request).toHaveBeenCalledWith( + expect.anything(), + 'POST', + expect.stringContaining('/addPassword'), + expect.anything(), + ); + }); + }); + }); +}); diff --git a/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-graph.service.test.ts b/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-graph.service.test.ts new file mode 100644 index 00000000000..fd600c780c8 --- /dev/null +++ b/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-graph.service.test.ts @@ -0,0 +1,144 @@ +import type { Logger } from '@n8n/backend-common'; +import type { OutboundHttp } from '@n8n/backend-network'; +import { mock } from 'vitest-mock-extended'; + +import { + describeGraphError, + graphErrorCode, + graphErrorMessage, + graphInnerErrorCode, + TeamsGraphService, +} from '../teams-graph.service'; + +describe('TeamsGraphService', () => { + let request: ReturnType; + let service: TeamsGraphService; + + /** The single request the service made, as the HTTP client saw it. */ + const sent = () => request.mock.calls[0][0] as Record; + + beforeEach(() => { + request = vi.fn().mockResolvedValue({ statusCode: 200, body: { id: 'app-1' } }); + const outboundHttp = mock(); + outboundHttp.requests.mockReturnValue(mock({ request }) as never); + service = new TeamsGraphService(outboundHttp, mock()); + }); + + describe('request', () => { + it('signs the call and sends JSON', async () => { + await service.request('a-token', 'POST', '/applications', { displayName: 'Bot' }); + + expect(sent()).toMatchObject({ + method: 'POST', + url: 'https://graph.microsoft.com/v1.0/applications', + headers: expect.objectContaining({ + authorization: 'Bearer a-token', + 'content-type': 'application/json', + }), + body: '{"displayName":"Bot"}', + }); + }); + + it('sends no body when there is none, rather than the string "undefined"', async () => { + await service.request('a-token', 'GET', '/organization'); + + expect(sent().body).toBeUndefined(); + }); + + /** A few Graph calls are gated behind a header, such as `create-if-missing`. */ + it('adds the caller’s own headers', async () => { + await service.request( + 'a-token', + 'PATCH', + "/applications(uniqueName='x')", + {}, + { + Prefer: 'create-if-missing', + }, + ); + + expect(sent().headers).toMatchObject({ Prefer: 'create-if-missing' }); + }); + + it.each([ + [200, true], + [204, true], + [299, true], + [300, false], + [403, false], + [500, false], + ])('reports %i as ok=%s', async (statusCode, ok) => { + request.mockResolvedValue({ statusCode, body: {} }); + + await expect(service.request('a-token', 'GET', '/organization')).resolves.toMatchObject({ + statusCode, + ok, + }); + }); + + /** + * The flow branches on what Graph refuses, so a refusal is handed back + * rather than thrown: a 403 on the publish call is how a user without the + * Teams administrator role is recognised. + */ + it('hands a refusal back instead of throwing', async () => { + request.mockResolvedValue({ statusCode: 403, body: { error: { code: 'Forbidden' } } }); + + await expect(service.request('a-token', 'GET', '/organization')).resolves.toMatchObject({ + ok: false, + body: { error: { code: 'Forbidden' } }, + }); + }); + + /** + * The path is concatenated onto the host, so a value that re-points the + * URL would send Microsoft's bearer token somewhere else. + */ + it.each(['@elsewhere.example/', '/../../elsewhere'])( + 'refuses to send the token off Graph for %s', + async (path) => { + await expect(service.request('a-token', 'GET', path)).rejects.toThrow(/Refusing/); + expect(request).not.toHaveBeenCalled(); + }, + ); + }); + + describe('error parsers', () => { + const refusal = { + error: { + code: 'BadRequest', + message: 'The app manifest is not valid.', + innerError: { code: 'UnableToParseTeamsAppManifest' }, + }, + }; + + it('reads the outer code, the message and the inner code', () => { + expect(graphErrorCode(refusal)).toBe('BadRequest'); + expect(graphErrorMessage(refusal)).toBe('The app manifest is not valid.'); + expect(graphInnerErrorCode(refusal)).toBe('UnableToParseTeamsAppManifest'); + }); + + /** The outer code is generic for a rejected package; the inner one names the fault. */ + it('prefers the inner code when describing a refusal', () => { + expect(describeGraphError(refusal)).toBe( + 'UnableToParseTeamsAppManifest: The app manifest is not valid.', + ); + }); + + it('falls back to the outer code when there is no inner one', () => { + expect(describeGraphError({ error: { code: 'Forbidden', message: 'No.' } })).toBe( + 'Forbidden: No.', + ); + }); + + it.each([undefined, null, 'a string', {}, { error: 'not an object' }])( + 'says nothing about %s', + (body) => { + expect(graphErrorCode(body)).toBeUndefined(); + expect(graphErrorMessage(body)).toBeUndefined(); + expect(graphInnerErrorCode(body)).toBeUndefined(); + expect(describeGraphError(body)).toBeUndefined(); + }, + ); + }); +}); diff --git a/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-managed-setup.service.test.ts b/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-managed-setup.service.test.ts new file mode 100644 index 00000000000..34c912acf0a --- /dev/null +++ b/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-managed-setup.service.test.ts @@ -0,0 +1,279 @@ +import { mock } from 'vitest-mock-extended'; +import type { User } from '@n8n/db'; + +import type { CredentialsFinderService } from '@n8n/backend-services'; +import type { CredentialsService } from '@/credentials/credentials.service'; +import type { CredentialsOverwrites } from '@/credentials-overwrites'; +import type { OauthService } from '@/oauth/oauth.service'; +import { BadRequestError } from '@n8n/errors'; + +import { + REQUIRED_MANAGER_SCOPES, + TEAMS_MANAGER_CREDENTIAL_TYPE, + TeamsManagedSetupService, +} from '../teams-managed-setup.service'; + +const PROJECT_ID = 'project-1'; +const AGENT_ID = 'agent-1'; +const user = mock({ id: 'user-1' }); +const scope = { projectId: PROJECT_ID, agentId: AGENT_ID, user }; + +/** + * What Entra records when the user consents to the credential as it stands, + * rather than a list written out here. A hand-written grant can satisfy a + * requirement the sign-in never asks for, which is the one case these tests + * exist to catch. + */ +const ALL_SCOPES = ['openid', 'offline_access', ...REQUIRED_MANAGER_SCOPES].join(' '); + +describe('TeamsManagedSetupService', () => { + let credentialsService: ReturnType>; + let credentialsFinderService: ReturnType>; + let credentialsOverwrites: ReturnType>; + let oauthService: ReturnType>; + let service: TeamsManagedSetupService; + + const withOverwrites = (overwrites: Record | undefined) => { + credentialsOverwrites.getOverwrites.mockReturnValue(overwrites as never); + }; + + /** One usable manager credential whose stored grant is `data`. */ + const withManagerCredential = ( + data: Record, + { id = 'cred-1', name = 'Microsoft organization', type = TEAMS_MANAGER_CREDENTIAL_TYPE } = {}, + ) => { + credentialsService.getCredentialsAUserCanUseInAWorkflow.mockResolvedValue([ + mock({ id, type }), + ] as never); + credentialsFinderService.findCredentialForUser.mockResolvedValue(mock({ id, name }) as never); + credentialsService.decrypt.mockResolvedValue(data as never); + }; + + beforeEach(() => { + credentialsService = mock(); + credentialsFinderService = mock(); + credentialsOverwrites = mock(); + oauthService = mock(); + oauthService.getBaseUrl.mockReturnValue('https://n8n.example.com/rest/oauth2-credential'); + service = new TeamsManagedSetupService( + credentialsService, + credentialsFinderService, + credentialsOverwrites, + oauthService, + ); + withOverwrites({ clientId: 'client-id', clientSecret: 'client-secret' }); + }); + + describe('isSetupAvailable', () => { + it('is available when the overwrite supplies a client ID and secret', () => { + expect(service.isSetupAvailable()).toBe(true); + }); + + it.each([ + ['no overwrite at all', undefined], + ['only a client ID', { clientId: 'client-id' }], + ['only a secret', { clientSecret: 'client-secret' }], + ['blank values', { clientId: ' ', clientSecret: ' ' }], + ])('is unavailable with %s', (_label, overwrites) => { + withOverwrites(overwrites); + expect(service.isSetupAvailable()).toBe(false); + }); + + it('reads the overwrite for the manager credential type', () => { + service.isSetupAvailable(); + expect(credentialsOverwrites.getOverwrites).toHaveBeenCalledWith( + 'microsoftTeamsManagerOAuth2Api', + ); + }); + }); + + describe('getSetupState', () => { + it('reports the flow unavailable, and lists nothing, without an overwrite', async () => { + withOverwrites(undefined); + + await expect(service.getSetupState(scope)).resolves.toEqual({ + managedSetupAvailable: false, + managerCredentials: [], + adminConsentUrl: null, + }); + expect(credentialsService.getCredentialsAUserCanUseInAWorkflow).not.toHaveBeenCalled(); + }); + + it('lists a connected sign-in with its organisation', async () => { + withManagerCredential({ + organizationName: 'Acme Corp', + tenantId: 'tenant-1', + oauthTokenData: { access_token: 'token', refresh_token: 'refresh-1', scope: ALL_SCOPES }, + }); + + await expect(service.getSetupState(scope)).resolves.toMatchObject({ + managedSetupAvailable: true, + managerCredentials: [ + { + id: 'cred-1', + name: 'Microsoft organization', + connected: true, + reconnectRequired: false, + organizationName: 'Acme Corp', + tenantId: 'tenant-1', + }, + ], + }); + }); + + /** + * Every provisioning step redeems the refresh token rather than the access + * token beside it, so a grant without one looks usable and fails on the + * first call. + */ + it('asks for a reconnect when the grant carries no refresh token', async () => { + withManagerCredential({ + oauthTokenData: { access_token: 'token', scope: ALL_SCOPES }, + }); + + const [summary] = (await service.getSetupState(scope)).managerCredentials; + expect(summary).toMatchObject({ connected: true, reconnectRequired: true }); + }); + + it('reports a credential whose OAuth round trip never finished as not connected', async () => { + withManagerCredential({}); + + const [summary] = (await service.getSetupState(scope)).managerCredentials; + expect(summary).toMatchObject({ + connected: false, + reconnectRequired: false, + organizationName: null, + tenantId: null, + }); + }); + + /** + * A sign-in made before publishing existed carries no catalogue consent, + * and both scopes are admin-consent-only -- so it has to be redone rather + * than fail on the publish call. + */ + it('asks for a reconnect when the grant predates the catalogue scopes', async () => { + withManagerCredential({ + oauthTokenData: { + access_token: 'token', + refresh_token: 'refresh-1', + scope: 'openid https://graph.microsoft.com/Application.ReadWrite.All', + }, + }); + + const [summary] = (await service.getSetupState(scope)).managerCredentials; + expect(summary).toMatchObject({ connected: true, reconnectRequired: true }); + }); + + it('asks for a reconnect when a required scope is missing from the grant', async () => { + withManagerCredential({ + oauthTokenData: { + access_token: 'token', + refresh_token: 'refresh-1', + // Everything but the one scope that registers the app. + scope: 'openid offline_access https://graph.microsoft.com/User.Read', + }, + }); + + const [summary] = (await service.getSetupState(scope)).managerCredentials; + expect(summary.reconnectRequired).toBe(true); + }); + + it('accepts a granted scope that Entra returned without its resource prefix', async () => { + withManagerCredential({ + oauthTokenData: { + access_token: 'token', + refresh_token: 'refresh-1', + // Entra sometimes answers with the bare permission name. + scope: REQUIRED_MANAGER_SCOPES.map((granted) => + granted.replace('https://graph.microsoft.com/', ''), + ).join(' '), + }, + }); + + const [summary] = (await service.getSetupState(scope)).managerCredentials; + expect(summary.reconnectRequired).toBe(false); + }); + + it('ignores credentials of any other type', async () => { + withManagerCredential({}, { type: 'microsoftEntraServicePrincipalApi' }); + + await expect(service.getSetupState(scope)).resolves.toMatchObject({ + managedSetupAvailable: true, + managerCredentials: [], + }); + }); + + it('skips a credential the user may not read', async () => { + withManagerCredential({}); + credentialsFinderService.findCredentialForUser.mockResolvedValue(null as never); + + const state = await service.getSetupState(scope); + expect(state.managerCredentials).toEqual([]); + }); + }); + + describe('the administrator consent prompt', () => { + /** + * A sign-in cannot ask for Graph and Azure together, because a code is + * redeemed for one resource. `/.default` asks for every permission on the + * app registration instead, which is what makes one prompt cover both. + */ + it('asks for every permission on the registration, so one prompt covers both APIs', () => { + const url = new URL(String(service.adminConsentUrl())); + + expect(url.searchParams.get('scope')).toBe('https://graph.microsoft.com/.default'); + expect(url.searchParams.get('client_id')).toBe('client-id'); + }); + + it('never offers organisation consent to a personal account', () => { + // `common` would; `organizations` cannot. + expect(String(service.adminConsentUrl())).toContain('/organizations/'); + expect(String(service.adminConsentUrl())).not.toContain('/common/'); + }); + + it('comes back with the setup state, so the step can offer it', async () => { + credentialsService.getCredentialsAUserCanUseInAWorkflow.mockResolvedValue([] as never); + + const state = await service.getSetupState(scope); + + expect(state.adminConsentUrl).toBe(service.adminConsentUrl()); + }); + + it('offers nothing when the instance has no manager client credentials', () => { + withOverwrites(undefined); + + expect(service.adminConsentUrl()).toBeNull(); + }); + }); + + describe('createManagerCredential', () => { + it('creates an empty credential of the manager type in the agent project', async () => { + credentialsService.createUnmanagedCredential.mockResolvedValue( + mock({ id: 'cred-new', name: 'Microsoft organization' }) as never, + ); + + await expect(service.createManagerCredential(scope)).resolves.toEqual({ + id: 'cred-new', + name: 'Microsoft organization', + type: 'microsoftTeamsManagerOAuth2Api', + isResolvable: false, + }); + expect(credentialsService.createUnmanagedCredential).toHaveBeenCalledWith( + expect.objectContaining({ + type: 'microsoftTeamsManagerOAuth2Api', + data: {}, + projectId: PROJECT_ID, + }), + user, + ); + }); + + it('refuses when the flow is unavailable', async () => { + withOverwrites(undefined); + + await expect(service.createManagerCredential(scope)).rejects.toThrow(BadRequestError); + expect(credentialsService.createUnmanagedCredential).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-manager-token.service.test.ts b/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-manager-token.service.test.ts new file mode 100644 index 00000000000..46369879eaf --- /dev/null +++ b/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-manager-token.service.test.ts @@ -0,0 +1,354 @@ +import type { Logger } from '@n8n/backend-common'; +import type { OutboundHttp } from '@n8n/backend-network'; +import type { CredentialsEntity, CredentialsRepository } from '@n8n/db'; +import { mock } from 'vitest-mock-extended'; + +import type { CredentialsService } from '@/credentials/credentials.service'; +import type { CredentialsOverwrites } from '@/credentials-overwrites'; +import { BadRequestError } from '@n8n/errors'; + +import { MicrosoftTeamsManagerOAuth2Api } from 'n8n-nodes-base/credentials/MicrosoftTeamsManagerOAuth2Api.credentials'; + +import { + AZURE_RESOURCE, + GRAPH_RESOURCE, + RESOURCE_SCOPES, + TeamsManagerTokenService, +} from '../teams-manager-token.service'; +import { REQUIRED_MANAGER_SCOPES } from '../teams-managed-setup.service'; + +const credential = mock({ + id: 'cred-1', + name: 'Microsoft organization', + type: 'microsoftTeamsManagerOAuth2Api', +}); + +/** The form body Entra was actually sent, parsed back out. */ +const sentBody = (request: ReturnType) => + new URLSearchParams(String(request.mock.calls[0][0].body)); + +describe('TeamsManagerTokenService', () => { + let credentialsService: ReturnType>; + let credentialsRepository: ReturnType>; + let credentialsOverwrites: ReturnType>; + let request: ReturnType; + let service: TeamsManagerTokenService; + + const respondWith = (statusCode: number, body: Record) => + request.mockResolvedValue({ statusCode, body }); + + beforeEach(() => { + credentialsService = mock(); + credentialsRepository = mock(); + credentialsRepository.findOneBy.mockResolvedValue(null); + credentialsOverwrites = mock(); + request = vi.fn(); + const outboundHttp = mock(); + outboundHttp.requests.mockReturnValue(mock({ request }) as never); + + service = new TeamsManagerTokenService( + credentialsService, + credentialsRepository, + credentialsOverwrites, + outboundHttp, + mock(), + ); + + credentialsOverwrites.getOverwrites.mockReturnValue({ + clientId: 'client-id', + clientSecret: 'client-secret', + } as never); + credentialsService.decrypt.mockResolvedValue({ + oauthTokenData: { refresh_token: 'refresh-1', scope: 'openid' }, + } as never); + credentialsService.createEncryptedData.mockResolvedValue({ data: 'encrypted' } as never); + respondWith(200, { access_token: 'graph-token' }); + }); + + it('redeems the stored refresh token for a Graph token', async () => { + await expect(service.acquire(credential, GRAPH_RESOURCE)).resolves.toBe('graph-token'); + + const body = sentBody(request); + expect(body.get('grant_type')).toBe('refresh_token'); + expect(body.get('refresh_token')).toBe('refresh-1'); + expect(body.get('scope')).toContain('https://graph.microsoft.com/Application.ReadWrite.All'); + }); + + it('redeems the same sign-in for an Azure token, without a second sign-in', async () => { + respondWith(200, { access_token: 'azure-token' }); + + await expect(service.acquire(credential, AZURE_RESOURCE)).resolves.toBe('azure-token'); + expect(sentBody(request).get('scope')).toContain( + 'https://management.azure.com/user_impersonation', + ); + }); + + it('never names two resources in one token request', async () => { + await service.acquire(credential, GRAPH_RESOURCE); + + const scope = String(sentBody(request).get('scope')); + expect(scope).not.toContain('management.azure.com'); + }); + + it('stores the rotated refresh token, so the next call still works', async () => { + respondWith(200, { access_token: 'graph-token', refresh_token: 'refresh-2' }); + + await service.acquire(credential, GRAPH_RESOURCE); + + expect(credentialsService.update).toHaveBeenCalledWith( + 'cred-1', + expect.anything(), + { kind: 'system', reason: 'integration' }, + expect.objectContaining({ + oauthTokenData: expect.objectContaining({ refresh_token: 'refresh-2' }), + }), + ); + }); + + /** + * `decrypt` reads the entity it is handed, so a caller that still holds the + * pre-rotation copy would write the spent refresh token back over the live + * one and sign the user out on the next call. + */ + it('puts the rotated token on the entity the caller holds', async () => { + const held = mock({ + id: 'cred-1', + name: 'Microsoft organization', + type: 'microsoftTeamsManagerOAuth2Api', + data: 'stale', + }); + credentialsService.createEncryptedData.mockResolvedValue({ data: 'rotated' } as never); + respondWith(200, { access_token: 'graph-token', refresh_token: 'refresh-2' }); + + await service.acquire(held, GRAPH_RESOURCE); + + expect(held.data).toBe('rotated'); + }); + + /** + * Queueing only orders the calls. Each one brought its own entity, read + * before the call ahead of it rotated the token, so the stored row -- not the + * entity -- is what says which refresh token is still live. + */ + it('redeems the stored token, not the spent one a caller still holds', async () => { + const stored = mock({ + id: 'cred-1', + name: 'Microsoft organization', + type: 'microsoftTeamsManagerOAuth2Api', + data: 'rotated', + }); + credentialsRepository.findOneBy.mockResolvedValue(stored); + credentialsService.decrypt.mockImplementation( + async (entity: CredentialsEntity) => + ({ + oauthTokenData: { + refresh_token: entity.data === 'rotated' ? 'refresh-2' : 'refresh-1', + }, + }) as never, + ); + respondWith(200, { access_token: 'graph-token' }); + + const stale = mock({ + id: 'cred-1', + name: 'Microsoft organization', + type: 'microsoftTeamsManagerOAuth2Api', + data: 'spent', + }); + await service.acquire(stale, GRAPH_RESOURCE); + + expect(sentBody(request).get('refresh_token')).toBe('refresh-2'); + }); + + /** + * Entra retires the refresh token each redemption uses. Two that overlap both + * send the same one, and the slower one then stores a token Microsoft has + * already retired -- which signs the user out on the next call. + */ + it('redeems one at a time for a credential, whatever the resource', async () => { + let active = 0; + let overlapped = false; + let n = 0; + request.mockImplementation(async () => { + active += 1; + overlapped ||= active > 1; + // Long enough for the other call to reach here if nothing held it back. + await new Promise((resolve) => setImmediate(resolve)); + active -= 1; + return { statusCode: 200, body: { access_token: `token-${++n}`, refresh_token: `r-${n}` } }; + }); + credentialsService.createEncryptedData.mockResolvedValue({ data: 'encrypted' } as never); + + await Promise.all([ + service.acquire(credential, GRAPH_RESOURCE), + service.acquire(credential, AZURE_RESOURCE), + ]); + + expect(request).toHaveBeenCalledTimes(2); + expect(overlapped).toBe(false); + }); + + /** + * Only a fresh sign-in clears `invalid_grant`, so it is the user's to act on + * rather than an internal failure to retry. + */ + it('reports a sign-in that no longer reaches the resource as the user’s to redo', async () => { + respondWith(400, { error: 'invalid_grant' }); + + await expect(service.acquire(credential, GRAPH_RESOURCE)).rejects.toThrow(BadRequestError); + }); + + it('reports a refusal that may pass on a retry as operational', async () => { + respondWith(503, { error: 'temporarily_unavailable' }); + + const error = await service + .acquire(credential, GRAPH_RESOURCE) + .catch((caught: Error) => caught); + expect(error).not.toBeInstanceOf(BadRequestError); + expect((error as Error).message).toMatch(/would not issue a token/); + }); + + it('keeps the stored token data when Microsoft returns no new refresh token', async () => { + await service.acquire(credential, GRAPH_RESOURCE); + + expect(credentialsService.update).not.toHaveBeenCalled(); + }); + + it('records a widened scope alongside the rotated token', async () => { + respondWith(200, { + access_token: 'graph-token', + refresh_token: 'refresh-2', + scope: 'openid User.Read', + }); + + await service.acquire(credential, GRAPH_RESOURCE); + + expect(credentialsService.update).toHaveBeenCalledWith( + 'cred-1', + expect.anything(), + { kind: 'system', reason: 'integration' }, + expect.objectContaining({ + oauthTokenData: expect.objectContaining({ scope: 'openid User.Read' }), + }), + ); + }); + + /** + * A refresh redeemed for one resource answers with that resource's scopes + * alone. Stored as they arrive, they shrink the record of what the sign-in + * granted, and the setup then asks for a sign-in it already has. + */ + it('keeps the scopes a single-resource refresh left out', async () => { + credentialsService.decrypt.mockResolvedValue({ + oauthTokenData: { + refresh_token: 'refresh-1', + scope: 'openid https://management.azure.com/user_impersonation', + }, + } as never); + respondWith(200, { + access_token: 'graph-token', + refresh_token: 'refresh-2', + scope: 'openid https://graph.microsoft.com/Application.ReadWrite.All', + }); + + await service.acquire(credential, GRAPH_RESOURCE); + + const [, , , stored] = credentialsService.update.mock.calls[0]; + const scope = String( + (stored as { oauthTokenData: { scope: string } }).oauthTokenData.scope, + ).split(' '); + expect(scope).toContain('https://management.azure.com/user_impersonation'); + expect(scope).toContain('https://graph.microsoft.com/Application.ReadWrite.All'); + expect(scope.filter((entry) => entry === 'openid')).toHaveLength(1); + }); + + it('asks the user to sign in again when there is no refresh token', async () => { + credentialsService.decrypt.mockResolvedValue({} as never); + + await expect(service.acquire(credential, GRAPH_RESOURCE)).rejects.toThrow(BadRequestError); + expect(request).not.toHaveBeenCalled(); + }); + + it('refuses a credential of the wrong type', async () => { + const wrongType = mock({ id: 'cred-2', type: 'slackManagerOAuth2Api' }); + + await expect(service.acquire(wrongType, GRAPH_RESOURCE)).rejects.toThrow(BadRequestError); + }); + + it('refuses when the instance has no manager client credentials', async () => { + credentialsOverwrites.getOverwrites.mockReturnValue(undefined as never); + + await expect(service.acquire(credential, GRAPH_RESOURCE)).rejects.toThrow(BadRequestError); + expect(request).not.toHaveBeenCalled(); + }); + + /** + * What Entra answers once the stored consent no longer matches the app + * registration — changing its permissions does exactly that. Retrying cannot + * fix it, so the message must not suggest it. + */ + it('says a stale sign-in has to be redone, not retried', async () => { + respondWith(400, { error: 'invalid_grant' }); + + await expect(service.acquire(credential, GRAPH_RESOURCE)).rejects.toThrow(/Sign in again/); + }); + + /** + * A grant is refused one resource at a time, and a sign-in that reaches Graph + * but not Azure is the common case. Calling that sign-in invalid sends the + * user to redo something that plainly works. + */ + it('names the resource it was refused for, not the sign-in as a whole', async () => { + respondWith(400, { error: 'invalid_grant' }); + + await expect(service.acquire(credential, AZURE_RESOURCE)).rejects.toThrow(/Azure/); + }); + + it('reports any other refusal without leaking the response', async () => { + respondWith(400, { error: 'temporarily_unavailable', error_description: 'tenant contoso' }); + + await expect(service.acquire(credential, GRAPH_RESOURCE)).rejects.toThrow( + /would not issue a token/, + ); + await expect(service.acquire(credential, GRAPH_RESOURCE)).rejects.not.toThrow(/contoso/); + }); +}); + +/** + * Three lists name the Graph permissions, in two packages: the credential asks + * for them at sign-in, the refresh asks again, and the setup checks the grant + * carries the ones it cannot work without. Asking for less shrinks the + * recorded grant and the setup sends the user round the sign-in again; asking + * for more is refused outright. A required scope the credential never asks + * for is worse still -- the reconnect it demands can never clear. + */ +describe('the Graph scopes on the refresh and on the credential', () => { + const graphOnly = (scopes: string) => + scopes + .split(' ') + .filter((scope) => scope.startsWith(GRAPH_RESOURCE)) + .sort(); + + it('name the same permissions', () => { + const signInScopes = graphOnly( + String( + new MicrosoftTeamsManagerOAuth2Api().properties.find(({ name }) => name === 'scope') + ?.default ?? '', + ), + ); + + expect(signInScopes.length).toBeGreaterThan(0); + expect(graphOnly(RESOURCE_SCOPES[GRAPH_RESOURCE])).toEqual(signInScopes); + }); + + it('require nothing the sign-in does not ask for', () => { + const signInScopes = graphOnly( + String( + new MicrosoftTeamsManagerOAuth2Api().properties.find(({ name }) => name === 'scope') + ?.default ?? '', + ), + ); + + expect(REQUIRED_MANAGER_SCOPES.length).toBeGreaterThan(0); + expect(signInScopes).toEqual(expect.arrayContaining([...REQUIRED_MANAGER_SCOPES])); + }); +}); diff --git a/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-manifest.service.test.ts b/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-manifest.service.test.ts index 90fd804b817..0e79a3c9cb1 100644 --- a/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-manifest.service.test.ts +++ b/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-manifest.service.test.ts @@ -96,6 +96,10 @@ describe('TeamsManifestService', () => { expect(service.buildManifest(options()).bots[0].botId).toBe(BOT_ID); }); + it('lets users attach files in direct messages', () => { + expect(service.buildManifest(options()).bots[0].supportsFiles).toBe(true); + }); + it('scopes the bot to direct messages when nothing else is turned on', () => { expect(service.buildManifest(options()).bots[0].scopes).toEqual(['personal']); }); @@ -125,30 +129,28 @@ describe('TeamsManifestService', () => { }); it.each([ - [ - 'channel messages', - { teamChannels: true, readAllChannelMessages: true }, - 'ChannelMessage.Read.Group', - ], - [ - 'group messages', - { groupChats: true, readAllGroupMessages: true }, - 'ChatMessage.Read.Chat', - ], - ])('asks to read all %s', (_label, availability, permission) => { - const manifest = service.buildManifest(options({ settings: availability })); + ['channel messages', { teamChannels: true }, 'ChannelMessage.Read.Group'], + ['group messages', { groupChats: true }, 'ChatMessage.Read.Chat'], + ])( + 'asks to read %s whenever the surface is on, to reach their files', + (_label, availability, permission) => { + const manifest = service.buildManifest(options({ settings: availability })); - expect(manifest.authorization?.permissions.resourceSpecific).toEqual([ - { name: permission, type: 'Application' }, - ]); - }); + expect(manifest.authorization?.permissions.resourceSpecific).toEqual([ + { name: permission, type: 'Application' }, + ]); + }, + ); it('pairs a read permission with webApplicationInfo, which Teams requires', () => { - const manifest = service.buildManifest( - options({ settings: { teamChannels: true, readAllChannelMessages: true } }), - ); + const manifest = service.buildManifest(options({ settings: { teamChannels: true } })); - expect(manifest.webApplicationInfo).toEqual({ id: BOT_ID }); + // `resource` does nothing for a resource-specific grant, but Microsoft + // answers with an error when it is absent. + expect(manifest.webApplicationInfo).toEqual({ + id: BOT_ID, + resource: 'https://RscBasedStoreApp', + }); }); it('drops a read permission whose surface is off, so it cannot read as in effect', () => { diff --git a/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-message-files.test.ts b/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-message-files.test.ts new file mode 100644 index 00000000000..e324fa52666 --- /dev/null +++ b/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-message-files.test.ts @@ -0,0 +1,287 @@ +import { InboundAttachmentAccessError } from '../../../agent-chat-integration'; +import { + fetchTeamsMessageFiles, + graphHttpOf, + graphMessagePaths, + type GraphHttp, +} from '../teams-message-files'; + +const TEAM = '1235c9a1-ef3a-4a0e-8529-0b40578bdabc'; +const CHANNEL = '19:abc@thread.tacv2'; +const GRAPH = 'https://graph.microsoft.com/v1.0'; + +function channelActivity(id: string, rootId: string) { + return { + id, + conversation: { conversationType: 'channel', id: `${CHANNEL};messageid=${rootId}` }, + channelData: { team: { aadGroupId: TEAM }, channel: { id: CHANNEL } }, + }; +} + +const groupChatActivity = { + id: '300', + conversation: { conversationType: 'groupChat', id: '19:chat@thread.v2' }, +}; + +const CHANNEL_PATH = `/teams/${TEAM}/channels/${encodeURIComponent(CHANNEL)}`; +const ROOT_PATH = `${CHANNEL_PATH}/messages/100`; + +const CONTENT_URL = 'https://contoso.sharepoint.com/sites/team/Shared Documents/plan.pdf'; +const SHARE_ID = `u!${Buffer.from(CONTENT_URL).toString('base64url')}`; +const FILE_BYTES = Buffer.from('file bytes'); + +const forbidden = () => Object.assign(new Error('403'), { response: { status: 403 } }); + +/** Answers Graph by URL prefix, so a test states only what differs. */ +function graphRouting(routes: Record) { + const get = vi.fn(async (url) => { + const key = Object.keys(routes).find((prefix) => url.startsWith(`${GRAPH}${prefix}`)); + if (key === undefined) throw new Error(`unrouted ${url}`); + const value = routes[key]; + if (value instanceof Error) throw value; + return { data: value }; + }); + return { http: { get }, get }; +} + +const DRIVE_ROOT = '/drives/drive-1/root:'; +const inDrive = (driveId: string, path: string) => ({ parentReference: { driveId, path } }); + +/** A message sharing one file, which lives in the files folder of channel `General`. */ +function sharedFileRoutes(overrides: Record = {}) { + return { + [ROOT_PATH]: { + from: { user: { id: 'sender-1' } }, + attachments: [{ contentType: 'reference', contentUrl: CONTENT_URL, name: 'plan.pdf' }], + }, + [`/shares/${SHARE_ID}/driveItem`]: { + id: 'item-1', + ...inDrive('drive-1', `${DRIVE_ROOT}/General`), + }, + [`${CHANNEL_PATH}/filesFolder`]: { name: 'General', ...inDrive('drive-1', DRIVE_ROOT) }, + '/drives/drive-1/items/item-1/content': FILE_BYTES, + ...overrides, + }; +} + +describe('graphMessagePaths', () => { + it('addresses a channel post that starts a thread, and the channel files', () => { + expect(graphMessagePaths(channelActivity('100', '100'))).toEqual({ + message: ROOT_PATH, + filesFolder: `${CHANNEL_PATH}/filesFolder`, + }); + }); + + it('addresses a reply under its thread root', () => { + expect(graphMessagePaths(channelActivity('200', '100'))?.message).toBe( + `${ROOT_PATH}/replies/200`, + ); + }); + + it('addresses a group chat message, which has no files folder', () => { + expect(graphMessagePaths(groupChatActivity)).toEqual({ + message: `/chats/${encodeURIComponent('19:chat@thread.v2')}/messages/300`, + }); + }); + + it('skips a direct message, which carries its files itself', () => { + expect( + graphMessagePaths({ id: '1', conversation: { conversationType: 'personal', id: 'a:1' } }), + ).toBeUndefined(); + }); +}); + +describe('fetchTeamsMessageFiles', () => { + it('downloads a file from the channel files', async () => { + const { http, get } = graphRouting(sharedFileRoutes()); + + const [file] = await fetchTeamsMessageFiles(http, channelActivity('100', '100')); + + expect(file).toMatchObject({ type: 'file', name: 'plan.pdf', url: CONTENT_URL }); + expect(await file.fetchData?.()).toEqual(FILE_BYTES); + expect(get).toHaveBeenLastCalledWith( + `${GRAPH}/drives/drive-1/items/item-1/content`, + expect.objectContaining({ responseType: 'arraybuffer' }), + ); + }); + + it('downloads a file from a folder inside the channel files', async () => { + const { http } = graphRouting( + sharedFileRoutes({ + [`/shares/${SHARE_ID}/driveItem`]: { + id: 'item-1', + ...inDrive('drive-1', `${DRIVE_ROOT}/General/Specs%202026`), + }, + }), + ); + + const [file] = await fetchTeamsMessageFiles(http, channelActivity('100', '100')); + + expect(await file.fetchData?.()).toEqual(FILE_BYTES); + }); + + it.each([ + ['another channel', `${DRIVE_ROOT}/Marketing`], + ['a folder that only starts like the channel', `${DRIVE_ROOT}/General Archive`], + ['the library root', DRIVE_ROOT], + ])('refuses a file in %s of the same library', async (_, path) => { + const { http, get } = graphRouting( + sharedFileRoutes({ + [`/shares/${SHARE_ID}/driveItem`]: { id: 'item-1', ...inDrive('drive-1', path) }, + '/drives/drive-1?': { owner: { group: { id: TEAM } } }, + }), + ); + + const [file] = await fetchTeamsMessageFiles(http, channelActivity('100', '100')); + + await expect(file.fetchData?.()).rejects.toBeInstanceOf(InboundAttachmentAccessError); + expect(get).not.toHaveBeenCalledWith(expect.stringContaining('/content'), expect.anything()); + }); + + it("downloads a file from the sender's own drive", async () => { + const { http } = graphRouting( + sharedFileRoutes({ + [`${CHANNEL_PATH}/filesFolder`]: { + name: 'General', + ...inDrive('team-drive', '/drives/team-drive/root:'), + }, + '/drives/drive-1?': { owner: { user: { id: 'sender-1' } } }, + }), + ); + + const [file] = await fetchTeamsMessageFiles(http, channelActivity('100', '100')); + + expect(await file.fetchData?.()).toEqual(FILE_BYTES); + }); + + it('refuses a file that is neither in the conversation nor owned by the sender', async () => { + const { http, get } = graphRouting( + sharedFileRoutes({ + [`${CHANNEL_PATH}/filesFolder`]: { + name: 'General', + ...inDrive('team-drive', '/drives/team-drive/root:'), + }, + '/drives/drive-1?': { owner: { user: { id: 'someone-else' } } }, + }), + ); + + const [file] = await fetchTeamsMessageFiles(http, channelActivity('100', '100')); + + await expect(file.fetchData?.()).rejects.toBeInstanceOf(InboundAttachmentAccessError); + expect(get).not.toHaveBeenCalledWith(expect.stringContaining('/content'), expect.anything()); + }); + + it("checks the sender's drive in a group chat", async () => { + const chatPath = `/chats/${encodeURIComponent('19:chat@thread.v2')}/messages/300`; + const { [ROOT_PATH]: message, ...rest } = sharedFileRoutes({ + '/drives/drive-1?': { owner: { user: { id: 'sender-1' } } }, + }); + const { http } = graphRouting({ ...rest, [chatPath]: message }); + + const [file] = await fetchTeamsMessageFiles(http, groupChatActivity); + + expect(await file.fetchData?.()).toEqual(FILE_BYTES); + }); + + it('asks for Files.Read.All when Graph refuses the file', async () => { + const { http } = graphRouting( + sharedFileRoutes({ [`/shares/${SHARE_ID}/driveItem`]: forbidden() }), + ); + + const [file] = await fetchTeamsMessageFiles(http, channelActivity('100', '100')); + + await expect(file.fetchData?.()).rejects.toThrow('Files.Read.All'); + }); + + it('downloads a pasted image from the message hosted content', async () => { + const src = `${GRAPH}${ROOT_PATH}/hostedContents/abc/$value`; + const { http } = graphRouting({ + [`${ROOT_PATH}/hostedContents/`]: FILE_BYTES, + [ROOT_PATH]: { body: { content: `

look

x` } }, + }); + + const [image] = await fetchTeamsMessageFiles(http, channelActivity('100', '100')); + + expect(image).toMatchObject({ type: 'image', url: src }); + expect(await image.fetchData?.()).toEqual(FILE_BYTES); + }); + + it('points a refused image to the app package, not to Files.Read.All', async () => { + const src = `${GRAPH}${ROOT_PATH}/hostedContents/abc/$value`; + const { http } = graphRouting({ + [`${ROOT_PATH}/hostedContents/`]: forbidden(), + [ROOT_PATH]: { body: { content: `` } }, + }); + + const [image] = await fetchTeamsMessageFiles(http, channelActivity('100', '100')); + + await expect(image.fetchData?.()).rejects.toThrow('latest package'); + }); + + it('ignores an image outside Graph, so the token is never sent elsewhere', async () => { + const { http } = graphRouting({ + [ROOT_PATH]: { body: { content: '' } }, + }); + + expect(await fetchTeamsMessageFiles(http, channelActivity('100', '100'))).toEqual([]); + }); + + it('reads an image whose address spells the channel id out, as Teams writes it', async () => { + const src = `${GRAPH}/teams/${TEAM}/channels/${CHANNEL}/messages/100/hostedContents/abc/$value`; + const { http } = graphRouting({ [ROOT_PATH]: { body: { content: `` } } }); + + expect(await fetchTeamsMessageFiles(http, channelActivity('100', '100'))).toHaveLength(1); + }); + + it('ignores Graph content that is not hosted on this message', async () => { + const elsewhere = [ + `${GRAPH}${CHANNEL_PATH}/messages/200/hostedContents/abc/$value`, + `${GRAPH}/drives/d1/root:/hostedContents/plan.pdf:/content`, + ]; + const { http } = graphRouting({ + [ROOT_PATH]: { + body: { content: elsewhere.map((src) => ``).join('') }, + }, + }); + + expect(await fetchTeamsMessageFiles(http, channelActivity('100', '100'))).toEqual([]); + }); + + it('ignores attachments that are not files, such as cards', async () => { + const { http } = graphRouting({ + [ROOT_PATH]: { + attachments: [{ contentType: 'application/vnd.microsoft.card.adaptive', content: '{}' }], + }, + }); + + expect(await fetchTeamsMessageFiles(http, channelActivity('100', '100'))).toEqual([]); + }); + + it('points a refused message lookup to the app package', async () => { + const { http } = graphRouting({ [ROOT_PATH]: forbidden() }); + + await expect(fetchTeamsMessageFiles(http, channelActivity('100', '100'))).rejects.toThrow( + 'latest package', + ); + }); + + it('makes no Graph call for a direct message', async () => { + const { http, get } = graphRouting({}); + + await fetchTeamsMessageFiles(http, { id: '1', conversation: { conversationType: 'personal' } }); + + expect(get).not.toHaveBeenCalled(); + }); +}); + +describe('graphHttpOf', () => { + it('finds the Graph client on the adapter', () => { + const http = { get: vi.fn() }; + + expect(graphHttpOf({ app: { graph: { http } } })).toBe(http); + }); + + it('returns nothing when the adapter has no Graph client', () => { + expect(graphHttpOf({})).toBeUndefined(); + }); +}); diff --git a/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-setup-telemetry.service.test.ts b/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-setup-telemetry.service.test.ts new file mode 100644 index 00000000000..bfbbed15985 --- /dev/null +++ b/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-setup-telemetry.service.test.ts @@ -0,0 +1,72 @@ +import { UserError } from 'n8n-workflow'; +import { mock } from 'vitest-mock-extended'; + +import type { Telemetry } from '@/telemetry'; + +import { TeamsSetupTelemetryService, withTeamsFailure } from '../teams-setup-telemetry.service'; + +const report = { + agentId: 'agent-1', + projectId: 'project-1', + userId: 'user-1', + step: 'create_bot' as const, +}; + +describe('TeamsSetupTelemetryService', () => { + let telemetry: ReturnType>; + let service: TeamsSetupTelemetryService; + + /** The properties the one event was tracked with. */ + const tracked = () => telemetry.track.mock.calls[0][1] as Record; + + beforeEach(() => { + telemetry = mock(); + service = new TeamsSetupTelemetryService(telemetry); + }); + + it('records which rung of the bot ladder was taken', () => { + service.succeeded({ ...report, botRoute: 'provisioned' }); + + expect(tracked()).toMatchObject({ + agent_id: 'agent-1', + step: 'create_bot', + outcome: 'succeeded', + bot_route: 'provisioned', + }); + }); + + /** + * The wall is named where it is hit, so rewording the sentence the user + * reads cannot quietly change what is counted. + */ + it('reports the wall the error was tagged with', () => { + service.failed( + report, + withTeamsFailure(new UserError('any wording at all'), 'personal_account'), + ); + + expect(tracked()).toMatchObject({ outcome: 'failed', reason: 'personal_account' }); + }); + + it('never reports the message itself, which can carry tenant detail', () => { + service.failed(report, new Error('Tenant contoso.onmicrosoft.com refused user a@contoso.com')); + + const properties = tracked(); + expect(properties.reason).toBe('unknown'); + expect(JSON.stringify(properties)).not.toContain('contoso'); + }); + + it('separates a wall the user can act on from an unexpected one', () => { + service.failed(report, new UserError('Something the tenant forbids')); + + expect(tracked()).toMatchObject({ reason: 'refused' }); + }); + + it('never lets reporting a step fail the step', () => { + telemetry.track.mockImplementation(() => { + throw new Error('telemetry is down'); + }); + + expect(() => service.succeeded(report)).not.toThrow(); + }); +}); diff --git a/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-setup.service.test.ts b/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-setup.service.test.ts index 7a58844b2cb..8e872714053 100644 --- a/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-setup.service.test.ts +++ b/packages/cli/src/modules/agents/integrations/platforms/teams/__tests__/teams-setup.service.test.ts @@ -4,10 +4,9 @@ import type { GlobalConfig } from '@n8n/config'; import type { User } from '@n8n/db'; import type { InstanceSettings } from 'n8n-core'; -import { JwtService } from '@/services/jwt.service'; +import { JwtService, type UrlService } from '@n8n/backend-services'; import type { CredentialsService } from '@/credentials/credentials.service'; -import type { UrlService } from '@n8n/backend-services'; import type { Agent } from '../../../../entities/agent.entity'; import { AgentCredentialLookupService } from '../../../agent-credential-lookup.service'; @@ -72,6 +71,7 @@ describe('TeamsSetupService', () => { credentialsService = mock(); urlService = mock(); urlService.getWebhookBaseUrl.mockReturnValue('https://n8n.example.com/'); + urlService.getInstanceBaseUrl.mockReturnValue('https://n8n.example.com'); credentialsService.findAllCredentialIdsForProject.mockResolvedValue([]); credentialsService.findAllGlobalCredentialIds.mockResolvedValue([]); credentialsService.getCredentialsAUserCanUseInAWorkflow.mockResolvedValue([ @@ -152,6 +152,146 @@ describe('TeamsSetupService', () => { expect(JSON.stringify(state)).not.toContain('super-secret'); }); + + /** + * The channel settings offer publishing only for an app n8n made for this + * agent. Reading the provenance too loosely offers it for an app n8n + * cannot change, and reading it too strictly sends the user back to the + * manual package. + */ + describe('the provenance that offers the managed app', () => { + const provisionedFor = (agentId: string) => { + connectTeamsCredential(); + credentialsService.decrypt.mockResolvedValue({ + clientId: CLIENT_ID, + tenantId: TENANT_ID, + clientSecret: 'super-secret', + provisionedForAgentId: agentId, + }); + }; + + it('claims the credential the recommended setup made for this agent', async () => { + provisionedFor(AGENT_ID); + + const state = await service.getSetupState(user, { + projectId: PROJECT_ID, + agentId: AGENT_ID, + }); + + expect(state.provisionedByN8n).toBe(true); + expect(state.fileAccessConsentUrl).toContain('/adminconsent?client_id='); + }); + + it('links the Azure Bot the recommended setup recorded', async () => { + provisionedFor(AGENT_ID); + credentialsService.decrypt.mockResolvedValue({ + clientId: CLIENT_ID, + tenantId: TENANT_ID, + provisionedForAgentId: AGENT_ID, + azureBotName: 'support-bot-abcd1234', + azureSubscriptionId: 'sub-1', + }); + + const state = await service.getSetupState(user, { + projectId: PROJECT_ID, + agentId: AGENT_ID, + }); + + expect(state.azureBot).toEqual({ + name: 'support-bot-abcd1234', + portalUrl: `https://portal.azure.com/#@${TENANT_ID}/resource/subscriptions/sub-1/resourceGroups/n8n-agents/providers/Microsoft.BotService/botServices/support-bot-abcd1234/overview`, + }); + }); + + it('has no bot link before the bot was recorded', async () => { + provisionedFor(AGENT_ID); + + const state = await service.getSetupState(user, { + projectId: PROJECT_ID, + agentId: AGENT_ID, + }); + + expect(state.azureBot).toBeNull(); + }); + + it('disclaims a hand-made credential, which carries no provenance', async () => { + connectTeamsCredential(); + + const state = await service.getSetupState(user, { + projectId: PROJECT_ID, + agentId: AGENT_ID, + }); + + expect(state.provisionedByN8n).toBe(false); + // A hand-made app registered no return address for the consent screen. + expect(state.fileAccessConsentUrl).toBeNull(); + }); + + it('disclaims one the recommended setup made for a different agent', async () => { + provisionedFor('agent-2'); + + const state = await service.getSetupState(user, { + projectId: PROJECT_ID, + agentId: AGENT_ID, + }); + + expect(state.provisionedByN8n).toBe(false); + }); + }); + }); + + describe('whether Teams holds an older version', () => { + const scope = { projectId: PROJECT_ID, agentId: AGENT_ID }; + const recorded = (teamsAppFingerprint: string) => + credentialsService.decrypt.mockResolvedValue({ + clientId: CLIENT_ID, + tenantId: TENANT_ID, + teamsAppFingerprint, + }); + + it('says nothing without a record of what n8n handed over', async () => { + connectTeamsCredential(); + + expect((await service.getSetupState(user, scope)).appOutdated).toBe(false); + }); + + it('matches the app n8n last handed over', async () => { + connectTeamsCredential(); + const { fingerprint } = await service.buildPackage(user, scope); + recorded(fingerprint); + + expect((await service.getSetupState(user, scope)).appOutdated).toBe(false); + }); + + it('flags an agent renamed since then', async () => { + connectTeamsCredential(); + const { fingerprint } = await service.buildPackage(user, scope); + recorded(fingerprint); + agentRepository.findByIdAndProjectId.mockResolvedValue( + Object.assign(agentWith([{ type: 'teams', credentialId: CREDENTIAL_ID, settings: {} }]), { + name: 'Helpdesk', + updatedAt: new Date('2026-09-16T10:00:00.000Z'), + }), + ); + + expect((await service.getSetupState(user, scope)).appOutdated).toBe(true); + }); + + it('flags an agent whose icon changed since then', async () => { + const withIcon = (icon: string) => + agentRepository.findByIdAndProjectId.mockResolvedValue( + Object.assign(agentWith([{ type: 'teams', credentialId: CREDENTIAL_ID, settings: {} }]), { + schema: { personalisation: { icon } }, + }), + ); + connectTeamsCredential(); + withIcon('robot'); + const { fingerprint } = await service.buildPackage(user, scope); + recorded(fingerprint); + withIcon('rocket'); + + expect((await service.getSetupState(user, scope)).appOutdated).toBe(true); + }); }); describe('a credential another agent already uses', () => { @@ -235,6 +375,52 @@ describe('TeamsSetupService', () => { }); }); + describe('botIdentityFor', () => { + /** + * An Azure bot carries one messaging endpoint, so provisioning against a + * credential another agent holds re-points that agent's bot here. + */ + it("refuses the identity another agent's bot is built on", async () => { + connectTeamsCredential(); + agentRepository.findByIntegrationCredentialAnyProject.mockResolvedValue([ + mock({ name: 'Sales Bot' }), + ]); + + await expect( + service.botIdentityFor(user, { projectId: PROJECT_ID, agentId: AGENT_ID }, CREDENTIAL_ID), + ).rejects.toThrow(/already backs the Teams channel/); + }); + + it('reads the bot identity from the credential the channel runs on', async () => { + connectTeamsCredential(); + + await expect( + service.botIdentityFor(user, { projectId: PROJECT_ID, agentId: AGENT_ID }, CREDENTIAL_ID), + ).resolves.toEqual({ + clientId: CLIENT_ID, + tenantId: TENANT_ID, + messagingEndpoint: expect.stringContaining('/webhooks/teams'), + agentName: 'Support Bot', + }); + }); + + it('refuses before a credential supplies the client ID', async () => { + await expect( + service.botIdentityFor(user, { projectId: PROJECT_ID, agentId: AGENT_ID }, CREDENTIAL_ID), + ).rejects.toThrow(/Create the Teams app/); + }); + + /** The credential is read as the signed-in user, not as the project. */ + it('refuses a credential this user may not use', async () => { + connectTeamsCredential(); + credentialsService.getCredentialsAUserCanUseInAWorkflow.mockResolvedValue([]); + + await expect( + service.botIdentityFor(user, { projectId: PROJECT_ID, agentId: AGENT_ID }, CREDENTIAL_ID), + ).rejects.toThrow(/Create the Teams app/); + }); + }); + describe('buildPackage', () => { it('refuses to build a package before a credential supplies the client ID', async () => { await expect( @@ -253,7 +439,7 @@ describe('TeamsSetupService', () => { await expect( service.buildPackage(user, { projectId: PROJECT_ID, agentId: AGENT_ID }, CREDENTIAL_ID), - ).resolves.toBeInstanceOf(Buffer); + ).resolves.toMatchObject({ archive: expect.any(Buffer), credentialId: CREDENTIAL_ID }); }); it('builds a package once a credential is connected', async () => { @@ -261,7 +447,7 @@ describe('TeamsSetupService', () => { await expect( service.buildPackage(user, { projectId: PROJECT_ID, agentId: AGENT_ID }), - ).resolves.toBeInstanceOf(Buffer); + ).resolves.toMatchObject({ archive: expect.any(Buffer), credentialId: CREDENTIAL_ID }); }); it('refuses a client ID that is not a GUID, which Teams rejects at upload', async () => { @@ -279,7 +465,7 @@ describe('TeamsSetupService', () => { ).rejects.toThrow(/not a GUID/); }); - const manifestOf = (archive: Buffer) => + const manifestOf = ({ archive }: { archive: Buffer }) => JSON.parse(Buffer.from(unzipSync(new Uint8Array(archive))['manifest.json']).toString()); it('builds from the settings it is given, which are not stored during setup', async () => { diff --git a/packages/cli/src/modules/agents/integrations/platforms/teams/teams-admin-consent.ts b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-admin-consent.ts new file mode 100644 index 00000000000..33a1e795e13 --- /dev/null +++ b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-admin-consent.ts @@ -0,0 +1,34 @@ +import type { TeamsFileAccessConsentState } from '@n8n/api-types'; + +/** + * Where Microsoft sends an administrator after they approve the app's + * permissions: the agent's page in n8n. Entra accepts only HTTPS, or plain + * HTTP on localhost, so an instance on any other HTTP address gets none. + */ +export function adminConsentRedirectUri( + instanceBaseUrl: string, + scope: { projectId: string; agentId: string }, +): string | undefined { + const url = URL.parse( + `${instanceBaseUrl}/projects/${encodeURIComponent(scope.projectId)}/agents/${encodeURIComponent(scope.agentId)}`, + ); + if (!url) return undefined; + const localhost = url.hostname === 'localhost' || url.hostname === '127.0.0.1'; + if (url.protocol !== 'https:' && !(url.protocol === 'http:' && localhost)) return undefined; + return url.href; +} + +const CONSENT_STATE: TeamsFileAccessConsentState = 'teams-file-access'; + +/** + * One screen on which an administrator approves every permission the app + * declares. It works only for an app that registered `redirectUri`. + */ +export function adminConsentUrl(tenantId: string, clientId: string, redirectUri: string): string { + const query = new URLSearchParams({ + client_id: clientId, + redirect_uri: redirectUri, + state: CONSENT_STATE, + }); + return `https://login.microsoftonline.com/${encodeURIComponent(tenantId)}/adminconsent?${query.toString()}`; +} diff --git a/packages/cli/src/modules/agents/integrations/platforms/teams/teams-arm-template.service.ts b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-arm-template.service.ts index 5a3c0ce4450..bfe60047d50 100644 --- a/packages/cli/src/modules/agents/integrations/platforms/teams/teams-arm-template.service.ts +++ b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-arm-template.service.ts @@ -2,8 +2,7 @@ import { Service } from '@n8n/di'; import { UserError } from 'n8n-workflow'; import { createHmac } from 'node:crypto'; -import { JwtService } from '@/services/jwt.service'; -import { UrlService } from '@n8n/backend-services'; +import { JwtService, UrlService } from '@n8n/backend-services'; import { sanitiseAppName } from '../../integration-helpers'; @@ -71,7 +70,7 @@ export class TeamsArmTemplateService { parameters: { botName: { type: 'string', - defaultValue: this.buildBotName(options.agentName, options.agentId), + defaultValue: this.botNameFor(options.agentName, options.agentId), metadata: { description: 'Name of the Azure Bot resource. Must be globally unique.' }, }, // An empty default looks filled in and fails validation only at the end @@ -185,10 +184,14 @@ export class TeamsArmTemplateService { } /** + * Public so the provisioned path names the bot exactly as the Deploy to + * Azure template does. Two rungs of the same ladder must not create two + * differently named bots for one agent. + * * A digest is appended because an Azure Bot resource name is globally unique, * so the bare agent name would collide across tenants. */ - private buildBotName(agentName: string, agentId: string): string { + botNameFor(agentName: string, agentId: string): string { const suffix = createHmac('sha256', 'teams-bot-name').update(agentId).digest('hex').slice(0, 8); const slug = agentName .toLowerCase() diff --git a/packages/cli/src/modules/agents/integrations/platforms/teams/teams-arm.service.ts b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-arm.service.ts new file mode 100644 index 00000000000..ca17001262b --- /dev/null +++ b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-arm.service.ts @@ -0,0 +1,100 @@ +import { Logger } from '@n8n/backend-common'; +import { OutboundHttp } from '@n8n/backend-network'; +import { Service } from '@n8n/di'; +import { UnexpectedError } from 'n8n-workflow'; + +// ARM reports failures in the same `{ error: { code, message } }` envelope as Graph. +import { graphErrorCode } from './teams-graph.service'; + +const ARM_BASE_URL = 'https://management.azure.com'; +const ARM_TIMEOUT_MS = 60_000; + +export interface ArmResponse { + statusCode: number; + body: unknown; + ok: boolean; +} + +/** Refuses a path that would move the request off the pinned host. */ +function armUrl(path: string): string { + let parsed: URL; + try { + parsed = new URL(`${ARM_BASE_URL}${path}`); + } catch { + throw new UnexpectedError('Refusing to send an Azure token to a path that is not a URL.'); + } + if (parsed.origin !== ARM_BASE_URL) { + throw new UnexpectedError('Refusing to send an Azure token off Azure Resource Manager.'); + } + return parsed.href; +} + +/** + * ARM returns `nextLink` as an absolute URL, but this client pins the host and + * takes a path. A link that points somewhere else is dropped rather than + * followed. + */ +export function armNextLinkPath(nextLink: string): string | undefined { + try { + const url = new URL(nextLink); + if (url.origin !== ARM_BASE_URL) return undefined; + return `${url.pathname}${url.search}`; + } catch { + return undefined; + } +} + +/** + * The smallest Azure Resource Manager client the bot step needs. + * + * Like the Graph client, this hands the status code back rather than throwing, + * because the bot step falls to its next option on a refusal instead of + * failing the setup. + */ +@Service() +export class TeamsArmService { + constructor( + private readonly outboundHttp: OutboundHttp, + private readonly logger: Logger, + ) {} + + async request( + accessToken: string, + method: 'GET' | 'PUT' | 'POST', + path: string, + body?: unknown, + ): Promise { + // The bearer token is Azure's, so the request must not be able to leave + // Azure. The base carries no path of its own, so a value beginning `@` + // becomes userinfo and the rest becomes the host. The parsed URL is what + // gets sent, so what was checked is what goes out. + const url = armUrl(path); + + const response = await this.outboundHttp + // Fixed public vendor host, not user-controllable. + .requests({ useDefaultSsrfPolicy: 'unsafe' }) + .request({ + method, + url, + headers: { + authorization: `Bearer ${accessToken}`, + 'content-type': 'application/json', + }, + body: body === undefined ? undefined : JSON.stringify(body), + returnFullResponse: true, + ignoreHttpStatusErrors: true, + timeout: ARM_TIMEOUT_MS, + }); + + const ok = response.statusCode >= 200 && response.statusCode < 300; + if (!ok) { + this.logger.debug('[TeamsArm] Azure refused a call', { + method, + path, + statusCode: response.statusCode, + error: graphErrorCode(response.body), + }); + } + return { statusCode: response.statusCode, body: response.body, ok }; + } +} diff --git a/packages/cli/src/modules/agents/integrations/platforms/teams/teams-bot-provisioning.service.ts b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-bot-provisioning.service.ts new file mode 100644 index 00000000000..8a684971fe9 --- /dev/null +++ b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-bot-provisioning.service.ts @@ -0,0 +1,361 @@ +import type { TeamsAzureSubscription, TeamsProvisionedBotSummary } from '@n8n/api-types'; +import type { CredentialsEntity, User } from '@n8n/db'; +import { Service } from '@n8n/di'; +import { isRecord } from '@n8n/utils/is-record'; +import { OperationalError, UserError } from 'n8n-workflow'; +import { withTeamsFailure } from './teams-setup-telemetry.service'; + +import { CredentialsFinderService } from '@n8n/backend-services'; +import { BadRequestError } from '@n8n/errors'; + +import { armNextLinkPath, type ArmResponse, TeamsArmService } from './teams-arm.service'; +import { graphErrorCode } from './teams-graph.service'; +import { TeamsArmTemplateService } from './teams-arm-template.service'; +import { TeamsCredentialNotesService } from './teams-credential-notes.service'; +import { TEAMS_MANAGER_CREDENTIAL_TYPE } from './teams-managed-setup.service'; +import { AZURE_RESOURCE, TeamsManagerTokenService } from './teams-manager-token.service'; +import { stringProperty } from '../../integration-helpers'; + +const SUBSCRIPTIONS_API = '2022-12-01'; +const RESOURCE_GROUP_API = '2021-04-01'; +const PROVIDER_API = '2021-04-01'; +const BOT_API = '2022-09-15'; +/** + * Paging is driven by a link the vendor returns, so a link that points at + * itself would loop for ever. No tenant has this many of either. + */ +const MAX_PAGES = 50; +/** Every provisioned bot lands here. Not configurable: it is Azure jargon in a + * flow that has none, and a wrong value fails late and confusingly. */ +const RESOURCE_GROUP = 'n8n-agents'; +/** Bot Service is a global resource; its resource group still needs a region. */ +const RESOURCE_GROUP_LOCATION = 'westeurope'; + +export function botResourceId(subscriptionId: string, botName: string): string { + return `/subscriptions/${subscriptionId}/resourceGroups/${RESOURCE_GROUP}/providers/Microsoft.BotService/botServices/${botName}`; +} + +/** `properties.msaAppId` of an existing bot resource. */ +function botAppIdOf(body: unknown): string | undefined { + if (!isRecord(body)) return undefined; + const properties = body.properties; + return isRecord(properties) ? stringProperty(properties, 'msaAppId') : undefined; +} + +export interface ListSubscriptionsOptions { + user: User; + managerCredentialId: string; +} + +export interface ProvisionBotOptions extends ListSubscriptionsOptions { + projectId: string; + agentId: string; + agentName: string; + /** The channel credential, which keeps where the bot is so the settings can link to it. */ + credentialId: string; + subscriptionId: string; + /** Entra application (client) ID the bot signs its messages with. */ + msaAppId: string; + msaAppTenantId: string; + messagingEndpoint: string; +} + +/** + * Creates the Bot Service resource that ties the Entra app to this instance's + * messaging endpoint. Without it Teams accepts the app and shows the bot, but + * every message goes nowhere. + * + * Graph cannot do this: the bot is an Azure resource, so it needs an Azure + * subscription and rights on it. When either is missing the caller falls back + * to a rung that does not, which is why the failures here are reported rather + * than thrown wherever the user could reasonably hit them. + */ +@Service() +export class TeamsBotProvisioningService { + constructor( + private readonly arm: TeamsArmService, + private readonly tokens: TeamsManagerTokenService, + private readonly armTemplateService: TeamsArmTemplateService, + private readonly credentialsFinderService: CredentialsFinderService, + private readonly notes: TeamsCredentialNotesService, + ) {} + + /** + * Subscriptions the signed-in account can use. An empty list is the normal + * answer for a Microsoft 365 tenant, which comes with no Azure subscription + * at all — not an error. + */ + async listSubscriptions(options: ListSubscriptionsOptions): Promise { + const token = await this.azureToken(options); + const response = await this.arm.request( + token, + 'GET', + `/subscriptions?api-version=${SUBSCRIPTIONS_API}`, + ); + // An empty list sends the user down the manual ladder with "your account + // has no Azure subscription". A refusal means we do not know, and saying + // so lets the step offer to ask again instead. + if (!response.ok) { + throw this.subscriptionsError(response.statusCode, graphErrorCode(response.body)); + } + + // ARM pages this. A tenant past the page size would otherwise be offered a + // truncated list, with the subscription they wanted missing from it. + const subscriptions: TeamsAzureSubscription[] = []; + let page: ArmResponse | undefined = response; + for (let read = 0; page && read < MAX_PAGES; read++) { + const value = isRecord(page.body) ? page.body.value : undefined; + if (Array.isArray(value)) { + for (const entry of value) { + const id = stringProperty(entry, 'subscriptionId'); + // A disabled or expired subscription cannot take a new resource. + if (!id || stringProperty(entry, 'state') !== 'Enabled') continue; + subscriptions.push({ id, name: stringProperty(entry, 'displayName') ?? id }); + } + } + + const next: string | undefined = isRecord(page.body) + ? stringProperty(page.body, 'nextLink') + : undefined; + const nextPath: string | undefined = next ? armNextLinkPath(next) : undefined; + page = nextPath ? await this.arm.request(token, 'GET', nextPath) : undefined; + // Keeping only the pages that arrived would hide the subscription the + // user came for, or read as "this account has none". + if (page && !page.ok) { + throw this.subscriptionsError(page.statusCode, graphErrorCode(page.body)); + } + } + return subscriptions; + } + + async provisionBot(options: ProvisionBotOptions): Promise { + if (!options.messagingEndpoint.startsWith('https://')) { + throw withTeamsFailure( + new UserError( + "The Teams bot needs an HTTPS messaging endpoint. Set N8N_WEBHOOK_URL to this instance's public HTTPS URL.", + ), + 'endpoint_not_https', + ); + } + + const token = await this.azureToken(options); + + await this.registerProvider(token, options.subscriptionId); + await this.ensureResourceGroup(token, options.subscriptionId); + + // An Azure resource cannot be renamed, and the name we would pick is derived + // from the agent's name — so renaming an agent would otherwise ask Azure for + // a second bot on the same app registration, which it refuses. Finding the + // bot by the app it signs for keeps a readable name and survives a rename. + const botName = + (await this.findBotByAppId(token, options.subscriptionId, options.msaAppId)) ?? + this.armTemplateService.botNameFor(options.agentName, options.agentId); + + const scope = botResourceId(options.subscriptionId, botName); + + // The bot name is derived from the agent, so a re-run lands on the bot made + // last time. Azure fixes a bot's app id at creation, so one left over from + // an earlier app registration can never be made to work for this one. + const existing = await this.arm.request(token, 'GET', `${scope}?api-version=${BOT_API}`); + if (existing.ok) { + const boundAppId = botAppIdOf(existing.body); + if (boundAppId && boundAppId.toLowerCase() !== options.msaAppId.toLowerCase()) { + throw new UserError( + `An Azure bot named ${botName} already exists and is tied to a different app registration. Azure fixes that at creation, so delete the bot or rename the agent, then try again.`, + ); + } + } + + const bot = await this.arm.request(token, 'PUT', `${scope}?api-version=${BOT_API}`, { + location: 'global', + kind: 'azurebot', + sku: { name: 'F0' }, + properties: { + displayName: botName, + endpoint: options.messagingEndpoint, + msaAppId: options.msaAppId, + // Microsoft stopped accepting new multi-tenant bots, so the bot is + // bound to the customer's own tenant. + msaAppType: 'SingleTenant', + msaAppTenantId: options.msaAppTenantId, + }, + }); + + if (!bot.ok) throw this.botError(bot.statusCode, graphErrorCode(bot.body)); + + const channel = await this.arm.request( + token, + 'PUT', + `${scope}/channels/MsTeamsChannel?api-version=${BOT_API}`, + { + location: 'global', + properties: { channelName: 'MsTeamsChannel', properties: { isEnabled: true } }, + }, + ); + if (!channel.ok) { + throw withTeamsFailure( + new OperationalError( + 'The bot was created but its Microsoft Teams channel could not be turned on.', + ), + 'teams_channel_failed', + ); + } + + // Azure has no read of a bot by the app it signs for without the + // subscription, so the channel credential keeps both for the settings link. + await this.notes.write(options.user, options.credentialId, { + azureBotName: botName, + azureSubscriptionId: options.subscriptionId, + }); + return { botName, resourceGroup: RESOURCE_GROUP, subscriptionId: options.subscriptionId }; + } + + /** + * The name of the bot in this resource group that already signs for `msaAppId`, + * if there is one. Azure binds an app id to one bot, so at most one can match. + */ + private async findBotByAppId( + token: string, + subscriptionId: string, + msaAppId: string, + ): Promise { + let page: ArmResponse = await this.arm.request( + token, + 'GET', + `/subscriptions/${subscriptionId}/resourceGroups/${RESOURCE_GROUP}/providers/Microsoft.BotService/botServices?api-version=${BOT_API}`, + ); + + // A resource group that is not there yet is the ordinary first run. Any + // other refusal is an unknown list, and reading it as "no bot" asks Azure + // for a second bot on an app registration that already has one. + if (page.statusCode === 404) return undefined; + if (!page.ok) { + throw this.botError(page.statusCode, graphErrorCode(page.body)); + } + + // Paged like the subscriptions are. Missing the bot on a later page asks + // Azure for a second one on the same app registration, which it refuses. + for (let read = 0; read < MAX_PAGES; read++) { + const value = isRecord(page.body) ? page.body.value : undefined; + if (Array.isArray(value)) { + const match = value.find( + (bot) => botAppIdOf(bot)?.toLowerCase() === msaAppId.toLowerCase(), + ); + if (match) return stringProperty(match, 'name'); + } + + const next: string | undefined = isRecord(page.body) + ? stringProperty(page.body, 'nextLink') + : undefined; + const nextPath: string | undefined = next ? armNextLinkPath(next) : undefined; + if (!nextPath) return undefined; + + page = await this.arm.request(token, 'GET', nextPath); + // Past the first page a refusal is not "no bot": taking it as one makes + // a second bot on an app registration that already has one. + if (!page.ok) { + throw this.botError(page.statusCode, graphErrorCode(page.body)); + } + } + return undefined; + } + + /** + * A subscription that has never used Bot Service rejects the bot until the + * resource provider is registered. Registration is asynchronous and the + * documentation says not to block on it, so a refusal here is left to + * surface on the create call instead. + */ + private async registerProvider(token: string, subscriptionId: string): Promise { + await this.arm.request( + token, + 'POST', + `/subscriptions/${subscriptionId}/providers/Microsoft.BotService/register?api-version=${PROVIDER_API}`, + ); + } + + /** + * A group this tenant already has is used where it stands. Creating it with + * our own location would ask ARM to move an existing one, which it refuses + * -- and that refusal reads as "this account cannot create resources". + */ + private async ensureResourceGroup(token: string, subscriptionId: string): Promise { + const path = `/subscriptions/${subscriptionId}/resourcegroups/${RESOURCE_GROUP}?api-version=${RESOURCE_GROUP_API}`; + const existing = await this.arm.request(token, 'GET', path); + if (existing.ok) return; + // A refused read is reported as itself. Creating over a group that exists + // asks Azure to move it, and that error reads to the user as "this account + // cannot create resources". Anything else -- a 404, or a blip -- still + // tries the create, which reports its own refusal. + const code = graphErrorCode(existing.body); + if (existing.statusCode === 403 || code === 'AuthorizationFailed') { + throw this.botError(existing.statusCode, code); + } + + const response = await this.arm.request(token, 'PUT', path, { + location: RESOURCE_GROUP_LOCATION, + }); + if (!response.ok) { + throw this.botError(response.statusCode, graphErrorCode(response.body)); + } + } + + /** + * Nothing is created yet at this point, so the "cannot create resources" + * wording of `botError` would send the user after a role they may not need. + */ + private subscriptionsError(statusCode: number, code: string | undefined): Error { + if (statusCode === 403 || code === 'AuthorizationFailed') { + return withTeamsFailure( + new UserError('This account cannot read the Azure subscriptions in this tenant.'), + 'no_contributor_role', + ); + } + return new OperationalError('Azure did not answer with the subscriptions. Try again.'); + } + + private botError(statusCode: number, code: string | undefined): Error { + if (statusCode === 403 || code === 'AuthorizationFailed') { + return withTeamsFailure( + new UserError( + 'This account cannot create resources in that Azure subscription. It needs the Contributor role.', + ), + 'no_contributor_role', + ); + } + if (code === 'MissingSubscriptionRegistration') { + return withTeamsFailure( + new OperationalError( + 'Azure is still enabling Bot Service on this subscription. Try again in a minute.', + ), + 'provider_registering', + ); + } + return new OperationalError('Azure refused to create the bot. Try again.'); + } + + private async azureToken(options: ListSubscriptionsOptions): Promise { + const credential = await this.managerCredential(options); + return await this.tokens.acquire(credential, AZURE_RESOURCE); + } + + /** + * `credential:use`, not `credential:read`: the token taken here creates a bot + * in the customer's Azure subscription. Seeing a sign-in is not standing to + * act with it. + */ + private async managerCredential(options: ListSubscriptionsOptions): Promise { + const credential = await this.credentialsFinderService.findCredentialForUser( + options.managerCredentialId, + options.user, + ['credential:use'], + ); + if (!credential || credential.type !== TEAMS_MANAGER_CREDENTIAL_TYPE) { + throw withTeamsFailure( + new BadRequestError('Sign in with Microsoft before creating the bot.'), + 'not_signed_in', + ); + } + return credential; + } +} diff --git a/packages/cli/src/modules/agents/integrations/platforms/teams/teams-catalog.service.ts b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-catalog.service.ts new file mode 100644 index 00000000000..86b6655ae23 --- /dev/null +++ b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-catalog.service.ts @@ -0,0 +1,439 @@ +import type { AgentTeamsIntegrationSettings, TeamsCatalogState } from '@n8n/api-types'; +import type { CredentialsEntity, User } from '@n8n/db'; +import { Logger } from '@n8n/backend-common'; +import { Service } from '@n8n/di'; +import { isRecord } from '@n8n/utils/is-record'; +import { sleep } from '@n8n/utils/sleep'; +import { OperationalError, UserError } from 'n8n-workflow'; + +import { CredentialsFinderService } from '@n8n/backend-services'; +import { BadRequestError } from '@n8n/errors'; + +import { CredentialsService } from '@/credentials/credentials.service'; + +import { TeamsCredentialNotesService } from './teams-credential-notes.service'; +import { BOT_CREDENTIAL_TYPE } from './teams-entra-provisioning.service'; +import { graphErrorCode, graphErrorMessage, TeamsGraphService } from './teams-graph.service'; +import { TeamsManifestService } from './teams-manifest.service'; +import { TEAMS_MANAGER_CREDENTIAL_TYPE } from './teams-managed-setup.service'; +import { GRAPH_RESOURCE, TeamsManagerTokenService } from './teams-manager-token.service'; +import { TeamsSetupService } from './teams-setup.service'; +import { stringProperty } from '../../integration-helpers'; + +/** + * How long the recorded publish answers for the catalogue. Microsoft takes up + * to a day or two to list a published app, and the note exists only to cover + * that. The far end of the range: expiring early offers a publish that already + * happened, which Microsoft then refuses as a duplicate. + */ +const PUBLISH_NOTE_TTL_MS = 48 * 60 * 60 * 1000; + +export interface TeamsCatalogScope { + user: User; + projectId: string; + agentId: string; + managerCredentialId: string; + /** The channel's own credential, which carries what the last publish made. */ + credentialId?: string; + /** Skips the listing, which answers empty straight after a publish. */ + teamsAppId?: string; +} + +/** + * Covers the seconds the listing index usually lags a write by, and no more. + * Microsoft documents up to a day for an availability change to apply, which + * no retry can sit through -- past this the step says to come back later. + */ +const CATALOG_LOOKUP_ATTEMPTS = 3; +const CATALOG_LOOKUP_DELAY_MS = 2000; + +interface CatalogEntry { + teamsAppId: string; + publishingState: string | null; +} + +export interface PublishTeamsAppOptions extends TeamsCatalogScope { + credentialId: string; + settings?: AgentTeamsIntegrationSettings; +} + +/** + * Publishes the generated app package to the organisation's Teams catalog. + * + * Publishing directly needs the Teams administrator role. Everyone else may + * only submit for review, and Microsoft decides which of the two applies — so + * the capability is read from what the publish call answers rather than from + * asking the user what role they hold. + */ +@Service() +export class TeamsCatalogService { + constructor( + private readonly graph: TeamsGraphService, + private readonly tokens: TeamsManagerTokenService, + private readonly setupService: TeamsSetupService, + private readonly manifestService: TeamsManifestService, + private readonly credentialsFinderService: CredentialsFinderService, + private readonly credentialsService: CredentialsService, + private readonly logger: Logger, + private readonly notes: TeamsCredentialNotesService, + ) {} + + async publish(options: PublishTeamsAppOptions): Promise { + const { archive, fingerprint } = await this.setupService.buildPackage( + options.user, + { projectId: options.projectId, agentId: options.agentId }, + options.credentialId, + options.settings, + ); + const state = await this.publishToCatalog(options, archive); + await this.rememberPublish(options, state, fingerprint); + return state; + } + + private async publishToCatalog( + options: PublishTeamsAppOptions, + archive: Buffer, + ): Promise { + const token = await this.graphToken(options); + + const existing = await this.findCatalogApp(token, options.agentId); + if (existing) { + const status = await this.updateExistingApp(token, existing.teamsAppId, archive); + return { status, teamsAppId: existing.teamsAppId }; + } + + // A Teams administrator may publish outright. Anyone else is refused, and + // the same package goes in for review instead. That refusal is the only + // reliable way to tell the two apart. + const direct = await this.graph.postZip(token, '/appCatalogs/teamsApps', archive); + if (direct.ok) { + this.logger.debug('[TeamsCatalog] Published straight to the organisation', { + agentId: options.agentId, + teamsAppId: stringProperty(direct.body, 'id') ?? null, + externalId: this.manifestService.buildManifestId(options.agentId), + }); + return this.createdState(direct.body, 'published'); + } + + if (direct.statusCode === 409 || graphErrorCode(direct.body) === 'Conflict') { + return await this.publishOverConflict(token, options.agentId, archive, direct.body); + } + + if (!this.isPermissionRefusal(direct.statusCode, graphErrorCode(direct.body))) { + throw this.publishError(direct.statusCode, direct.body); + } + + const submitted = await this.graph.postZip( + token, + '/appCatalogs/teamsApps?requiresReview=true', + archive, + ); + if (submitted.ok) { + // A submitted app is not in the catalogue until somebody approves it, + // which is why nothing can be installed from it yet. + this.logger.debug('[TeamsCatalog] Sent for review instead of published', { + agentId: options.agentId, + teamsAppId: stringProperty(submitted.body, 'id') ?? null, + refusedWith: direct.statusCode, + }); + return this.createdState(submitted.body, 'submitted'); + } + + if (submitted.statusCode === 409 || graphErrorCode(submitted.body) === 'Conflict') { + return await this.publishOverConflict(token, options.agentId, archive, submitted.body); + } + throw this.publishError(submitted.statusCode, submitted.body); + } + + /** + * The listing is filtered on a value Microsoft indexes after the write, so a + * read taken straight after a create can come back empty. The created app + * answers for itself instead -- reporting "not listed yet" for an app we + * just made is what sends someone round to publish a second one. + */ + private createdState(body: unknown, status: 'published' | 'submitted'): TeamsCatalogState { + const teamsAppId = stringProperty(body, 'id'); + return teamsAppId ? { status, teamsAppId } : { status: 'unknown', teamsAppId: null }; + } + + /** + * The name is taken, which means a publish already landed -- here or on an + * earlier run whose result never came back. Updating that app is what the + * caller asked for, so the second attempt finishes the job instead of + * reporting a clash they cannot act on. + */ + private async publishOverConflict( + token: string, + agentId: string, + archive: Buffer, + refusal: unknown, + ): Promise { + // Microsoft names the app it clashed with, and names it by the id from + // our own manifest when the app is one of ours. That is a surer answer + // than the listing, which has not caught up -- it is the reason the + // caller published a second time. A message that does not name ours + // proves nothing, though: the wording is Microsoft's to change. + const externalId = this.manifestService.buildManifestId(agentId); + const ours = (graphErrorMessage(refusal) ?? '').includes(externalId); + + const existing = await this.awaitCatalogApp(token, agentId); + if (!existing) { + throw ours + ? new UserError( + 'This agent already has an app in the organisation catalogue, and Microsoft has not listed it yet, so it cannot be updated. Nothing is wrong and nothing was lost — try again in a few minutes.', + ) + : new UserError( + 'An app with this name is already in the organisation catalogue, and Microsoft has not listed it yet, so it cannot be updated. If an earlier publish made it, try again in a few minutes. If another app holds the name, rename the agent and try again.', + ); + } + const status = await this.updateExistingApp(token, existing.teamsAppId, archive); + return { status, teamsAppId: existing.teamsAppId }; + } + + /** + * Reads the review back from Microsoft rather than tracking it here. An + * n8n-side copy would be a second queue that can disagree with the real one. + */ + async getState(options: TeamsCatalogScope): Promise { + const token = await this.graphToken(options); + const state = await this.readState(token, options.agentId); + if (state.status !== 'unknown') return state; + + // The listing does not return an app for some minutes after a publish, + // and Microsoft allows itself a day. Asked in that window, it answers the + // same way it answers about an app that was never published -- so a setup + // reopened in it offered to publish again, and Microsoft refused the + // second publish as a duplicate. + return (await this.rememberedPublish(options)) ?? state; + } + + /** + * Records what the publish made, beside the app registration the channel + * credential already carries. It is the only account of the publish that + * outlives the dialog: Microsoft has no route that reads one app back. + */ + private async rememberPublish( + options: PublishTeamsAppOptions, + state: TeamsCatalogState, + fingerprint: string, + ): Promise { + if (!options.credentialId) return; + // Microsoft took the package even when it has not listed it yet, so what + // was handed over is recorded either way. + const notes: Record = { teamsAppFingerprint: fingerprint }; + if (state.teamsAppId && state.status !== 'unknown') { + // Rewritten even when it says the same thing: the timestamp is what + // bounds it, so a re-publish has to push the window out. + notes.publishedTeamsAppId = state.teamsAppId; + notes.publishedTeamsAppState = state.status; + notes.publishedTeamsAppAt = new Date().toISOString(); + } + await this.notes.write(options.user, options.credentialId, notes); + } + + /** What the last publish made, for when the catalogue will not say. */ + private async rememberedPublish( + options: TeamsCatalogScope, + ): Promise { + const credential = await this.botCredential(options, 'credential:read'); + if (!credential) return undefined; + + const data = await this.credentialsService.decrypt(credential, true); + const teamsAppId = stringProperty(data, 'publishedTeamsAppId'); + const status = stringProperty(data, 'publishedTeamsAppState'); + if (!teamsAppId || (status !== 'published' && status !== 'submitted')) return undefined; + + // The note stands in for a listing that has not caught up, so it is only + // worth what that lag costs. Past the window the catalogue is the better + // answer: an administrator may have removed the app, and a note that + // never expires would report it published for good. A note written + // before the window existed carries no timestamp, and reading it as + // expired puts those credentials back on the catalogue's own answer. + const writtenAt = Date.parse(stringProperty(data, 'publishedTeamsAppAt') ?? ''); + if (Number.isNaN(writtenAt) || Date.now() - writtenAt > PUBLISH_NOTE_TTL_MS) { + return undefined; + } + return { status, teamsAppId }; + } + + private async botCredential( + options: TeamsCatalogScope, + scope: 'credential:read' | 'credential:update', + ): Promise { + if (!options.credentialId) return undefined; + const credential = await this.credentialsFinderService.findCredentialForUser( + options.credentialId, + options.user, + [scope], + ); + return credential?.type === BOT_CREDENTIAL_TYPE ? credential : undefined; + } + + /** + * The same two-step the first publish takes: an administrator updates the + * catalogue entry outright, and anyone else has to ask for a review. Without + * the retry a member could publish an app once and never update it again. + * + * It answers which route the update took, because the listing cannot: an + * update sent for review leaves the previously approved definition in place, + * so it still reads `published` while the change waits for somebody. + */ + private async updateExistingApp( + token: string, + teamsAppId: string, + archive: Buffer, + ): Promise<'published' | 'submitted'> { + const path = `/appCatalogs/teamsApps/${teamsAppId}/appDefinitions`; + const direct = await this.graph.postZip(token, path, archive); + if (direct.ok) return 'published'; + + if (!this.isPermissionRefusal(direct.statusCode, graphErrorCode(direct.body))) { + throw this.publishError(direct.statusCode, direct.body); + } + + const submitted = await this.graph.postZip(token, `${path}?requiresReview=true`, archive); + if (!submitted.ok) { + throw this.publishError(submitted.statusCode, submitted.body); + } + return 'submitted'; + } + + /** + * Graph serves catalogue entries only as a filtered collection -- there is no + * read of a single app by key -- and the index behind that filter is written + * after the app is. So the entry a publish just made is missing for a short + * while, and the only honest answer is to ask again. + */ + private async awaitCatalogApp(token: string, agentId: string): Promise { + for (let attempt = 0; attempt < CATALOG_LOOKUP_ATTEMPTS; attempt++) { + if (attempt > 0) await sleep(CATALOG_LOOKUP_DELAY_MS); + + const byExternalId = await this.queryCatalog( + token, + `externalId eq '${this.manifestService.buildManifestId(agentId)}'`, + ); + if (byExternalId) return byExternalId; + + this.logger.debug('[TeamsCatalog] Catalogue has not listed the app yet', { + agentId, + attempt: attempt + 1, + of: CATALOG_LOOKUP_ATTEMPTS, + }); + } + return undefined; + } + + private async queryCatalog(token: string, filter: string): Promise { + const query = new URLSearchParams({ $filter: filter, $expand: 'appDefinitions' }); + const response = await this.graph.request( + token, + 'GET', + `/appCatalogs/teamsApps?${query.toString()}`, + ); + // A refusal and an empty catalogue both answer `undefined`, and the caller + // tells the user the app is not listed yet. Logged so a missing + // `AppCatalog` consent does not read as Microsoft still catching up. + if (!response.ok) { + this.logger.debug('[TeamsCatalog] Could not read the catalogue', { + statusCode: response.statusCode, + error: graphErrorCode(response.body), + }); + return undefined; + } + const value = isRecord(response.body) ? response.body.value : undefined; + return this.toCatalogEntry(Array.isArray(value) ? value[0] : undefined); + } + + /** + * The app is found by the id in our own manifest, which is derived from the + * agent id, so nothing has to be stored to find it again. + */ + private async findCatalogApp(token: string, agentId: string): Promise { + return await this.queryCatalog( + token, + `externalId eq '${this.manifestService.buildManifestId(agentId)}'`, + ); + } + + private toCatalogEntry(entry: unknown): CatalogEntry | undefined { + const teamsAppId = stringProperty(entry, 'id'); + if (!teamsAppId) return undefined; + + const definitions = isRecord(entry) ? entry.appDefinitions : undefined; + const latest = Array.isArray(definitions) ? definitions[definitions.length - 1] : undefined; + return { + teamsAppId, + publishingState: stringProperty(latest, 'publishingState') ?? null, + }; + } + + private async readState(token: string, agentId: string): Promise { + const app = await this.findCatalogApp(token, agentId); + if (!app) { + // Policies take a day or two to apply, so an app that is not listed yet + // is unknown rather than rejected. Treating absent as terminal would + // tell a user their app was refused when it is merely not visible. + return { status: 'unknown', teamsAppId: null }; + } + + switch (app.publishingState) { + case 'published': + return { status: 'published', teamsAppId: app.teamsAppId }; + case 'submitted': + return { status: 'submitted', teamsAppId: app.teamsAppId }; + case 'rejected': + return { status: 'rejected', teamsAppId: app.teamsAppId }; + default: + return { status: 'unknown', teamsAppId: app.teamsAppId }; + } + } + + /** A user without the Teams administrator role is refused this way. */ + private isPermissionRefusal(statusCode: number, code: string | undefined): boolean { + return statusCode === 403 || code === 'Forbidden' || code === 'UnauthorizedAccessException'; + } + + /** + * Deliberately vague to the user. Microsoft's own wording for a rejected + * package runs to internal request ids and backend host names — unreadable, + * and nothing a user can act on. The full text goes to the log instead, where + * whoever can act on it will look. + */ + private publishError(statusCode: number, body: unknown): Error { + if (statusCode === 409 || graphErrorCode(body) === 'Conflict') { + return new UserError('An app with this name is already in the organisation catalogue.'); + } + // Waiting changes nothing about a role the account does not hold, and this + // is the answer when even the review route is closed to it. + if (this.isPermissionRefusal(statusCode, graphErrorCode(body))) { + return new UserError( + 'This account may not put the app in the organisation catalogue. A Teams administrator has to publish it.', + ); + } + return new OperationalError( + 'Microsoft would not accept the Teams app. Try again in a few minutes.', + ); + } + + private async graphToken(options: TeamsCatalogScope): Promise { + const credential = await this.managerCredential(options); + return await this.tokens.acquire(credential, GRAPH_RESOURCE); + } + + /** + * `credential:use`, not `credential:read`: the token taken here puts an app + * in the organisation's catalogue, as this sign-in. Seeing a sign-in is not + * standing to act with it. + */ + private async managerCredential(options: TeamsCatalogScope): Promise { + const credential = await this.credentialsFinderService.findCredentialForUser( + options.managerCredentialId, + options.user, + ['credential:use'], + ); + if (!credential || credential.type !== TEAMS_MANAGER_CREDENTIAL_TYPE) { + throw new BadRequestError('Sign in with Microsoft before publishing the Teams app.'); + } + return credential; + } +} diff --git a/packages/cli/src/modules/agents/integrations/platforms/teams/teams-cleanup.service.ts b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-cleanup.service.ts new file mode 100644 index 00000000000..84e0fdc6aa1 --- /dev/null +++ b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-cleanup.service.ts @@ -0,0 +1,57 @@ +import type { AgentIntegrationDisconnectWarning } from '@n8n/api-types'; +import type { User } from '@n8n/db'; +import { Service } from '@n8n/di'; + +import { AgentCredentialLookupService } from '../../agent-credential-lookup.service'; +import { stringProperty } from '../../integration-helpers'; + +const BOT_CREDENTIAL_TYPE = 'microsoftEntraServicePrincipalApi'; +const ENTRA_APPS_URL = + 'https://entra.microsoft.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade'; + +export interface TeamsCleanupContext { + user: User; + projectId: string; + credentialId: string; +} + +/** + * Disconnecting deletes nothing in the customer's Microsoft tenant. + * + * The pieces depend on each other, and one of them — the catalogued Teams app — + * may have been approved by an administrator and installed by colleagues. + * Removing the Entra app while that stays leaves an app that is installed for + * other people and silently broken, which is worse than leaving both. So the + * user is told what remains and where to remove it. + */ +@Service() +export class TeamsCleanupService { + constructor(private readonly credentialLookup: AgentCredentialLookupService) {} + + async describeLeftovers( + ctx: TeamsCleanupContext, + ): Promise { + if (!ctx.credentialId) return undefined; + + // Through the disconnecting user: `decryptForProject` consults nobody, and + // would read a global credential this user may no longer use. + const data = await this.credentialLookup.decryptForUser( + ctx.user, + ctx.projectId, + ctx.credentialId, + BOT_CREDENTIAL_TYPE, + ); + // Only an app n8n registered is worth warning about. A credential the user + // made by hand is theirs to keep, and they know where it is. + if (!data || !stringProperty(data, 'entraAppObjectId')) return undefined; + + return { + integrationType: 'teams', + code: 'resources_not_deleted', + action: { type: 'open_url', url: ENTRA_APPS_URL }, + details: { + appId: stringProperty(data, 'clientId') ?? '', + }, + }; + } +} diff --git a/packages/cli/src/modules/agents/integrations/platforms/teams/teams-credential-check.service.ts b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-credential-check.service.ts index dc6c2be9b5a..5d4de9bdb17 100644 --- a/packages/cli/src/modules/agents/integrations/platforms/teams/teams-credential-check.service.ts +++ b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-credential-check.service.ts @@ -1,8 +1,11 @@ -import type { TeamsCredentialCheck } from '@n8n/api-types'; +import type { TeamsCredentialCheck, TeamsFileAccessCheck } from '@n8n/api-types'; import { Logger } from '@n8n/backend-common'; import { OutboundHttp } from '@n8n/backend-network'; import type { User } from '@n8n/db'; import { Service } from '@n8n/di'; +import { isRecord } from '@n8n/utils/is-record'; +import { jsonParse } from 'n8n-workflow'; + import { AgentCredentialLookupService } from '../../agent-credential-lookup.service'; import { stringProperty } from '../../integration-helpers'; @@ -11,6 +14,10 @@ const TEAMS_CREDENTIAL_TYPE = 'microsoftEntraServicePrincipalApi'; /** The audience the Bot Framework connector issues tokens for. */ const BOT_FRAMEWORK_SCOPE = 'https://api.botframework.com/.default'; +/** Graph lists the app permissions it granted in the token's `roles` claim. */ +const GRAPH_SCOPE = 'https://graph.microsoft.com/.default'; +const FILES_READ_ALL = 'Files.Read.All'; + /** The only cloud the Teams channel reaches, matching what the channel enforces. */ const GLOBAL_GRAPH_API_BASE_URL = 'https://graph.microsoft.com'; @@ -57,37 +64,12 @@ export class TeamsCredentialCheckService { return { status: 'failed', reason: 'cloud' }; } - // Trimmed the way the channel trims them, so the check does not refuse a - // credential that would actually work. - const tenantId = stringProperty(data, 'tenantId')?.trim(); - const clientId = stringProperty(data, 'clientId')?.trim(); - const clientSecret = stringProperty(data, 'clientSecret')?.trim(); - if (!tenantId || !clientId || !clientSecret) { - return { status: 'failed', reason: 'incomplete' }; - } + const secret = clientSecretOf(data); + if (!secret) return { status: 'failed', reason: 'incomplete' }; try { - const response = await this.outboundHttp - // Fixed public vendor host, not user-controllable. - .requests({ useDefaultSsrfPolicy: 'unsafe' }) - .request({ - method: 'POST', - url: `https://login.microsoftonline.com/${encodeURIComponent(tenantId)}/oauth2/v2.0/token`, - headers: { 'content-type': 'application/x-www-form-urlencoded' }, - body: new URLSearchParams({ - grant_type: 'client_credentials', - client_id: clientId, - client_secret: clientSecret, - scope: BOT_FRAMEWORK_SCOPE, - }).toString(), - returnFullResponse: true, - ignoreHttpStatusErrors: true, - timeout: CHECK_TIMEOUT_MS, - }); - - const body: unknown = response.body; - const token = stringProperty(body, 'access_token'); - if (response.statusCode === 200 && token) return { status: 'ok' }; + const response = await this.requestToken(secret, BOT_FRAMEWORK_SCOPE); + if (response.token) return { status: 'ok' }; this.logger.debug('[TeamsCredentialCheck] Microsoft refused the credential', { statusCode: response.statusCode, @@ -98,4 +80,90 @@ export class TeamsCredentialCheckService { return { status: 'failed', reason: 'unreachable' }; } } + + /** + * Reads the grant from a fresh Graph token rather than asking Graph about + * the app, which would need a permission the bot does not hold. + */ + async checkFileAccess( + user: User, + projectId: string, + credentialId: string, + ): Promise { + const data = await this.credentialLookup.decryptForUser( + user, + projectId, + credentialId, + TEAMS_CREDENTIAL_TYPE, + ); + const secret = clientSecretOf(data); + if (!secret) return { status: 'unknown' }; + + try { + const { token } = await this.requestToken(secret, GRAPH_SCOPE); + if (!token) return { status: 'unknown' }; + return { status: rolesOf(token).includes(FILES_READ_ALL) ? 'approved' : 'notApproved' }; + } catch (error) { + this.logger.debug('[TeamsCredentialCheck] Could not read the file access grant', { error }); + return { status: 'unknown' }; + } + } + + private async requestToken( + { tenantId, clientId, clientSecret }: ClientSecret, + scope: string, + ): Promise<{ statusCode: number; token?: string }> { + const response = await this.outboundHttp + // Fixed public vendor host, not user-controllable. + .requests({ useDefaultSsrfPolicy: 'unsafe' }) + .request({ + method: 'POST', + url: `https://login.microsoftonline.com/${encodeURIComponent(tenantId)}/oauth2/v2.0/token`, + headers: { 'content-type': 'application/x-www-form-urlencoded' }, + body: new URLSearchParams({ + grant_type: 'client_credentials', + client_id: clientId, + client_secret: clientSecret, + scope, + }).toString(), + returnFullResponse: true, + ignoreHttpStatusErrors: true, + timeout: CHECK_TIMEOUT_MS, + }); + const body: unknown = response.body; + const token = stringProperty(body, 'access_token'); + return { + statusCode: response.statusCode, + token: response.statusCode === 200 ? token : undefined, + }; + } +} + +interface ClientSecret { + tenantId: string; + clientId: string; + clientSecret: string; +} + +/** Trimmed the way the channel trims them, so a working credential is not refused. */ +function clientSecretOf(data: unknown): ClientSecret | undefined { + const tenantId = stringProperty(data, 'tenantId')?.trim(); + const clientId = stringProperty(data, 'clientId')?.trim(); + const clientSecret = stringProperty(data, 'clientSecret')?.trim(); + return tenantId && clientId && clientSecret ? { tenantId, clientId, clientSecret } : undefined; +} + +/** + * The token comes straight from Microsoft over TLS, so its payload is read + * without verifying the signature. + */ +function rolesOf(token: string): string[] { + const payload: unknown = jsonParse( + Buffer.from(token.split('.')[1] ?? '', 'base64url').toString('utf8'), + { fallbackValue: {} }, + ); + const roles = isRecord(payload) ? payload.roles : undefined; + return Array.isArray(roles) + ? roles.filter((role): role is string => typeof role === 'string') + : []; } diff --git a/packages/cli/src/modules/agents/integrations/platforms/teams/teams-credential-notes.service.ts b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-credential-notes.service.ts new file mode 100644 index 00000000000..38098c61dab --- /dev/null +++ b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-credential-notes.service.ts @@ -0,0 +1,59 @@ +import { Logger } from '@n8n/backend-common'; +import { CredentialsFinderService } from '@n8n/backend-services'; +import type { User } from '@n8n/db'; +import { Service } from '@n8n/di'; + +import { CredentialsService } from '@/credentials/credentials.service'; + +import { BOT_CREDENTIAL_TYPE } from './teams-entra-provisioning.service'; +import { stringProperty } from '../../integration-helpers'; + +/** + * Keeps what n8n did with the channel's Teams app on the channel credential, + * the only record that outlives the dialog. Each note is a convenience, so a + * failed write is logged and never fails the action it describes. + */ +@Service() +export class TeamsCredentialNotesService { + constructor( + private readonly credentialsFinderService: CredentialsFinderService, + private readonly credentialsService: CredentialsService, + private readonly logger: Logger, + ) {} + + async write(user: User, credentialId: string, notes: Record): Promise { + try { + const credential = await this.credentialsFinderService.findCredentialForUser( + credentialId, + user, + ['credential:update'], + ); + if (credential?.type !== BOT_CREDENTIAL_TYPE) return; + // Raw: a redacted read written back would store the blanking sentinel. + const current = await this.credentialsService.decrypt(credential, true); + // Decrypt answers `{}` when it fails, and writing that back would erase the secret. + if (!stringProperty(current, 'clientId')) return; + if (Object.entries(notes).every(([key, value]) => current[key] === value)) return; + + const updated = { ...current, ...notes }; + const encrypted = await this.credentialsService.createEncryptedData({ + id: credential.id, + name: credential.name, + type: credential.type, + data: updated, + }); + await this.credentialsService.update( + credential.id, + encrypted, + { kind: 'user', user }, + updated, + ); + } catch (error) { + this.logger.warn('[Teams] Could not write a note on the channel credential', { + credentialId, + notes: Object.keys(notes), + error: error instanceof Error ? error.message : String(error), + }); + } + } +} diff --git a/packages/cli/src/modules/agents/integrations/platforms/teams/teams-entra-provisioning.service.ts b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-entra-provisioning.service.ts new file mode 100644 index 00000000000..cf7d284dc17 --- /dev/null +++ b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-entra-provisioning.service.ts @@ -0,0 +1,566 @@ +import type { TeamsProvisionedAppSummary } from '@n8n/api-types'; +import type { CredentialsEntity, User } from '@n8n/db'; +import { Service } from '@n8n/di'; +import { isRecord } from '@n8n/utils/is-record'; +import { OperationalError, UserError } from 'n8n-workflow'; +import { withTeamsFailure } from './teams-setup-telemetry.service'; + +import { CredentialsFinderService, UrlService } from '@n8n/backend-services'; +import { CredentialsService } from '@/credentials/credentials.service'; +import { BadRequestError } from '@n8n/errors'; + +import { adminConsentRedirectUri, adminConsentUrl } from './teams-admin-consent'; +import { graphErrorCode, TeamsGraphService } from './teams-graph.service'; +import { TEAMS_MANAGER_CREDENTIAL_TYPE } from './teams-managed-setup.service'; +import { GRAPH_RESOURCE, TeamsManagerTokenService } from './teams-manager-token.service'; +import { sanitiseAppName, stringProperty } from '../../integration-helpers'; + +export const BOT_CREDENTIAL_TYPE = 'microsoftEntraServicePrincipalApi'; + +/** Replaced before it lapses, so a channel does not stop signing mid-life. */ +const SECRET_RENEW_BEFORE_MS = 7 * 24 * 60 * 60 * 1000; + +/** The secret a previous run stored, when it has enough life left to keep. */ +function usableSecret( + data: Record, +): { value: string; expiresAt: string } | undefined { + const value = stringProperty(data, 'clientSecret'); + const expiresAt = stringProperty(data, 'secretExpiresAt'); + if (!value || !expiresAt) return undefined; + + const expiry = Date.parse(expiresAt); + if (Number.isNaN(expiry) || expiry - Date.now() < SECRET_RENEW_BEFORE_MS) return undefined; + return { value, expiresAt }; +} +const GRAPH_APP_ID = '00000003-0000-0000-c000-000000000000'; +const FILES_READ_ALL_ROLE = { id: '01d4889c-1287-42c6-ac1f-5d1e02578ef6', type: 'Role' }; + +function withFileAccess(requiredResourceAccess: unknown): unknown[] { + const entries: unknown[] = Array.isArray(requiredResourceAccess) ? requiredResourceAccess : []; + const graph = entries.find((entry) => isRecord(entry) && entry.resourceAppId === GRAPH_APP_ID); + const roles: unknown[] = + isRecord(graph) && Array.isArray(graph.resourceAccess) ? graph.resourceAccess : []; + if (roles.some((role) => isRecord(role) && role.id === FILES_READ_ALL_ROLE.id)) return entries; + return [ + ...entries.filter((entry) => entry !== graph), + { resourceAppId: GRAPH_APP_ID, resourceAccess: [...roles, FILES_READ_ALL_ROLE] }, + ]; +} + +const ENTRA_APP_URL = + 'https://entra.microsoft.com/#view/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/~/Overview/appId'; + +/** + * Tenants cap how long a client secret may live, and the cap varies. Ask for + * the longest first and step down, so a tenant with a strict policy still gets + * a secret rather than an error. + */ +const SECRET_LIFETIMES_MONTHS = [24, 12, 6, 3] as const; + +/** + * Prefix for the client-chosen alternate key the app is found by. No whitespace: + * Entra rejects a tag containing any, and the same string is used for both. + */ +const UNIQUE_NAME_PREFIX = 'n8n-agent-'; + +/** OData closes a string literal on a quote, and escapes one by doubling it. */ +const odataLiteral = (value: string) => value.replace(/'/g, "''"); + +/** Entra refuses a display name longer than this. */ +const APP_NAME_MAX = 120; + +export interface ProvisionEntraAppOptions { + user: User; + projectId: string; + agentId: string; + agentName: string; + managerCredentialId: string; +} + +interface CreatedApp { + objectId: string; + appId: string; + displayName: string; +} + +@Service() +export class TeamsEntraProvisioningService { + constructor( + private readonly graph: TeamsGraphService, + private readonly tokens: TeamsManagerTokenService, + private readonly credentialsService: CredentialsService, + private readonly credentialsFinderService: CredentialsFinderService, + private readonly urlService: UrlService, + ) {} + + /** + * Registers the customer's own Entra app and writes the channel credential + * from the values it just created, so the user never handles a secret. + * + * Running twice reuses the app registered the first time and only mints a + * fresh secret, rather than leaving a second registration behind. + */ + async provision(options: ProvisionEntraAppOptions): Promise { + const manager = await this.managerCredential(options); + const token = await this.tokens.acquire(manager, GRAPH_RESOURCE); + const tenant = await this.readTenant(token); + await this.rememberTenant(options.user, manager, tenant); + + const existing = await this.findProvisionedCredential(options); + // The registration is always resolved by the unique name n8n derives from + // the agent, which the upsert owns: it returns the app this agent already + // has, and makes one when the tenant no longer carries it. What a + // credential stores is a shortcut to the secret, never the address of the + // app the setup then writes to. + const app = await this.createApp(token, options.agentId, options.agentName); + + // Only when there is not already one to use: every mint is a write in the + // customer's directory, and Entra caps how many an app may hold. A secret + // kept for some other registration does not open this one, so it is reused + // only where the credential and the upsert name the same app. + const secret = + (existing?.objectId === app.objectId ? existing.secret : undefined) ?? + (await this.addSecret(token, app.objectId)); + // Harmless when one is already there, and an app picked up from an earlier + // run may have lost its principal. + await this.createServicePrincipal(token, app.appId); + + const redirectUri = adminConsentRedirectUri(this.urlService.getInstanceBaseUrl(), options); + const fileAccessDeclared = await this.declareFileAccess(token, app.objectId, redirectUri); + + const credentialId = await this.writeBotCredential({ + options, + app, + secret, + tenantId: tenant.tenantId, + existingCredential: existing?.credential, + }); + + return { + credentialId, + appId: app.appId, + appName: app.displayName, + organizationName: tenant.organizationName, + entraAppUrl: `${ENTRA_APP_URL}/${app.appId}`, + fileAccessConsentUrl: + fileAccessDeclared && redirectUri + ? adminConsentUrl(tenant.tenantId, app.appId, redirectUri) + : null, + secretExpiresAt: secret.expiresAt, + }; + } + + /** + * `credential:use`, not `credential:read`: the setup acts as this sign-in -- + * it registers an application in the directory and mints a secret for it. + * Reading is the rung that sees a credential, and seeing one is not standing + * to act with it. + */ + private async managerCredential(options: ProvisionEntraAppOptions): Promise { + const credential = await this.credentialsFinderService.findCredentialForUser( + options.managerCredentialId, + options.user, + ['credential:use'], + ); + if (!credential || credential.type !== TEAMS_MANAGER_CREDENTIAL_TYPE) { + throw withTeamsFailure( + new BadRequestError('Sign in with Microsoft before creating the Teams app.'), + 'not_signed_in', + ); + } + return credential; + } + + /** + * The directory behind the sign-in: the tenant ID the channel credential + * needs, and the organisation name the setup shows back. + */ + private async readTenant( + token: string, + ): Promise<{ tenantId: string; organizationName: string | null }> { + const organization = await this.graph.request( + token, + 'GET', + '/organization?$select=id,displayName', + ); + // Graph hands the status back rather than throwing, so a refusal would + // otherwise read as an empty directory and be blamed on the account type. + if (!organization.ok) { + throw new OperationalError('Could not read the organisation this account belongs to.'); + } + const first = isRecord(organization.body) + ? (organization.body.value as unknown[] | undefined)?.[0] + : undefined; + const tenantId = stringProperty(first, 'id'); + if (!tenantId) { + // A personal Microsoft account has no directory behind it. + throw withTeamsFailure( + new UserError('Sign in with a work or school account. A personal account cannot be used.'), + 'personal_account', + ); + } + + return { tenantId, organizationName: stringProperty(first, 'displayName') ?? null }; + } + + /** Lets the setup show which organisation the sign-in belongs to. */ + private async rememberTenant( + user: User, + manager: CredentialsEntity, + tenant: { tenantId: string; organizationName: string | null }, + ): Promise { + const rawData = await this.credentialsService.decrypt(manager, true); + const current = rawData as Record; + if ( + current.tenantId === tenant.tenantId && + current.organizationName === (tenant.organizationName ?? '') + ) { + return; + } + + const updated = { + ...rawData, + tenantId: tenant.tenantId, + organizationName: tenant.organizationName ?? '', + }; + const encrypted = await this.credentialsService.createEncryptedData({ + id: manager.id, + name: manager.name, + type: manager.type, + data: updated, + }); + await this.credentialsService.update(manager.id, encrypted, { kind: 'user', user }, updated); + } + + /** + * Creates the app, or picks up the one an earlier run created for this agent. + * + * `uniqueName` is a client-chosen alternate key, and the upsert keyed on it is + * one atomic call: Microsoft either makes the app or hands back the existing + * one. Searching first and creating second would leave a window in which two + * runs both decide to create, and losing the n8n credential would strand the + * old registration in the customer's directory. + */ + private async createApp(token: string, agentId: string, agentName: string): Promise { + const displayName = sanitiseAppName( + `${agentName || 'n8n Agent'} (n8n)`, + APP_NAME_MAX, + 'n8n Agent (n8n)', + ); + const uniqueName = `${UNIQUE_NAME_PREFIX}${agentId}`; + + const response = await this.graph.request( + token, + 'PATCH', + `/applications(uniqueName='${encodeURIComponent(odataLiteral(uniqueName))}')`, + { + displayName, + // Microsoft no longer accepts new multi-tenant bots, and the app backs + // one, so the registration is single tenant to match. + signInAudience: 'AzureADMyOrg', + // Not how the app is found — that is `uniqueName` — but it is what + // someone sees in the Entra portal when they ask what made this. + tags: [uniqueName], + }, + { Prefer: 'create-if-missing' }, + ); + + if (!response.ok) { + throw this.registrationError(response.statusCode, graphErrorCode(response.body)); + } + + // A create answers 201 with the app; an update answers 204 with nothing, so + // the identifiers have to be read back. + const objectId = stringProperty(response.body, 'id'); + const appId = stringProperty(response.body, 'appId'); + if (objectId && appId) return { objectId, appId, displayName }; + + return await this.findAppByUniqueName(token, uniqueName, displayName); + } + + private async findAppByUniqueName( + token: string, + uniqueName: string, + displayName: string, + ): Promise { + const query = new URLSearchParams({ + $filter: `uniqueName eq '${odataLiteral(uniqueName)}'`, + $select: 'id,appId,displayName', + }); + const response = await this.graph.request(token, 'GET', `/applications?${query.toString()}`); + + if (!response.ok) { + // Otherwise a refusal reads as Microsoft having made the app and then + // declined to name it, which is a different problem entirely. + throw this.registrationError(response.statusCode, graphErrorCode(response.body)); + } + + const value = isRecord(response.body) ? response.body.value : undefined; + const first = Array.isArray(value) ? value[0] : undefined; + const objectId = stringProperty(first, 'id'); + const appId = stringProperty(first, 'appId'); + if (!objectId || !appId) { + throw new OperationalError('Microsoft updated the app but would not say which one.'); + } + return { objectId, appId, displayName: stringProperty(first, 'displayName') ?? displayName }; + } + + /** + * This sign-in cannot grant app permissions, only declare them, so the setup + * links an administrator to the consent screen. Merges into what the app has: + * an administrator may have added permissions or addresses of their own. A + * failure leaves the setup working; the link then falls back to the app in Entra. + */ + private async declareFileAccess( + token: string, + objectId: string, + redirectUri: string | undefined, + ): Promise { + try { + return await this.mergeFileAccess(token, objectId, redirectUri); + } catch { + return false; + } + } + + private async mergeFileAccess( + token: string, + objectId: string, + redirectUri: string | undefined, + ): Promise { + const current = await this.graph.request( + token, + 'GET', + `/applications/${objectId}?$select=requiredResourceAccess,web`, + ); + if (!current.ok) return false; + const app = isRecord(current.body) ? current.body : {}; + const web = isRecord(app.web) ? app.web : {}; + const redirectUris: unknown[] = Array.isArray(web.redirectUris) ? web.redirectUris : []; + + const response = await this.graph.request(token, 'PATCH', `/applications/${objectId}`, { + requiredResourceAccess: withFileAccess(app.requiredResourceAccess), + ...(redirectUri && !redirectUris.includes(redirectUri) + ? { web: { redirectUris: [...redirectUris, redirectUri] } } + : {}), + }); + return response.ok; + } + + /** `undefined` when the app is gone from the tenant, so the caller remakes it. */ + /** + * Removes only secrets whose own expiry has passed. A live one may belong to + * another instance running the same agent, and Entra caps how many an app + * may hold -- so the dead ones are cleared and nothing else is touched. + */ + private async dropExpiredSecrets(token: string, objectId: string): Promise { + const response = await this.graph.request(token, 'GET', `/applications/${objectId}`); + if (!response.ok) return; + + const credentials = isRecord(response.body) ? response.body.passwordCredentials : undefined; + if (!Array.isArray(credentials)) return; + + const now = Date.now(); + for (const credential of credentials) { + const keyId = stringProperty(credential, 'keyId'); + const endDateTime = stringProperty(credential, 'endDateTime'); + if (!keyId || !endDateTime) continue; + const expiry = Date.parse(endDateTime); + if (Number.isNaN(expiry) || expiry > now) continue; + // Best effort: a secret we cannot remove is not a reason to fail a setup. + await this.graph.request(token, 'POST', `/applications/${objectId}/removePassword`, { + keyId, + }); + } + } + + /** + * Steps down through the lifetimes until the tenant accepts one. A tenant + * that forbids secrets outright rejects every length, and the user is sent + * to the manual setup rather than left with a half-made app. + */ + private async addSecret( + token: string, + objectId: string, + ): Promise<{ value: string; expiresAt: string }> { + await this.dropExpiredSecrets(token, objectId); + let lastCode: string | undefined; + + for (const months of SECRET_LIFETIMES_MONTHS) { + const endDateTime = new Date(); + endDateTime.setMonth(endDateTime.getMonth() + months); + + const response = await this.graph.request( + token, + 'POST', + `/applications/${objectId}/addPassword`, + { + passwordCredential: { + displayName: 'n8n agent channel', + endDateTime: endDateTime.toISOString(), + }, + }, + ); + + if (response.ok) { + const value = stringProperty(response.body, 'secretText'); + if (!value) { + throw new OperationalError('Microsoft created a secret but did not return it.'); + } + return { + value, + expiresAt: stringProperty(response.body, 'endDateTime') ?? endDateTime.toISOString(), + }; + } + lastCode = graphErrorCode(response.body); + } + + throw withTeamsFailure( + new UserError( + lastCode === 'Authorization_RequestDenied' + ? 'This organisation does not allow n8n to add a client secret. Use the manual setup.' + : 'This organisation refused every client secret lifetime n8n offered. Use the manual setup.', + ), + 'secrets_refused', + ); + } + + /** Without a service principal the app exists but cannot sign in to the tenant. */ + private async createServicePrincipal(token: string, appId: string): Promise { + const response = await this.graph.request(token, 'POST', '/servicePrincipals', { appId }); + // A principal already present is the desired end state, not a failure. + if ( + !response.ok && + graphErrorCode(response.body) !== 'Request_MultipleObjectsWithSameKeyValue' + ) { + throw new OperationalError('Could not finish registering the app in this organisation.'); + } + } + + private registrationError(statusCode: number, code: string | undefined): Error { + if (statusCode === 403 || code === 'Authorization_RequestDenied') { + return withTeamsFailure( + new UserError( + 'This account is not allowed to register applications in the organisation. Ask an administrator, or use the manual setup.', + ), + 'cannot_register_apps', + ); + } + return new OperationalError('Microsoft refused to register the app. Try again.'); + } + + /** + * Finds the credential a previous run of this agent's setup created, so a + * second run updates it rather than registering a second app. + */ + private async findProvisionedCredential(options: ProvisionEntraAppOptions): Promise< + | { + credential: CredentialsEntity; + objectId: string; + secret?: { value: string; expiresAt: string }; + } + | undefined + > { + const usable = await this.credentialsService.getCredentialsAUserCanUseInAWorkflow( + options.user, + { projectId: options.projectId }, + ); + + for (const candidate of usable) { + if (candidate.type !== BOT_CREDENTIAL_TYPE) continue; + const credential = await this.credentialsFinderService.findCredentialForUser( + candidate.id, + options.user, + ['credential:read'], + ); + if (!credential) continue; + + const data = await this.credentialsService.decrypt(credential, true); + const objectId = stringProperty(data, 'entraAppObjectId'); + if (objectId && stringProperty(data, 'provisionedForAgentId') === options.agentId) { + return { credential, objectId, secret: usableSecret(data) }; + } + } + return undefined; + } + + private async writeBotCredential(input: { + options: ProvisionEntraAppOptions; + app: CreatedApp; + secret: { value: string; expiresAt: string }; + tenantId: string; + existingCredential?: CredentialsEntity; + }): Promise { + // Anything already on the credential is kept. The publish records what it + // put in the catalogue here, and that note is the only answer `getState` + // has during the day Microsoft can take to list the app -- rebuilding the + // data from scratch on a re-run would throw it away. + // Raw: the default redacts every password field, and this data is written + // straight back -- so a redacted read would store the blanking sentinel + // over whatever it did not overwrite. + const existingData = input.existingCredential + ? ((await this.credentialsService.decrypt(input.existingCredential, true)) as Record< + string, + unknown + >) + : {}; + + // The publish note answers for one app in one directory. A re-run that + // lands on either a different tenant or a different registration would + // otherwise carry it across, and `getState` would report a listing the + // new tenant has never seen -- suppressing the publish that is due. + const movedIdentity = + (existingData.tenantId !== undefined && existingData.tenantId !== input.tenantId) || + (existingData.clientId !== undefined && existingData.clientId !== input.app.appId); + if (movedIdentity) { + delete existingData.publishedTeamsAppId; + delete existingData.publishedTeamsAppState; + delete existingData.publishedTeamsAppAt; + // The bot signs for the app it was made with, so it does not move either. + delete existingData.azureBotName; + delete existingData.azureSubscriptionId; + // The fingerprint stays: it describes the app Teams still holds, which + // names the old bot, so the settings can say it needs installing again. + } + + const data = { + ...existingData, + tenantId: input.tenantId, + clientId: input.app.appId, + clientSecret: input.secret.value, + // Provenance, so a re-run finds this app and the settings view can show + // when the secret runs out and offer to renew it. + entraAppObjectId: input.app.objectId, + provisionedForAgentId: input.options.agentId, + managerCredentialId: input.options.managerCredentialId, + secretExpiresAt: input.secret.expiresAt, + }; + + if (input.existingCredential) { + const encrypted = await this.credentialsService.createEncryptedData({ + id: input.existingCredential.id, + name: input.existingCredential.name, + type: BOT_CREDENTIAL_TYPE, + data, + }); + await this.credentialsService.update( + input.existingCredential.id, + encrypted, + { kind: 'user', user: input.options.user }, + data, + ); + return input.existingCredential.id; + } + + const created = await this.credentialsService.createUnmanagedCredential( + { + name: input.app.displayName, + type: BOT_CREDENTIAL_TYPE, + data, + projectId: input.options.projectId, + }, + input.options.user, + ); + return created.id; + } +} diff --git a/packages/cli/src/modules/agents/integrations/platforms/teams/teams-graph.service.ts b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-graph.service.ts new file mode 100644 index 00000000000..87a9d83bec2 --- /dev/null +++ b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-graph.service.ts @@ -0,0 +1,160 @@ +import { Logger } from '@n8n/backend-common'; +import { OutboundHttp } from '@n8n/backend-network'; +import { Service } from '@n8n/di'; +import { isRecord } from '@n8n/utils/is-record'; +import { UnexpectedError } from 'n8n-workflow'; + +import { stringProperty } from '../../integration-helpers'; + +const GRAPH_BASE_URL = 'https://graph.microsoft.com/v1.0'; +const GRAPH_TIMEOUT_MS = 30_000; + +/** + * The bearer token is Microsoft's, so the request must not be able to leave + * Graph. A path is concatenated onto the base, and `..` segments walk out of + * `/v1.0` -- so the whole parsed URL is checked, and the parsed URL is what + * gets sent. + */ +function graphUrl(path: string): string { + let parsed: URL; + try { + parsed = new URL(`${GRAPH_BASE_URL}${path}`); + } catch { + throw new UnexpectedError( + 'Refusing to send a Microsoft Graph token to a path that is not a URL.', + ); + } + if (!parsed.href.startsWith(`${GRAPH_BASE_URL}/`)) { + throw new UnexpectedError('Refusing to send a Microsoft Graph token elsewhere.'); + } + return parsed.href; +} + +export interface GraphResponse { + statusCode: number; + body: unknown; + ok: boolean; +} + +/** + * The smallest Microsoft Graph client the setup needs. + * + * Callers read the status code themselves rather than being handed an + * exception, because the flow branches on what Graph refuses: a 404 on the app + * registration is how a deleted app is told from a failed read. + */ +@Service() +export class TeamsGraphService { + constructor( + private readonly outboundHttp: OutboundHttp, + private readonly logger: Logger, + ) {} + + async request( + accessToken: string, + method: 'GET' | 'POST' | 'PATCH' | 'DELETE', + path: string, + body?: unknown, + /** Extra request headers, for the few calls Graph gates behind one. */ + headers: Record = {}, + ): Promise { + const response = await this.outboundHttp + // Fixed public vendor host, not user-controllable. + .requests({ useDefaultSsrfPolicy: 'unsafe' }) + .request({ + method, + url: graphUrl(path), + headers: { + authorization: `Bearer ${accessToken}`, + 'content-type': 'application/json', + ...headers, + }, + body: body === undefined ? undefined : JSON.stringify(body), + returnFullResponse: true, + ignoreHttpStatusErrors: true, + timeout: GRAPH_TIMEOUT_MS, + }); + + const ok = response.statusCode >= 200 && response.statusCode < 300; + if (!ok) { + this.logger.debug('[TeamsGraph] Graph refused a call', { + method, + path, + statusCode: response.statusCode, + error: describeGraphError(response.body) ?? graphErrorCode(response.body), + }); + } + return { statusCode: response.statusCode, body: response.body, ok }; + } + + /** + * The app catalog takes the package as a raw zip rather than JSON, so the + * body is sent unencoded with the zip content type. + */ + async postZip(accessToken: string, path: string, archive: Buffer): Promise { + const response = await this.outboundHttp + // Fixed public vendor host, not user-controllable. + .requests({ useDefaultSsrfPolicy: 'unsafe' }) + .request({ + method: 'POST', + url: graphUrl(path), + headers: { + authorization: `Bearer ${accessToken}`, + 'content-type': 'application/zip', + }, + body: archive, + returnFullResponse: true, + ignoreHttpStatusErrors: true, + timeout: GRAPH_TIMEOUT_MS, + }); + + const ok = response.statusCode >= 200 && response.statusCode < 300; + if (!ok) { + // The outer code is generic for a rejected package; the reason is in the + // inner code and the message, which name the manifest field at fault. + this.logger.warn('[TeamsGraph] Graph refused the app package', { + path, + statusCode: response.statusCode, + error: describeGraphError(response.body) ?? graphErrorCode(response.body), + }); + } + return { statusCode: response.statusCode, body: response.body, ok }; + } +} + +/** Graph reports failures as `{ error: { code, message } }`. */ +export function graphErrorCode(body: unknown): string | undefined { + if (!isRecord(body)) return undefined; + const error = body.error; + return isRecord(error) ? stringProperty(error, 'code') : undefined; +} + +export function graphErrorMessage(body: unknown): string | undefined { + if (!isRecord(body)) return undefined; + const error = body.error; + return isRecord(error) ? stringProperty(error, 'message') : undefined; +} + +/** + * Graph puts the useful part of a rejected app package in `innerError.code` — + * `UnableToParseTeamsAppManifest` and its hundred-odd siblings — while the outer + * code stays generic. + */ +export function graphInnerErrorCode(body: unknown): string | undefined { + if (!isRecord(body)) return undefined; + const error = body.error; + if (!isRecord(error)) return undefined; + const inner = error.innerError; + return isRecord(inner) ? stringProperty(inner, 'code') : undefined; +} + +/** + * What Graph said, in one line, for a message a user can act on. A bare "try + * again" is useless when the cause is a named field in the app manifest. + */ +export function describeGraphError(body: unknown): string | undefined { + const parts = [graphInnerErrorCode(body) ?? graphErrorCode(body), graphErrorMessage(body)].filter( + (part): part is string => typeof part === 'string' && part.length > 0, + ); + return parts.length > 0 ? parts.join(': ') : undefined; +} diff --git a/packages/cli/src/modules/agents/integrations/platforms/teams/teams-integration.ts b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-integration.ts index fc8ef2beb95..726831ea5c0 100644 --- a/packages/cli/src/modules/agents/integrations/platforms/teams/teams-integration.ts +++ b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-integration.ts @@ -1,7 +1,12 @@ -import type { AgentIntegrationConfig, RichCardComponentType } from '@n8n/api-types'; +import type { + AgentIntegrationConfig, + AgentIntegrationDisconnectWarning, + RichCardComponentType, +} from '@n8n/api-types'; import { Logger } from '@n8n/backend-common'; -import { Service } from '@n8n/di'; +import { Container, Service } from '@n8n/di'; import { isRecord } from '@n8n/utils/is-record'; +import type { Attachment, Message, Thread } from 'chat'; import { UserError } from 'n8n-workflow'; import { AgentRepository } from '../../../repositories/agent.repository'; @@ -11,6 +16,7 @@ import { AgentChatIntegration, type AgentChannelPreconditionContext, type AgentChatIntegrationContext, + type AgentIntegrationRemovalContext, type BridgeExecutionContext, type BridgeMessageContextParams, type BridgeResumeExecutionContext, @@ -21,7 +27,9 @@ import { loadTeamsAdapter } from '../../esm-loader'; import { resolveIntegrationActionDefinitions } from '../../integration-tool-definitions'; import type { ReplyExpectation } from '../../integration-tool-types'; import { startTypingIndicator } from '../typing-indicator'; +import { TeamsCleanupService } from './teams-cleanup.service'; import { READ_PERMISSIONS } from './teams-manifest.service'; +import { fetchTeamsMessageFiles, graphHttpOf } from './teams-message-files'; /** Pinned so a stray TEAMS_API_URL env var cannot redirect proactive sends. */ const TEAMS_API_URL = 'https://smba.trafficmanager.net/teams'; @@ -96,17 +104,33 @@ const TENANT_ID_DOMAIN = * In a channel that subscription covers the one thread, because the thread id * carries the root message id. In a group chat it covers the whole chat. * - * Reading messages without a mention is a setup choice for each surface. The - * manifest carries `ChannelMessage.Read.Group` and `ChatMessage.Read.Chat` only - * when `readAllChannelMessages` and `readAllGroupMessages` are on. Teams grants + * The manifest carries `ChannelMessage.Read.Group` and `ChatMessage.Read.Chat` + * for each surface that is on, so files can be read through Graph. Teams grants * them when the app is added to a team or a chat, and they make Teams deliver - * every message instead of mentions alone. Each such message runs the agent - * with an optional reply, so the agent decides whether to speak. + * every message instead of mentions alone. Acting on a message without a + * mention is a setup choice for each surface: `readAllChannelMessages` and + * `readAllGroupMessages`. Each such message runs the agent with an optional + * reply, so the agent decides whether to speak. */ @Service() export class TeamsIntegration extends AgentChatIntegration { readonly type = 'teams'; + /** + * Deletes nothing. The app registration, the bot and the catalogued Teams app + * depend on each other, and colleagues may already have the app installed, so + * the user is told what is left rather than having it removed for them. + */ + async onRemove( + ctx: AgentIntegrationRemovalContext, + ): Promise { + return await Container.get(TeamsCleanupService).describeLeftovers({ + user: ctx.user, + projectId: ctx.projectId, + credentialId: ctx.credentialId, + }); + } + readonly credentialTypes = ['microsoftEntraServicePrincipalApi']; readonly displayLabel = 'Microsoft Teams'; @@ -217,6 +241,17 @@ export class TeamsIntegration extends AgentChatIntegration { return conversationTypeOf(message.raw) === 'personal' ? 'required' : 'optional'; } + async fetchInboundAttachments({ + thread, + message, + }: { + thread: Thread; + message: Message; + }): Promise { + const http = graphHttpOf(thread.adapter); + return http ? await fetchTeamsMessageFiles(http, message.raw) : []; + } + constructor( private readonly logger: Logger, private readonly agentRepository: AgentRepository, diff --git a/packages/cli/src/modules/agents/integrations/platforms/teams/teams-managed-setup.service.ts b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-managed-setup.service.ts new file mode 100644 index 00000000000..165284596bc --- /dev/null +++ b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-managed-setup.service.ts @@ -0,0 +1,228 @@ +import type { + CreateTeamsManagerCredentialResponse, + TeamsManagedSetupState, + TeamsManagerCredentialSummary, +} from '@n8n/api-types'; +import type { User } from '@n8n/db'; +import { Service } from '@n8n/di'; +import { isRecord } from '@n8n/utils/is-record'; +import type { ICredentialDataDecryptedObject } from 'n8n-workflow'; + +import { CredentialsFinderService } from '@n8n/backend-services'; +import { CredentialsService } from '@/credentials/credentials.service'; +import { CredentialsOverwrites } from '@/credentials-overwrites'; +import { OauthService, OauthVersion } from '@/oauth/oauth.service'; +import { BadRequestError } from '@n8n/errors'; + +import { stringProperty } from '../../integration-helpers'; + +export const TEAMS_MANAGER_CREDENTIAL_TYPE = 'microsoftTeamsManagerOAuth2Api'; + +/** + * `organizations` rather than `common`, because a personal account cannot grant + * organisation consent and `common` would offer it one. + */ +const ADMIN_CONSENT_URL = 'https://login.microsoftonline.com/organizations/v2.0/adminconsent'; +const DEFAULT_MANAGER_CREDENTIAL_NAME = 'Microsoft organization'; + +/** + * Scopes this flow cannot work without. A credential connected before the list + * changed still holds a valid token, so it is reported as needing a reconnect + * rather than being hidden -- the user keeps the credential and re-consents. + * + * Every entry must be one the credential actually asks for. A scope listed + * here and not requested at sign-in can never be granted, so the reconnect it + * demands would never clear and the setup would stay locked for everyone. + * `teams-manager-token.service.test.ts` holds the three lists to each other. + */ +export const REQUIRED_MANAGER_SCOPES = [ + 'https://graph.microsoft.com/Application.ReadWrite.All', + 'https://graph.microsoft.com/AppCatalog.ReadWrite.All', + 'https://graph.microsoft.com/AppCatalog.Submit', +] as const; + +export interface TeamsManagedSetupScope { + projectId: string; + agentId: string; + user: User; +} + +function childRecord( + record: Record, + key: string, +): Record | undefined { + const child = record[key]; + return isRecord(child) ? child : undefined; +} + +/** Entra returns granted scopes space-separated, and drops the resource prefix for some. */ +function grantedScopes(scope: string | undefined): Set { + if (!scope) return new Set(); + const granted = new Set(); + for (const entry of scope.split(' ')) { + if (!entry) continue; + granted.add(entry); + const short = entry.split('/').pop(); + if (short) granted.add(short); + } + return granted; +} + +function isMissingScope(granted: Set, required: string): boolean { + const short = required.split('/').pop(); + return !granted.has(required) && !(short !== undefined && granted.has(short)); +} + +/** + * The recommended ("managed") Teams setup: an n8n-owned multi-tenant Entra app, + * consented once by the customer's tenant admin, acting in their tenant. + * + * This service owns only the sign-in half — whether the flow is available at + * all, and which sign-ins the project already has. Provisioning rides on top of + * the credentials it hands back. + */ +@Service() +export class TeamsManagedSetupService { + constructor( + private readonly credentialsService: CredentialsService, + private readonly credentialsFinderService: CredentialsFinderService, + private readonly credentialsOverwrites: CredentialsOverwrites, + private readonly oauthService: OauthService, + ) {} + + /** + * Cloud supplies the manager app through credential overwrites. A + * self-hosted operator who supplies their own client ID and secret the same + * way gets the flow too; everyone else sees only the manual stepper. + */ + isSetupAvailable(): boolean { + const overwrite = this.credentialsOverwrites.getOverwrites(TEAMS_MANAGER_CREDENTIAL_TYPE); + return ( + typeof overwrite?.clientId === 'string' && + overwrite.clientId.trim().length > 0 && + typeof overwrite.clientSecret === 'string' && + overwrite.clientSecret.trim().length > 0 + ); + } + + assertSetupAvailable(): void { + if (!this.isSetupAvailable()) { + throw new BadRequestError('The recommended Microsoft Teams setup is not available here.'); + } + } + + /** + * One prompt that approves everything n8n needs, across both Microsoft Graph + * and Azure management. + * + * `/.default` asks for every permission on the app registration rather than a + * list, which is what makes it span both APIs — a sign-in cannot, because a + * code is redeemed for one resource at a time. An administrator does this once + * per organisation and nobody sees a consent screen afterwards. + */ + adminConsentUrl(): string | null { + const overwrite = this.credentialsOverwrites.getOverwrites(TEAMS_MANAGER_CREDENTIAL_TYPE); + const clientId = typeof overwrite?.clientId === 'string' ? overwrite.clientId.trim() : ''; + if (!clientId) return null; + + // No `state`. The grant lands on the tenant, not on anything n8n holds: + // the callback reads nothing from the query and only renders a page, so + // there is no n8n-side effect for a forged return to reach. Every step + // after this still runs on the user's own signed-in credential. + const query = new URLSearchParams({ + client_id: clientId, + scope: 'https://graph.microsoft.com/.default', + redirect_uri: `${this.oauthService.getBaseUrl(OauthVersion.V2)}/callback`, + }); + return `${ADMIN_CONSENT_URL}?${query.toString()}`; + } + + async getSetupState(options: TeamsManagedSetupScope): Promise { + if (!this.isSetupAvailable()) { + return { managedSetupAvailable: false, managerCredentials: [], adminConsentUrl: null }; + } + + const usable = await this.credentialsService.getCredentialsAUserCanUseInAWorkflow( + options.user, + { + projectId: options.projectId, + }, + ); + + const managerCredentials: TeamsManagerCredentialSummary[] = []; + for (const candidate of usable) { + if (candidate.type !== TEAMS_MANAGER_CREDENTIAL_TYPE) continue; + const credential = await this.credentialsFinderService.findCredentialForUser( + candidate.id, + options.user, + ['credential:read'], + ); + if (!credential) continue; + + const rawData = await this.credentialsService.decrypt(credential, true); + managerCredentials.push({ + id: credential.id, + name: credential.name, + ...this.summarizeGrant(rawData), + }); + } + + return { + managedSetupAvailable: true, + managerCredentials, + adminConsentUrl: this.adminConsentUrl(), + }; + } + + /** + * Creates the empty credential the OAuth round trip fills in. The frontend + * then drives the sign-in, exactly as the Slack manager credential does. + */ + async createManagerCredential( + options: TeamsManagedSetupScope, + ): Promise { + this.assertSetupAvailable(); + const credential = await this.credentialsService.createUnmanagedCredential( + { + name: DEFAULT_MANAGER_CREDENTIAL_NAME, + type: TEAMS_MANAGER_CREDENTIAL_TYPE, + data: {}, + projectId: options.projectId, + }, + options.user, + ); + return { + id: credential.id, + name: credential.name, + type: TEAMS_MANAGER_CREDENTIAL_TYPE, + isResolvable: false, + }; + } + + private summarizeGrant( + rawData: ICredentialDataDecryptedObject, + ): Pick< + TeamsManagerCredentialSummary, + 'connected' | 'reconnectRequired' | 'organizationName' | 'tenantId' + > { + const data = rawData as Record; + const tokenData = childRecord(data, 'oauthTokenData'); + const connected = typeof stringProperty(tokenData, 'access_token') === 'string'; + const granted = grantedScopes(stringProperty(tokenData, 'scope')); + // Every step redeems the refresh token rather than the access token it was + // issued beside. Without one the sign-in looks usable and fails on the + // first call, so it is a sign-in to redo. + const canRefresh = typeof stringProperty(tokenData, 'refresh_token') === 'string'; + + return { + connected, + reconnectRequired: + connected && + (!canRefresh || REQUIRED_MANAGER_SCOPES.some((scope) => isMissingScope(granted, scope))), + // Written by the provisioning step once it has read the tenant; absent + // until then, which is why both are nullable rather than empty strings. + organizationName: stringProperty(data, 'organizationName') ?? null, + tenantId: stringProperty(data, 'tenantId') ?? null, + }; + } +} diff --git a/packages/cli/src/modules/agents/integrations/platforms/teams/teams-manager-token.service.ts b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-manager-token.service.ts new file mode 100644 index 00000000000..e1f2a765e4d --- /dev/null +++ b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-manager-token.service.ts @@ -0,0 +1,253 @@ +import { OutboundHttp } from '@n8n/backend-network'; +import { Logger } from '@n8n/backend-common'; +import { type CredentialsEntity, CredentialsRepository } from '@n8n/db'; +import { Service } from '@n8n/di'; +import { isRecord } from '@n8n/utils/is-record'; +import type { ICredentialDataDecryptedObject } from 'n8n-workflow'; + +import { CredentialsService } from '@/credentials/credentials.service'; +import { CredentialsOverwrites } from '@/credentials-overwrites'; +import { BadRequestError } from '@n8n/errors'; +import { OperationalError } from 'n8n-workflow'; + +import { TEAMS_MANAGER_CREDENTIAL_TYPE } from './teams-managed-setup.service'; +import { withTeamsFailure } from './teams-setup-telemetry.service'; +import { stringProperty } from '../../integration-helpers'; + +// `organizations`, matching the sign-in: a personal account has no Teams +// organisation, so it is refused at the door rather than several steps in. +const TOKEN_ENDPOINT = 'https://login.microsoftonline.com/organizations/oauth2/v2.0/token'; +const TOKEN_TIMEOUT_MS = 30_000; + +export const GRAPH_RESOURCE = 'https://graph.microsoft.com'; +export const AZURE_RESOURCE = 'https://management.azure.com'; + +/** Entra issues one token per resource, so the caller says which one it needs. */ +export type ManagerResource = typeof GRAPH_RESOURCE | typeof AZURE_RESOURCE; + +/** Named for the user, who knows these as two Microsoft products, not two hosts. */ +function resourceName(resource: ManagerResource): string { + return resource === AZURE_RESOURCE ? 'Azure' : 'Microsoft Graph'; +} + +export const RESOURCE_SCOPES: Record = { + [GRAPH_RESOURCE]: [ + 'offline_access', + `${GRAPH_RESOURCE}/Application.ReadWrite.All`, + `${GRAPH_RESOURCE}/AppCatalog.ReadWrite.All`, + `${GRAPH_RESOURCE}/AppCatalog.Submit`, + `${GRAPH_RESOURCE}/User.Read`, + ].join(' '), + [AZURE_RESOURCE]: ['offline_access', `${AZURE_RESOURCE}/user_impersonation`].join(' '), +}; + +/** + * A refresh redeemed for one resource answers with that resource's scopes and + * no others. Recording them as they arrive shrinks the record of what the + * sign-in granted, and the setup then reads a working sign-in as incomplete and + * asks for another one, which the next call shrinks again. + * + * A scope that was really withdrawn is not hidden by this for long: the + * exchange that needs it fails, which is the honest signal. + */ +function mergeScopes(stored: string | undefined, granted: string): string { + const all = [...(stored ?? '').split(' '), ...granted.split(' ')].filter(Boolean); + return [...new Set(all)].join(' '); +} + +/** + * Turns the one Microsoft sign-in into the per-resource tokens the provisioning + * steps need. + * + * Entra issues an access token for a single resource, but a refresh token is + * bound to the user and the client rather than to a resource. So the sign-in + * consents to Graph and Azure together, and each call here redeems the stored + * refresh token for whichever resource it was asked for. + * + * A token request must never name scopes from two resources at once; Entra + * rejects that outright, which is why the scope strings are per resource. + */ +@Service() +export class TeamsManagerTokenService { + constructor( + private readonly credentialsService: CredentialsService, + private readonly credentialsRepository: CredentialsRepository, + private readonly credentialsOverwrites: CredentialsOverwrites, + private readonly outboundHttp: OutboundHttp, + private readonly logger: Logger, + ) {} + + /** + * One redemption at a time for a given credential. Entra invalidates the + * refresh token it was called with and answers with a new one, so two calls + * that overlap both redeem the same token: the slower one stores a token + * Microsoft has already retired, and the next call signs the user out. The + * install step polls while a publish may be running, so the overlap is + * ordinary rather than rare. + */ + private readonly inFlight = new Map>(); + + async acquire(credential: CredentialsEntity, resource: ManagerResource): Promise { + if (credential.type !== TEAMS_MANAGER_CREDENTIAL_TYPE) { + throw new BadRequestError('That credential is not a Microsoft setup sign-in.'); + } + + // Keyed on the credential, not the resource: every resource redeems the + // same refresh token, so a Graph call and an Azure call race just as two + // Graph calls would. + const running = this.inFlight.get(credential.id); + const next = running + ? running.then( + async () => await this.redeem(credential, resource), + async () => await this.redeem(credential, resource), + ) + : this.redeem(credential, resource); + + this.inFlight.set(credential.id, next); + next + .finally(() => { + if (this.inFlight.get(credential.id) === next) this.inFlight.delete(credential.id); + }) + .catch(() => {}); + return await next; + } + + private async redeem(credential: CredentialsEntity, resource: ManagerResource): Promise { + // Queueing alone is not enough: a caller that read its entity before the + // call ahead of it rotated the token still holds the spent one. The row is + // read again here so the queued call redeems what Entra last issued. + const current = + (await this.credentialsRepository.findOneBy({ id: credential.id })) ?? credential; + const rawData = await this.credentialsService.decrypt(current, true); + const tokenData = this.tokenDataOf(rawData); + const refreshToken = stringProperty(tokenData, 'refresh_token'); + if (!refreshToken) { + // The same wall `invalid_grant` names below, reached a step earlier, so + // telemetry counts it under one reason rather than two. + throw withTeamsFailure( + new BadRequestError('Sign in with Microsoft again to continue.'), + 'not_signed_in', + ); + } + + const client = this.clientCredentials(); + const response = await this.outboundHttp + // Fixed public vendor host, not user-controllable. + .requests({ useDefaultSsrfPolicy: 'unsafe' }) + .request({ + method: 'POST', + url: TOKEN_ENDPOINT, + headers: { 'content-type': 'application/x-www-form-urlencoded' }, + body: new URLSearchParams({ + grant_type: 'refresh_token', + refresh_token: refreshToken, + client_id: client.clientId, + client_secret: client.clientSecret, + scope: RESOURCE_SCOPES[resource], + }).toString(), + returnFullResponse: true, + ignoreHttpStatusErrors: true, + timeout: TOKEN_TIMEOUT_MS, + }); + + const body: unknown = response.body; + const accessToken = stringProperty(body, 'access_token'); + if (response.statusCode !== 200 || !accessToken) { + // The body carries the token on success, so it is never logged. + // `error` alone never says which of a dozen causes it was. The + // description carries the AADSTS code that names it, and the refusal + // body holds no token, so all of it is safe to log. + this.logger.debug('[TeamsManagerToken] Microsoft refused the refresh', { + statusCode: response.statusCode, + resource, + error: stringProperty(body, 'error'), + suberror: stringProperty(body, 'suberror'), + errorDescription: stringProperty(body, 'error_description'), + }); + // `invalid_grant` is what Entra answers once the stored consent no longer + // matches the app registration — which is exactly what changing its + // permissions does. It is not a transient failure; only a fresh sign-in + // clears it. + // + // It is refused for one resource at a time, and a sign-in that reaches + // Graph but not Azure is the common case: saying "no longer valid" of a + // sign-in that plainly works sends the user to fix the wrong thing. + // `invalid_grant` only clears with a fresh sign-in, so it is the user's + // to act on. Everything else may pass on a retry. + if (stringProperty(body, 'error') === 'invalid_grant') { + throw withTeamsFailure( + new BadRequestError( + `This Microsoft sign-in does not reach ${resourceName(resource)}. Sign in again, and make sure the organisation approved n8n for it.`, + ), + 'not_signed_in', + ); + } + throw new OperationalError( + `Microsoft would not issue a token for ${resourceName(resource)}. Sign in again and retry.`, + ); + } + + await this.persistRotatedRefreshToken(credential, rawData, tokenData, body); + return accessToken; + } + + /** + * Entra replaces the refresh token on every use, so the new one has to be + * stored or the next call signs the user out. + */ + private async persistRotatedRefreshToken( + credential: CredentialsEntity, + rawData: ICredentialDataDecryptedObject, + tokenData: Record, + body: unknown, + ): Promise { + const rotated = stringProperty(body, 'refresh_token'); + if (!rotated) return; + + const oauthTokenData: Record = { ...tokenData, refresh_token: rotated }; + const scope = stringProperty(body, 'scope'); + if (scope !== undefined) { + oauthTokenData.scope = mergeScopes(stringProperty(tokenData, 'scope'), scope); + } + + // Token data is an opaque provider blob. `oauth2-credential.controller` + // narrows it the same way when it stores the first grant. + const updated = { ...rawData, oauthTokenData } as ICredentialDataDecryptedObject; + const encrypted = await this.credentialsService.createEncryptedData({ + id: credential.id, + name: credential.name, + type: credential.type, + data: updated, + }); + // Entra hands back a new refresh token on every use, so this write is the + // integration keeping its own credential alive rather than anything the + // signed-in user asked for. + await this.credentialsService.update( + credential.id, + encrypted, + { kind: 'system', reason: 'integration' }, + updated, + ); + + // The caller still holds this entity, and `decrypt` reads the copy it is + // given. Leaving the spent token on it lets a later write put it back over + // the live one. + if (encrypted.data) credential.data = encrypted.data; + } + + private tokenDataOf(rawData: ICredentialDataDecryptedObject): Record { + const tokenData = (rawData as Record).oauthTokenData; + return isRecord(tokenData) ? tokenData : {}; + } + + private clientCredentials(): { clientId: string; clientSecret: string } { + const overwrite = this.credentialsOverwrites.getOverwrites(TEAMS_MANAGER_CREDENTIAL_TYPE); + const clientId = typeof overwrite?.clientId === 'string' ? overwrite.clientId.trim() : ''; + const clientSecret = + typeof overwrite?.clientSecret === 'string' ? overwrite.clientSecret.trim() : ''; + if (!clientId || !clientSecret) { + throw new BadRequestError('The recommended Microsoft Teams setup is not available here.'); + } + return { clientId, clientSecret }; + } +} diff --git a/packages/cli/src/modules/agents/integrations/platforms/teams/teams-manifest.service.ts b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-manifest.service.ts index 4af06a0cc16..4a0e197959b 100644 --- a/packages/cli/src/modules/agents/integrations/platforms/teams/teams-manifest.service.ts +++ b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-manifest.service.ts @@ -6,6 +6,7 @@ import { } from '@n8n/api-types'; import { Service } from '@n8n/di'; import { zipSync } from 'fflate'; +import { createHash } from 'node:crypto'; import { readFile } from 'node:fs/promises'; import { join } from 'node:path'; import { v5 as uuidv5 } from 'uuid'; @@ -57,10 +58,14 @@ export interface BuildTeamsManifestOptions { settings?: AgentTeamsIntegrationSettings; } +/** The placeholder Microsoft's own resource-specific consent examples carry. */ +const RSC_RESOURCE = 'https://RscBasedStoreApp'; + /** - * Teams delivers only @mentions in a shared conversation unless the app asks to - * read everything there. Each name is paired with the scope it depends on, so a - * permission cannot be emitted without its surface. `conversationType` is the + * Each surface asks to read its messages, because Teams leaves files out of a + * shared conversation's activity and they are read through Graph instead. The + * permission also makes Teams deliver every message there, not only @mentions; + * `setting` decides whether the agent acts on them. `conversationType` is the * surface as Teams reports it on an activity. */ export const READ_PERMISSIONS = [ @@ -123,7 +128,7 @@ export class TeamsManifestService { botId: options.botId, scopes: this.buildScopes(options.settings), isNotificationOnly: false, - supportsFiles: false, + supportsFiles: true, }, ], permissions: ['identity', 'messageTeamMembers'], @@ -132,6 +137,18 @@ export class TeamsManifestService { }; } + /** + * What Teams would show from this manifest, so two builds can be compared. + * The version is left out: it moves on every build without changing the app. + * The agent's icon is included ahead of the package carrying it. + */ + fingerprint(manifest: TeamsAgentAppManifest, icon?: unknown): string { + const { version: _version, ...content } = manifest; + return createHash('sha256') + .update(JSON.stringify({ content, icon: icon ?? null })) + .digest('hex'); + } + /** * A flat zip. A nested folder is the single most common reason the Teams * upload fails, so entries are added by name and never by directory. @@ -164,18 +181,22 @@ export class TeamsManifestService { /** * `webApplicationInfo` is required alongside resource-specific permissions, * so both appear together or neither does. + * + * `resource` does nothing in a resource-specific grant, but Microsoft answers + * with an error when it is missing, so it carries the placeholder their own + * examples use. */ private buildReadPermissions( botId: string, availability: BuildTeamsManifestOptions['settings'], ): Partial { const resourceSpecific = READ_PERMISSIONS.filter( - ({ setting, requires }) => availability?.[setting] && availability?.[requires], + ({ requires }) => availability?.[requires], ).map(({ name }) => ({ name, type: 'Application' as const })); if (resourceSpecific.length === 0) return {}; return { - webApplicationInfo: { id: botId }, + webApplicationInfo: { id: botId, resource: RSC_RESOURCE }, authorization: { permissions: { resourceSpecific } }, }; } diff --git a/packages/cli/src/modules/agents/integrations/platforms/teams/teams-message-files.ts b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-message-files.ts new file mode 100644 index 00000000000..ac2c2c2ac38 --- /dev/null +++ b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-message-files.ts @@ -0,0 +1,252 @@ +import { MAX_AGENT_CHAT_ATTACHMENT_SIZE_BYTES } from '@n8n/api-types'; +import { isRecord } from '@n8n/utils/is-record'; +import type { Attachment } from 'chat'; +import { OperationalError } from 'n8n-workflow'; + +import { InboundAttachmentAccessError } from '../../agent-chat-integration'; +import { stringProperty } from '../../integration-helpers'; + +const GRAPH_ORIGIN = 'https://graph.microsoft.com'; +const GRAPH_V1 = `${GRAPH_ORIGIN}/v1.0`; + +export interface GraphHttp { + get( + url: string, + config?: { responseType?: 'arraybuffer'; maxContentLength?: number }, + ): Promise<{ data: unknown }>; +} + +/** + * The adapter keeps its token-carrying Graph client on the protected `app`. + * The adapter version is pinned, so the shape is stable for that version. + */ +export function graphHttpOf(adapter: unknown): GraphHttp | undefined { + if (!isRecord(adapter) || !isRecord(adapter.app) || !isRecord(adapter.app.graph)) return; + const http: unknown = adapter.app.graph.http; + return isGraphHttp(http) ? http : undefined; +} + +function isGraphHttp(value: unknown): value is GraphHttp { + return isRecord(value) && typeof value.get === 'function'; +} + +/** Axios returns a Buffer on Node, an ArrayBuffer elsewhere. */ +function toBuffer(data: unknown): Buffer { + if (Buffer.isBuffer(data)) return data; + if (data instanceof ArrayBuffer) return Buffer.from(data); + throw new OperationalError('Microsoft Graph returned no file content'); +} + +/** The Graph token goes only to Graph, and only for content hosted on this message. */ +function isHostedOn(messagePath: string, src: string): boolean { + try { + const url = new URL(src); + const path = decodeURIComponent(url.pathname); + const hosted = decodeURIComponent(`/v1.0${messagePath}/hostedContents/`); + return url.origin === GRAPH_ORIGIN && path.startsWith(hosted) && !path.includes('/..'); + } catch { + return false; + } +} + +interface GraphMessagePaths { + message: string; + filesFolder?: string; +} + +/** + * The Graph paths of the message in a channel or group chat activity. A direct + * message carries its files on the activity, so it has none. + */ +export function graphMessagePaths(activity: unknown): GraphMessagePaths | undefined { + if (!isRecord(activity) || !isRecord(activity.conversation)) return; + const messageId = stringProperty(activity, 'id'); + const conversationId = stringProperty(activity.conversation, 'id'); + if (!messageId || !conversationId) return; + const enc = encodeURIComponent; + + const type = activity.conversation.conversationType; + if (type === 'groupChat') { + return { message: `/chats/${enc(conversationId)}/messages/${enc(messageId)}` }; + } + if (type !== 'channel' || !isRecord(activity.channelData)) return; + + const teamId = stringProperty(activity.channelData.team, 'aadGroupId'); + const channelId = stringProperty(activity.channelData.channel, 'id'); + if (!teamId || !channelId) return; + const rootId = /;messageid=([^;]+)/.exec(conversationId)?.[1] ?? messageId; + const channel = `/teams/${enc(teamId)}/channels/${enc(channelId)}`; + const root = `${channel}/messages/${enc(rootId)}`; + return { + message: rootId === messageId ? root : `${root}/replies/${enc(messageId)}`, + filesFolder: `${channel}/filesFolder`, + }; +} + +function statusOf(error: unknown): unknown { + return isRecord(error) && isRecord(error.response) ? error.response.status : undefined; +} + +/** + * Graph addresses a sharing URL as `u!` plus its unpadded base64url form. The + * docs list Files.ReadWrite.All for `/shares`, but Files.Read.All works. + */ +function shareIdOf(url: string): string { + return `u!${Buffer.from(url, 'utf8').toString('base64url')}`; +} + +const FILE_ACCESS_DENIED = + 'a Microsoft administrator has not allowed file access for this app yet. Ask them to grant admin consent for its Files.Read.All application permission in Microsoft Entra. After approval, it can take up to an hour to apply'; + +const MESSAGE_ACCESS_DENIED = + "Microsoft Teams has not let this app read messages here yet. Update the app in Teams with the latest package from the agent's Teams settings"; + +const FOREIGN_FILE = + "the file is not in this channel's files and the sender does not own it, so the agent does not read it"; + +interface DriveFolder { + driveId: string; + path: string; +} + +/** Graph may percent-encode a path, but never a name, so both sides are compared decoded. */ +function decodedPath(path: string): string { + try { + return decodeURIComponent(path); + } catch { + return path; + } +} + +/** Where Graph puts a drive item: its drive, and the path of its parent folder. */ +function locationOf(item: unknown): DriveFolder | undefined { + if (!isRecord(item)) return; + const driveId = stringProperty(item.parentReference, 'driveId'); + const path = stringProperty(item.parentReference, 'path'); + return driveId && path ? { driveId, path: decodedPath(path) } : undefined; +} + +function isInside(item: DriveFolder | undefined, folder: DriveFolder | undefined): boolean { + if (!item || !folder || item.driveId !== folder.driveId) return false; + return item.path === folder.path || item.path.startsWith(`${folder.path}/`); +} + +async function getOrExplain( + http: GraphHttp, + url: string, + accessDenied: string, + config?: Parameters[1], +): Promise { + try { + return (await http.get(url, config)).data; + } catch (error) { + if (statusOf(error) === 403) throw new InboundAttachmentAccessError(accessDenied); + throw error; + } +} + +const DOWNLOAD = { + responseType: 'arraybuffer', + maxContentLength: MAX_AGENT_CHAT_ATTACHMENT_SIZE_BYTES, +} as const; + +/** + * The app token reads every file in the tenant, but a message can reference + * any file. So only a file the conversation already holds is read: one in the + * channel's files folder, or one the sender owns and chose to share. The rest + * of the team's library can have stricter permissions than the channel. + */ +async function downloadSharedFile( + http: GraphHttp, + contentUrl: string, + channelFolder: () => Promise, + senderId: string | undefined, +): Promise { + const [item, folder] = await Promise.all([ + getOrExplain( + http, + `${GRAPH_V1}/shares/${shareIdOf(contentUrl)}/driveItem?$select=id,parentReference`, + FILE_ACCESS_DENIED, + ), + channelFolder(), + ]); + const itemId = stringProperty(item, 'id'); + const driveId = isRecord(item) ? stringProperty(item.parentReference, 'driveId') : undefined; + if (!itemId || !driveId) + throw new OperationalError('Microsoft Graph did not say where the file is'); + + const ownedBySender = async () => { + if (!senderId) return false; + const drive = await getOrExplain( + http, + `${GRAPH_V1}/drives/${encodeURIComponent(driveId)}?$select=owner`, + FILE_ACCESS_DENIED, + ); + return ( + isRecord(drive) && + isRecord(drive.owner) && + stringProperty(drive.owner.user, 'id') === senderId + ); + }; + if (!isInside(locationOf(item), folder) && !(await ownedBySender())) { + throw new InboundAttachmentAccessError(FOREIGN_FILE); + } + + const content = `${GRAPH_V1}/drives/${encodeURIComponent(driveId)}/items/${encodeURIComponent(itemId)}/content`; + return toBuffer(await getOrExplain(http, content, FILE_ACCESS_DENIED, DOWNLOAD)); +} + +/** + * Teams leaves files out of a channel or group chat activity, so they are read + * from the message through Graph. A shared file is a `reference` to SharePoint + * or OneDrive, and a pasted image is hosted content on the message itself. + */ +export async function fetchTeamsMessageFiles( + http: GraphHttp, + activity: unknown, +): Promise { + const paths = graphMessagePaths(activity); + if (!paths) return []; + const message = await getOrExplain(http, `${GRAPH_V1}${paths.message}`, MESSAGE_ACCESS_DENIED); + if (!isRecord(message)) return []; + const senderId = isRecord(message.from) ? stringProperty(message.from.user, 'id') : undefined; + let folder: Promise | undefined; + const channelFolder = async () => + await (folder ??= paths.filesFolder + ? getOrExplain( + http, + `${GRAPH_V1}${paths.filesFolder}?$select=name,parentReference`, + FILE_ACCESS_DENIED, + ).then((found) => { + const parent = locationOf(found); + const name = stringProperty(found, 'name'); + return parent && name ? { ...parent, path: `${parent.path}/${name}` } : undefined; + }) + : Promise.resolve(undefined)); + + const files: Attachment[] = []; + for (const attachment of Array.isArray(message.attachments) ? message.attachments : []) { + const contentUrl = stringProperty(attachment, 'contentUrl'); + if (stringProperty(attachment, 'contentType') !== 'reference' || !contentUrl) continue; + files.push({ + type: 'file', + name: stringProperty(attachment, 'name'), + url: contentUrl, + fetchData: async () => await downloadSharedFile(http, contentUrl, channelFolder, senderId), + }); + } + + // Hosted content needs only the message read permission, not Files.Read.All. + const body = stringProperty(message.body, 'content') ?? ''; + for (const [, src] of body.matchAll(/]+src="([^"]+)"/g)) { + if (!isHostedOn(paths.message, src)) continue; + files.push({ + type: 'image', + name: 'image', + url: src, + fetchData: async () => + toBuffer(await getOrExplain(http, src, MESSAGE_ACCESS_DENIED, DOWNLOAD)), + }); + } + return files; +} diff --git a/packages/cli/src/modules/agents/integrations/platforms/teams/teams-setup-telemetry.service.ts b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-setup-telemetry.service.ts new file mode 100644 index 00000000000..75f526c5865 --- /dev/null +++ b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-setup-telemetry.service.ts @@ -0,0 +1,103 @@ +import { Service } from '@n8n/di'; +import { TELEMETRY_EVENT } from '@n8n/telemetry'; +import { UserError } from 'n8n-workflow'; + +import { Telemetry } from '@/telemetry'; + +type Step = 'create_app' | 'create_bot' | 'install'; + +export interface TeamsSetupStepReport { + agentId: string; + projectId: string; + userId: string; + step: Step; + /** `manual` is the rung taken when the account reaches no subscription. */ + botRoute?: 'provisioned' | 'manual'; + /** + * Only the catalogue routes. A sideload finishes in the Teams client, where + * n8n cannot see it, so it reports no outcome at all. + */ + installRoute?: 'published' | 'submitted'; +} + +/** + * The walls the setup runs into, named at the point they are hit rather than + * recognised from the message afterwards. A message is never reported: + * Microsoft puts tenant and account detail in them, and matching on it couples + * the taxonomy to copy that gets reworded. + */ +export type TeamsSetupFailure = + | 'cannot_register_apps' + | 'personal_account' + | 'secrets_refused' + | 'no_contributor_role' + | 'provider_registering' + | 'endpoint_not_https' + | 'teams_channel_failed' + | 'not_signed_in'; + +const FAILURE_TAG = 'teamsSetupFailure'; + +/** Tags an error with the wall it represents, for `reasonFor` to read back. */ +export function withTeamsFailure(error: E, reason: TeamsSetupFailure): E { + // Writable, so an error that reaches a second tagging site is re-tagged + // rather than throwing on the way out. + Object.defineProperty(error, FAILURE_TAG, { + value: reason, + enumerable: false, + writable: true, + configurable: true, + }); + return error; +} + +/** + * Records how far the recommended Teams setup got, and where it stopped. + * + * The bot ladder exists because n8n can only create the bot when the tenant has + * an Azure subscription, and a Microsoft 365 tenant does not come with one. + * Which rung people land on is the question this answers. + */ +@Service() +export class TeamsSetupTelemetryService { + constructor(private readonly telemetry: Telemetry) {} + + succeeded(report: TeamsSetupStepReport): void { + this.track(report, 'succeeded'); + } + + failed(report: TeamsSetupStepReport, error: unknown): void { + this.track(report, 'failed', reasonFor(error)); + } + + /** Telemetry must never turn a working step into a failed request. */ + private track( + report: TeamsSetupStepReport, + outcome: 'succeeded' | 'failed', + reason?: string, + ): void { + try { + this.telemetry.track(TELEMETRY_EVENT.AGENTS.AGENT_TEAMS_SETUP_STEP, { + agent_id: report.agentId, + project_id: report.projectId, + user_id: report.userId, + step: report.step, + outcome, + ...(report.botRoute ? { bot_route: report.botRoute } : {}), + ...(report.installRoute ? { install_route: report.installRoute } : {}), + ...(reason ? { reason } : {}), + }); + } catch { + // Reporting a step must not fail the step. + } + } +} + +function reasonFor(error: unknown): string { + if (!(error instanceof Error)) return 'unknown'; + const tagged = (error as unknown as Record)[FAILURE_TAG]; + if (typeof tagged === 'string') return tagged; + // A UserError is something the user can act on, so the distinction is worth + // keeping even when the specific wall has no name of its own yet. + return error instanceof UserError ? 'refused' : 'unknown'; +} diff --git a/packages/cli/src/modules/agents/integrations/platforms/teams/teams-setup.service.ts b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-setup.service.ts index c5d42bf9c22..ca4f767e899 100644 --- a/packages/cli/src/modules/agents/integrations/platforms/teams/teams-setup.service.ts +++ b/packages/cli/src/modules/agents/integrations/platforms/teams/teams-setup.service.ts @@ -5,7 +5,9 @@ import { Service } from '@n8n/di'; import { BadRequestError, NotFoundError } from '@n8n/errors'; import { UrlService } from '@n8n/backend-services'; +import { adminConsentRedirectUri, adminConsentUrl } from './teams-admin-consent'; import { TeamsArmTemplateService } from './teams-arm-template.service'; +import { botResourceId } from './teams-bot-provisioning.service'; import { TeamsManifestService } from './teams-manifest.service'; import type { Agent } from '../../../entities/agent.entity'; import { AgentRepository } from '../../../repositories/agent.repository'; @@ -24,6 +26,12 @@ interface AgentScope { interface BotIdentity { clientId: string; tenantId: string; + /** Written by the recommended setup, so a hand-made credential lacks it. */ + provisionedForAgentId?: string; + azureBotName?: string; + azureSubscriptionId?: string; + /** The manifest n8n last handed over, as `TeamsManifestService.fingerprint` reads it. */ + teamsAppFingerprint?: string; } @Service() @@ -53,6 +61,8 @@ export class TeamsSetupService { credentialId ? this.credentialClaimedBy(agent.id, credentialId) : null, ]); + const provisionedByN8n = identity?.provisionedForAgentId === agent.id; + return { messagingEndpointUrl: this.messagingEndpointUrl(scope), botId: identity?.clientId ?? null, @@ -64,6 +74,10 @@ export class TeamsSetupService { ? this.armTemplateService.buildDeployUrl(scope.projectId, scope.agentId, credentialId) : null, credentialClaimedBy: claimedBy, + provisionedByN8n, + fileAccessConsentUrl: provisionedByN8n ? this.fileAccessConsentUrl(scope, identity) : null, + azureBot: provisionedByN8n ? this.azureBot(identity) : null, + appOutdated: this.appOutdated(agent, identity), ...this.defaultIdentity(agent.name), }; } @@ -78,7 +92,7 @@ export class TeamsSetupService { scope: AgentScope, selectedCredentialId?: string, selectedSettings?: AgentTeamsIntegrationSettings, - ): Promise { + ): Promise<{ archive: Buffer; fingerprint: string; credentialId: string }> { const agent = await this.getAgent(scope); const credentialId = selectedCredentialId ?? this.connectedCredentialId(agent); const identity = credentialId @@ -105,7 +119,7 @@ export class TeamsSetupService { ); } - return await this.manifestService.buildPackage({ + const options = { agentName: agent.name, agentId: agent.id, botId: identity.clientId, @@ -118,7 +132,15 @@ export class TeamsSetupService { // The open form wins over what is stored: during setup nothing is stored // yet, and in the settings view the fields sit above this button. settings: selectedSettings ?? this.teamsSettingsOf(agent), - }); + }; + return { + archive: await this.manifestService.buildPackage(options), + fingerprint: this.manifestService.fingerprint( + this.manifestService.buildManifest(options), + agent.schema?.personalisation, + ), + credentialId, + }; } /** @@ -182,6 +204,50 @@ export class TeamsSetupService { return { defaultDisplayName: displayName, defaultDescription: description }; } + /** The name the provisioned Entra app and Teams app are built from. */ + async agentNameFor(projectId: string, agentId: string): Promise { + const agent = await this.getAgent({ projectId, agentId }); + return agent.name; + } + + /** + * What the bot has to be created against: the Entra app it signs as, and + * where Teams should deliver to. Both are read here so the provisioned bot + * and the Deploy to Azure template agree on every value. + */ + async botIdentityFor( + user: User, + scope: AgentScope, + credentialId: string, + ): Promise<{ + clientId: string; + tenantId: string; + messagingEndpoint: string; + agentName: string; + }> { + const agent = await this.getAgent(scope); + const identity = await this.readIdentity(agent.projectId, credentialId, user); + if (!identity) { + throw new BadRequestError('Create the Teams app before deploying the bot.'); + } + + // An Azure bot carries one messaging endpoint. Creating one against a + // credential another agent holds re-points that agent's bot at this + // endpoint, so its messages would arrive here instead. + const claimedBy = await this.credentialClaimedBy(agent.id, credentialId); + if (claimedBy) { + throw new BadRequestError( + `This credential already backs the Teams channel of "${claimedBy}". Pick a different one.`, + ); + } + + return { + ...identity, + messagingEndpoint: this.messagingEndpointUrl(scope), + agentName: agent.name, + }; + } + private async getAgent(scope: AgentScope): Promise { const agent = await this.agentRepository.findByIdAndProjectId(scope.agentId, scope.projectId); if (!agent) throw new NotFoundError(`Agent "${scope.agentId}" not found`); @@ -221,7 +287,53 @@ export class TeamsSetupService { ); const clientId = stringProperty(data, 'clientId'); const tenantId = stringProperty(data, 'tenantId'); - return clientId && tenantId ? { clientId, tenantId } : null; + const provisionedForAgentId = stringProperty(data, 'provisionedForAgentId'); + return clientId && tenantId + ? { + clientId, + tenantId, + provisionedForAgentId, + azureBotName: stringProperty(data, 'azureBotName'), + azureSubscriptionId: stringProperty(data, 'azureSubscriptionId'), + teamsAppFingerprint: stringProperty(data, 'teamsAppFingerprint'), + } + : null; + } + + /** + * Whether the saved channel would build a different app than the one n8n last + * handed over, for example after the agent was renamed. n8n sees the download + * or the publish, not the upload in Teams, so this is as close as it gets. + */ + private appOutdated(agent: Agent, identity: BotIdentity | null): boolean { + if (!identity?.teamsAppFingerprint) return false; + const current = this.manifestService.buildManifest({ + agentName: agent.name, + agentId: agent.id, + botId: identity.clientId, + versionAt: agent.updatedAt, + settings: this.teamsSettingsOf(agent), + }); + return ( + this.manifestService.fingerprint(current, agent.schema?.personalisation) !== + identity.teamsAppFingerprint + ); + } + + private azureBot(identity: BotIdentity | null): TeamsAgentSetupState['azureBot'] { + if (!identity?.azureBotName || !identity.azureSubscriptionId) return null; + const resource = botResourceId(identity.azureSubscriptionId, identity.azureBotName); + return { + name: identity.azureBotName, + portalUrl: `https://portal.azure.com/#@${identity.tenantId}/resource${resource}/overview`, + }; + } + + private fileAccessConsentUrl(scope: AgentScope, identity: BotIdentity | null): string | null { + const redirectUri = adminConsentRedirectUri(this.urlService.getInstanceBaseUrl(), scope); + return identity && redirectUri + ? adminConsentUrl(identity.tenantId, identity.clientId, redirectUri) + : null; } private messagingEndpointUrl(scope: AgentScope): string { diff --git a/packages/cli/src/modules/agents/integrations/platforms/whatsapp/whatsapp-credential-check.service.ts b/packages/cli/src/modules/agents/integrations/platforms/whatsapp/whatsapp-credential-check.service.ts new file mode 100644 index 00000000000..99520444ad4 --- /dev/null +++ b/packages/cli/src/modules/agents/integrations/platforms/whatsapp/whatsapp-credential-check.service.ts @@ -0,0 +1,202 @@ +import type { WhatsAppBusinessProfile, WhatsAppCredentialCheck } from '@n8n/api-types'; +import { Logger } from '@n8n/backend-common'; +import { OutboundHttp } from '@n8n/backend-network'; +import { AgentsConfig } from '@n8n/config'; +import type { User } from '@n8n/db'; +import { Service } from '@n8n/di'; +import { NotFoundError } from '@n8n/errors'; +import { ensureError } from '@n8n/utils/errors/ensure-error'; +import { isRecord } from '@n8n/utils/is-record'; +import { sanitizeErrorDetail } from '@n8n/utils/redaction/sanitize-error-detail'; +import { createHmac } from 'node:crypto'; + +import { AgentCredentialLookupService } from '../../agent-credential-lookup.service'; +import { numberProperty, stringProperty } from '../../integration-helpers'; + +const WHATSAPP_CREDENTIAL_TYPE = 'whatsAppBotApi'; + +/** The version the pinned `@chat-adapter/whatsapp` sends to, so both see the same API. */ +const GRAPH_API_BASE_URL = 'https://graph.facebook.com/v25.0'; + +/** + * The token on the API Setup page lasts about 24 hours. A permanent system + * user token never expires, so anything that ends this soon will stop the + * channel within days of connecting it. + */ +const TEMPORARY_TOKEN_WINDOW_MS = 48 * 60 * 60 * 1000; + +/** The check gates a button, so a stalled request has to give up quickly. */ +const CHECK_TIMEOUT_MS = 30_000; + +const MAX_LOGGED_ERROR_LENGTH = 500; + +interface GraphResponse { + statusCode: number; + body: unknown; +} + +@Service() +export class WhatsAppCredentialCheckService { + constructor( + private readonly credentialLookup: AgentCredentialLookupService, + private readonly outboundHttp: OutboundHttp, + private readonly logger: Logger, + private readonly agentsConfig: AgentsConfig, + ) {} + + /** + * Calls Meta with the credential exactly as the channel will. Each request + * carries an `appsecret_proof`, which Meta rejects when the app secret does + * not belong to the token's app, so a wrong secret fails here and not on the + * first inbound webhook. + */ + async check( + user: User, + projectId: string, + credentialId: string, + ): Promise { + // Scoped to the caller: this sends the token to Meta, and naming a + // credential is not the same as being allowed to use it. + const data = await this.credentialLookup.decryptForUser( + user, + projectId, + credentialId, + WHATSAPP_CREDENTIAL_TYPE, + ); + // Same answer as connecting the channel gives. Reporting this as + // `incomplete` would send the user to fix fields that are not empty. + if (!data) throw new NotFoundError(`WhatsApp credential "${credentialId}" not found`); + + // Trimmed the way the channel trims them. + const accessToken = stringProperty(data, 'accessToken')?.trim(); + const phoneNumberId = stringProperty(data, 'phoneNumberId')?.trim(); + const businessAccountId = stringProperty(data, 'businessAccountId')?.trim(); + const appSecret = stringProperty(data, 'appSecret')?.trim(); + if (!accessToken || !phoneNumberId || !businessAccountId || !appSecret) { + return { status: 'failed', reason: 'incomplete' }; + } + + const proof = createHmac('sha256', appSecret).update(accessToken).digest('hex'); + const get = async (path: string, qs: Record = {}) => + await this.get(path, accessToken, { ...qs, appsecret_proof: proof }); + + try { + const phone = await get(`/${encodeURIComponent(phoneNumberId)}`, { + fields: 'display_phone_number,verified_name', + }); + if (phone.statusCode !== 200) return this.refused('phone number', phone); + + const [expiresAt, accountNumbers, profile] = await Promise.all([ + this.tokenExpiry(accessToken, proof), + get(`/${encodeURIComponent(businessAccountId)}/phone_numbers`, { + fields: 'id', + limit: '100', + }), + get(`/${encodeURIComponent(phoneNumberId)}/whatsapp_business_profile`, { + fields: 'about,description,profile_picture_url', + }).catch(() => undefined), + ]); + + if ( + expiresAt !== undefined && + expiresAt - Date.now() < TEMPORARY_TOKEN_WINDOW_MS && + !this.agentsConfig.whatsAppAllowTemporaryToken + ) { + return { status: 'failed', reason: 'temporaryToken' }; + } + + if (accountNumbers.statusCode !== 200) { + return this.refused('business account', accountNumbers); + } + if (!listedIds(accountNumbers.body).includes(phoneNumberId)) { + this.logger.debug('[WhatsAppCredentialCheck] Phone number is not in the business account'); + return { status: 'failed', reason: 'mismatch' }; + } + + return { + status: 'ok', + profile: toProfile(phone.body, profile?.statusCode === 200 ? profile.body : undefined), + }; + } catch (error) { + // Only the cleaned message: the raw error can carry the request config, + // which holds the access token and the `appsecret_proof`. + this.logger.debug('[WhatsAppCredentialCheck] Could not reach Meta', { + error: sanitizeErrorDetail(ensureError(error).message, MAX_LOGGED_ERROR_LENGTH), + }); + return { status: 'failed', reason: 'unreachable' }; + } + } + + /** + * When the token expires, in epoch milliseconds, or `undefined` when it never + * does or Meta does not say. Best effort: a token that cannot inspect itself + * still passes, because the other requests already prove it works. + */ + private async tokenExpiry(accessToken: string, proof: string): Promise { + try { + const response = await this.get('/debug_token', accessToken, { + input_token: accessToken, + appsecret_proof: proof, + }); + const data = isRecord(response.body) ? response.body.data : undefined; + const expiresAt = numberProperty(data, 'expires_at'); + // Meta reports 0 for a token that never expires. + return expiresAt ? expiresAt * 1000 : undefined; + } catch { + return undefined; + } + } + + private refused(target: string, response: GraphResponse): WhatsAppCredentialCheck { + // Meta's own outage is not evidence that the credential is wrong. + if (response.statusCode >= 500) return { status: 'failed', reason: 'unreachable' }; + const error = isRecord(response.body) ? response.body.error : undefined; + this.logger.debug(`[WhatsAppCredentialCheck] Meta refused the ${target} request`, { + statusCode: response.statusCode, + code: numberProperty(error, 'code'), + }); + return { status: 'failed', reason: 'mismatch' }; + } + + private async get( + path: string, + accessToken: string, + qs: Record, + ): Promise { + // Throws only when Meta gives no answer. A refusal comes back as a status. + return await this.outboundHttp + // Fixed public vendor host, not user-controllable. + .requests({ useDefaultSsrfPolicy: 'unsafe' }) + .request({ + method: 'GET', + url: `${GRAPH_API_BASE_URL}${path}`, + qs, + headers: { Authorization: `Bearer ${accessToken}` }, + json: true, + returnFullResponse: true, + ignoreHttpStatusErrors: true, + timeout: CHECK_TIMEOUT_MS, + }); + } +} + +function listedIds(body: unknown): string[] { + const data = isRecord(body) && Array.isArray(body.data) ? body.data : []; + return data + .map((entry: unknown) => stringProperty(entry, 'id')) + .filter((id): id is string => id !== undefined); +} + +function toProfile(phone: unknown, profileBody: unknown): WhatsAppBusinessProfile { + // Meta wraps the business profile in a one-item `data` array. + const profile = + isRecord(profileBody) && Array.isArray(profileBody.data) ? profileBody.data[0] : undefined; + return { + verifiedName: stringProperty(phone, 'verified_name'), + displayPhoneNumber: stringProperty(phone, 'display_phone_number'), + // `description` is the longer text on the profile. `about` is the short + // status line, which many businesses fill in instead. + description: stringProperty(profile, 'description') ?? stringProperty(profile, 'about'), + profilePictureUrl: stringProperty(profile, 'profile_picture_url'), + }; +} diff --git a/packages/cli/src/modules/agents/integrations/platforms/whatsapp-integration.ts b/packages/cli/src/modules/agents/integrations/platforms/whatsapp/whatsapp-integration.ts similarity index 88% rename from packages/cli/src/modules/agents/integrations/platforms/whatsapp-integration.ts rename to packages/cli/src/modules/agents/integrations/platforms/whatsapp/whatsapp-integration.ts index 2cd3aa33b0d..c2f46a262d0 100644 --- a/packages/cli/src/modules/agents/integrations/platforms/whatsapp-integration.ts +++ b/packages/cli/src/modules/agents/integrations/platforms/whatsapp/whatsapp-integration.ts @@ -1,4 +1,8 @@ -import type { RichCardComponentType } from '@n8n/api-types'; +import { + resolveWhatsAppSettings, + type AgentIntegrationConfig, + type RichCardComponentType, +} from '@n8n/api-types'; import { Logger } from '@n8n/backend-common'; import { Service } from '@n8n/di'; import { isRecord } from '@n8n/utils/is-record'; @@ -9,27 +13,35 @@ import { OperationalError, UserError } from 'n8n-workflow'; import type { WhatsAppRawMessage } from '@chat-adapter/whatsapp'; -import { AgentRepository } from '../../repositories/agent.repository'; +import { AgentRepository } from '../../../repositories/agent.repository'; import { AgentChatIntegration, type AgentChannelPreconditionContext, + type AgentIntegrationRemovalContext, type AgentChatIntegrationContext, type ActionDecisionMessageParams, + type BridgeMessageContextParams, + type BridgeResumeExecutionContext, type UnauthenticatedWebhookContext, type UnauthenticatedWebhookResponse, -} from '../agent-chat-integration'; -import { channelRateLimitMessage, type RecipientScopedRateLimitError } from '../channel-rate-limit'; -import { ChannelRateLimitGuard } from '../channel-rate-limit.guard'; +} from '../../agent-chat-integration'; +import { + channelRateLimitMessage, + type RecipientScopedRateLimitError, +} from '../../channel-rate-limit'; +import { ChannelRateLimitGuard } from '../../channel-rate-limit.guard'; import { componentTextToString, type NormalizeComponentsContext, type SuspendComponent, -} from '../component-mapper'; -import { assertCredentialNotClaimed } from '../credential-claim'; -import { loadChatSdk, loadWhatsAppAdapter } from '../esm-loader'; -import { deriveWhatsAppVerifyToken, stringProperty, stringValue } from '../integration-helpers'; -import { resolveIntegrationActionDefinitions } from '../integration-tool-definitions'; -import { buildIntegrationConnectionId } from '../integration-tool-factory'; +} from '../../component-mapper'; +import { assertCredentialNotClaimed } from '../../credential-claim'; +import { loadChatSdk, loadWhatsAppAdapter } from '../../esm-loader'; +import { deriveWhatsAppVerifyToken, stringProperty, stringValue } from '../../integration-helpers'; +import { resolveIntegrationActionDefinitions } from '../../integration-tool-definitions'; +import { buildIntegrationConnectionId } from '../../integration-tool-factory'; +import { startTypingIndicator } from '../typing-indicator'; +import { WhatsAppWebhookVerificationStore } from './whatsapp-webhook-verification.store'; type ChatSdk = Awaited>; @@ -54,6 +66,13 @@ const WHATSAPP_DEFAULT_SESSION_IDLE_TIMEOUT_MINUTES = 30; /** WhatsApp Cloud API's own limit on interactive reply buttons per message. */ const WHATSAPP_MAX_REPLY_BUTTONS = 3; +/** + * WhatsApp's typing indicator ends after about 25 seconds or when a reply is + * sent, whichever comes first, so refresh it inside that window. + * @see https://developers.facebook.com/docs/whatsapp/cloud-api/typing-indicators + */ +const WHATSAPP_TYPING_REFRESH_MS = 20 * 1000; + const WHATSAPP_BOT_USER_NAME = 'n8n-agent'; /** @@ -174,6 +193,7 @@ export class WhatsAppIntegration extends AgentChatIntegration { private readonly agentRepository: AgentRepository, private readonly instanceSettings: InstanceSettings, private readonly channelRateLimitGuard: ChannelRateLimitGuard, + private readonly webhookVerification: WhatsAppWebhookVerificationStore, ) { super(); } @@ -186,6 +206,15 @@ export class WhatsAppIntegration extends AgentChatIntegration { await this.assertStartupPreconditions(ctx); } + /** + * A new setup of this agent can use a different Meta app. Without this, step + * 4 would confirm the handshake that the removed channel's app completed. + */ + async onRemove(ctx: AgentIntegrationRemovalContext): Promise { + await this.webhookVerification.clear(ctx.agentId); + return undefined; + } + /** * Answer Meta's webhook verification handshake (`hub.mode` / `hub.verify_token` * / `hub.challenge`) before a credential is connected. The verify token is @@ -210,9 +239,37 @@ export class WhatsAppIntegration extends AgentChatIntegration { if (token !== this.deriveVerifyToken(context.agentId)) { return { status: 403, body: 'Forbidden', raw: true }; } + // Recorded so the setup can confirm the step. Not awaited, because Meta + // times out the handshake and the record is only for display. + void this.webhookVerification.markVerified(context.agentId); return { status: 200, body: challenge, raw: true }; } + /** + * Starts the typing indicator when a queued message is picked up, which is + * when the agent actually starts working on it. + */ + async createResumeExecutionContext(params: { + thread: BridgeMessageContextParams['thread']; + logger: BridgeMessageContextParams['logger']; + agentId: string; + integration?: AgentIntegrationConfig; + }): Promise { + if (!whatsAppSettings(params.integration).typingIndicator) return {}; + return await Promise.resolve({ + statusHandle: startTypingIndicator(params.thread, { + logger: params.logger, + agentId: params.agentId, + platform: 'WhatsApp', + refreshMs: WHATSAPP_TYPING_REFRESH_MS, + }), + }); + } + + shouldDownloadAttachments(integration: AgentIntegrationConfig): boolean { + return whatsAppSettings(integration).downloadMedia; + } + async createAdapter(ctx: AgentChatIntegrationContext): Promise { const config = { accessToken: this.extractAccessToken(ctx.credential), @@ -240,12 +297,23 @@ export class WhatsAppIntegration extends AgentChatIntegration { // a persistent limit would let every later reply start its own full // retry cycle against an already-limited number instead of failing fast. const connectionId = buildIntegrationConnectionId(ctx.integration); + const webhookVerification = this.webhookVerification; + const agentId = ctx.agentId; // Wraps the real adapter to enforce the 24-hour customer service window // and the rate-limit backoff (see module doc). `stream` needs no override // of its own — the base adapter's `stream` already delegates to // `this.postMessage`. class ConversationWindowGuardedAdapter extends AdapterClass { + // A connected channel answers Meta's handshake here, not in + // `handleUnauthenticatedWebhook`. Record it too, so a later setup of + // the same agent still confirms the step. + protected override handleVerificationChallenge(request: Request): Response { + const response = super.handleVerificationChallenge(request); + if (response.status === 200) void webhookVerification.markVerified(agentId); + return response; + } + override async postMessage( threadId: string, message: AdapterPostableMessage, @@ -412,6 +480,13 @@ export class WhatsAppIntegration extends AgentChatIntegration { } } +/** The channel's settings, with the defaults for any that were never saved. */ +function whatsAppSettings(integration?: AgentIntegrationConfig) { + return resolveWhatsAppSettings( + integration?.type === 'whatsapp' ? integration.settings : undefined, + ); +} + /** * Summarize a `contacts` message in the same bracketed style the adapter uses * for other non-text types (e.g. `[Location: ...]`). The adapter's inbound diff --git a/packages/cli/src/modules/agents/integrations/platforms/whatsapp/whatsapp-webhook-verification.store.ts b/packages/cli/src/modules/agents/integrations/platforms/whatsapp/whatsapp-webhook-verification.store.ts new file mode 100644 index 00000000000..872709d7e5f --- /dev/null +++ b/packages/cli/src/modules/agents/integrations/platforms/whatsapp/whatsapp-webhook-verification.store.ts @@ -0,0 +1,65 @@ +import { Logger } from '@n8n/backend-common'; +import { CacheService } from '@n8n/backend-services'; +import { Time } from '@n8n/constants'; +import { Service } from '@n8n/di'; + +/** + * Long enough to cover a setup that someone leaves and returns to. After it + * expires, clicking "Verify and save" in Meta again records a new handshake. + */ +const VERIFIED_TTL_MS = 7 * Time.days.toMilliseconds; + +const cacheKey = (agentId: string) => `agents:whatsapp:webhook-verified:${agentId}`; + +/** + * Remembers that Meta completed the webhook handshake for an agent, so the + * setup can confirm that step. The handshake can reach any main, so this uses + * the shared cache and not process memory. + */ +@Service() +export class WhatsAppWebhookVerificationStore { + constructor( + private readonly cacheService: CacheService, + private readonly logger: Logger, + ) {} + + /** Never throws: Meta has already received its answer when this runs. */ + async markVerified(agentId: string): Promise { + try { + await this.cacheService.set(cacheKey(agentId), true, VERIFIED_TTL_MS); + } catch (error) { + this.logger.warn('[WhatsAppIntegration] Failed to record the webhook handshake', { + agentId, + error: error instanceof Error ? error.message : String(error), + }); + } + } + + /** + * Never throws: removing the channel has already succeeded when this runs, + * and a leftover record expires on its own. + */ + async clear(agentId: string): Promise { + try { + await this.reset(agentId); + } catch (error) { + this.logger.warn('[WhatsAppIntegration] Failed to clear the webhook handshake', { + agentId, + error: error instanceof Error ? error.message : String(error), + }); + } + } + + /** + * Throws, unlike {@link clear}: the setup resets before it asks for a new + * handshake, and a record that survives would confirm the step for the + * wrong Meta app. + */ + async reset(agentId: string): Promise { + await this.cacheService.delete(cacheKey(agentId)); + } + + async isVerified(agentId: string): Promise { + return (await this.cacheService.get(cacheKey(agentId))) === true; + } +} diff --git a/packages/cli/src/modules/agents/json-config/__tests__/mcp-client-factory.test.ts b/packages/cli/src/modules/agents/json-config/__tests__/mcp-client-factory.test.ts index c1560257d27..9c4a4fa3049 100644 --- a/packages/cli/src/modules/agents/json-config/__tests__/mcp-client-factory.test.ts +++ b/packages/cli/src/modules/agents/json-config/__tests__/mcp-client-factory.test.ts @@ -6,11 +6,7 @@ import { OperationalError, UserError } from 'n8n-workflow'; import type { OauthService } from '@/oauth/oauth.service'; -import { - buildMcpClientForServer, - listMcpServerTools, - mapApprovalToSdk, -} from '../mcp-client-factory'; +import { buildMcpClientForServer, listMcpServerTools } from '../mcp-client-factory'; // --------------------------------------------------------------------------- // Module mocks @@ -68,24 +64,6 @@ function make401(): Response { return new Response('unauthorized', { status: 401 }); } -// --------------------------------------------------------------------------- -// mapApprovalToSdk -// --------------------------------------------------------------------------- - -describe('mapApprovalToSdk', () => { - it('returns undefined when approval is absent', () => { - expect(mapApprovalToSdk(undefined)).toBeUndefined(); - }); - - it('maps mode "global" to literal true (all tools require approval)', () => { - expect(mapApprovalToSdk({ mode: 'global' })).toBe(true); - }); - - it('maps mode "selected" to the literal tools list', () => { - expect(mapApprovalToSdk({ mode: 'selected', tools: ['a', 'b'] })).toEqual(['a', 'b']); - }); -}); - // --------------------------------------------------------------------------- // buildMcpClientForServer — header derivation per auth type // --------------------------------------------------------------------------- @@ -314,8 +292,10 @@ describe('buildMcpClientForServer — SDK config mapping', () => { await buildMcpClientForServer( makeServer({ transport: 'sse', - toolFilter: { mode: 'allow', tools: ['echo'] }, - approval: { mode: 'selected', tools: ['create'] }, + toolPermissions: { + categories: { read: 'blocked', write: 'blocked' }, + tools: { echo: 'always_allow', create: 'require_approval' }, + }, connectionTimeoutMs: 5_000, }), { @@ -333,12 +313,54 @@ describe('buildMcpClientForServer — SDK config mapping', () => { name: 'srv', url: 'https://example.test/mcp', transport: 'sse', - toolFilter: { mode: 'allow', tools: ['echo'] }, - requireApproval: ['create'], connectionTimeoutMs: 5_000, onToolCallSettled, }); expect(typeof configs[0].fetch).toBe('function'); + const configureTools = configs[0].configureTools; + expect(configureTools).toBeTypeOf('function'); + expect( + (configureTools as (tools: Array<{ name: string }>) => unknown)([ + { name: 'echo' }, + { name: 'create' }, + { name: 'other' }, + ]), + ).toEqual({ + toolFilter: { mode: 'exclude', tools: ['other'] }, + requireApproval: ['create'], + }); + }); + + it('omits configureTools from the SDK config when tool permissions are not provided', async () => { + const credentialProvider = mock(); + const oauthService = mock(); + + await buildMcpClientForServer(makeServer(), { + credentialProvider, + oauthService, + projectId: 'proj-1', + proxyFetch, + }); + + const [configs] = mcpClientCtor.mock.calls[0] as [Array>]; + expect(configs[0]).not.toHaveProperty('configureTools'); + }); + + it('marks tool configuration as non-interrupting only when the runtime cannot suspend', async () => { + const credentialProvider = mock(); + const oauthService = mock(); + const server = makeServer({ + toolPermissions: { categories: { read: 'always_allow', write: 'always_allow' } }, + }); + const deps = { credentialProvider, oauthService, projectId: 'proj-1', proxyFetch }; + + await buildMcpClientForServer(server, { ...deps, nonInterrupting: true }); + await buildMcpClientForServer(server, deps); + + const [inlineConfigs] = mcpClientCtor.mock.calls[0] as [Array>]; + const [defaultConfigs] = mcpClientCtor.mock.calls[1] as [Array>]; + expect(inlineConfigs[0]).toMatchObject({ configureToolsNonInterrupting: true }); + expect(defaultConfigs[0]).not.toHaveProperty('configureToolsNonInterrupting'); }); it('omits connectionTimeoutMs from the SDK config when not provided', async () => { @@ -594,11 +616,10 @@ describe('buildMcpClientForServer — credential domain restrictions', () => { expect(proxyFetchMock).not.toHaveBeenCalled(); }); - it('falls back to the MCP hostname for native OAuth2 credentials in none mode', async () => { + it('falls back to the MCP hostname for native OAuth2 credentials with no domain mode', async () => { const credentialProvider = mock(); credentialProvider.resolve.mockResolvedValue({ oauthTokenData: { access_token: 'github-token' }, - allowedHttpRequestDomains: 'none', } as never); const oauthService = mock(); @@ -614,6 +635,8 @@ describe('buildMcpClientForServer — credential domain restrictions', () => { const [configs] = mcpClientCtor.mock.calls[0] as [Array<{ fetch: typeof fetch }>]; await expect(configs[0].fetch('https://api.githubcopilot.com/mcp/')).resolves.toBeDefined(); expect(proxyFetchMock).toHaveBeenCalledTimes(1); + await expect(configs[0].fetch('https://other.example.test/mcp/')).rejects.toThrow(UserError); + expect(proxyFetchMock).toHaveBeenCalledTimes(1); }); it('blocks requests when the server URL is not in the credential allowlist', async () => { diff --git a/packages/cli/src/modules/agents/json-config/agent-document.ts b/packages/cli/src/modules/agents/json-config/agent-document.ts index 84c611c51d5..4f8ad8cfcaa 100644 --- a/packages/cli/src/modules/agents/json-config/agent-document.ts +++ b/packages/cli/src/modules/agents/json-config/agent-document.ts @@ -1,9 +1,8 @@ import type { AgentJsonConfig, AgentJsonSkillConfig, StoredAgentConfig } from '@n8n/api-types'; /** - * Skill refs of one agent draft or one published version, in document order. - * `undefined` means that the config has no skill list. Keep this apart from an - * empty list, because the config hash sees the difference. + * Skill refs of a JSON document. `undefined` means that an inbound document + * has no skill list. The refs of a stored draft or version are always a list. */ export type AgentSkillRefs = AgentJsonSkillConfig[] | undefined; @@ -25,3 +24,12 @@ export function fromAgentDocument(document: AgentJsonConfig): { const { skills, ...config } = document; return { config, skillRefs: skills }; } + +/** + * A stored config without the legacy `skills` key. Configs written before the + * skills hub can still hold it. Nothing reads it, so do not copy it on. + */ +export function withoutLegacySkillRefs(config: StoredAgentConfig): StoredAgentConfig { + const { skills: _legacy, ...rest } = config; + return rest; +} diff --git a/packages/cli/src/modules/agents/json-config/from-json-config.ts b/packages/cli/src/modules/agents/json-config/from-json-config.ts index 7314479ac23..b3b6a3fc296 100644 --- a/packages/cli/src/modules/agents/json-config/from-json-config.ts +++ b/packages/cli/src/modules/agents/json-config/from-json-config.ts @@ -390,7 +390,6 @@ function getConfiguredSkillSource( >(); for (const ref of refs) { - if (ref.enabled === false) continue; if (seen.has(ref.id)) continue; seen.add(ref.id); const skill = skills[ref.id]; @@ -405,7 +404,6 @@ function getConfiguredSkillSource( name: skill.name, description: skill.description, instructions: skill.instructions, - ...(skill.allowedTools ? { allowedTools: skill.allowedTools } : {}), linkedFiles, }); } diff --git a/packages/cli/src/modules/agents/json-config/mcp-client-factory.ts b/packages/cli/src/modules/agents/json-config/mcp-client-factory.ts index d2ca10b31bc..85954223efd 100644 --- a/packages/cli/src/modules/agents/json-config/mcp-client-factory.ts +++ b/packages/cli/src/modules/agents/json-config/mcp-client-factory.ts @@ -5,44 +5,21 @@ import type { McpConnectionFailedEvent, } from '@n8n/agents'; import type { AgentJsonMcpServerConfig } from '@n8n/api-types'; +import { compileMcpToolPermissions } from '@n8n/ai-utilities/agent-config'; import type { CustomFetch } from '@n8n/backend-network'; import { ensureError } from '@n8n/utils/errors/ensure-error'; -import { isRecord } from '@n8n/utils/is-record'; -import { - getMcpAuthHeaders, - isMcpOAuth2Authentication, - OperationalError, - shouldRefreshMcpOAuth2Token, -} from 'n8n-workflow'; +import { getMcpAuthHeaders, isMcpOAuth2Authentication, OperationalError } from 'n8n-workflow'; import type { ICredentialDataDecryptedObject, McpRegistryConnection } from 'n8n-workflow'; import { prepareMcpRegistryConnection, toAgentMcpTransport, } from '@/modules/mcp-registry/mcp-registry-connection'; -import type { OauthService } from '@/oauth/oauth.service'; import { - type AuthFetchDomainPolicy, - createAuthFetch, - getBearerTokenRevision, - resolveAllowedDomains, -} from '@/utils/auth-fetch'; - -/** - * Convert the JSON-config `approval` shape into the SDK's `requireApproval` - * field. The two representations carry the same semantics: - * - * - `undefined` -> `undefined` (no per-server approval) - * - `{ mode: 'global' }` -> `true` (every tool requires approval) - * - `{ mode: 'selected' }` -> `string[]` (only listed tools require approval) - */ -export function mapApprovalToSdk( - approval: AgentJsonMcpServerConfig['approval'], -): McpServerConfig['requireApproval'] { - if (!approval) return undefined; - if (approval.mode === 'global') return true; - return approval.tools; -} + createMcpAuthFetch, + resolveMcpAuthDomainPolicy, +} from '@/modules/mcp-registry/mcp-auth-fetch'; +import type { OauthService } from '@/oauth/oauth.service'; type DerivedAuth = { headers: Record; @@ -88,33 +65,6 @@ async function deriveAuthHeaders( } } -function isNativeOAuth2Credential(authentication: string): boolean { - return ( - isMcpOAuth2Authentication(authentication) && - authentication !== 'mcpOAuth2Api' && - !authentication.endsWith('McpOAuth2Api') - ); -} - -function resolveMcpDomainPolicy( - server: AgentJsonMcpServerConfig, - credentialData: ICredentialDataDecryptedObject, - mcpHostname: string | undefined, -): AuthFetchDomainPolicy | undefined { - if (!isNativeOAuth2Credential(server.authentication) || !mcpHostname) { - return resolveAllowedDomains(credentialData); - } - - switch (credentialData.allowedHttpRequestDomains) { - case 'domains': - return resolveAllowedDomains(credentialData); - case 'all': - return undefined; - default: - return { mode: 'domains', domains: mcpHostname }; - } -} - export interface BuildMcpClientDeps { credentialProvider: CredentialProvider; resolveRegistryConnection?: (nodeTypeName: string) => Promise; @@ -134,6 +84,11 @@ export interface BuildMcpClientDeps { */ onConnectionFailed?: (event: McpConnectionFailedEvent) => void; onToolCallSettled?: McpServerConfig['onToolCallSettled']; + /** + * The runtime cannot suspend and resume (inline agents have no checkpoint + * storage), so tool permissions must never require approval. + */ + nonInterrupting?: boolean; } /** Stand-in for a URL that could not be built. `.invalid` never resolves (RFC 2606), and `authFetch` rejects before any request is sent. */ @@ -158,7 +113,9 @@ export async function buildMcpClientForServer( proxyFetch, onConnectionFailed, onToolCallSettled, + nonInterrupting, } = deps; + const { toolPermissions } = server; const { McpClient } = await import('@n8n/agents'); const derivedAuth = await deriveAuthHeaders(server, credentialProvider); @@ -166,12 +123,9 @@ export async function buildMcpClientForServer( let { headers: initialHeaders, credentialError } = derivedAuth; let runtimeUrl = server.url; let runtimeTransport = server.transport; - const nativeMcpHostname = - isNativeOAuth2Credential(server.authentication) && URL.canParse(server.url) - ? new URL(server.url).hostname - : undefined; + const mcpHostname = URL.canParse(server.url) ? new URL(server.url).hostname : undefined; let allowedDomains = credentialData - ? resolveMcpDomainPolicy(server, credentialData, nativeMcpHostname) + ? resolveMcpAuthDomainPolicy(server.authentication, credentialData, mcpHostname) : undefined; const registryNodeName = server.metadata?.nodeTypeName; @@ -205,39 +159,6 @@ export async function buildMcpClientForServer( } } - const oauthTokenData = isRecord(credentialData?.oauthTokenData) - ? { ...credentialData.oauthTokenData } - : undefined; - const grantType = credentialData?.grantType; - const refreshAuthHeaders = - isMcpOAuth2Authentication(server.authentication) && server.credential - ? async (currentHeaders: Record) => { - const credentialId = server.credential; - if (!credentialId) return null; - const result = await oauthService.refreshOAuth2CredentialById( - credentialId, - projectId, - getBearerTokenRevision(currentHeaders, oauthTokenData?.n8n_expires_at), - ); - if (!result) return null; - - if (oauthTokenData) { - if (result.expiresAt === undefined) { - delete oauthTokenData.n8n_expires_at; - } else { - oauthTokenData.n8n_expires_at = String(result.expiresAt); - } - if (result.expiresInSeconds === undefined) { - delete oauthTokenData.expires_in; - } else { - oauthTokenData.expires_in = result.expiresInSeconds; - } - } - - return result.headers; - } - : undefined; - // An unresolved credential fails at connect time so the real reason travels // the SDK's connection-failure channel (surfaced as a `warning` chunk); // connecting unauthenticated returns an opaque 401/403 instead. @@ -262,13 +183,14 @@ export async function buildMcpClientForServer( } : { url: runtimeUrl, - fetch: createAuthFetch({ + fetch: createMcpAuthFetch({ + authentication: server.authentication, baseFetch: proxyFetch, + credentialData: credentialData ?? {}, + credentialId: server.credential, initialHeaders, - onUnauthorized: refreshAuthHeaders, - ...(refreshAuthHeaders - ? { shouldRefresh: () => shouldRefreshMcpOAuth2Token(oauthTokenData, grantType) } - : {}), + oauthService, + projectId, allowedDomains, }), }; @@ -278,8 +200,10 @@ export async function buildMcpClientForServer( url, transport: runtimeTransport, fetch: authFetch, - toolFilter: server.toolFilter, - requireApproval: mapApprovalToSdk(server.approval), + ...(toolPermissions !== undefined && { + configureTools: (tools) => compileMcpToolPermissions(toolPermissions, tools), + }), + ...(nonInterrupting && { configureToolsNonInterrupting: true }), ...(onToolCallSettled !== undefined && { onToolCallSettled }), ...(server.connectionTimeoutMs !== undefined && { connectionTimeoutMs: server.connectionTimeoutMs, diff --git a/packages/cli/src/modules/agents/json-config/model-config.ts b/packages/cli/src/modules/agents/json-config/model-config.ts index 1d887a783b9..7a0f0842450 100644 --- a/packages/cli/src/modules/agents/json-config/model-config.ts +++ b/packages/cli/src/modules/agents/json-config/model-config.ts @@ -20,10 +20,11 @@ export async function resolveCredentialAwareModelConfig( credential: string, credentialProvider: CredentialProvider & Partial, /** - * Azure OpenAI classic deployments are user-named in Azure and surfaced in - * the deployment-based URL path. The catalog model id is not the deployment + * Azure OpenAI deployments are user-named in Azure and surfaced in the URL + * path on both endpoint types. The catalog model id is not the deployment * id, so the agent flow must carry the user's deployment name separately. - * Only meaningful for the `azure-openai` provider with a classic endpoint. + * Only meaningful for the `azure-openai` provider — on classic it is + * required, on Foundry it is optional and overrides the model id. */ deploymentName?: string, ): Promise { diff --git a/packages/cli/src/modules/agents/json-config/prune-missing-config-references.ts b/packages/cli/src/modules/agents/json-config/prune-missing-config-references.ts index beadccc9477..9f76ed30b62 100644 --- a/packages/cli/src/modules/agents/json-config/prune-missing-config-references.ts +++ b/packages/cli/src/modules/agents/json-config/prune-missing-config-references.ts @@ -2,19 +2,16 @@ import type { AgentJsonConfig } from '@n8n/api-types'; import type { AgentDefinition } from '../utils/agent-definition'; -/** Preserve existing and disabled refs while new refs require an available body. */ +/** + * Preserve existing and disabled refs while new refs require an available body. + * Skill refs are not pruned here: `AgentSkillRefsService.replaceDraftRefs` + * checks them against the skills hub. + */ export function pruneMissingConfigReferences( config: AgentJsonConfig, previousSchema: AgentJsonConfig | null, - available: Pick & { taskIds: ReadonlySet }, + available: Pick & { taskIds: ReadonlySet }, ): void { - if (config.skills !== undefined) { - const existingIds = new Set((previousSchema?.skills ?? []).map((ref) => ref.id)); - config.skills = config.skills.filter( - (ref) => - ref.enabled === false || existingIds.has(ref.id) || Object.hasOwn(available.skills, ref.id), - ); - } if (config.tools !== undefined) { const existingIds = new Set( (previousSchema?.tools ?? []).filter((ref) => ref.type === 'custom').map((ref) => ref.id), diff --git a/packages/cli/src/modules/agents/repositories/agent-chat-attachment.repository.ts b/packages/cli/src/modules/agents/repositories/agent-chat-attachment.repository.ts index fd895b9f288..e5839fc0562 100644 --- a/packages/cli/src/modules/agents/repositories/agent-chat-attachment.repository.ts +++ b/packages/cli/src/modules/agents/repositories/agent-chat-attachment.repository.ts @@ -1,5 +1,5 @@ import { Service } from '@n8n/di'; -import { DataSource, In, Repository } from '@n8n/typeorm'; +import { DataSource, In, LessThan, Repository } from '@n8n/typeorm'; import { AgentChatAttachment } from '../entities/agent-chat-attachment.entity'; @@ -40,4 +40,17 @@ export class AgentChatAttachmentRepository extends Repository { return await this.findBy({ id: In(ids) }); } + + /** Oldest first, so a capped batch always removes the files most overdue. */ + async findFromSourceCreatedBefore( + scope: { agentId: string; source: string }, + before: Date, + limit: number, + ): Promise { + return await this.find({ + where: { agentId: scope.agentId, source: scope.source, createdAt: LessThan(before) }, + order: { createdAt: 'ASC' }, + take: limit, + }); + } } diff --git a/packages/cli/src/modules/agents/repositories/agent-history.repository.ts b/packages/cli/src/modules/agents/repositories/agent-history.repository.ts index 9d77ddbe368..4c08b1c5614 100644 --- a/packages/cli/src/modules/agents/repositories/agent-history.repository.ts +++ b/packages/cli/src/modules/agents/repositories/agent-history.repository.ts @@ -40,7 +40,7 @@ export class AgentHistoryRepository extends BaseRepository { agentId: string; schema: StoredAgentConfig | null; tools: Agent['tools'] | null; - skills: Agent['skills'] | null; + skills?: Agent['skills'] | null; publishedBy: User | string; }, ctx: OperationContext = {}, @@ -60,7 +60,7 @@ export class AgentHistoryRepository extends BaseRepository { agentId: data.agentId, schema: data.schema as InsertShape['schema'], tools: data.tools as InsertShape['tools'], - skills: data.skills as InsertShape['skills'], + skills: (data.skills ?? null) as InsertShape['skills'], author, publishedById, }); diff --git a/packages/cli/src/modules/agents/repositories/agent.repository.ts b/packages/cli/src/modules/agents/repositories/agent.repository.ts index c0b19f1f8cc..3ead72b96ab 100644 --- a/packages/cli/src/modules/agents/repositories/agent.repository.ts +++ b/packages/cli/src/modules/agents/repositories/agent.repository.ts @@ -1,8 +1,16 @@ import { N8N_CHAT_INTEGRATION_TYPE } from '@n8n/api-types'; import type { AgentIntegrationConfig, ListAgentsQueryDto } from '@n8n/api-types'; -import { BaseRepository, chunkIds, TransactionRunner, type OperationContext } from '@n8n/db'; +import { + BaseRepository, + chunkIds, + escapeLike, + LIKE_ESCAPE_CLAUSE, + TransactionRunner, + type OperationContext, +} from '@n8n/db'; import { Service } from '@n8n/di'; import { DataSource, In, IsNull, Not, type SelectQueryBuilder } from '@n8n/typeorm'; +import { randomUUID } from 'node:crypto'; import type { QueryDeepPartialEntity } from '@n8n/typeorm/query-builder/QueryPartialEntity'; import { Agent } from '../entities/agent.entity'; @@ -553,6 +561,21 @@ export class AgentRepository extends BaseRepository { ); } + /** + * Finds every agent with a channel of the given type in its `integrations` + * JSON column. The `LIKE` is a portable pre-filter; it can match another + * field, so the exact check still runs in memory. + */ + async findWithIntegrationType(type: string): Promise>> { + const agents = await this.createQueryBuilder('agent') + .select(['agent.id', 'agent.integrations']) + .where(`CAST(agent.integrations AS TEXT) LIKE :pattern ${LIKE_ESCAPE_CLAUSE}`, { + pattern: `%${escapeLike(JSON.stringify(type))}%`, + }) + .getMany(); + return agents.filter((agent) => (agent.integrations ?? []).some((i) => i.type === type)); + } + /** * Finds agents within a project whose `integrations` JSON column contains an * entry matching the given `type` + `credentialId`, excluding `excludeAgentId`. @@ -644,12 +667,121 @@ export class AgentRepository extends BaseRepository { return won; } + /** + * A skill that these agents follow got a new saved version. Give each agent that is in + * sync with its published version a new draft version id, so it shows unpublished + * changes. One conditional UPDATE per agent and no read first, so a concurrent draft + * edit cannot make the skill save fail. `revision` does not move: a draft edit also + * moves `versionId` away from `activeVersionId`, so neither write undoes the other. + * Returns the agents it changed. + */ + async markDraftChangedIfInSync( + agentIds: string[], + ctx: OperationContext = {}, + ): Promise { + const changed: string[] = []; + for (const id of agentIds) { + const result = await this.managerFor(ctx) + .createQueryBuilder() + .update(Agent) + .set({ versionId: randomUUID() }) + .where('id = :id', { id }) + .andWhere('"versionId" = "activeVersionId"') + .execute(); + if ((result.affected ?? 0) > 0) changed.push(id); + } + return changed; + } + + /** + * One page of agent keys, oldest first, for the startup skill copy. Pages by the last + * row seen, so an agent deleted meanwhile cannot shift later agents past the next page. + */ + async findPageForSkillCopy( + after: Pick | null, + take: number, + ctx: OperationContext = {}, + ): Promise>> { + const query = this.managerFor(ctx) + .createQueryBuilder(Agent, 'agent') + .select(['agent.id', 'agent.createdAt']) + .orderBy('agent.createdAt', 'ASC') + .addOrderBy('agent.id', 'ASC') + .limit(take); + if (after) { + query.where( + '(agent.createdAt > :createdAt OR (agent.createdAt = :createdAt AND agent.id > :id))', + { + createdAt: after.createdAt, + id: after.id, + }, + ); + } + return await query.getMany(); + } + + /** The inline skill columns of one agent, for the startup skill copy. */ + async findForSkillCopy( + agentId: string, + ctx: OperationContext = {}, + ): Promise | null> { + return await this.managerFor(ctx).findOne(Agent, { + select: ['id', 'schema', 'skills'], + where: { id: agentId }, + }); + } + + /** + * Holds the agent row until the transaction ends, so a draft write to the agent waits + * for the startup skill copy of it. SQLite allows one write transaction at a time. + */ + async lockForSkillCopy(agentId: string, ctx: OperationContext): Promise { + if (this.manager.connection.options.type !== 'postgres') return; + await this.managerFor(ctx).find(Agent, { + select: ['id'], + where: { id: agentId }, + lock: { mode: 'pessimistic_write' }, + }); + } + + /** The project of each agent, to send an update push to the right project. */ + async findProjectIdsByIds( + ids: string[], + ctx: OperationContext = {}, + ): Promise>> { + const agents: Array> = []; + // In batches: a skill can have more followers than SQLite allows bound parameters. + for (const chunk of chunkIds([...new Set(ids)])) { + agents.push( + ...(await this.managerFor(ctx).find(Agent, { + where: { id: In(chunk) }, + select: ['id', 'projectId'], + })), + ); + } + return agents; + } + /** * Write the `schema` column of a draft. Write `updatedAt` too, with the value * from the fenced save: without it, TypeORM sets `CURRENT_TIMESTAMP`. This * write does not check `revision`: call it only in the same transaction as a * won `saveDraftFenced`. */ + async updateDraftSkills( + agent: Pick, + ctx: OperationContext, + ): Promise { + // Write `updatedAt` too, with the value of the fenced save: without it, TypeORM + // sets `CURRENT_TIMESTAMP`, which drops the milliseconds on SQLite. + await this.managerFor(ctx) + .createQueryBuilder() + .update(Agent) + .set({ schema: agent.schema, skills: agent.skills, updatedAt: agent.updatedAt }) + .where('id = :id', { id: agent.id }) + .execute(); + } + async updateDraftSchema( agent: Pick, ctx: OperationContext, diff --git a/packages/cli/src/modules/agents/repositories/skill.repository.ts b/packages/cli/src/modules/agents/repositories/skill.repository.ts new file mode 100644 index 00000000000..e485f9122cc --- /dev/null +++ b/packages/cli/src/modules/agents/repositories/skill.repository.ts @@ -0,0 +1,843 @@ +import { + BaseRepository, + LIKE_ESCAPE_CLAUSE, + Project, + TransactionRunner, + chunkIds, + escapeLike, + type OperationContext, +} from '@n8n/db'; +import { Service } from '@n8n/di'; +import { Brackets, DataSource, In, IsNull, type EntityManager } from '@n8n/typeorm'; +import type { SkillUsage } from '@n8n/api-types'; +import { UnexpectedError } from 'n8n-workflow'; +import { randomUUID } from 'node:crypto'; + +import { AgentVersionSkillDependency } from '../entities/agent-version-skill-dependency.entity'; +import { AgentHistory } from '../entities/agent-history.entity'; +import { AgentSkillDependency } from '../entities/agent-skill-dependency.entity'; +import { Agent } from '../entities/agent.entity'; +import { SkillFile } from '../entities/skill-file.entity'; +import { SkillVersion } from '../entities/skill-version.entity'; +import { Skill, type SkillSource } from '../entities/skill.entity'; +import { + compareSkillFilePaths, + skillContentHash, + type SkillContent, +} from '../skills/skill-content-hash'; + +/** + * Where a skill lives: a project, one agent, or the instance (both null). An agent skill + * has no projectId: its project is the agent's. + */ +export type SkillTarget = { projectId: string | null; agentId: string | null }; + +/** One skill with one of its version rows and that row's files, sorted by path. */ +export type ResolvedSkillRow = { + skill: Skill; + version: SkillVersion; + files: SkillFile[]; +}; + +/** A skill ref of an agent draft. A ref with `versionId` is pinned to that saved version. */ +export type SkillDependencyRef = { skillId: string; versionId?: string | null }; + +/** Which skills one user may list: instance skills always, plus the skills of these projects and of their agents. */ +export type SkillVisibility = { + projectIds: string[] | 'all'; +}; + +/** Narrows the visible skills of `findVisiblePage` and cuts one page. */ +export type SkillListFilter = { + scope?: 'project' | 'agent' | 'instance'; + /** The skills of this project and of its agents. */ + projectId?: string; + /** What this agent may attach: instance skills, its project's skills and its own. */ + attachableTo?: { agentId: string; projectId: string }; + search?: string; + skip: number; + take?: number; +}; + +export type { SkillUsage } from '@n8n/api-types'; + +/** Latest version of a skill without its content. */ +export type SkillSummary = { name: string; description: string; version: number }; + +/** Persistence for skills, their versions and files, and the agent rows that use them. */ +@Service() +export class SkillRepository extends BaseRepository { + constructor(dataSource: DataSource, transactionRunner: TransactionRunner) { + super(Skill, dataSource.manager, transactionRunner); + } + + /** + * One page of the skills the user may see, newest change first, and the count of all + * matches. The filters, the search and the page cut run in the query, so the read grows + * with the page, not with the skills on the instance. The search matches the name or + * the description of the latest version. Without `take` every match is returned. + */ + async findVisiblePage( + visibility: SkillVisibility, + filter: SkillListFilter, + ctx: OperationContext = {}, + ): Promise<{ skills: Skill[]; count: number }> { + const manager = this.managerFor(ctx); + // An agent skill has no projectId: its project comes from its agent. + const agentsOf = (projectCondition: string) => + manager + .createQueryBuilder() + .subQuery() + .select('owner.id') + .from(Agent, 'owner') + .where(projectCondition) + .getQuery(); + const { projectIds } = visibility; + const branches: string[] = []; + if (!filter.scope || filter.scope === 'instance') { + branches.push('skill.projectId IS NULL AND skill.agentId IS NULL'); + } + if (filter.attachableTo !== undefined) { + if (projectIds === 'all' || projectIds.includes(filter.attachableTo.projectId)) { + branches.push('skill.projectId = :attachProjectId', 'skill.agentId = :attachAgentId'); + } + } else { + if (!filter.scope || filter.scope === 'project') { + if (projectIds === 'all') branches.push('skill.projectId IS NOT NULL'); + else if (projectIds.length > 0) branches.push('skill.projectId IN (:...projectIds)'); + } + if (!filter.scope || filter.scope === 'agent') { + if (projectIds === 'all') branches.push('skill.agentId IS NOT NULL'); + else if (projectIds.length > 0) { + branches.push(`skill.agentId IN ${agentsOf('owner.projectId IN (:...projectIds)')}`); + } + } + } + if (branches.length === 0) return { skills: [], count: 0 }; + + const query = manager + .createQueryBuilder(Skill, 'skill') + .where(new Brackets((qb) => branches.forEach((branch) => qb.orWhere(`(${branch})`)))) + .setParameters({ + projectIds, + ...(filter.attachableTo !== undefined && { + attachProjectId: filter.attachableTo.projectId, + attachAgentId: filter.attachableTo.agentId, + }), + }); + if (filter.projectId) { + query.andWhere( + new Brackets((qb) => + qb + .where('skill.projectId = :projectId') + .orWhere(`skill.agentId IN ${agentsOf('owner.projectId = :projectId')}`), + ), + { projectId: filter.projectId }, + ); + } + if (filter.search) { + query + .innerJoin(SkillVersion, 'latest', 'latest.skillId = skill.id') + .andWhere((qb) => { + const highest = qb + .subQuery() + .select('MAX(later.version)') + .from(SkillVersion, 'later') + .where('later.skillId = skill.id') + .getQuery(); + return `latest.version = ${highest}`; + }) + .andWhere( + new Brackets((qb) => + qb + .where(`LOWER(latest.name) LIKE :search ${LIKE_ESCAPE_CLAUSE}`) + .orWhere(`LOWER(latest.description) LIKE :search ${LIKE_ESCAPE_CLAUSE}`), + ), + { search: `%${escapeLike(filter.search.toLowerCase())}%` }, + ); + } + query.orderBy('skill.updatedAt', 'DESC').addOrderBy('skill.id', 'ASC').offset(filter.skip); + if (filter.take !== undefined) query.limit(filter.take); + const [skills, count] = await query.getManyAndCount(); + return { skills, count }; + } + + async findByIds(ids: string[], ctx: OperationContext = {}): Promise { + const manager = this.managerFor(ctx); + return await inChunks( + ids, + async (chunk) => await manager.find(Skill, { where: { id: In(chunk) } }), + ); + } + + /** The highest version of each skill, keyed by skill id. A following ref reads it. */ + async findLatestSaved( + skillIds: string[], + ctx: OperationContext = {}, + ): Promise> { + const manager = this.managerFor(ctx); + const versions = await inChunks( + skillIds, + async (chunk) => await latestVersionsQuery(manager, chunk).getMany(), + ); + return await this.resolveBySkill(versions, ctx); + } + + /** Name, description and number of the latest version, without its content. */ + async findLatestSummaries( + skillIds: string[], + ctx: OperationContext = {}, + ): Promise> { + const manager = this.managerFor(ctx); + const versions = await inChunks( + skillIds, + async (chunk) => + await latestVersionsQuery(manager, chunk) + .select(['version.skillId', 'version.name', 'version.description', 'version.version']) + .getMany(), + ); + return new Map( + versions.map((v) => [ + v.skillId, + { name: v.name, description: v.description, version: v.version }, + ]), + ); + } + + /** Version rows by id, keyed by version id. A pinned ref reads them. */ + async findVersionsByIds( + versionIds: string[], + ctx: OperationContext = {}, + ): Promise> { + if (versionIds.length === 0) return new Map(); + const versions = await this.managerFor(ctx).find(SkillVersion, { + where: { id: In(unique(versionIds)) }, + }); + const rows = await this.resolve(versions, ctx); + return new Map(rows.map((row) => [row.version.id, row])); + } + + /** + * The pinned version of each skill of one published agent version, keyed by skill id, + * in the order of the draft refs at publish. + */ + async findPinned( + agentVersionId: string, + ctx: OperationContext = {}, + ): Promise> { + const pins = await this.managerFor(ctx).find(AgentVersionSkillDependency, { + where: { agentVersionId }, + order: { createdAt: 'ASC' }, + }); + const versions = await this.findVersionsByIds( + pins.map((pin) => pin.skillVersionId), + ctx, + ); + const result = new Map(); + for (const pin of pins) { + const row = versions.get(pin.skillVersionId); + if (row) result.set(pin.skillId, row); + } + return result; + } + + /** + * The skill ids one published agent version pins, in the order of the draft refs at + * publish. Reads no version or file rows. + */ + async findPinnedSkillIds(agentVersionId: string, ctx: OperationContext = {}): Promise { + const pins = await this.managerFor(ctx).find(AgentVersionSkillDependency, { + select: ['skillId'], + where: { agentVersionId }, + order: { createdAt: 'ASC' }, + }); + return pins.map((pin) => pin.skillId); + } + + /** The next version number of a skill: the highest version plus one, or 1. */ + async nextVersionNumber(skillId: string, ctx: OperationContext = {}): Promise { + const latest = await this.managerFor(ctx).findOne(SkillVersion, { + select: ['version'], + where: { skillId }, + order: { version: 'DESC' }, + }); + return (latest?.version ?? 0) + 1; + } + + /** Inserts the skill with its v1 and returns the id of that version. */ + async createSkill( + skill: { id: string; target: SkillTarget; source: SkillSource; createdById: string | null }, + content: SkillContent, + ctx: OperationContext = {}, + ): Promise { + return await this.runInTransaction(ctx, async (manager) => { + await manager.insert(Skill, { + id: skill.id, + projectId: skill.target.projectId, + agentId: skill.target.agentId, + source: skill.source, + createdById: skill.createdById, + }); + return await insertVersion(manager, skill.id, 1, content, skill.createdById); + }); + } + + /** Inserts the next version with its files and returns its id. The skill moves up the list. */ + async insertSavedVersion( + skillId: string, + version: number, + content: SkillContent, + createdById: string | null, + ctx: OperationContext = {}, + ): Promise { + return await this.runInTransaction(ctx, async (manager) => { + const id = await insertVersion(manager, skillId, version, content, createdById); + await manager.update(Skill, { id: skillId }, { updatedAt: new Date() }); + return id; + }); + } + + /** + * Inserts the pins of one publish in the given order. `createdAt` orders the skills of + * a published version, so each pin gets its own timestamp, like `replaceDependencies`. + */ + async insertPins( + pins: Array<{ agentVersionId: string; skillId: string; skillVersionId: string }>, + ctx: OperationContext = {}, + ): Promise { + if (pins.length === 0) return; + const first = Date.now(); + await this.managerFor(ctx).insert( + AgentVersionSkillDependency, + pins.map((pin, index) => ({ ...pin, createdAt: new Date(first + index) })), + ); + } + + /** + * Sets the dependency rows of one agent to these refs. Refs to unknown skills are + * skipped. A row that stays keeps its `createdAt`, which orders an agent's skills, and + * new rows sort after it in the given order. When one skill has a following ref and a + * pinned ref, the following ref wins, because the draft then runs the latest version. + */ + async replaceDependencies( + agentId: string, + refs: SkillDependencyRef[], + ctx: OperationContext = {}, + ): Promise { + const pinBySkill = new Map(); + for (const ref of refs) { + if (pinBySkill.get(ref.skillId) === null) continue; + pinBySkill.set(ref.skillId, ref.versionId ?? null); + } + await this.runInTransaction(ctx, async (manager, txCtx) => { + const known = new Set( + (await this.findByIds([...pinBySkill.keys()], txCtx)).map((skill) => skill.id), + ); + const current = await manager.find(AgentSkillDependency, { where: { agentId } }); + const removed = current.filter( + (row) => !known.has(row.skillId) || !pinBySkill.has(row.skillId), + ); + if (removed.length > 0) { + await manager.delete(AgentSkillDependency, { + agentId, + skillId: In(removed.map((row) => row.skillId)), + }); + } + const kept = new Map(current.map((row) => [row.skillId, row])); + for (const [skillId, skillVersionId] of pinBySkill) { + const row = kept.get(skillId); + if (row && row.skillVersionId !== skillVersionId) { + await manager.update(AgentSkillDependency, { agentId, skillId }, { skillVersionId }); + } + } + const added = [...pinBySkill].filter(([skillId]) => known.has(skillId) && !kept.has(skillId)); + if (added.length === 0) return; + // One insert gives every row the same timestamp, so each new row gets its own. + const newest = Math.max(Date.now(), ...current.map((row) => row.createdAt.getTime() + 1)); + await manager.insert( + AgentSkillDependency, + added.map(([skillId, skillVersionId], index) => ({ + agentId, + skillId, + skillVersionId, + createdAt: new Date(newest + index), + })), + ); + }); + } + + /** Agents whose draft follows the skill (no pin). */ + async findFollowingAgents( + skillId: string, + ctx: OperationContext = {}, + ): Promise>> { + const agentIds = await this.findFollowingAgentIds([skillId], ctx); + if (agentIds.length === 0) return []; + return await this.managerFor(ctx).find(Agent, { + where: { id: In(agentIds) }, + select: ['id', 'name'], + }); + } + + /** The skill refs of each agent's draft, in the order they were attached. */ + async findDependencies( + agentIds: string[], + ctx: OperationContext = {}, + ): Promise>> { + if (agentIds.length === 0) return new Map(); + const rows = await this.managerFor(ctx).find(AgentSkillDependency, { + where: { agentId: In(unique(agentIds)) }, + order: { createdAt: 'ASC' }, + }); + const result = new Map>(); + for (const row of rows) { + const refs = result.get(row.agentId) ?? []; + refs.push({ skillId: row.skillId, versionId: row.skillVersionId }); + result.set(row.agentId, refs); + } + return result; + } + + /** Ids of the agents whose draft follows any of these skills (no pin). */ + async findFollowingAgentIds(skillIds: string[], ctx: OperationContext = {}): Promise { + if (skillIds.length === 0) return []; + const rows = await this.managerFor(ctx).find(AgentSkillDependency, { + where: { skillId: In(unique(skillIds)), skillVersionId: IsNull() }, + }); + return unique(rows.map((row) => row.agentId)); + } + + /** + * "Used by": each agent that uses the skill once, as a draft ref, as a published pin, or + * both. A pin row shows the version the agent's current published version runs, or + * null when only older published versions use the skill. Agents outside `projectIds` + * are only counted. The read grows with the agents, not with their publishes. + */ + async findUsage( + skillId: string, + projectIds: string[] | 'all' = 'all', + ctx: OperationContext = {}, + ): Promise { + const manager = this.managerFor(ctx); + const drafted = await manager + .createQueryBuilder(Agent, 'agent') + .innerJoin(AgentSkillDependency, 'dep', 'dep.agentId = agent.id') + .where('dep.skillId = :skillId', { skillId }) + .select(['agent.id', 'agent.name', 'agent.projectId']) + .getMany(); + const published = await manager + .createQueryBuilder(Agent, 'agent') + .where((qb) => { + const pinned = qb + .subQuery() + .select('history.agentId') + .from(AgentHistory, 'history') + .innerJoin(AgentVersionSkillDependency, 'pin', 'pin.agentVersionId = history.versionId') + .where('pin.skillId = :skillId') + .getQuery(); + return `agent.id IN ${pinned}`; + }) + .setParameter('skillId', skillId) + .select(['agent.id', 'agent.name', 'agent.projectId', 'agent.activeVersionId']) + .getMany(); + + const isVisible = (agent: Pick) => + projectIds === 'all' || projectIds.includes(agent.projectId); + const hidden = new Set( + [...drafted, ...published].filter((agent) => !isVisible(agent)).map((agent) => agent.id), + ); + const visiblePublished = published.filter(isVisible); + const activeVersions = await this.findActivePinVersions( + skillId, + visiblePublished.flatMap((agent) => (agent.activeVersionId ? [agent.activeVersionId] : [])), + manager, + ); + return { + drafts: drafted.filter(isVisible).map((agent) => ({ + agentId: agent.id, + agentName: agent.name, + projectId: agent.projectId, + })), + pins: visiblePublished.map((agent) => ({ + agentId: agent.id, + agentName: agent.name, + projectId: agent.projectId, + version: activeVersions.get(agent.activeVersionId ?? '') ?? null, + })), + hiddenAgents: hidden.size, + }; + } + + /** + * Whether the agent already has skills hub rows: a draft ref, an agent skill, or a pin + * of one of its published versions. The startup copy leaves such an agent alone. + */ + async hasHubState(agentId: string, ctx: OperationContext = {}): Promise { + const manager = this.managerFor(ctx); + if (await manager.exists(AgentSkillDependency, { where: { agentId } })) return true; + if (await manager.exists(Skill, { where: { agentId } })) return true; + return await manager + .createQueryBuilder(AgentVersionSkillDependency, 'pin') + .innerJoin(AgentHistory, 'history', 'history.versionId = pin.agentVersionId') + .where('history.agentId = :agentId', { agentId }) + .getExists(); + } + + /** The published versions of an agent that pin no skill, oldest first. */ + async findUnpinnedVersions( + agentId: string, + ctx: OperationContext = {}, + ): Promise>> { + return await this.managerFor(ctx) + .createQueryBuilder(AgentHistory, 'history') + .select(['history.versionId', 'history.schema', 'history.skills']) + .where('history.agentId = :agentId', { agentId }) + .andWhere((qb) => { + const pinned = qb + .subQuery() + .select('1') + .from(AgentVersionSkillDependency, 'pin') + .where('pin.agentVersionId = history.versionId') + .getQuery(); + return `NOT EXISTS ${pinned}`; + }) + .orderBy('history.createdAt', 'ASC') + .addOrderBy('history.versionId', 'ASC') + .getMany(); + } + + /** + * Every version of the skills one agent owns or refers to: its agent skills and the + * skills of its draft refs. The startup copy reuses a version with the same content. + */ + async findAgentSkillVersions( + agentId: string, + ctx: OperationContext = {}, + ): Promise>> { + return await this.managerFor(ctx) + .createQueryBuilder(SkillVersion, 'version') + .innerJoin(Skill, 'skill', 'skill.id = version.skillId') + .select(['version.id', 'version.skillId', 'version.version', 'version.contentHash']) + .where('skill.agentId = :agentId', { agentId }) + .orWhere((qb) => { + const refs = qb + .subQuery() + .select('dep.skillId') + .from(AgentSkillDependency, 'dep') + .where('dep.agentId = :agentId') + .getQuery(); + return `skill.id IN ${refs}`; + }) + .orderBy('version.version', 'ASC') + .getMany(); + } + + /** Ids of the agents that have draft refs in the skills hub, in id order. */ + async findAgentIdsWithDraftRefs(ctx: OperationContext = {}): Promise { + // The primary key is (agentId, skillId), so one agent can have several rows. + const rows = await this.managerFor(ctx) + .createQueryBuilder(AgentSkillDependency, 'dep') + .select('dep.agentId', 'agentId') + .distinct(true) + .orderBy('dep.agentId', 'ASC') + .getRawMany<{ agentId: string }>(); + return rows.map((row) => row.agentId); + } + + /** + * The content hash of each skill version a draft runs, by agent: the pinned version of + * a ref, else the latest version of its skill. + */ + async findDraftContentHashes( + agentIds: string[], + ctx: OperationContext = {}, + ): Promise> { + const manager = this.managerFor(ctx); + const deps = await this.findDependencies(agentIds, ctx); + const refs = [...deps.values()].flat(); + const pinnedIds = refs.flatMap((ref) => (ref.versionId ? [ref.versionId] : [])); + const followedIds = refs.flatMap((ref) => (ref.versionId ? [] : [ref.skillId])); + const pinned = await inChunks( + pinnedIds, + async (chunk) => + await manager.find(SkillVersion, { + select: ['id', 'contentHash'], + where: { id: In(chunk) }, + }), + ); + const latest = await inChunks( + followedIds, + async (chunk) => + await latestVersionsQuery(manager, chunk) + .select(['version.skillId', 'version.contentHash']) + .getMany(), + ); + const hashByVersion = new Map(pinned.map((version) => [version.id, version.contentHash])); + const hashBySkill = new Map(latest.map((version) => [version.skillId, version.contentHash])); + const result = new Map(); + for (const [agentId, agentRefs] of deps) { + result.set( + agentId, + agentRefs.flatMap((ref) => { + const hash = ref.versionId + ? hashByVersion.get(ref.versionId) + : hashBySkill.get(ref.skillId); + return hash ? [hash] : []; + }), + ); + } + return result; + } + + /** Whether a skill with this id exists. */ + async existsById(skillId: string, ctx: OperationContext = {}): Promise { + return await this.managerFor(ctx).exists(Skill, { where: { id: skillId } }); + } + + /** The agents that use the skill: a draft ref or a published pin. */ + async findUsingAgentIds(skillId: string, ctx: OperationContext = {}): Promise { + const manager = this.managerFor(ctx); + const drafts = await manager.find(AgentSkillDependency, { + select: ['agentId'], + where: { skillId }, + }); + const pins = await manager + .createQueryBuilder(AgentVersionSkillDependency, 'pin') + .innerJoin(AgentHistory, 'history', 'history.versionId = pin.agentVersionId') + .where('pin.skillId = :skillId', { skillId }) + .select('history.agentId', 'agentId') + .distinct(true) + .getRawMany<{ agentId: string }>(); + return unique([...drafts, ...pins].map((row) => row.agentId)); + } + + /** Moves a skill to a project, one agent or the instance. */ + async updateTarget(skillId: string, target: SkillTarget, ctx: OperationContext = {}) { + await this.managerFor(ctx).update( + Skill, + { id: skillId }, + { projectId: target.projectId, agentId: target.agentId, updatedAt: new Date() }, + ); + } + + /** Distinct agents per skill, drafts and pins together. Skills nobody uses are left out. */ + async countUsingAgents( + skillIds: string[], + ctx: OperationContext = {}, + ): Promise> { + const manager = this.managerFor(ctx); + const pairs = await inChunks(skillIds, async (chunk) => { + const drafts = await manager.find(AgentSkillDependency, { + select: ['skillId', 'agentId'], + where: { skillId: In(chunk) }, + }); + const pins = await manager + .createQueryBuilder(AgentVersionSkillDependency, 'pin') + .innerJoin(AgentHistory, 'history', 'history.versionId = pin.agentVersionId') + .where('pin.skillId IN (:...chunk)', { chunk }) + .select('pin.skillId', 'skillId') + .addSelect('history.agentId', 'agentId') + .distinct(true) + .getRawMany<{ skillId: string; agentId: string }>(); + return [...drafts, ...pins]; + }); + const agentsBySkill = new Map>(); + for (const { skillId, agentId } of pairs) { + agentsBySkill.set(skillId, (agentsBySkill.get(skillId) ?? new Set()).add(agentId)); + } + return new Map([...agentsBySkill].map(([skillId, agents]) => [skillId, agents.size])); + } + + async findProjectNames( + projectIds: string[], + ctx: OperationContext = {}, + ): Promise> { + const manager = this.managerFor(ctx); + const projects = await inChunks( + projectIds, + async (chunk) => + await manager.find(Project, { where: { id: In(chunk) }, select: ['id', 'name'] }), + ); + return new Map(projects.map((project) => [project.id, project.name])); + } + + /** Name and project of each agent, keyed by agent id. An agent skill takes its project from them. */ + async findAgents( + agentIds: string[], + ctx: OperationContext = {}, + ): Promise>> { + const manager = this.managerFor(ctx); + const agents = await inChunks( + agentIds, + async (chunk) => + await manager.find(Agent, { + where: { id: In(chunk) }, + select: ['id', 'name', 'projectId'], + }), + ); + return new Map(agents.map(({ id, name, projectId }) => [id, { name, projectId }])); + } + + /** + * Deletes the skill. Its versions, files, dependency rows and pins go by cascade, + * so callers check usage first. + */ + async deleteSkill(skillId: string, ctx: OperationContext = {}): Promise { + await this.managerFor(ctx).delete(Skill, { id: skillId }); + } + + /** + * Holds the skill rows for writing until the transaction ends, so a save and a publish + * that pins the same skill run one after the other. See `lockForPublish`. + */ + async lockForEdit(skillIds: string[], ctx: OperationContext = {}): Promise { + await this.lock(skillIds, 'pessimistic_write', ctx); + } + + /** Shared lock: publishes run side by side, a save waits for them. */ + async lockForPublish(skillIds: string[], ctx: OperationContext = {}): Promise { + await this.lock(skillIds, 'pessimistic_read', ctx); + } + + private async lock( + skillIds: string[], + mode: 'pessimistic_write' | 'pessimistic_read', + ctx: OperationContext, + ): Promise { + if (!ctx.trx) throw new UnexpectedError('Skill row locks need a transaction'); + // SQLite allows one write transaction at a time, so the rows cannot change under us. + if (skillIds.length === 0 || this.manager.connection.options.type !== 'postgres') return; + await this.managerFor(ctx).find(Skill, { + select: ['id'], + where: { id: In(unique(skillIds)) }, + lock: { mode }, + }); + } + + /** The skill version number each of these published agent versions pins. */ + private async findActivePinVersions( + skillId: string, + agentVersionIds: string[], + manager: EntityManager, + ): Promise> { + const rows = await inChunks( + agentVersionIds, + async (chunk) => + await manager + .createQueryBuilder(AgentVersionSkillDependency, 'pin') + .innerJoin(SkillVersion, 'version', 'version.id = pin.skillVersionId') + .where('pin.skillId = :skillId', { skillId }) + .andWhere('pin.agentVersionId IN (:...chunk)', { chunk }) + .select('pin.agentVersionId', 'agentVersionId') + .addSelect('version.version', 'version') + .getRawMany<{ agentVersionId: string; version: number | string }>(), + ); + return new Map(rows.map((row) => [row.agentVersionId, Number(row.version)])); + } + + private async resolveBySkill( + versions: SkillVersion[], + ctx: OperationContext, + ): Promise> { + const rows = await this.resolve(versions, ctx); + return new Map(rows.map((row) => [row.skill.id, row])); + } + + /** Adds the skill and the files, sorted by path, to each version row. */ + private async resolve( + versions: SkillVersion[], + ctx: OperationContext, + ): Promise { + if (versions.length === 0) return []; + const manager = this.managerFor(ctx); + const skills = await this.findByIds( + versions.map((version) => version.skillId), + ctx, + ); + const files = await inChunks( + versions.map((version) => version.id), + async (chunk) => await manager.find(SkillFile, { where: { skillVersionId: In(chunk) } }), + ); + const skillById = new Map(skills.map((skill) => [skill.id, skill])); + const filesByVersion = new Map(); + for (const file of files.sort((a, b) => compareSkillFilePaths(a.path, b.path))) { + filesByVersion.set(file.skillVersionId, [ + ...(filesByVersion.get(file.skillVersionId) ?? []), + file, + ]); + } + return versions.flatMap((version) => { + const skill = skillById.get(version.skillId); + return skill ? [{ skill, version, files: filesByVersion.get(version.id) ?? [] }] : []; + }); + } +} + +function unique(values: string[]): string[] { + return [...new Set(values)]; +} + +/** Runs `read` over the distinct ids in chunks that stay under the bind limit. */ +async function inChunks(ids: string[], read: (chunk: string[]) => Promise): Promise { + const results: T[] = []; + for (const chunk of chunkIds(unique(ids))) results.push(...(await read(chunk))); + return results; +} + +/** The version rows of these skills that have the highest number of their skill. */ +function latestVersionsQuery(manager: EntityManager, skillIds: string[]) { + return manager + .createQueryBuilder(SkillVersion, 'version') + .where('version.skillId IN (:...skillIds)', { skillIds }) + .andWhere((qb) => { + const highest = qb + .subQuery() + .select('MAX(later.version)') + .from(SkillVersion, 'later') + .where('later.skillId = version.skillId') + .getQuery(); + return `version.version = ${highest}`; + }); +} + +async function insertVersion( + manager: EntityManager, + skillId: string, + version: number, + content: SkillContent, + createdById: string | null, +): Promise { + const id = randomUUID(); + // `save`, not `insert`: the partial-entity type of `insert` rejects free-form JSON. + await manager.save( + manager.create(SkillVersion, { + id, + skillId, + version, + name: content.name, + description: content.description, + instructions: content.instructions, + frontmatter: content.frontmatter, + contentHash: skillContentHash(content), + createdById, + }), + ); + await insertFiles(manager, id, content.files); + return id; +} + +async function insertFiles( + manager: EntityManager, + skillVersionId: string, + files: SkillContent['files'], +): Promise { + if (files.length === 0) return; + await manager.insert( + SkillFile, + files.map((file) => ({ + skillVersionId, + path: file.path, + content: file.content, + })), + ); +} diff --git a/packages/cli/src/modules/agents/scheduling/agent-task-job-registrar.ts b/packages/cli/src/modules/agents/scheduling/agent-task-job-registrar.ts index ab1e728c747..34c1d9ee3bb 100644 --- a/packages/cli/src/modules/agents/scheduling/agent-task-job-registrar.ts +++ b/packages/cli/src/modules/agents/scheduling/agent-task-job-registrar.ts @@ -45,6 +45,7 @@ export class AgentTaskJobRegistrar { /** Whether the durable scheduler runs agent tasks on this instance. */ isEnabled(): boolean { + // oxlint-disable-next-line typescript/no-deprecated -- the in-memory scheduler will be removed in a future version const { enabled, enabledForAgentTasks } = this.globalConfig.scheduler; return enabled && enabledForAgentTasks; } @@ -119,6 +120,7 @@ export class AgentTaskJobRegistrar { * startups converge. */ async reconcileAll(): Promise { + // oxlint-disable-next-line typescript/no-deprecated -- the in-memory scheduler will be removed in a future version if (!this.globalConfig.scheduler.enabled) return; if (!this.isEnabled()) { diff --git a/packages/cli/src/modules/agents/skills.controller.ts b/packages/cli/src/modules/agents/skills.controller.ts new file mode 100644 index 00000000000..6435f184398 --- /dev/null +++ b/packages/cli/src/modules/agents/skills.controller.ts @@ -0,0 +1,71 @@ +import { CreateSkillDto, ListSkillsQueryDto, SaveSkillDto } from '@n8n/api-types'; +import type { AuthenticatedRequest } from '@n8n/db'; +import { + Body, + Delete, + Get, + Middleware, + Param, + Patch, + Post, + Query, + RestController, +} from '@n8n/decorators'; +import type { NextFunction, Request, Response } from 'express'; + +import { SkillsApiService } from './skills/skills-api.service'; +import { SkillsHubRollout } from './skills/skills-hub-rollout'; + +/** + * Skills for the settings page. No route scope: the scope of each skill decides who may + * see or change it, so `SkillsApiService` checks every row. + */ +@RestController('/skills') +export class SkillsController { + constructor( + private readonly skillsApi: SkillsApiService, + private readonly rollout: SkillsHubRollout, + ) {} + + /** Runs before the request is validated, so every request answers 404 while the flag is off. */ + @Middleware() + requireSkillsHub(_req: Request, res: Response, next: NextFunction) { + if (!this.rollout.isEnabled) { + res.status(404).send('Not found'); + return; + } + next(); + } + + @Get('/') + async list(req: AuthenticatedRequest, _res: Response, @Query query: ListSkillsQueryDto) { + return await this.skillsApi.list(req.user, query); + } + + @Get('/:skillId') + async get(req: AuthenticatedRequest, _res: Response, @Param('skillId') skillId: string) { + return await this.skillsApi.get(req.user, skillId); + } + + @Post('/') + async create(req: AuthenticatedRequest, _res: Response, @Body payload: CreateSkillDto) { + return await this.skillsApi.create(req.user, payload); + } + + /** Saves the changes as the next version. There is no draft: the editor keeps them until here. */ + @Patch('/:skillId') + async update( + req: AuthenticatedRequest, + _res: Response, + @Param('skillId') skillId: string, + @Body payload: SaveSkillDto, + ) { + return await this.skillsApi.update(req.user, skillId, payload); + } + + @Delete('/:skillId') + async delete(req: AuthenticatedRequest, _res: Response, @Param('skillId') skillId: string) { + await this.skillsApi.delete(req.user, skillId); + return { ok: true }; + } +} diff --git a/packages/cli/src/modules/agents/skills/skill-content-hash.ts b/packages/cli/src/modules/agents/skills/skill-content-hash.ts new file mode 100644 index 00000000000..cf6cb5c335d --- /dev/null +++ b/packages/cli/src/modules/agents/skills/skill-content-hash.ts @@ -0,0 +1,55 @@ +import { createHash } from 'node:crypto'; + +import type { SkillFrontmatter } from '../entities/skill-version.entity'; + +/** Everything one `skill_version` row holds, the name included. */ +export type SkillContent = { + name: string; + description: string; + instructions: string; + frontmatter: SkillFrontmatter | null; + files: Array<{ path: string; content: string }>; +}; + +/** Plain code-unit order, the same order every reader of `skill_file` uses. */ +export function compareSkillFilePaths(left: string, right: string): number { + return left < right ? -1 : left > right ? 1 : 0; +} + +/** + * Map keys in sorted order at every level, so two equal maps hash the same. List order + * stays. For a flat map of strings, the only shape the data migration writes, this is + * the same as its top-level sort. + */ +function sortKeys(value: unknown): unknown { + if (Array.isArray(value)) return value.map(sortKeys); + if (value === null || typeof value !== 'object') return value; + return Object.fromEntries( + Object.entries(value) + .sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0)) + .map(([key, entry]) => [key, sortKeys(entry)]), + ); +} + +/** + * Identity of a version's content, name included. Save creates no version when the + * draft has the hash of the latest version. + * + * The data migration `MigrateAgentSkillsToHub` (CONTEXT-225) must compute the same value. + * Keep both in sync: the migration test must pin the literals of `skill-content-hash.test.ts`. + */ +export function skillContentHash(content: SkillContent): string { + return createHash('sha256') + .update( + JSON.stringify({ + name: content.name, + description: content.description, + instructions: content.instructions, + frontmatter: content.frontmatter ? sortKeys(content.frontmatter) : null, + files: content.files + .map((file) => [file.path, file.content]) + .sort(([left], [right]) => compareSkillFilePaths(left, right)), + }), + ) + .digest('hex'); +} diff --git a/packages/cli/src/modules/agents/skills/skill-names.ts b/packages/cli/src/modules/agents/skills/skill-names.ts new file mode 100644 index 00000000000..5a569890cbd --- /dev/null +++ b/packages/cli/src/modules/agents/skills/skill-names.ts @@ -0,0 +1,47 @@ +/** + * The rule for two skill names that are hard to tell apart inside one agent: case, + * surrounding spaces, and runs of spaces, hyphens and underscores do not count. + */ +export function skillNameKey(name: string): string { + return name + .trim() + .toLowerCase() + .replace(/[\s_-]+/g, ' ') + .trim(); +} + +/** + * Names in `added` that clash with a name in `existing` or with an earlier added name. + * Clashes among `existing` alone are allowed: agents keep the names they already had. + */ +export function findIntroducedNameClashes(existing: string[], added: string[]): string[] { + const taken = new Set(existing.map(skillNameKey)); + const clashes: string[] = []; + for (const name of added) { + const key = skillNameKey(name); + if (taken.has(key)) clashes.push(name); + taken.add(key); + } + return clashes; +} + +/** Whether renaming one skill of an agent makes it clash with the agent's other skills. */ +export function renameIntroducesClash( + otherNames: string[], + oldName: string, + newName: string, +): boolean { + const newKey = skillNameKey(newName); + if (newKey === skillNameKey(oldName)) return false; + return otherNames.some((name) => skillNameKey(name) === newKey); +} + +/** Groups of names that clash with each other, as written. */ +export function findNameClashGroups(names: string[]): string[][] { + const byKey = new Map(); + for (const name of names) { + const key = skillNameKey(name); + byKey.set(key, [...(byKey.get(key) ?? []), name]); + } + return [...byKey.values()].filter((group) => group.length > 1); +} diff --git a/packages/cli/src/modules/agents/skills/skill.service.ts b/packages/cli/src/modules/agents/skills/skill.service.ts new file mode 100644 index 00000000000..aa656044fbd --- /dev/null +++ b/packages/cli/src/modules/agents/skills/skill.service.ts @@ -0,0 +1,567 @@ +import type { AgentSkill } from '@n8n/api-types'; +import { Logger } from '@n8n/backend-common'; +import { ProjectScopeService } from '@n8n/backend-services'; +import { TransactionRunner, type OperationContext, type User } from '@n8n/db'; +import { Container, Service } from '@n8n/di'; +import { ConflictError, ForbiddenError, NotFoundError, UserError } from '@n8n/errors'; +import { hasGlobalScope } from '@n8n/permissions'; +import { generateNanoId } from '@n8n/utils/generate-nano-id'; + +import { userHasScopes } from '@/permissions.ee/check-access'; + +import { AgentUpdateBroadcaster } from '../agent-update-broadcaster'; +import type { SkillFrontmatter } from '../entities/skill-version.entity'; +import type { Skill, SkillSource } from '../entities/skill.entity'; +import { AgentRepository } from '../repositories/agent.repository'; +import { + SkillRepository, + type ResolvedSkillRow, + type SkillTarget, +} from '../repositories/skill.repository'; +import { getAgentSkillHash } from '../utils/agent-config-hash'; +import { skillContentHash, type SkillContent } from './skill-content-hash'; +import { findIntroducedNameClashes, renameIntroducesClash } from './skill-names'; + +/** A skill ref in an agent config. A ref with `versionId` runs that version. */ +export type SkillRef = { id: string; versionId?: string }; + +/** Fields to change, plus the hash of the version the editor started from. */ +export type SkillUpdate = Partial & { baseSkillHash: string }; + +export type SkillSaveResult = { + versionId: string; + version: number; + /** False when the content matched the latest version and nothing was saved. */ + created: boolean; + /** The content of the latest version after the save. */ + skill: AgentSkill; + /** Agents that follow the skill. A save in a caller's transaction does not refresh them. */ + followingAgentIds: string[]; +}; + +/** + * The content of one version. Skills ignore `allowedTools`: the frontmatter, the + * `allowed-tools` key included, stays as given. + */ +export function toSkillContent(skill: AgentSkill, frontmatter: SkillFrontmatter | null = null) { + const content: SkillContent = { + name: skill.name, + description: skill.description, + instructions: skill.instructions, + frontmatter: frontmatter && Object.keys(frontmatter).length > 0 ? { ...frontmatter } : null, + files: (skill.references ?? []).map(({ path, content: text }) => ({ path, content: text })), + }; + return content; +} + +/** The `AgentSkill` shape the runtime and the API use, from one version row. */ +export function toAgentSkill(row: ResolvedSkillRow): AgentSkill { + return { + name: row.version.name, + description: row.version.description, + instructions: row.version.instructions, + ...(row.files.length + ? { references: row.files.map(({ path, content }) => ({ path, content })) } + : {}), + }; +} + +function assertHasInstructions(skill: AgentSkill): void { + if (!skill.instructions.trim()) throw new UserError('Skill instructions are required.'); +} + +function toRecord(rows: Map): Record { + return Object.fromEntries([...rows].map(([refId, row]) => [refId, toAgentSkill(row)])); +} + +/** + * The rules of skills: which version an agent runs, save, publish pins, revert pins, + * attach checks, edit permission and the delete guard. The runtime loads skills by id + * with no permission check. + */ +@Service() +export class SkillService { + constructor( + private readonly logger: Logger, + private readonly skillRepository: SkillRepository, + private readonly agentRepository: AgentRepository, + private readonly txRunner: TransactionRunner, + private readonly agentUpdateBroadcaster: AgentUpdateBroadcaster, + private readonly projectScopeService: ProjectScopeService, + ) {} + + // ---------------------------------------------------------------- reads + + /** + * What an agent draft runs, keyed by ref id: the latest version, or the pinned version + * of a ref with `versionId`. A pin to a version of another skill falls back to the latest. + */ + async resolveForAgentDraft( + refs: SkillRef[], + ctx: OperationContext = {}, + ): Promise> { + return toRecord(await this.resolveRows(refs, ctx)); + } + + /** The pinned versions of one published agent version, keyed by skill id. */ + async resolvePinned( + agentVersionId: string, + ctx: OperationContext = {}, + ): Promise> { + return toRecord(await this.skillRepository.findPinned(agentVersionId, ctx)); + } + + private async resolveRows( + refs: SkillRef[], + ctx: OperationContext, + ): Promise> { + const latest = await this.skillRepository.findLatestSaved( + refs.map((ref) => ref.id), + ctx, + ); + const pinnedIds = refs.flatMap((ref) => (ref.versionId ? [ref.versionId] : [])); + const pinned = await this.skillRepository.findVersionsByIds(pinnedIds, ctx); + const rows = new Map(); + for (const ref of refs) { + const pin = ref.versionId ? pinned.get(ref.versionId) : undefined; + const row = pin?.skill.id === ref.id ? pin : latest.get(ref.id); + if (row) rows.set(ref.id, row); + } + return rows; + } + + /** The names agents see: those of the latest versions. */ + private async latestNames(skillIds: string[], ctx: OperationContext) { + const rows = await this.skillRepository.findLatestSaved(skillIds, ctx); + return new Map([...rows].map(([id, row]) => [id, row.version.name])); + } + + /** + * The name each ref runs under: its pinned version's name, else the latest. Works per + * ref, because one agent can pin a skill that another agent follows. + */ + private async runtimeNames( + refs: Array<{ id: string; versionId?: string | null }>, + ctx: OperationContext, + ): Promise<(ref: { id: string; versionId?: string | null }) => string | undefined> { + const latest = await this.latestNames( + refs.map((ref) => ref.id), + ctx, + ); + const pinned = await this.skillRepository.findVersionsByIds( + refs.flatMap((ref) => (ref.versionId ? [ref.versionId] : [])), + ctx, + ); + return (ref) => { + const pin = ref.versionId ? pinned.get(ref.versionId) : undefined; + return pin?.skill.id === ref.id ? pin.version.name : latest.get(ref.id); + }; + } + + // ---------------------------------------------------------------- writes + + /** Creates a skill with its v1. Returns the new id. */ + async create( + input: { target: SkillTarget; skill: AgentSkill; source: SkillSource; createdById: string }, + ctx: OperationContext = {}, + ): Promise { + assertHasInstructions(input.skill); + const id = `skill_${generateNanoId()}`; + await this.skillRepository.createSkill( + { id, target: input.target, source: input.source, createdById: input.createdById }, + toSkillContent(input.skill), + ctx, + ); + this.logger.debug('Created skill', { skillId: id }); + return id; + } + + /** + * Save: merges the update onto the latest version and stores the result as the next + * version, unless the content did not change. Every agent that follows the skill then + * runs the new version, and each one that was in sync with its published version + * shows unpublished changes. `baseSkillHash` is checked under the edit lock, so two + * saves from the same base cannot both pass. + * + * When `ctx` has a transaction, the caller calls `refreshFollowingAgents` after its + * commit. `pushRef` is the tab that saved: it gets no reload push. + */ + async save( + skillId: string, + update: SkillUpdate, + userId: string, + ctx: OperationContext = {}, + pushRef?: string, + ): Promise { + const { saved, following } = await this.txRunner.run(ctx, async (txCtx) => { + await this.skillRepository.lockForEdit([skillId], txCtx); + const latest = (await this.skillRepository.findLatestSaved([skillId], txCtx)).get(skillId); + if (!latest) throw new NotFoundError('Skill not found'); + const current = toAgentSkill(latest); + const { baseSkillHash, allowedTools: _ignored, ...changes } = update; + if (baseSkillHash !== getAgentSkillHash(current)) { + throw new ConflictError( + 'The skill was changed somewhere else. Reload to get the latest version.', + ); + } + const skill: AgentSkill = { ...current, ...changes }; + if (!skill.references?.length) delete skill.references; + assertHasInstructions(skill); + const content = toSkillContent(skill, latest.version.frontmatter); + if (skillContentHash(content) === latest.version.contentHash) { + const unchanged = { versionId: latest.version.id, version: latest.version.version }; + const result = { ...unchanged, created: false, skill: current, followingAgentIds: [] }; + return { saved: result, following: [] }; + } + if (skill.name !== latest.version.name) { + await this.assertRenameKeepsNamesApart(skillId, latest.version.name, skill.name, txCtx); + } + const version = await this.skillRepository.nextVersionNumber(skillId, txCtx); + const versionId = await this.skillRepository.insertSavedVersion( + skillId, + version, + content, + userId, + txCtx, + ); + const followingIds = await this.skillRepository.findFollowingAgentIds([skillId], txCtx); + await this.agentRepository.markDraftChangedIfInSync(followingIds, txCtx); + const result = { versionId, version, created: true, skill, followingAgentIds: followingIds }; + return { saved: result, following: followingIds }; + }); + if (!ctx.trx) await this.refreshFollowingAgents(following, pushRef); + this.logger.debug('Saved skill', { + skillId, + version: saved.version, + created: saved.created, + following, + }); + return saved; + } + + /** + * After a save commits: following agents drop their cached runtime and their editors + * reload, except the tab of `excludePushRef`. + */ + async refreshFollowingAgents(agentIds: string[], excludePushRef?: string): Promise { + if (agentIds.length === 0) return; + // Imported on use: the runtime cache depends on services that will depend on this one. + const { AgentRuntimeCacheService } = await import('../agent-runtime-cache.service.js'); + const cache = Container.get(AgentRuntimeCacheService); + for (const agentId of agentIds) cache.clearRuntimes(agentId); + for (const agent of await this.agentRepository.findProjectIdsByIds(agentIds)) { + this.agentUpdateBroadcaster.notify( + { projectId: agent.projectId, agentId: agent.id, source: 'user' }, + excludePushRef, + ); + } + } + + private async assertRenameKeepsNamesApart( + skillId: string, + oldName: string, + newName: string, + ctx: OperationContext, + ): Promise { + const agents = await this.skillRepository.findFollowingAgents(skillId, ctx); + const refs = await this.skillRepository.findDependencies( + agents.map((agent) => agent.id), + ctx, + ); + const otherRefs = (agent: (typeof agents)[number]) => + (refs.get(agent.id) ?? []) + .filter((ref) => ref.skillId !== skillId) + .map((ref) => ({ id: ref.skillId, versionId: ref.versionId })); + const nameOf = await this.runtimeNames(agents.flatMap(otherRefs), ctx); + const clashing = agents.filter((agent) => + renameIntroducesClash( + otherRefs(agent).flatMap((ref) => nameOf(ref) ?? []), + oldName, + newName, + ), + ); + if (clashing.length > 0) { + throw new UserError( + `Cannot rename to "${newName}": ${clashing.map((agent) => agent.name).join(', ')} already ${ + clashing.length > 1 ? 'use' : 'uses' + } a skill with a name like that.`, + ); + } + } + + // ---------------------------------------------------------------- publish and revert + + /** + * Publish, step 1: the version each ref resolves to. Publish + * creates no version. Needs the caller's transaction for the publish lock. + */ + async snapshotForPublish( + refs: SkillRef[], + ctx: OperationContext, + ): Promise<{ skills: Record; versionByRef: Map }> { + const refIds = [...new Set(refs.map((ref) => ref.id))]; + await this.skillRepository.lockForPublish(refIds, ctx); + const rows = await this.resolveRows(refs, ctx); + const versionByRef = new Map([...rows].map(([refId, row]) => [refId, row.version.id])); + return { skills: toRecord(rows), versionByRef }; + } + + /** + * Publish, step 2: after the `agent_history` row exists. The pins keep the order of + * `versionByRef`, which is the order of the draft refs. + */ + async pinForPublish( + agentVersionId: string, + versionByRef: Map, + ctx: OperationContext, + ): Promise { + await this.skillRepository.insertPins( + [...versionByRef].map(([skillId, skillVersionId]) => ({ + agentVersionId, + skillId, + skillVersionId, + })), + ctx, + ); + } + + /** + * Revert: each ref gets a pin to the version that agent version used. No skill row is + * written, so other agents are not affected and no skill permission is needed. A ref + * with no pin follows the latest version. + */ + async restoreFromVersion( + agentVersionId: string, + refs: SkillRef[], + ctx: OperationContext = {}, + ): Promise { + const pinned = await this.skillRepository.findPinned(agentVersionId, ctx); + return refs.map(({ versionId: _dropped, ...ref }) => { + const row = pinned.get(ref.id); + return row ? { ...ref, versionId: row.version.id } : ref; + }); + } + + // ---------------------------------------------------------------- attach + + /** An agent can attach instance skills, the skills of its own project and its own agent skills. */ + isAttachable( + skill: Pick, + agent: { id: string; projectId: string }, + ): boolean { + if (skill.agentId !== null) return skill.agentId === agent.id; + return skill.projectId === null || skill.projectId === agent.projectId; + } + + /** + * The check an agent config save runs on the skill refs it gets. The agent's current + * refs come from its dependency rows. Unknown ids are dropped unless already + * attached. A ref keeps a pin only when the agent already had it. A new ref + * must be attachable and must not clash by name. + */ + async checkRefs( + agent: { id: string; projectId: string }, + refs: SkillRef[], + ctx: OperationContext = {}, + ): Promise { + const current = + (await this.skillRepository.findDependencies([agent.id], ctx)).get(agent.id) ?? []; + const existingIds = new Set(current.map((ref) => ref.skillId)); + const existingPins = new Map(current.map((ref) => [ref.skillId, ref.versionId])); + const found = new Map( + ( + await this.skillRepository.findByIds( + refs.map((ref) => ref.id), + ctx, + ) + ).map((skill) => [skill.id, skill]), + ); + const kept = refs + .filter((ref) => existingIds.has(ref.id) || found.has(ref.id)) + .map(({ versionId, ...ref }) => + versionId !== undefined && existingPins.get(ref.id) === versionId + ? { ...ref, versionId } + : ref, + ); + const newIds = [...new Set(kept.map((ref) => ref.id))].filter( + (id) => !existingIds.has(id) && found.has(id), + ); + if (newIds.length === 0) return kept; + // Shared lock until the attach commits, so `changeTarget` cannot narrow a skill in between. + if (ctx.trx) await this.skillRepository.lockForPublish(newIds, ctx); + + const keptExisting = kept.filter((ref) => existingIds.has(ref.id)); + const newRefs = newIds.map((id) => ({ id })); + const nameOf = await this.runtimeNames([...keptExisting, ...newRefs], ctx); + for (const id of newIds) { + const skill = found.get(id); + if (skill && !this.isAttachable(skill, agent)) { + throw new UserError( + `Skill "${nameOf({ id }) ?? id}" (${id}) is not available to this agent. An agent can use the skills of its own project, its own skills and instance skills.`, + ); + } + } + // A kept ref runs its pinned version, so compare the name of that version. + const clashes = findIntroducedNameClashes( + keptExisting.flatMap((ref) => nameOf(ref) ?? []), + newRefs.flatMap((ref) => nameOf(ref) ?? []), + ); + if (clashes.length > 0) { + throw new UserError( + `This agent already has a skill with a name like "${clashes.join('", "')}". Rename one of them, or detach the other skill first.`, + ); + } + return kept; + } + + /** + * Moves a skill to a project, one agent or the instance. Refused while an agent other + * than `keepAgentId` uses it. The edit lock makes a concurrent attach wait, so the check + * and the move see the same agents. + */ + async changeTarget( + skillId: string, + target: SkillTarget, + keepAgentId: string, + ctx: OperationContext = {}, + ): Promise { + await this.txRunner.run(ctx, async (txCtx) => { + await this.skillRepository.lockForEdit([skillId], txCtx); + const others = (await this.skillRepository.findUsingAgentIds(skillId, txCtx)).filter( + (id) => id !== keepAgentId, + ); + if (others.length > 0) { + throw new ConflictError( + 'Other agents use this skill. Detach it from those agents first, then change where it can be added.', + ); + } + await this.skillRepository.updateTarget(skillId, target, txCtx); + }); + } + + // ---------------------------------------------------------------- permission + + /** + * The project a skill's permissions come from: its own for a project skill, its + * agent's for an agent skill, none for an instance skill. A skill whose agent is gone + * has none either, and only the global scope can reach it. + */ + async projectOf( + skill: Pick, + ctx: OperationContext = {}, + ): Promise { + if (skill.projectId) return skill.projectId; + if (!skill.agentId) return null; + const agent = (await this.skillRepository.findAgents([skill.agentId], ctx)).get(skill.agentId); + return agent?.projectId ?? null; + } + + /** + * Whether the user may do `operation` on the skill, from the skill's own scope: + * `projectSkill:*` on the project of a project or agent skill, and the global + * `skill:*` for an instance skill. Every user may read an instance skill. + */ + async canAccess( + user: User, + skill: Pick, + operation: 'read' | 'update' | 'delete', + ): Promise { + const projectId = await this.projectOf(skill); + if (projectId) { + return await userHasScopes(user, [`projectSkill:${operation}`], false, { projectId }); + } + return this.canAccessInstanceSkill(user, skill, operation); + } + + /** + * `canAccess` for a whole list: one query for the user's projects, not one per skill. + * The caller passes each skill's project from `projectOf`, resolved in bulk. + */ + async accessCheck( + user: User, + operation: 'read' | 'update' | 'delete', + ): Promise<(skill: Pick, projectId: string | null) => boolean> { + const projectIds = await this.projectScopeService.getProjectIds(user, [ + `projectSkill:${operation}`, + ]); + const allowed = projectIds === null ? null : new Set(projectIds); + return (skill, projectId) => + projectId + ? allowed === null || allowed.has(projectId) + : this.canAccessInstanceSkill(user, skill, operation); + } + + private canAccessInstanceSkill( + user: User, + skill: Pick, + operation: 'read' | 'update' | 'delete', + ): boolean { + // An agent skill without a project lost its agent mid-request: only the global scope. + if (skill.agentId === null && operation === 'read') return true; + return hasGlobalScope(user, `skill:${operation}`); + } + + async canEdit(user: User, skill: Pick): Promise { + return await this.canAccess(user, skill, 'update'); + } + + async assertCanEdit(user: User, skillIds: string[], ctx: OperationContext = {}): Promise { + const skills = await this.skillRepository.findByIds(skillIds, ctx); + const names = await this.latestNames( + skills.map((skill) => skill.id), + ctx, + ); + const denied: string[] = []; + for (const skill of skills) { + if (!(await this.canEdit(user, skill))) { + denied.push(`"${names.get(skill.id) ?? skill.id}" (${skill.id})`); + } + } + if (denied.length > 0) { + throw new ForbiddenError( + `You can use but not edit ${denied.join(', ')}. Ask someone who can edit ${ + denied.length > 1 ? 'these skills' : 'this skill' + }, or detach it from this agent.`, + ); + } + } + + // ---------------------------------------------------------------- delete + + /** + * Deletes a skill that no agent draft and no published agent version uses. The conflict + * names the agents in `agentProjectIds` and only counts the others. + */ + async deleteSkill( + skillId: string, + agentProjectIds: string[] | 'all' = 'all', + ctx: OperationContext = {}, + ): Promise { + await this.txRunner.run(ctx, async (txCtx) => { + const [skill] = await this.skillRepository.findByIds([skillId], txCtx); + if (!skill) throw new NotFoundError('Skill not found'); + await this.skillRepository.lockForEdit([skillId], txCtx); + const usage = await this.skillRepository.findUsage(skillId, agentProjectIds, txCtx); + if (usage.drafts.length > 0 || usage.pins.length > 0 || usage.hiddenAgents > 0) { + const name = (await this.latestNames([skillId], txCtx)).get(skillId) ?? skillId; + const users = [ + ...usage.drafts.map((draft) => `${draft.agentName} (draft)`), + ...usage.pins.map( + (pin) => + `${pin.agentName} (${pin.version === null ? 'older published version' : `published v${pin.version}`})`, + ), + ]; + if (usage.hiddenAgents > 0) { + users.push( + `${usage.hiddenAgents} ${usage.hiddenAgents === 1 ? 'agent' : 'agents'} in other projects`, + ); + } + throw new ConflictError( + `Skill "${name}" is used by ${[...new Set(users)].join(', ')} and cannot be deleted.`, + ); + } + await this.skillRepository.deleteSkill(skillId, txCtx); + }); + this.logger.debug('Deleted skill', { skillId }); + } +} diff --git a/packages/cli/src/modules/agents/skills/skills-api.service.ts b/packages/cli/src/modules/agents/skills/skills-api.service.ts new file mode 100644 index 00000000000..b6e29aa4d7e --- /dev/null +++ b/packages/cli/src/modules/agents/skills/skills-api.service.ts @@ -0,0 +1,230 @@ +import type { + CreateSkillDto, + ListSkillsQueryDto, + SkillDetail, + SkillListItem, + SkillListResponse, + SkillSaveResponse, + SaveSkillDto, + SkillScope, +} from '@n8n/api-types'; +import { ProjectScopeService } from '@n8n/backend-services'; +import type { User } from '@n8n/db'; +import { Service } from '@n8n/di'; +import { ForbiddenError, NotFoundError, UserError } from '@n8n/errors'; +import { hasGlobalScope } from '@n8n/permissions'; + +import { userHasScopes } from '@/permissions.ee/check-access'; + +import type { Skill } from '../entities/skill.entity'; +import { SkillRepository, type SkillTarget } from '../repositories/skill.repository'; +import { getAgentSkillHash } from '../utils/agent-config-hash'; +import { SkillService, toAgentSkill } from './skill.service'; + +function scopeOf(skill: Pick): SkillScope { + if (skill.agentId) return 'agent'; + if (skill.projectId) return 'project'; + return 'instance'; +} + +/** + * Skills as the settings page sees them: list, read, create, save and delete. The + * permission comes from each skill's own scope (see `SkillService.canAccess`), so the + * routes carry no scope decorator. + */ +@Service() +export class SkillsApiService { + constructor( + private readonly skillService: SkillService, + private readonly skillRepository: SkillRepository, + private readonly projectScopeService: ProjectScopeService, + ) {} + + async list(user: User, query: ListSkillsQueryDto): Promise { + if (query.attachableTo !== undefined && (query.scope || query.projectId)) { + throw new UserError('Filter by attachableTo alone, without scope or projectId.'); + } + const projectIds = await this.projectScopeService.getProjectIds(user, ['projectSkill:list']); + const attachableTo = await this.attachTarget(query.attachableTo); + const { skills, count } = await this.skillRepository.findVisiblePage( + { projectIds: projectIds ?? 'all' }, + { + scope: query.scope, + projectId: query.projectId, + attachableTo, + search: query.search, + skip: query.skip, + take: query.take, + }, + ); + return { count, data: await this.toListItems(user, skills) }; + } + + async get(user: User, skillId: string): Promise { + return await this.toDetail(user, await this.requireAccess(user, skillId, 'read')); + } + + async create(user: User, payload: CreateSkillDto): Promise { + const target = await this.targetForCreate(user, payload); + const id = await this.skillService.create({ + target, + skill: payload.skill, + source: 'ui', + createdById: user.id, + }); + // No second access check: a custom role can create skills it cannot read later. + const [skill] = await this.skillRepository.findByIds([id]); + if (!skill) throw new NotFoundError('Skill not found'); + return await this.toDetail(user, skill); + } + + /** Saves the changes as the next version. Unchanged content creates nothing. */ + async update(user: User, skillId: string, payload: SaveSkillDto): Promise { + await this.requireAccess(user, skillId, 'update'); + const { followingAgentIds: _following, ...saved } = await this.skillService.save( + skillId, + { ...payload }, + user.id, + ); + return { id: skillId, ...saved, skillHash: getAgentSkillHash(saved.skill) }; + } + + async delete(user: User, skillId: string): Promise { + await this.requireAccess(user, skillId, 'delete'); + // The conflict message names only the agents the user may read, as the detail does. + const agentProjectIds = await this.projectScopeService.getProjectIds(user, ['agent:read']); + await this.skillService.deleteSkill(skillId, agentProjectIds ?? 'all'); + } + + private async toDetail(user: User, skill: Skill): Promise { + const [item] = await this.toListItems(user, [skill]); + const latest = (await this.skillRepository.findLatestSaved([skill.id])).get(skill.id); + if (!item || !latest) throw new NotFoundError('Skill not found'); + const content = toAgentSkill(latest); + // Any user can read an instance skill, so "used by" only names the agents they can read. + const agentProjectIds = await this.projectScopeService.getProjectIds(user, ['agent:read']); + return { + ...item, + // Name, description and number from the same row as the content, so a save that + // lands between the two reads cannot mix two versions. + name: latest.version.name, + description: latest.version.description, + latestVersion: latest.version.version, + skill: content, + skillHash: getAgentSkillHash(content), + usedBy: await this.skillRepository.findUsage(skill.id, agentProjectIds ?? 'all'), + }; + } + + /** A skill the user cannot see answers like a missing one. */ + private async requireAccess( + user: User, + skillId: string, + operation: 'read' | 'update' | 'delete', + ): Promise { + const [skill] = await this.skillRepository.findByIds([skillId]); + if (!skill || !(await this.skillService.canAccess(user, skill, 'read'))) { + throw new NotFoundError('Skill not found'); + } + if (operation !== 'read' && !(await this.skillService.canAccess(user, skill, operation))) { + throw new ForbiddenError( + operation === 'delete' + ? 'You are not allowed to delete this skill.' + : 'You can use but not edit this skill.', + ); + } + return skill; + } + + /** The agent of an `attachableTo` filter with its project. An unknown agent can attach nothing. */ + private async attachTarget( + agentId: string | undefined, + ): Promise<{ agentId: string; projectId: string } | undefined> { + if (agentId === undefined) return undefined; + const agent = (await this.skillRepository.findAgents([agentId])).get(agentId); + if (!agent) throw new NotFoundError('Agent not found'); + return { agentId, projectId: agent.projectId }; + } + + private async targetForCreate(user: User, payload: CreateSkillDto): Promise { + switch (payload.scope) { + case 'instance': + if (payload.projectId || payload.agentId) { + throw new UserError('An instance skill has no project and no agent.'); + } + if (!hasGlobalScope(user, 'skill:create')) { + throw new ForbiddenError('You are not allowed to create skills for the whole instance.'); + } + return { projectId: null, agentId: null }; + case 'project': { + const { projectId } = payload; + if (!projectId) throw new UserError('A project skill needs a project id.'); + if (payload.agentId) throw new UserError('A project skill has no agent.'); + await this.assertCanCreateIn(user, projectId); + // A global scope passes without looking at the project, so check that it exists. + if (!(await this.skillRepository.findProjectNames([projectId])).has(projectId)) { + throw new NotFoundError('Project not found'); + } + // A personal project keeps its own skills, as a team project does. + return { projectId, agentId: null }; + } + case 'agent': { + const { agentId } = payload; + if (!agentId) throw new UserError('An agent skill needs an agent id.'); + if (payload.projectId) + throw new UserError('An agent skill takes its project from the agent.'); + const agent = (await this.skillRepository.findAgents([agentId])).get(agentId); + if (!agent) throw new NotFoundError('Agent not found'); + await this.assertCanCreateIn(user, agent.projectId); + return { projectId: null, agentId }; + } + } + } + + private async assertCanCreateIn(user: User, projectId: string): Promise { + if (!(await userHasScopes(user, ['projectSkill:create'], false, { projectId }))) { + throw new ForbiddenError('You are not allowed to create skills for this project.'); + } + } + + private async toListItems(user: User, skills: Skill[]): Promise { + const ids = skills.map((skill) => skill.id); + // An agent skill has no projectId: resolve its project through its agent. + const agents = await this.skillRepository.findAgents( + skills.flatMap((skill) => (skill.agentId ? [skill.agentId] : [])), + ); + const projectOf = (skill: Skill) => + skill.projectId ?? (skill.agentId ? (agents.get(skill.agentId)?.projectId ?? null) : null); + const [latest, usage, projects, canEdit, canDelete] = await Promise.all([ + this.skillRepository.findLatestSummaries(ids), + this.skillRepository.countUsingAgents(ids), + this.skillRepository.findProjectNames(skills.flatMap((skill) => projectOf(skill) ?? [])), + this.skillService.accessCheck(user, 'update'), + this.skillService.accessCheck(user, 'delete'), + ]); + const items: SkillListItem[] = []; + for (const skill of skills) { + const summary = latest.get(skill.id); + if (!summary) continue; + const projectId = projectOf(skill); + items.push({ + id: skill.id, + name: summary.name, + description: summary.description, + scope: scopeOf(skill), + projectId, + projectName: projectId ? (projects.get(projectId) ?? null) : null, + agentId: skill.agentId, + agentName: skill.agentId ? (agents.get(skill.agentId)?.name ?? null) : null, + source: skill.source, + latestVersion: summary.version, + usedByAgents: usage.get(skill.id) ?? 0, + canEdit: canEdit(skill, projectId), + canDelete: canDelete(skill, projectId), + createdAt: skill.createdAt.toISOString(), + updatedAt: skill.updatedAt.toISOString(), + }); + } + return items; + } +} diff --git a/packages/cli/src/modules/agents/skills/skills-hub-rollout.ts b/packages/cli/src/modules/agents/skills/skills-hub-rollout.ts new file mode 100644 index 00000000000..9b637253e4d --- /dev/null +++ b/packages/cli/src/modules/agents/skills/skills-hub-rollout.ts @@ -0,0 +1,30 @@ +import { SKILLS_FLAG } from '@n8n/api-types'; +import { Logger } from '@n8n/backend-common'; +import { Service } from '@n8n/di'; + +import { PostHogClient } from '@/posthog'; + +/** + * Whether agents use the skills hub, from the PostHog flag `125_context_skills` for the + * instance. `init` reads the flag once at startup and the value holds for the life of the + * process, so the startup copy and every read agree. A change needs a restart. PostHog + * down or diagnostics off means off, unless `N8N_FEATURE_FLAG_OVERRIDES` turns it on. + */ +@Service() +export class SkillsHubRollout { + private enabled = false; + + constructor( + private readonly postHogClient: PostHogClient, + private readonly logger: Logger, + ) {} + + async init(): Promise { + this.enabled = (await this.postHogClient.getFeatureFlagForInstance(SKILLS_FLAG)) === true; + this.logger.debug('Read the skills hub rollout flag', { enabled: this.enabled }); + } + + get isEnabled(): boolean { + return this.enabled; + } +} diff --git a/packages/cli/src/modules/agents/skills/skills-hub-startup-copy.ts b/packages/cli/src/modules/agents/skills/skills-hub-startup-copy.ts new file mode 100644 index 00000000000..f9146819a2a --- /dev/null +++ b/packages/cli/src/modules/agents/skills/skills-hub-startup-copy.ts @@ -0,0 +1,392 @@ +import type { AgentSkill } from '@n8n/api-types'; +import { Logger } from '@n8n/backend-common'; +import { TransactionRunner, type OperationContext } from '@n8n/db'; +import { Service } from '@n8n/di'; +import { generateNanoId } from '@n8n/utils/generate-nano-id'; +import { InstanceSettings } from 'n8n-core'; + +import type { Agent } from '../entities/agent.entity'; +import type { AgentHistory } from '../entities/agent-history.entity'; +import { AgentRepository } from '../repositories/agent.repository'; +import { SkillRepository } from '../repositories/skill.repository'; +import { skillContentHash, type SkillContent } from './skill-content-hash'; +import { toSkillContent } from './skill.service'; +import { SkillsHubRollout } from './skills-hub-rollout'; + +/** `skill.id` is varchar(36). A longer inline ref id gets a new id. */ +const SKILL_ID_MAX_LENGTH = 36; + +const BATCH_SIZE = 100; + +/** How many agent ids the flag-off warning names. It counts all of them. */ +const WARN_AGENT_IDS = 20; + +type CopyCounts = { + agents: number; + skills: number; + versions: number; + pins: number; + failed: number; +}; + +/** What one agent's copy wrote. */ +type AgentCounts = Pick; + +type AgentWork = { + agent: Pick; + versions: Array>; + copyDraft: boolean; +}; + +type HubVersion = { id: string; skillId: string }; + +/** + * What one agent's copy knows: hub versions by content hash, the hub skill of each ref, + * and the ref that claimed each skill, so two refs with the same body keep two skills. + */ +type AgentCopyState = { + byHash: Map; + skillByRef: Map; + refBySkill: Map; + latest: Map; +}; + +/** + * Copies the inline skills of agents (`agents.skills`, `agent_history.skills`) into the + * skills hub when the rollout flag is on, so agents read and write only the hub. Each + * inline skill becomes an agent skill of its agent. The legacy columns stay as they are, + * so turning the flag off gives agents their inline skills back. + * + * Every main runs it at startup, before it serves agents. It does not wait for the + * leader: a main promoted during startup could miss both the startup check and the + * takeover event. Running it on several mains at once is safe, and so is running it again: + * - Each agent is copied in one transaction that holds the agent row, so a second main + * waits and then finds the hub rows. + * - A published version is copied only while it pins nothing. Its bodies become versions + * and it pins them. + * - A draft is copied only while the agent has no hub rows at all. Its refs become + * dependency rows, and its current text becomes the newest version of each skill. + * - Content that a skill of the agent already holds is reused, found by content hash. + * - Refs that were switched off are not copied. + */ +@Service() +export class SkillsHubStartupCopy { + constructor( + private readonly logger: Logger, + private readonly rollout: SkillsHubRollout, + private readonly instanceSettings: InstanceSettings, + private readonly agentRepository: AgentRepository, + private readonly skillRepository: SkillRepository, + private readonly txRunner: TransactionRunner, + ) {} + + /** Called when the agents module starts, after the rollout flag is read. */ + async runOnStartup(): Promise { + if (this.instanceSettings.instanceType !== 'main') return; + if (this.rollout.isEnabled) await this.copyAll(); + // One warning per instance is enough: only the leader logs it. + else if (this.instanceSettings.isLeader) await this.warnAboutHubOnlySkills(); + } + + async copyAll(): Promise { + const counts: CopyCounts = { agents: 0, skills: 0, versions: 0, pins: 0, failed: 0 }; + let after: Pick | null = null; + for (;;) { + const agents = await this.agentRepository.findPageForSkillCopy(after, BATCH_SIZE); + for (const agent of agents) { + try { + const copied = await this.copyAgentWithRetry(agent.id); + if (copied) { + counts.agents++; + counts.skills += copied.skills; + counts.versions += copied.versions; + counts.pins += copied.pins; + } + } catch (error) { + // One broken agent must not stop the others. Its copy rolls back, so the + // next start tries it again. + counts.failed++; + this.logger.error('Failed to copy the skills of an agent into the skills hub', { + agentId: agent.id, + error: error instanceof Error ? error.message : String(error), + }); + } + } + if (agents.length < BATCH_SIZE) break; + after = agents[agents.length - 1]; + } + this.logger.info('Copied inline agent skills into the skills hub', counts); + return counts; + } + + /** + * With the flag off, agents read their inline skills again. Skills that were added or + * changed in the hub while it was on are not there, so name the agents whose hub draft + * runs other content than their inline skills. + */ + private async warnAboutHubOnlySkills(): Promise { + const changed: string[] = []; + const withRefs = await this.skillRepository.findAgentIdsWithDraftRefs(); + for (let start = 0; start < withRefs.length; start += BATCH_SIZE) { + const page = withRefs.slice(start, start + BATCH_SIZE); + const hubHashes = await this.skillRepository.findDraftContentHashes(page); + for (const agentId of page) { + const agent = await this.agentRepository.findForSkillCopy(agentId); + const inline = agent + ? inlineSkills(agent).map(({ body }) => skillContentHash(toSkillContent(body))) + : []; + if (!sameHashes(inline, hubHashes.get(agentId) ?? [])) changed.push(agentId); + } + } + const count = changed.length; + if (count === 0) return; + const agentIds = changed.slice(0, WARN_AGENT_IDS); + this.logger.warn( + 'The skills hub is off, so agents run their inline skills. Skills that were added or changed in the hub while it was on are not available to these agents until it is on again.', + { agents: count, agentIds }, + ); + } + + /** + * Two mains can pick the same free inline id for two different agents at the same + * time, so one of them fails on the primary key. A second try picks another id. A + * failed try rolls back, so only the counts of the try that commits are kept. + */ + private async copyAgentWithRetry(agentId: string): Promise { + // Most agents have nothing left to copy after the first start. Check that without + // a transaction and a row lock, and check again under the lock. + if (!(await this.findWork(agentId, {}))) return null; + try { + return await this.copyAgent(agentId); + } catch { + return await this.copyAgent(agentId); + } + } + + /** + * What one agent still needs: the published versions that pin nothing and have inline + * skills, and its draft while it has no hub rows. Null when nothing is left. + */ + private async findWork(agentId: string, ctx: OperationContext): Promise { + const agent = await this.agentRepository.findForSkillCopy(agentId, ctx); + if (!agent) return null; + const versions = (await this.skillRepository.findUnpinnedVersions(agentId, ctx)).filter( + (version) => inlineSkills(version).length > 0, + ); + const copyDraft = + inlineSkills(agent).length > 0 && !(await this.skillRepository.hasHubState(agentId, ctx)); + if (versions.length === 0 && !copyDraft) return null; + return { agent, versions, copyDraft }; + } + + /** Copies one agent in one transaction. Returns null when it wrote nothing. */ + private async copyAgent(agentId: string): Promise { + return await this.txRunner.run({}, async (ctx) => { + // A draft write to this agent waits until the copy commits. The agent row and the + // hub-row check are read under the lock, so the copy never uses stale inline + // content or replaces refs written meanwhile. + await this.agentRepository.lockForSkillCopy(agentId, ctx); + const work = await this.findWork(agentId, ctx); + if (!work) return null; + const { agent, versions, copyDraft } = work; + const counts: AgentCounts = { skills: 0, versions: 0, pins: 0 }; + + const state = await this.loadState(agent.id, ctx); + for (const version of versions) { + const pins: Array<{ agentVersionId: string; skillId: string; skillVersionId: string }> = []; + for (const { refId, body } of inlineSkills(version)) { + const pinned = await this.versionFor(agent, refId, body, false, state, counts, ctx); + if (!pins.some((pin) => pin.skillId === pinned.skillId)) { + pins.push({ + agentVersionId: version.versionId, + skillId: pinned.skillId, + skillVersionId: pinned.id, + }); + } + } + await this.skillRepository.insertPins(pins, ctx); + counts.pins += pins.length; + } + if (copyDraft) { + const refs: Array<{ skillId: string }> = []; + for (const { refId, body } of inlineSkills(agent)) { + // The draft runs the newest version, so its text must be the newest one. + const { skillId } = await this.versionFor(agent, refId, body, true, state, counts, ctx); + if (!refs.some((ref) => ref.skillId === skillId)) refs.push({ skillId }); + } + await this.skillRepository.replaceDependencies(agent.id, refs, ctx); + } + return counts; + }); + } + + private async loadState(agentId: string, ctx: OperationContext): Promise { + const state: AgentCopyState = { + byHash: new Map(), + skillByRef: new Map(), + refBySkill: new Map(), + latest: new Map(), + }; + for (const row of await this.skillRepository.findAgentSkillVersions(agentId, ctx)) { + addByHash(state, row.contentHash, { id: row.id, skillId: row.skillId }); + const current = state.latest.get(row.skillId); + if (!current || row.version > current.version) { + state.latest.set(row.skillId, { + versionId: row.id, + hash: row.contentHash, + version: row.version, + }); + } + } + return state; + } + + /** + * The hub version that holds this inline body. A ref seen before uses its own skill: a + * version with the same content, else a new version. A new ref reuses a skill with the + * same content that no other ref claimed, else creates an agent skill. With + * `mustBeLatest`, a match that is not the newest version of its skill gets the body + * again as the newest one. + */ + private async versionFor( + agent: Pick, + refId: string, + body: AgentSkill, + mustBeLatest: boolean, + state: AgentCopyState, + counts: AgentCounts, + ctx: OperationContext, + ): Promise { + const content = toSkillContent(body); + const hash = skillContentHash(content); + const matches = state.byHash.get(hash) ?? []; + const skillId = + state.skillByRef.get(refId) ?? + matches.find((version) => !state.refBySkill.has(version.skillId))?.skillId; + if (skillId) { + claim(state, refId, skillId); + const match = matches.find((version) => version.skillId === skillId); + if (match && (!mustBeLatest || state.latest.get(skillId)?.hash === hash)) return match; + return await this.addVersion(skillId, content, hash, state, counts, ctx); + } + + const id = await this.newSkillId(refId, ctx); + const versionId = await this.skillRepository.createSkill( + { id, target: { projectId: null, agentId: agent.id }, source: 'agent', createdById: null }, + content, + ctx, + ); + const version = { id: versionId, skillId: id }; + addByHash(state, hash, version); + claim(state, refId, id); + state.latest.set(id, { versionId, hash, version: 1 }); + counts.skills++; + counts.versions++; + return version; + } + + private async addVersion( + skillId: string, + content: SkillContent, + hash: string, + state: AgentCopyState, + counts: AgentCounts, + ctx: OperationContext, + ): Promise { + const next = (state.latest.get(skillId)?.version ?? 0) + 1; + const id = await this.skillRepository.insertSavedVersion(skillId, next, content, null, ctx); + const version = { id, skillId }; + addByHash(state, hash, version); + state.latest.set(skillId, { versionId: id, hash, version: next }); + counts.versions++; + return version; + } + + /** Keeps the inline ref id when it is free and short enough, else a new one. */ + private async newSkillId(refId: string, ctx: OperationContext): Promise { + if ( + refId.length <= SKILL_ID_MAX_LENGTH && + !(await this.skillRepository.existsById(refId, ctx)) + ) { + return refId; + } + return `skill_${generateNanoId()}`; + } +} + +/** Whether two lists hold the same hashes, in any order. */ +function sameHashes(left: string[], right: string[]): boolean { + if (left.length !== right.length) return false; + const sortedRight = [...right].sort(); + return [...left].sort().every((hash, index) => hash === sortedRight[index]); +} + +/** Keeps one version of each skill for each content: the first one seen, which is the oldest. */ +function addByHash(state: AgentCopyState, hash: string, version: HubVersion): void { + const versions = state.byHash.get(hash) ?? []; + if (!versions.some((known) => known.skillId === version.skillId)) versions.push(version); + state.byHash.set(hash, versions); +} + +function claim(state: AgentCopyState, refId: string, skillId: string): void { + state.skillByRef.set(refId, skillId); + state.refBySkill.set(skillId, refId); +} + +/** + * The inline skills of a draft or a published version, in ref order: each ref that is + * not switched off and has a body the runtime could load. + */ +function inlineSkills( + source: Pick, +): Array<{ refId: string; body: AgentSkill }> { + const refs: unknown = (source.schema as { skills?: unknown } | null)?.skills; + if (!Array.isArray(refs)) return []; + const bodies = source.skills ?? {}; + const seen = new Set(); + const result: Array<{ refId: string; body: AgentSkill }> = []; + for (const ref of refs as unknown[]) { + if (!isRecord(ref) || ref.type !== 'skill' || typeof ref.id !== 'string') continue; + if (ref.enabled === false || seen.has(ref.id)) continue; + seen.add(ref.id); + const body = toInlineBody(Object.hasOwn(bodies, ref.id) ? bodies[ref.id] : undefined); + if (body) result.push({ refId: ref.id, body }); + } + return result; +} + +function isRecord(value: unknown): value is Record { + return typeof value === 'object' && value !== null && !Array.isArray(value); +} + +/** Null for a body the runtime could not load either. A repeated file path keeps its first copy. */ +function toInlineBody(raw: unknown): AgentSkill | null { + if (!isRecord(raw)) return null; + const { name, description, instructions, references } = raw; + if ( + typeof name !== 'string' || + typeof description !== 'string' || + typeof instructions !== 'string' + ) { + return null; + } + const files = new Map(); + if (Array.isArray(references)) { + for (const file of references as unknown[]) { + if ( + isRecord(file) && + typeof file.path === 'string' && + typeof file.content === 'string' && + !files.has(file.path) + ) { + files.set(file.path, { path: file.path, content: file.content }); + } + } + } + return { + name, + description, + instructions, + ...(files.size > 0 ? { references: [...files.values()] } : {}), + }; +} diff --git a/packages/cli/src/modules/agents/sub-agents/__tests__/delegate-sub-agent-tool.test.ts b/packages/cli/src/modules/agents/sub-agents/__tests__/delegate-sub-agent-tool.test.ts index 1dc6ca91e47..b93f7809633 100644 --- a/packages/cli/src/modules/agents/sub-agents/__tests__/delegate-sub-agent-tool.test.ts +++ b/packages/cli/src/modules/agents/sub-agents/__tests__/delegate-sub-agent-tool.test.ts @@ -343,6 +343,32 @@ describe('createN8nDelegateSubAgentTool', () => { ); }); + it('fails loudly when an inline sub-agent has no parent identity', async () => { + const tool = createN8nDelegateSubAgentTool({ + runner, + sourcesById: { 'agent-2': source }, + projectId, + credentialProvider, + runType: 'production', + } as unknown as Parameters[0]); + + await expect( + tool.handler?.( + { + subAgentId: INLINE_SUB_AGENT_ID, + taskName: 'Research API', + goal: 'Find behavior.', + }, + { runId: 'parent-run-1' }, + ), + ).resolves.toMatchObject({ + status: 'failed', + answer: '', + error: 'Inline sub-agent parent Agent identity is missing', + }); + expect(runner.run).not.toHaveBeenCalled(); + }); + it('routes a configured child resume to the exact persisted checkpoint', async () => { runner.resumeForeground.mockResolvedValue(foregroundResult); const parentExecutionCounter = { diff --git a/packages/cli/src/modules/agents/sub-agents/__tests__/sub-agent-runner.test.ts b/packages/cli/src/modules/agents/sub-agents/__tests__/sub-agent-runner.test.ts index 0c4f969d6af..5d3fc1c063b 100644 --- a/packages/cli/src/modules/agents/sub-agents/__tests__/sub-agent-runner.test.ts +++ b/packages/cli/src/modules/agents/sub-agents/__tests__/sub-agent-runner.test.ts @@ -32,6 +32,7 @@ import { hashAgentSandboxPrincipal, } from '../../agent-sandbox-principal'; import type { AgentSandboxRuntime } from '../../agent-sandbox-runtime.service'; +import { AgentSpendLedger } from '../../budget-guardrail'; import type { N8NCheckpointStorage } from '../../integrations/n8n-checkpoint-storage'; import { SubAgentRunner } from '../sub-agent-runner'; import type { @@ -665,13 +666,14 @@ describe('SubAgentRunner', () => { expect(childAgent.close).toHaveBeenCalledTimes(1); }); - it('reports a guardrail stop as a completion that carries the finish reason', async () => { + it('reports a guardrail stop as a failure that carries the stop code', async () => { childAgent.stream.mockResolvedValue( makeStreamResult([ { type: 'text-delta', id: 'text-1', delta: 'Partial answer' }, { type: 'finish', finishReason: 'guardrail', guardrail: { code: 'budget.session' } }, ]), ); + const onBudgetNotice = vi.fn(); await expect( runner.run(spawnRequest, { @@ -679,14 +681,122 @@ describe('SubAgentRunner', () => { projectId, credentialProvider, runType: 'production', + onBudgetNotice, }), ).resolves.toMatchObject({ - status: 'completed', + status: 'failed', result: { runId: 'child-run-1', finishReason: 'guardrail', + guardrail: { code: 'budget.session' }, }, }); + expect(onBudgetNotice).toHaveBeenCalledWith({ code: 'budget.session' }); + }); + + it('names the child as the budget owner on a monthly guardrail stop', async () => { + childAgent.stream.mockResolvedValue( + makeStreamResult([ + { type: 'text-delta', id: 'text-1', delta: 'Partial answer' }, + { type: 'finish', finishReason: 'guardrail', guardrail: { code: 'budget.monthly' } }, + ]), + ); + const onBudgetNotice = vi.fn(); + + await expect( + runner.run(spawnRequest, { + parentAgentId, + projectId, + credentialProvider, + runType: 'production', + onBudgetNotice, + }), + ).resolves.toMatchObject({ + status: 'failed', + result: { + runId: 'child-run-1', + finishReason: 'guardrail', + guardrail: { code: 'budget.monthly' }, + }, + }); + expect(onBudgetNotice).toHaveBeenCalledWith({ + code: 'budget.monthly', + agentId: 'agent-1', + }); + }); + + it('does not emit a budget notice for a non-budget guardrail stop', async () => { + childAgent.stream.mockResolvedValue( + makeStreamResult([ + { type: 'text-delta', id: 'text-1', delta: 'Partial answer' }, + { type: 'finish', finishReason: 'guardrail', guardrail: { code: 'budget.misconfigured' } }, + ]), + ); + const onBudgetNotice = vi.fn(); + + await expect( + runner.run(spawnRequest, { + parentAgentId, + projectId, + credentialProvider, + runType: 'production', + onBudgetNotice, + }), + ).resolves.toMatchObject({ + status: 'failed', + result: { finishReason: 'guardrail' }, + }); + expect(onBudgetNotice).not.toHaveBeenCalled(); + }); + + it('forwards the budget notice sink into the child guardrail options', async () => { + Container.set(AgentSpendLedger, mock()); + const onBudgetNotice = vi.fn(); + + await runner.run(spawnRequest, { + parentAgentId, + projectId, + credentialProvider, + runType: 'production', + rootSessionId: parentThreadId, + rootSessionCapUsd: 5, + onBudgetNotice, + }); + + const options = childAgent.stream.mock.calls[0]?.[1]; + const sink = options?.guardrails?.onNotice; + expect(sink).toBeDefined(); + // A locally-originated notice gets this child's source id. + sink?.({ code: 'budget.alert' }); + expect(onBudgetNotice).toHaveBeenCalledWith({ code: 'budget.alert', agentId: 'agent-1' }); + // A deeper child's stamp survives: the innermost owner wins. + sink?.({ code: 'budget.alert', agentId: 'grandchild-1' }); + expect(onBudgetNotice).toHaveBeenCalledWith({ + code: 'budget.alert', + agentId: 'grandchild-1', + }); + // A session stop always spends the root bucket, so it carries no owner. + sink?.({ code: 'budget.session', agentId: 'grandchild-1' }); + expect(onBudgetNotice).toHaveBeenCalledWith({ code: 'budget.session' }); + sink?.({ code: 'pii.block' }); + expect(onBudgetNotice).toHaveBeenCalledTimes(3); + }); + + it('installs the notice ferry even when the child has no budget bucket', async () => { + Container.set(AgentSpendLedger, mock()); + const onBudgetNotice = vi.fn(); + + await runner.run(spawnRequest, { + parentAgentId, + projectId, + credentialProvider, + runType: 'production', + onBudgetNotice, + }); + + const options = childAgent.stream.mock.calls[0]?.[1]; + expect(options?.guardrails?.hooks).toEqual([]); + expect(options?.guardrails?.onNotice).toBeDefined(); }); it('applies the self-delegation model while preserving the parent draft', async () => { diff --git a/packages/cli/src/modules/agents/sub-agents/__tests__/sub-agent-source-resolver.test.ts b/packages/cli/src/modules/agents/sub-agents/__tests__/sub-agent-source-resolver.test.ts index d63838f8e0d..f1a16ffcb8d 100644 --- a/packages/cli/src/modules/agents/sub-agents/__tests__/sub-agent-source-resolver.test.ts +++ b/packages/cli/src/modules/agents/sub-agents/__tests__/sub-agent-source-resolver.test.ts @@ -13,6 +13,7 @@ import { type AgentFixtureOverrides, type AgentHistoryFixtureOverrides, createAgentSkillRefsService, + type FakeAgentSkillRefsService, } from '../../__tests__/test-utils/stored-agent-config'; const projectId = 'project-1'; @@ -27,6 +28,7 @@ const runnableConfig: AgentJsonConfig = { config: { maxIterations: 5, }, + skills: [], }; const customToolDescriptor: ToolDescriptor = { @@ -51,7 +53,6 @@ function makeAgentHistory(overrides: AgentHistoryFixtureOverrides = {}): AgentHi versionId, schema: runnableConfig, tools: {}, - skills: {}, ...overrides, } as unknown as AgentHistory; } @@ -65,7 +66,6 @@ function makeAgent(overrides: AgentFixtureOverrides = {}): Agent { schema: runnableConfig, integrations: [], tools: {}, - skills: {}, activeVersionId: versionId, activeVersion: makeAgentHistory(), ...overrides, @@ -75,17 +75,15 @@ function makeAgent(overrides: AgentFixtureOverrides = {}): Agent { describe('SubAgentSourceResolver', () => { let agentRepository: Mocked; let agentHistoryRepository: Mocked; + let skillRefs: FakeAgentSkillRefsService; let resolver: SubAgentSourceResolver; beforeEach(() => { vi.clearAllMocks(); agentRepository = mock(); agentHistoryRepository = mock(); - resolver = new SubAgentSourceResolver( - agentRepository, - agentHistoryRepository, - createAgentSkillRefsService(agentRepository), - ); + skillRefs = createAgentSkillRefsService(); + resolver = new SubAgentSourceResolver(agentRepository, agentHistoryRepository, skillRefs); }); it('resolves the latest draft when no version is pinned', async () => { @@ -123,18 +121,21 @@ describe('SubAgentSourceResolver', () => { }); it('retains background configuration and tool bodies after a draft edit', async () => { + skillRefs.readDraft.mockResolvedValueOnce({ + skillRefs: [{ type: 'skill', id: 'original_skill' }], + skills: { + original_skill: { + name: 'Original skill', + description: 'Original description', + instructions: 'Original skill body', + }, + }, + }); agentRepository.findByIdAndProjectId.mockResolvedValue( makeAgent({ tools: { lookup: { descriptor: customToolDescriptor, code: 'original tool body' }, }, - skills: { - original_skill: { - name: 'Original skill', - description: 'Original description', - instructions: 'Original skill body', - }, - }, }), ); const original = await resolver.resolveForRuntime({ agentId }, { projectId }); @@ -241,6 +242,26 @@ describe('SubAgentSourceResolver', () => { }); it('resolves runtime assets from the draft, not the published version', async () => { + skillRefs.readDraft.mockResolvedValue({ + skillRefs: [{ type: 'skill', id: 'draft_skill' }], + skills: { + draft_skill: { + name: 'Draft skill', + description: 'Draft description', + instructions: 'Draft body', + }, + }, + }); + skillRefs.readVersion.mockResolvedValue({ + skillRefs: [{ type: 'skill', id: 'published_skill' }], + skills: { + published_skill: { + name: 'Published skill', + description: 'Published description', + instructions: 'Published body', + }, + }, + }); agentRepository.findByIdAndProjectId.mockResolvedValue( makeAgent({ tools: { @@ -249,13 +270,6 @@ describe('SubAgentSourceResolver', () => { descriptor: { ...customToolDescriptor, name: 'draft_only_tool' }, }, }, - skills: { - draft_skill: { - name: 'Draft skill', - description: 'Draft description', - instructions: 'Draft body', - }, - }, activeVersion: makeAgentHistory({ tools: { published_tool: { @@ -263,13 +277,6 @@ describe('SubAgentSourceResolver', () => { descriptor: { ...customToolDescriptor, name: 'published_tool' }, }, }, - skills: { - published_skill: { - name: 'Published skill', - description: 'Published description', - instructions: 'Published body', - }, - }, }), }), ); @@ -332,13 +339,13 @@ describe('SubAgentSourceResolver', () => { describe('skill refs round trip', () => { const draftRefs = [ { type: 'skill' as const, id: 'zeta' }, - { type: 'skill' as const, id: 'alpha', enabled: false }, + { type: 'skill' as const, id: 'alpha', versionId: '0b2c6f1e-7d3a-4c1b-9f2e-5a6b7c8d9e0f' }, ]; const publishedRefs = [ - { type: 'skill' as const, id: 'mid', enabled: true }, + { type: 'skill' as const, id: 'mid' }, { type: 'skill' as const, id: 'zeta' }, ]; - const pinnedRefs = [{ type: 'skill' as const, id: 'old', enabled: false }]; + const pinnedRefs = [{ type: 'skill' as const, id: 'old' }]; beforeEach(() => { agentRepository.findByIdAndProjectId.mockResolvedValue( diff --git a/packages/cli/src/modules/agents/sub-agents/delegate-sub-agent-tool.ts b/packages/cli/src/modules/agents/sub-agents/delegate-sub-agent-tool.ts index f95834aad02..43ab33e593d 100644 --- a/packages/cli/src/modules/agents/sub-agents/delegate-sub-agent-tool.ts +++ b/packages/cli/src/modules/agents/sub-agents/delegate-sub-agent-tool.ts @@ -101,6 +101,9 @@ export function createN8nDelegateSubAgentTool(options: CreateN8nDelegateSubAgent ...(isSelfDelegation && request.difficulty !== undefined ? { selfDelegationDifficulty: request.difficulty } : {}), + ...(request.parentOnGuardrailNotice !== undefined + ? { onBudgetNotice: request.parentOnGuardrailNotice } + : {}), }, ); @@ -130,6 +133,9 @@ export function createN8nDelegateSubAgentTool(options: CreateN8nDelegateSubAgent ...(request.subAgentId === INLINE_SUB_AGENT_ID && request.difficulty !== undefined ? { selfDelegationDifficulty: request.difficulty } : {}), + ...(request.parentOnGuardrailNotice !== undefined + ? { onBudgetNotice: request.parentOnGuardrailNotice } + : {}), }; const result = request.subAgentId === INLINE_SUB_AGENT_ID diff --git a/packages/cli/src/modules/agents/sub-agents/sub-agent-runner.ts b/packages/cli/src/modules/agents/sub-agents/sub-agent-runner.ts index 404087d2337..258a1289d1c 100644 --- a/packages/cli/src/modules/agents/sub-agents/sub-agent-runner.ts +++ b/packages/cli/src/modules/agents/sub-agents/sub-agent-runner.ts @@ -20,6 +20,7 @@ import { type SubAgentTaskPath, } from '@n8n/agents'; import type { + AgentBudgetNotice, ResolvedSubAgentSource, RunnableAgentJsonConfig, SubAgentSource, @@ -118,6 +119,8 @@ export interface SubAgentRunContext { beforeResume?: () => Promise; shouldPause?: () => Promise; runtimeSnapshot?: string; + /** Preview-chat budget sink forwarded from the root run. Absent elsewhere. */ + onBudgetNotice?: (notice: AgentBudgetNotice) => void; } export interface SubAgentRunResult { @@ -345,6 +348,15 @@ export class SubAgentRunner { agent = reconstructed.agent; context.abortSignal?.throwIfAborted(); + const forwardBudgetNotice = context.onBudgetNotice + ? (notice: AgentBudgetNotice) => + context.onBudgetNotice?.( + notice.code === 'budget.session' + ? { code: notice.code } + : // The innermost budget owner wins. + { ...notice, agentId: notice.agentId ?? runtimeSource.source.sourceId }, + ) + : undefined; const executionOptions = withBudgetGuardrail( { approvalContext: await this.toolApprovalService.createContext( @@ -363,6 +375,7 @@ export class SubAgentRunner { sessionId: context.rootSessionId, agentId: runtimeSource.source.sourceId, rootSessionCapUsd: context.rootSessionCapUsd, + ...(forwardBudgetNotice !== undefined ? { onNotice: forwardBudgetNotice } : {}), }, ); context.abortSignal?.throwIfAborted(); @@ -428,6 +441,15 @@ export class SubAgentRunner { if (result.finishReason === 'paused') status = 'paused'; else if (suspended) status = 'suspended'; else if (result.finishReason === 'error' || result.error !== undefined) status = 'failed'; + else if (result.finishReason === 'guardrail') { + // A budget stop is not a completed task: the parent model gets a + // failure with the reason, and the preview chat gets the card. + status = 'failed'; + const code = result.guardrail?.code; + if (code === 'budget.session' || code === 'budget.monthly') { + forwardBudgetNotice?.({ code }); + } + } return { taskPath: operation.taskPath, @@ -520,6 +542,7 @@ async function consumeAgentStream( const pendingSuspend: NonNullable = []; let structuredOutput: unknown; let executionError: unknown; + let guardrail: GenerateResult['guardrail']; for await (const value of streamAgentChunks(resultStream.stream)) { recorder.record(value); @@ -541,8 +564,11 @@ async function consumeAgentStream( ...(value.resumeSchema !== undefined ? { resumeSchema: value.resumeSchema } : {}), }); } - if (value.type === 'finish' && value.structuredOutput !== undefined) { - structuredOutput = value.structuredOutput; + if (value.type === 'finish') { + if (value.structuredOutput !== undefined) structuredOutput = value.structuredOutput; + // The recorder keeps only the finish reason; the stop code lives + // on the chunk, so capture it here or it is lost. + if (value.guardrail !== undefined) guardrail = value.guardrail; } } @@ -555,6 +581,7 @@ async function consumeAgentStream( structuredOutput, () => resultStream.getState(), pendingSuspend, + guardrail, ), }; } @@ -640,6 +667,7 @@ function buildGenerateResultFromRecord( structuredOutput: unknown, getState: () => SerializableAgentState, pendingSuspend: NonNullable = [], + guardrail?: GenerateResult['guardrail'], ): GenerateResult { const messages = createAssistantMessages(record.assistantResponse); const finishReason = isFinishReason(record.finishReason) ? record.finishReason : undefined; @@ -659,6 +687,7 @@ function buildGenerateResultFromRecord( ...(structuredOutput !== undefined ? { structuredOutput } : {}), ...(record.error !== null ? { error: record.error } : {}), ...(pendingSuspend.length > 0 ? { pendingSuspend } : {}), + ...(guardrail !== undefined ? { guardrail } : {}), getState, }; return result; diff --git a/packages/cli/src/modules/agents/sub-agents/sub-agent-source-resolver.ts b/packages/cli/src/modules/agents/sub-agents/sub-agent-source-resolver.ts index 4f87a6dd1e2..d94c60e4e82 100644 --- a/packages/cli/src/modules/agents/sub-agents/sub-agent-source-resolver.ts +++ b/packages/cli/src/modules/agents/sub-agents/sub-agent-source-resolver.ts @@ -93,15 +93,14 @@ export class SubAgentSourceResolver { ); } + const { skillRefs, skills } = await this.agentSkillRefs.readVersion(version, {}); return { source: { sourceId: source.agentId, versionId: source.versionId, - config: this.toRunnableConfig( - toAgentDocument(version.schema, await this.agentSkillRefs.refsForVersion(version, {})), - ), + config: this.toRunnableConfig(toAgentDocument(version.schema, skillRefs)), }, - ...getAgentRuntimeAssets(version), + ...getAgentRuntimeAssets(version, skills), }; } @@ -113,18 +112,14 @@ export class SubAgentSourceResolver { ); } + const { skillRefs, skills } = await this.agentSkillRefs.readVersion(activeVersion, {}); return { source: { sourceId: source.agentId, versionId: activeVersion.versionId, - config: this.toRunnableConfig( - toAgentDocument( - activeVersion.schema, - await this.agentSkillRefs.refsForVersion(activeVersion, {}), - ), - ), + config: this.toRunnableConfig(toAgentDocument(activeVersion.schema, skillRefs)), }, - ...getAgentRuntimeAssets(activeVersion), + ...getAgentRuntimeAssets(activeVersion, skills), }; } @@ -132,14 +127,13 @@ export class SubAgentSourceResolver { throw new UserError(`Sub-agent "${source.agentId}" has no config`); } + const { skillRefs, skills } = await this.agentSkillRefs.readDraft(agent, {}); return { source: { sourceId: source.agentId, - config: this.toRunnableConfig( - toAgentDocument(agent.schema, await this.agentSkillRefs.refsForDraft(agent, {})), - ), + config: this.toRunnableConfig(toAgentDocument(agent.schema, skillRefs)), }, - ...getAgentRuntimeAssets(agent), + ...getAgentRuntimeAssets(agent, skills), }; } diff --git a/packages/cli/src/modules/agents/tools/__tests__/node-tool-factory.test.ts b/packages/cli/src/modules/agents/tools/__tests__/node-tool-factory.test.ts index c362a22bb72..a75ba8710ce 100644 --- a/packages/cli/src/modules/agents/tools/__tests__/node-tool-factory.test.ts +++ b/packages/cli/src/modules/agents/tools/__tests__/node-tool-factory.test.ts @@ -1,12 +1,25 @@ import type { AgentJsonToolConfig } from '@n8n/api-types'; +import type { PolicyViolation } from '@n8n/decorators'; import { Container } from '@n8n/di'; +import { hasPolicyRefusalMarker } from 'n8n-workflow'; import { z } from 'zod'; import type { EphemeralNodeExecutor } from '@/node-execution'; import { NodeTypes } from '@/node-types'; +import type { NonEmptyViolations } from '@/policy/policy-violation.error'; import { resolveNodeTool } from '../node-tool-factory'; +const violation = (overrides: Partial = {}): PolicyViolation => ({ + kind: 'node-type-unavailable', + checkId: 'node-type-availability', + message: 'The node type n8n-nodes-base.googleDrive is not available on this instance', + subject: 'n8n-nodes-base.googleDrive', + subjectType: 'nodeType', + scope: 'instance', + ...overrides, +}); + // The node-tool-factory imports the DI `Container` to look up NodeTypes inside // `resolveInputSchema` (for auto-seeding a `{ input: string }` schema on // native tools). In the unit-test scope the container isn't registered and @@ -212,6 +225,48 @@ describe('resolveNodeTool → tool name sanitization', () => { }); }); +describe('resolveNodeTool → policy refusal', () => { + it('returns a policy refusal in the serialized refusal shape instead of throwing', async () => { + const violations: NonEmptyViolations = [violation()]; + const executeInline = vi.fn().mockResolvedValue({ + status: 'error', + data: [], + error: 'Node type is not permitted for agent tool execution', + violations, + }); + + const tool = await resolveNodeTool(baseToolSchema, { + executor: { executeInline } as unknown as EphemeralNodeExecutor, + projectId: 'p1', + }); + + const output = await tool.handler!({}, {} as never); + expect(output).toEqual({ + isPolicyRefusal: true, + message: 'Node type is not permitted for agent tool execution', + violations, + instruction: expect.stringMatching(/do not retry/i), + }); + expect(output).toMatchObject({ instruction: expect.stringMatching(/tell the user/i) }); + expect(hasPolicyRefusalMarker(output)).toBe(true); + }); + + it('throws for an ordinary executor error with no violations, as before', async () => { + const executeInline = vi.fn().mockResolvedValue({ + status: 'error', + data: [], + error: 'boom', + }); + + const tool = await resolveNodeTool(baseToolSchema, { + executor: { executeInline } as unknown as EphemeralNodeExecutor, + projectId: 'p1', + }); + + await expect(tool.handler!({}, {} as never)).rejects.toThrow('boom'); + }); +}); + describe('toExecutorCredentials (credential mapping at execution)', () => { type NodeCredentials = Extract['node']['credentials']; diff --git a/packages/cli/src/modules/agents/tools/node-tool-factory.ts b/packages/cli/src/modules/agents/tools/node-tool-factory.ts index 29fcb49ee26..5c8460144a2 100644 --- a/packages/cli/src/modules/agents/tools/node-tool-factory.ts +++ b/packages/cli/src/modules/agents/tools/node-tool-factory.ts @@ -17,6 +17,7 @@ import { resolveToolNodeType, type EphemeralNodeExecutor } from '@/node-executio import { NodeTypes } from '@/node-types'; import type { InstrumentToolAdditionalData } from '../agent-runtime-instrumentation'; +import { toPolicyRefusalResult } from './policy-refusal'; type NodeToolInputSchema = JSONSchema7 | z.ZodType; @@ -164,6 +165,13 @@ export async function resolveNodeTool( projectId: ctx.projectId, ...instrumentedExecution, }); + // A refusal is returned, not thrown: thrown errors reach the chat as plain text. + if (result.status === 'error' && result.violations) { + return toPolicyRefusalResult( + result.error ?? result.violations[0].message, + result.violations, + ); + } // Throw on the executor's structured error so the agent runtime // flags the tool-result with `isError: true` and the recorder // marks the timeline entry as a failed call. Returning the error diff --git a/packages/cli/src/modules/agents/tools/policy-refusal.ts b/packages/cli/src/modules/agents/tools/policy-refusal.ts new file mode 100644 index 00000000000..c842bfec851 --- /dev/null +++ b/packages/cli/src/modules/agents/tools/policy-refusal.ts @@ -0,0 +1,20 @@ +import type { NonEmptyViolations } from '@/policy/policy-violation.error'; + +const POLICY_REFUSAL_INSTRUCTION = + 'An administrator policy refused this tool call. Do not retry it or work around it. ' + + 'Tell the user which action you could not do and why, then continue with the rest of the request.'; + +/** Same fields as a serialized `PolicyViolationError`, so existing refusal readers apply. */ +export interface ToolPolicyRefusalResult { + isPolicyRefusal: true; + message: string; + violations: NonEmptyViolations; + instruction: string; +} + +export function toPolicyRefusalResult( + message: string, + violations: NonEmptyViolations, +): ToolPolicyRefusalResult { + return { isPolicyRefusal: true, message, violations, instruction: POLICY_REFUSAL_INSTRUCTION }; +} diff --git a/packages/cli/src/modules/agents/utils/agent-definition.ts b/packages/cli/src/modules/agents/utils/agent-definition.ts index 2398cc02cd2..bde89c16b5b 100644 --- a/packages/cli/src/modules/agents/utils/agent-definition.ts +++ b/packages/cli/src/modules/agents/utils/agent-definition.ts @@ -1,13 +1,15 @@ -import type { AgentJsonConfig, AgentTaskConfig } from '@n8n/api-types'; +import type { AgentJsonConfig, AgentSkill, AgentTaskConfig } from '@n8n/api-types'; import type { AgentHistory } from '../entities/agent-history.entity'; import type { Agent } from '../entities/agent.entity'; import { toAgentDocument, type AgentSkillRefs } from '../json-config/agent-document'; /** Published chat settings stay in schema. Credential integrations stay on the agent. */ -export interface AgentDefinition extends Pick { +export interface AgentDefinition extends Pick { /** The JSON document, with the skill refs. */ schema: AgentJsonConfig | null; + /** Skill bodies from the skills hub, keyed by skill id. */ + skills: Record; tasks: ReadonlyMap; } @@ -19,15 +21,16 @@ export interface PendingSkillRefs { skillRefs: AgentSkillRefs; } -/** Keep configuration and inline bodies from the same draft or version. */ +/** Keep configuration, inline bodies and skill bodies from the same draft or version. */ export function getAgentDefinitionContent( - source: Pick, + source: Pick, skillRefs: AgentSkillRefs, + skills: Record, ) { return { schema: source.schema ? toAgentDocument(source.schema, skillRefs) : null, tools: source.tools ?? {}, - skills: source.skills ?? {}, + skills, }; } diff --git a/packages/cli/src/modules/agents/utils/agent-missing-skill-ids.ts b/packages/cli/src/modules/agents/utils/agent-missing-skill-ids.ts index 28d8df714ca..39dedb76b50 100644 --- a/packages/cli/src/modules/agents/utils/agent-missing-skill-ids.ts +++ b/packages/cli/src/modules/agents/utils/agent-missing-skill-ids.ts @@ -11,7 +11,6 @@ export function getMissingSkillIds( const missing: string[] = []; for (const ref of refs) { - if (ref.enabled === false) continue; if (seen.has(ref.id)) continue; seen.add(ref.id); if (!skills[ref.id]) missing.push(ref.id); diff --git a/packages/cli/src/modules/agents/utils/agent-published-snapshot.ts b/packages/cli/src/modules/agents/utils/agent-published-snapshot.ts index b0eeab66e94..01899e826ae 100644 --- a/packages/cli/src/modules/agents/utils/agent-published-snapshot.ts +++ b/packages/cli/src/modules/agents/utils/agent-published-snapshot.ts @@ -1,3 +1,4 @@ +import type { AgentSkill } from '@n8n/api-types'; import type { OperationContext } from '@n8n/db'; import { OperationalError } from 'n8n-workflow'; @@ -11,6 +12,8 @@ export interface AgentRunSource { /** The agent draft, or the agent with the content of its published version. */ agent: Agent; skillRefs: AgentSkillRefs; + /** Skill bodies from the skills hub, keyed by skill id: the draft's or the pinned ones. */ + skills: Record; } function getPublishedVersion(agentEntity: Agent): AgentHistory { @@ -29,7 +32,6 @@ function getPublishedAgentSnapshot(agentEntity: Agent): Agent { ...agentEntity, schema: activeVersion.schema, tools: activeVersion.tools ?? {}, - skills: activeVersion.skills ?? {}, } as Agent; } @@ -44,11 +46,11 @@ export async function resolveAgentRunSource( ctx: OperationContext, ): Promise { if (!usePublishedVersion) { - return { agent: agentEntity, skillRefs: await agentSkillRefs.refsForDraft(agentEntity, ctx) }; + return { agent: agentEntity, ...(await agentSkillRefs.readDraft(agentEntity, ctx)) }; } const activeVersion = getPublishedVersion(agentEntity); return { agent: getPublishedAgentSnapshot(agentEntity), - skillRefs: await agentSkillRefs.refsForVersion(activeVersion, ctx), + ...(await agentSkillRefs.readVersion(activeVersion, ctx)), }; } diff --git a/packages/cli/src/modules/agents/utils/agent-runtime-assets.ts b/packages/cli/src/modules/agents/utils/agent-runtime-assets.ts index eb6133752cb..d85487b2366 100644 --- a/packages/cli/src/modules/agents/utils/agent-runtime-assets.ts +++ b/packages/cli/src/modules/agents/utils/agent-runtime-assets.ts @@ -1,11 +1,16 @@ import type { ToolDescriptor } from '@n8n/agents'; +import type { AgentSkill } from '@n8n/api-types'; import type { AgentHistory } from '../entities/agent-history.entity'; import type { Agent } from '../entities/agent.entity'; export type AgentRuntimeAssets = ReturnType; -export function getAgentRuntimeAssets(agent: Pick) { +/** `skills`: the skill bodies from the skills hub that the draft or version runs. */ +export function getAgentRuntimeAssets( + agent: Pick, + skills: Record, +) { const toolDescriptors: Record = {}; const toolCodeByName: Record = {}; @@ -14,5 +19,5 @@ export function getAgentRuntimeAssets(agent: Pick { let workflowSharingService: MockProxy; let eventService: MockProxy; let ownerAssignmentService: MockProxy; + let notificationService: MockProxy; let controller: BreakingChangesController; beforeEach(() => { @@ -81,6 +83,7 @@ describe('BreakingChangesController', () => { req.user = admin; eventService = mock(); ownerAssignmentService = mock(); + notificationService = mock(); controller = new BreakingChangesController( migrationService, syncService, @@ -90,6 +93,7 @@ describe('BreakingChangesController', () => { workflowSharingService, eventService, ownerAssignmentService, + notificationService, ); }); @@ -363,6 +367,35 @@ describe('BreakingChangesController', () => { }); }); + describe('POST /report/:ruleId/workflows/notify', () => { + it('passes the rule, workflows and acting user to the notification service and returns its result', async () => { + const expected = { notifiedWorkflowIds: ['wf-1'], skipped: [] }; + notificationService.notifyOwners.mockResolvedValue(expected); + + const result = await controller.notifyOwners(req, res, 'removed-nodes-v3', { + workflowIds: ['wf-1', 'wf-2'], + }); + + expect(result).toBe(expected); + expect(notificationService.notifyOwners).toHaveBeenCalledWith( + 'removed-nodes-v3', + ['wf-1', 'wf-2'], + req.user, + ); + }); + + it('requires the global breakingChanges:migrate scope', () => { + const metadata = Container.get(ControllerRegistryMetadata).getControllerMetadata( + BreakingChangesController as Controller, + ); + + expect(metadata.routes.get('notifyOwners')?.accessScope).toEqual({ + scope: 'breakingChanges:migrate', + globalOnly: true, + }); + }); + }); + describe('PATCH /report/:ruleId/workflows/:workflowId', () => { it('passes the rule, workflow and status to the triage service and returns nothing', async () => { triageService.setStatus.mockResolvedValue(undefined); diff --git a/packages/cli/src/modules/breaking-changes/__tests__/migration-finding.repository.integration.test.ts b/packages/cli/src/modules/breaking-changes/__tests__/migration-finding.repository.integration.test.ts index e3467ec14ae..c50438aaea5 100644 --- a/packages/cli/src/modules/breaking-changes/__tests__/migration-finding.repository.integration.test.ts +++ b/packages/cli/src/modules/breaking-changes/__tests__/migration-finding.repository.integration.test.ts @@ -277,6 +277,18 @@ describe('MigrationFindingRepository', () => { expect(after.statusChangedAt.getTime()).toBe(PAST.getTime()); }); + test('leaves a finding that was resolved in the meantime as it is', async () => { + const workflow = await createWorkflow(); + const id = await insertWithStatusChangedAt(workflow.id, PAST); + await findingRepository.markFixedForIds([id], ctx); + + await findingRepository.markNotifiedForIds([id], ctx); + + const [after] = await findingRepository.listForWorkflows('v3', [workflow.id], ctx); + expect(after.status).toBe('fixed'); + expect(after.notifiedAt).toBeNull(); + }); + test('does nothing for an empty id array', async () => { const workflow = await createWorkflow(); await findingRepository.insertMany([finding(workflow.id)], ctx); @@ -289,8 +301,8 @@ describe('MigrationFindingRepository', () => { }); }); - describe('countOpenByRule', () => { - test('counts only open findings, per rule, for the requested version', async () => { + describe('countUnresolvedByRule', () => { + test('counts open and notified findings, per rule, for the requested version', async () => { const [first, second, third] = await Promise.all([ createWorkflow(), createWorkflow(), @@ -308,8 +320,10 @@ describe('MigrationFindingRepository', () => { ); const [fixed] = await findingRepository.listForWorkflows('v3', [third.id], ctx); await findingRepository.markFixedForIds([fixed.id], ctx); + const [notified] = await findingRepository.listForWorkflows('v3', [second.id], ctx); + await findingRepository.markNotifiedForIds([notified.id], ctx); - const counts = await findingRepository.countOpenByRule('v3', undefined, ctx); + const counts = await findingRepository.countUnresolvedByRule('v3', undefined, ctx); expect(counts.sort((a, b) => a.ruleId.localeCompare(b.ruleId))).toEqual([ { ruleId: 'rule-a', count: 2 }, @@ -321,7 +335,7 @@ describe('MigrationFindingRepository', () => { const workflow = await createWorkflow(); await findingRepository.insertMany([finding(workflow.id, 'rule-a', 'v2')], ctx); - expect(await findingRepository.countOpenByRule('v3', undefined, ctx)).toEqual([]); + expect(await findingRepository.countUnresolvedByRule('v3', undefined, ctx)).toEqual([]); }); }); @@ -356,8 +370,8 @@ describe('MigrationFindingRepository', () => { }); }); - describe('countDistinctOpenWorkflows', () => { - test('counts a workflow once even when several rules hit it, and ignores fixed and other versions', async () => { + describe('countDistinctUnresolvedWorkflows', () => { + test('counts a workflow once even when several rules hit it, counts notified, and ignores fixed and other versions', async () => { const [first, second, third] = await Promise.all([ createWorkflow(), createWorkflow(), @@ -375,17 +389,23 @@ describe('MigrationFindingRepository', () => { ); const [fixed] = await findingRepository.listForWorkflows('v3', [third.id], ctx); await findingRepository.markFixedForIds([fixed.id], ctx); + const [notified] = await findingRepository.listForWorkflows('v3', [second.id], ctx); + await findingRepository.markNotifiedForIds([notified.id], ctx); - expect(await findingRepository.countDistinctOpenWorkflows('v3', undefined, ctx)).toBe(2); + expect(await findingRepository.countDistinctUnresolvedWorkflows('v3', undefined, ctx)).toBe( + 2, + ); }); test('returns zero when the version has no open findings', async () => { - expect(await findingRepository.countDistinctOpenWorkflows('v3', undefined, ctx)).toBe(0); + expect(await findingRepository.countDistinctUnresolvedWorkflows('v3', undefined, ctx)).toBe( + 0, + ); }); }); - describe('listWorkflowIdsWithOpenFindings', () => { - test('returns each given workflow with an open finding once, skipping fixed findings, other versions and other workflows', async () => { + describe('listWorkflowIdsWithUnresolvedFindings', () => { + test('returns each given workflow with an open or notified finding once, skipping fixed findings, other versions and other workflows', async () => { const [first, second, third, fourth] = await Promise.all([ createWorkflow(), createWorkflow(), @@ -404,23 +424,27 @@ describe('MigrationFindingRepository', () => { ); const [fixed] = await findingRepository.listForWorkflows('v3', [second.id], ctx); await findingRepository.markFixedForIds([fixed.id], ctx); + const [notified] = await findingRepository.listForWorkflows('v3', [fourth.id], ctx); + await findingRepository.markNotifiedForIds([notified.id], ctx); - const ids = await findingRepository.listWorkflowIdsWithOpenFindings( + const ids = await findingRepository.listWorkflowIdsWithUnresolvedFindings( 'v3', - [first.id, second.id, third.id], + [first.id, second.id, third.id, fourth.id], ctx, ); - expect(ids).toEqual([first.id]); + expect(ids.sort()).toEqual([first.id, fourth.id].sort()); }); test('returns an empty list for an empty id array', async () => { - expect(await findingRepository.listWorkflowIdsWithOpenFindings('v3', [], ctx)).toEqual([]); + expect(await findingRepository.listWorkflowIdsWithUnresolvedFindings('v3', [], ctx)).toEqual( + [], + ); }); }); describe('listTriageableForRule', () => { - test('returns each open and wont_fix finding of the rule with its status, workflow name, published state and last update', async () => { + test('returns each open, notified and wont_fix finding of the rule with its status, workflow name, published state and last update', async () => { const published = await createWorkflowWithHistory({ name: 'Published flow' }); await setActiveVersion(published.id, published.versionId); const [dismissed, fixed, notified, fixedUnpublished, otherRule] = await Promise.all([ @@ -444,12 +468,15 @@ describe('MigrationFindingRepository', () => { ); await setStatus(dismissed.id, 'rule-a', 'wont_fix'); await setStatus(fixed.id, 'rule-a', 'fixed'); - await setStatus(notified.id, 'rule-a', 'notified'); + const [notifiedRow] = await findingRepository.listForWorkflows('v3', [notified.id], ctx); + await findingRepository.markNotifiedForIds([notifiedRow.id], ctx); await setStatus(fixedUnpublished.id, 'rule-a', 'fixed_unpublished'); const listed = await findingRepository.listTriageableForRule('v3', 'rule-a', undefined, ctx); - expect(listed.map((f) => f.workflowId).sort()).toEqual([published.id, dismissed.id].sort()); + expect(listed.map((f) => f.workflowId).sort()).toEqual( + [published.id, dismissed.id, notified.id].sort(), + ); for (const row of listed) { expect(row.ruleId).toBe('rule-a'); expect(row.id).toEqual(expect.any(Number)); @@ -471,6 +498,11 @@ describe('MigrationFindingRepository', () => { name: 'Dismissed flow', activeVersionId: null, }); + + const notifiedFinding = listed.find((f) => f.workflowId === notified.id); + expect(notifiedFinding?.status).toBe('notified'); + expect(notifiedFinding?.notifiedAt).toBeInstanceOf(Date); + expect(publishedFinding?.notifiedAt).toBeNull(); }); test('returns an empty list when the rule has no open or wont_fix findings', async () => { @@ -507,12 +539,12 @@ describe('MigrationFindingRepository', () => { await setStatus(second.id, 'rule-a', 'wont_fix'); const inScope = [first.id, third.id]; - const counts = await findingRepository.countOpenByRule('v3', inScope, ctx); + const counts = await findingRepository.countUnresolvedByRule('v3', inScope, ctx); expect(counts).toEqual([{ ruleId: 'rule-a', count: 2 }]); expect(await findingRepository.countWontFixByRule('v3', inScope, ctx)).toEqual([ { ruleId: 'rule-b', count: 1 }, ]); - expect(await findingRepository.countDistinctOpenWorkflows('v3', inScope, ctx)).toBe(2); + expect(await findingRepository.countDistinctUnresolvedWorkflows('v3', inScope, ctx)).toBe(2); const listed = await findingRepository.listTriageableForRule('v3', 'rule-a', inScope, ctx); expect(listed.map((row) => row.workflowId).sort()).toEqual([...inScope].sort()); }); @@ -521,9 +553,9 @@ describe('MigrationFindingRepository', () => { const workflow = await createWorkflow(); await findingRepository.insertMany([finding(workflow.id, 'rule-a')], ctx); - expect(await findingRepository.countOpenByRule('v3', [], ctx)).toEqual([]); + expect(await findingRepository.countUnresolvedByRule('v3', [], ctx)).toEqual([]); expect(await findingRepository.countWontFixByRule('v3', [], ctx)).toEqual([]); - expect(await findingRepository.countDistinctOpenWorkflows('v3', [], ctx)).toBe(0); + expect(await findingRepository.countDistinctUnresolvedWorkflows('v3', [], ctx)).toBe(0); expect(await findingRepository.listTriageableForRule('v3', 'rule-a', [], ctx)).toEqual([]); }); }); @@ -531,6 +563,44 @@ describe('MigrationFindingRepository', () => { describe('setTriageStatus', () => { const RULE_ID = 'removed-nodes-v3'; + test('sets open on a notified finding and clears notifiedAt', async () => { + const workflow = await createWorkflow(); + const id = await insertWithStatusChangedAt(workflow.id, PAST); + await findingRepository.markNotifiedForIds([id], ctx); + + const updated = await findingRepository.setTriageStatus( + 'v3', + RULE_ID, + workflow.id, + 'open', + ctx, + ); + + expect(updated).toBe(true); + const [after] = await findingRepository.listForWorkflows('v3', [workflow.id], ctx); + expect(after.status).toBe('open'); + expect(after.notifiedAt).toBeNull(); + }); + + test('sets wont_fix on a notified finding and keeps notifiedAt', async () => { + const workflow = await createWorkflow(); + const id = await insertWithStatusChangedAt(workflow.id, PAST); + await findingRepository.markNotifiedForIds([id], ctx); + + const updated = await findingRepository.setTriageStatus( + 'v3', + RULE_ID, + workflow.id, + 'wont_fix', + ctx, + ); + + expect(updated).toBe(true); + const [after] = await findingRepository.listForWorkflows('v3', [workflow.id], ctx); + expect(after.status).toBe('wont_fix'); + expect(after.notifiedAt).toBeInstanceOf(Date); + }); + test('sets wont_fix on an open finding and moves statusChangedAt', async () => { const workflow = await createWorkflow(); await insertWithStatusChangedAt(workflow.id, PAST); diff --git a/packages/cli/src/modules/breaking-changes/breaking-changes.controller.ts b/packages/cli/src/modules/breaking-changes/breaking-changes.controller.ts index d52274219a6..e8d03c025ad 100644 --- a/packages/cli/src/modules/breaking-changes/breaking-changes.controller.ts +++ b/packages/cli/src/modules/breaking-changes/breaking-changes.controller.ts @@ -4,7 +4,9 @@ import { BreakingChangeReportQueryDto, BreakingChangeRuleDetailResult, BreakingChangeVersion, + MigrationNotifyResult, MigrationWorkflowOwnerResponse, + NotifyMigrationOwnersRequestDto, UpdateMigrationFindingStatusRequestDto, UpdateMigrationFindingStatusesRequestDto, WorkflowMigrationResult, @@ -29,6 +31,7 @@ import { Response } from 'express'; import { BreakingChangeMigrationService } from './breaking-changes.migration.service'; import { RuleRegistry } from './breaking-changes.rule-registry.service'; +import { MigrationFindingNotificationService } from './notifications/migration-finding-notification.service'; import { MigrationOwnerAssignmentService } from './owners/migration-owner-assignment.service'; import { MigrationFindingQueryService, @@ -52,6 +55,7 @@ export class BreakingChangesController { private readonly workflowSharingService: WorkflowSharingService, private readonly eventService: EventService, private readonly ownerAssignmentService: MigrationOwnerAssignmentService, + private readonly notificationService: MigrationFindingNotificationService, ) {} /** @@ -153,6 +157,22 @@ export class BreakingChangesController { await this.triageService.setStatuses(ruleId, body.workflowIds, body.status); } + /** + * Emails the owners of the given workflows about the rule's finding on them. + * A repeated call is a reminder. The response names the workflows that were + * notified and the ones that were skipped, with the reason. + */ + @Post('/report/:ruleId/workflows/notify') + @GlobalScope('breakingChanges:migrate') + async notifyOwners( + req: AuthenticatedRequest, + _res: Response, + @Param('ruleId') ruleId: string, + @Body body: NotifyMigrationOwnersRequestDto, + ): Promise { + return await this.notificationService.notifyOwners(ruleId, body.workflowIds, req.user); + } + /** Sets the status a user picks for the finding of one rule on one workflow. */ @Patch('/report/:ruleId/workflows/:workflowId') @GlobalScope('breakingChanges:migrate') diff --git a/packages/cli/src/modules/breaking-changes/database/repositories/migration-finding.repository.ts b/packages/cli/src/modules/breaking-changes/database/repositories/migration-finding.repository.ts index 7079a72c508..3c82864f73d 100644 --- a/packages/cli/src/modules/breaking-changes/database/repositories/migration-finding.repository.ts +++ b/packages/cli/src/modules/breaking-changes/database/repositories/migration-finding.repository.ts @@ -1,6 +1,7 @@ import { - migrationFindingTriageStatusSchema, + migrationFindingListedStatusSchema, type BreakingChangeVersion, + type MigrationFindingListedStatus, type MigrationFindingStatus, type MigrationFindingTriageStatus, } from '@n8n/api-types'; @@ -19,18 +20,23 @@ import { MigrationFinding, type MigrationFindingId } from '../entities/migration /** A finding the scan detected. New findings always start as `open`. */ export type NewMigrationFinding = Pick; -/** A finding in a status a user can set, with the workflow columns the report shows. */ -export type TriageableMigrationFinding = Pick & { - status: MigrationFindingTriageStatus; +/** A finding the rule detail lists, with the workflow columns the report shows. */ +export type TriageableMigrationFinding = Pick< + MigrationFinding, + 'id' | 'ruleId' | 'workflowId' | 'notifiedAt' +> & { + status: MigrationFindingListedStatus; workflow: Pick; }; -const TRIAGE_STATUSES = migrationFindingTriageStatusSchema.options; +const LISTED_STATUSES = migrationFindingListedStatusSchema.options; +/** The statuses that still need a fix. A notification does not resolve a finding. */ +const UNRESOLVED_STATUSES: MigrationFindingStatus[] = ['open', 'notified']; -function hasTriageStatus( +function hasListedStatus( finding: MigrationFinding, -): finding is MigrationFinding & { status: MigrationFindingTriageStatus } { - return migrationFindingTriageStatusSchema.safeParse(finding.status).success; +): finding is MigrationFinding & { status: MigrationFindingListedStatus } { + return migrationFindingListedStatusSchema.safeParse(finding.status).success; } export interface RuleFindingCount { @@ -38,6 +44,15 @@ export interface RuleFindingCount { count: number; } +/** The columns a triage change writes. Reopening also drops the notified mark. */ +function triagePatch(status: MigrationFindingTriageStatus) { + return { + status, + statusChangedAt: new Date(), + ...(status === 'open' ? { notifiedAt: null } : {}), + }; +} + /** The id lists to query one by one. No filter means one unfiltered query; an empty filter, none. */ function chunksOrAll(workflowIds: string[] | undefined): Array { return workflowIds === undefined ? [undefined] : chunkIds(workflowIds); @@ -67,15 +82,15 @@ export class MigrationFindingRepository extends BaseRepository } /** - * Number of open findings per rule for the version. Rules without open findings - * are absent. `workflowIds` limits the count to those workflows; `undefined` counts all. + * Number of open or notified findings per rule for the version. Rules without + * them are absent. `workflowIds` limits the count to those workflows; `undefined` counts all. */ - async countOpenByRule( + async countUnresolvedByRule( targetVersion: BreakingChangeVersion, workflowIds: string[] | undefined, ctx: OperationContext, ): Promise { - return await this.countByRuleWithStatus(targetVersion, 'open', workflowIds, ctx); + return await this.countByRuleWithStatus(targetVersion, UNRESOLVED_STATUSES, workflowIds, ctx); } /** @@ -87,14 +102,14 @@ export class MigrationFindingRepository extends BaseRepository workflowIds: string[] | undefined, ctx: OperationContext, ): Promise { - return await this.countByRuleWithStatus(targetVersion, 'wont_fix', workflowIds, ctx); + return await this.countByRuleWithStatus(targetVersion, ['wont_fix'], workflowIds, ctx); } /** - * Number of distinct workflows with at least one open finding for the version. - * `workflowIds` limits the count to those workflows; `undefined` counts all. + * Number of distinct workflows with at least one open or notified finding for + * the version. `workflowIds` limits the count to those workflows; `undefined` counts all. */ - async countDistinctOpenWorkflows( + async countDistinctUnresolvedWorkflows( targetVersion: BreakingChangeVersion, workflowIds: string[] | undefined, ctx: OperationContext, @@ -105,7 +120,7 @@ export class MigrationFindingRepository extends BaseRepository .createQueryBuilder(MigrationFinding, 'finding') .select('COUNT(DISTINCT finding.workflowId)', 'count') .where('finding.targetVersion = :targetVersion', { targetVersion }) - .andWhere('finding.status = :status', { status: 'open' }); + .andWhere('finding.status IN (:...statuses)', { statuses: UNRESOLVED_STATUSES }); if (chunk) query.andWhere('finding.workflowId IN (:...workflowIds)', { workflowIds: chunk }); const row = await query.getRawOne<{ count: number | string }>(); @@ -116,8 +131,8 @@ export class MigrationFindingRepository extends BaseRepository return total; } - /** The given workflows that have at least one open finding for the version. */ - async listWorkflowIdsWithOpenFindings( + /** The given workflows that have at least one open or notified finding for the version. */ + async listWorkflowIdsWithUnresolvedFindings( targetVersion: BreakingChangeVersion, workflowIds: string[], ctx: OperationContext, @@ -125,15 +140,15 @@ export class MigrationFindingRepository extends BaseRepository if (workflowIds.length === 0) return []; const rows = await this.managerFor(ctx).find(MigrationFinding, { select: { workflowId: true }, - where: { targetVersion, status: 'open', workflowId: In(workflowIds) }, + where: { targetVersion, status: In(UNRESOLVED_STATUSES), workflowId: In(workflowIds) }, }); return [...new Set(rows.map((row) => row.workflowId))]; } /** - * Findings of one rule for the version in a status a user can set (open and - * won't fix), each with its workflow's report columns. `workflowIds` limits - * the list to those workflows; `undefined` lists all. + * Findings of one rule for the version that the rule detail lists (open, + * notified and won't fix), each with its workflow's report columns. + * `workflowIds` limits the list to those workflows; `undefined` lists all. */ async listTriageableForRule( targetVersion: BreakingChangeVersion, @@ -149,12 +164,13 @@ export class MigrationFindingRepository extends BaseRepository ruleId: true, workflowId: true, status: true, + notifiedAt: true, workflow: { id: true, name: true, activeVersionId: true, updatedAt: true }, }, where: { targetVersion, ruleId, - status: In(TRIAGE_STATUSES), + status: In(LISTED_STATUSES), ...(chunk ? { workflowId: In(chunk) } : {}), }, relations: { workflow: true }, @@ -162,13 +178,14 @@ export class MigrationFindingRepository extends BaseRepository findings.push(...rows); } // The query already filters by status. The guard only narrows the type. - return findings.sort((a, b) => a.id - b.id).filter(hasTriageStatus); + return findings.sort((a, b) => a.id - b.id).filter(hasListedStatus); } /** * Sets the status a user picked on one finding. Returns `false` when the finding * does not exist or is in a status only the scan sets, for example `fixed`. - * `statusChangedAt` moves only when the status actually changes. + * A notified finding can be set like an open one; setting it to `open` drops + * the notified mark and its date. `statusChangedAt` moves only when the status actually changes. */ async setTriageStatus( targetVersion: BreakingChangeVersion, @@ -180,7 +197,7 @@ export class MigrationFindingRepository extends BaseRepository const manager = this.managerFor(ctx); const finding = await manager.findOne(MigrationFinding, { select: { id: true, status: true }, - where: { targetVersion, ruleId, workflowId, status: In(TRIAGE_STATUSES) }, + where: { targetVersion, ruleId, workflowId, status: In(LISTED_STATUSES) }, }); if (!finding) return false; if (finding.status === status) return true; @@ -190,8 +207,8 @@ export class MigrationFindingRepository extends BaseRepository // and the caller gets `false`. const result = await manager.update( MigrationFinding, - { id: finding.id, status: In(TRIAGE_STATUSES) }, - { status, statusChangedAt: new Date() }, + { id: finding.id, status: In(LISTED_STATUSES) }, + triagePatch(status), ); return (result.affected ?? 0) > 0; } @@ -208,14 +225,14 @@ export class MigrationFindingRepository extends BaseRepository status: MigrationFindingTriageStatus, ctx: OperationContext, ): Promise { - const otherTriageStatuses = TRIAGE_STATUSES.filter((triageStatus) => triageStatus !== status); + const otherListedStatuses = LISTED_STATUSES.filter((listed) => listed !== status); // One transaction, so a failed chunk does not leave the earlier chunks changed. await this.runInTransaction(ctx, async (manager) => { for (const chunk of chunkIds(workflowIds)) { await manager.update( MigrationFinding, - { targetVersion, ruleId, workflowId: In(chunk), status: In(otherTriageStatuses) }, - { status, statusChangedAt: new Date() }, + { targetVersion, ruleId, workflowId: In(chunk), status: In(otherListedStatuses) }, + triagePatch(status), ); } }); @@ -261,7 +278,7 @@ export class MigrationFindingRepository extends BaseRepository private async countByRuleWithStatus( targetVersion: BreakingChangeVersion, - status: MigrationFindingStatus, + statuses: MigrationFindingStatus[], workflowIds: string[] | undefined, ctx: OperationContext, ): Promise { @@ -272,7 +289,7 @@ export class MigrationFindingRepository extends BaseRepository .select('finding.ruleId', 'ruleId') .addSelect('COUNT(finding.id)', 'count') .where('finding.targetVersion = :targetVersion', { targetVersion }) - .andWhere('finding.status = :status', { status }) + .andWhere('finding.status IN (:...statuses)', { statuses }) .groupBy('finding.ruleId'); if (chunk) query.andWhere('finding.workflowId IN (:...workflowIds)', { workflowIds: chunk }); const rows = await query.getRawMany<{ ruleId: string; count: number | string }>(); @@ -304,14 +321,27 @@ export class MigrationFindingRepository extends BaseRepository } /** - * Records a notification. `notifiedAt` is bumped for every id, so a reminder - * updates it, while `statusChangedAt` moves only on the first transition. + * Records a notification on the given findings. Only an open finding becomes + * notified, and only a notified one gets the date, so a finding that a sync or + * a user resolved after the caller read it stays resolved. `notifiedAt` is + * bumped on every call, so a reminder updates it, while `statusChangedAt` + * moves only on the first transition. */ async markNotifiedForIds(ids: MigrationFindingId[], ctx: OperationContext): Promise { if (ids.length === 0) return; - const manager = this.managerFor(ctx); - await this.transitionStatus(manager, ids, 'notified'); - await manager.update(MigrationFinding, { id: In(ids) }, { notifiedAt: new Date() }); + // One transaction, so a row never carries a new `notifiedAt` without the status. + await this.runInTransaction(ctx, async (manager) => { + await manager.update( + MigrationFinding, + { id: In(ids), status: 'open' }, + { status: 'notified', statusChangedAt: new Date() }, + ); + await manager.update( + MigrationFinding, + { id: In(ids), status: 'notified' }, + { notifiedAt: new Date() }, + ); + }); } } diff --git a/packages/cli/src/modules/breaking-changes/migrations/ai-transform-to-code.migration.ts b/packages/cli/src/modules/breaking-changes/migrations/ai-transform-to-code.migration.ts deleted file mode 100644 index 7c296e4dcdb..00000000000 --- a/packages/cli/src/modules/breaking-changes/migrations/ai-transform-to-code.migration.ts +++ /dev/null @@ -1,36 +0,0 @@ -import type { NodeMigration } from './node-migration'; - -/** - * AI Transform → Code. Lossless when the node has generated code: both nodes run - * the same JsTaskRunnerSandbox and store it under `jsCode`, and AI Transform always - * runs once for all items. The AI-authoring-only params (`instructions`, - * `codeGeneratedForPrompt`) are dropped because they have no runtime effect on the - * Code node. - * - * A node whose prompt was never turned into code (`jsCode` empty) has nothing to - * carry over, so we refuse rather than silently produce an empty Code node and - * lose the prompt. - */ -export const aiTransformToCode: NodeMigration = { - ruleId: 'ai-transform-deprecated', - migrate: (node) => { - const jsCode = node.parameters.jsCode; - if (!jsCode) { - throw new Error( - 'This AI Transform node never generated any code, so there is nothing to carry over. Replace it with a Code node and write the code for its instructions by hand.', - ); - } - - return { - node: { - type: 'n8n-nodes-base.code', - typeVersion: 2, - parameters: { - mode: 'runOnceForAllItems', - language: 'javaScript', - jsCode, - }, - }, - }; - }, -}; diff --git a/packages/cli/src/modules/breaking-changes/migrations/index.ts b/packages/cli/src/modules/breaking-changes/migrations/index.ts index db3a469c235..d97afc16094 100644 --- a/packages/cli/src/modules/breaking-changes/migrations/index.ts +++ b/packages/cli/src/modules/breaking-changes/migrations/index.ts @@ -1,5 +1,5 @@ -import { aiTransformToCode } from './ai-transform-to-code.migration'; +import { nodeRemovalMigrations } from './node-removals'; import type { Migration } from './node-migration'; -// All registered migrations. A rule is auto-migratable only if it appears here. -export const nodeMigrations: Migration[] = [aiTransformToCode]; +// All registered migrations, grouped by the kind of breaking change they handle. +export const nodeMigrations: Migration[] = [...nodeRemovalMigrations]; diff --git a/packages/cli/src/modules/breaking-changes/migrations/node-migration.ts b/packages/cli/src/modules/breaking-changes/migrations/node-migration.ts index 5e11ac5ef25..b8b4f866de6 100644 --- a/packages/cli/src/modules/breaking-changes/migrations/node-migration.ts +++ b/packages/cli/src/modules/breaking-changes/migrations/node-migration.ts @@ -63,6 +63,35 @@ export interface WorkflowMigration { migrateWorkflow(input: WorkflowMigrationInput): WorkflowMigrationOutput; } +/** + * Replaces each flagged node with the result of `migrateNode`. A throw from `migrateNode` + * becomes a `WorkflowMigrationNodeError` that names the node. Other nodes pass through. + */ +export function replaceAffectedNodes( + nodes: INode[], + affectedNodeIds: Set, + migrateNode: (node: INode) => INode, +): Pick { + const migratedNodeIds: string[] = []; + + const migratedNodes = nodes.map((node) => { + if (!affectedNodeIds.has(node.id)) return node; + + try { + const migrated = migrateNode(node); + migratedNodeIds.push(node.id); + return migrated; + } catch (error) { + throw new WorkflowMigrationNodeError( + error instanceof Error ? error.message : 'Migration failed.', + { nodeId: node.id, nodeName: node.name }, + ); + } + }); + + return { nodes: migratedNodes, migratedNodeIds }; +} + export type Migration = NodeMigration | WorkflowMigration; export const isWorkflowMigration = (migration: Migration): migration is WorkflowMigration => diff --git a/packages/cli/src/modules/breaking-changes/migrations/node-removals/__tests__/ai-nodes.migrations.test.ts b/packages/cli/src/modules/breaking-changes/migrations/node-removals/__tests__/ai-nodes.migrations.test.ts new file mode 100644 index 00000000000..8521441e9b5 --- /dev/null +++ b/packages/cli/src/modules/breaking-changes/migrations/node-removals/__tests__/ai-nodes.migrations.test.ts @@ -0,0 +1,358 @@ +import type { IConnections, INode } from 'n8n-workflow'; + +import { createNode } from '../../../__tests__/test-helpers'; +import { + binaryInputLoaderToDefaultDataLoader, + jsonInputLoaderToDefaultDataLoader, +} from '../document-loaders.migration'; +import { WorkflowMigrationNodeError } from '../../node-migration'; +import type { WorkflowMigration } from '../../node-migration'; +import { + inMemoryInsertToVectorStore, + inMemoryLoadToVectorStore, + pineconeInsertToVectorStore, + pineconeLoadToVectorStore, + supabaseInsertToVectorStore, + supabaseLoadToVectorStore, +} from '../vector-stores.migration'; + +const LOADER = '@n8n/n8n-nodes-langchain.documentDefaultDataLoader'; + +describe('binaryInputLoaderToDefaultDataLoader migration', () => { + const binaryLoader = (parameters: Record) => + createNode('Loader', '@n8n/n8n-nodes-langchain.documentBinaryInputLoader', parameters); + + it('is keyed by the Binary Input Loader rule id', () => { + expect(binaryInputLoaderToDefaultDataLoader.ruleId).toBe('binary-input-loader-removed-v3'); + }); + + it('keeps the custom text splitter and writes the old loader default', () => { + const { node } = binaryInputLoaderToDefaultDataLoader.migrate(binaryLoader({})); + + expect(node).toEqual({ + type: LOADER, + typeVersion: 1.1, + parameters: { + dataType: 'binary', + binaryMode: 'allInputData', + // The old default is jsonLoader. The new default is auto. + loader: 'jsonLoader', + textSplittingMode: 'custom', + options: { pointers: '' }, + }, + }); + }); + + it('moves PDF settings into options and writes the old split pages default', () => { + const { node } = binaryInputLoaderToDefaultDataLoader.migrate( + binaryLoader({ loader: 'pdfLoader', binaryDataKey: 'file' }), + ); + + expect(node.parameters).toMatchObject({ + loader: 'pdfLoader', + binaryDataKey: 'file', + options: { splitPages: true }, + }); + }); + + it('moves CSV settings and the metadata option into options', () => { + const metadata = { metadataValues: [{ name: 'source', value: 'crm' }] }; + + const { node } = binaryInputLoaderToDefaultDataLoader.migrate( + binaryLoader({ loader: 'csvLoader', column: 'text', options: { metadata } }), + ); + + expect(node.parameters.options).toEqual({ column: 'text', separator: ',', metadata }); + }); + + it('moves no loader settings for a loader that has none', () => { + const { node } = binaryInputLoaderToDefaultDataLoader.migrate( + binaryLoader({ loader: 'docxLoader' }), + ); + + expect(node.parameters.options).toEqual({}); + }); + + it('refuses a loader set by an expression', () => { + expect(() => + binaryInputLoaderToDefaultDataLoader.migrate(binaryLoader({ loader: '={{ $json.type }}' })), + ).toThrow(); + }); +}); + +describe('jsonInputLoaderToDefaultDataLoader migration', () => { + const loader = createNode('Loader', '@n8n/n8n-nodes-langchain.documentJsonInputLoader', { + pointers: '/text', + options: { metadata: { metadataValues: [{ name: 'a', value: 'b' }] } }, + }); + const splitter = createNode('Splitter', '@n8n/n8n-nodes-langchain.textSplitterTokenSplitter'); + const other = createNode('Other', 'n8n-nodes-base.set'); + + const splitterConnections: IConnections = { + Splitter: { ai_textSplitter: [[{ node: 'Loader', type: 'ai_textSplitter', index: 0 }]] }, + }; + const migrate = (nodes: INode[], connections: IConnections) => + jsonInputLoaderToDefaultDataLoader.migrateWorkflow({ + nodes, + connections, + affectedNodeIds: new Set([loader.id]), + }); + + it('is keyed by the JSON Input Loader rule id', () => { + expect(jsonInputLoaderToDefaultDataLoader.ruleId).toBe('json-input-loader-removed-v3'); + }); + + it('migrates a loader that has a text splitter and leaves other nodes and connections alone', () => { + const result = migrate([splitter, loader, other], splitterConnections); + + expect(result.migratedNodeIds).toEqual([loader.id]); + expect(result.connections).toBe(splitterConnections); + expect(result.nodes[0]).toBe(splitter); + expect(result.nodes[2]).toBe(other); + expect(result.nodes[1]).toEqual({ + ...loader, + type: LOADER, + typeVersion: 1.1, + parameters: { + dataType: 'json', + jsonMode: 'allInputData', + textSplittingMode: 'custom', + options: { + pointers: '/text', + metadata: { metadataValues: [{ name: 'a', value: 'b' }] }, + }, + }, + }); + }); + + it('refuses a loader with no text splitter, because Default Data Loader always splits', () => { + const run = () => migrate([loader, other], {}); + + expect(run).toThrow(WorkflowMigrationNodeError); + expect(run).toThrow('no text splitter'); + }); + + it('does not count a splitter that is connected to another node', () => { + const elsewhere: IConnections = { + Splitter: { ai_textSplitter: [[{ node: 'Other', type: 'ai_textSplitter', index: 0 }]] }, + }; + + expect(() => migrate([splitter, loader, other], elsewhere)).toThrow(WorkflowMigrationNodeError); + }); +}); + +describe('vector store migrations', () => { + const node = (type: string, parameters: Record = {}) => + createNode('Store', `@n8n/n8n-nodes-langchain.${type}`, parameters); + + // Runs an insert migration on a workflow with `sources` wired to the node's document input. + const insertInWorkflow = ( + migration: WorkflowMigration, + store: INode, + sources: INode[] = [], + connections: IConnections = {}, + ) => + migration.migrateWorkflow({ + nodes: [...sources, store], + connections: { + ...Object.fromEntries( + sources.map(({ name }) => [ + name, + { ai_document: [[{ node: store.name, type: 'ai_document', index: 0 }]] }, + ]), + ), + ...connections, + }, + affectedNodeIds: new Set([store.id]), + }); + + const insert = (migration: WorkflowMigration, store: INode) => { + const { nodes } = insertInWorkflow(migration, store); + const { type, typeVersion, parameters } = nodes[nodes.length - 1]; + return { type, typeVersion, parameters }; + }; + + describe('document source of Insert', () => { + const store = node('vectorStoreInMemoryInsert'); + const migrate = (sources: INode[], connections?: IConnections) => + insertInWorkflow(inMemoryInsertToVectorStore, store, sources, connections); + + it.each(['documentDefaultDataLoader', 'documentJsonInputLoader', 'documentBinaryInputLoader'])( + 'migrates when the documents come from %s', + (type) => { + const result = migrate([createNode('Loader', `@n8n/n8n-nodes-langchain.${type}`)]); + + expect(result.migratedNodeIds).toEqual([store.id]); + }, + ); + + it('migrates when no document source is connected, because both nodes then fail', () => { + expect(migrate([]).migratedNodeIds).toEqual([store.id]); + }); + + it.each(['documentGithubLoader', 'code'])( + 'refuses when the documents come from %s, because the new node would repeat them for each item', + (type) => { + const source = createNode('Source', `@n8n/n8n-nodes-langchain.${type}`); + + expect(() => migrate([createNode('Loader', LOADER), source])).toThrow( + WorkflowMigrationNodeError, + ); + }, + ); + + it('does not count a source that is connected to another node', () => { + const github = createNode('Source', '@n8n/n8n-nodes-langchain.documentGithubLoader'); + const result = inMemoryInsertToVectorStore.migrateWorkflow({ + nodes: [github, store], + connections: { + Source: { ai_document: [[{ node: 'Other', type: 'ai_document', index: 0 }]] }, + }, + affectedNodeIds: new Set([store.id]), + }); + + expect(result.migratedNodeIds).toEqual([store.id]); + }); + + it('leaves nodes that are not affected as they are', () => { + const other = createNode('Other', 'n8n-nodes-base.set'); + const { nodes } = inMemoryInsertToVectorStore.migrateWorkflow({ + nodes: [other, store], + connections: {}, + affectedNodeIds: new Set([store.id]), + }); + + expect(nodes[0]).toBe(other); + }); + }); + + describe('In-Memory', () => { + it('migrates Insert to insert mode and keeps the memory key', () => { + const migrated = insert( + inMemoryInsertToVectorStore, + node('vectorStoreInMemoryInsert', { memoryKey: 'kb' }), + ); + + expect(migrated).toEqual({ + type: '@n8n/n8n-nodes-langchain.vectorStoreInMemory', + typeVersion: 1.1, + parameters: { mode: 'insert', memoryKey: 'kb' }, + }); + }); + + it('refuses Insert with Clear Store on, because the new node clears for each batch', () => { + expect(() => + insert( + inMemoryInsertToVectorStore, + node('vectorStoreInMemoryInsert', { clearStore: true }), + ), + ).toThrow('Clear Store'); + }); + + it('migrates Load to retrieve mode, not to Get Many, so it keeps the vector store output', () => { + const { node: migrated } = inMemoryLoadToVectorStore.migrate( + node('vectorStoreInMemoryLoad', { memoryKey: 'kb' }), + ); + + expect(migrated.parameters).toEqual({ mode: 'retrieve', memoryKey: 'kb' }); + expect(migrated.typeVersion).toBe(1.1); + }); + }); + + describe('Pinecone', () => { + const pineconeIndex = { __rl: true, mode: 'list', value: 'docs' }; + + it('moves the namespace into options on Insert', () => { + const migrated = insert( + pineconeInsertToVectorStore, + node('vectorStorePineconeInsert', { pineconeIndex, pineconeNamespace: 'team-a' }), + ); + + expect(migrated).toEqual({ + type: '@n8n/n8n-nodes-langchain.vectorStorePinecone', + typeVersion: 1.1, + parameters: { mode: 'insert', pineconeIndex, options: { pineconeNamespace: 'team-a' } }, + }); + }); + + it('writes no namespace for an empty one, because the old node treats it as unset', () => { + const migrated = insert( + pineconeInsertToVectorStore, + node('vectorStorePineconeInsert', { pineconeIndex, pineconeNamespace: '' }), + ); + + expect(migrated.parameters.options).toEqual({}); + }); + + it('refuses Insert that clears a namespace', () => { + expect(() => + insert( + pineconeInsertToVectorStore, + node('vectorStorePineconeInsert', { pineconeNamespace: 'a', clearNamespace: true }), + ), + ).toThrow('Clear Namespace'); + }); + + it('allows Clear Namespace when no namespace is set, because it does nothing', () => { + const migrated = insert( + pineconeInsertToVectorStore, + node('vectorStorePineconeInsert', { clearNamespace: true }), + ); + + expect(migrated.parameters.mode).toBe('insert'); + }); + + it('migrates Load to retrieve mode with the namespace and metadata filter in options', () => { + const metadata = { metadataValues: [{ name: 'a', value: 'b' }] }; + + const { node: migrated } = pineconeLoadToVectorStore.migrate( + node('vectorStorePineconeLoad', { + pineconeIndex, + pineconeNamespace: 'team-a', + options: { metadata }, + }), + ); + + expect(migrated.parameters).toEqual({ + mode: 'retrieve', + pineconeIndex, + options: { pineconeNamespace: 'team-a', metadata }, + }); + }); + }); + + describe('Supabase', () => { + const tableName = { __rl: true, mode: 'list', value: 'documents' }; + + it('moves the query name into options on Insert', () => { + const migrated = insert( + supabaseInsertToVectorStore, + node('vectorStoreSupabaseInsert', { tableName, queryName: 'match_docs' }), + ); + + expect(migrated).toEqual({ + type: '@n8n/n8n-nodes-langchain.vectorStoreSupabase', + typeVersion: 1.1, + parameters: { mode: 'insert', tableName, options: { queryName: 'match_docs' } }, + }); + }); + + it('migrates Load to retrieve mode with the query name and metadata filter in options', () => { + const metadata = { metadataValues: [{ name: 'a', value: 'b' }] }; + + const { node: migrated } = supabaseLoadToVectorStore.migrate( + node('vectorStoreSupabaseLoad', { + tableName, + queryName: 'match_docs', + options: { metadata }, + }), + ); + + expect(migrated.parameters).toEqual({ + mode: 'retrieve', + tableName, + options: { queryName: 'match_docs', metadata }, + }); + }); + }); +}); diff --git a/packages/cli/src/modules/breaking-changes/migrations/__tests__/ai-transform-to-code.migration.test.ts b/packages/cli/src/modules/breaking-changes/migrations/node-removals/__tests__/ai-transform-to-code.migration.test.ts similarity index 89% rename from packages/cli/src/modules/breaking-changes/migrations/__tests__/ai-transform-to-code.migration.test.ts rename to packages/cli/src/modules/breaking-changes/migrations/node-removals/__tests__/ai-transform-to-code.migration.test.ts index 8e12502f4cc..cd796eba2db 100644 --- a/packages/cli/src/modules/breaking-changes/migrations/__tests__/ai-transform-to-code.migration.test.ts +++ b/packages/cli/src/modules/breaking-changes/migrations/node-removals/__tests__/ai-transform-to-code.migration.test.ts @@ -1,5 +1,5 @@ -import { createNode } from '../../__tests__/test-helpers'; -import { AI_TRANSFORM_NODE_TYPE } from '../../rules/v3/ai-transform-deprecated.rule'; +import { createNode } from '../../../__tests__/test-helpers'; +import { AI_TRANSFORM_NODE_TYPE } from '../../../rules/v3/ai-transform-deprecated.rule'; import { aiTransformToCode } from '../ai-transform-to-code.migration'; describe('aiTransformToCode migration', () => { diff --git a/packages/cli/src/modules/breaking-changes/migrations/node-removals/__tests__/file-and-html-nodes.migrations.test.ts b/packages/cli/src/modules/breaking-changes/migrations/node-removals/__tests__/file-and-html-nodes.migrations.test.ts new file mode 100644 index 00000000000..02ed9564eb2 --- /dev/null +++ b/packages/cli/src/modules/breaking-changes/migrations/node-removals/__tests__/file-and-html-nodes.migrations.test.ts @@ -0,0 +1,222 @@ +import { createNode } from '../../../__tests__/test-helpers'; +import { htmlExtractToHtml } from '../html-extract-to-html.migration'; +import { readPdfToExtractFromFile } from '../read-pdf-to-extract-from-file.migration'; +import { writeBinaryFileToReadWriteFile } from '../write-binary-file-to-read-write-file.migration'; + +describe('htmlExtractToHtml migration', () => { + const extractionValues = { + values: [{ key: 'title', cssSelector: 'h1', returnValue: 'text', returnArray: false }], + }; + + it('is keyed by the HTML Extract rule id', () => { + expect(htmlExtractToHtml.ruleId).toBe('html-extract-removed-v3'); + }); + + it('targets HTML 1.1 and keeps the extraction settings', () => { + const node = createNode('Extract', 'n8n-nodes-base.htmlExtract', { + sourceData: 'binary', + dataPropertyName: 'file', + extractionValues, + options: { trimValues: false }, + }); + + const result = htmlExtractToHtml.migrate(node); + + expect(result.node).toEqual({ + type: 'n8n-nodes-base.html', + typeVersion: 1.1, + parameters: { + operation: 'extractHtmlContent', + sourceData: 'binary', + dataPropertyName: 'file', + extractionValues, + options: { trimValues: false, cleanUpText: false }, + }, + }); + }); + + describe('note about the empty text', () => { + const migrateWith = (values: unknown[]) => + htmlExtractToHtml.migrate( + createNode('Extract', 'n8n-nodes-base.htmlExtract', { extractionValues: { values } }), + ); + + it.each([ + ['the text return value', [{ key: 'a', cssSelector: 'h1', returnValue: 'text' }]], + ['no return value, because the default is text', [{ key: 'a', cssSelector: 'h1' }]], + [ + 'an expression for the return value', + [{ key: 'a', cssSelector: 'h1', returnValue: '={{ $json.kind }}' }], + ], + [ + 'text next to other return values', + [ + { key: 'a', cssSelector: 'a', returnValue: 'attribute', attribute: 'href' }, + { key: 'b', cssSelector: 'h1', returnValue: 'text', returnArray: true }, + ], + ], + ])('reports one note for %s', (_name, values) => { + expect(migrateWith(values).notes).toEqual([expect.stringContaining('no value')]); + }); + + it('reports one note for several text values', () => { + const { notes } = migrateWith([ + { key: 'a', cssSelector: 'h1', returnValue: 'text' }, + { key: 'b', cssSelector: 'h2', returnValue: 'text' }, + ]); + + expect(notes).toHaveLength(1); + }); + + it.each([ + ['html', { key: 'a', cssSelector: 'h1', returnValue: 'html' }], + ['attribute', { key: 'a', cssSelector: 'a', returnValue: 'attribute', attribute: 'href' }], + ['value', { key: 'a', cssSelector: 'input', returnValue: 'value' }], + ])('reports no note when every value returns %s', (_name, value) => { + expect(migrateWith([value]).notes).toBeUndefined(); + }); + + it('reports no note for a node with no extraction values', () => { + const { notes } = htmlExtractToHtml.migrate( + createNode('Extract', 'n8n-nodes-base.htmlExtract', {}), + ); + + expect(notes).toBeUndefined(); + }); + }); + + it('writes trimValues explicitly, because the old node trims when it is missing', () => { + const node = createNode('Extract', 'n8n-nodes-base.htmlExtract', { extractionValues }); + + const { node: migrated } = htmlExtractToHtml.migrate(node); + + expect(migrated.parameters.options).toEqual({ trimValues: true, cleanUpText: false }); + }); + + it('keeps the old failure for a node with no extraction values', () => { + const { node } = htmlExtractToHtml.migrate( + createNode('Extract', 'n8n-nodes-base.htmlExtract', {}), + ); + + expect(node.parameters.extractionValues).toEqual({}); + }); + + it('refuses options in an unsupported format', () => { + const node = createNode('Extract', 'n8n-nodes-base.htmlExtract', { options: 'x' }); + + expect(() => htmlExtractToHtml.migrate(node)).toThrow('not in a supported format'); + }); + + it('refuses an expression for Trim Values, because the old and new node read falsy values differently', () => { + const node = createNode('Extract', 'n8n-nodes-base.htmlExtract', { + extractionValues, + options: { trimValues: '={{ $json.trim }}' }, + }); + + expect(() => htmlExtractToHtml.migrate(node)).toThrow('"Trim Values" is an expression'); + }); + + it.each([[true], [false]])('keeps a plain Trim Values value of %s', (trimValues) => { + const node = createNode('Extract', 'n8n-nodes-base.htmlExtract', { + extractionValues, + options: { trimValues }, + }); + + const { node: migrated } = htmlExtractToHtml.migrate(node); + + expect(migrated.parameters.options).toEqual({ trimValues, cleanUpText: false }); + }); +}); + +describe('readPdfToExtractFromFile migration', () => { + it('is keyed by the Read PDF rule id', () => { + expect(readPdfToExtractFromFile.ruleId).toBe('read-pdf-removed-v3'); + }); + + it('keeps the binary and drops the input JSON, as the old node did', () => { + const result = readPdfToExtractFromFile.migrate( + createNode('PDF', 'n8n-nodes-base.readPDF', { binaryPropertyName: 'invoice' }), + ); + + expect(result.node).toEqual({ + type: 'n8n-nodes-base.extractFromFile', + typeVersion: 1.2, + parameters: { + operation: 'pdf', + binaryPropertyName: 'invoice', + options: { keepSource: 'binary' }, + }, + }); + }); + + it('moves the password only for an encrypted PDF', () => { + const encrypted = readPdfToExtractFromFile.migrate( + createNode('PDF', 'n8n-nodes-base.readPDF', { encrypted: true, password: 'secret' }), + ); + const stale = readPdfToExtractFromFile.migrate( + createNode('PDF', 'n8n-nodes-base.readPDF', { encrypted: false, password: 'secret' }), + ); + + expect(encrypted.node.parameters.options).toEqual({ keepSource: 'binary', password: 'secret' }); + expect(stale.node.parameters.options).toEqual({ keepSource: 'binary' }); + }); + + it('passes an empty password for an encrypted PDF with no password, as the old node did', () => { + const { node } = readPdfToExtractFromFile.migrate( + createNode('PDF', 'n8n-nodes-base.readPDF', { encrypted: true }), + ); + + expect(node.parameters.options).toEqual({ keepSource: 'binary', password: '' }); + }); + + it('does not write maxPages, because 0 reads no pages', () => { + const { node } = readPdfToExtractFromFile.migrate( + createNode('PDF', 'n8n-nodes-base.readPDF', {}), + ); + + expect(node.parameters.options).not.toHaveProperty('maxPages'); + expect(node.parameters.options).not.toHaveProperty('joinPages'); + }); + + it('refuses an expression for Encrypted', () => { + const node = createNode('PDF', 'n8n-nodes-base.readPDF', { encrypted: '={{ $json.enc }}' }); + + expect(() => readPdfToExtractFromFile.migrate(node)).toThrow('Encrypted'); + }); +}); + +describe('writeBinaryFileToReadWriteFile migration', () => { + it('is keyed by the Write Binary File rule id', () => { + expect(writeBinaryFileToReadWriteFile.ruleId).toBe('write-binary-file-removed-v3'); + }); + + it('keeps the file name, the binary property and the append option', () => { + const result = writeBinaryFileToReadWriteFile.migrate( + createNode('Write', 'n8n-nodes-base.writeBinaryFile', { + fileName: '/data/out.txt', + dataPropertyName: 'content', + options: { append: true }, + }), + ); + + expect(result.node).toEqual({ + type: 'n8n-nodes-base.readWriteFile', + typeVersion: 1.1, + parameters: { + operation: 'write', + fileName: '/data/out.txt', + dataPropertyName: 'content', + options: { append: true }, + }, + }); + }); + + it('refuses an append expression, because the old node reads it once', () => { + const node = createNode('Write', 'n8n-nodes-base.writeBinaryFile', { + fileName: '/data/out.txt', + options: { append: '={{ $json.append }}' }, + }); + + expect(() => writeBinaryFileToReadWriteFile.migrate(node)).toThrow('Append'); + }); +}); diff --git a/packages/cli/src/modules/breaking-changes/migrations/node-removals/__tests__/ical-to-convert-to-file.migration.test.ts b/packages/cli/src/modules/breaking-changes/migrations/node-removals/__tests__/ical-to-convert-to-file.migration.test.ts new file mode 100644 index 00000000000..0019d77e49b --- /dev/null +++ b/packages/cli/src/modules/breaking-changes/migrations/node-removals/__tests__/ical-to-convert-to-file.migration.test.ts @@ -0,0 +1,38 @@ +import { createNode } from '../../../__tests__/test-helpers'; +import { icalToConvertToFile } from '../ical-to-convert-to-file.migration'; + +describe('icalToConvertToFile migration', () => { + it('is keyed by the iCalendar rule id', () => { + expect(icalToConvertToFile.ruleId).toBe('i-calendar-removed-v3'); + }); + + it('keeps every parameter and switches the operation', () => { + const parameters = { + operation: 'createEventFile', + title: 'Standup', + start: '2026-01-01T09:00:00', + end: '2026-01-01T09:15:00', + allDay: false, + binaryPropertyName: 'invite', + additionalFields: { location: 'Room 1', attendeesUi: { attendees: [{ name: 'A' }] } }, + }; + + const result = icalToConvertToFile.migrate( + createNode('iCal', 'n8n-nodes-base.iCal', parameters), + ); + + expect(result.node).toEqual({ + type: 'n8n-nodes-base.convertToFile', + typeVersion: 1.1, + parameters: { ...parameters, operation: 'iCal' }, + }); + }); + + it('sets the operation when the saved workflow omits it', () => { + const { node } = icalToConvertToFile.migrate( + createNode('iCal', 'n8n-nodes-base.iCal', { title: 'x' }), + ); + + expect(node.parameters).toEqual({ title: 'x', operation: 'iCal' }); + }); +}); diff --git a/packages/cli/src/modules/breaking-changes/migrations/node-removals/__tests__/item-lists-legacy.migration.test.ts b/packages/cli/src/modules/breaking-changes/migrations/node-removals/__tests__/item-lists-legacy.migration.test.ts new file mode 100644 index 00000000000..56e347b59d5 --- /dev/null +++ b/packages/cli/src/modules/breaking-changes/migrations/node-removals/__tests__/item-lists-legacy.migration.test.ts @@ -0,0 +1,594 @@ +import type { INodeParameters } from 'n8n-workflow'; + +import { createNode } from '../../../__tests__/test-helpers'; +import { itemListsToTransformNodes } from '../item-lists.migration'; + +// Item Lists 1 and 2 store field lists as a collection: `{ fields: [{ fieldName }] }`. +const fields = (...names: string[]) => ({ fields: names.map((fieldName) => ({ fieldName })) }); + +const migrate = (typeVersion: number, parameters: INodeParameters) => + itemListsToTransformNodes.migrate({ + ...createNode('Item Lists', 'n8n-nodes-base.itemLists', { + resource: 'itemList', + ...parameters, + }), + typeVersion, + }); + +const LEGACY_VERSIONS = [1, 2, 2.1, 2.2]; + +describe('Item Lists 1 and 2', () => { + describe('operation names', () => { + it.each(LEGACY_VERSIONS)('does not know "concatenateItems" in Item Lists %s', (version) => { + expect(() => migrate(version, { operation: 'concatenateItems' })).toThrow('not supported'); + }); + + it('does not know "aggregateItems" in Item Lists 3', () => { + expect(() => migrate(3, { operation: 'aggregateItems' })).toThrow('not supported'); + }); + }); + + // The old nodes stop with an error where the new nodes continue. A note tells the user to + // check the workflow, and it turns off the one-click republish. + describe('note about a failure that becomes a success', () => { + const aggregate = (parameters: INodeParameters = {}, options: INodeParameters = {}) => ({ + operation: 'aggregateItems', + aggregate: 'aggregateIndividualFields', + fieldsToAggregate: { fieldToAggregate: [{ fieldToAggregate: 'id' }] }, + ...parameters, + ...(Object.keys(options).length > 0 ? { options } : {}), + }); + + describe('Aggregate with individual fields', () => { + it.each([1, 2])( + 'reports a note in Item Lists %s when a missing field stops the node', + (v) => { + expect(migrate(v, aggregate()).notes).toEqual([ + expect.stringContaining('missing in all items'), + ]); + }, + ); + + it('reports a note when the saved node omits the mode and the field', () => { + expect(migrate(2, { operation: 'aggregateItems' }).notes).toHaveLength(1); + }); + + it.each([2.1, 2.2])('reports no note in Item Lists %s, because it never stops', (v) => { + expect(migrate(v, aggregate()).notes).toBeUndefined(); + }); + + it.each([1, 2])('reports no note in Item Lists %s when Keep Missing is on', (v) => { + expect(migrate(v, aggregate({}, { keepMissing: true })).notes).toBeUndefined(); + }); + + it.each([ + ['off', false], + ['an expression, which could be off', '={{ $json.keep }}'], + ])('reports a note when Keep Missing is %s', (_name, keepMissing) => { + expect(migrate(1, aggregate({}, { keepMissing })).notes).toHaveLength(1); + }); + }); + + describe('Split Out', () => { + const splitOut = { operation: 'splitOutItems', fieldToSplitOut: 'tags' }; + + it.each([1, 2])( + 'reports a note in Item Lists %s for a missing field or a plain value', + (v) => { + expect(migrate(v, splitOut).notes).toEqual([expect.stringContaining('was missing')]); + }, + ); + + it('reports a note in Item Lists 2.1 for a plain value only', () => { + const { notes } = migrate(2.1, splitOut); + + expect(notes).toEqual([expect.stringContaining('not a list or an object')]); + expect(notes?.[0]).not.toContain('was missing'); + }); + + it('reports no note in Item Lists 2.2, because it never stops', () => { + expect(migrate(2.2, splitOut).notes).toBeUndefined(); + }); + }); + + it.each(LEGACY_VERSIONS)( + 'reports no note for Aggregate with all item data in %s', + (version) => { + const result = migrate(version, { + operation: 'aggregateItems', + aggregate: 'aggregateAllItemData', + }); + + expect(result.notes).toBeUndefined(); + }, + ); + + it.each([ + ['limit', { operation: 'limit', maxItems: 2 }], + ['sort', { operation: 'sort', type: 'simple' }], + ['removeDuplicates', { operation: 'removeDuplicates' }], + ['summarize', { operation: 'summarize' }], + ])('reports no note for %s', (_name, parameters) => { + expect(migrate(2.2, parameters).notes).toBeUndefined(); + }); + + it.each([ + ['concatenateItems', { operation: 'concatenateItems' }], + ['splitOutItems', { operation: 'splitOutItems', fieldToSplitOut: 'tags' }], + ])( + 'reports no note for %s in Item Lists 3, because it is the template', + (_name, parameters) => { + expect(migrate(3, parameters).notes).toBeUndefined(); + }, + ); + }); + + describe('Concatenate Items (aggregateItems) to Aggregate', () => { + it.each(LEGACY_VERSIONS)('migrates a sparse node in Item Lists %s', (version) => { + const { node } = migrate(version, { operation: 'aggregateItems' }); + + expect(node).toEqual({ type: 'n8n-nodes-base.aggregate', typeVersion: 1, parameters: {} }); + }); + + it('copies individual fields and the known options, and drops the rest', () => { + const fieldsToAggregate = { + fieldToAggregate: [{ fieldToAggregate: 'id', renameField: true, outputFieldName: 'ids' }], + }; + + const { node } = migrate(1, { + operation: 'aggregateItems', + aggregate: 'aggregateIndividualFields', + fieldsToAggregate, + options: { disableDotNotation: true, mergeLists: true, keepMissing: true, stale: 1 }, + // Hidden in this mode. + destinationFieldName: 'stale', + include: 'specifiedFields', + fieldsToInclude: fields('stale'), + }); + + expect(node.parameters).toEqual({ + aggregate: 'aggregateIndividualFields', + fieldsToAggregate, + options: { disableDotNotation: true, mergeLists: true, keepMissing: true }, + }); + }); + + it('keeps an expression in a field name of individual mode', () => { + const fieldsToAggregate = { fieldToAggregate: [{ fieldToAggregate: '={{ $json.k }}' }] }; + + const { node } = migrate(2.2, { operation: 'aggregateItems', fieldsToAggregate }); + + expect(node.parameters).toEqual({ fieldsToAggregate }); + }); + + it('converts the excluded fields of all item data to a string', () => { + const { node } = migrate(2.1, { + operation: 'aggregateItems', + aggregate: 'aggregateAllItemData', + include: 'allFieldsExcept', + destinationFieldName: 'rows', + fieldsToExclude: fields('a', 'b'), + }); + + expect(node.parameters).toEqual({ + aggregate: 'aggregateAllItemData', + include: 'allFieldsExcept', + destinationFieldName: 'rows', + fieldsToExclude: 'a, b', + }); + }); + + it('converts the included fields and drops the list of the other mode', () => { + const { node } = migrate(1, { + operation: 'aggregateItems', + aggregate: 'aggregateAllItemData', + include: 'specifiedFields', + fieldsToInclude: fields('x'), + fieldsToExclude: fields('stale'), + options: { mergeLists: true }, + }); + + expect(node.parameters).toEqual({ + aggregate: 'aggregateAllItemData', + include: 'specifiedFields', + fieldsToInclude: 'x', + }); + }); + + it('writes no list for a sparse all-data node or an empty list', () => { + const sparse = migrate(2, { operation: 'aggregateItems', aggregate: 'aggregateAllItemData' }); + + expect(sparse.node.parameters).toEqual({ aggregate: 'aggregateAllItemData' }); + + const { node } = migrate(2, { + operation: 'aggregateItems', + aggregate: 'aggregateAllItemData', + include: 'specifiedFields', + fieldsToInclude: { fields: [] }, + }); + + expect(node.parameters).toEqual({ + aggregate: 'aggregateAllItemData', + include: 'specifiedFields', + }); + }); + + it.each([ + ['an empty field name', { fields: [{}] }], + ['a blank field name', fields('')], + ['a name with a space at the start', fields(' a')], + ['a name with a comma', fields('a,b')], + ['a name that is an expression', fields('={{ $json.k }}')], + ['a list that is not readable', { fields: 'a' }], + ])('refuses a list with %s', (_name, fieldsToInclude) => { + const run = () => + migrate(2.2, { + operation: 'aggregateItems', + aggregate: 'aggregateAllItemData', + include: 'specifiedFields', + fieldsToInclude, + }); + + expect(run).toThrow('Fields to Include'); + }); + + it.each([ + ['an expression for the mode', { aggregate: '={{ $json.m }}' }], + ['an unknown mode', { aggregate: 'merge' }], + [ + 'an expression for the fields to include', + { aggregate: 'aggregateAllItemData', include: '={{ $json.i }}' }, + ], + ])('refuses %s', (_name, parameters) => { + expect(() => migrate(2, { operation: 'aggregateItems', ...parameters })).toThrow(); + }); + }); + + describe('Remove Duplicates', () => { + it.each(LEGACY_VERSIONS)('migrates a sparse node in Item Lists %s', (version) => { + const { node } = migrate(version, { operation: 'removeDuplicates' }); + + expect(node).toEqual({ + type: 'n8n-nodes-base.removeDuplicates', + typeVersion: 1, + parameters: {}, + }); + }); + + it('trims the compared fields, as the old node does, and drops empty names', () => { + const { node } = migrate(2.2, { + operation: 'removeDuplicates', + compare: 'selectedFields', + fieldsToCompare: fields('a', ' b.c ', ''), + }); + + expect(node.parameters).toEqual({ compare: 'selectedFields', fieldsToCompare: 'a, b.c' }); + }); + + it('converts the excluded fields and copies the options', () => { + const { node } = migrate(1, { + operation: 'removeDuplicates', + compare: 'allFieldsExcept', + fieldsToExclude: fields('id', 'createdAt'), + options: { disableDotNotation: true, removeOtherFields: true }, + }); + + expect(node.parameters).toEqual({ + compare: 'allFieldsExcept', + fieldsToExclude: 'id, createdAt', + options: { disableDotNotation: true, removeOtherFields: true }, + }); + }); + + it('drops a stale list and stale options when all fields are compared', () => { + const { node } = migrate(2, { + operation: 'removeDuplicates', + compare: 'allFields', + fieldsToCompare: fields('={{ $json.k }}'), + options: { removeOtherFields: '={{ true }}' }, + }); + + expect(node.parameters).toEqual({ compare: 'allFields' }); + }); + + it.each([ + ['a name that is an expression', 'selectedFields', fields('={{ $json.k }}')], + ['a name with a comma', 'selectedFields', fields('a,b')], + ['a name without a field name', 'selectedFields', { fields: [{}] }], + ['an excluded name with a space at the start', 'allFieldsExcept', fields(' id')], + ['an excluded name that is only spaces', 'allFieldsExcept', fields(' ')], + ['an excluded name without a field name', 'allFieldsExcept', { fields: [{}] }], + ])('refuses %s', (_name, compare, list) => { + const run = () => + migrate(2.1, { + operation: 'removeDuplicates', + compare, + ...(compare === 'selectedFields' ? { fieldsToCompare: list } : { fieldsToExclude: list }), + }); + + expect(run).toThrow(); + }); + + it.each([ + ['an expression for the mode', { compare: '={{ $json.m }}' }], + ['an unknown mode', { compare: 'some' }], + [ + 'an option that is an expression', + { compare: 'selectedFields', options: { removeOtherFields: '={{ true }}' } }, + ], + ])('refuses %s', (_name, parameters) => { + expect(() => migrate(2, { operation: 'removeDuplicates', ...parameters })).toThrow(); + }); + }); + + describe('Split Out Items', () => { + it('migrates a list of fields with destination fields in Item Lists 2.2', () => { + const { node } = migrate(2.2, { + operation: 'splitOutItems', + fieldToSplitOut: 'a, b', + options: { destinationFieldName: 'x,y' }, + }); + + expect(node).toEqual({ + type: 'n8n-nodes-base.splitOut', + typeVersion: 1, + parameters: { fieldToSplitOut: 'a, b', options: { destinationFieldName: 'x,y' } }, + }); + }); + + it('converts the included fields to a string', () => { + const { node } = migrate(2.1, { + operation: 'splitOutItems', + fieldToSplitOut: 'a', + include: 'selectedOtherFields', + fieldsToInclude: fields('id', 'user.name'), + }); + + expect(node.parameters).toEqual({ + fieldToSplitOut: 'a', + include: 'selectedOtherFields', + fieldsToInclude: 'id,user.name', + }); + }); + + it('drops options that belong to other operations', () => { + const { node } = migrate(2.2, { + operation: 'splitOutItems', + fieldToSplitOut: 'a', + options: { + includeBinary: true, + mergeLists: true, + keepMissing: true, + disableDotNotation: true, + }, + }); + + expect(node.parameters).toEqual({ + fieldToSplitOut: 'a', + options: { disableDotNotation: true }, + }); + }); + + it('accepts an expression in the field of Item Lists 2, which can only be checked at run time', () => { + const { node } = migrate(2, { + operation: 'splitOutItems', + fieldToSplitOut: '={{ $json.field }}', + }); + + expect(node.parameters).toEqual({ fieldToSplitOut: '={{ $json.field }}' }); + }); + + it.each([ + ['no field', {}], + ['an empty entry', { fieldToSplitOut: 'a,,b' }], + ['a field that starts with $json.', { fieldToSplitOut: '$json.a' }], + ['a field that is $binary', { fieldToSplitOut: ' $binary ' }], + [ + 'an included field without a name', + { fieldToSplitOut: 'a', include: 'selectedOtherFields', fieldsToInclude: { fields: [{}] } }, + ], + [ + 'an included field with a comma', + { fieldToSplitOut: 'a', include: 'selectedOtherFields', fieldsToInclude: fields('x,y') }, + ], + [ + 'dot notation set by an expression', + { fieldToSplitOut: 'a', options: { disableDotNotation: '={{ true }}' } }, + ], + ['an unknown include mode', { fieldToSplitOut: 'a', include: 'some' }], + ])('refuses Item Lists 2.2 with %s', (_name, parameters) => { + expect(() => migrate(2.2, { operation: 'splitOutItems', ...parameters })).toThrow(); + }); + + describe('Item Lists 1', () => { + it('migrates one field with a destination field', () => { + const { node } = migrate(1, { + operation: 'splitOutItems', + fieldToSplitOut: 'items', + options: { destinationFieldName: 'item' }, + }); + + expect(node.parameters).toEqual({ + fieldToSplitOut: 'items', + options: { destinationFieldName: 'item' }, + }); + }); + + it.each([ + ['a list of fields', { fieldToSplitOut: 'a,b' }], + ['a field with a space at the start', { fieldToSplitOut: ' a' }], + ['a field that is an expression', { fieldToSplitOut: '={{ $json.f }}' }], + [ + 'a destination field with a comma', + { fieldToSplitOut: 'a', options: { destinationFieldName: 'x,y' } }, + ], + [ + 'a destination field that is an expression', + { fieldToSplitOut: 'a', options: { destinationFieldName: '={{ $json.d }}' } }, + ], + [ + 'an included field with the name of the split field', + { fieldToSplitOut: 'a', include: 'selectedOtherFields', fieldsToInclude: fields('a') }, + ], + [ + 'an included field with the name of the destination field', + { + fieldToSplitOut: 'a', + include: 'selectedOtherFields', + fieldsToInclude: fields('d'), + options: { destinationFieldName: 'd' }, + }, + ], + [ + 'all other fields with a dot name and dot notation off', + { + fieldToSplitOut: 'a.b', + include: 'allOtherFields', + options: { disableDotNotation: true }, + }, + ], + ])('refuses %s', (_name, parameters) => { + expect(() => migrate(1, { operation: 'splitOutItems', ...parameters })).toThrow(); + }); + + it('migrates all other fields with a dot name when dot notation is on', () => { + const { node } = migrate(1, { + operation: 'splitOutItems', + fieldToSplitOut: 'a.b', + include: 'allOtherFields', + }); + + expect(node.parameters).toEqual({ fieldToSplitOut: 'a.b', include: 'allOtherFields' }); + }); + }); + }); + + describe('Summarize', () => { + const values = (...entries: INodeParameters[]) => ({ fieldsToSummarize: { values: entries } }); + + it('migrates a sparse count to Summarize 1.1 in Item Lists 2.2', () => { + const { node } = migrate(2.2, { operation: 'summarize', ...values({ field: 'a' }) }); + + expect(node).toEqual({ + type: 'n8n-nodes-base.summarize', + typeVersion: 1.1, + parameters: values({ field: 'a' }), + }); + }); + + it.each([ + [1, 1], + [2, 1], + [2.1, 1.1], + [2.2, 1.1], + ])( + 'migrates Item Lists %s to Summarize %s, which treats a missing field in the same way', + (version, expected) => { + const { node } = migrate(version, { + operation: 'summarize', + ...values({ aggregation: 'sum', field: 'amount' }), + }); + + expect(node.typeVersion).toBe(expected); + }, + ); + + it('copies the known options and drops the others', () => { + const { node } = migrate(2, { + operation: 'summarize', + ...values({ aggregation: 'sum', field: 'amount' }), + options: { + outputFormat: 'singleItem', + disableDotNotation: true, + skipEmptySplitFields: true, + continueIfFieldNotFound: true, + }, + }); + + expect(node.parameters).toEqual({ + ...values({ aggregation: 'sum', field: 'amount' }), + options: { + outputFormat: 'singleItem', + disableDotNotation: true, + skipEmptySplitFields: true, + }, + }); + }); + + it('keeps Include Empty and the separator for concatenate', () => { + const entry = { + aggregation: 'concatenate', + field: 'a', + includeEmpty: true, + separateBy: 'other', + customSeparator: '|', + }; + + const { node } = migrate(2.2, { operation: 'summarize', ...values(entry) }); + + expect(node.parameters).toEqual(values(entry)); + }); + + it('migrates a field with a dot in Item Lists 2, which cleans up the name as the new node does', () => { + const { node } = migrate(2.2, { operation: 'summarize', ...values({ field: 'a.b' }) }); + + expect(node.type).toBe('n8n-nodes-base.summarize'); + }); + + it('migrates a field that is an expression in Item Lists 2', () => { + const { node } = migrate(2, { + operation: 'summarize', + ...values({ field: '={{ $json.f }}' }), + }); + + expect(node.type).toBe('n8n-nodes-base.summarize'); + }); + + it.each([ + ['a field with a dot', { field: 'a.b' }], + ['a field with a space', { field: 'a b' }], + ['a field with a bracket', { field: 'a[0]' }], + ['a field that is an expression', { field: '={{ $json.f }}' }], + ])('refuses %s in Item Lists 1, which keeps the output name as it is', (_name, entry) => { + expect(() => migrate(1, { operation: 'summarize', ...values(entry) })).toThrow(); + }); + + it.each([ + ['Count with Include Empty', { aggregation: 'count', field: 'a', includeEmpty: true }], + ['a missing aggregation with Include Empty', { field: 'a', includeEmpty: true }], + [ + 'Count Unique with an expression', + { aggregation: 'countUnique', field: 'a', includeEmpty: '={{ true }}' }, + ], + ['Minimum', { aggregation: 'min', field: 'price' }], + ['Maximum', { aggregation: 'max', field: 'price' }], + ['an aggregation that is an expression', { aggregation: '={{ $json.a }}', field: 'a' }], + ['an unknown aggregation', { aggregation: 'median', field: 'a' }], + ])('refuses %s', (_name, entry) => { + expect(() => migrate(2.1, { operation: 'summarize', ...values(entry) })).toThrow(); + }); + + it('refuses two fields that give the same output name after cleanup', () => { + const run = () => + migrate(2.1, { operation: 'summarize', ...values({ field: 'a b' }, { field: 'a_b' }) }); + + expect(run).toThrow('same output name'); + }); + + it('migrates two entries with the same output name, which behave in the same way', () => { + const { node } = migrate(2.1, { + operation: 'summarize', + ...values({ field: 'a b' }, { field: 'a b' }), + }); + + expect(node.type).toBe('n8n-nodes-base.summarize'); + }); + + it.each([['team'], ['={{ $json.k }}']])('refuses a split by "%s"', (fieldsToSplitBy) => { + const run = () => + migrate(2.2, { operation: 'summarize', ...values({ field: 'a' }), fieldsToSplitBy }); + + expect(run).toThrow('Fields to Split By'); + }); + }); +}); diff --git a/packages/cli/src/modules/breaking-changes/migrations/node-removals/__tests__/item-lists.migration.test.ts b/packages/cli/src/modules/breaking-changes/migrations/node-removals/__tests__/item-lists.migration.test.ts new file mode 100644 index 00000000000..52d4570eaed --- /dev/null +++ b/packages/cli/src/modules/breaking-changes/migrations/node-removals/__tests__/item-lists.migration.test.ts @@ -0,0 +1,271 @@ +import type { INodeParameters } from 'n8n-workflow'; + +import { createNode } from '../../../__tests__/test-helpers'; +import { itemListsToTransformNodes } from '../item-lists.migration'; + +const itemLists = (typeVersion: number, parameters: INodeParameters) => ({ + ...createNode('Item Lists', 'n8n-nodes-base.itemLists', { resource: 'itemList', ...parameters }), + typeVersion, +}); + +describe('itemListsToTransformNodes migration', () => { + it('is keyed by the Item Lists rule id', () => { + expect(itemListsToTransformNodes.ruleId).toBe('item-lists-removed-v3'); + }); + + describe.each([1, 2, 2.1, 2.2, 3, 3.1])('Item Lists %s', (version) => { + it('migrates Limit', () => { + const { node } = itemListsToTransformNodes.migrate( + itemLists(version, { operation: 'limit', maxItems: 5, keep: 'lastItems' }), + ); + + expect(node).toEqual({ + type: 'n8n-nodes-base.limit', + typeVersion: 1, + parameters: { maxItems: 5, keep: 'lastItems' }, + }); + }); + + it('migrates Sort', () => { + const sortFieldsUi = { sortField: [{ fieldName: 'name', order: 'descending' }] }; + + const { node } = itemListsToTransformNodes.migrate( + itemLists(version, { + operation: 'sort', + type: 'simple', + sortFieldsUi, + options: { disableDotNotation: true }, + }), + ); + + expect(node).toEqual({ + type: 'n8n-nodes-base.sort', + typeVersion: 1, + parameters: { + type: 'simple', + sortFieldsUi, + options: { disableDotNotation: true }, + }, + }); + }); + }); + + describe.each([3, 3.1])('Item Lists %s', (version) => { + it('migrates Concatenate Items to Aggregate', () => { + const fieldsToAggregate = { + fieldToAggregate: [{ fieldToAggregate: 'id', renameField: true, outputFieldName: 'ids' }], + }; + + const { node } = itemListsToTransformNodes.migrate( + itemLists(version, { + operation: 'concatenateItems', + aggregate: 'aggregateIndividualFields', + fieldsToAggregate, + options: { mergeLists: true }, + }), + ); + + expect(node).toEqual({ + type: 'n8n-nodes-base.aggregate', + typeVersion: 1, + parameters: { + aggregate: 'aggregateIndividualFields', + fieldsToAggregate, + options: { mergeLists: true }, + }, + }); + }); + + it('migrates Split Out Items to Split Out 1, which has no nested destination paths', () => { + const { node } = itemListsToTransformNodes.migrate( + itemLists(version, { + operation: 'splitOutItems', + fieldToSplitOut: 'items', + include: 'selectedOtherFields', + fieldsToInclude: 'a, b', + options: { destinationFieldName: 'item' }, + }), + ); + + expect(node).toEqual({ + type: 'n8n-nodes-base.splitOut', + typeVersion: 1, + parameters: { + fieldToSplitOut: 'items', + include: 'selectedOtherFields', + fieldsToInclude: 'a, b', + options: { destinationFieldName: 'item' }, + }, + }); + }); + + it.each([[''], ['a,'], [' , b'], ['a,,b']])( + 'refuses Split Out Items with an empty entry in Field to Split Out (%j), which Split Out ignores', + (fieldToSplitOut) => { + const node = itemLists(version, { operation: 'splitOutItems', fieldToSplitOut }); + + expect(() => itemListsToTransformNodes.migrate(node)).toThrow('empty'); + }, + ); + + it('refuses Split Out Items when Field to Split Out is missing', () => { + const node = itemLists(version, { operation: 'splitOutItems' }); + + expect(() => itemListsToTransformNodes.migrate(node)).toThrow('empty'); + }); + + it.each([['a, b'], ['={{ $json.fields }}']])( + 'migrates Split Out Items with Field to Split Out %j', + (fieldToSplitOut) => { + const node = itemLists(version, { operation: 'splitOutItems', fieldToSplitOut }); + + expect(itemListsToTransformNodes.migrate(node).node.type).toBe('n8n-nodes-base.splitOut'); + }, + ); + + it('treats a missing operation as Split Out Items, the Item Lists default', () => { + const { node } = itemListsToTransformNodes.migrate( + itemLists(version, { fieldToSplitOut: 'items' }), + ); + + expect(node.type).toBe('n8n-nodes-base.splitOut'); + }); + + it('migrates Summarize to Summarize 1.1, which reports a missing field as a hint', () => { + const parameters = { + fieldsToSummarize: { values: [{ aggregation: 'sum', field: 'amount' }] }, + options: { outputFormat: 'singleItem' }, + }; + + const { node } = itemListsToTransformNodes.migrate( + itemLists(version, { operation: 'summarize', ...parameters }), + ); + + expect(node).toEqual({ + type: 'n8n-nodes-base.summarize', + typeVersion: 1.1, + parameters, + }); + }); + + it.each([['team'], ['team, region'], [' , team']])( + 'refuses Summarize that splits by "%s", because Summarize keeps the type and order of the values', + (fieldsToSplitBy) => { + const node = itemLists(version, { + operation: 'summarize', + fieldsToSummarize: { values: [{ aggregation: 'sum', field: 'amount' }] }, + fieldsToSplitBy, + }); + + expect(() => itemListsToTransformNodes.migrate(node)).toThrow('Fields to Split By'); + }, + ); + + it.each([[undefined], [''], [' , ']])( + 'migrates Summarize with an empty Fields to Split By (%j)', + (fieldsToSplitBy) => { + const node = itemLists(version, { + operation: 'summarize', + fieldsToSummarize: { values: [{ aggregation: 'sum', field: 'amount' }] }, + ...(fieldsToSplitBy === undefined ? {} : { fieldsToSplitBy }), + }); + + expect(itemListsToTransformNodes.migrate(node).node.type).toBe('n8n-nodes-base.summarize'); + }, + ); + + it('refuses Summarize that splits by an expression', () => { + const node = itemLists(version, { + operation: 'summarize', + fieldsToSummarize: { values: [{ aggregation: 'sum', field: 'amount' }] }, + fieldsToSplitBy: '={{ $json.field }}', + }); + + expect(() => itemListsToTransformNodes.migrate(node)).toThrow('Fields to Split By'); + }); + + it.each([['count'], ['countUnique'], [undefined]])( + 'refuses Summarize with "Include Empty Values" on for %s', + (aggregation) => { + // A saved workflow omits the default aggregation, `count`. + const node = itemLists(version, { + operation: 'summarize', + fieldsToSummarize: { + values: [{ ...(aggregation ? { aggregation } : {}), field: 'x', includeEmpty: true }], + }, + }); + + expect(() => itemListsToTransformNodes.migrate(node)).toThrow('Include Empty'); + }, + ); + + it('refuses "Include Empty Values" when an expression sets the aggregation', () => { + const node = itemLists(version, { + operation: 'summarize', + fieldsToSummarize: { + values: [{ aggregation: '={{ $json.how }}', field: 'x', includeEmpty: true }], + }, + }); + + expect(() => itemListsToTransformNodes.migrate(node)).toThrow('Include Empty'); + }); + + it('keeps "Include Empty Values" for append, where both nodes use it', () => { + const { node } = itemListsToTransformNodes.migrate( + itemLists(version, { + operation: 'summarize', + fieldsToSummarize: { + values: [{ aggregation: 'append', field: 'x', includeEmpty: true }], + }, + }), + ); + + expect(node.parameters.fieldsToSummarize).toEqual({ + values: [{ aggregation: 'append', field: 'x', includeEmpty: true }], + }); + }); + }); + + it('migrates Remove Duplicates 3 to Remove Duplicates 1, which has a single output', () => { + const { node } = itemListsToTransformNodes.migrate( + itemLists(3, { + operation: 'removeDuplicates', + compare: 'selectedFields', + fieldsToCompare: 'email', + options: { removeOtherFields: true }, + }), + ); + + expect(node).toEqual({ + type: 'n8n-nodes-base.removeDuplicates', + typeVersion: 1, + parameters: { + compare: 'selectedFields', + fieldsToCompare: 'email', + options: { removeOtherFields: true }, + }, + }); + }); + + it('refuses Remove Duplicates 3.1, which accepts values of mixed types', () => { + const node = itemLists(3.1, { operation: 'removeDuplicates' }); + + expect(() => itemListsToTransformNodes.migrate(node)).toThrow('different types'); + }); + + it.each([ + ['an unknown operation', { operation: 'merge' }], + ['an operation set by an expression', { operation: '={{ $json.op }}' }], + ['an operation that names a prototype property', { operation: 'constructor' }], + ])('refuses %s', (_name, parameters) => { + expect(() => itemListsToTransformNodes.migrate(itemLists(3, parameters))).toThrow(); + }); + + it('leaves out parameters that belong to other operations', () => { + const { node } = itemListsToTransformNodes.migrate( + itemLists(3, { operation: 'limit', maxItems: 2, fieldToSplitOut: 'stale' }), + ); + + expect(node.parameters).toEqual({ maxItems: 2 }); + }); +}); diff --git a/packages/cli/src/modules/breaking-changes/migrations/node-removals/__tests__/node-migrations.test.ts b/packages/cli/src/modules/breaking-changes/migrations/node-removals/__tests__/node-migrations.test.ts new file mode 100644 index 00000000000..d5a40f8baac --- /dev/null +++ b/packages/cli/src/modules/breaking-changes/migrations/node-removals/__tests__/node-migrations.test.ts @@ -0,0 +1,42 @@ +import { directNodeReplacementRules } from '../../../rules/v3/removed-nodes-with-replacements.rule'; +import { nodeRemovalMigrations } from '../index'; + +describe('nodeRemovalMigrations', () => { + const ruleIds = new Set(directNodeReplacementRules.map(({ rule }) => new rule().id)); + + it('registers each rule once', () => { + const migrationRuleIds = nodeRemovalMigrations.map(({ ruleId }) => ruleId); + + expect(new Set(migrationRuleIds).size).toBe(migrationRuleIds.length); + }); + + it('keys every migration to a rule that exists', () => { + const known = new Set([...ruleIds, 'ai-transform-deprecated']); + + for (const { ruleId } of nodeRemovalMigrations) { + expect(known, ruleId).toContain(ruleId); + } + }); + + it('does not migrate nodes that cannot keep their configuration', () => { + // See README.md in the migrations folder for the reason for each node. + const notMigratable = [ + 'function-removed-v3', + 'function-item-removed-v3', + 'convert-to-from-binary-data-removed-v3', + 'read-binary-file-removed-v3', + 'read-binary-files-removed-v3', + 'http-request-tool-removed-v3', + 'openai-removed-v3', + 'openai-assistant-removed-v3', + 'openai-model-removed-v3', + 'serpapi-google-search-removed-v3', + ]; + const migrated = new Set(nodeRemovalMigrations.map(({ ruleId }) => ruleId)); + + for (const ruleId of notMigratable) { + expect(ruleIds, ruleId).toContain(ruleId); + expect(migrated.has(ruleId), ruleId).toBe(false); + } + }); +}); diff --git a/packages/cli/src/modules/breaking-changes/migrations/node-removals/__tests__/schedule-trigger.migration.test.ts b/packages/cli/src/modules/breaking-changes/migrations/node-removals/__tests__/schedule-trigger.migration.test.ts new file mode 100644 index 00000000000..3196b8cd7e1 --- /dev/null +++ b/packages/cli/src/modules/breaking-changes/migrations/node-removals/__tests__/schedule-trigger.migration.test.ts @@ -0,0 +1,261 @@ +import { createNode } from '../../../__tests__/test-helpers'; +import { cronToScheduleTrigger } from '../schedule-trigger.migration'; + +const cron = (...items: Array>) => + createNode('Cron', 'n8n-nodes-base.cron', { triggerTimes: { item: items } }); + +const intervals = (migrated: ReturnType) => + migrated.node.parameters.rule; + +describe('cronToScheduleTrigger migration', () => { + it('is keyed by the Cron rule id', () => { + expect(cronToScheduleTrigger.ruleId).toBe('cron-removed-v3'); + }); + + it('targets Schedule Trigger 1.4 and writes no missed-run settings, so the defaults skip a missed run', () => { + const { node } = cronToScheduleTrigger.migrate(cron({ mode: 'everyMinute' })); + + expect(node.type).toBe('n8n-nodes-base.scheduleTrigger'); + expect(node.typeVersion).toBe(1.4); + expect(Object.keys(node.parameters)).toEqual(['rule']); + }); + + it.each([ + ['everyMinute', { mode: 'everyMinute' }, { field: 'minutes', minutesInterval: 1 }], + [ + 'everyHour', + { mode: 'everyHour', minute: 15 }, + { field: 'hours', hoursInterval: 1, triggerAtMinute: 15 }, + ], + [ + 'everyDay', + { mode: 'everyDay', hour: 9, minute: 30 }, + { field: 'days', daysInterval: 1, triggerAtHour: 9, triggerAtMinute: 30 }, + ], + [ + 'everyWeek, with a string weekday', + { mode: 'everyWeek', weekday: '5', hour: 8, minute: 5 }, + { + field: 'weeks', + weeksInterval: 1, + triggerAtDay: [5], + triggerAtHour: 8, + triggerAtMinute: 5, + }, + ], + [ + 'everyMonth', + { mode: 'everyMonth', dayOfMonth: 31, hour: 0, minute: 0 }, + { + field: 'months', + monthsInterval: 1, + triggerAtDayOfMonth: 31, + triggerAtHour: 0, + triggerAtMinute: 0, + }, + ], + [ + 'everyX minutes', + { mode: 'everyX', unit: 'minutes', value: 15 }, + { field: 'minutes', minutesInterval: 15 }, + ], + [ + 'everyX hours, with a minute that the migration picks', + { mode: 'everyX', unit: 'hours', value: 6 }, + { field: 'hours', hoursInterval: 6, triggerAtMinute: expect.any(Number) }, + ], + [ + 'custom, with the expression trimmed', + { mode: 'custom', cronExpression: ' 0 0 9 * * 1-5 ' }, + { field: 'cronExpression', expression: '0 0 9 * * 1-5' }, + ], + ])('maps %s', (_name, item, expected) => { + const result = cronToScheduleTrigger.migrate(cron(item)); + + expect(intervals(result)).toEqual({ interval: [expected] }); + expect(result.unmapped).toBeUndefined(); + expect(result.notes).toBeUndefined(); + }); + + it.each([ + ['minutes', 7, { field: 'minutes', minutesInterval: 7 }], + ['minutes', 50, { field: 'minutes', minutesInterval: 50 }], + ['hours', 5, { field: 'hours', hoursInterval: 5, triggerAtMinute: expect.any(Number) }], + ['hours', 18, { field: 'hours', hoursInterval: 18, triggerAtMinute: expect.any(Number) }], + ])( + 'maps everyX %s with value %i to an even gap and reports a note, because cron */n did not divide the period', + (unit, value, expected) => { + const result = cronToScheduleTrigger.migrate(cron({ mode: 'everyX', unit, value })); + + expect(intervals(result)).toEqual({ interval: [expected] }); + expect(result.notes).toHaveLength(1); + }, + ); + + it('reports one note for a Cron node with several uneven everyX trigger times', () => { + const { notes } = cronToScheduleTrigger.migrate( + cron( + { mode: 'everyX', unit: 'minutes', value: 7 }, + { mode: 'everyX', unit: 'hours', value: 5 }, + ), + ); + + expect(notes).toHaveLength(1); + }); + + it.each([ + ['minutes', 30], + ['hours', 12], + ])( + 'reports no note for everyX %s with value %i, because cron */n divides the period', + (unit, value) => { + const { notes } = cronToScheduleTrigger.migrate(cron({ mode: 'everyX', unit, value })); + + expect(notes).toBeUndefined(); + }, + ); + + describe('minute of everyX hours', () => { + const everyThreeHours = { mode: 'everyX', unit: 'hours', value: 3 }; + const minuteOf = (node: ReturnType, index = 0) => { + const { interval } = cronToScheduleTrigger.migrate(node).node.parameters.rule as { + interval: Array<{ triggerAtMinute: number }>; + }; + return interval[index].triggerAtMinute; + }; + + it('is a whole minute from 0 to 59', () => { + const minute = minuteOf(cron(everyThreeHours)); + + expect(Number.isInteger(minute)).toBe(true); + expect(minute).toBeGreaterThanOrEqual(0); + expect(minute).toBeLessThanOrEqual(59); + }); + + it('stays the same when the same node migrates again', () => { + expect(minuteOf(cron(everyThreeHours))).toBe(minuteOf(cron(everyThreeHours))); + }); + + it('differs between nodes, so migrated workflows do not start together', () => { + const minutes = new Set( + Array.from({ length: 30 }, (_, i) => + minuteOf( + createNode(`Cron ${i}`, 'n8n-nodes-base.cron', { + triggerTimes: { item: [everyThreeHours] }, + }), + ), + ), + ); + + expect(minutes.size).toBeGreaterThan(10); + }); + + it('differs between the rules of one node, as Cron picked a minute for each', () => { + const node = cron(everyThreeHours, { ...everyThreeHours, value: 5 }); + + expect(minuteOf(node, 0)).not.toBe(minuteOf(node, 1)); + }); + + it('gives two identical everyX hours trigger times different minutes', () => { + const node = cron(everyThreeHours, everyThreeHours); + + expect(minuteOf(node, 0)).not.toBe(minuteOf(node, 1)); + }); + + it('does not add a minute to everyX minutes', () => { + const { node } = cronToScheduleTrigger.migrate( + cron({ mode: 'everyX', unit: 'minutes', value: 15 }), + ); + + expect(node.parameters.rule).toEqual({ + interval: [{ field: 'minutes', minutesInterval: 15 }], + }); + }); + }); + + it('uses the Cron defaults for values that the saved workflow omits', () => { + const { node } = cronToScheduleTrigger.migrate(cron({})); + + // Defaults: mode everyDay, hour 14, minute 0. + expect(node.parameters.rule).toEqual({ + interval: [{ field: 'days', daysInterval: 1, triggerAtHour: 14, triggerAtMinute: 0 }], + }); + }); + + it('maps each trigger time to its own rule, in order', () => { + const { node } = cronToScheduleTrigger.migrate( + cron({ mode: 'everyMinute' }, { mode: 'custom', cronExpression: '0 * * * * *' }), + ); + + expect(node.parameters.rule).toEqual({ + interval: [ + { field: 'minutes', minutesInterval: 1 }, + { field: 'cronExpression', expression: '0 * * * * *' }, + ], + }); + }); + + describe('trigger times that fire at the same moment', () => { + // Schedule Trigger gives one execution for them. We accept this change. + it('migrates two identical trigger times to two rules', () => { + const { node } = cronToScheduleTrigger.migrate( + cron({ mode: 'everyMinute' }, { mode: 'everyMinute' }), + ); + + expect(node.parameters.rule).toEqual({ + interval: [ + { field: 'minutes', minutesInterval: 1 }, + { field: 'minutes', minutesInterval: 1 }, + ], + }); + }); + + it('migrates trigger times that become equal after defaults apply', () => { + const { node } = cronToScheduleTrigger.migrate( + cron({}, { mode: 'everyDay', hour: 14, minute: 0 }), + ); + + expect(node.parameters.rule).toEqual({ + interval: [ + { field: 'days', daysInterval: 1, triggerAtHour: 14, triggerAtMinute: 0 }, + { field: 'days', daysInterval: 1, triggerAtHour: 14, triggerAtMinute: 0 }, + ], + }); + }); + + it('migrates overlapping trigger times and reports no note', () => { + const result = cronToScheduleTrigger.migrate( + cron({ mode: 'everyX', unit: 'minutes', value: 5 }, { mode: 'everyHour', minute: 0 }), + ); + + expect(intervals(result)).toEqual({ + interval: [ + { field: 'minutes', minutesInterval: 5 }, + { field: 'hours', hoursInterval: 1, triggerAtMinute: 0 }, + ], + }); + expect(result.notes).toBeUndefined(); + }); + }); + + it.each([ + ['no trigger times', createNode('Cron', 'n8n-nodes-base.cron', {})], + ['an empty list of trigger times', cron()], + ['an expression for the mode', cron({ mode: '={{ $json.mode }}' })], + ['an expression for the hour', cron({ mode: 'everyDay', hour: '={{ 1 }}' })], + ['an hour out of range', cron({ mode: 'everyDay', hour: 24 })], + [ + 'every 60 minutes, which Schedule Trigger rejects', + cron({ mode: 'everyX', unit: 'minutes', value: 60 }), + ], + [ + 'every 24 hours, which Schedule Trigger rejects', + cron({ mode: 'everyX', unit: 'hours', value: 24 }), + ], + ['every 0 hours', cron({ mode: 'everyX', unit: 'hours', value: 0 })], + ['an unknown everyX unit', cron({ mode: 'everyX', unit: 'days', value: 2 })], + ['an unknown mode', cron({ mode: 'everyYear' })], + ])('refuses %s', (_name, node) => { + expect(() => cronToScheduleTrigger.migrate(node)).toThrow(); + }); +}); diff --git a/packages/cli/src/modules/breaking-changes/migrations/node-removals/__tests__/workflow-trigger-to-n8n-trigger.migration.test.ts b/packages/cli/src/modules/breaking-changes/migrations/node-removals/__tests__/workflow-trigger-to-n8n-trigger.migration.test.ts new file mode 100644 index 00000000000..d4cd9db11df --- /dev/null +++ b/packages/cli/src/modules/breaking-changes/migrations/node-removals/__tests__/workflow-trigger-to-n8n-trigger.migration.test.ts @@ -0,0 +1,42 @@ +import { createNode } from '../../../__tests__/test-helpers'; +import { workflowTriggerToN8nTrigger } from '../workflow-trigger-to-n8n-trigger.migration'; + +const trigger = (parameters: Record) => + createNode('Trigger', 'n8n-nodes-base.workflowTrigger', parameters); + +describe('workflowTriggerToN8nTrigger migration', () => { + it('is keyed by the Workflow Trigger rule id', () => { + expect(workflowTriggerToN8nTrigger.ruleId).toBe('workflow-trigger-removed-v3'); + }); + + it('keeps the update event with no note', () => { + const result = workflowTriggerToN8nTrigger.migrate(trigger({ events: ['update'] })); + + expect(result.node).toEqual({ + type: 'n8n-nodes-base.n8nTrigger', + typeVersion: 1, + parameters: { events: ['update'] }, + }); + expect(result.notes).toBeUndefined(); + }); + + it('keeps the activate event and reports the new event text', () => { + const result = workflowTriggerToN8nTrigger.migrate(trigger({ events: ['activate', 'update'] })); + + expect(result.node.parameters).toEqual({ events: ['activate', 'update'] }); + expect(result.notes).toEqual([expect.stringContaining('Workflow published')]); + }); + + it('keeps an empty event list', () => { + expect(workflowTriggerToN8nTrigger.migrate(trigger({})).node.parameters).toEqual({ + events: [], + }); + }); + + it.each([['={{ $json.events }}'], ['activate'], [['init']]])( + 'refuses events that it cannot check (%j)', + (events) => { + expect(() => workflowTriggerToN8nTrigger.migrate(trigger({ events }))).toThrow('Events'); + }, + ); +}); diff --git a/packages/cli/src/modules/breaking-changes/migrations/node-removals/ai-transform-to-code.migration.ts b/packages/cli/src/modules/breaking-changes/migrations/node-removals/ai-transform-to-code.migration.ts new file mode 100644 index 00000000000..68273351f8a --- /dev/null +++ b/packages/cli/src/modules/breaking-changes/migrations/node-removals/ai-transform-to-code.migration.ts @@ -0,0 +1,41 @@ +import type { NodeMigration } from '../node-migration'; + +/** + * AI Transform to Code. + * + * Does: + * - Target: `code`, version 2, `mode` = `runOnceForAllItems`, `language` = `javaScript`. + * Both nodes run the code in the same `JsTaskRunnerSandbox` and store it in `jsCode`. + * - Keeps: `jsCode`. + * - Drops: `instructions` and `codeGeneratedForPrompt`. They only help to write the + * code and have no effect at run time. + * + * Refuses when: + * - `jsCode` is empty: the node has no generated code to carry over. + * + * Accepted changes: + * - The prompt text is lost. It has no effect at run time. + */ +export const aiTransformToCode: NodeMigration = { + ruleId: 'ai-transform-deprecated', + migrate: (node) => { + const jsCode = node.parameters.jsCode; + if (!jsCode) { + throw new Error( + 'This AI Transform node never generated any code, so there is nothing to carry over. Replace it with a Code node and write the code for its instructions by hand.', + ); + } + + return { + node: { + type: 'n8n-nodes-base.code', + typeVersion: 2, + parameters: { + mode: 'runOnceForAllItems', + language: 'javaScript', + jsCode, + }, + }, + }; + }, +}; diff --git a/packages/cli/src/modules/breaking-changes/migrations/node-removals/document-loaders.migration.ts b/packages/cli/src/modules/breaking-changes/migrations/node-removals/document-loaders.migration.ts new file mode 100644 index 00000000000..f9a8c84c5ee --- /dev/null +++ b/packages/cli/src/modules/breaking-changes/migrations/node-removals/document-loaders.migration.ts @@ -0,0 +1,130 @@ +import { NodeConnectionTypes } from 'n8n-workflow'; +import type { IConnections, INode, INodeParameters } from 'n8n-workflow'; + +import type { NodeMigration, WorkflowMigration } from '../node-migration'; +import { replaceAffectedNodes } from '../node-migration'; +import { pickDefined, readOptions, readString } from '../parameter-readers'; + +const DEFAULT_DATA_LOADER_TYPE = '@n8n/n8n-nodes-langchain.documentDefaultDataLoader'; +const DEFAULT_DATA_LOADER_VERSION = 1.1; + +// Both old loaders move their settings into the `options` collection of the new node. +// The loader reads each one with a fallback that differs from the old default, so the +// old default has to be written out. +function binaryLoaderOptions(node: INode): INodeParameters { + const { parameters } = node; + const loader = readString(parameters, 'loader', 'jsonLoader', 'Loader Type'); + const metadata = pickDefined(readOptions(parameters), ['metadata']); + + switch (loader) { + case 'pdfLoader': + return { splitPages: parameters.splitPages ?? true, ...metadata }; + case 'csvLoader': + return { + column: parameters.column ?? '', + separator: parameters.separator ?? ',', + ...metadata, + }; + case 'jsonLoader': + return { pointers: parameters.pointers ?? '', ...metadata }; + default: + return metadata; + } +} + +/** + * Binary Input Loader to Default Data Loader (binary). + * + * Does: + * - Target: `documentDefaultDataLoader`, version 1.1, `dataType` = `binary`, + * `binaryMode` = `allInputData` (the old node always loads all input binary data) and + * `textSplittingMode` = `custom`. The old node requires a text splitter, and `simple` + * would chunk the text in a different way. + * - Keeps: `binaryDataKey`, `options.metadata`, and the settings of the selected loader + * (`splitPages`, `column`, `separator`, `pointers`). They move into `options`. + * - Writes: `loader` explicitly, because the old default is `jsonLoader` and the new + * default is `auto`. It also writes the old defaults of the loader settings, because + * the new loader reads them with other fallbacks. + * + * Refuses when: + * - `loader` is an expression: the migration must know the loader to pick its settings. + * - `options` is not an object. + * + * Accepted changes: + * - None. + */ +export const binaryInputLoaderToDefaultDataLoader: NodeMigration = { + ruleId: 'binary-input-loader-removed-v3', + migrate: (node) => ({ + node: { + type: DEFAULT_DATA_LOADER_TYPE, + typeVersion: DEFAULT_DATA_LOADER_VERSION, + parameters: { + dataType: 'binary', + binaryMode: 'allInputData', + loader: readString(node.parameters, 'loader', 'jsonLoader', 'Loader Type'), + ...pickDefined(node.parameters, ['binaryDataKey']), + textSplittingMode: 'custom', + options: binaryLoaderOptions(node), + }, + }, + }), +}; + +/** Names of the nodes that have a text splitter connected. */ +function nodesWithTextSplitter(connections: IConnections): Set { + const names = new Set(); + for (const byType of Object.values(connections)) { + for (const group of byType[NodeConnectionTypes.AiTextSplitter] ?? []) { + for (const connection of group ?? []) names.add(connection.node); + } + } + return names; +} + +/** + * JSON Input Loader to Default Data Loader (JSON). + * + * Does: + * - Target: `documentDefaultDataLoader`, version 1.1, `dataType` = `json`, + * `jsonMode` = `allInputData` and `textSplittingMode` = `custom`. + * - Keeps: `pointers` and `options.metadata`. They move into `options`. + * - Needs the connections, so it is a workflow migration. + * + * Refuses when: + * - No text splitter is connected: the old splitter input is optional, but the new + * node always splits the text. `simple` would chunk it and `custom` needs a splitter. + * - `options` is not an object. + * + * Accepted changes: + * - None. + */ +export const jsonInputLoaderToDefaultDataLoader: WorkflowMigration = { + ruleId: 'json-input-loader-removed-v3', + migrateWorkflow: ({ nodes, connections, affectedNodeIds }) => { + const withSplitter = nodesWithTextSplitter(connections); + + const migrated = replaceAffectedNodes(nodes, affectedNodeIds, (node) => { + if (!withSplitter.has(node.name)) { + throw new Error( + 'This JSON Input Loader has no text splitter. Default Data Loader always splits the text, so the node cannot be migrated automatically.', + ); + } + + const options = pickDefined(readOptions(node.parameters), ['metadata']); + return { + ...node, + type: DEFAULT_DATA_LOADER_TYPE, + typeVersion: DEFAULT_DATA_LOADER_VERSION, + parameters: { + dataType: 'json', + jsonMode: 'allInputData', + textSplittingMode: 'custom', + options: { ...pickDefined(node.parameters, ['pointers']), ...options }, + }, + } satisfies INode; + }); + + return { ...migrated, connections }; + }, +}; diff --git a/packages/cli/src/modules/breaking-changes/migrations/node-removals/html-extract-to-html.migration.ts b/packages/cli/src/modules/breaking-changes/migrations/node-removals/html-extract-to-html.migration.ts new file mode 100644 index 00000000000..b922803a957 --- /dev/null +++ b/packages/cli/src/modules/breaking-changes/migrations/node-removals/html-extract-to-html.migration.ts @@ -0,0 +1,72 @@ +import type { NodeMigration } from '../node-migration'; +import { asParameters, isExpression, pickDefined } from '../parameter-readers'; + +const EMPTY_TEXT_NOTE = + 'A value that returns "Text" now has no value, not an empty text, when its selector finds nothing or the element has no text. Check the nodes that read these values.'; + +// The default return value is `text`, and saved workflows omit defaults. An expression +// can also give `text`. +function mayReturnText(extractionValues: unknown): boolean { + const values = asParameters(extractionValues)?.values; + if (!Array.isArray(values)) return false; + + return values.some((value) => { + const { returnValue = 'text' } = asParameters(value) ?? {}; + return returnValue === 'text' || isExpression(returnValue); + }); +} + +/** + * HTML Extract to HTML (Extract HTML Content). + * + * Does: + * - Target: `html`, version 1.1, `operation` = `extractHtmlContent`. Version 1 reads + * the data property without dot notation, and 1.2 changes text extraction to + * `html-to-text`. Only 1.1 matches the old node. + * - Keeps: `sourceData`, `dataPropertyName` and `extractionValues`. + * - Writes: `options.trimValues` explicitly, because the old node trims unless the value + * is `false` and the new node trims only when it is `true`. It writes `cleanUpText` = + * `false`, because the old node has no such step. With no `extractionValues`, it writes + * an empty value, so the node fails as before. + * + * Refuses when: + * - `options` is not an object. + * - `options.trimValues` is an expression: a falsy result that is not `false` (for example + * `undefined` or `0`) trims in the old node and does not trim in the new node. + * + * Accepted changes: + * - With the text return value, a selector that matches nothing, or an element with no + * text, gives no value instead of an empty string. The ticket accepts this. The + * migration reports a note when a value can use the text return value. The note also + * turns off the one-click republish. + */ +export const htmlExtractToHtml: NodeMigration = { + ruleId: 'html-extract-removed-v3', + migrate: (node) => { + const options = + node.parameters.options === undefined ? {} : asParameters(node.parameters.options); + if (!options) { + throw new Error('The options of this node are not in a supported format.'); + } + if (isExpression(options.trimValues)) { + throw new Error( + '"Trim Values" is an expression, so the node cannot be migrated automatically.', + ); + } + + return { + node: { + type: 'n8n-nodes-base.html', + typeVersion: 1.1, + parameters: { + operation: 'extractHtmlContent', + ...pickDefined(node.parameters, ['sourceData', 'dataPropertyName']), + // With no entries the old node throws. An empty value keeps that. + extractionValues: node.parameters.extractionValues ?? {}, + options: { trimValues: options.trimValues ?? true, cleanUpText: false }, + }, + }, + notes: mayReturnText(node.parameters.extractionValues) ? [EMPTY_TEXT_NOTE] : undefined, + }; + }, +}; diff --git a/packages/cli/src/modules/breaking-changes/migrations/node-removals/ical-to-convert-to-file.migration.ts b/packages/cli/src/modules/breaking-changes/migrations/node-removals/ical-to-convert-to-file.migration.ts new file mode 100644 index 00000000000..f896535de69 --- /dev/null +++ b/packages/cli/src/modules/breaking-changes/migrations/node-removals/ical-to-convert-to-file.migration.ts @@ -0,0 +1,31 @@ +import type { NodeMigration } from '../node-migration'; + +/** + * iCalendar to Convert to File (Convert to ICS). + * + * Does: + * - Target: `convertToFile`, version 1.1, `operation` = `iCal`. + * - Keeps: every other parameter with the same name and shape. Convert to File reuses + * the iCalendar `createEvent` description and executor. + * - Changes: only `operation`, from `createEventFile` (the only old operation) to `iCal`. + * + * Refuses when: + * - Never refuses. + * + * Accepted changes: + * - None. + */ +export const icalToConvertToFile: NodeMigration = { + ruleId: 'i-calendar-removed-v3', + migrate: (node) => { + const { operation: _operation, ...parameters } = node.parameters; + + return { + node: { + type: 'n8n-nodes-base.convertToFile', + typeVersion: 1.1, + parameters: { ...parameters, operation: 'iCal' }, + }, + }; + }, +}; diff --git a/packages/cli/src/modules/breaking-changes/migrations/node-removals/index.ts b/packages/cli/src/modules/breaking-changes/migrations/node-removals/index.ts new file mode 100644 index 00000000000..c7fd3374c2d --- /dev/null +++ b/packages/cli/src/modules/breaking-changes/migrations/node-removals/index.ts @@ -0,0 +1,40 @@ +import { aiTransformToCode } from './ai-transform-to-code.migration'; +import { + binaryInputLoaderToDefaultDataLoader, + jsonInputLoaderToDefaultDataLoader, +} from './document-loaders.migration'; +import { htmlExtractToHtml } from './html-extract-to-html.migration'; +import { icalToConvertToFile } from './ical-to-convert-to-file.migration'; +import { itemListsToTransformNodes } from './item-lists.migration'; +import { readPdfToExtractFromFile } from './read-pdf-to-extract-from-file.migration'; +import { cronToScheduleTrigger } from './schedule-trigger.migration'; +import { + inMemoryInsertToVectorStore, + inMemoryLoadToVectorStore, + pineconeInsertToVectorStore, + pineconeLoadToVectorStore, + supabaseInsertToVectorStore, + supabaseLoadToVectorStore, +} from './vector-stores.migration'; +import { workflowTriggerToN8nTrigger } from './workflow-trigger-to-n8n-trigger.migration'; +import { writeBinaryFileToReadWriteFile } from './write-binary-file-to-read-write-file.migration'; +import type { Migration } from '../node-migration'; + +export const nodeRemovalMigrations: Migration[] = [ + aiTransformToCode, + binaryInputLoaderToDefaultDataLoader, + cronToScheduleTrigger, + htmlExtractToHtml, + icalToConvertToFile, + inMemoryInsertToVectorStore, + inMemoryLoadToVectorStore, + itemListsToTransformNodes, + jsonInputLoaderToDefaultDataLoader, + pineconeInsertToVectorStore, + pineconeLoadToVectorStore, + readPdfToExtractFromFile, + supabaseInsertToVectorStore, + supabaseLoadToVectorStore, + workflowTriggerToN8nTrigger, + writeBinaryFileToReadWriteFile, +]; diff --git a/packages/cli/src/modules/breaking-changes/migrations/node-removals/item-lists-checks.ts b/packages/cli/src/modules/breaking-changes/migrations/node-removals/item-lists-checks.ts new file mode 100644 index 00000000000..1d999ebf12c --- /dev/null +++ b/packages/cli/src/modules/breaking-changes/migrations/node-removals/item-lists-checks.ts @@ -0,0 +1,68 @@ +import type { INode } from 'n8n-workflow'; + +import { asParameters, isExpression } from '../parameter-readers'; + +/* + * Checks that every Item Lists version shares. Each one throws when the value has no + * exact equivalent in the new node. + */ + +// `includeEmpty` is hidden for `count` and `countUnique` in Item Lists, so it has no effect there. +// Summarize applies it, so a stored `true` would change the result. +export function assertIncludeEmptyIsInert(node: INode) { + const { fieldsToSummarize } = node.parameters; + const entries = asParameters(fieldsToSummarize)?.values; + if (!Array.isArray(entries)) return; + + for (const entry of entries.map(asParameters)) { + if (!entry) continue; + // `aggregation` defaults to `count`, so saved workflows often omit it. + const aggregation = entry.aggregation ?? 'count'; + const ignoredByItemLists = + aggregation === 'count' || aggregation === 'countUnique' || isExpression(aggregation); + if (!ignoredByItemLists) continue; + + if (entry.includeEmpty !== undefined && entry.includeEmpty !== false) { + throw new Error( + '"Include Empty Values" is turned on for a field. The old node ignored this setting for Count and Count Unique, but the new node uses it, so your results could change. Turn it off or replace this node by hand.', + ); + } + } +} + +// Item Lists groups by split values in a plain object. Every key becomes a string, keys +// like `1` and `"1"` merge, and numeric keys sort first. Summarize 1.1 groups in a `Map`, +// so values keep their type and groups keep their order. The output would change. +export function assertNoSplitBy(node: INode) { + const { fieldsToSplitBy } = node.parameters; + if (fieldsToSplitBy === undefined) return; + if (typeof fieldsToSplitBy !== 'string' || isExpression(fieldsToSplitBy)) { + throw new Error( + '"Fields to Split By" is an expression or has an unsupported value. Replace this node by hand.', + ); + } + if (fieldsToSplitBy.split(',').some((field) => field.trim() !== '')) { + throw new Error( + '"Fields to Split By" is set. The new Summarize node can return the groups in a different order, and numbers stay numbers where the old node returned text. Replace this node by hand.', + ); + } +} + +// Item Lists keeps an empty entry of the comma-separated list. Split Out drops it. That +// changes how many fields are split and can turn a result into an error. +export function assertNoEmptyFieldToSplitOut(node: INode) { + const { fieldToSplitOut = '' } = node.parameters; + if (typeof fieldToSplitOut !== 'string') { + throw new Error( + '"Field to Split Out" could not be read. Open the node, check this field and migrate again.', + ); + } + // An expression can only be checked when it runs. + if (isExpression(fieldToSplitOut)) return; + + if (fieldToSplitOut.split(',').some((field) => field.trim() === '')) { + throw new Error( + '"Field to Split Out" is empty or has an empty name in the list, for example "a,,b". The new node ignores empty names, so the result could change. Remove the empty name or replace this node by hand.', + ); + } +} diff --git a/packages/cli/src/modules/breaking-changes/migrations/node-removals/item-lists-legacy.ts b/packages/cli/src/modules/breaking-changes/migrations/node-removals/item-lists-legacy.ts new file mode 100644 index 00000000000..f4cd4bc653f --- /dev/null +++ b/packages/cli/src/modules/breaking-changes/migrations/node-removals/item-lists-legacy.ts @@ -0,0 +1,390 @@ +import type { INode, INodeParameters } from 'n8n-workflow'; + +import { + assertIncludeEmptyIsInert, + assertNoEmptyFieldToSplitOut, + assertNoSplitBy, +} from './item-lists-checks'; +import { asParameters, isExpression, pickDefined, readString } from '../parameter-readers'; + +/* + * Item Lists 1 and 2 (`typeVersion` 1, 2, 2.1 and 2.2). Limit and Sort have the same shape + * as in version 3, so they need no code here. The other operations differ in two ways: + * - They store field lists as a collection (`{ fields: [{ fieldName }] }`). The new nodes + * use one comma-separated string. + * - Some behavior differs from version 3 (see each function). + * Each function returns the new parameters, or throws when the node has no exact equivalent. + */ + +export interface LegacyResult { + /** The version of the new node. The default is the version of the target. */ + typeVersion?: number; + parameters: INodeParameters; + /** Behavior changes that the user should check. A note turns off the one-click republish. */ + notes?: string[]; +} + +// A note turns off the one-click republish, so it only fits where the old node can throw. +const MISSING_FIELD_NOTE = + 'This node used to stop with an error when a field was missing in all items. The new node continues. Check the workflow if it relies on that error.'; + +// Item Lists 2.1 and later never throw. Before that, Keep Missing off (or an expression) can. +function canStopForMissingField(node: INode, options: INodeParameters): boolean { + return node.typeVersion < 2.1 && options.keepMissing !== true; +} + +// Split Out throws for a missing field before 2.1, and for a value it cannot split before 2.2. +function splitOutNote(typeVersion: number): string[] | undefined { + if (typeVersion >= 2.2) return undefined; + + const cause = + typeVersion < 2.1 + ? 'the field was missing, or when its value was not a list or an object' + : 'the value of the field was not a list or an object'; + return [ + `This node used to stop with an error when ${cause}. The new node continues. Check the workflow if it relies on that error.`, + ]; +} + +const unreadable = (label: string) => + new Error(`"${label}" could not be read. Open the node, check this field and migrate again.`); + +function readChoice( + parameters: INodeParameters, + key: string, + fallback: string, + label: string, + allowed: string[], +): string { + const value = readString(parameters, key, fallback, label); + if (!allowed.includes(value)) { + throw new Error(`"${label}" has an unsupported value. Replace this node by hand.`); + } + return value; +} + +/** Reads the `options` of the node and keeps only the listed keys, which the new node knows. */ +function readOptions(node: INode, keys: string[]): INodeParameters { + const { options } = node.parameters; + if (options === undefined) return {}; + + const parsed = asParameters(options); + if (!parsed) throw new Error('The options of this node are not in a supported format.'); + return pickDefined(parsed, keys); +} + +const withOptions = (options: INodeParameters): INodeParameters => + Object.keys(options).length > 0 ? { options } : {}; + +/** + * Reads a field list collection and returns the names. + * The new nodes split a string on commas, trim each name and drop empty names. So a name + * is only safe when none of that changes it. With `trim` set, the old node also trims the + * names, so surrounding spaces and empty names are fine. + */ +function readFieldNames(value: unknown, label: string, { trim = false } = {}): string[] { + if (value === undefined) return []; + + const list = asParameters(value)?.fields; + if (list === undefined) return []; + if (!Array.isArray(list)) throw unreadable(label); + + const names: string[] = []; + for (const entry of list) { + const name = asParameters(entry)?.fieldName; + // A saved workflow omits the default name, which is empty. + if (name === undefined) { + throw new Error( + `"${label}" has an empty field name. Remove it or replace this node by hand.`, + ); + } + if (typeof name !== 'string') throw unreadable(label); + if (isExpression(name)) { + throw new Error( + `"${label}" has a field name that is an expression. Replace this node by hand.`, + ); + } + if (name.includes(',')) { + throw new Error( + `"${label}" has the field name "${name}" with a comma. The new node would split it into two names. Replace this node by hand.`, + ); + } + + if (trim) { + if (name.trim() !== '') names.push(name.trim()); + continue; + } + if (name === '') { + throw new Error( + `"${label}" has an empty field name. Remove it or replace this node by hand.`, + ); + } + if (name !== name.trim()) { + throw new Error( + `"${label}" has the field name "${name}" with a space at the start or end. The new node removes it, so the name would change. Replace this node by hand.`, + ); + } + names.push(name); + } + return names; +} + +/** Version 1 reads a name as one literal value. The new node splits it and trims it. */ +function assertPlainName(value: string, label: string, { allowEmpty = false } = {}) { + if (isExpression(value)) { + throw new Error( + `"${label}" is an expression, and the migration cannot check it. Replace this node by hand.`, + ); + } + if (value.includes(',') || value !== value.trim() || (value === '' && !allowEmpty)) { + throw new Error( + `"${label}" is empty or has a comma or a space at the start or end. The old version of the node reads it as one name, so the result could change. Replace this node by hand.`, + ); + } +} + +/** + * Concatenate Items (`aggregateItems`) to Aggregate. + * Individual fields copy as they are. The all-data mode needs the field lists as strings. + * Versions 1 and 2 throw for a missing field and the new node adds a hint, which is accepted. + */ +export function legacyAggregate(node: INode): LegacyResult { + const { parameters } = node; + const aggregate = readChoice(parameters, 'aggregate', 'aggregateIndividualFields', 'Aggregate', [ + 'aggregateIndividualFields', + 'aggregateAllItemData', + ]); + + if (aggregate === 'aggregateIndividualFields') { + const options = readOptions(node, ['disableDotNotation', 'mergeLists', 'keepMissing']); + return { + parameters: { + ...pickDefined(parameters, ['aggregate', 'fieldsToAggregate']), + ...withOptions(options), + }, + notes: canStopForMissingField(node, options) ? [MISSING_FIELD_NOTE] : undefined, + }; + } + + const include = readChoice(parameters, 'include', 'allFields', 'Include', [ + 'allFields', + 'specifiedFields', + 'allFieldsExcept', + ]); + const result = pickDefined(parameters, ['aggregate', 'destinationFieldName', 'include']); + + if (include === 'allFieldsExcept') { + const names = readFieldNames(parameters.fieldsToExclude, 'Fields to Exclude'); + if (names.length > 0) result.fieldsToExclude = names.join(', '); + } + if (include === 'specifiedFields') { + const names = readFieldNames(parameters.fieldsToInclude, 'Fields to Include'); + if (names.length > 0) result.fieldsToInclude = names.join(', '); + } + return { parameters: result }; +} + +/** + * Remove Duplicates to Remove Duplicates 1. The old code is the same in every version. + * Version 1 of the new node does not skip `null`, as the old node did not. + */ +export function legacyRemoveDuplicates(node: INode): LegacyResult { + const { parameters } = node; + const compare = readChoice(parameters, 'compare', 'allFields', 'Compare', [ + 'allFields', + 'allFieldsExcept', + 'selectedFields', + ]); + const result = pickDefined(parameters, ['compare']); + // The field lists and the options are hidden when all fields are compared. + if (compare === 'allFields') return { parameters: result }; + + const options = readOptions(node, ['disableDotNotation', 'removeOtherFields']); + if (Object.values(options).some((value) => typeof value !== 'boolean')) { + throw new Error( + 'An option of this node is an expression or has an unsupported value. Replace this node by hand.', + ); + } + + if (compare === 'allFieldsExcept') { + // The old node compares these names as they are. The new node trims them. + const names = readFieldNames(parameters.fieldsToExclude, 'Fields to Exclude'); + if (names.length > 0) result.fieldsToExclude = names.join(', '); + } else { + // The old node trims these names. An empty name throws there and is dropped here. + const names = readFieldNames(parameters.fieldsToCompare, 'Fields to Compare', { trim: true }); + if (names.length > 0) result.fieldsToCompare = names.join(', '); + } + return { parameters: { ...result, ...withOptions(options) } }; +} + +const INCLUDE_MODES = ['noOtherFields', 'allOtherFields', 'selectedOtherFields']; + +/** + * Split Out Items to Split Out 1. + * Versions 2 to 2.2 read the field as a comma-separated list, as the new node does. + * Version 1 reads it as one literal name, so it needs more checks. + * The new node removes a leading `$json.` and reads `$binary` as the binary data. + * Item Lists 1 and 2 do neither, so those names are refused. + */ +export function legacySplitOut(node: INode): LegacyResult { + const { parameters } = node; + const isVersion1 = node.typeVersion < 2; + + const fieldToSplitOut = parameters.fieldToSplitOut ?? ''; + if (typeof fieldToSplitOut !== 'string') throw unreadable('Field to Split Out'); + if (isVersion1) assertPlainName(fieldToSplitOut, 'Field to Split Out'); + else assertNoEmptyFieldToSplitOut(node); + + // An expression can only be checked when it runs. + if (!isExpression(fieldToSplitOut)) { + for (const name of fieldToSplitOut.split(',').map((entry) => entry.trim())) { + if (name.startsWith('$json.') || name === '$binary') { + throw new Error( + '"Field to Split Out" starts with "$json." or is "$binary". The new node reads these names in a special way, so the result could change. Replace this node by hand.', + ); + } + } + } + + const include = readChoice(parameters, 'include', 'noOtherFields', 'Include', INCLUDE_MODES); + const options = readOptions(node, ['disableDotNotation', 'destinationFieldName']); + const { disableDotNotation, destinationFieldName } = options; + + // The old node reads this option once and the new node reads it for each item. + if (disableDotNotation !== undefined && typeof disableDotNotation !== 'boolean') { + throw new Error( + '"Disable Dot Notation" is an expression. The old node reads it once and the new node reads it for each item, so the results could differ. Replace this node by hand.', + ); + } + if (destinationFieldName !== undefined && typeof destinationFieldName !== 'string') { + throw unreadable('Destination Field Name'); + } + if (isVersion1 && destinationFieldName !== undefined) { + assertPlainName(destinationFieldName, 'Destination Field Name', { allowEmpty: true }); + } + + const result = pickDefined(parameters, ['fieldToSplitOut', 'include']); + + if (include === 'selectedOtherFields') { + const names = readFieldNames(parameters.fieldsToInclude, 'Fields to Include'); + if (names.length > 0) result.fieldsToInclude = names.join(','); + + // Version 1 lets one value win when a name matches the split field or its destination. + // The new node always writes the original value. + if ( + isVersion1 && + names.some((name) => name === fieldToSplitOut || name === destinationFieldName) + ) { + throw new Error( + '"Fields to Include" has the same name as the field to split out or its destination field. The new node orders these in a different way. Replace this node by hand.', + ); + } + } + + // Version 1 always removes the field with a dot path. The new node removes the literal name. + if ( + isVersion1 && + include === 'allOtherFields' && + disableDotNotation === true && + /[.[]/.test(fieldToSplitOut) + ) { + throw new Error( + '"Field to Split Out" has a dot or a bracket while "Disable Dot Notation" is on. The new node removes this field in a different way. Replace this node by hand.', + ); + } + + return { + parameters: { ...result, ...withOptions(options) }, + notes: splitOutNote(node.typeVersion), + }; +} + +const SUMMARIZE_KEY_PREFIXES: Record = { + append: 'appended_', + average: 'average_', + concatenate: 'concatenated_', + count: 'count_', + countUnique: 'unique_count_', + sum: 'sum_', +}; + +// Same cleanup that Summarize and Item Lists 2 apply to the output names. +const normalizeKey = (key: string) => key.replace(/[\]["]/g, '').replace(/[ .]/g, '_'); + +/** + * Summarize to Summarize. + * Versions 1 and 2 throw when a field is missing in all items, as Summarize 1 does. + * Versions 2.1 and 2.2 do not throw, as Summarize 1.1 does not. + * The checks for a split and for Include Empty are the same as for version 3. + */ +export function legacySummarize(node: INode): LegacyResult { + assertNoSplitBy(node); + assertIncludeEmptyIsInert(node); + + const isVersion1 = node.typeVersion < 2; + const entries = asParameters(node.parameters.fieldsToSummarize)?.values; + const normalizedToRaw = new Map(); + + for (const entry of Array.isArray(entries) ? entries.map(asParameters) : []) { + const aggregation = entry?.aggregation ?? 'count'; + if (typeof aggregation !== 'string' || isExpression(aggregation)) { + throw new Error( + 'A field to summarize has an aggregation that is an expression. Replace this node by hand.', + ); + } + // Item Lists 1 and 2 compare only numbers for Minimum and Maximum, and can return + // Infinity. The new node also compares text and dates, and returns null. + if (aggregation === 'min' || aggregation === 'max') { + throw new Error( + 'A field uses Minimum or Maximum. The old node compared only numbers, and the new node also compares text and dates, so the results could change. Replace this node by hand.', + ); + } + const prefix = SUMMARIZE_KEY_PREFIXES[aggregation]; + if (prefix === undefined) { + throw new Error( + 'A field to summarize has an unsupported aggregation. Replace this node by hand.', + ); + } + + const field = entry?.field ?? ''; + if (typeof field !== 'string') throw unreadable('Field'); + // Version 1 does not know the field at this point, so it cannot compare the names. + if (isExpression(field)) { + if (isVersion1) { + throw new Error('A field to summarize is an expression. Replace this node by hand.'); + } + continue; + } + + const raw = `${prefix}${field}`; + const normalized = normalizeKey(raw); + + // Version 1 keeps the name as it is. The new node cleans it up. + if (isVersion1 && normalized !== raw) { + throw new Error( + `The field "${field}" has a bracket, a quote, a dot or a space. The old version of the node keeps it in the output name and the new node changes it, so the output names would change. Replace this node by hand.`, + ); + } + + // Version 2 renames the keys one after the other. When two names collide, the order + // of the values can differ from the new node. + const earlier = normalizedToRaw.get(normalized); + if (earlier !== undefined && earlier !== raw) { + throw new Error( + 'Two fields to summarize give the same output name after the new node cleans up the names. Replace this node by hand.', + ); + } + normalizedToRaw.set(normalized, raw); + } + + return { + typeVersion: node.typeVersion < 2.1 ? 1 : 1.1, + parameters: { + ...pickDefined(node.parameters, ['fieldsToSummarize']), + ...withOptions( + readOptions(node, ['disableDotNotation', 'outputFormat', 'skipEmptySplitFields']), + ), + }, + }; +} diff --git a/packages/cli/src/modules/breaking-changes/migrations/node-removals/item-lists.migration.ts b/packages/cli/src/modules/breaking-changes/migrations/node-removals/item-lists.migration.ts new file mode 100644 index 00000000000..55416cfe7a7 --- /dev/null +++ b/packages/cli/src/modules/breaking-changes/migrations/node-removals/item-lists.migration.ts @@ -0,0 +1,170 @@ +import type { INode, INodeParameters } from 'n8n-workflow'; + +import { + assertIncludeEmptyIsInert, + assertNoEmptyFieldToSplitOut, + assertNoSplitBy, +} from './item-lists-checks'; +import type { LegacyResult } from './item-lists-legacy'; +import { + legacyAggregate, + legacyRemoveDuplicates, + legacySplitOut, + legacySummarize, +} from './item-lists-legacy'; +import type { NodeMigration } from '../node-migration'; +import { pickDefined, readString } from '../parameter-readers'; + +type Target = { + type: string; + // The version of the new node for Item Lists 3 and 3.1. + typeVersion: number; + // Parameters that the old operation owns in Item Lists 3 and 3.1. + parameters: string[]; + // Refuses an Item Lists 3 or 3.1 node that this operation cannot carry over exactly. + check?: (node: INode) => void; + // Migrates an Item Lists 1 or 2 node. These versions store field lists as collections + // and the new nodes use one string, so they need their own code. + legacy: (node: INode) => LegacyResult; +}; + +const TRANSFORM_NODE = (name: string) => `n8n-nodes-base.${name}`; + +// Limit and Sort have the same shape in every Item Lists version. +const copyParameters = + (...keys: string[]) => + (node: INode): LegacyResult => ({ parameters: pickDefined(node.parameters, keys) }); +const TARGETS = new Map( + Object.entries({ + limit: { + type: TRANSFORM_NODE('limit'), + typeVersion: 1, + parameters: ['maxItems', 'keep'], + legacy: copyParameters('maxItems', 'keep'), + }, + sort: { + type: TRANSFORM_NODE('sort'), + typeVersion: 1, + parameters: ['type', 'sortFieldsUi', 'code', 'options'], + legacy: copyParameters('type', 'sortFieldsUi', 'code', 'options'), + }, + concatenateItems: { + type: TRANSFORM_NODE('aggregate'), + typeVersion: 1, + parameters: [ + 'aggregate', + 'fieldsToAggregate', + 'destinationFieldName', + 'include', + 'fieldsToExclude', + 'fieldsToInclude', + 'options', + ], + legacy: legacyAggregate, + }, + removeDuplicates: { + type: TRANSFORM_NODE('removeDuplicates'), + // Remove Duplicates 2 has two outputs. Version 1 has one, as Item Lists does. + typeVersion: 1, + parameters: ['compare', 'fieldsToExclude', 'fieldsToCompare', 'options'], + legacy: legacyRemoveDuplicates, + check: (node) => { + // Item Lists 3.1 sorts values of mixed types. Remove Duplicates 1 throws for them. + if (node.typeVersion >= 3.1) { + throw new Error( + 'The old node can compare values of different types, such as numbers and text, but the new node stops with an error. Replace this node by hand.', + ); + } + }, + }, + splitOutItems: { + type: TRANSFORM_NODE('splitOut'), + // Split Out 1.1 writes destination fields as nested paths. Version 1 does not. + typeVersion: 1, + parameters: ['fieldToSplitOut', 'include', 'fieldsToInclude', 'options'], + legacy: legacySplitOut, + check: assertNoEmptyFieldToSplitOut, + }, + summarize: { + type: TRANSFORM_NODE('summarize'), + // Item Lists 2.1 and later report a missing field as a hint. Summarize 1.1 does the same. + typeVersion: 1.1, + parameters: ['fieldsToSummarize', 'fieldsToSplitBy', 'options'], + legacy: legacySummarize, + check: (node) => { + assertNoSplitBy(node); + assertIncludeEmptyIsInert(node); + }, + }, + }), +); + +/** + * Item Lists to the single-purpose Transform nodes. + * + * Does: + * - Target: `operation` picks it (default `splitOutItems`). Limit 1, Sort 1, Aggregate 1, + * Remove Duplicates 1, Split Out 1 or Summarize. Each version is the one that matches + * the old behavior. Remove Duplicates 2 has two outputs, and Split Out 1.1 writes nested + * destination paths. Summarize 1.1 is the target for Item Lists 2.1 and later, and + * Summarize 1 for Item Lists 1 and 2, because Summarize 1 throws for a field that is + * missing in all items, as those versions do. + * - Item Lists 3 and 3.1: copies the parameters of the operation with the same names and + * shapes. Item Lists 3 was the template for the new nodes. + * - Item Lists 1 and 2: Limit and Sort copy in the same way. The other operations call + * the functions in `item-lists-legacy.ts`. They store field lists as a collection, and + * the new nodes use one comma-separated string. The function converts the lists. + * + * Refuses when: + * - The operation is unknown or is an expression. Item Lists 1 and 2 call Concatenate + * `aggregateItems`, and Item Lists 3 calls it `concatenateItems`. + * - Remove Duplicates, version 3.1: it compares values of mixed types and the new node + * throws. + * - Split Out: `fieldToSplitOut` is empty or has an empty name. The old node keeps it, + * the new node drops it, so the result changes. + * - Summarize: `fieldsToSplitBy` is set or is an expression. The new node keeps the type + * and the order of the split values, and the old node does not. + * - Summarize: "Include Empty Values" is on for Count or Count Unique (the old node + * ignores it, the new node uses it). A missing `aggregation` means Count. + * - Item Lists 1 and 2, field lists: a name is empty, has a comma, has a space at the + * start or end, or is an expression. The new nodes read a string and would change it. + * - Item Lists 1 and 2, other values that behave in a different way. See each function in + * `item-lists-legacy.ts`. Examples: Minimum and Maximum in Summarize, `$json.` and + * `$binary` in Split Out, and a mode or an option that is an expression. + * + * Accepted changes: + * - Split Out: an expression in `fieldToSplitOut` is not checked, because it can only be + * checked when it runs. + * - Split Out: the new node refuses reserved output names, such as `__proto__`. + * - Summarize 1.1 adds a hint for a missing field. Item Lists 2.1 and later already did + * not throw. + * - Item Lists 1 and 2: a failure becomes a success when the node did not find a field + * (Aggregate, Split Out) or got a value that is not an array or object (Split Out). + * The new nodes add a hint or wrap the value. The migration reports a note where the old + * node can throw. The note also turns off the one-click republish. + */ +export const itemListsToTransformNodes: NodeMigration = { + ruleId: 'item-lists-removed-v3', + migrate: (node) => { + const operation = readString(node.parameters, 'operation', 'splitOutItems', 'Operation'); + const isLegacy = node.typeVersion < 3; + + const target = isLegacy + ? TARGETS.get(operation === 'aggregateItems' ? 'concatenateItems' : operation) + : TARGETS.get(operation); + + if (!target || (isLegacy && operation === 'concatenateItems')) { + throw new Error(`Item Lists operation "${operation}" is not supported.`); + } + + if (isLegacy) { + const { typeVersion = target.typeVersion, parameters, notes } = target.legacy(node); + return { node: { type: target.type, typeVersion, parameters }, notes }; + } + + target.check?.(node); + + const parameters: INodeParameters = pickDefined(node.parameters, target.parameters); + return { node: { type: target.type, typeVersion: target.typeVersion, parameters } }; + }, +}; diff --git a/packages/cli/src/modules/breaking-changes/migrations/node-removals/read-pdf-to-extract-from-file.migration.ts b/packages/cli/src/modules/breaking-changes/migrations/node-removals/read-pdf-to-extract-from-file.migration.ts new file mode 100644 index 00000000000..a2fdbcc2030 --- /dev/null +++ b/packages/cli/src/modules/breaking-changes/migrations/node-removals/read-pdf-to-extract-from-file.migration.ts @@ -0,0 +1,49 @@ +import type { NodeMigration } from '../node-migration'; +import { isExpression, pickDefined } from '../parameter-readers'; + +/** + * Read PDF to Extract From File (Extract From PDF). + * + * Does: + * - Target: `extractFromFile`, version 1.2, `operation` = `pdf`. Both nodes call the + * same `extractDataFromPDF` helper. + * - Keeps: `binaryPropertyName`. + * - Moves: `password` to `options.password`, only when `encrypted` is `true`. The old + * node reads the password only in that case. + * - Writes: `options.keepSource` = `binary`, to keep the input binary and drop the input + * JSON, as the old node did. It does not write `maxPages` (0 reads no pages) or + * `joinPages` (the helper default matches). + * + * Refuses when: + * - `encrypted` is an expression: the migration must know if the password is used. + * + * Accepted changes: + * - The new node adds `pairedItem` to its output items. + */ +export const readPdfToExtractFromFile: NodeMigration = { + ruleId: 'read-pdf-removed-v3', + migrate: (node) => { + const { encrypted, password } = node.parameters; + if (isExpression(encrypted)) { + throw new Error( + '"Encrypted" is an expression, so the node cannot be migrated automatically.', + ); + } + + return { + node: { + type: 'n8n-nodes-base.extractFromFile', + typeVersion: 1.2, + parameters: { + operation: 'pdf', + ...pickDefined(node.parameters, ['binaryPropertyName']), + options: { + keepSource: 'binary', + // The old node passes an empty password when it is encrypted and unset. + ...(encrypted === true ? { password: password ?? '' } : {}), + }, + }, + }, + }; + }, +}; diff --git a/packages/cli/src/modules/breaking-changes/migrations/node-removals/schedule-trigger.migration.ts b/packages/cli/src/modules/breaking-changes/migrations/node-removals/schedule-trigger.migration.ts new file mode 100644 index 00000000000..57b5b16e93c --- /dev/null +++ b/packages/cli/src/modules/breaking-changes/migrations/node-removals/schedule-trigger.migration.ts @@ -0,0 +1,151 @@ +import { createHash } from 'node:crypto'; +import type { INodeParameters } from 'n8n-workflow'; + +import type { NodeMigration } from '../node-migration'; +import { asParameters, readInteger, readString } from '../parameter-readers'; + +const SCHEDULE_TRIGGER_TYPE = 'n8n-nodes-base.scheduleTrigger'; +// 1.4 adds the missed-run settings. Their defaults skip a missed run, as Cron did. +const SCHEDULE_TRIGGER_VERSION = 1.4; + +const scheduleTrigger = (...intervals: INodeParameters[]) => ({ + type: SCHEDULE_TRIGGER_TYPE, + typeVersion: SCHEDULE_TRIGGER_VERSION, + parameters: { rule: { interval: intervals } }, +}); + +// Cron picked a random minute for "every X hours". A fixed minute 0 would start all migrated +// workflows together. The hash gives each rule its own minute, and the same one on every run. +const spreadMinute = (seed: string) => + createHash('sha256').update(seed).digest().readUInt32BE(0) % 60; + +function cronItemToRule(item: INodeParameters, seed: string): INodeParameters { + // Defaults come from `NodeHelpers.cronNodeOptions`. Saved workflows omit them. + const mode = readString(item, 'mode', 'everyDay', 'Mode'); + const time = () => ({ + triggerAtHour: readInteger(item, 'hour', 14, 'Hour', { min: 0, max: 23 }), + triggerAtMinute: readInteger(item, 'minute', 0, 'Minute', { min: 0, max: 59 }), + }); + + switch (mode) { + case 'everyMinute': + return { field: 'minutes', minutesInterval: 1 }; + case 'everyHour': + return { + field: 'hours', + hoursInterval: 1, + triggerAtMinute: readInteger(item, 'minute', 0, 'Minute', { min: 0, max: 59 }), + }; + case 'everyDay': + return { field: 'days', daysInterval: 1, ...time() }; + case 'everyWeek': + return { + field: 'weeks', + weeksInterval: 1, + triggerAtDay: [readInteger(item, 'weekday', 1, 'Weekday', { min: 0, max: 6 })], + ...time(), + }; + case 'everyMonth': + return { + field: 'months', + monthsInterval: 1, + triggerAtDayOfMonth: readInteger(item, 'dayOfMonth', 1, 'Day of Month', { + min: 1, + max: 31, + }), + ...time(), + }; + case 'everyX': { + const unit = readString(item, 'unit', 'hours', 'Unit'); + // Cron fires `*/n`, which is uneven when `n` does not divide the period. + // Schedule Trigger keeps an even gap. We accept that change. + // Schedule Trigger 1.3 and later rejects values outside these ranges. + if (unit === 'minutes') { + const value = readInteger(item, 'value', 2, 'Value', { min: 1, max: 59 }); + return { field: 'minutes', minutesInterval: value }; + } + if (unit === 'hours') { + const value = readInteger(item, 'value', 2, 'Value', { min: 1, max: 23 }); + return { field: 'hours', hoursInterval: value, triggerAtMinute: spreadMinute(seed) }; + } + throw new Error(`Cron unit "${unit}" is not supported, so the node cannot be migrated.`); + } + case 'custom': { + const expression = readString(item, 'cronExpression', '* * * * * *', 'Cron Expression'); + return { field: 'cronExpression', expression: expression.trim() }; + } + default: + throw new Error(`Cron mode "${mode}" is not supported, so the node cannot be migrated.`); + } +} + +// `*/n` restarts every hour or day, so it only gives an even gap when `n` divides the period. +// Schedule Trigger does not use `*/n` in that case, so the run times change. +const hasUnevenStep = (rule: INodeParameters) => + (rule.field === 'minutes' && + typeof rule.minutesInterval === 'number' && + 60 % rule.minutesInterval !== 0) || + (rule.field === 'hours' && + typeof rule.hoursInterval === 'number' && + 24 % rule.hoursInterval !== 0); + +const UNEVEN_STEP_NOTE = + 'Cron ran an "Every X" schedule at fixed clock times, which did not repeat at an even gap. Schedule Trigger now repeats at an even gap from the first run, so the run times changed. Check the schedule.'; + +/** + * Cron to Schedule Trigger. + * + * Does: + * - Target: `scheduleTrigger`, version 1.4. It adds the missed-run settings. The migration + * does not write them. Their defaults skip a missed run, as Cron did. + * - Maps: each Cron trigger time to one schedule rule that fires at the same wall-clock + * times. + * - Writes: every value explicitly, because the Cron defaults (for example hour 14) + * differ from the Schedule Trigger defaults. + * - Picks: a minute for `everyX` hours, from a hash of the node id and the rule position. + * Cron picked a random minute, and the default minute 0 would start all migrated + * workflows together. + * + * Refuses when: + * - There are no trigger times: Cron never fires, but Schedule Trigger fires every day. + * - A value is an expression or is out of range. + * - `everyX` is outside 1-59 for minutes or 1-23 for hours, or has an unknown unit. + * - The mode is unknown. + * + * Accepted changes: + * - `everyX` keeps an even gap. Cron used a cron step of `n`, which is uneven when `n` + * does not divide 60 (minutes) or 24 (hours). The run times then change, so the + * migration reports a note. The note also turns off the one-click republish. + * - Cron picks a random second at each activation and Schedule Trigger picks a stable + * one. The second is not a setting. + * - The minute of `everyX` hours is fixed at migration. Cron picked a new minute at each + * activation. + * - Trigger times that fire at the same moment give one execution. Cron fired each at its + * own random second and ran twice. Schedule Trigger uses one stable second for the node + * and drops the second run. The two runs got the same input, because Cron has no + * output that names the trigger time. This applies to equal rules and to overlapping + * rules, such as "every 5 minutes" and "every hour at minute 0". + * - The output has extra date fields. + */ +export const cronToScheduleTrigger: NodeMigration = { + ruleId: 'cron-removed-v3', + migrate: (node) => { + const { triggerTimes } = node.parameters; + const items = asParameters(triggerTimes)?.item; + const rules = Array.isArray(items) ? items.map(asParameters) : []; + if (rules.length === 0 || rules.includes(undefined)) { + throw new Error( + 'This Cron node has no trigger times, so it never fires. Add a schedule or remove the node before migrating.', + ); + } + + const migratedRules = rules.map((rule, index) => + cronItemToRule(rule ?? {}, `${node.id}:${index}`), + ); + + return { + node: scheduleTrigger(...migratedRules), + notes: migratedRules.some(hasUnevenStep) ? [UNEVEN_STEP_NOTE] : undefined, + }; + }, +}; diff --git a/packages/cli/src/modules/breaking-changes/migrations/node-removals/vector-stores.migration.ts b/packages/cli/src/modules/breaking-changes/migrations/node-removals/vector-stores.migration.ts new file mode 100644 index 00000000000..94d3a0ef5bc --- /dev/null +++ b/packages/cli/src/modules/breaking-changes/migrations/node-removals/vector-stores.migration.ts @@ -0,0 +1,295 @@ +import { NodeConnectionTypes } from 'n8n-workflow'; +import type { IConnections, INode } from 'n8n-workflow'; + +import type { NodeMigration, WorkflowMigration } from '../node-migration'; +import { replaceAffectedNodes } from '../node-migration'; +import { pickDefined, readOptions } from '../parameter-readers'; + +/** + * The old Insert and Load nodes became one node per vector store with a `mode`. + * + * Insert maps to `insert`. Load maps to `retrieve`, not to `load` (Get Many). The old + * Load nodes output `ai_vectorStore`, and so does `retrieve`. `load` needs a main input + * and a `prompt` and outputs main items, which would break the connections. + * + * Version 1.1 is the target. In-Memory 1.2 and later stops prefixing the key with the + * workflow id, which would hide the data that the old nodes stored. + * + * Insert refusals, common to all Insert migrations: + * - The clear refusals exist because the new insert works in batches of 200 documents + * and clears the store on every batch. The old nodes cleared it once. + * - The document source refusal exists because the old insert reads the documents once + * for all input items, and the new insert reads them for each input item. A loader + * gives the documents of its own item. Any other source gives one fixed list, which + * the new insert would store again for each input item. + */ +const VERSION = 1.1; + +const isOff = (value: unknown) => value === undefined || value === false; + +const refuseClear = (label: string) => + new Error( + `"${label}" is turned on, and the new node handles it differently. Some of your stored documents could be lost. Replace this node by hand.`, + ); + +// Document loaders whose documents the old and the new insert read in the same way. +// They include the removed loaders, because their own migrations replace them with the first one. +const DOCUMENT_LOADER_TYPES = new Set([ + '@n8n/n8n-nodes-langchain.documentDefaultDataLoader', + '@n8n/n8n-nodes-langchain.documentJsonInputLoader', + '@n8n/n8n-nodes-langchain.documentBinaryInputLoader', +]); + +/** Node types that feed `nodeName` through its `ai_document` input. */ +function documentSourceTypes( + nodeName: string, + nodes: INode[], + connections: IConnections, +): string[] { + const typeByName = new Map(nodes.map(({ name, type }) => [name, type])); + const types: string[] = []; + for (const [source, byType] of Object.entries(connections)) { + for (const group of byType[NodeConnectionTypes.AiDocument] ?? []) { + for (const connection of group ?? []) { + if (connection.node === nodeName) types.push(typeByName.get(source) ?? 'unknown'); + } + } + } + return types; +} + +/** + * The old insert reads documents once for all input items. The new insert reads them for each + * input item. A loader gives the documents of its own item, so the result is the same. + * Any other source (the GitHub loader, a Code node) gives one fixed list of documents. + * The new insert would then store that list once for each input item. + * So an insert migrates only when all its document sources are loaders. + */ +function insertMigration(ruleId: string, migrate: NodeMigration['migrate']): WorkflowMigration { + return { + ruleId, + migrateWorkflow: ({ nodes, connections, affectedNodeIds }) => { + const migrated = replaceAffectedNodes(nodes, affectedNodeIds, (node) => { + const unsupported = documentSourceTypes(node.name, nodes, connections).find( + (type) => !DOCUMENT_LOADER_TYPES.has(type), + ); + if (unsupported !== undefined) { + throw new Error( + 'The documents come from a node that the migration does not support, so they could be saved more than once. Replace this node by hand.', + ); + } + + const { node: replacement } = migrate(node); + return { ...node, ...replacement } satisfies INode; + }); + + return { ...migrated, connections }; + }, + }; +} + +// In-Memory + +/** + * In Memory Vector Store Insert to Simple Vector Store (Insert Documents). + * + * Does: + * - Target: `vectorStoreInMemory`, version 1.1, `mode` = `insert`. Version 1.2 and later + * stops prefixing the key with the workflow id, which would hide the stored data. + * - Keeps: `memoryKey`. + * - A workflow migration, because it reads the `ai_document` connections. + * + * Refuses when: + * - `clearStore` is on: the new node clears the store for every batch of documents, and + * the old node cleared it once. + * - A document source is not a loader (see the top of this file). + * + * Accepted changes: + * - None. + */ +export const inMemoryInsertToVectorStore = insertMigration( + 'in-memory-vector-store-insert-removed-v3', + (node) => { + if (!isOff(node.parameters.clearStore)) throw refuseClear('Clear Store'); + + return { + node: { + type: '@n8n/n8n-nodes-langchain.vectorStoreInMemory', + typeVersion: VERSION, + parameters: { mode: 'insert', ...pickDefined(node.parameters, ['memoryKey']) }, + }, + }; + }, +); + +/** + * In Memory Vector Store Load to Simple Vector Store (Retrieve). + * + * Does: + * - Target: `vectorStoreInMemory`, version 1.1, `mode` = `retrieve` (see the top of this + * file for why it is not `load`). + * - Keeps: `memoryKey`. + * + * Refuses when: + * - Never refuses. + * + * Accepted changes: + * - None. + */ +export const inMemoryLoadToVectorStore: NodeMigration = { + ruleId: 'in-memory-vector-store-load-removed-v3', + migrate: (node) => ({ + node: { + type: '@n8n/n8n-nodes-langchain.vectorStoreInMemory', + typeVersion: VERSION, + parameters: { mode: 'retrieve', ...pickDefined(node.parameters, ['memoryKey']) }, + }, + }), +}; + +// Pinecone + +const PINECONE_TYPE = '@n8n/n8n-nodes-langchain.vectorStorePinecone'; + +/** + * Pinecone: Insert to Pinecone Vector Store (Insert Documents). + * + * Does: + * - Target: `vectorStorePinecone`, version 1.1, `mode` = `insert`. The credentials keep + * their type (`pineconeApi`). + * - Keeps: `pineconeIndex`. `pineconeNamespace` moves to `options.pineconeNamespace`. An + * empty namespace means no namespace. + * - Drops: `clearNamespace` when no namespace is set. Both nodes ignore it then. + * - A workflow migration, because it reads the `ai_document` connections. + * + * Refuses when: + * - `clearNamespace` is on and a namespace is set: the new node clears the namespace for + * every batch of documents, and the old node cleared it once. + * - A document source is not a loader (see the top of this file). + * + * Accepted changes: + * - None. + */ +export const pineconeInsertToVectorStore = insertMigration('pinecone-insert-removed-v3', (node) => { + const { pineconeNamespace, clearNamespace } = node.parameters; + const hasNamespace = pineconeNamespace !== undefined && pineconeNamespace !== ''; + // Both nodes clear only when a namespace is set. + if (hasNamespace && !isOff(clearNamespace)) throw refuseClear('Clear Namespace'); + + return { + node: { + type: PINECONE_TYPE, + typeVersion: VERSION, + parameters: { + mode: 'insert', + ...pickDefined(node.parameters, ['pineconeIndex']), + // An empty namespace and no namespace are the same for the old node. + options: hasNamespace ? { pineconeNamespace } : {}, + }, + }, + }; +}); + +/** + * Pinecone: Load to Pinecone Vector Store (Retrieve). + * + * Does: + * - Target: `vectorStorePinecone`, version 1.1, `mode` = `retrieve`. The credentials keep + * their type (`pineconeApi`). + * - Keeps: `pineconeIndex`, `pineconeNamespace` (to `options.pineconeNamespace`) and + * `options.metadata`. + * + * Refuses when: + * - `options` is not an object. + * + * Accepted changes: + * - None. + */ +export const pineconeLoadToVectorStore: NodeMigration = { + ruleId: 'pinecone-load-removed-v3', + migrate: (node) => { + const { pineconeNamespace } = node.parameters; + const hasNamespace = pineconeNamespace !== undefined && pineconeNamespace !== ''; + + return { + node: { + type: PINECONE_TYPE, + typeVersion: VERSION, + parameters: { + mode: 'retrieve', + ...pickDefined(node.parameters, ['pineconeIndex']), + options: { + ...(hasNamespace ? { pineconeNamespace } : {}), + ...pickDefined(readOptions(node.parameters), ['metadata']), + }, + }, + }, + }; + }, +}; + +// Supabase + +const SUPABASE_TYPE = '@n8n/n8n-nodes-langchain.vectorStoreSupabase'; + +/** + * Supabase: Insert to Supabase Vector Store (Insert Documents). + * + * Does: + * - Target: `vectorStoreSupabase`, version 1.1, `mode` = `insert`. The credentials keep + * their type (`supabaseApi`). + * - Keeps: `tableName`. `queryName` moves to `options.queryName`. + * - A workflow migration, because it reads the `ai_document` connections. + * + * Refuses when: + * - A document source is not a loader (see the top of this file). + * + * Accepted changes: + * - None. + */ +export const supabaseInsertToVectorStore = insertMigration( + 'supabase-insert-removed-v3', + (node) => ({ + node: { + type: SUPABASE_TYPE, + typeVersion: VERSION, + parameters: { + mode: 'insert', + ...pickDefined(node.parameters, ['tableName']), + options: pickDefined(node.parameters, ['queryName']), + }, + }, + }), +); + +/** + * Supabase: Load to Supabase Vector Store (Retrieve). + * + * Does: + * - Target: `vectorStoreSupabase`, version 1.1, `mode` = `retrieve`. The credentials keep + * their type (`supabaseApi`). + * - Keeps: `tableName`, `queryName` (to `options.queryName`) and `options.metadata`. + * + * Refuses when: + * - `options` is not an object. + * + * Accepted changes: + * - None. + */ +export const supabaseLoadToVectorStore: NodeMigration = { + ruleId: 'supabase-load-removed-v3', + migrate: (node) => ({ + node: { + type: SUPABASE_TYPE, + typeVersion: VERSION, + parameters: { + mode: 'retrieve', + ...pickDefined(node.parameters, ['tableName']), + options: { + ...pickDefined(node.parameters, ['queryName']), + ...pickDefined(readOptions(node.parameters), ['metadata']), + }, + }, + }, + }), +}; diff --git a/packages/cli/src/modules/breaking-changes/migrations/node-removals/workflow-trigger-to-n8n-trigger.migration.ts b/packages/cli/src/modules/breaking-changes/migrations/node-removals/workflow-trigger-to-n8n-trigger.migration.ts new file mode 100644 index 00000000000..155b72c1c7d --- /dev/null +++ b/packages/cli/src/modules/breaking-changes/migrations/node-removals/workflow-trigger-to-n8n-trigger.migration.ts @@ -0,0 +1,44 @@ +import type { NodeMigration } from '../node-migration'; + +/** + * Workflow Trigger to n8n Trigger. + * + * Does: + * - Target: `n8nTrigger`, version 1. + * - Keeps: `events` with the same name and values (`activate`, `update`). The new node + * only adds `init`. + * + * Refuses when: + * - `events` is an expression or has a value other than `activate` or `update`. + * + * Accepted changes: + * - For `activate`, the event text changes from "Workflow activated" to "Workflow + * published". Reported as a note. + */ +export const workflowTriggerToN8nTrigger: NodeMigration = { + ruleId: 'workflow-trigger-removed-v3', + migrate: (node) => { + const { events = [] } = node.parameters; + if ( + !Array.isArray(events) || + !events.every((event) => event === 'activate' || event === 'update') + ) { + throw new Error( + '"Events" is an expression or has an unsupported value, so the node cannot be migrated automatically.', + ); + } + + return { + node: { + type: 'n8n-nodes-base.n8nTrigger', + typeVersion: 1, + parameters: { events }, + }, + notes: events.includes('activate') + ? [ + 'The event text for activation changed from "Workflow activated" to "Workflow published".', + ] + : undefined, + }; + }, +}; diff --git a/packages/cli/src/modules/breaking-changes/migrations/node-removals/write-binary-file-to-read-write-file.migration.ts b/packages/cli/src/modules/breaking-changes/migrations/node-removals/write-binary-file-to-read-write-file.migration.ts new file mode 100644 index 00000000000..2bfd4e01f27 --- /dev/null +++ b/packages/cli/src/modules/breaking-changes/migrations/node-removals/write-binary-file-to-read-write-file.migration.ts @@ -0,0 +1,44 @@ +import type { NodeMigration } from '../node-migration'; +import { asParameters, isExpression, pickDefined } from '../parameter-readers'; + +/** + * Write Binary File to Read/Write Files from Disk (Write File to Disk). + * + * Does: + * - Target: `readWriteFile`, version 1.1, `operation` = `write`. + * - Keeps: `fileName`, `dataPropertyName` and `options` (with `append`). Names and + * meaning stay the same. + * + * Refuses when: + * - `options.append` is an expression: the old node reads `options` once, for item 0, + * and the new node reads it for each item, so the results could differ. + * - `options` is not an object. + * + * Accepted changes: + * - None. + */ +export const writeBinaryFileToReadWriteFile: NodeMigration = { + ruleId: 'write-binary-file-removed-v3', + migrate: (node) => { + const options = asParameters(node.parameters.options); + if (node.parameters.options !== undefined && !options) { + throw new Error('The options of this node are not in a supported format.'); + } + if (isExpression(options?.append)) { + throw new Error( + '"Append" is an expression. The old node reads it once and the new node reads it for each item, so the node cannot be migrated automatically.', + ); + } + + return { + node: { + type: 'n8n-nodes-base.readWriteFile', + typeVersion: 1.1, + parameters: { + operation: 'write', + ...pickDefined(node.parameters, ['fileName', 'dataPropertyName', 'options']), + }, + }, + }; + }, +}; diff --git a/packages/cli/src/modules/breaking-changes/migrations/parameter-readers.ts b/packages/cli/src/modules/breaking-changes/migrations/parameter-readers.ts new file mode 100644 index 00000000000..d578637c6d6 --- /dev/null +++ b/packages/cli/src/modules/breaking-changes/migrations/parameter-readers.ts @@ -0,0 +1,81 @@ +import { isNodeParameters } from 'n8n-workflow'; +import type { INodeParameters } from 'n8n-workflow'; + +/** + * Returns a parameter value as a plain parameter object, or `undefined` for any other value. + * The `isNodeParameters` guard alone leaves special value types in the union, such as icons. + */ +export function asParameters(value: unknown): INodeParameters | undefined { + return isNodeParameters(value) ? value : undefined; +} + +/** An n8n expression is a string that starts with `=`. */ +export const isExpression = (value: unknown): boolean => + typeof value === 'string' && value.startsWith('='); + +/** + * Reads a whole-number parameter that a migration must compute with. + * Saved workflows omit default values, so `fallback` stands in for a missing one. + * Throws for expressions and out-of-range values, because the migration cannot prove + * what they mean at run time. + */ +export function readInteger( + parameters: INodeParameters, + key: string, + fallback: number, + label: string, + { min, max }: { min?: number; max?: number } = {}, +): number { + const value = parameters[key] ?? fallback; + const parsed = + typeof value === 'number' || (typeof value === 'string' && /^\d+$/.test(value)) + ? Number(value) + : Number.NaN; + + if ( + !Number.isInteger(parsed) || + (min !== undefined && parsed < min) || + (max !== undefined && parsed > max) + ) { + throw new Error( + `"${label}" is an expression or has a value that has no exact replacement, so the node cannot be migrated automatically.`, + ); + } + + return parsed; +} + +/** Reads a text option parameter. Throws for expressions and other value types. */ +export function readString( + parameters: INodeParameters, + key: string, + fallback: string, + label: string, +): string { + const value = parameters[key] ?? fallback; + if (typeof value !== 'string' || isExpression(value)) { + throw new Error( + `"${label}" is an expression or has an unsupported value, so the node cannot be migrated automatically.`, + ); + } + return value; +} + +/** Reads the `options` collection of a node. A missing collection is empty. */ +export function readOptions(parameters: INodeParameters): INodeParameters { + if (parameters.options === undefined) return {}; + + const options = asParameters(parameters.options); + if (!options) throw new Error('The options of this node are not in a supported format.'); + return options; +} + +/** Copies the listed parameters that the old node has set. */ +export function pickDefined(parameters: INodeParameters, keys: string[]): INodeParameters { + const picked: INodeParameters = {}; + for (const key of keys) { + const value = parameters[key]; + if (value !== undefined) picked[key] = value; + } + return picked; +} diff --git a/packages/cli/src/modules/breaking-changes/notifications/__tests__/migration-finding-notification.service.test.ts b/packages/cli/src/modules/breaking-changes/notifications/__tests__/migration-finding-notification.service.test.ts new file mode 100644 index 00000000000..b46a5daab1a --- /dev/null +++ b/packages/cli/src/modules/breaking-changes/notifications/__tests__/migration-finding-notification.service.test.ts @@ -0,0 +1,245 @@ +import type { UrlService } from '@n8n/backend-services'; +import { mockLogger } from '@n8n/backend-test-utils'; +import type { User, UserRepository } from '@n8n/db'; +import { BadRequestError, NotFoundError } from '@n8n/errors'; +import type { MockProxy } from 'vitest-mock-extended'; +import { mock } from 'vitest-mock-extended'; + +import type { UserManagementMailer } from '@/user-management/email/user-management-mailer'; + +import type { RuleRegistry } from '../../breaking-changes.rule-registry.service'; +import type { + MigrationFindingRepository, + TriageableMigrationFinding, +} from '../../database/repositories/migration-finding.repository'; +import type { MigrationWorkflowOwnerRepository } from '../../database/repositories/migration-workflow-owner.repository'; +import type { MigrationWorkflowOwner } from '../../database/entities/migration-workflow-owner.entity'; +import type { IBreakingChangeRule } from '../../types'; +import { MigrationFindingNotificationService } from '../migration-finding-notification.service'; + +const RULE_ID = 'removed-nodes-v3'; +const notifier = { + id: 'admin', + firstName: 'Ada', + lastName: 'Lovelace', + email: 'ada@n8n.io', +} as User; + +function user(id: string, email: string | null = `${id}@example.com`): User { + return { id, firstName: id, lastName: null, email } as unknown as User; +} + +function finding( + id: number, + workflowId: string, + status: TriageableMigrationFinding['status'] = 'open', +): TriageableMigrationFinding { + return { + id, + ruleId: RULE_ID, + workflowId, + status, + notifiedAt: null, + workflow: { + id: workflowId, + name: `Flow ${workflowId}`, + activeVersionId: null, + updatedAt: new Date(), + }, + }; +} + +function ownerRow(workflowId: string, userId: string | null): MigrationWorkflowOwner { + return { workflowId, userId, source: 'assigned' } as MigrationWorkflowOwner; +} + +describe('MigrationFindingNotificationService', () => { + let ruleRegistry: MockProxy; + let findingRepository: MockProxy; + let ownerRepository: MockProxy; + let userRepository: MockProxy; + let mailer: MockProxy; + let service: MigrationFindingNotificationService; + + beforeEach(() => { + ruleRegistry = mock(); + findingRepository = mock(); + ownerRepository = mock(); + userRepository = mock(); + mailer = mock({ isEmailSetUp: true }); + const urlService = mock(); + urlService.getInstanceBaseUrl.mockReturnValue('https://n8n.example'); + service = new MigrationFindingNotificationService( + ruleRegistry, + findingRepository, + ownerRepository, + userRepository, + mailer, + urlService, + mockLogger(), + ); + + // A plain object, not a proxy: the service tells rule kinds apart by their methods. + const rule = { + id: RULE_ID, + getMetadata: () => ({ version: 'v3', title: 'Removed nodes' }), + detectWorkflow: vi.fn(), + }; + ruleRegistry.getRule + .calledWith(RULE_ID) + .mockReturnValue(rule as unknown as IBreakingChangeRule); + mailer.migrationFindings.mockResolvedValue({ emailSent: true }); + }); + + describe('notifyOwners', () => { + it('sends one email per owner with all their workflows and marks those findings notified', async () => { + findingRepository.listTriageableForRule.mockResolvedValue([ + finding(1, 'wf-1'), + finding(2, 'wf-2', 'notified'), + finding(3, 'wf-3'), + ]); + ownerRepository.findByWorkflowIds.mockResolvedValue([ + ownerRow('wf-1', 'alice'), + ownerRow('wf-2', 'alice'), + ownerRow('wf-3', 'bob'), + ]); + userRepository.findManyByIds.mockResolvedValue([user('alice'), user('bob')]); + + const result = await service.notifyOwners(RULE_ID, ['wf-1', 'wf-2', 'wf-3'], notifier); + + expect(findingRepository.listTriageableForRule).toHaveBeenCalledWith( + 'v3', + RULE_ID, + ['wf-1', 'wf-2', 'wf-3'], + expect.anything(), + ); + expect(mailer.migrationFindings).toHaveBeenCalledTimes(2); + expect(mailer.migrationFindings).toHaveBeenCalledWith({ + email: 'alice@example.com', + firstName: 'alice', + notifierName: 'Ada Lovelace', + ruleTitle: 'Removed nodes', + targetVersion: 'v3', + workflows: [ + { id: 'wf-1', name: 'Flow wf-1' }, + { id: 'wf-2', name: 'Flow wf-2' }, + ], + reportUrl: `https://n8n.example/settings/migration-report/${RULE_ID}`, + }); + expect(findingRepository.markNotifiedForIds).toHaveBeenCalledWith([1, 2], expect.anything()); + expect(findingRepository.markNotifiedForIds).toHaveBeenCalledWith([3], expect.anything()); + expect(result.notifiedWorkflowIds.sort()).toEqual(['wf-1', 'wf-2', 'wf-3']); + expect(result.skipped).toEqual([]); + }); + + it('skips a workflow without a finding that needs a fix, and one without an owner email', async () => { + findingRepository.listTriageableForRule.mockResolvedValue([ + finding(1, 'wf-1'), + finding(2, 'wf-2', 'wont_fix'), + finding(3, 'wf-3'), + finding(4, 'wf-4'), + finding(5, 'wf-5'), + ]); + ownerRepository.findByWorkflowIds.mockResolvedValue([ + ownerRow('wf-1', 'alice'), + ownerRow('wf-3', null), + ownerRow('wf-4', 'gone'), + ownerRow('wf-5', 'noemail'), + ]); + userRepository.findManyByIds.mockResolvedValue([user('alice'), user('noemail', null)]); + + const result = await service.notifyOwners( + RULE_ID, + ['wf-1', 'wf-2', 'wf-3', 'wf-4', 'wf-5', 'wf-6'], + notifier, + ); + + expect(mailer.migrationFindings).toHaveBeenCalledTimes(1); + expect(result.notifiedWorkflowIds).toEqual(['wf-1']); + expect(result.skipped).toEqual( + expect.arrayContaining([ + { workflowId: 'wf-2', reason: 'no_finding' }, + { workflowId: 'wf-6', reason: 'no_finding' }, + { workflowId: 'wf-3', reason: 'no_owner' }, + { workflowId: 'wf-4', reason: 'no_owner' }, + { workflowId: 'wf-5', reason: 'no_owner' }, + ]), + ); + expect(result.skipped).toHaveLength(5); + }); + + it('leaves the findings of an owner untouched when their email fails', async () => { + findingRepository.listTriageableForRule.mockResolvedValue([ + finding(1, 'wf-1'), + finding(2, 'wf-2'), + ]); + ownerRepository.findByWorkflowIds.mockResolvedValue([ + ownerRow('wf-1', 'alice'), + ownerRow('wf-2', 'bob'), + ]); + userRepository.findManyByIds.mockResolvedValue([user('alice'), user('bob')]); + mailer.migrationFindings.mockImplementation(async ({ email }) => { + if (email === 'alice@example.com') throw new Error('SMTP down'); + return { emailSent: true }; + }); + + const result = await service.notifyOwners(RULE_ID, ['wf-1', 'wf-2'], notifier); + + expect(findingRepository.markNotifiedForIds).toHaveBeenCalledTimes(1); + expect(findingRepository.markNotifiedForIds).toHaveBeenCalledWith([2], expect.anything()); + expect(result.notifiedWorkflowIds).toEqual(['wf-2']); + expect(result.skipped).toEqual([{ workflowId: 'wf-1', reason: 'send_failed' }]); + }); + + it('still reports the workflows notified when the email went out but the mark failed', async () => { + findingRepository.listTriageableForRule.mockResolvedValue([finding(1, 'wf-1')]); + ownerRepository.findByWorkflowIds.mockResolvedValue([ownerRow('wf-1', 'alice')]); + userRepository.findManyByIds.mockResolvedValue([user('alice')]); + findingRepository.markNotifiedForIds.mockRejectedValue(new Error('DB down')); + + const result = await service.notifyOwners(RULE_ID, ['wf-1'], notifier); + + expect(mailer.migrationFindings).toHaveBeenCalledTimes(1); + expect(result).toEqual({ notifiedWorkflowIds: ['wf-1'], skipped: [] }); + }); + + it('skips the owner as send failed when the mailer sends nothing', async () => { + findingRepository.listTriageableForRule.mockResolvedValue([finding(1, 'wf-1')]); + ownerRepository.findByWorkflowIds.mockResolvedValue([ownerRow('wf-1', 'alice')]); + userRepository.findManyByIds.mockResolvedValue([user('alice')]); + mailer.migrationFindings.mockResolvedValue({ emailSent: false }); + + const result = await service.notifyOwners(RULE_ID, ['wf-1'], notifier); + + expect(findingRepository.markNotifiedForIds).not.toHaveBeenCalled(); + expect(result).toEqual({ + notifiedWorkflowIds: [], + skipped: [{ workflowId: 'wf-1', reason: 'send_failed' }], + }); + }); + + it('rejects the request before reading anything when email is not set up', async () => { + mailer = mock({ isEmailSetUp: false }); + service = new MigrationFindingNotificationService( + ruleRegistry, + findingRepository, + ownerRepository, + userRepository, + mailer, + mock(), + mockLogger(), + ); + + await expect(service.notifyOwners(RULE_ID, ['wf-1'], notifier)).rejects.toBeInstanceOf( + BadRequestError, + ); + expect(findingRepository.listTriageableForRule).not.toHaveBeenCalled(); + }); + + it('rejects an unknown rule with not-found', async () => { + await expect(service.notifyOwners('unknown', ['wf-1'], notifier)).rejects.toBeInstanceOf( + NotFoundError, + ); + }); + }); +}); diff --git a/packages/cli/src/modules/breaking-changes/notifications/migration-finding-notification.service.ts b/packages/cli/src/modules/breaking-changes/notifications/migration-finding-notification.service.ts new file mode 100644 index 00000000000..9f3f8ae6ab3 --- /dev/null +++ b/packages/cli/src/modules/breaking-changes/notifications/migration-finding-notification.service.ts @@ -0,0 +1,180 @@ +import type { MigrationNotifyResult, MigrationNotifySkipReason } from '@n8n/api-types'; +import { Logger } from '@n8n/backend-common'; +import { UrlService } from '@n8n/backend-services'; +import { UserRepository, type User } from '@n8n/db'; +import { Service } from '@n8n/di'; +import { BadRequestError, NotFoundError } from '@n8n/errors'; + +import { UserManagementMailer } from '@/user-management/email/user-management-mailer'; + +import { RuleRegistry } from '../breaking-changes.rule-registry.service'; +import { + MigrationFindingRepository, + type TriageableMigrationFinding, +} from '../database/repositories/migration-finding.repository'; +import { MigrationWorkflowOwnerRepository } from '../database/repositories/migration-workflow-owner.repository'; +import { isWorkflowLevelRule } from '../types'; + +/** The user as the email names them. */ +function displayName(user: Pick): string { + return [user.firstName, user.lastName].filter(Boolean).join(' ') || user.email || 'An admin'; +} + +/** + * Emails the owners of workflows about one rule's findings on them and records + * the notification on the findings. One email per owner lists all their workflows. + */ +@Service() +export class MigrationFindingNotificationService { + constructor( + private readonly ruleRegistry: RuleRegistry, + private readonly findingRepository: MigrationFindingRepository, + private readonly ownerRepository: MigrationWorkflowOwnerRepository, + private readonly userRepository: UserRepository, + private readonly mailer: UserManagementMailer, + private readonly urlService: UrlService, + private readonly logger: Logger, + ) { + this.logger = logger.scoped('breaking-changes'); + } + + /** + * Notifies the owners of the given workflows about the rule's finding on them. + * A finding is marked notified only when its owner's email went out, so the + * report never claims a notification that nobody received. A notified finding + * is emailed again as a reminder. A workflow whose finding is won't fix or + * missing, or that has no owner with an email, is reported as skipped. + */ + async notifyOwners( + ruleId: string, + workflowIds: string[], + notifier: User, + ): Promise { + const rule = this.ruleRegistry.getRule(ruleId); + if (!rule || !isWorkflowLevelRule(rule)) { + throw new NotFoundError(`Breaking change rule with ID '${ruleId}' not found.`); + } + if (!this.mailer.isEmailSetUp) { + throw new BadRequestError( + 'Email is not set up on this instance, so owners cannot be notified', + ); + } + const { version, title } = rule.getMetadata(); + + const result: MigrationNotifyResult = { notifiedWorkflowIds: [], skipped: [] }; + const skip = (ids: string[], reason: MigrationNotifySkipReason) => { + for (const workflowId of ids) result.skipped.push({ workflowId, reason }); + }; + + // Only a finding that still needs a fix is worth an email. A won't fix one is resolved. + const findings = ( + await this.findingRepository.listTriageableForRule(version, ruleId, workflowIds, {}) + ).filter((finding) => finding.status !== 'wont_fix'); + const findingByWorkflow = new Map(findings.map((finding) => [finding.workflowId, finding])); + skip( + workflowIds.filter((workflowId) => !findingByWorkflow.has(workflowId)), + 'no_finding', + ); + + const findingsByOwner = await this.groupByOwner(findings); + skip( + findings + .filter((finding) => !findingsByOwner.has(finding.workflowId)) + .map((finding) => finding.workflowId), + 'no_owner', + ); + + const reportUrl = `${this.urlService.getInstanceBaseUrl()}/settings/migration-report/${ruleId}`; + const notifierName = displayName(notifier); + await Promise.all( + [...new Set(findingsByOwner.values())].map(async ({ owner, findings: ownerFindings }) => { + const ownerWorkflowIds = ownerFindings.map((finding) => finding.workflowId); + let emailSent = false; + try { + ({ emailSent } = await this.mailer.migrationFindings({ + email: owner.email, + firstName: owner.firstName, + notifierName, + ruleTitle: title, + targetVersion: version, + workflows: ownerFindings.map((finding) => ({ + id: finding.workflowId, + name: finding.workflow.name, + })), + reportUrl, + })); + } catch (error) { + this.logger.warn('Emailing a workflow owner about migration findings failed', { + ruleId, + ownerId: owner.id, + error, + }); + } + if (!emailSent) { + skip(ownerWorkflowIds, 'send_failed'); + return; + } + + // The email is out either way. A failed mark must not read as a failed send, + // or the user re-sends it. + try { + await this.findingRepository.markNotifiedForIds( + ownerFindings.map((finding) => finding.id), + {}, + ); + } catch (error) { + this.logger.error( + 'The owner was emailed, but the findings could not be marked notified', + { + ruleId, + ownerId: owner.id, + error, + }, + ); + } + result.notifiedWorkflowIds.push(...ownerWorkflowIds); + }), + ); + + return result; + } + + /** + * The group of each workflow id: the owner who receives the email and all + * their findings. A workflow whose owner is gone or has no email is left out. + */ + private async groupByOwner(findings: TriageableMigrationFinding[]) { + type Owner = Pick & { email: string }; + type Group = { owner: Owner; findings: TriageableMigrationFinding[] }; + + const ownerRows = await this.ownerRepository.findByWorkflowIds( + findings.map((finding) => finding.workflowId), + {}, + ); + const userIds = [...new Set(ownerRows.flatMap((row) => (row.userId ? [row.userId] : [])))]; + const users = userIds.length > 0 ? await this.userRepository.findManyByIds(userIds) : []; + const usersById = new Map(users.map((user) => [user.id, user])); + const ownerIdByWorkflow = new Map(ownerRows.map((row) => [row.workflowId, row.userId])); + + const groupsByOwner = new Map(); + const groupsByWorkflow = new Map(); + for (const finding of findings) { + const userId = ownerIdByWorkflow.get(finding.workflowId); + const user = userId ? usersById.get(userId) : undefined; + if (!user?.email) continue; + const group = groupsByOwner.get(user.id) ?? { + owner: { + id: user.id, + firstName: user.firstName, + lastName: user.lastName, + email: user.email, + }, + findings: [], + }; + group.findings.push(finding); + groupsByOwner.set(user.id, group); + groupsByWorkflow.set(finding.workflowId, group); + } + return groupsByWorkflow; + } +} diff --git a/packages/cli/src/modules/breaking-changes/query/__tests__/migration-finding-query.service.test.ts b/packages/cli/src/modules/breaking-changes/query/__tests__/migration-finding-query.service.test.ts index 7e8ba447f30..ca2f6cca859 100644 --- a/packages/cli/src/modules/breaking-changes/query/__tests__/migration-finding-query.service.test.ts +++ b/packages/cli/src/modules/breaking-changes/query/__tests__/migration-finding-query.service.test.ts @@ -3,7 +3,7 @@ import type { BreakingChangeVersion, BreakingChangeWorkflowIssue, BreakingChangeWorkflowRuleResult, - MigrationFindingTriageStatus, + MigrationFindingListedStatus, } from '@n8n/api-types'; import { mockLogger } from '@n8n/backend-test-utils'; import type { @@ -105,9 +105,10 @@ function triageableFinding( id: number, ruleId: string, workflow: TriageableMigrationFinding['workflow'], - status: MigrationFindingTriageStatus = 'open', + status: MigrationFindingListedStatus = 'open', + notifiedAt: Date | null = null, ): TriageableMigrationFinding { - return { id, ruleId, workflowId: workflow.id, status, workflow }; + return { id, ruleId, workflowId: workflow.id, status, notifiedAt, workflow }; } function workflowWithNodes(id: string, nodeTypes: string[]): WorkflowEntity { @@ -165,9 +166,9 @@ describe('MigrationFindingQueryService', () => { workflowRepository.count.mockResolvedValue(0); workflowRepository.findByIds.mockResolvedValue([]); workflowStatisticsRepository.findByWorkflowIds.mockResolvedValue([]); - findingRepository.countOpenByRule.mockResolvedValue([]); + findingRepository.countUnresolvedByRule.mockResolvedValue([]); findingRepository.countWontFixByRule.mockResolvedValue([]); - findingRepository.countDistinctOpenWorkflows.mockResolvedValue(0); + findingRepository.countDistinctUnresolvedWorkflows.mockResolvedValue(0); findingRepository.listTriageableForRule.mockResolvedValue([]); syncRepository.getForVersion.mockResolvedValue(null); ownerRepository.findByWorkflowIds.mockResolvedValue([]); @@ -192,13 +193,13 @@ describe('MigrationFindingQueryService', () => { describe('getLightReport', () => { it('lists each workflow rule with open findings, with its metadata and count from the table', async () => { - findingRepository.countOpenByRule.mockResolvedValue([{ ruleId: 'rule-a', count: 3 }]); + findingRepository.countUnresolvedByRule.mockResolvedValue([{ ruleId: 'rule-a', count: 3 }]); workflowRepository.count.mockResolvedValue(10); const result = await service.getLightReport(TARGET_VERSION, INSTANCE); expect(ruleRegistry.getRules).toHaveBeenCalledWith(TARGET_VERSION); - expect(findingRepository.countOpenByRule).toHaveBeenCalledWith( + expect(findingRepository.countUnresolvedByRule).toHaveBeenCalledWith( TARGET_VERSION, undefined, expect.anything(), @@ -223,7 +224,7 @@ describe('MigrationFindingQueryService', () => { }); it('lists each rule with its wont_fix count, and a rule with only wont_fix findings with an open count of zero', async () => { - findingRepository.countOpenByRule.mockResolvedValue([{ ruleId: 'rule-a', count: 3 }]); + findingRepository.countUnresolvedByRule.mockResolvedValue([{ ruleId: 'rule-a', count: 3 }]); findingRepository.countWontFixByRule.mockResolvedValue([ { ruleId: 'rule-a', count: 1 }, { ruleId: 'rule-b', count: 2 }, @@ -251,15 +252,15 @@ describe('MigrationFindingQueryService', () => { }); it('counts each affected workflow once across rules', async () => { - findingRepository.countOpenByRule.mockResolvedValue([ + findingRepository.countUnresolvedByRule.mockResolvedValue([ { ruleId: 'rule-a', count: 3 }, { ruleId: 'rule-b', count: 2 }, ]); - findingRepository.countDistinctOpenWorkflows.mockResolvedValue(4); + findingRepository.countDistinctUnresolvedWorkflows.mockResolvedValue(4); const result = await service.getLightReport(TARGET_VERSION, INSTANCE); - expect(findingRepository.countDistinctOpenWorkflows).toHaveBeenCalledWith( + expect(findingRepository.countDistinctUnresolvedWorkflows).toHaveBeenCalledWith( TARGET_VERSION, undefined, expect.anything(), @@ -294,15 +295,15 @@ describe('MigrationFindingQueryService', () => { it('limits counts and the total to the workflows in scope, and hides instance results', async () => { const scope: ReportScope = { kind: 'workflows', workflowIds: ['wf-1', 'wf-2', 'wf-3'] }; - findingRepository.countOpenByRule.mockResolvedValue([{ ruleId: 'rule-a', count: 2 }]); - findingRepository.countDistinctOpenWorkflows.mockResolvedValue(2); + findingRepository.countUnresolvedByRule.mockResolvedValue([{ ruleId: 'rule-a', count: 2 }]); + findingRepository.countDistinctUnresolvedWorkflows.mockResolvedValue(2); breakingChangeService.getAllInstanceRulesResults.mockResolvedValue([ mock({ ruleId: 'instance-rule' }), ]); const result = await service.getLightReport(TARGET_VERSION, scope); - expect(findingRepository.countOpenByRule).toHaveBeenCalledWith( + expect(findingRepository.countUnresolvedByRule).toHaveBeenCalledWith( TARGET_VERSION, scope.workflowIds, expect.anything(), @@ -312,7 +313,7 @@ describe('MigrationFindingQueryService', () => { scope.workflowIds, expect.anything(), ); - expect(findingRepository.countDistinctOpenWorkflows).toHaveBeenCalledWith( + expect(findingRepository.countDistinctUnresolvedWorkflows).toHaveBeenCalledWith( TARGET_VERSION, scope.workflowIds, expect.anything(), @@ -333,6 +334,37 @@ describe('MigrationFindingQueryService', () => { }); describe('getRuleFindings', () => { + it('carries the status and the notified date of a notified finding', async () => { + const notifiedAt = new Date('2026-05-01T00:00:00.000Z'); + findingRepository.listTriageableForRule.mockResolvedValue([ + triageableFinding( + 1, + 'rule-a', + { id: 'wf-1', name: 'First', activeVersionId: null, updatedAt: UPDATED_AT }, + 'notified', + notifiedAt, + ), + triageableFinding(2, 'rule-a', { + id: 'wf-2', + name: 'Second', + activeVersionId: null, + updatedAt: UPDATED_AT, + }), + ]); + workflowRepository.findByIds.mockResolvedValue([ + workflowWithNodes('wf-1', ['n8n-nodes-base.a']), + workflowWithNodes('wf-2', ['n8n-nodes-base.a']), + ]); + workflowStatisticsRepository.findByWorkflowIds.mockResolvedValue([]); + + const result = await service.getRuleFindings(TARGET_VERSION, 'rule-a', INSTANCE); + + expect(result.affectedWorkflows.map((w) => [w.id, w.status, w.notifiedAt])).toEqual([ + ['wf-1', 'notified', notifiedAt], + ['wf-2', 'open', undefined], + ]); + }); + it('returns one workflow per open or wont_fix finding with its status, statistics and the issues of that rule', async () => { findingRepository.listTriageableForRule.mockResolvedValue([ triageableFinding(1, 'rule-a', { diff --git a/packages/cli/src/modules/breaking-changes/query/migration-finding-query.service.ts b/packages/cli/src/modules/breaking-changes/query/migration-finding-query.service.ts index 09cfda011ad..673972eadcc 100644 --- a/packages/cli/src/modules/breaking-changes/query/migration-finding-query.service.ts +++ b/packages/cli/src/modules/breaking-changes/query/migration-finding-query.service.ts @@ -82,7 +82,7 @@ export class MigrationFindingQueryService { } /** - * The overview: one entry per workflow rule with its open and won't fix finding counts, + * The overview: one entry per workflow rule with its unresolved (open or notified) and won't fix finding counts, * plus live instance results. */ async getLightReport( @@ -102,9 +102,9 @@ export class MigrationFindingQueryService { totalWorkflows, instanceResults, ] = await Promise.all([ - this.findingRepository.countOpenByRule(targetVersion, filter, {}), + this.findingRepository.countUnresolvedByRule(targetVersion, filter, {}), this.findingRepository.countWontFixByRule(targetVersion, filter, {}), - this.findingRepository.countDistinctOpenWorkflows(targetVersion, filter, {}), + this.findingRepository.countDistinctUnresolvedWorkflows(targetVersion, filter, {}), this.syncRepository.getForVersion(targetVersion, {}), scope.kind === 'instance' ? this.workflowRepository.count() : scope.workflowIds.length, // Instance rules read config and environment, not workflows, so they stay live. @@ -148,7 +148,7 @@ export class MigrationFindingQueryService { } /** - * The detail of one workflow rule: every open and won't fix finding in scope + * The detail of one workflow rule: every open, notified and won't fix finding in scope * with its status, workflow, statistics and issues. */ async getRuleFindings( @@ -192,6 +192,7 @@ export class MigrationFindingQueryService { // A workflow the rule no longer flags stays listed, without issues, until the next sync. issues: issuesByWorkflow.get(finding.workflowId) ?? [], status: finding.status, + notifiedAt: finding.notifiedAt ?? undefined, owner: ownersByWorkflow.get(finding.workflowId), homeProjectId: projectsByWorkflow.get(finding.workflowId)?.id, }); diff --git a/packages/cli/src/modules/breaking-changes/sync/__tests__/migration-finding-diff.test.ts b/packages/cli/src/modules/breaking-changes/sync/__tests__/migration-finding-diff.test.ts index af25e6f77ca..9741daeb1eb 100644 --- a/packages/cli/src/modules/breaking-changes/sync/__tests__/migration-finding-diff.test.ts +++ b/packages/cli/src/modules/breaking-changes/sync/__tests__/migration-finding-diff.test.ts @@ -107,15 +107,36 @@ describe('diffMigrationFindings', () => { expect(diff).toEqual({ toInsert: [], toMarkFixed: [4], toReopen: [] }); }); + it('keeps a notified row as it is while the hit remains', () => { + const diff = diffMigrationFindings({ + targetVersion: TARGET_VERSION, + workflowIds: ['wf-1'], + hits: [{ ruleId: 'rule-a', workflowId: 'wf-1' }], + existing: [existingRow(5, 'rule-a', 'wf-1', 'notified')], + }); + + expect(diff).toEqual({ toInsert: [], toMarkFixed: [], toReopen: [] }); + }); + + it('marks a notified row fixed when the hit is gone', () => { + const diff = diffMigrationFindings({ + targetVersion: TARGET_VERSION, + workflowIds: ['wf-1'], + hits: [], + existing: [existingRow(5, 'rule-a', 'wf-1', 'notified')], + }); + + expect(diff).toEqual({ toInsert: [], toMarkFixed: [5], toReopen: [] }); + }); + it('leaves rows in other statuses unchanged', () => { const diff = diffMigrationFindings({ targetVersion: TARGET_VERSION, - workflowIds: ['wf-1', 'wf-2', 'wf-3'], + workflowIds: ['wf-1', 'wf-2'], hits: [{ ruleId: 'rule-a', workflowId: 'wf-2' }], existing: [ - existingRow(1, 'rule-a', 'wf-1', 'notified'), - existingRow(2, 'rule-a', 'wf-2', 'notified'), - existingRow(3, 'rule-a', 'wf-3', 'fixed_unpublished'), + existingRow(1, 'rule-a', 'wf-1', 'fixed_unpublished'), + existingRow(2, 'rule-a', 'wf-2', 'fixed_unpublished'), ], }); diff --git a/packages/cli/src/modules/breaking-changes/sync/__tests__/migration-finding-sync.service.test.ts b/packages/cli/src/modules/breaking-changes/sync/__tests__/migration-finding-sync.service.test.ts index 865e2ebebaf..f546a6dc517 100644 --- a/packages/cli/src/modules/breaking-changes/sync/__tests__/migration-finding-sync.service.test.ts +++ b/packages/cli/src/modules/breaking-changes/sync/__tests__/migration-finding-sync.service.test.ts @@ -122,7 +122,7 @@ describe('MigrationFindingSyncService', () => { workflowRepository.findExistingIds.mockImplementation(async (ids) => ids); ruleRegistry.getRules.mockReturnValue(rules('rule-a', 'rule-b')); findingRepository.listForWorkflows.mockResolvedValue([]); - findingRepository.listWorkflowIdsWithOpenFindings.mockResolvedValue([]); + findingRepository.listWorkflowIdsWithUnresolvedFindings.mockResolvedValue([]); ownerSuggestionService.suggestOwners.mockResolvedValue([]); breakingChangeService.detect.mockResolvedValue(detectionResult([])); @@ -472,14 +472,17 @@ describe('MigrationFindingSyncService', () => { describe('suggested owners', () => { it('stores a suggestion for each workflow in the batch with an open finding and clears the rest', async () => { givenWorkflows(3); - findingRepository.listWorkflowIdsWithOpenFindings.mockResolvedValue(['wf-0000', 'wf-0002']); + findingRepository.listWorkflowIdsWithUnresolvedFindings.mockResolvedValue([ + 'wf-0000', + 'wf-0002', + ]); ownerSuggestionService.suggestOwners.mockResolvedValue([ { workflowId: 'wf-0000', userId: 'user-1' }, ]); await service.sync(TARGET_VERSION); - expect(findingRepository.listWorkflowIdsWithOpenFindings).toHaveBeenCalledWith( + expect(findingRepository.listWorkflowIdsWithUnresolvedFindings).toHaveBeenCalledWith( TARGET_VERSION, ['wf-0000', 'wf-0001', 'wf-0002'], expect.anything(), @@ -690,14 +693,14 @@ describe('MigrationFindingSyncService', () => { }); it('refreshes the suggested owner of that workflow', async () => { - findingRepository.listWorkflowIdsWithOpenFindings.mockResolvedValue([WORKFLOW_ID]); + findingRepository.listWorkflowIdsWithUnresolvedFindings.mockResolvedValue([WORKFLOW_ID]); ownerSuggestionService.suggestOwners.mockResolvedValue([ { workflowId: WORKFLOW_ID, userId: 'user-1' }, ]); await service.syncWorkflow(WORKFLOW_ID); - expect(findingRepository.listWorkflowIdsWithOpenFindings).toHaveBeenCalledWith( + expect(findingRepository.listWorkflowIdsWithUnresolvedFindings).toHaveBeenCalledWith( REPORT_VERSION, [WORKFLOW_ID], expect.anything(), diff --git a/packages/cli/src/modules/breaking-changes/sync/migration-finding-diff.ts b/packages/cli/src/modules/breaking-changes/sync/migration-finding-diff.ts index 91c42297242..4da0cc48dec 100644 --- a/packages/cli/src/modules/breaking-changes/sync/migration-finding-diff.ts +++ b/packages/cli/src/modules/breaking-changes/sync/migration-finding-diff.ts @@ -1,4 +1,4 @@ -import type { BreakingChangeVersion } from '@n8n/api-types'; +import type { BreakingChangeVersion, MigrationFindingStatus } from '@n8n/api-types'; import type { MigrationFinding, @@ -39,14 +39,16 @@ const hitKey = (ruleId: string, workflowId: string) => `${ruleId}\u0000${workflo /** * Compares the scan hits for one batch of workflows with the stored findings. - * Only `open`, `wont_fix` and `fixed` rows take part. An `open` or `wont_fix` - * row without a hit is marked fixed, so a won't fix choice does not outlive - * the issue. A `fixed` row with a hit is reopened. Rows in any other status - * stay as they are. A pair listed in `unknown` is never inserted, marked fixed, - * or reopened: a missing hit there means the pair was not decided, not that the - * workflow is clean. The other rules on the same workflow are handled as usual. - * TODO(CAT-4710): handle `notified` rows once triage can set them. + * Only `open`, `notified`, `wont_fix` and `fixed` rows take part. An `open`, + * `notified` or `wont_fix` row without a hit is marked fixed, so a won't fix + * choice does not outlive the issue. A `fixed` row with a hit is reopened. Rows + * in any other status stay as they are. A pair listed in `unknown` is never + * inserted, marked fixed, or reopened: a missing hit there means the pair was + * not decided, not that the workflow is clean. The other rules on the same + * workflow are handled as usual. */ +const RESOLVABLE_STATUSES = new Set(['open', 'notified', 'wont_fix']); + export function diffMigrationFindings(input: MigrationFindingDiffInput): MigrationFindingDiff { const { targetVersion, hits, existing, unknown = [] } = input; const batchWorkflowIds = new Set(input.workflowIds); @@ -69,9 +71,7 @@ export function diffMigrationFindings(input: MigrationFindingDiffInput): Migrati if (unknownKeys.has(key)) continue; const isHit = hitKeys.has(key); - if ((row.status === 'open' || row.status === 'wont_fix') && !isHit) { - diff.toMarkFixed.push(row.id); - } + if (RESOLVABLE_STATUSES.has(row.status) && !isHit) diff.toMarkFixed.push(row.id); if (row.status === 'fixed' && isHit) diff.toReopen.push(row.id); } diff --git a/packages/cli/src/modules/breaking-changes/sync/migration-finding-sync.service.ts b/packages/cli/src/modules/breaking-changes/sync/migration-finding-sync.service.ts index ab8332bb990..2541f7626f0 100644 --- a/packages/cli/src/modules/breaking-changes/sync/migration-finding-sync.service.ts +++ b/packages/cli/src/modules/breaking-changes/sync/migration-finding-sync.service.ts @@ -226,7 +226,7 @@ export class MigrationFindingSyncService { workflowIds: string[], ): Promise { try { - const affectedIds = await this.findingRepository.listWorkflowIdsWithOpenFindings( + const affectedIds = await this.findingRepository.listWorkflowIdsWithUnresolvedFindings( targetVersion, workflowIds, {}, diff --git a/packages/cli/src/modules/chat-hub/__tests__/chat-hub-agent.service.test.ts b/packages/cli/src/modules/chat-hub/__tests__/chat-hub-agent.service.test.ts index 09abac33f19..b10186d1eca 100644 --- a/packages/cli/src/modules/chat-hub/__tests__/chat-hub-agent.service.test.ts +++ b/packages/cli/src/modules/chat-hub/__tests__/chat-hub-agent.service.test.ts @@ -1,6 +1,7 @@ import type { ChatHubAgentKnowledgeItem } from '@n8n/api-types'; import type { Logger } from '@n8n/backend-common'; import type { User } from '@n8n/db'; +import type { EntityManager } from '@n8n/typeorm'; import type { IRunExecutionData, IWorkflowBase } from 'n8n-workflow'; import { v4 as uuid } from 'uuid'; import { mock } from 'vitest-mock-extended'; @@ -80,6 +81,7 @@ describe('ChatHubAgentService', () => { const dynamicNodeParametersService = mock(); const toolService = mock(); const mockUser = mock({ id: mockUserId }); + const mockTrx = mock(); let service: ChatHubAgentService; @@ -99,6 +101,11 @@ describe('ChatHubAgentService', () => { dynamicNodeParametersService, toolService, ); + + agentRepository.runInTransaction.mockImplementation( + async (ctx: unknown, fn: (em: never, ctx: unknown) => Promise) => + await fn(mockTrx as never, ctx), + ); }); describe('createAgent', () => { @@ -129,6 +136,7 @@ describe('ChatHubAgentService', () => { model: 'gpt-4', ownerId: mockUserId, }), + mockTrx, ); expect(dto.id).toBe(agent.id); expect(dto.name).toBe('Test Agent'); @@ -153,6 +161,7 @@ describe('ChatHubAgentService', () => { expect(agentRepository.createAgent).toHaveBeenCalledWith( expect.objectContaining({ description: null }), + mockTrx, ); }); @@ -171,10 +180,34 @@ describe('ChatHubAgentService', () => { toolIds, }); - expect(toolService.setAgentTools).toHaveBeenCalledWith(expect.any(String), toolIds); + expect(toolService.setAgentTools).toHaveBeenCalledWith( + expect.any(String), + mockUserId, + toolIds, + mockTrx, + ); expect(dto.toolIds).toEqual(toolIds); }); + it('should create the agent and set its tools in one transaction', async () => { + agentRepository.createAgent.mockResolvedValue(makeAgent()); + toolService.setAgentTools.mockRejectedValue(new NotFoundError('Chat hub tool not found')); + + await expect( + service.createAgent(mockUser, { + name: 'Test Agent', + systemPrompt: 'You are helpful', + icon: { type: 'emoji', value: '🤖' }, + credentialId: 'cred-1', + provider: 'openai', + model: 'gpt-4', + toolIds: [uuid()], + }), + ).rejects.toThrow(NotFoundError); + + expect(agentRepository.createAgent).toHaveBeenCalledWith(expect.anything(), mockTrx); + }); + it('should not call setAgentTools when toolIds is empty', async () => { const agent = makeAgent(); agentRepository.createAgent.mockResolvedValue(agent); @@ -210,6 +243,7 @@ describe('ChatHubAgentService', () => { expect(agentRepository.createAgent).toHaveBeenCalledWith( expect.objectContaining({ suggestedPrompts: prompts }), + mockTrx, ); expect(dto.suggestedPrompts).toEqual(prompts); }); @@ -230,6 +264,7 @@ describe('ChatHubAgentService', () => { expect(agentRepository.createAgent).toHaveBeenCalledWith( expect.objectContaining({ suggestedPrompts: [] }), + mockTrx, ); }); }); @@ -273,7 +308,11 @@ describe('ChatHubAgentService', () => { await service.updateAgent(agent.id, mockUser, { name: 'New Name' }); - expect(agentRepository.updateAgent).toHaveBeenCalledWith(agent.id, { name: 'New Name' }); + expect(agentRepository.updateAgent).toHaveBeenCalledWith( + agent.id, + { name: 'New Name' }, + mockTrx, + ); }); it('should update multiple fields at once', async () => { @@ -294,11 +333,15 @@ describe('ChatHubAgentService', () => { systemPrompt: 'New prompt', }); - expect(agentRepository.updateAgent).toHaveBeenCalledWith(agent.id, { - name: 'Updated', - description: 'New desc', - systemPrompt: 'New prompt', - }); + expect(agentRepository.updateAgent).toHaveBeenCalledWith( + agent.id, + { + name: 'Updated', + description: 'New desc', + systemPrompt: 'New prompt', + }, + mockTrx, + ); expect(dto.name).toBe('Updated'); }); @@ -311,7 +354,24 @@ describe('ChatHubAgentService', () => { await service.updateAgent(agent.id, mockUser, { toolIds }); - expect(toolService.setAgentTools).toHaveBeenCalledWith(agent.id, toolIds); + expect(toolService.setAgentTools).toHaveBeenCalledWith( + agent.id, + mockUserId, + toolIds, + mockTrx, + ); + }); + + it('should not update the agent fields when the tools are rejected', async () => { + const agent = makeAgent(); + agentRepository.getOneById.mockResolvedValue(agent); + toolService.setAgentTools.mockRejectedValue(new NotFoundError('Chat hub tool not found')); + + await expect( + service.updateAgent(agent.id, mockUser, { name: 'New Name', toolIds: [uuid()] }), + ).rejects.toThrow(NotFoundError); + + expect(agentRepository.updateAgent).not.toHaveBeenCalled(); }); it('should not set tools when toolIds is not provided', async () => { @@ -339,6 +399,7 @@ describe('ChatHubAgentService', () => { expect(agentRepository.updateAgent).toHaveBeenCalledWith( agent.id, expect.objectContaining({ suggestedPrompts: prompts }), + mockTrx, ); expect(dto.suggestedPrompts).toEqual(prompts); }); @@ -354,6 +415,7 @@ describe('ChatHubAgentService', () => { expect(agentRepository.updateAgent).toHaveBeenCalledWith( agent.id, expect.not.objectContaining({ suggestedPrompts: expect.anything() }), + mockTrx, ); }); }); diff --git a/packages/cli/src/modules/chat-hub/__tests__/chat-hub-tool-references.integration.test.ts b/packages/cli/src/modules/chat-hub/__tests__/chat-hub-tool-references.integration.test.ts new file mode 100644 index 00000000000..8689af4d153 --- /dev/null +++ b/packages/cli/src/modules/chat-hub/__tests__/chat-hub-tool-references.integration.test.ts @@ -0,0 +1,307 @@ +import { mockInstance, testDb, testModules } from '@n8n/backend-test-utils'; +import type { User } from '@n8n/db'; +import { Container } from '@n8n/di'; +import { NotFoundError } from '@n8n/errors'; +import { BinaryDataService } from 'n8n-core'; +import type { INode } from 'n8n-workflow'; + +import { saveCredential } from '@test-integration/db/credentials'; +import { createMember } from '@test-integration/db/users'; + +import { WorkflowExecutionService } from '../../../workflows/workflow-execution.service'; +import { ChatHubAgent } from '../chat-hub-agent.entity'; +import { ChatHubAgentRepository } from '../chat-hub-agent.repository'; +import { ChatHubAgentService } from '../chat-hub-agent.service'; +import { ChatHubCredentialsService } from '../chat-hub-credentials.service'; +import { ChatHubSession } from '../chat-hub-session.entity'; +import type { ChatHubTool } from '../chat-hub-tool.entity'; +import { ChatHubToolRepository } from '../chat-hub-tool.repository'; +import { ChatHubToolService } from '../chat-hub-tool.service'; +import { ChatHubService } from '../chat-hub.service'; +import { ChatHubSessionRepository } from '../chat-session.repository'; + +mockInstance(BinaryDataService); +mockInstance(WorkflowExecutionService); +mockInstance(ChatHubCredentialsService); + +beforeAll(async () => { + await testModules.loadModules(['chat-hub']); + await testDb.init(); +}); + +beforeEach(async () => { + await testDb.truncate([ + 'ChatHubSession', + 'ChatHubAgent', + 'ChatHubTool', + 'SharedCredentials', + 'CredentialsEntity', + ]); +}); + +afterAll(async () => { + await testDb.terminate(); +}); + +describe('chat hub tool references', () => { + let chatHubService: ChatHubService; + let agentService: ChatHubAgentService; + let toolService: ChatHubToolService; + let toolRepository: ChatHubToolRepository; + let sessionRepository: ChatHubSessionRepository; + let agentRepository: ChatHubAgentRepository; + + let owner: User; + let otherUser: User; + + beforeAll(() => { + chatHubService = Container.get(ChatHubService); + agentService = Container.get(ChatHubAgentService); + toolService = Container.get(ChatHubToolService); + toolRepository = Container.get(ChatHubToolRepository); + sessionRepository = Container.get(ChatHubSessionRepository); + agentRepository = Container.get(ChatHubAgentRepository); + }); + + beforeEach(async () => { + owner = await createMember(); + otherUser = await createMember(); + }); + + async function createTool(ownerId: string) { + const id = crypto.randomUUID(); + const definition: INode = { + id, + name: `Tool ${id}`, + type: 'n8n-nodes-base.httpRequestTool', + typeVersion: 4.4, + position: [0, 0], + parameters: {}, + }; + return await toolRepository.createTool({ + id, + name: definition.name, + type: definition.type, + typeVersion: definition.typeVersion, + ownerId, + definition, + enabled: true, + }); + } + + async function createSession(ownerId: string) { + return await sessionRepository.createChatSession({ + id: crypto.randomUUID(), + ownerId, + title: 'session', + lastMessageAt: new Date(), + }); + } + + async function createAgent(ownerId: string) { + return await agentRepository.createAgent({ + id: crypto.randomUUID(), + name: 'agent', + systemPrompt: 'prompt', + ownerId, + credentialId: null, + provider: 'openai', + model: 'gpt-4', + files: [], + }); + } + + /** Reads every stored link row, without the owner filter that the services apply */ + async function storedLinkIds(entity: typeof ChatHubSession | typeof ChatHubAgent, id: string) { + const tools = await toolRepository.manager + .createQueryBuilder() + .relation(entity, 'tools') + .of(id) + .loadMany(); + return tools.map((t) => t.id).sort(); + } + + describe('updateSession', () => { + it('should set tools that the user owns', async () => { + const session = await createSession(owner.id); + const tool = await createTool(owner.id); + + await chatHubService.updateSession(owner, session.id, { toolIds: [tool.id] }); + + expect(await toolService.getToolIdsForSession(session.id)).toEqual([tool.id]); + }); + + it('should reject tools that another user owns and keep the session unchanged', async () => { + const session = await createSession(owner.id); + const ownTool = await createTool(owner.id); + const foreignTool = await createTool(otherUser.id); + await chatHubService.updateSession(owner, session.id, { toolIds: [ownTool.id] }); + + await expect( + chatHubService.updateSession(owner, session.id, { + title: 'renamed', + toolIds: [ownTool.id, foreignTool.id], + }), + ).rejects.toThrow(NotFoundError); + + expect(await toolService.getToolIdsForSession(session.id)).toEqual([ownTool.id]); + const stored = await sessionRepository.findOneByOrFail({ id: session.id }); + expect(stored.title).toBe('session'); + }); + + it('should accept duplicate IDs of an owned tool', async () => { + const session = await createSession(owner.id); + const tool = await createTool(owner.id); + + await chatHubService.updateSession(owner, session.id, { toolIds: [tool.id, tool.id] }); + + expect(await toolService.getToolIdsForSession(session.id)).toEqual([tool.id]); + }); + + it('should keep the tool links unchanged when the session update fails', async () => { + const session = await createSession(owner.id); + const tool = await createTool(owner.id); + + await expect( + chatHubService.updateSession(owner, session.id, { + credentialId: crypto.randomUUID(), + toolIds: [tool.id], + }), + ).rejects.toThrow(); + + expect(await storedLinkIds(ChatHubSession, session.id)).toEqual([]); + }); + + it('should only return owned tool IDs and remove other links on the next save', async () => { + const session = await createSession(owner.id); + const ownTool = await createTool(owner.id); + const foreignTool = await createTool(otherUser.id); + // Write the link rows directly to simulate rows stored before validation existed + await toolRepository.setSessionTools(session.id, [ownTool.id, foreignTool.id]); + + const { session: dto } = await chatHubService.getConversation(owner.id, session.id); + expect(dto.toolIds).toEqual([ownTool.id]); + + await chatHubService.updateSession(owner, session.id, { toolIds: dto.toolIds }); + + expect(await storedLinkIds(ChatHubSession, session.id)).toEqual([ownTool.id]); + }); + }); + + describe('createAgent', () => { + async function agentRequest() { + const credential = await saveCredential( + { name: 'OpenAI', type: 'openAiApi', data: { apiKey: 'test-api-key' } }, + { user: owner, role: 'credential:owner' }, + ); + return { + name: 'agent', + systemPrompt: 'prompt', + icon: { type: 'emoji' as const, value: '🤖' }, + credentialId: credential.id, + provider: 'openai' as const, + model: 'gpt-4', + }; + } + + it('should set tools that the user owns', async () => { + const tool = await createTool(owner.id); + + const agent = await agentService.createAgent(owner, { + ...(await agentRequest()), + toolIds: [tool.id], + }); + + expect(await toolService.getToolIdsForAgent(agent.id)).toEqual([tool.id]); + }); + + it('should reject tools that another user owns and not create the agent', async () => { + const foreignTool = await createTool(otherUser.id); + + await expect( + agentService.createAgent(owner, { ...(await agentRequest()), toolIds: [foreignTool.id] }), + ).rejects.toThrow(NotFoundError); + + expect(await agentRepository.getManyByUserId(owner.id)).toHaveLength(0); + }); + + it('should return each tool ID once when the request repeats an ID', async () => { + const tool = await createTool(owner.id); + + const agent = await agentService.createAgent(owner, { + ...(await agentRequest()), + toolIds: [tool.id, tool.id], + }); + + expect(agent.toolIds).toEqual([tool.id]); + }); + }); + + describe('updateAgent', () => { + it('should reject tools that another user owns and keep the agent unchanged', async () => { + const agent = await createAgent(owner.id); + const foreignTool = await createTool(otherUser.id); + + await expect( + agentService.updateAgent(agent.id, owner, { name: 'renamed', toolIds: [foreignTool.id] }), + ).rejects.toThrow(NotFoundError); + + expect(await toolService.getToolIdsForAgent(agent.id)).toEqual([]); + const stored = await agentRepository.findOneByOrFail({ id: agent.id }); + expect(stored.name).toBe('agent'); + }); + + it('should keep the tool links unchanged when the agent update fails', async () => { + const agent = await createAgent(owner.id); + const tool = await createTool(owner.id); + + await expect( + agentService.updateAgent(agent.id, owner, { + credentialId: crypto.randomUUID(), + toolIds: [tool.id], + }), + ).rejects.toThrow(); + + expect(await storedLinkIds(ChatHubAgent, agent.id)).toEqual([]); + }); + + it('should only return owned tool IDs and remove other links on the next save', async () => { + const agent = await createAgent(owner.id); + const ownTool = await createTool(owner.id); + const foreignTool = await createTool(otherUser.id); + await toolRepository.setAgentTools(agent.id, [ownTool.id, foreignTool.id]); + + const dto = await agentService.getAgentByIdAsDto(agent.id, owner.id); + expect(dto.toolIds).toEqual([ownTool.id]); + + await agentService.updateAgent(agent.id, owner, { toolIds: dto.toolIds }); + + expect(await storedLinkIds(ChatHubAgent, agent.id)).toEqual([ownTool.id]); + }); + }); + + describe('tool definitions at run time', () => { + it('should only return session tools that the session owner owns', async () => { + const session = await createSession(owner.id); + const ownTool = await createTool(owner.id); + const foreignTool = await createTool(otherUser.id); + // Write the link rows directly to simulate rows stored before validation existed + await toolRepository.setSessionTools(session.id, [ownTool.id, foreignTool.id]); + + const definitions = await toolService.getToolDefinitionsForSession(session.id); + + expect(definitions.map((d) => d.id)).toEqual([ownTool.id]); + }); + + it('should only return agent tools that the agent owner owns', async () => { + const agent = await createAgent(owner.id); + const ownTool = await createTool(owner.id); + const foreignTool = await createTool(otherUser.id); + await toolRepository.setAgentTools(agent.id, [ownTool.id, foreignTool.id]); + + const definitions = await toolService.getToolDefinitionsForAgent(agent.id); + + expect(definitions.map((d) => d.id)).toEqual([ownTool.id]); + }); + }); +}); diff --git a/packages/cli/src/modules/chat-hub/__tests__/chat-hub-tool.service.test.ts b/packages/cli/src/modules/chat-hub/__tests__/chat-hub-tool.service.test.ts index ed464b82a84..abf961c3db4 100644 --- a/packages/cli/src/modules/chat-hub/__tests__/chat-hub-tool.service.test.ts +++ b/packages/cli/src/modules/chat-hub/__tests__/chat-hub-tool.service.test.ts @@ -136,6 +136,85 @@ describe('ChatHubToolService', () => { }); }); + describe('setSessionTools', () => { + it('should set tools that the user owns', async () => { + const tool = makeTool(); + chatToolRepository.getByIds.mockResolvedValue([tool]); + + await service.setSessionTools(mockSessionId, mockUserId, [tool.id]); + + expect(chatToolRepository.setSessionTools).toHaveBeenCalledWith( + mockSessionId, + [tool.id], + undefined, + ); + }); + + it('should not set tools when the user does not own one of them', async () => { + chatToolRepository.getByIds.mockResolvedValue([]); + + await expect(service.setSessionTools(mockSessionId, mockUserId, [uuid()])).rejects.toThrow( + NotFoundError, + ); + expect(chatToolRepository.setSessionTools).not.toHaveBeenCalled(); + }); + + it('should not set tools when the user owns only some of them', async () => { + const ownTool = makeTool(); + chatToolRepository.getByIds.mockResolvedValue([ownTool]); + + await expect( + service.setSessionTools(mockSessionId, mockUserId, [ownTool.id, uuid()]), + ).rejects.toThrow(NotFoundError); + expect(chatToolRepository.setSessionTools).not.toHaveBeenCalled(); + }); + + it('should check and store each tool once when IDs repeat', async () => { + const tool = makeTool(); + chatToolRepository.getByIds.mockResolvedValue([tool]); + + await service.setSessionTools(mockSessionId, mockUserId, [tool.id, tool.id]); + + expect(chatToolRepository.getByIds).toHaveBeenCalledWith([tool.id], mockUserId, undefined); + expect(chatToolRepository.setSessionTools).toHaveBeenCalledWith( + mockSessionId, + [tool.id], + undefined, + ); + }); + + it('should clear the tools without a lookup when the list is empty', async () => { + await service.setSessionTools(mockSessionId, mockUserId, []); + + expect(chatToolRepository.getByIds).not.toHaveBeenCalled(); + expect(chatToolRepository.setSessionTools).toHaveBeenCalledWith(mockSessionId, [], undefined); + }); + }); + + describe('setAgentTools', () => { + it('should set tools that the user owns', async () => { + const tool = makeTool(); + chatToolRepository.getByIds.mockResolvedValue([tool]); + + await service.setAgentTools(mockAgentId, mockUserId, [tool.id]); + + expect(chatToolRepository.setAgentTools).toHaveBeenCalledWith( + mockAgentId, + [tool.id], + undefined, + ); + }); + + it('should not set tools when the user does not own one of them', async () => { + chatToolRepository.getByIds.mockResolvedValue([]); + + await expect(service.setAgentTools(mockAgentId, mockUserId, [uuid()])).rejects.toThrow( + NotFoundError, + ); + expect(chatToolRepository.setAgentTools).not.toHaveBeenCalled(); + }); + }); + const deprecatedCodeTool: INode = { ...mockDefinition, type: '@n8n/n8n-nodes-langchain.code', diff --git a/packages/cli/src/modules/chat-hub/__tests__/chat-hub-workflow.service.test.ts b/packages/cli/src/modules/chat-hub/__tests__/chat-hub-workflow.service.test.ts index 86d98215bf4..19617de66de 100644 --- a/packages/cli/src/modules/chat-hub/__tests__/chat-hub-workflow.service.test.ts +++ b/packages/cli/src/modules/chat-hub/__tests__/chat-hub-workflow.service.test.ts @@ -1,6 +1,7 @@ +import type { ChatHubConversationModel, ChatProviderSettingsDto } from '@n8n/api-types'; import type { PolicyCleared } from '@n8n/decorators'; import type { Logger } from '@n8n/backend-common'; -import type { WorkflowRepository, SharedWorkflowRepository, User } from '@n8n/db'; +import type { Project, WorkflowRepository, SharedWorkflowRepository, User } from '@n8n/db'; import type { EntityManager } from '@n8n/typeorm'; import type { Cipher, BinaryDataService } from 'n8n-core'; import { type IBinaryData, type INode, CHAT_TRIGGER_NODE_TYPE } from 'n8n-workflow'; @@ -1409,7 +1410,7 @@ describe('ChatHubWorkflowService', () => { vi.spyOn(serviceWithRepo, 'getSystemMessageMetadata').mockReturnValue('__metadata__'); const result = await serviceWithRepo.prepareReplyWorkflow( - { id: 'user-123' } as User, + { id: 'user-123', role: { slug: 'global:member' } } as User, 'session-456' as any, {}, { provider: 'custom-agent', agentId: 'agent-1' } as any, @@ -1508,4 +1509,78 @@ __metadata__" `); }); }); + + describe('tool type authorization', () => { + const toolNode = (name: string, type: string): INode => ({ + id: `id-${name}`, + name, + type, + typeVersion: 1, + position: [0, 0], + parameters: {}, + }); + + const storedTools = [ + toolNode('Shell', 'n8n-nodes-base.executeCommandTool'), + toolNode('Code', '@n8n/n8n-nodes-langchain.toolCode'), + toolNode('Slack', 'n8n-nodes-base.slackTool'), + ]; + + beforeEach(() => { + chatHubSettingsService.ensureModelIsAllowed.mockResolvedValue(undefined); + chatHubSettingsService.getProviderSettings.mockResolvedValue(mock()); + chatHubSettingsService.getSemanticSearchOptions.mockResolvedValue(null); + chatHubCredentialsService.findPersonalProject.mockResolvedValue( + mock({ id: 'project-789' }), + ); + }); + + async function getToolNodeNames(user: User, model: ChatHubConversationModel) { + const result = await service.prepareReplyWorkflow( + user, + 'session-456', + { openAiApi: { id: 'cred-1', name: '' } }, + model, + [], + 'Hello', + storedTools, + [], + 'UTC', + {}, + defaultExecutionMetadata, + ); + const toolNames = new Set(storedTools.map((t) => t.name)); + return result.workflowData.nodes.map((n) => n.name).filter((name) => toolNames.has(name)); + } + + const chatUser = { id: 'user-123', role: { slug: 'global:chatUser' } } as User; + const member = { id: 'user-123', role: { slug: 'global:member' } } as User; + const baseModel: ChatHubConversationModel = { provider: 'openai', model: 'gpt-4' }; + + it('should drop stored tools that a chat user is not allowed to run', async () => { + expect(await getToolNodeNames(chatUser, baseModel)).toEqual(['Slack']); + }); + + it('should keep all stored tools for a member', async () => { + expect(await getToolNodeNames(member, baseModel)).toEqual(['Shell', 'Code', 'Slack']); + }); + + it('should drop blocked tools from a chat user agent', async () => { + chatHubAgentRepository.getOneById.mockResolvedValue( + mock({ + id: 'agent-1', + provider: 'openai', + model: 'gpt-4', + credentialId: 'cred-1', + systemPrompt: '', + files: [], + }), + ); + chatHubToolService.getToolDefinitionsForAgent.mockResolvedValue(storedTools); + + expect( + await getToolNodeNames(chatUser, { provider: 'custom-agent', agentId: 'agent-1' }), + ).toEqual(['Slack']); + }); + }); }); diff --git a/packages/cli/src/modules/chat-hub/__tests__/chat-hub.controller.test.ts b/packages/cli/src/modules/chat-hub/__tests__/chat-hub.controller.test.ts index fd04514a378..366653849f7 100644 --- a/packages/cli/src/modules/chat-hub/__tests__/chat-hub.controller.test.ts +++ b/packages/cli/src/modules/chat-hub/__tests__/chat-hub.controller.test.ts @@ -1,11 +1,15 @@ +import type { ChatHubCreateToolRequest, ChatHubUpdateToolRequest } from '@n8n/api-types'; import type { ModuleRegistry } from '@n8n/backend-common'; +import type { AuthenticatedRequest } from '@n8n/db'; import type { ModuleSettings } from '@n8n/decorators'; import type { NextFunction, Request, Response } from 'express'; +import type { INode } from 'n8n-workflow'; import { mock } from 'vitest-mock-extended'; -import { ForbiddenError } from '@n8n/errors'; +import { BadRequestError, ForbiddenError } from '@n8n/errors'; import { sendErrorResponse } from '@/response-helper'; +import type { ChatHubToolService } from '../chat-hub-tool.service'; import { ChatHubController } from '../chat-hub.controller'; vi.mock('@/response-helper'); @@ -13,7 +17,15 @@ vi.mock('@/response-helper'); describe('ChatHubController', () => { const settingsMap = new Map(); const moduleRegistry = { settings: settingsMap } as unknown as ModuleRegistry; - const controller = new ChatHubController(mock(), mock(), mock(), mock(), mock(), moduleRegistry); + const chatToolService = mock(); + const controller = new ChatHubController( + mock(), + mock(), + mock(), + chatToolService, + mock(), + moduleRegistry, + ); const req = mock(); const res = mock(); @@ -51,4 +63,81 @@ describe('ChatHubController', () => { expect(sendErrorResponse).toHaveBeenCalledWith(res, expect.any(ForbiddenError)); }); }); + + describe('tool type authorization', () => { + const chatUserReq = mock({ + user: { id: 'chat-user', role: { slug: 'global:chatUser' } }, + }); + const memberReq = mock({ + user: { id: 'member', role: { slug: 'global:member' } }, + }); + + const toolDefinition = (type: string): INode => ({ + id: '00000000-0000-4000-8000-000000000001', + name: 'Tool', + type, + typeVersion: 1, + position: [0, 0], + parameters: {}, + }); + + const createPayload = (type: string) => + ({ definition: toolDefinition(type) }) as ChatHubCreateToolRequest; + const updatePayload = (type: string) => + ({ definition: toolDefinition(type) }) as ChatHubUpdateToolRequest; + + beforeEach(() => { + chatToolService.createTool.mockResolvedValue(mock({ definition: toolDefinition('x') })); + chatToolService.updateTool.mockResolvedValue(mock({ definition: toolDefinition('x') })); + }); + + it.each([ + 'n8n-nodes-base.executeCommandTool', + 'n8n-nodes-base.gitTool', + '@n8n/n8n-nodes-langchain.toolCode', + 'n8n-nodes-base.messageAnAgentTool', + ])('should reject creating a %s tool for a chat user', async (type) => { + await expect(controller.createTool(chatUserReq, res, createPayload(type))).rejects.toThrow( + BadRequestError, + ); + expect(chatToolService.createTool).not.toHaveBeenCalled(); + }); + + it('should reject updating a tool to a blocked type for a chat user', async () => { + await expect( + controller.updateTool( + chatUserReq, + res, + 'tool-1', + updatePayload('n8n-nodes-base.executeCommandTool'), + ), + ).rejects.toThrow(BadRequestError); + expect(chatToolService.updateTool).not.toHaveBeenCalled(); + }); + + it.each(['n8n-nodes-base.slackTool', 'n8n-nodes-base.httpRequestTool'])( + 'should allow creating a %s tool for a chat user', + async (type) => { + await controller.createTool(chatUserReq, res, createPayload(type)); + + expect(chatToolService.createTool).toHaveBeenCalled(); + }, + ); + + it('should allow creating a Code tool for a member', async () => { + await controller.createTool( + memberReq, + res, + createPayload('@n8n/n8n-nodes-langchain.toolCode'), + ); + + expect(chatToolService.createTool).toHaveBeenCalled(); + }); + + it('should reject creating a Chat tool for a member', async () => { + await expect( + controller.createTool(memberReq, res, createPayload('@n8n/n8n-nodes-langchain.chatTool')), + ).rejects.toThrow(BadRequestError); + }); + }); }); diff --git a/packages/cli/src/modules/chat-hub/chat-hub-agent.service.ts b/packages/cli/src/modules/chat-hub/chat-hub-agent.service.ts index 49e8580ed04..4b9f6e39bea 100644 --- a/packages/cli/src/modules/chat-hub/chat-hub-agent.service.ts +++ b/packages/cli/src/modules/chat-hub/chat-hub-agent.service.ts @@ -98,26 +98,34 @@ export class ChatHubAgentService { const id = uuidv4(); - const agent = await this.chatAgentRepository.createAgent({ - id, - name: data.name, - description: data.description ?? null, - icon: data.icon, - suggestedPrompts: data.suggestedPrompts ?? [], - systemPrompt: data.systemPrompt, - ownerId: user.id, - credentialId: data.credentialId, - provider: data.provider, - model: data.model, - files: [], + // One transaction: a rejected tool removes the new agent again + const agent = await this.chatAgentRepository.runInTransaction({}, async (trx) => { + const created = await this.chatAgentRepository.createAgent( + { + id, + name: data.name, + description: data.description ?? null, + icon: data.icon, + suggestedPrompts: data.suggestedPrompts ?? [], + systemPrompt: data.systemPrompt, + ownerId: user.id, + credentialId: data.credentialId, + provider: data.provider, + model: data.model, + files: [], + }, + trx, + ); + + if (data.toolIds.length > 0) { + await this.chatHubToolService.setAgentTools(id, user.id, data.toolIds, trx); + } + + return created; }); - if (data.toolIds.length > 0) { - await this.chatHubToolService.setAgentTools(id, data.toolIds); - } - this.logger.debug(`Chat agent created: ${id} by user ${user.id}`); - return this.toDto(agent, data.toolIds); + return this.toDto(agent, [...new Set(data.toolIds)]); } async updateAgent( @@ -148,11 +156,14 @@ export class ChatHubAgentService { if (updates.provider !== undefined) updateData.provider = updates.provider; if (updates.model !== undefined) updateData.model = updates.model ?? null; - const agent = await this.chatAgentRepository.updateAgent(id, updateData); - - if (updates.toolIds !== undefined) { - await this.chatHubToolService.setAgentTools(id, updates.toolIds); - } + // One transaction: a rejected tool or a failed field update leaves the agent unchanged + const { toolIds: newToolIds } = updates; + const agent = await this.chatAgentRepository.runInTransaction({}, async (trx) => { + if (newToolIds !== undefined) { + await this.chatHubToolService.setAgentTools(id, user.id, newToolIds, trx); + } + return await this.chatAgentRepository.updateAgent(id, updateData, trx); + }); this.logger.debug(`Chat agent updated: ${id} by user ${user.id}`); const toolIds = await this.chatHubToolService.getToolIdsForAgent(agent.id); diff --git a/packages/cli/src/modules/chat-hub/chat-hub-tool.repository.ts b/packages/cli/src/modules/chat-hub/chat-hub-tool.repository.ts index a357ae04971..50990b799f1 100644 --- a/packages/cli/src/modules/chat-hub/chat-hub-tool.repository.ts +++ b/packages/cli/src/modules/chat-hub/chat-hub-tool.repository.ts @@ -69,7 +69,7 @@ export class ChatHubToolRepository extends Repository { const em = trx ?? this.manager; const session = await em .createQueryBuilder(ChatHubSession, 'session') - .innerJoinAndSelect('session.tools', 'tool') + .innerJoinAndSelect('session.tools', 'tool', 'tool.ownerId = session.ownerId') .where('session.id = :sessionId', { sessionId }) .orderBy('tool.createdAt', 'ASC') .getOne(); @@ -80,7 +80,7 @@ export class ChatHubToolRepository extends Repository { const em = trx ?? this.manager; const agent = await em .createQueryBuilder(ChatHubAgent, 'agent') - .innerJoinAndSelect('agent.tools', 'tool') + .innerJoinAndSelect('agent.tools', 'tool', 'tool.ownerId = agent.ownerId') .where('agent.id = :agentId', { agentId }) .orderBy('tool.createdAt', 'ASC') .getOne(); @@ -91,7 +91,7 @@ export class ChatHubToolRepository extends Repository { const em = trx ?? this.manager; const rows = await em .createQueryBuilder(ChatHubSession, 'session') - .innerJoin('session.tools', 'tool') + .innerJoin('session.tools', 'tool', 'tool.ownerId = session.ownerId') .select('tool.id', 'toolId') .where('session.id = :sessionId', { sessionId }) .getRawMany<{ toolId: string }>(); @@ -102,7 +102,7 @@ export class ChatHubToolRepository extends Repository { const em = trx ?? this.manager; const rows = await em .createQueryBuilder(ChatHubAgent, 'agent') - .innerJoin('agent.tools', 'tool') + .innerJoin('agent.tools', 'tool', 'tool.ownerId = agent.ownerId') .select('tool.id', 'toolId') .where('agent.id = :agentId', { agentId }) .getRawMany<{ toolId: string }>(); @@ -110,22 +110,28 @@ export class ChatHubToolRepository extends Repository { } async setSessionTools(sessionId: string, toolIds: string[], trx?: EntityManager): Promise { - const em = trx ?? this.manager; - const currentToolIds = await this.getToolIdsForSession(sessionId, em); - await em - .createQueryBuilder() - .relation(ChatHubSession, 'tools') - .of(sessionId) - .addAndRemove(toolIds, currentToolIds); + await this.replaceLinkedTools(ChatHubSession, sessionId, toolIds, trx ?? this.manager); } async setAgentTools(agentId: string, toolIds: string[], trx?: EntityManager): Promise { - const em = trx ?? this.manager; - const currentToolIds = await this.getToolIdsForAgent(agentId, em); - await em - .createQueryBuilder() - .relation(ChatHubAgent, 'tools') - .of(agentId) - .addAndRemove(toolIds, currentToolIds); + await this.replaceLinkedTools(ChatHubAgent, agentId, toolIds, trx ?? this.manager); + } + + /** + * Replaces every link row, including rows to tools that the owner does not own, + * so that a save also removes those rows. + */ + private async replaceLinkedTools( + entity: typeof ChatHubSession | typeof ChatHubAgent, + id: string, + toolIds: string[], + em: EntityManager, + ): Promise { + const relation = em.createQueryBuilder().relation(entity, 'tools').of(id); + const currentTools = await relation.loadMany(); + await relation.addAndRemove( + toolIds, + currentTools.map((t) => t.id), + ); } } diff --git a/packages/cli/src/modules/chat-hub/chat-hub-tool.service.ts b/packages/cli/src/modules/chat-hub/chat-hub-tool.service.ts index 4291a553a88..85ae6018783 100644 --- a/packages/cli/src/modules/chat-hub/chat-hub-tool.service.ts +++ b/packages/cli/src/modules/chat-hub/chat-hub-tool.service.ts @@ -53,12 +53,41 @@ export class ChatHubToolService { return await this.chatToolRepository.getToolIdsForAgent(agentId, trx); } - async setSessionTools(sessionId: string, toolIds: string[], trx?: EntityManager): Promise { - await this.chatToolRepository.setSessionTools(sessionId, toolIds, trx); + async setSessionTools( + sessionId: string, + ownerId: string, + toolIds: string[], + trx?: EntityManager, + ): Promise { + await this.ensureToolsOwnedBy(ownerId, toolIds, trx); + await this.chatToolRepository.setSessionTools(sessionId, [...new Set(toolIds)], trx); } - async setAgentTools(agentId: string, toolIds: string[], trx?: EntityManager): Promise { - await this.chatToolRepository.setAgentTools(agentId, toolIds, trx); + async setAgentTools( + agentId: string, + ownerId: string, + toolIds: string[], + trx?: EntityManager, + ): Promise { + await this.ensureToolsOwnedBy(ownerId, toolIds, trx); + await this.chatToolRepository.setAgentTools(agentId, [...new Set(toolIds)], trx); + } + + /** + * Throws `NotFoundError` unless the user owns every tool in `toolIds`. + */ + private async ensureToolsOwnedBy( + userId: string, + toolIds: string[], + trx?: EntityManager, + ): Promise { + const uniqueIds = [...new Set(toolIds)]; + if (uniqueIds.length === 0) return; + + const ownedTools = await this.chatToolRepository.getByIds(uniqueIds, userId, trx); + if (ownedTools.length !== uniqueIds.length) { + throw new NotFoundError('Chat hub tool not found'); + } } private validateToolExpressions(definition: INode) { diff --git a/packages/cli/src/modules/chat-hub/chat-hub-workflow.service.ts b/packages/cli/src/modules/chat-hub/chat-hub-workflow.service.ts index bc804c08f61..4e714db8c49 100644 --- a/packages/cli/src/modules/chat-hub/chat-hub-workflow.service.ts +++ b/packages/cli/src/modules/chat-hub/chat-hub-workflow.service.ts @@ -5,6 +5,7 @@ import { type ChatHubBaseLLMModel, type ChatProviderSettingsDto, type ChatHubAgentKnowledgeItem, + isChatHubToolTypeAllowed, } from '@n8n/api-types'; import { Logger } from '@n8n/backend-common'; import { @@ -1361,7 +1362,7 @@ Respond the title only:`, credentials, model, systemMessage, - tools, + this.filterAllowedTools(user, tools), timeZone, vectorStoreSearch, executionMetadata, @@ -1371,6 +1372,22 @@ Respond the title only:`, }); } + /** + * Stored tools can predate a tool type rule or a role change, so check them + * again before each run. + */ + private filterAllowedTools(user: User, tools: INode[]): INode[] { + const isChatUser = user.role.slug === 'global:chatUser'; + return tools.filter((tool) => { + if (isChatHubToolTypeAllowed(tool.type, { isChatUser })) return true; + this.logger.warn('Skipped a Chat Hub tool that the user is not allowed to run', { + userId: user.id, + toolType: tool.type, + }); + return false; + }); + } + private async prepareChatAgentWorkflow( agentId: string, user: User, diff --git a/packages/cli/src/modules/chat-hub/chat-hub.controller.ts b/packages/cli/src/modules/chat-hub/chat-hub.controller.ts index d77ed8bf615..d4c5cc0f61f 100644 --- a/packages/cli/src/modules/chat-hub/chat-hub.controller.ts +++ b/packages/cli/src/modules/chat-hub/chat-hub.controller.ts @@ -20,8 +20,7 @@ import { type ChatSendMessageResponse, type ChatReconnectResponse, ChatReconnectRequest, - ALWAYS_BLOCKED_CHAT_HUB_TOOL_TYPES, - CHAT_USER_BLOCKED_CHAT_HUB_TOOL_TYPES, + isChatHubToolTypeAllowed, } from '@n8n/api-types'; import { ModuleRegistry } from '@n8n/backend-common'; import { AuthenticatedRequest } from '@n8n/db'; @@ -518,13 +517,10 @@ export class ChatHubController { } private assertToolTypeAllowed(type: string, user: AuthenticatedRequest['user']) { - if (ALWAYS_BLOCKED_CHAT_HUB_TOOL_TYPES.includes(type)) { + if (!isChatHubToolTypeAllowed(type, { isChatUser: false })) { throw new BadRequestError(`Tool type "${type}" is not supported in the Chat Hub`); } - if ( - user.role.slug === 'global:chatUser' && - CHAT_USER_BLOCKED_CHAT_HUB_TOOL_TYPES.includes(type) - ) { + if (!isChatHubToolTypeAllowed(type, { isChatUser: user.role.slug === 'global:chatUser' })) { throw new BadRequestError(`Tool type "${type}" is not available for your role`); } } diff --git a/packages/cli/src/modules/chat-hub/chat-hub.service.ts b/packages/cli/src/modules/chat-hub/chat-hub.service.ts index e3111197e1b..93bf9df951c 100644 --- a/packages/cli/src/modules/chat-hub/chat-hub.service.ts +++ b/packages/cli/src/modules/chat-hub/chat-hub.service.ts @@ -240,7 +240,7 @@ export class ChatHubService { const enabledTools = await this.chatHubToolService.getEnabledTools(user.id, trx); const toolIds = enabledTools.map((t) => t.id); if (toolIds.length > 0) { - await this.chatHubToolService.setSessionTools(sessionId, toolIds, trx); + await this.chatHubToolService.setSessionTools(sessionId, user.id, toolIds, trx); } return session; @@ -378,11 +378,14 @@ export class ChatHubService { if (updates.title !== undefined) sessionUpdates.title = updates.title; if (updates.credentialId !== undefined) sessionUpdates.credentialId = updates.credentialId; - await this.sessionRepository.updateChatSession(sessionId, sessionUpdates); - - if (updates.toolIds !== undefined) { - await this.chatHubToolService.setSessionTools(sessionId, updates.toolIds); - } + // One transaction: a rejected tool or a failed field update leaves the session unchanged + const { toolIds } = updates; + await this.sessionRepository.runInTransaction({}, async (trx) => { + if (toolIds !== undefined) { + await this.chatHubToolService.setSessionTools(sessionId, user.id, toolIds, trx); + } + await this.sessionRepository.updateChatSession(sessionId, sessionUpdates, trx); + }); } /** diff --git a/packages/cli/src/modules/data-table/__tests__/data-table-file-cleanup.task.test.ts b/packages/cli/src/modules/data-table/__tests__/data-table-file-cleanup.task.test.ts index 06ab0840e48..a82f6e2ed2e 100644 --- a/packages/cli/src/modules/data-table/__tests__/data-table-file-cleanup.task.test.ts +++ b/packages/cli/src/modules/data-table/__tests__/data-table-file-cleanup.task.test.ts @@ -34,8 +34,7 @@ describe('DataTableFileCleanupTask', () => { it('should run on every main at the configured interval', () => { expect(task.name).toBe('data-table-file-cleanup'); expect(task.schedule).toEqual({ kind: 'interval', intervalSeconds: 60 }); - expect(task.effects).toBe('idempotent'); - expect(task.placement).toEqual({ scope: 'instance', instanceTypes: ['main'] }); + expect(task.target).toEqual({ scope: 'instance', instanceTypes: ['main'] }); }); it('should delete the old upload files of this process', async () => { diff --git a/packages/cli/src/modules/data-table/__tests__/data-table-proxy.service.integration.test.ts b/packages/cli/src/modules/data-table/__tests__/data-table-proxy.service.integration.test.ts index 107420f6a4b..257750d7004 100644 --- a/packages/cli/src/modules/data-table/__tests__/data-table-proxy.service.integration.test.ts +++ b/packages/cli/src/modules/data-table/__tests__/data-table-proxy.service.integration.test.ts @@ -1,6 +1,7 @@ import type { ListDataTableQueryDto } from '@n8n/api-types'; import type { Logger } from '@n8n/backend-common'; -import { createTeamProject, testDb, testModules } from '@n8n/backend-test-utils'; +import { CacheService } from '@n8n/backend-services'; +import { createTeamProject, createWorkflow, testDb, testModules } from '@n8n/backend-test-utils'; import type { Project, User } from '@n8n/db'; import { Container } from '@n8n/di'; import type { @@ -17,7 +18,7 @@ import { mock } from 'vitest-mock-extended'; import type { InstanceWriteAccessService } from '@n8n/backend-services'; import * as checkAccess from '@/permissions.ee/check-access'; -import type { OwnershipService } from '@/services/ownership.service'; +import { OwnershipService } from '@/services/ownership.service'; import type { DataTableAggregateService } from '../data-table-aggregate.service'; import { DataTableProxyService } from '../data-table-proxy.service'; @@ -299,7 +300,15 @@ describe('DataTableProxyService (with database)', () => { const workflow = mock({ id: 'workflow-id' }); afterEach(async () => { - await testDb.truncate(['DataTable', 'DataTableColumn', 'Project', 'ProjectRelation']); + await testDb.truncate([ + 'DataTable', + 'DataTableColumn', + 'SharedWorkflow', + 'WorkflowEntity', + 'Project', + 'ProjectRelation', + ]); + await Container.get(CacheService).delete('workflow-project'); }); it('resolves the proxy when the data table exists in the project', async () => { @@ -332,6 +341,29 @@ describe('DataTableProxyService (with database)', () => { await expect(promise).rejects.toBeInstanceOf(NodeOperationError); await expect(promise).rejects.toThrow(table.id); }); + + it('rejects a table from another project for a workflow with the id `__proto__`', async () => { + const workflowProject = await createTeamProject(); + const otherProject = await createTeamProject(); + const table = await Container.get(DataTableService).createDataTable(otherProject.id, { + name: 'Other Project Table', + columns: [], + }); + await createWorkflow({ id: '__proto__' }, workflowProject); + // The ownership cache must already exist, as it does on any instance that ran a workflow + await Container.get(CacheService).setHash('workflow-project', { + 'other-workflow': Container.get(OwnershipService).copyProject(workflowProject), + }); + + const promise = Container.get(DataTableProxyService).getDataTableProxy( + mock({ id: '__proto__' }), + node, + table.id, + ); + + await expect(promise).rejects.toBeInstanceOf(NodeOperationError); + await expect(promise).rejects.toThrow(table.id); + }); }); describe('makeDataTableOperationsForUser', () => { diff --git a/packages/cli/src/modules/data-table/data-table-file-cleanup.task.ts b/packages/cli/src/modules/data-table/data-table-file-cleanup.task.ts index 2a439d3b065..3f7f3e44c7d 100644 --- a/packages/cli/src/modules/data-table/data-table-file-cleanup.task.ts +++ b/packages/cli/src/modules/data-table/data-table-file-cleanup.task.ts @@ -1,6 +1,6 @@ import { GlobalConfig } from '@n8n/config'; -import { intervalFromMilliseconds, SystemTask } from '@n8n/decorators'; -import type { SystemTaskEffects, SystemTaskPlacement, SystemTaskSchedule } from '@n8n/decorators'; +import { instanceTarget, intervalFromMilliseconds, SystemTask } from '@n8n/decorators'; +import type { SystemTaskSchedule } from '@n8n/decorators'; import { DataTableFileCleanupService } from './data-table-file-cleanup.service'; @@ -15,13 +15,8 @@ export class DataTableFileCleanupTask implements SystemTask { this.globalConfig.dataTable.cleanupIntervalMs, ); - readonly effects: SystemTaskEffects = 'idempotent'; - /** The upload directory is on the local disk of each main. */ - readonly placement: SystemTaskPlacement = { - scope: 'instance', - instanceTypes: ['main'], - }; + readonly target = instanceTarget(['main']); constructor( private readonly globalConfig: GlobalConfig, diff --git a/packages/cli/src/modules/external-secrets.ee/__tests__/external-secrets-refresh.task.test.ts b/packages/cli/src/modules/external-secrets.ee/__tests__/external-secrets-refresh.task.test.ts index a3ac058f605..1f45c80d365 100644 --- a/packages/cli/src/modules/external-secrets.ee/__tests__/external-secrets-refresh.task.test.ts +++ b/packages/cli/src/modules/external-secrets.ee/__tests__/external-secrets-refresh.task.test.ts @@ -17,8 +17,7 @@ describe('ExternalSecretsRefreshTask', () => { it('should refresh in every kind of instance every update interval', () => { expect(task.name).toBe('external-secrets-refresh'); expect(task.schedule).toEqual({ kind: 'interval', intervalSeconds: 600 }); - expect(task.effects).toBe('idempotent'); - expect(task.placement).toEqual({ + expect(task.target).toEqual({ scope: 'instance', instanceTypes: ['main', 'worker', 'webhook'], }); diff --git a/packages/cli/src/modules/external-secrets.ee/external-secrets-refresh.task.ts b/packages/cli/src/modules/external-secrets.ee/external-secrets-refresh.task.ts index c9f86bc48a4..d451301328d 100644 --- a/packages/cli/src/modules/external-secrets.ee/external-secrets-refresh.task.ts +++ b/packages/cli/src/modules/external-secrets.ee/external-secrets-refresh.task.ts @@ -1,5 +1,5 @@ -import { intervalFromSeconds, SystemTask } from '@n8n/decorators'; -import type { SystemTaskEffects, SystemTaskPlacement, SystemTaskSchedule } from '@n8n/decorators'; +import { instanceTarget, intervalFromSeconds, SystemTask } from '@n8n/decorators'; +import type { SystemTaskSchedule } from '@n8n/decorators'; import { ExternalSecretsManager } from './external-secrets-manager.ee'; import { ExternalSecretsConfig } from './external-secrets.config'; @@ -13,13 +13,8 @@ export class ExternalSecretsRefreshTask implements SystemTask { readonly schedule: SystemTaskSchedule; - readonly effects: SystemTaskEffects = 'idempotent'; - /** The secrets cache belongs to this process, so every instance refreshes its own. */ - readonly placement: SystemTaskPlacement = { - scope: 'instance', - instanceTypes: ['main', 'worker', 'webhook'], - }; + readonly target = instanceTarget(['main', 'worker', 'webhook']); constructor( config: ExternalSecretsConfig, diff --git a/packages/cli/src/modules/inbound-auth-core/__tests__/authentication-pipeline.test.ts b/packages/cli/src/modules/inbound-auth-core/__tests__/authentication-pipeline.test.ts index 145b5e238b6..d87a05f9427 100644 --- a/packages/cli/src/modules/inbound-auth-core/__tests__/authentication-pipeline.test.ts +++ b/packages/cli/src/modules/inbound-auth-core/__tests__/authentication-pipeline.test.ts @@ -41,7 +41,7 @@ const verified: Verified = { }; const context: SecurityContext = { - subject: { id: 'user-1', type: 'human' } as Principal, + subject: { id: 'user-1', type: 'human', email: 'alice@example.com' } as Principal, authMethod: 'oauth-access-token', subjectClaim: { sourceId: SOURCE_ID, issuer: 'https://idp.example', subject: 'alice' }, }; @@ -58,7 +58,7 @@ beforeEach(() => { }); describe('InboundAuthPipeline', () => { - it('returns the identity result when both steps pass, without logging', async () => { + it('returns the identity result when both steps pass, without a warning', async () => { authentication.authenticate.mockResolvedValue({ ok: true, value: verified }); identity.identify.mockResolvedValue({ ok: true, value: context }); @@ -70,6 +70,34 @@ describe('InboundAuthPipeline', () => { expect(logger.warn).not.toHaveBeenCalled(); }); + describe('accept log line', () => { + beforeEach(() => { + authentication.authenticate.mockResolvedValue({ ok: true, value: verified }); + identity.identify.mockResolvedValue({ ok: true, value: context }); + }); + + it('logs one info line with surface, resource, source, auth method and user id', async () => { + await pipeline.run(extracted); + + expect(logger.info).toHaveBeenCalledTimes(1); + expect(logger.info).toHaveBeenCalledWith(expect.any(String), { + surface: 'instance-mcp', + resource: RESOURCE, + sourceId: SOURCE_ID, + authMethod: 'oauth-access-token', + userId: 'user-1', + }); + }); + + it('never writes the bearer token, the external subject or the email', async () => { + await pipeline.run(extracted); + + const written = JSON.stringify(logger.info.mock.calls); + expect(written).not.toContain(TOKEN); + expect(written).not.toContain('alice'); + }); + }); + it('returns the authentication reject and skips the identity step', async () => { const reject: Reject = { ok: false, reason: 'signature-invalid', detail: 'bad sig' }; authentication.authenticate.mockResolvedValue(reject); @@ -146,5 +174,13 @@ describe('InboundAuthPipeline', () => { expect(JSON.stringify(logger.warn.mock.calls)).not.toContain(TOKEN); }, ); + + it.each(cases)('writes no accept line on an $step reject', async ({ arrange, reject }) => { + arrange(reject); + + await pipeline.run(extracted); + + expect(logger.info).not.toHaveBeenCalled(); + }); }); }); diff --git a/packages/cli/src/modules/inbound-auth-core/__tests__/inbound-auth-core.module.test.ts b/packages/cli/src/modules/inbound-auth-core/__tests__/inbound-auth-core.module.test.ts index 3941de64270..d6382aada12 100644 --- a/packages/cli/src/modules/inbound-auth-core/__tests__/inbound-auth-core.module.test.ts +++ b/packages/cli/src/modules/inbound-auth-core/__tests__/inbound-auth-core.module.test.ts @@ -12,26 +12,50 @@ import { InstanceSettings } from 'n8n-core'; import { OperationalError } from 'n8n-workflow'; import { mock } from 'vitest-mock-extended'; +import { AuthStrategyRegistry } from '@/services/auth-strategy.registry'; +import { ProtectedResourceRegistry } from '@/services/protected-resource.registry'; + // Importing the module runs the @BackendModule decorator, registering its metadata. import { InboundAuthPipeline } from '../authentication-pipeline'; import { OAuth2AuthenticationService } from '../authentication.service'; import { TrustedSourceIdentityService } from '../identity/trusted-source-identity.service'; import { InboundAuthCoreModule } from '../inbound-auth-core.module'; +import { PublicApiOAuthStrategy } from '../public-api-oauth.strategy'; +import { PublicApiProtectedResource } from '../public-api-protected-resource'; import { TrustedSourceDiscoveryTask } from '../trusted-source-discovery.task'; import { TrustedSourceDbGate } from '../trusted-source.gate'; import { TrustedSourceDbStore } from '../trusted-source.store'; +// A mocked module's factory runs on its first import, so the first `init()` that imports the +// controller is the one that proves the gate. Keep the "loaded" case last. +const { loadController } = vi.hoisted(() => ({ loadController: vi.fn() })); +const FLAG = 'N8N_ENV_FEAT_TRUSTED_SOURCES_API_ENABLED'; +vi.mock('../trusted-source.controller', () => { + loadController(); + return {}; +}); + describe('InboundAuthCoreModule', () => { describe('init', () => { const dbStore = mock(); const dbGate = mock(); const identityService = mock(); + const strategyRegistry = mock(); + const resourceRegistry = mock(); + const publicApiResource = mock(); + const publicApiStrategy = mock(); beforeAll(async () => { + // The shell may carry the flag; the first init must not be the one that imports the controller. + vi.stubEnv(FLAG, ''); Container.set(InstanceSettings, mock({ instanceType: 'main' })); Container.set(TrustedSourceDbStore, dbStore); Container.set(TrustedSourceDbGate, dbGate); Container.set(TrustedSourceIdentityService, identityService); + Container.set(AuthStrategyRegistry, strategyRegistry); + Container.set(ProtectedResourceRegistry, resourceRegistry); + Container.set(PublicApiProtectedResource, publicApiResource); + Container.set(PublicApiOAuthStrategy, publicApiStrategy); await new InboundAuthCoreModule().init(); }); @@ -85,6 +109,38 @@ describe('InboundAuthCoreModule', () => { it('binds the AuthenticationPipeline contract to the inbound-auth pipeline', () => { expect(Container.get(AuthenticationPipeline)).toBeInstanceOf(InboundAuthPipeline); }); + + describe('public API surface', () => { + afterEach(() => { + Container.set(InstanceSettings, mock({ instanceType: 'main' })); + }); + + it('registers the public API resource and its OAuth2 strategy once on a main instance', async () => { + resourceRegistry.register.mockClear(); + strategyRegistry.register.mockClear(); + + await new InboundAuthCoreModule().init(); + + expect(resourceRegistry.register).toHaveBeenCalledTimes(1); + expect(resourceRegistry.register).toHaveBeenCalledWith(publicApiResource); + expect(strategyRegistry.register).toHaveBeenCalledTimes(1); + expect(strategyRegistry.register).toHaveBeenCalledWith(publicApiStrategy); + }); + + it.each(['webhook', 'worker'] as const)( + 'registers neither on a %s instance, which serves no public API', + async (instanceType) => { + Container.set(InstanceSettings, mock({ instanceType })); + resourceRegistry.register.mockClear(); + strategyRegistry.register.mockClear(); + + await new InboundAuthCoreModule().init(); + + expect(resourceRegistry.register).not.toHaveBeenCalled(); + expect(strategyRegistry.register).not.toHaveBeenCalled(); + }, + ); + }); }); it('registers itself on main, webhook and worker instances without a license flag', () => { @@ -112,4 +168,41 @@ describe('InboundAuthCoreModule', () => { 'TrustedSourceIdentityEntity', ]); }); + describe('management controller', () => { + beforeEach(() => { + loadController.mockClear(); + vi.stubEnv(FLAG, ''); + }); + + afterEach(() => { + vi.unstubAllEnvs(); + Container.set(InstanceSettings, mock({ instanceType: 'main' })); + }); + + it('is not loaded while the flag is unset', async () => { + await new InboundAuthCoreModule().init(); + + expect(loadController).not.toHaveBeenCalled(); + }); + + it.each(['webhook', 'worker'] as const)( + 'is not loaded on a %s instance even with the flag', + async (instanceType) => { + vi.stubEnv(FLAG, 'true'); + Container.set(InstanceSettings, mock({ instanceType })); + + await new InboundAuthCoreModule().init(); + + expect(loadController).not.toHaveBeenCalled(); + }, + ); + + it('is loaded on a main instance when the flag is true', async () => { + vi.stubEnv(FLAG, 'true'); + + await new InboundAuthCoreModule().init(); + + expect(loadController).toHaveBeenCalledOnce(); + }); + }); }); diff --git a/packages/cli/src/modules/inbound-auth-core/__tests__/public-api-oauth.strategy.test.ts b/packages/cli/src/modules/inbound-auth-core/__tests__/public-api-oauth.strategy.test.ts new file mode 100644 index 00000000000..894b5d1ba26 --- /dev/null +++ b/packages/cli/src/modules/inbound-auth-core/__tests__/public-api-oauth.strategy.test.ts @@ -0,0 +1,261 @@ +import { JwtService } from '@n8n/backend-services'; +import type { AuthenticatedRequest, User, UserRepository } from '@n8n/db'; +import type { AuthenticationPipeline, AuthenticationService } from '@n8n/inbound-auth'; +import { getApiKeyScopesForRole, type Scope, type SecurityContext } from '@n8n/permissions'; +import type { Response } from 'express'; +import { sign } from 'jsonwebtoken'; +import type { InstanceSettings } from 'n8n-core'; +import { mock } from 'vitest-mock-extended'; + +import { PublicApiOAuthStrategy } from '../public-api-oauth.strategy'; +import type { PublicApiProtectedResource } from '../public-api-protected-resource'; + +const RESOURCE_URL = 'https://n8n.test/api/v1'; +const CHALLENGE = + 'Bearer resource_metadata="https://n8n.test/.well-known/oauth-protected-resource/api/v1"'; + +const jwtService = new JwtService( + mock({ encryptionKey: 'test-key' }), + mock(), + mock(), +); +const resource = mock({ surface: 'public-api' }); +const pipeline = mock(); +const authenticationService = mock(); +const userRepository = mock(); + +let strategy: PublicApiOAuthStrategy; + +/** Only `iss` matters here: the pipeline, not the strategy, verifies the signature. */ +const tokenFrom = (iss: string) => sign({ iss, sub: 'alice' }, 'unverified'); + +const makeReq = (headers: Record) => { + const res = mock(); + const req = mock({ + headers: headers as AuthenticatedRequest['headers'], + method: 'GET', + originalUrl: '/api/v1/workflows', + ip: '203.0.113.7', + res, + }); + return { req, res }; +}; + +const makeUser = (id: string, scopeSlugs: string[]): User => + ({ + ...mock(), + id, + role: { + ...mock(), + slug: 'global:member', + scopes: scopeSlugs.map((slug) => ({ ...mock(), slug: slug as Scope })), + }, + }) as User; + +beforeEach(() => { + vi.clearAllMocks(); + resource.isAvailable.mockResolvedValue(true); + resource.getResourceUrl.mockReturnValue(RESOURCE_URL); + resource.getAudiences.mockReturnValue([RESOURCE_URL]); + authenticationService.advertise.mockResolvedValue({ + authorizationServers: ['https://idp.example'], + challenges: [CHALLENGE], + }); + strategy = new PublicApiOAuthStrategy( + resource, + pipeline, + authenticationService, + jwtService, + userRepository, + ); +}); + +describe('PublicApiOAuthStrategy', () => { + describe('buildTokenGrant', () => { + it('abstains: the pipeline needs the request, not a bare token', async () => { + expect(await strategy.buildTokenGrant()).toBeNull(); + }); + }); + + describe('authenticate', () => { + it.each([ + ['no Authorization header', {}], + ['a non-bearer Authorization header', { authorization: 'Basic dXNlcjpwYXNz' }], + ['a bearer that is not a JWT', { authorization: 'Bearer not-a-jwt' }], + ])('abstains with %s', async (_name, headers) => { + const { req } = makeReq(headers); + + expect(await strategy.authenticate(req)).toBeNull(); + expect(pipeline.run).not.toHaveBeenCalled(); + }); + + it.each(['n8n', 'n8n-token-exchange', 'urn:example:idp', 'ftp://idp.example', ''])( + 'abstains for issuer %j, which is not an http(s) URL', + async (iss) => { + const { req } = makeReq({ authorization: `Bearer ${tokenFrom(iss)}` }); + + expect(await strategy.authenticate(req)).toBeNull(); + expect(pipeline.run).not.toHaveBeenCalled(); + }, + ); + + it('abstains while the public API is unavailable', async () => { + resource.isAvailable.mockResolvedValue(false); + const { req } = makeReq({ authorization: `Bearer ${tokenFrom('https://idp.example')}` }); + + expect(await strategy.authenticate(req)).toBeNull(); + expect(pipeline.run).not.toHaveBeenCalled(); + }); + + it.each(['https://idp.example', 'http://localhost:5678'])( + 'runs the pipeline for issuer %s on the public-api surface with the resource and the request', + async (iss) => { + const token = tokenFrom(iss); + pipeline.run.mockResolvedValue({ ok: false, reason: 'unknown-issuer' }); + const { req } = makeReq({ authorization: `Bearer ${token}` }); + + await strategy.authenticate(req); + + expect(pipeline.run).toHaveBeenCalledTimes(1); + expect(pipeline.run).toHaveBeenCalledWith( + expect.objectContaining({ + surface: 'public-api', + resource: { url: RESOURCE_URL, acceptedAudiences: [RESOURCE_URL] }, + credential: { kind: 'bearer', token }, + request: expect.objectContaining({ + method: 'GET', + url: '/api/v1/workflows', + ip: '203.0.113.7', + }), + }), + ); + }, + ); + + describe('on a pipeline reject', () => { + it('fails fast with the advertised challenge, error=invalid_token and the reason', async () => { + pipeline.run.mockResolvedValue({ + ok: false, + reason: 'source-not-accepted', + detail: 'internal detail', + }); + const { req, res } = makeReq({ + authorization: `Bearer ${tokenFrom('https://idp.example')}`, + }); + + expect(await strategy.authenticate(req)).toBe(false); + + expect(authenticationService.advertise).toHaveBeenCalledWith( + expect.objectContaining({ + surface: 'public-api', + resource: { url: RESOURCE_URL, acceptedAudiences: [RESOURCE_URL] }, + }), + ); + expect(res.setHeader).toHaveBeenCalledWith( + 'WWW-Authenticate', + `${CHALLENGE}, error="invalid_token", error_description="source-not-accepted"`, + ); + }); + + it('never puts the reject detail into the response header', async () => { + pipeline.run.mockResolvedValue({ + ok: false, + reason: 'source-unusable', + detail: 'source status is error', + }); + const { req, res } = makeReq({ + authorization: `Bearer ${tokenFrom('https://idp.example')}`, + }); + + await strategy.authenticate(req); + + expect(JSON.stringify(res.setHeader.mock.calls)).not.toContain('source status is error'); + }); + + it('falls back to a bare Bearer challenge when no source is advertised', async () => { + authenticationService.advertise.mockResolvedValue({ + authorizationServers: [], + challenges: [], + }); + pipeline.run.mockResolvedValue({ ok: false, reason: 'unknown-issuer' }); + const { req, res } = makeReq({ + authorization: `Bearer ${tokenFrom('https://idp.example')}`, + }); + + expect(await strategy.authenticate(req)).toBe(false); + expect(res.setHeader).toHaveBeenCalledWith( + 'WWW-Authenticate', + 'Bearer, error="invalid_token", error_description="unknown-issuer"', + ); + }); + }); + + describe('on success', () => { + const contextWith = (tokenScopes?: string[]): SecurityContext => ({ + subject: { id: 'user-1', type: 'human', role: mock() }, + authMethod: 'oauth-access-token', + subjectClaim: { sourceId: 'source-1', issuer: 'https://idp.example', subject: 'alice' }, + ...(tokenScopes && { tokenScopes }), + }); + + it('sets the reloaded user, a role-derived grant and the security context on the request', async () => { + const user = makeUser('user-1', ['workflow:list', 'workflow:create']); + const context = contextWith(['workflow:list']); + pipeline.run.mockResolvedValue({ ok: true, value: context }); + userRepository.findByIdWithRole.mockResolvedValue(user); + const { req, res } = makeReq({ + authorization: `Bearer ${tokenFrom('https://idp.example')}`, + }); + + expect(await strategy.authenticate(req)).toBe(true); + + expect(userRepository.findByIdWithRole).toHaveBeenCalledWith('user-1'); + expect(req.user).toBe(user); + expect(req.tokenGrant).toEqual({ + scopes: ['workflow:list', 'workflow:create'], + apiKeyScopes: ['workflow:list'], + subject: user, + }); + expect(req.ctx).toEqual({ security: context }); + expect(res.setHeader).not.toHaveBeenCalled(); + }); + + // Only API key scopes narrow the grant; an IdP's own scopes are ignored. + it.each<{ name: string; tokenScopes?: string[]; expected: (role: string[]) => string[] }>([ + { + name: 'an API key scope', + tokenScopes: ['workflow:list'], + expected: () => ['workflow:list'], + }, + { + name: 'an API key scope next to IdP scopes', + tokenScopes: ['workflow:list', 'openid'], + expected: () => ['workflow:list'], + }, + { name: 'only IdP scopes', tokenScopes: ['openid', 'profile'], expected: (role) => role }, + { name: 'no scopes', tokenScopes: [], expected: (role) => role }, + { name: 'no scope claim', expected: (role) => role }, + { name: 'an API key scope the role lacks', tokenScopes: ['user:list'], expected: () => [] }, + ])('grants $name as the role allows', async ({ tokenScopes, expected }) => { + const user = makeUser('user-1', ['workflow:list', 'workflow:create']); + pipeline.run.mockResolvedValue({ ok: true, value: contextWith(tokenScopes) }); + userRepository.findByIdWithRole.mockResolvedValue(user); + const { req } = makeReq({ authorization: `Bearer ${tokenFrom('https://idp.example')}` }); + + await strategy.authenticate(req); + + expect(req.tokenGrant?.apiKeyScopes).toEqual(expected(getApiKeyScopesForRole(user))); + }); + + it('fails fast when the subject no longer exists', async () => { + pipeline.run.mockResolvedValue({ ok: true, value: contextWith() }); + userRepository.findByIdWithRole.mockResolvedValue(null); + const { req } = makeReq({ + authorization: `Bearer ${tokenFrom('https://idp.example')}`, + }); + + expect(await strategy.authenticate(req)).toBe(false); + }); + }); + }); +}); diff --git a/packages/cli/src/modules/inbound-auth-core/__tests__/public-api-protected-resource.test.ts b/packages/cli/src/modules/inbound-auth-core/__tests__/public-api-protected-resource.test.ts new file mode 100644 index 00000000000..58ad1b3e7e1 --- /dev/null +++ b/packages/cli/src/modules/inbound-auth-core/__tests__/public-api-protected-resource.test.ts @@ -0,0 +1,95 @@ +import type { LicenseState } from '@n8n/backend-common'; +import type { UrlService } from '@n8n/backend-services'; +import type { GlobalConfig } from '@n8n/config'; +import type { ProtectedResource, ResourceUser } from '@n8n/inbound-auth'; +import { ALL_API_KEY_SCOPES, getApiKeyScopesForRole, type Scope } from '@n8n/permissions'; +import { mock } from 'vitest-mock-extended'; + +import { PublicApiProtectedResource } from '../public-api-protected-resource'; + +const urlService = mock(); +const licenseState = mock(); +const globalConfig = { publicApi: { disabled: false, path: 'api' } } as unknown as GlobalConfig; + +let resource: PublicApiProtectedResource; + +const principal = (roleSlug: string, scopeSlugs: string[]): ResourceUser => ({ + ...mock(), + role: { + ...mock(), + slug: roleSlug, + scopes: scopeSlugs.map((slug) => ({ ...mock(), slug: slug as Scope })), + }, +}); + +beforeEach(() => { + vi.clearAllMocks(); + globalConfig.publicApi.disabled = false; + globalConfig.publicApi.path = 'api'; + urlService.getInstanceBaseUrl.mockReturnValue('https://n8n.test/'); + licenseState.isAPIDisabled.mockReturnValue(false); + resource = new PublicApiProtectedResource(urlService, globalConfig, licenseState); +}); + +describe('PublicApiProtectedResource', () => { + it('is served on the public-api surface, advertises the API key scopes, and is neither default nor first-party', () => { + const contract: ProtectedResource = resource; + + expect(contract.surface).toBe('public-api'); + expect(contract.scopes).toEqual([...ALL_API_KEY_SCOPES]); + expect(contract.isDefault).toBeFalsy(); + expect(contract.isFirstParty).toBeFalsy(); + }); + + it('names itself on the consent screen', () => { + expect(resource.displayName).toBe('n8n public API'); + expect(resource.uiHints).toEqual({ icon: 'key-round', consentType: 'api' }); + }); + + it('lets a member grant the API key scopes of their role', async () => { + const member = principal('global:member', [ + 'workflow:list', + 'workflow:create', + 'workflow:read', + ]); + + await expect(resource.getGrantableScopes(member)).resolves.toEqual( + getApiKeyScopesForRole(member), + ); + }); + + it('lets a chat user grant nothing', async () => { + await expect(resource.getGrantableScopes(principal('global:chatUser', []))).resolves.toEqual( + [], + ); + }); + + it('derives the resource URL from the instance base URL and the public API path', () => { + expect(resource.getResourceUrl()).toBe('https://n8n.test/api/v1'); + }); + + it('follows a custom public API path segment', () => { + globalConfig.publicApi.path = 'my-api'; + + expect(resource.getResourceUrl()).toBe('https://n8n.test/my-api/v1'); + }); + + it('accepts only its own resource URL as audience', () => { + expect(resource.getAudiences()).toEqual(['https://n8n.test/api/v1']); + }); + + it('is available and authorizes any user while the public API is enabled', async () => { + await expect(resource.isAvailable()).resolves.toBe(true); + await expect(resource.authorize()).resolves.toBe(true); + }); + + it.each([ + ['the public API is disabled by config', () => (globalConfig.publicApi.disabled = true)], + ['the license disables the API', () => licenseState.isAPIDisabled.mockReturnValue(true)], + ])('is unavailable and authorizes nobody when %s', async (_name, arrange) => { + arrange(); + + await expect(resource.isAvailable()).resolves.toBe(false); + await expect(resource.authorize()).resolves.toBe(false); + }); +}); diff --git a/packages/cli/src/modules/inbound-auth-core/__tests__/trusted-source-discovery.task.test.ts b/packages/cli/src/modules/inbound-auth-core/__tests__/trusted-source-discovery.task.test.ts index 2a7e4389aa7..7b30e7883b4 100644 --- a/packages/cli/src/modules/inbound-auth-core/__tests__/trusted-source-discovery.task.test.ts +++ b/packages/cli/src/modules/inbound-auth-core/__tests__/trusted-source-discovery.task.test.ts @@ -10,8 +10,7 @@ describe('TrustedSourceDiscoveryTask', () => { it('declares a durable, idempotent, cluster-wide 60-second poll', () => { expect(task.name).toBe('trusted-source-discovery'); expect(task.schedule).toEqual({ kind: 'interval', intervalSeconds: 60 }); - expect(task.effects).toBe('idempotent'); - expect(task.placement).toEqual({ scope: 'cluster', durable: true }); + expect(task.target).toEqual({ scope: 'cluster', scheduler: { retryOnFailure: true } }); }); it('refreshes the due sources with the run signal', async () => { diff --git a/packages/cli/src/modules/inbound-auth-core/__tests__/trusted-source.controller.test.ts b/packages/cli/src/modules/inbound-auth-core/__tests__/trusted-source.controller.test.ts new file mode 100644 index 00000000000..bbf61e658c6 --- /dev/null +++ b/packages/cli/src/modules/inbound-auth-core/__tests__/trusted-source.controller.test.ts @@ -0,0 +1,60 @@ +import { ControllerRegistryMetadata } from '@n8n/decorators'; +import { Container } from '@n8n/di'; + +import { TrustedSourceController } from '../trusted-source.controller'; + +describe('TrustedSourceController', () => { + const metadata = Container.get(ControllerRegistryMetadata).getControllerMetadata( + TrustedSourceController as never, + ); + const routes = Array.from(metadata.routes.values()) + .map((route) => ({ + route: `${route.method.toUpperCase()} ${route.path}`, + scope: route.accessScope?.scope, + globalOnly: route.accessScope?.globalOnly, + licenseFeature: route.licenseFeature, + })) + .sort((a, b) => a.route.localeCompare(b.route)); + + it('is mounted at /trusted-sources', () => { + expect(metadata.basePath).toBe('/trusted-sources'); + }); + + // Every route needs a global trustedSource scope; only the two writes that create or change a + // source are licensed, so an operator can still inspect and remove sources after a lapse. + it('gates each route with a global scope and licenses only create and update', () => { + expect(routes).toEqual([ + { + route: 'DELETE /:id', + scope: 'trustedSource:delete', + globalOnly: true, + licenseFeature: undefined, + }, + { route: 'GET /', scope: 'trustedSource:list', globalOnly: true, licenseFeature: undefined }, + { + route: 'GET /:id', + scope: 'trustedSource:read', + globalOnly: true, + licenseFeature: undefined, + }, + { + route: 'PATCH /:id', + scope: 'trustedSource:update', + globalOnly: true, + licenseFeature: 'feat:trustedSourceManage', + }, + { + route: 'POST /', + scope: 'trustedSource:create', + globalOnly: true, + licenseFeature: 'feat:trustedSourceManage', + }, + { + route: 'POST /:id/check', + scope: 'trustedSource:update', + globalOnly: true, + licenseFeature: undefined, + }, + ]); + }); +}); diff --git a/packages/cli/src/modules/inbound-auth-core/authentication-pipeline.ts b/packages/cli/src/modules/inbound-auth-core/authentication-pipeline.ts index 241b8100989..64e1dca3c48 100644 --- a/packages/cli/src/modules/inbound-auth-core/authentication-pipeline.ts +++ b/packages/cli/src/modules/inbound-auth-core/authentication-pipeline.ts @@ -30,6 +30,13 @@ export class InboundAuthPipeline extends AuthenticationPipeline { if (!context.ok) { return this.reject(extracted, context, verified.value.source.id); } + this.logger.info('Inbound authentication accepted', { + surface: extracted.surface, + resource: extracted.resource.url, + sourceId: verified.value.source.id, + authMethod: context.value.authMethod, + userId: context.value.subject.id, + }); return context; } diff --git a/packages/cli/src/modules/inbound-auth-core/inbound-auth-core.module.ts b/packages/cli/src/modules/inbound-auth-core/inbound-auth-core.module.ts index 6ad8ea9d5a0..b6ec193a7b5 100644 --- a/packages/cli/src/modules/inbound-auth-core/inbound-auth-core.module.ts +++ b/packages/cli/src/modules/inbound-auth-core/inbound-auth-core.module.ts @@ -1,3 +1,4 @@ +import { isEnvFeatureEnabled } from '@n8n/backend-common'; import type { ModuleInterface } from '@n8n/decorators'; import { BackendModule } from '@n8n/decorators'; import { Container } from '@n8n/di'; @@ -14,6 +15,9 @@ import { import { InstanceSettings } from 'n8n-core'; import { OperationalError } from 'n8n-workflow'; +import { AuthStrategyRegistry } from '@/services/auth-strategy.registry'; +import { ProtectedResourceRegistry } from '@/services/protected-resource.registry'; + // Discovery of the local source must fail, not succeed with made-up documents. class UnregisteredLocalAuthorizationServer extends LocalAuthorizationServer { async getMetadata(): Promise { @@ -52,6 +56,12 @@ export class InboundAuthCoreModule implements ModuleInterface { if (Container.get(InstanceSettings).instanceType === 'main') { const { SystemTrustedSourceSeeder } = await import('./system-trusted-source.seeder.js'); await Container.get(SystemTrustedSourceSeeder).seed(); + + // Ships dark. Set `N8N_ENV_FEAT_TRUSTED_SOURCES_API_ENABLED=true` on a main instance to register + // the `/trusted-sources` management routes; the license gates only create and update. + if (isEnvFeatureEnabled('N8N_ENV_FEAT_TRUSTED_SOURCES_API_ENABLED')) { + await import('./trusted-source.controller.js'); + } } const { OAuth2AuthenticationService } = await import('./authentication.service.js'); @@ -66,6 +76,14 @@ export class InboundAuthCoreModule implements ModuleInterface { const { InboundAuthPipeline } = await import('./authentication-pipeline.js'); Container.set(AuthenticationPipeline, Container.get(InboundAuthPipeline)); + + // Only main serves the public API. The strategy resolves the pipeline, so it registers last. + if (Container.get(InstanceSettings).instanceType === 'main') { + const { PublicApiProtectedResource } = await import('./public-api-protected-resource.js'); + const { PublicApiOAuthStrategy } = await import('./public-api-oauth.strategy.js'); + Container.get(ProtectedResourceRegistry).register(Container.get(PublicApiProtectedResource)); + Container.get(AuthStrategyRegistry).register(Container.get(PublicApiOAuthStrategy)); + } } // Ungated: the runner skips a cluster-scoped task on webhook and worker instances itself. diff --git a/packages/cli/src/modules/inbound-auth-core/public-api-oauth.strategy.ts b/packages/cli/src/modules/inbound-auth-core/public-api-oauth.strategy.ts new file mode 100644 index 00000000000..1192c820fe1 --- /dev/null +++ b/packages/cli/src/modules/inbound-auth-core/public-api-oauth.strategy.ts @@ -0,0 +1,98 @@ +import type { AuthenticatedRequest, TokenGrant } from '@n8n/db'; +import { UserRepository } from '@n8n/db'; +import { Service } from '@n8n/di'; +import { + AuthenticationPipeline, + AuthenticationService, + extractBearer, + inboundFrom, +} from '@n8n/inbound-auth'; +import { + getApiKeyScopesForRole, + isApiKeyScope, + type ApiKeyScope, + type Scope, +} from '@n8n/permissions'; + +import type { AuthStrategy } from '@/services/auth-strategy.types'; +import { JwtService } from '@n8n/backend-services'; + +import { PublicApiProtectedResource } from './public-api-protected-resource'; + +// Token scopes arrive as plain strings; `isApiKeyScope` only takes known scope names. +const isApiKeyScopeName = (scope: string): scope is ApiKeyScope => + isApiKeyScope(scope as Scope | ApiKeyScope); + +/** + * Sends `Authorization: Bearer` JWTs from an OAuth2 issuer through the inbound-auth pipeline. + * API keys and token-exchange JWTs stay with their own strategies. + */ +@Service() +export class PublicApiOAuthStrategy implements AuthStrategy { + constructor( + private readonly resource: PublicApiProtectedResource, + private readonly pipeline: AuthenticationPipeline, + private readonly authenticationService: AuthenticationService, + private readonly jwtService: JwtService, + private readonly userRepository: UserRepository, + ) {} + + async buildTokenGrant(): Promise { + return null; + } + + private isOAuthIssuer(token: string): boolean { + const iss: unknown = this.jwtService.decodeUnverified<{ iss?: unknown } | null>(token)?.iss; + return typeof iss === 'string' && URL.canParse(iss) && /^https?:$/.test(new URL(iss).protocol); + } + + async authenticate(req: AuthenticatedRequest): Promise { + const isAvailable = await this.resource.isAvailable(); + if (!isAvailable) { + return null; + } + + const inbound = inboundFrom(this.resource, { + method: req.method, + url: req.originalUrl, + headers: req.headers, + ip: req.ip ?? '', + }); + const extracted = extractBearer(inbound); + if (!extracted.ok || !this.isOAuthIssuer(extracted.value.credential.token)) { + return null; + } + + const result = await this.pipeline.run(extracted.value); + if (!result.ok) { + const { challenges } = await this.authenticationService.advertise(inbound); + + req.res?.setHeader( + 'WWW-Authenticate', + `${challenges[0] ?? 'Bearer'}, error="invalid_token", error_description="${result.reason}"`, + ); + return false; + } + + const user = await this.userRepository.findByIdWithRole(result.value.subject.id); + if (!user) { + return false; + } + + // Only API key scopes narrow the grant. An external IdP's own scopes (`openid`, ...) are + // ignored, so its users keep the role set until a source can map scopes itself. + const roleScopes = getApiKeyScopesForRole(user); + const requested = (result.value.tokenScopes ?? []).filter(isApiKeyScopeName); + req.user = user; + req.tokenGrant = { + scopes: user.role.scopes.map((scope) => scope.slug), + apiKeyScopes: + requested.length > 0 ? roleScopes.filter((s) => requested.includes(s)) : roleScopes, + subject: user, + }; + req.ctx = { + security: result.value, + }; + return true; + } +} diff --git a/packages/cli/src/modules/inbound-auth-core/public-api-protected-resource.ts b/packages/cli/src/modules/inbound-auth-core/public-api-protected-resource.ts new file mode 100644 index 00000000000..5bd7b05ab5c --- /dev/null +++ b/packages/cli/src/modules/inbound-auth-core/public-api-protected-resource.ts @@ -0,0 +1,48 @@ +import type { ConsentUiHints } from '@n8n/api-types'; +import { LicenseState } from '@n8n/backend-common'; +import { UrlService } from '@n8n/backend-services'; +import { GlobalConfig } from '@n8n/config'; +import { Service } from '@n8n/di'; +import type { ProtectedResource, ResourceUser } from '@n8n/inbound-auth'; +import { ALL_API_KEY_SCOPES, getApiKeyScopesForRole } from '@n8n/permissions'; + +/** The public API at `/api/v1` as an OAuth 2.1 protected resource on the `public-api` surface. */ +@Service() +export class PublicApiProtectedResource implements ProtectedResource { + readonly id = 'public-api'; + + readonly surface = 'public-api' as const; + + readonly displayName = 'n8n public API'; + + readonly uiHints: ConsentUiHints = { icon: 'key-round', consentType: 'api' }; + + readonly scopes: string[] = [...ALL_API_KEY_SCOPES]; + + constructor( + private readonly urlService: UrlService, + private readonly globalConfig: GlobalConfig, + private readonly licenseState: LicenseState, + ) {} + + getResourceUrl(): string { + const baseUrl = this.urlService.getInstanceBaseUrl().replace(/\/$/, ''); + return `${baseUrl}/${this.globalConfig.publicApi.path}/v1`; + } + + getAudiences(): string[] { + return [this.getResourceUrl()]; + } + + async isAvailable(): Promise { + return !this.globalConfig.publicApi.disabled && !this.licenseState.isAPIDisabled(); + } + + async authorize(): Promise { + return await this.isAvailable(); + } + + async getGrantableScopes(user: ResourceUser): Promise { + return getApiKeyScopesForRole(user); + } +} diff --git a/packages/cli/src/modules/inbound-auth-core/trusted-source-discovery.task.ts b/packages/cli/src/modules/inbound-auth-core/trusted-source-discovery.task.ts index 8f4ad89a5e0..d8454775ad4 100644 --- a/packages/cli/src/modules/inbound-auth-core/trusted-source-discovery.task.ts +++ b/packages/cli/src/modules/inbound-auth-core/trusted-source-discovery.task.ts @@ -1,5 +1,5 @@ -import { intervalFromSeconds, SystemTask } from '@n8n/decorators'; -import type { SystemTaskEffects, SystemTaskPlacement, SystemTaskSchedule } from '@n8n/decorators'; +import { clusterTarget, intervalFromSeconds, SystemTask } from '@n8n/decorators'; +import type { SystemTaskSchedule } from '@n8n/decorators'; import { TrustedSourceDiscoveryService } from './trusted-source-discovery.service'; @@ -16,9 +16,7 @@ export class TrustedSourceDiscoveryTask implements SystemTask { readonly schedule: SystemTaskSchedule = intervalFromSeconds(DISCOVERY_POLL_INTERVAL_SECONDS); - readonly effects: SystemTaskEffects = 'idempotent'; - - readonly placement: SystemTaskPlacement = { scope: 'cluster', durable: true }; + readonly target = clusterTarget({ scheduler: { retryOnFailure: true } }); constructor(private readonly discovery: TrustedSourceDiscoveryService) {} diff --git a/packages/cli/src/modules/inbound-auth-core/trusted-source.controller.ts b/packages/cli/src/modules/inbound-auth-core/trusted-source.controller.ts new file mode 100644 index 00000000000..1b7167115c8 --- /dev/null +++ b/packages/cli/src/modules/inbound-auth-core/trusted-source.controller.ts @@ -0,0 +1,198 @@ +import { CreateTrustedSourceDto, UpdateTrustedSourceDto } from '@n8n/api-types'; +import { EventService } from '@n8n/backend-services'; +import { isUniqueConstraintError, type AuthenticatedRequest } from '@n8n/db'; +import { + Body, + Delete, + Get, + GlobalScope, + Licensed, + Param, + Patch, + Post, + RestController, +} from '@n8n/decorators'; +import { BadRequestError, ConflictError, NotFoundError } from '@n8n/errors'; +import { + deriveCapabilities, + type Capability, + type TrustedSource, + type TrustedSourceConfigInput, + type TrustedSourceConfigLatest, +} from '@n8n/inbound-auth'; +import type { Response } from 'express'; +import { CREDENTIAL_BLANKING_VALUE } from 'n8n-workflow'; + +import { TrustedSourceDiscoveryService } from './trusted-source-discovery.service'; +import { TrustedSourceDbStore } from './trusted-source.store'; + +/** What every caller may see of a source: no issuer, no config, no status. */ +type TrustedSourceSummary = { + id: string; + name: string; + capabilities: Capability[]; + surfaces: string[]; +}; + +function toSummary(source: TrustedSource): TrustedSourceSummary { + return { + id: source.id, + name: source.name, + capabilities: [...deriveCapabilities(source.config, source.metadata)], + surfaces: Object.keys(source.config.surfaces), + }; +} + +/** The stored secret never leaves the instance; the response carries the blanking value instead. */ +function redact(source: TrustedSource): TrustedSource { + const { client } = source.config.authentication; + if (client?.kind !== 'registered' || client.clientSecret === undefined) return source; + return { + ...source, + config: { + ...source.config, + authentication: { + ...source.config.authentication, + client: { ...client, clientSecret: CREDENTIAL_BLANKING_VALUE }, + }, + }, + }; +} + +/** + * The blanking value in an incoming config means "keep the stored secret", the same contract as + * credentials. Any other value replaces it; an absent key clears it. + */ +function restoreSecret( + config: TrustedSourceConfigInput, + current: TrustedSourceConfigLatest, +): TrustedSourceConfigInput { + const { client } = config.authentication; + if (client?.kind !== 'registered' || client.clientSecret !== CREDENTIAL_BLANKING_VALUE) { + return config; + } + const storedClient = current.authentication.client; + const { clientSecret: _, ...withoutSecret } = client; + const restored = + storedClient?.kind === 'registered' && storedClient.clientSecret !== undefined + ? { ...withoutSecret, clientSecret: storedClient.clientSecret } + : withoutSecret; + return { ...config, authentication: { ...config.authentication, client: restored } }; +} + +async function wrapConflict(write: () => Promise): Promise { + try { + return await write(); + } catch (error) { + if (isUniqueConstraintError(error)) { + throw new ConflictError('A trusted source with this name or issuer already exists'); + } + throw error; + } +} + +@RestController('/trusted-sources') +export class TrustedSourceController { + constructor( + private readonly store: TrustedSourceDbStore, + private readonly discovery: TrustedSourceDiscoveryService, + private readonly eventService: EventService, + ) {} + + @Get('/') + @GlobalScope('trustedSource:list') + async list(): Promise { + return (await this.store.listAll()).map(toSummary); + } + + @Get('/:id') + @GlobalScope('trustedSource:read') + async get(_req: AuthenticatedRequest, _res: Response, @Param('id') id: string) { + return redact(await this.require(id)); + } + + @Post('/') + @Licensed('feat:trustedSourceManage') + @GlobalScope('trustedSource:create') + async create(req: AuthenticatedRequest, _res: Response, @Body dto: CreateTrustedSourceDto) { + const { client } = dto.config.authentication; + // The blanking value stands for a stored secret, and a new source has none to stand for. + if (client?.kind === 'registered' && client.clientSecret === CREDENTIAL_BLANKING_VALUE) { + throw new BadRequestError( + 'clientSecret must be a real secret on create, not the blanking value', + ); + } + const source = await wrapConflict(async () => await this.store.create(dto)); + this.eventService.emit('trusted-source-created', { + user: req.user, + sourceId: source.id, + issuer: source.issuer, + }); + return redact(source); + } + + @Patch('/:id') + @Licensed('feat:trustedSourceManage') + @GlobalScope('trustedSource:update') + async update( + req: AuthenticatedRequest, + _res: Response, + @Param('id') id: string, + @Body dto: UpdateTrustedSourceDto, + ) { + const current = await this.require(id); + const { clearBindings = false, config, ...rest } = dto; + // An empty patch changes nothing, so it writes no row and emits no audit event. + if ( + rest.name === undefined && + rest.issuer === undefined && + config === undefined && + !clearBindings + ) { + return redact(current); + } + await wrapConflict( + async () => + await this.store.update( + id, + { ...rest, ...(config && { config: restoreSecret(config, current.config) }) }, + { clearBindings }, + ), + ); + const updated = await this.require(id); + this.eventService.emit('trusted-source-updated', { + user: req.user, + sourceId: updated.id, + issuer: updated.issuer, + }); + return redact(updated); + } + + @Delete('/:id') + @GlobalScope('trustedSource:delete') + async delete(req: AuthenticatedRequest, _res: Response, @Param('id') id: string) { + const source = await this.require(id); + await this.store.delete(id); + this.eventService.emit('trusted-source-deleted', { + user: req.user, + sourceId: source.id, + issuer: source.issuer, + }); + } + + @Post('/:id/check') + @GlobalScope('trustedSource:update') + async check(_req: AuthenticatedRequest, _res: Response, @Param('id') id: string) { + await this.require(id); + // ponytail: shares the cron lease; a check during a cron run returns the row unchanged for at + // most 60 s. A lease-free path is the upgrade if that window is reported. + await this.discovery.refresh(id); + return redact(await this.require(id)); + } + + private async require(id: string): Promise { + const source = await this.store.getById(id); + if (!source) throw new NotFoundError(`Trusted source "${id}" not found`); + return source; + } +} diff --git a/packages/cli/src/modules/inbound-auth-core/trusted-source.store.ts b/packages/cli/src/modules/inbound-auth-core/trusted-source.store.ts index f25ad87b900..be7c7e7b302 100644 --- a/packages/cli/src/modules/inbound-auth-core/trusted-source.store.ts +++ b/packages/cli/src/modules/inbound-auth-core/trusted-source.store.ts @@ -93,12 +93,17 @@ export class TrustedSourceDbStore extends TrustedSourceStore { }); } - async listBySurface(surface: SurfaceId): Promise { - const all = + async listAll(): Promise { + return ( (await this.cacheService.get(ALL_KEY, { ttl: CACHE_TTL, refreshFn: async () => await this.loadAll(), - })) ?? []; + })) ?? [] + ); + } + + async listBySurface(surface: SurfaceId): Promise { + const all = await this.listAll(); return all.filter((source) => source.config.surfaces[surface] !== undefined); } diff --git a/packages/cli/src/modules/instance-ai/__tests__/credit-counting.test.ts b/packages/cli/src/modules/instance-ai/__tests__/credit-counting.test.ts index 868bcfa82b2..ba788259792 100644 --- a/packages/cli/src/modules/instance-ai/__tests__/credit-counting.test.ts +++ b/packages/cli/src/modules/instance-ai/__tests__/credit-counting.test.ts @@ -1,15 +1,9 @@ import type { Mock } from 'vitest'; import type { Thread } from '@n8n/agents'; -import { UNLIMITED_CREDITS } from '@n8n/api-types'; import type { User } from '@n8n/db'; import type { BuilderUsageItem } from '@n8n/instance-ai'; -import { mock } from 'vitest-mock-extended'; - -import type { InstanceActivationService } from '@/services/instance-activation.service'; import { InstanceAiCreditService } from '../instance-ai-credit.service'; -import type { InstanceAiSettingsService } from '../instance-ai-settings.service'; -import type { InstanceAiMessageRepository } from '../repositories/instance-ai-message.repository'; import type { InstanceAiThreadRepository } from '../repositories/instance-ai-thread.repository'; // Skip the real backoff sleeps so retry tests run instantly. @@ -26,18 +20,9 @@ function createService(deps: { aiService: { isProxyEnabled: Mock; getClient: Mock }; push: { sendToUsers: Mock }; telemetry: { track: Mock }; - activationCapped?: boolean; }) { const scopedLogger = { warn: vi.fn(), debug: vi.fn() }; const logger = { scoped: vi.fn().mockReturnValue(scopedLogger) }; - const settingsService = mock(); - settingsService.isActivationCapped.mockReturnValue(deps.activationCapped ?? false); - - // Typed, so a rename on either collaborator fails the build instead of silently - // producing `undefined` and sending the caller down its catch. Neither is exercised - // by the claim path this file covers — the lock has its own suite. - const activationService = mock(); - const messageRepo = mock(); return new InstanceAiCreditService( logger as never, deps.aiService as never, @@ -45,9 +30,6 @@ function createService(deps: { { instanceId: 'inst-1' } as never, deps.push as never, deps.threadRepo as never, - settingsService, - activationService, - messageRepo, ); } @@ -187,38 +169,6 @@ describe('claimRunUsage', () => { expect(delta).toBe(0.5); }); - it('masks the pushed balance for the activation-capped cohort', async () => { - const threadRepo = createMockThreadRepo({ id: 't1', metadata: { creditsUsed: 2 } }); - const ai = createMockAiService({ - claimResult: { delta: 0.5, creditsClaimed: 5.5, creditsQuota: 100 }, - }); - const push = { sendToUsers: vi.fn() }; - const telemetry = { track: vi.fn() }; - - const service = createService({ - threadRepo, - aiService: ai, - push, - telemetry, - activationCapped: true, - }); - await callClaim(service); - - // No `quotaLocked`: a claim knows nothing about the lock, and saying `false` here would - // retract the warning a preceding lock had raised. Claims can land after the lock. - expect(push.sendToUsers).toHaveBeenCalledWith( - expect.objectContaining({ - type: 'updateInstanceAiCredits', - data: { creditsQuota: UNLIMITED_CREDITS, creditsClaimed: 0 }, - }), - ['user-1'], - ); - expect(telemetry.track).toHaveBeenCalledWith( - 'Builder credits claimed', - expect.objectContaining({ credits_claimed_total: 5.5, credits_quota: 100 }), - ); - }); - it('fires the "Builder credits claimed" event with success true on the happy path', async () => { const threadRepo = createMockThreadRepo({ id: 't1', metadata: {} }); const ai = createMockAiService(); diff --git a/packages/cli/src/modules/instance-ai/__tests__/instance-ai-activation-lock.test.ts b/packages/cli/src/modules/instance-ai/__tests__/instance-ai-activation-lock.test.ts deleted file mode 100644 index 1b897666c3d..00000000000 --- a/packages/cli/src/modules/instance-ai/__tests__/instance-ai-activation-lock.test.ts +++ /dev/null @@ -1,302 +0,0 @@ -import { UNLIMITED_CREDITS, type InstanceAiCredits } from '@n8n/api-types'; -import type { User } from '@n8n/db'; -import { mock } from 'vitest-mock-extended'; - -import type { Push } from '@/push'; -import type { AiService } from '@/services/ai.service'; -import type { InstanceActivationService } from '@/services/instance-activation.service'; -import type { Telemetry } from '@/telemetry'; - -import { InstanceAiCreditService } from '../instance-ai-credit.service'; -import type { InstanceAiSettingsService } from '../instance-ai-settings.service'; -import type { InstanceAiMessageRepository } from '../repositories/instance-ai-message.repository'; -import type { InstanceAiThreadRepository } from '../repositories/instance-ai-thread.repository'; - -describe('InstanceAiCreditService activation lock', () => { - const user = mock({ id: 'user-1' }); - - function setup( - opts: { - activationCapped?: boolean; - proxyEnabled?: boolean; - activatedAt?: number; - /** Whether the instance has met the message threshold. */ - messageThresholdMet?: boolean; - /** Value of `N8N_INSTANCE_AI_ACTIVATION_LOCK_MESSAGE_THRESHOLD`. */ - messageThreshold?: number; - /** `quotaLocked` stays required here so each case states the service's verdict. */ - lockResult?: InstanceAiCredits & { quotaLocked: boolean }; - lockRejects?: Error; - } = {}, - ) { - const aiService = mock(); - aiService.isProxyEnabled.mockReturnValue(opts.proxyEnabled ?? true); - if (opts.lockRejects) { - aiService.lockInstanceAiQuota.mockRejectedValue(opts.lockRejects); - } else { - aiService.lockInstanceAiQuota.mockResolvedValue( - opts.lockResult ?? { creditsQuota: 800, creditsClaimed: 12.5, quotaLocked: true }, - ); - } - - const settingsService = mock(); - settingsService.isActivationCapped.mockReturnValue(opts.activationCapped ?? true); - settingsService.getActivationLockMessageThreshold.mockReturnValue(opts.messageThreshold ?? 1); - - const activationService = mock(); - activationService.getActivatedAt.mockResolvedValue(opts.activatedAt); - - const messageRepo = mock(); - messageRepo.hasAtLeastUserMessages.mockResolvedValue(opts.messageThresholdMet ?? false); - - // `info` matters: the success path logs through it, so omitting it makes every happy-path - // test fall into the catch instead — silently, and taking the push branch with it. - const scopedLogger = { warn: vi.fn(), debug: vi.fn(), info: vi.fn() }; - const logger = { scoped: vi.fn().mockReturnValue(scopedLogger) }; - const push = mock(); - - const service = new InstanceAiCreditService( - logger as never, - aiService, - mock(), - { instanceId: 'inst-1' } as never, - push, - mock(), - settingsService, - activationService, - messageRepo, - ); - - return { - service, - aiService, - settingsService, - activationService, - messageRepo, - scopedLogger, - push, - }; - } - - describe('when both conditions are met', () => { - it('locks the pool, reporting when the instance activated', async () => { - const { service, aiService } = setup({ - activatedAt: 1_700_000_000, - messageThresholdMet: true, - }); - - await service.ensureQuotaLockApplied(user); - - expect(aiService.lockInstanceAiQuota).toHaveBeenCalledWith(user, 1_700_000_000); - }); - - it('stops calling the service once the lock is confirmed', async () => { - const { service, aiService } = setup({ - activatedAt: 1_700_000_000, - messageThresholdMet: true, - }); - - await service.ensureQuotaLockApplied(user); - await service.ensureQuotaLockApplied(user); - await service.ensureQuotaLockApplied(user); - - expect(aiService.lockInstanceAiQuota).toHaveBeenCalledTimes(1); - }); - - it('pushes the lock to the acting user so the banner appears', async () => { - const { service, push } = setup({ activatedAt: 1_700_000_000, messageThresholdMet: true }); - - await service.ensureQuotaLockApplied(user); - - // Amounts stay masked for this cohort — the banner is raised by the flag alone. - expect(push.sendToUsers).toHaveBeenCalledWith( - { - type: 'updateInstanceAiCredits', - data: { creditsQuota: UNLIMITED_CREDITS, creditsClaimed: 0, quotaLocked: true }, - }, - [user.id], - ); - }); - - it('reaches the success path without falling into the catch', async () => { - const { service, scopedLogger } = setup({ - activatedAt: 1_700_000_000, - messageThresholdMet: true, - }); - - await service.ensureQuotaLockApplied(user); - - expect(scopedLogger.info).toHaveBeenCalled(); - expect(scopedLogger.warn).not.toHaveBeenCalled(); - }); - - it('raises no banner when the service reports the pool was not locked', async () => { - const { service, push } = setup({ - activatedAt: 1_700_000_000, - messageThresholdMet: true, - lockResult: { creditsQuota: 800, creditsClaimed: 12.5, quotaLocked: false }, - }); - - await service.ensureQuotaLockApplied(user); - - expect(push.sendToUsers).not.toHaveBeenCalled(); - }); - }); - - describe('when only one condition is met', () => { - it('asks for the configured number of messages, not merely one', async () => { - const { service, messageRepo } = setup({ activatedAt: 1_700_000_000, messageThreshold: 3 }); - - await service.ensureQuotaLockApplied(user); - - expect(messageRepo.hasAtLeastUserMessages).toHaveBeenCalledWith(3); - }); - - it('defaults to a single message when the operator sets nothing', async () => { - const { service, messageRepo } = setup({ activatedAt: 1_700_000_000 }); - - await service.ensureQuotaLockApplied(user); - - expect(messageRepo.hasAtLeastUserMessages).toHaveBeenCalledWith(1); - }); - - it('does not lock on activation alone', async () => { - const { service, aiService } = setup({ - activatedAt: 1_700_000_000, - messageThresholdMet: false, - }); - - await service.ensureQuotaLockApplied(user); - - expect(aiService.lockInstanceAiQuota).not.toHaveBeenCalled(); - }); - - it('does not lock on assistant use alone', async () => { - const { service, aiService, messageRepo } = setup({ - activatedAt: undefined, - messageThresholdMet: true, - }); - - await service.ensureQuotaLockApplied(user); - - expect(aiService.lockInstanceAiQuota).not.toHaveBeenCalled(); - // Short-circuits before the message lookup, so the cheap check runs first. - expect(messageRepo.hasAtLeastUserMessages).not.toHaveBeenCalled(); - }); - - it('locks as soon as the outstanding half arrives', async () => { - const { service, aiService, messageRepo } = setup({ - activatedAt: 1_700_000_000, - messageThresholdMet: false, - }); - - await service.ensureQuotaLockApplied(user); - expect(aiService.lockInstanceAiQuota).not.toHaveBeenCalled(); - - messageRepo.hasAtLeastUserMessages.mockResolvedValue(true); - await service.ensureQuotaLockApplied(user); - - expect(aiService.lockInstanceAiQuota).toHaveBeenCalledTimes(1); - }); - }); - - describe('outside the activation-capped cohort', () => { - it('never calls the service, whatever the conditions', async () => { - const { service, aiService, activationService, messageRepo } = setup({ - activationCapped: false, - activatedAt: 1_700_000_000, - messageThresholdMet: true, - }); - - await service.ensureQuotaLockApplied(user); - - expect(aiService.lockInstanceAiQuota).not.toHaveBeenCalled(); - expect(activationService.getActivatedAt).not.toHaveBeenCalled(); - expect(messageRepo.hasAtLeastUserMessages).not.toHaveBeenCalled(); - }); - }); - - // A run awaits this before starting, so nothing in here — including the prerequisite reads — - // may escape and take the run down with it. - describe('when a prerequisite read fails', () => { - it('swallows an activation-row read failure', async () => { - const { service, activationService, scopedLogger } = setup({ messageThresholdMet: true }); - activationService.getActivatedAt.mockRejectedValue(new Error('db unavailable')); - - await expect(service.ensureQuotaLockApplied(user)).resolves.toBeUndefined(); - expect(scopedLogger.warn).toHaveBeenCalled(); - }); - - it('swallows a message-count read failure', async () => { - const { service, messageRepo, scopedLogger } = setup({ activatedAt: 1_700_000_000 }); - messageRepo.hasAtLeastUserMessages.mockRejectedValue(new Error('db unavailable')); - - await expect(service.ensureQuotaLockApplied(user)).resolves.toBeUndefined(); - expect(scopedLogger.warn).toHaveBeenCalled(); - }); - - it('retries on the next call rather than giving up', async () => { - const { service, aiService, activationService } = setup({ messageThresholdMet: true }); - activationService.getActivatedAt.mockRejectedValueOnce(new Error('db unavailable')); - - await service.ensureQuotaLockApplied(user); - expect(aiService.lockInstanceAiQuota).not.toHaveBeenCalled(); - - activationService.getActivatedAt.mockResolvedValue(1_700_000_000); - await service.ensureQuotaLockApplied(user); - - expect(aiService.lockInstanceAiQuota).toHaveBeenCalledTimes(1); - }); - }); - - it('does nothing when the proxy is disabled', async () => { - const { service, aiService } = setup({ - proxyEnabled: false, - activatedAt: 1_700_000_000, - messageThresholdMet: true, - }); - - await service.ensureQuotaLockApplied(user); - - expect(aiService.lockInstanceAiQuota).not.toHaveBeenCalled(); - }); - - describe('when the lock call fails', () => { - it('swallows the error so the caller can continue', async () => { - const { service, scopedLogger } = setup({ - activatedAt: 1_700_000_000, - messageThresholdMet: true, - lockRejects: new Error('service unavailable'), - }); - - await expect(service.ensureQuotaLockApplied(user)).resolves.toBeUndefined(); - expect(scopedLogger.warn).toHaveBeenCalled(); - }); - - it('retries on the next call', async () => { - const { service, aiService } = setup({ - activatedAt: 1_700_000_000, - messageThresholdMet: true, - lockRejects: new Error('service unavailable'), - }); - - await service.ensureQuotaLockApplied(user); - await service.ensureQuotaLockApplied(user); - - expect(aiService.lockInstanceAiQuota).toHaveBeenCalledTimes(2); - }); - - it('retries when the service reports the pool was not locked', async () => { - const { service, aiService } = setup({ - activatedAt: 1_700_000_000, - messageThresholdMet: true, - lockResult: { creditsQuota: 800, creditsClaimed: 12.5, quotaLocked: false }, - }); - - await service.ensureQuotaLockApplied(user); - await service.ensureQuotaLockApplied(user); - - expect(aiService.lockInstanceAiQuota).toHaveBeenCalledTimes(2); - }); - }); -}); diff --git a/packages/cli/src/modules/instance-ai/__tests__/instance-ai-checkpoint-pruning.task.test.ts b/packages/cli/src/modules/instance-ai/__tests__/instance-ai-checkpoint-pruning.task.test.ts index a58f4150f84..0273a8dcca6 100644 --- a/packages/cli/src/modules/instance-ai/__tests__/instance-ai-checkpoint-pruning.task.test.ts +++ b/packages/cli/src/modules/instance-ai/__tests__/instance-ai-checkpoint-pruning.task.test.ts @@ -17,9 +17,11 @@ describe('InstanceAiCheckpointPruningTask', () => { it('should declare the configured prune cadence', () => { expect(task.name).toBe('instance-ai-checkpoint-pruning'); expect(task.schedule).toEqual({ kind: 'interval', intervalSeconds: 3600 }); - expect(task.effects).toBe('idempotent'); - expect(task.placement).toEqual({ scope: 'cluster', durable: true, runOnTakeover: true }); - expect(task.retryDelaySeconds).toBe(30); + expect(task.target).toEqual({ + scope: 'cluster', + scheduler: { retryOnFailure: true, timeoutSeconds: 1200 }, + leaderTimer: { runOnTakeover: true, retryDelaySeconds: 30 }, + }); }); it('should declare a fractional prune interval as is', () => { @@ -43,7 +45,8 @@ describe('InstanceAiCheckpointPruningTask', () => { const database = mock({ type, postgresdb: { statementTimeoutMs } }); expect( - new InstanceAiCheckpointPruningTask(config, database, instanceAiService).timeoutSeconds, + new InstanceAiCheckpointPruningTask(config, database, instanceAiService).target.scheduler + .timeoutSeconds, ).toBe(timeoutSeconds); }, ); diff --git a/packages/cli/src/modules/instance-ai/__tests__/instance-ai-credit-display.test.ts b/packages/cli/src/modules/instance-ai/__tests__/instance-ai-credit-display.test.ts deleted file mode 100644 index b897382f5c8..00000000000 --- a/packages/cli/src/modules/instance-ai/__tests__/instance-ai-credit-display.test.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { UNLIMITED_CREDITS } from '@n8n/api-types'; - -import { maskCreditsForDisplay } from '../instance-ai-credit-display'; - -describe('maskCreditsForDisplay', () => { - const credits = { creditsQuota: 800, creditsClaimed: 12.5 }; - const perThread = { threadId: 't1', totalCreditsUsed: 3 }; - - describe('outside the activation-capped cohort', () => { - it('passes the balance through untouched', () => { - expect(maskCreditsForDisplay(credits, false)).toEqual(credits); - }); - - it('keeps the per-thread total when one was computed', () => { - expect(maskCreditsForDisplay(credits, false, perThread)).toEqual({ - ...credits, - creditsPerThread: perThread, - }); - }); - - it('omits the per-thread total when none was computed', () => { - expect(maskCreditsForDisplay(credits, false)).not.toHaveProperty('creditsPerThread'); - }); - }); - - describe('inside the activation-capped cohort', () => { - it('reports the unlimited sentinel instead of the balance', () => { - expect(maskCreditsForDisplay(credits, true)).toEqual({ - creditsQuota: UNLIMITED_CREDITS, - creditsClaimed: 0, - }); - }); - - it('suppresses the per-thread total too', () => { - expect(maskCreditsForDisplay(credits, true, perThread)).not.toHaveProperty( - 'creditsPerThread', - ); - }); - - it('still hides the balance once the quota is spent', () => { - expect(maskCreditsForDisplay({ creditsQuota: 800, creditsClaimed: 800 }, true)).toEqual({ - creditsQuota: UNLIMITED_CREDITS, - creditsClaimed: 0, - }); - }); - - // The lock carries no figure, so it survives the masking — it is the only usage signal this - // cohort gets, and the editor needs it to warn before the user types. - it('keeps the lock flag while hiding the balance', () => { - expect( - maskCreditsForDisplay({ creditsQuota: 800, creditsClaimed: 12.5, quotaLocked: true }, true), - ).toEqual({ - creditsQuota: UNLIMITED_CREDITS, - creditsClaimed: 0, - quotaLocked: true, - }); - }); - - // A claim reports a balance and knows nothing about the lock. Saying `false` for it would - // retract a warning the lock had already raised, so the key is omitted entirely. - it('stays silent on the lock when the caller had no opinion', () => { - const masked = maskCreditsForDisplay({ creditsQuota: 800, creditsClaimed: 12.5 }, true); - - expect(masked).toEqual({ creditsQuota: UNLIMITED_CREDITS, creditsClaimed: 0 }); - expect('quotaLocked' in masked).toBe(false); - }); - - it('reports an explicitly unlocked pool as false', () => { - expect( - maskCreditsForDisplay( - { creditsQuota: 800, creditsClaimed: 12.5, quotaLocked: false }, - true, - ), - ).toEqual({ - creditsQuota: UNLIMITED_CREDITS, - creditsClaimed: 0, - quotaLocked: false, - }); - }); - }); -}); diff --git a/packages/cli/src/modules/instance-ai/__tests__/instance-ai-pending-agent.service.test.ts b/packages/cli/src/modules/instance-ai/__tests__/instance-ai-pending-agent.service.test.ts index af3d7a64909..3cdccc83392 100644 --- a/packages/cli/src/modules/instance-ai/__tests__/instance-ai-pending-agent.service.test.ts +++ b/packages/cli/src/modules/instance-ai/__tests__/instance-ai-pending-agent.service.test.ts @@ -39,6 +39,7 @@ function setup() { const runnableState = mockInstance(AgentRunnableStateService); const defaultModelResolver = mockInstance(AgentDefaultModelResolverService); const moduleRegistry = mock(); + Object.defineProperty(moduleRegistry, 'settings', { value: new Map() }); moduleRegistry.isActive.mockReturnValue(true); defaultModelResolver.resolve.mockResolvedValue(null); @@ -266,4 +267,12 @@ describe('InstanceAiPendingAgentService', () => { await expect(service.persistAndBind(user, THREAD_ID, payload)).rejects.toThrow(NotFoundError); expect(memoryService.getThreadMetadata).not.toHaveBeenCalled(); }); + + it('reports agents being unavailable when Settings > Agents is off', async () => { + const { service, memoryService, moduleRegistry } = setup(); + moduleRegistry.settings.set('agents', { enabled: false }); + + await expect(service.persistAndBind(user, THREAD_ID, payload)).rejects.toThrow(NotFoundError); + expect(memoryService.getThreadMetadata).not.toHaveBeenCalled(); + }); }); diff --git a/packages/cli/src/modules/instance-ai/__tests__/instance-ai-sandbox.service.test.ts b/packages/cli/src/modules/instance-ai/__tests__/instance-ai-sandbox.service.test.ts index d2b1df266ec..02ae424676b 100644 --- a/packages/cli/src/modules/instance-ai/__tests__/instance-ai-sandbox.service.test.ts +++ b/packages/cli/src/modules/instance-ai/__tests__/instance-ai-sandbox.service.test.ts @@ -529,6 +529,29 @@ describe('InstanceAiSandboxService', () => { expect(setupSandboxWorkspace).toHaveBeenCalledTimes(1); }); + it('passes the verified bundles of the sandbox to workspace setup', async () => { + const { service } = createSandboxService({ + config: { sandboxEnabled: true, sandboxProvider: 'daytona' }, + }); + const workspace = { init: vi.fn(async () => {}), destroy: vi.fn(async () => {}) }; + (createSandbox as Mock).mockResolvedValue({ id: 'sandbox-1' }); + (createWorkspace as Mock).mockReturnValue(workspace); + (setupSandboxWorkspace as Mock).mockResolvedValue(undefined); + + const entry = await service.getOrCreateWorkspace( + 'thread-1', + fakeUser, + {} as InstanceAiContext, + ); + + expect(entry?.verifiedBundles).toEqual(new Map()); + const setupOptions = (setupSandboxWorkspace as Mock).mock.calls[0]?.[2] as { + verifiedBundles: unknown; + }; + expect((setupSandboxWorkspace as Mock).mock.calls[0]?.[0]).toBe(workspace); + expect(setupOptions.verifiedBundles).toBe(entry?.verifiedBundles); + }); + it('assigns a deterministic thread-scoped UUID for the n8n-sandbox provider', async () => { const n8nSandboxConfig: Overrides['config'] = { sandboxEnabled: true, diff --git a/packages/cli/src/modules/instance-ai/__tests__/instance-ai.adapter.service.test.ts b/packages/cli/src/modules/instance-ai/__tests__/instance-ai.adapter.service.test.ts index 57e65050e00..1455b425703 100644 --- a/packages/cli/src/modules/instance-ai/__tests__/instance-ai.adapter.service.test.ts +++ b/packages/cli/src/modules/instance-ai/__tests__/instance-ai.adapter.service.test.ts @@ -1970,7 +1970,7 @@ describe('executeNodeService adapter', () => { mockedUserHasScopes.mockReset(); }); - it('runs the node in the bound project after asserting execute scope there', async () => { + it('runs the node in the bound project after asserting create and execute scopes there', async () => { mockedUserHasScopes.mockResolvedValue(true); const executeNodeService = { run: vi.fn().mockResolvedValue({ status: 'success', output: [] }), @@ -1980,16 +1980,19 @@ describe('executeNodeService adapter', () => { const context = service.createContext(mockUser, { projectId: 'team-project-1' }); await context.executeNodeService?.execute(executeRequest); - expect(mockedUserHasScopes).toHaveBeenCalledWith(mockUser, ['workflow:execute'], false, { - projectId: 'team-project-1', - }); + expect(mockedUserHasScopes).toHaveBeenCalledWith( + mockUser, + ['workflow:create', 'workflow:execute'], + false, + { projectId: 'team-project-1' }, + ); expect(executeNodeService.run).toHaveBeenCalledWith( mockUser, expect.objectContaining({ projectId: 'team-project-1' }), ); }); - it('does not run when the user lacks execute scope in the bound project', async () => { + it('does not run when the user lacks the required scopes in the bound project', async () => { mockedUserHasScopes.mockResolvedValue(false); const executeNodeService = { run: vi.fn() }; const { service, mockUser } = createNodeAdapterServiceForTests([], { executeNodeService }); @@ -7823,24 +7826,24 @@ describe('createContext — builder delegate wiring', () => { it.each([ { - name: 'omits new Agent builds when Agents are disabled', + name: 'omits Agent builds when Settings > Agents is off', moduleActive: true, - resumeAgentBuild: false, + agentsEnabled: false, expected: false, }, { - name: 'keeps admitted Agent builds when Agents are disabled', + name: 'wires Agent builds when the module is active and Settings > Agents is on', moduleActive: true, - resumeAgentBuild: true, + agentsEnabled: true, expected: true, }, { - name: 'omits admitted Agent builds when the module is inactive', + name: 'omits Agent builds when the module is inactive', moduleActive: false, - resumeAgentBuild: true, + agentsEnabled: true, expected: false, }, - ])('$name', async ({ moduleActive, resumeAgentBuild, expected }) => { + ])('$name', async ({ moduleActive, agentsEnabled, expected }) => { const { createOrchestrationTools } = await import( '../../../../../@n8n/instance-ai/dist/tools/index.js' ); @@ -7849,13 +7852,12 @@ describe('createContext — builder delegate wiring', () => { mockBuilderModuleActive(delegate); const moduleRegistry = Container.get(ModuleRegistry); vi.mocked(moduleRegistry.isActive).mockReturnValue(moduleActive); - moduleRegistry.settings.set('agents', { enabled: false }); + moduleRegistry.settings.set('agents', { enabled: agentsEnabled }); const context = service.createContext(mockUser, { threadId: 'thread-1', projectId: 'proj-1', agentId: 'agent-42', - resumeAgentBuild, }); const orchestrationContext = mock(); orchestrationContext.domainContext = context; @@ -8251,6 +8253,41 @@ describe('createCredentialAdapter', () => { await expect(credentialService.test('cred-1')).rejects.toBe(refusal); expect(test).not.toHaveBeenCalled(); }); + + it('writes the stand-in URL into the credential field an eval target names', async () => { + const decryptForUse = vi.fn().mockResolvedValue({ apiKey: 'secret' }); + const test = vi.fn().mockResolvedValue({ status: 'OK', message: 'ok' }); + const { service, mockUser } = adapterWith(decryptForUse, test); + const { credentialService } = service.createContext(mockUser, { + getCredentialTestTarget: () => ({ + credentialType: 'slackApi', + baseUrl: 'http://stand-in.test:4100', + urlField: 'url', + }), + }); + + await credentialService.test('cred-1'); + + expect(test).toHaveBeenCalledWith( + mockUser.id, + expect.objectContaining({ + data: { apiKey: 'secret', url: 'http://stand-in.test:4100' }, + }), + ); + }); + + it('tests the stored data unchanged when the thread has no target', async () => { + const decryptForUse = vi.fn().mockResolvedValue({ apiKey: 'secret' }); + const test = vi.fn().mockResolvedValue({ status: 'OK', message: 'ok' }); + const { credentialService, mockUser } = adapterWith(decryptForUse, test); + + await credentialService.test('cred-1'); + + expect(test).toHaveBeenCalledWith( + mockUser.id, + expect.objectContaining({ data: { apiKey: 'secret' } }), + ); + }); }); describe('getCredentialFillState', () => { diff --git a/packages/cli/src/modules/instance-ai/__tests__/instance-ai.controller.test.ts b/packages/cli/src/modules/instance-ai/__tests__/instance-ai.controller.test.ts index b874220ddb4..81dcce4a100 100644 --- a/packages/cli/src/modules/instance-ai/__tests__/instance-ai.controller.test.ts +++ b/packages/cli/src/modules/instance-ai/__tests__/instance-ai.controller.test.ts @@ -46,6 +46,7 @@ import type { InstanceAiAdminSettingsUpdateRequest, InstanceAiEvalAgentExecutionResult, InstanceAiEvalCredentialAllowlistRequest, + InstanceAiEvalCredentialTestTargetRequest, InstanceAiEvalExecutionResult, InstanceAiEvalLlmUsage, InstanceAiEvalRestoreThreadRequest, @@ -1106,6 +1107,70 @@ describe('InstanceAiController', () => { }); }); + describe('setThreadCredentialTestTarget', () => { + const target = { + credentialType: 'slackApi', + baseUrl: 'http://stand-in.test:4100', + urlField: 'url', + }; + const payload = { threadId: THREAD_ID, ...target }; + + it('should require instanceAi:eval scope', () => { + expect(scopeOf('setThreadCredentialTestTarget')).toEqual({ + scope: 'instanceAi:eval', + globalOnly: true, + }); + }); + + beforeEach(() => { + globalConfig.instanceAi.evalInstance = true; + }); + + afterEach(() => { + globalConfig.instanceAi.evalInstance = false; + }); + + it('should set the test target for an owned thread', async () => { + memoryService.checkThreadOwnership.mockResolvedValue('owned'); + + const result = await controller.setThreadCredentialTestTarget( + req, + res, + payload as InstanceAiEvalCredentialTestTargetRequest, + ); + + expect(result).toEqual({ ok: true }); + expect(evalCredentialAllowlists.getTestTarget(THREAD_ID, 'slackApi')).toEqual(target); + }); + + it('should reject a thread that does not exist', async () => { + memoryService.checkThreadOwnership.mockResolvedValue('not_found'); + + await expect( + controller.setThreadCredentialTestTarget( + req, + res, + payload as InstanceAiEvalCredentialTestTargetRequest, + ), + ).rejects.toThrow(NotFoundError); + }); + + it('should refuse the target on an instance that is not an eval instance', async () => { + globalConfig.instanceAi.evalInstance = false; + evalCredentialAllowlists.clearThread(THREAD_ID); + memoryService.checkThreadOwnership.mockResolvedValue('owned'); + + await expect( + controller.setThreadCredentialTestTarget( + req, + res, + payload as InstanceAiEvalCredentialTestTargetRequest, + ), + ).rejects.toThrow(NotFoundError); + expect(evalCredentialAllowlists.getTestTarget(THREAD_ID, 'slackApi')).toBeUndefined(); + }); + }); + describe('getEvalThreadMemory', () => { const memory: InstanceAiEvalThreadMemoryResponse = { observations: [{ marker: 'critical', text: 'Posting via HTTP Request', tokenCount: 7 }], diff --git a/packages/cli/src/modules/instance-ai/__tests__/instance-ai.service.agent-context.test.ts b/packages/cli/src/modules/instance-ai/__tests__/instance-ai.service.agent-context.test.ts index 1e14fb715fb..8e7533a44d4 100644 --- a/packages/cli/src/modules/instance-ai/__tests__/instance-ai.service.agent-context.test.ts +++ b/packages/cli/src/modules/instance-ai/__tests__/instance-ai.service.agent-context.test.ts @@ -30,7 +30,10 @@ describe('InstanceAiService Agent context binding', () => { const adapter = mock(); adapter.createReader.mockReturnValue(reader); vi.spyOn(Container, 'get') - .mockReturnValueOnce({ isActive: vi.fn().mockReturnValue(true) } as unknown as ModuleRegistry) + .mockReturnValueOnce({ + isActive: vi.fn().mockReturnValue(true), + settings: new Map(), + } as unknown as ModuleRegistry) .mockReturnValueOnce(adapter); const service = Object.create(InstanceAiService.prototype) as ServiceInternals; const context = { projectId: 'project-1' } as unknown as InstanceAiContext; diff --git a/packages/cli/src/modules/instance-ai/__tests__/instance-ai.service.build-mode.test.ts b/packages/cli/src/modules/instance-ai/__tests__/instance-ai.service.build-mode.test.ts index e2d55e913c8..f4a4480fa02 100644 --- a/packages/cli/src/modules/instance-ai/__tests__/instance-ai.service.build-mode.test.ts +++ b/packages/cli/src/modules/instance-ai/__tests__/instance-ai.service.build-mode.test.ts @@ -72,12 +72,12 @@ function createService(checkpoint?: SerializableAgentState): ServiceInternals { describe('InstanceAiService build mode recovery', () => { it.each([ - { toolName: 'build-agent', hasBuilderCheckpoint: true, resumeAgentBuild: true }, - { toolName: 'build-agent', hasBuilderCheckpoint: false, resumeAgentBuild: false }, - { toolName: 'workflows', hasBuilderCheckpoint: true, resumeAgentBuild: false }, + { toolName: 'build-agent', hasBuilderCheckpoint: true }, + { toolName: 'build-agent', hasBuilderCheckpoint: false }, + { toolName: 'workflows', hasBuilderCheckpoint: true }, ])( 'restores $toolName with a builder checkpoint $hasBuilderCheckpoint', - async ({ toolName, hasBuilderCheckpoint, resumeAgentBuild }) => { + async ({ toolName, hasBuilderCheckpoint }) => { const suspendPayload = { requestId: orphan.requestId, message: 'Confirm the next step', @@ -121,8 +121,6 @@ describe('InstanceAiService build mode recovery', () => { undefined, undefined, undefined, - undefined, - resumeAgentBuild, ); }, ); diff --git a/packages/cli/src/modules/instance-ai/__tests__/instance-ai.service.errorMessage.test.ts b/packages/cli/src/modules/instance-ai/__tests__/instance-ai.service.errorMessage.test.ts index af0648c1e8b..11184a6c61c 100644 --- a/packages/cli/src/modules/instance-ai/__tests__/instance-ai.service.errorMessage.test.ts +++ b/packages/cli/src/modules/instance-ai/__tests__/instance-ai.service.errorMessage.test.ts @@ -202,36 +202,6 @@ describe('reclassifyMaskedStreamFailure', () => { ); }); - // The activation lock refuses use while the quota still has credits, so the numbers alone - // wouldn't explain the failure. - it('substitutes a quota-exhausted error when the proxy reports the pool locked', async () => { - const service = createService(async () => ({ - creditsQuota: 100, - creditsClaimed: 40, - quotaLocked: true, - })); - const masked = createNoOutputGeneratedError(); - - const resolved = await service.reclassifyMaskedStreamFailure(masked, user, context); - - expect(resolved).toBeInstanceOf(QuotaExhaustedStreamError); - }); - - // The lock is read from the proxy, never inferred from n8n's own trigger state: a lock call - // that failed leaves the pool open, and an unrelated stream death must not become a paywall. - it('keeps the original error when the proxy reports the pool unlocked', async () => { - const service = createService(async () => ({ - creditsQuota: 100, - creditsClaimed: 40, - quotaLocked: false, - })); - const masked = new TypeError('terminated'); - - await expect(service.reclassifyMaskedStreamFailure(masked, user, context)).resolves.toBe( - masked, - ); - }); - it('keeps the original error on the unlimited-credits sentinel', async () => { const service = createService(async () => ({ creditsQuota: -1, creditsClaimed: 0 })); const masked = new TypeError('terminated'); @@ -290,18 +260,6 @@ describe('assertAssistantCreditsAvailable', () => { expect(service.modelService.getCredits).toHaveBeenCalledTimes(1); }); - it('fails the run when the pool is locked', async () => { - const service = createService(async () => ({ - creditsQuota: 800, - creditsClaimed: 10, - quotaLocked: true, - })); - - await expect(service.assertAssistantCreditsAvailable(user)).rejects.toBeInstanceOf( - QuotaExhaustedStreamError, - ); - }); - it('allows a run that still has credits', async () => { const service = createService(async () => ({ creditsQuota: 800, creditsClaimed: 10 })); diff --git a/packages/cli/src/modules/instance-ai/__tests__/instance-ai.service.test.ts b/packages/cli/src/modules/instance-ai/__tests__/instance-ai.service.test.ts index 84ba2650d32..fdb3ce42162 100644 --- a/packages/cli/src/modules/instance-ai/__tests__/instance-ai.service.test.ts +++ b/packages/cli/src/modules/instance-ai/__tests__/instance-ai.service.test.ts @@ -267,6 +267,7 @@ import { createSandbox, createWorkspace, createInstanceAiTraceContext, + disabledInstanceAiSkillIds, loadInstanceAiPromptSkills, resumeAgentRun, streamAgentRun, @@ -600,7 +601,7 @@ type TerminalGuardOrderServiceInternals = { ) => void; backgroundTasks: { getRunningTasks: Mock; getRunningTasksByParentCheckpoint?: Mock }; temporaryWorkflowService: { reapForRun: Mock }; - creditService: { claimRunUsage: Mock; ensureQuotaLockApplied: Mock }; + creditService: { claimRunUsage: Mock }; failedInternalFollowUpStreaks: Map; schedulePlannedTasks: Mock; createPlannedTaskState: Mock; @@ -698,10 +699,7 @@ function createTerminalGuardOrderService(): TerminalGuardOrderServiceInternals { service.pendingBrowserCredentialSetups = new Map(); service.backgroundTasks = { getRunningTasks: vi.fn(() => []) }; service.temporaryWorkflowService = { reapForRun: vi.fn(async () => []) }; - service.creditService = { - claimRunUsage: vi.fn(async () => {}), - ensureQuotaLockApplied: vi.fn(async () => {}), - }; + service.creditService = { claimRunUsage: vi.fn(async () => {}) }; service.failedInternalFollowUpStreaks = new Map(); service.schedulePlannedTasks = vi.fn(async () => {}); service.preserveHitlOnShutdown = new Set(); @@ -825,18 +823,16 @@ describe('InstanceAiService — runtime workspace setup', () => { snapshotMode, instanceContextEnabled, boundGates: undefined as ContextGates | undefined, - resumeAgentBuild: false, })), ), ...[true, false].map((enabled) => ({ snapshotMode: 'off', instanceContextEnabled: !enabled, boundGates: { instanceContextEnabled: enabled, nodeUsageEnabled: !enabled }, - resumeAgentBuild: enabled, })), ]; it.each(environmentGates)('starts with gates %j', async (gates) => { - const { snapshotMode, instanceContextEnabled, boundGates, resumeAgentBuild } = gates; + const { snapshotMode, instanceContextEnabled, boundGates } = gates; const service = Object.create(InstanceAiService.prototype) as unknown as { createExecutionEnvironment: ( user: User, @@ -848,7 +844,6 @@ describe('InstanceAiService — runtime workspace setup', () => { proxyRunConfig?: undefined, instanceContextGates?: ContextGates, experimentGates?: undefined, - resumeAgentBuild?: boolean, ) => Promise<{ instanceContextEnabled: boolean; nodeUsageEnabled: boolean; @@ -922,7 +917,7 @@ describe('InstanceAiService — runtime workspace setup', () => { threadGrantRepo: { findKeys: Mock }; evalCredentialAllowlists: EvalThreadCredentialAllowlistService; instanceAiErrorReporter: ReturnType; - creditService: { claimRunUsage: Mock; ensureQuotaLockApplied: Mock }; + creditService: { claimRunUsage: Mock }; aiUsageService: { isParameterValueSharingAllowed: Mock }; areMcpConnectionsAvailable: Mock; }; @@ -1024,10 +1019,7 @@ describe('InstanceAiService — runtime workspace setup', () => { service.evalCredentialAllowlists = new EvalThreadCredentialAllowlistService(); service.instanceAiErrorReporter = createInstanceAiErrorReporterMock(); service.aiUsageService = { isParameterValueSharingAllowed: vi.fn(async () => true) }; - service.creditService = { - claimRunUsage: vi.fn(), - ensureQuotaLockApplied: vi.fn(async () => {}), - }; + service.creditService = { claimRunUsage: vi.fn() }; const sandbox = { id: 'sandbox-1' }; const workspace = { init: vi.fn(async () => {}), @@ -1036,6 +1028,10 @@ describe('InstanceAiService — runtime workspace setup', () => { (createSandbox as Mock).mockResolvedValue(sandbox); (createWorkspace as Mock).mockReturnValue(workspace); (setupSandboxWorkspace as Mock).mockResolvedValue(undefined); + const agentBuildingAvailable = snapshotMode === 'seeded'; + if (agentBuildingAvailable) { + service.adapterService.createContext.mockReturnValue({ builderDelegate: {} }); + } const environment = await service.createExecutionEnvironment( fakeUser, @@ -1046,8 +1042,10 @@ describe('InstanceAiService — runtime workspace setup', () => { undefined, undefined, boundGates, - undefined, - resumeAgentBuild, + ); + // The agent-building skills follow whether the context has a builder delegate. + expect(disabledInstanceAiSkillIds).toHaveBeenCalledWith( + expect.objectContaining({ agentBuildingEnabled: agentBuildingAvailable }), ); const expectedGates = boundGates ?? { instanceContextEnabled, @@ -1060,7 +1058,6 @@ describe('InstanceAiService — runtime workspace setup', () => { ...expectedGates, configEvalsEnabled: true, setupPanelVariant: snapshotMode === 'off' ? 'control' : 'variant', - resumeAgentBuild, }), ); expect(service.settingsService.getPermissions).toHaveBeenCalled(); @@ -1175,6 +1172,17 @@ describe('InstanceAiService — runtime workspace setup', () => { expect(workspace.init).toHaveBeenCalledTimes(1); expect(setupSandboxWorkspace).toHaveBeenCalledTimes(1); + // Runtime skills and workspace setup share the verified bundles of the sandbox. + const { resolveVerifiedBundles } = (createLazyWorkspaceRuntimeSkillSource as Mock).mock + .calls[0]?.[0] as { resolveVerifiedBundles: () => Promise }; + const verifiedBundles = await resolveVerifiedBundles(); + expect(verifiedBundles).toEqual(new Map()); + const setupOptions = (setupSandboxWorkspace as Mock).mock.calls[0]?.[2] as { + verifiedBundles: unknown; + }; + expect((setupSandboxWorkspace as Mock).mock.calls[0]?.[0]).toBe(workspace); + expect(setupOptions.verifiedBundles).toBe(verifiedBundles); + (createLazyRuntimeWorkspace as Mock).mockClear(); (createLazyWorkspaceRuntimeSkillSource as Mock).mockClear(); (createSandbox as Mock).mockClear(); @@ -1301,7 +1309,7 @@ describe('InstanceAiService — runtime workspace setup', () => { threadGrantRepo: { findKeys: Mock }; evalCredentialAllowlists: EvalThreadCredentialAllowlistService; instanceAiErrorReporter: ReturnType; - creditService: { claimRunUsage: Mock; ensureQuotaLockApplied: Mock }; + creditService: { claimRunUsage: Mock }; aiUsageService: { isParameterValueSharingAllowed: Mock }; areMcpConnectionsAvailable: Mock; }; @@ -1401,10 +1409,7 @@ describe('InstanceAiService — runtime workspace setup', () => { service.aiUsageService = { isParameterValueSharingAllowed: vi.fn(async () => allowSendingParameterValues), }; - service.creditService = { - claimRunUsage: vi.fn(), - ensureQuotaLockApplied: vi.fn(async () => {}), - }; + service.creditService = { claimRunUsage: vi.fn() }; (createSandbox as Mock).mockResolvedValue({ id: 'sandbox-1' }); (createWorkspace as Mock).mockReturnValue({ init: vi.fn(async () => {}), @@ -2962,7 +2967,6 @@ describe('InstanceAiService — suspended run user revalidation', () => { undefined, 'group-1', expect.objectContaining({ instanceContextEnabled: false, nodeUsageEnabled: true }), - toolName === 'build-agent', ); expect(service.processResumedStream).toHaveBeenCalledWith( rebuiltAgent, @@ -3067,7 +3071,6 @@ describe('InstanceAiService — suspended run user revalidation', () => { undefined, 'group-1', expect.objectContaining({ instanceContextEnabled: false, nodeUsageEnabled: true }), - false, ); expect(service.processResumedStream).toHaveBeenCalledWith( rebuiltAgent, @@ -3201,7 +3204,6 @@ describe('InstanceAiService — rebuildAgentForResume', () => { runHandoff: { handoffReason?: string } | undefined, messageGroupId?: string, instanceContextGates?: { instanceContextEnabled: boolean; nodeUsageEnabled: boolean }, - resumeAgentBuild?: boolean, ) => Promise<{ agent: unknown; modelId?: unknown } | undefined>; buildFreshInstanceAgent: Mock; threadPushRef: { get: Mock }; @@ -3240,7 +3242,6 @@ describe('InstanceAiService — rebuildAgentForResume', () => { undefined, 'group-1', gates, - enabled, ); expect(service.createExecutionEnvironment).toHaveBeenCalledWith( @@ -3252,8 +3253,6 @@ describe('InstanceAiService — rebuildAgentForResume', () => { undefined, undefined, gates, - undefined, - enabled, ); }); @@ -6422,7 +6421,7 @@ describe('createAgentMemoryOptions', () => { 'observerMessageTokens' | 'reflectorObservationTokens' >; runState: { getObserverThresholdTokens: Mock }; - creditService: { claimRunUsage: Mock; ensureQuotaLockApplied: Mock }; + creditService: { claimRunUsage: Mock }; logger: { warn: Mock }; }; @@ -6430,10 +6429,7 @@ describe('createAgentMemoryOptions', () => { const service = Object.create(InstanceAiService.prototype) as unknown as MemoryOptionsInternals; service.instanceAiConfig = { observerMessageTokens: 8_000, reflectorObservationTokens: 12_000 }; service.runState = { getObserverThresholdTokens: vi.fn().mockReturnValue(undefined) }; - service.creditService = { - claimRunUsage: vi.fn(async () => {}), - ensureQuotaLockApplied: vi.fn(async () => {}), - }; + service.creditService = { claimRunUsage: vi.fn(async () => {}) }; service.logger = { warn: vi.fn() }; return service; } @@ -7687,8 +7683,6 @@ describe('InstanceAiService — instance-context turn event', () => { undefined, undefined, saved.instanceContext, - undefined, - false, ); expect(checkpoint.persistence?.hostMetadata?.buildMode).toBe('default'); instanceContext = restored.state.instanceContext!; diff --git a/packages/cli/src/modules/instance-ai/agents-access.ts b/packages/cli/src/modules/instance-ai/agents-access.ts new file mode 100644 index 00000000000..7e92bef12bf --- /dev/null +++ b/packages/cli/src/modules/instance-ai/agents-access.ts @@ -0,0 +1,16 @@ +import { ModuleRegistry } from '@n8n/backend-common'; +import { Container } from '@n8n/di'; + +/** + * Whether the Assistant can use Agents: the Agents module is active and the + * Settings > Agents switch is on. Every main keeps the switch state current + * through the `reload-agents-settings` command, so the Assistant loses its + * Agents access as soon as an admin turns the switch off. + */ +export function isAgentsAccessEnabled( + moduleRegistry: ModuleRegistry = Container.get(ModuleRegistry), +): boolean { + return ( + moduleRegistry.isActive('agents') && moduleRegistry.settings.get('agents')?.enabled !== false + ); +} diff --git a/packages/cli/src/modules/instance-ai/eval/README.md b/packages/cli/src/modules/instance-ai/eval/README.md index dda59b716a5..3f3bb030146 100644 --- a/packages/cli/src/modules/instance-ai/eval/README.md +++ b/packages/cli/src/modules/instance-ai/eval/README.md @@ -9,7 +9,7 @@ Mocks the **raw HTTP response a service sends over the wire**. The node then executes for real: its routing, pagination, response parsing, and post-processing (e.g. `simplify` options) all run against the mocked body. -- Shape source: fetched API documentation (`api-docs.ts`) + endpoint quirks. +- Shape source: the LLM's own knowledge of the API + endpoint quirks. - Used when a node executes against intercepted HTTP. ## Node-output level — pin data / simulation fixtures diff --git a/packages/cli/src/modules/instance-ai/eval/__tests__/agent-execution.service.test.ts b/packages/cli/src/modules/instance-ai/eval/__tests__/agent-execution.service.test.ts index 9db7a14ffb6..e873bec3ebb 100644 --- a/packages/cli/src/modules/instance-ai/eval/__tests__/agent-execution.service.test.ts +++ b/packages/cli/src/modules/instance-ai/eval/__tests__/agent-execution.service.test.ts @@ -15,6 +15,8 @@ import { AgentsSettingsService } from '@/modules/agents/agents-settings.service' import type { Agent as AgentEntity } from '@/modules/agents/entities/agent.entity'; import type { AgentRunSource } from '@/modules/agents/utils/agent-published-snapshot'; import { AgentRepository } from '@/modules/agents/repositories/agent.repository'; +import { AgentSkillRefsService } from '@/modules/agents/agent-skill-refs.service'; +import { createAgentSkillRefsService } from '@/modules/agents/__tests__/test-utils/stored-agent-config'; import { createAgentCredentialProvider } from '@/modules/agents/utils/agent-credential-provider'; import { userHasScopes } from '@/permissions.ee/check-access'; @@ -108,13 +110,23 @@ const makeGenerateResult = (overrides: Partial = {}): GenerateRe ...overrides, }) as unknown as GenerateResult; -function buildService(overrides: { queueMode?: boolean; agentsActive?: boolean } = {}) { +function buildService( + overrides: { + queueMode?: boolean; + agentsActive?: boolean; + mcpRegistryActive?: boolean; + } = {}, +) { const executionsConfig = mock(); Object.defineProperty(executionsConfig, 'mode', { get: () => (overrides.queueMode ? 'queue' : 'regular'), }); const moduleRegistry = mock(); - moduleRegistry.isActive.mockReturnValue(overrides.agentsActive ?? true); + moduleRegistry.isActive.mockImplementation((moduleName) => { + if (moduleName === 'agents') return overrides.agentsActive ?? true; + if (moduleName === 'mcp-registry') return overrides.mcpRegistryActive ?? true; + return true; + }); return new EvalAgentExecutionService( logger, executionsConfig, @@ -130,6 +142,7 @@ describe('EvalAgentExecutionService.executeWithLlmMock', () => { settingsService.getEnabled.mockResolvedValue(true); Container.set(AgentsSettingsService, settingsService); Container.set(AgentRepository, { findByIdAndProjectId } as unknown as AgentRepository); + Container.set(AgentSkillRefsService, createAgentSkillRefsService()); Container.set(AgentRuntimeReconstructionService, { reconstructFromAgentEntity, } as unknown as AgentRuntimeReconstructionService); @@ -460,6 +473,46 @@ describe('EvalAgentExecutionService.executeWithLlmMock', () => { ]); }); + it('uses explicit non-blocked tools as the canonical catalog when both categories are blocked', async () => { + const config = { + ...baseConfig, + mcpServers: [ + { + name: 'Restricted MCP', + url: 'https://custom.example.com/mcp', + transport: 'streamableHttp', + authentication: 'none', + toolPermissions: { + categories: { read: 'blocked', write: 'blocked' }, + tools: { + search: 'always_allow', + update: 'require_approval', + delete: 'blocked', + }, + }, + }, + ], + } as unknown as AgentJsonConfig; + findByIdAndProjectId.mockResolvedValue(makeEntity(config)); + reconstructFromAgentEntity.mockResolvedValue({ + agent: { generate: vi.fn().mockResolvedValue(makeGenerateResult()), close: vi.fn() }, + toolRegistry: {}, + }); + + await buildService({ mcpRegistryActive: false }).executeWithLlmMock('agent-1', user, request); + + expect(createMcpMockFetch).toHaveBeenCalledWith( + expect.objectContaining({ + knownToolsByServer: { + 'Restricted MCP': [ + { name: 'search', description: 'search' }, + { name: 'update', description: 'update' }, + ], + }, + }), + ); + }); + it('prunes unmockable features and reports them', async () => { const fullConfig = { ...baseConfig, @@ -490,11 +543,13 @@ describe('EvalAgentExecutionService.executeWithLlmMock', () => { expect(rebuiltEntity.schema?.subAgents).toEqual({ agents: [{ agentId: 'child-1' }] }); }); - it('keeps the draft skill refs through pruning', async () => { + it('keeps the draft skill refs and their bodies through pruning', async () => { const skillRefs = [ { type: 'skill' as const, id: 'zeta' }, - { type: 'skill' as const, id: 'alpha', enabled: false }, + { type: 'skill' as const, id: 'alpha' }, ]; + const zeta = { name: 'Zeta', description: 'Zeta skill', instructions: 'Use zeta.' }; + Container.set(AgentSkillRefsService, createAgentSkillRefsService({ zeta })); findByIdAndProjectId.mockResolvedValue(makeEntity({ ...baseConfig, skills: skillRefs })); reconstructFromAgentEntity.mockResolvedValue({ agent: { generate: vi.fn().mockResolvedValue(makeGenerateResult()), close: vi.fn() }, @@ -505,6 +560,7 @@ describe('EvalAgentExecutionService.executeWithLlmMock', () => { const runSource = reconstructFromAgentEntity.mock.calls[0][0] as AgentRunSource; expect(runSource.skillRefs).toEqual(skillRefs); + expect(runSource.skills).toEqual({ zeta }); }); it('serves fallback web search and configured sub-agents through the instrumentation', async () => { diff --git a/packages/cli/src/modules/instance-ai/eval/__tests__/api-docs.test.ts b/packages/cli/src/modules/instance-ai/eval/__tests__/api-docs.test.ts deleted file mode 100644 index 0d232f3c21e..00000000000 --- a/packages/cli/src/modules/instance-ai/eval/__tests__/api-docs.test.ts +++ /dev/null @@ -1,254 +0,0 @@ -import type { Mock } from 'vitest'; -const mockLogger = { - warn: vi.fn(), - debug: vi.fn(), -}; - -vi.mock('@n8n/backend-common', () => ({ - Logger: class Logger {}, -})); - -vi.mock('@n8n/di', () => ({ - Container: { - get: vi.fn().mockReturnValue(mockLogger), - }, - Service: () => vi.fn(), -})); - -// --------------------------------------------------------------------------- -// Helpers -// --------------------------------------------------------------------------- - -const FALLBACK_INSTRUCTIONS = - 'No API documentation was found for this endpoint. Generate the response based on your knowledge of this API. Follow standard REST conventions for the HTTP method: GET returns resource data, POST returns the created resource, PUT/PATCH returns the updated resource, DELETE returns 204 or confirmation.'; - -let mockFetch: Mock; -let savedApiKey: string | undefined; - -function mockFetchResponse(status: number, body: unknown, ok?: boolean) { - const isOk = ok ?? (status >= 200 && status < 300); - const textBody = typeof body === 'string' ? body : JSON.stringify(body); - mockFetch.mockResolvedValueOnce({ - ok: isOk, - status, - text: vi.fn().mockResolvedValue(textBody), - json: vi.fn().mockResolvedValue(body), - }); -} - -beforeEach(() => { - vi.resetModules(); - vi.clearAllMocks(); - mockFetch = vi.fn(); - global.fetch = mockFetch; - savedApiKey = process.env.CONTEXT7_API_KEY; - delete process.env.CONTEXT7_API_KEY; -}); - -afterEach(() => { - if (savedApiKey !== undefined) { - process.env.CONTEXT7_API_KEY = savedApiKey; - } else { - delete process.env.CONTEXT7_API_KEY; - } -}); - -// --------------------------------------------------------------------------- -// resolveLibraryId (tested indirectly through fetchApiDocs) -// --------------------------------------------------------------------------- - -describe('resolveLibraryId (via fetchApiDocs)', () => { - it('should return docs when library search and docs fetch both succeed', async () => { - const { fetchApiDocs } = await import('../api-docs.js'); - - // Library search - mockFetchResponse(200, [{ id: '/lib/slack-api', trust_score: 90 }]); - // Docs fetch - mockFetchResponse(200, 'POST /chat.postMessage — sends a message to a channel'); - - const result = await fetchApiDocs('Slack', 'chat.postMessage'); - - expect(result).toBe('POST /chat.postMessage — sends a message to a channel'); - expect(mockFetch).toHaveBeenCalledTimes(2); - }); - - it('should cache library ID — second call does not re-fetch library search', async () => { - const { fetchApiDocs } = await import('../api-docs.js'); - - // First call: library search + docs - mockFetchResponse(200, [{ id: '/lib/slack-api', trust_score: 90 }]); - mockFetchResponse(200, 'docs for postMessage'); - - await fetchApiDocs('Slack', 'chat.postMessage'); - - // Second call: only docs fetch needed (library ID is cached) - mockFetchResponse(200, 'docs for conversations.list'); - - const result = await fetchApiDocs('Slack', 'conversations.list'); - - expect(result).toBe('docs for conversations.list'); - // 2 from first call + 1 from second call = 3 - expect(mockFetch).toHaveBeenCalledTimes(3); - }); - - it('should return fallback when library search returns non-200', async () => { - const { fetchApiDocs } = await import('../api-docs.js'); - - mockFetchResponse(500, 'Internal Server Error'); - - const result = await fetchApiDocs('FakeService', 'endpoint'); - - expect(result).toBe(FALLBACK_INSTRUCTIONS); - expect(mockFetch).toHaveBeenCalledTimes(1); - }); - - it('should return fallback when library search returns empty results', async () => { - const { fetchApiDocs } = await import('../api-docs.js'); - - mockFetchResponse(200, []); - - const result = await fetchApiDocs('ObscureService', 'endpoint'); - - expect(result).toBe(FALLBACK_INSTRUCTIONS); - expect(mockFetch).toHaveBeenCalledTimes(1); - }); - - it('should log warning on 429 status (quota exceeded)', async () => { - const { fetchApiDocs } = await import('../api-docs.js'); - - mockFetchResponse(429, 'Rate limit exceeded'); - - await fetchApiDocs('Slack', 'endpoint'); - - expect(mockLogger.warn).toHaveBeenCalledWith( - expect.stringContaining('Context7 quota exceeded'), - ); - }); - - it('should log warning when response body contains "Quota"', async () => { - const { fetchApiDocs } = await import('../api-docs.js'); - - mockFetchResponse(403, 'Quota limit reached for your plan'); - - await fetchApiDocs('Slack', 'endpoint'); - - expect(mockLogger.warn).toHaveBeenCalledWith( - expect.stringContaining('Context7 quota exceeded'), - ); - }); - - it('should log warning only once per session (context7WarningLogged flag)', async () => { - const { fetchApiDocs } = await import('../api-docs.js'); - - // First call — 429, should warn - mockFetchResponse(429, 'Rate limit'); - await fetchApiDocs('Service1', 'endpoint'); - - // Second call — also 429, should NOT warn again - mockFetchResponse(429, 'Rate limit'); - await fetchApiDocs('Service2', 'endpoint'); - - expect(mockLogger.warn).toHaveBeenCalledTimes(1); - }); - - it('should return fallback on fetch timeout / network error', async () => { - const { fetchApiDocs } = await import('../api-docs.js'); - - mockFetch.mockRejectedValueOnce(new Error('network timeout')); - - const result = await fetchApiDocs('Slack', 'endpoint'); - - expect(result).toBe(FALLBACK_INSTRUCTIONS); - expect(mockLogger.debug).toHaveBeenCalledWith( - expect.stringContaining('Context7 library search failed'), - ); - }); -}); - -// --------------------------------------------------------------------------- -// fetchApiDocs -// --------------------------------------------------------------------------- - -describe('fetchApiDocs', () => { - it('should return docs text from Context7 on success', async () => { - const { fetchApiDocs } = await import('../api-docs.js'); - - mockFetchResponse(200, [{ id: '/lib/github-api', trust_score: 80 }]); - mockFetchResponse(200, 'GET /repos/{owner}/{repo} — returns a repository'); - - const result = await fetchApiDocs('GitHub', 'repos'); - - expect(result).toBe('GET /repos/{owner}/{repo} — returns a repository'); - }); - - it('should cache docs per serviceName + endpointQuery', async () => { - const { fetchApiDocs } = await import('../api-docs.js'); - - // First call: library search + docs - mockFetchResponse(200, [{ id: '/lib/slack-api', trust_score: 90 }]); - mockFetchResponse(200, 'cached docs content'); - - const first = await fetchApiDocs('Slack', 'chat.postMessage'); - - // Second call with same args: should hit cache, no fetch - const second = await fetchApiDocs('Slack', 'chat.postMessage'); - - expect(first).toBe('cached docs content'); - expect(second).toBe('cached docs content'); - // Only 2 fetches total (library search + docs from first call) - expect(mockFetch).toHaveBeenCalledTimes(2); - }); - - it('should return fallback when docs endpoint returns non-200', async () => { - const { fetchApiDocs } = await import('../api-docs.js'); - - mockFetchResponse(200, [{ id: '/lib/slack-api', trust_score: 90 }]); - mockFetchResponse(500, 'Server Error'); - - const result = await fetchApiDocs('Slack', 'endpoint'); - - expect(result).toBe(FALLBACK_INSTRUCTIONS); - }); - - it('should return fallback when docs response is empty text', async () => { - const { fetchApiDocs } = await import('../api-docs.js'); - - mockFetchResponse(200, [{ id: '/lib/slack-api', trust_score: 90 }]); - mockFetchResponse(200, ' '); - - const result = await fetchApiDocs('Slack', 'endpoint'); - - expect(result).toBe(FALLBACK_INSTRUCTIONS); - }); - - it('should pass CONTEXT7_API_KEY as Bearer Authorization header when env var is set', async () => { - process.env.CONTEXT7_API_KEY = 'test-api-key-123'; - const { fetchApiDocs } = await import('../api-docs.js'); - - mockFetchResponse(200, [{ id: '/lib/slack-api', trust_score: 90 }]); - mockFetchResponse(200, 'docs'); - - await fetchApiDocs('Slack', 'endpoint'); - - // Both the library search and docs fetch should include the header - for (const call of mockFetch.mock.calls) { - const options = call[1] as { headers: Record }; - expect(options.headers.Authorization).toBe('Bearer test-api-key-123'); - } - }); - - it('should not send Authorization header when CONTEXT7_API_KEY is not set', async () => { - delete process.env.CONTEXT7_API_KEY; - const { fetchApiDocs } = await import('../api-docs.js'); - - mockFetchResponse(200, [{ id: '/lib/slack-api', trust_score: 90 }]); - mockFetchResponse(200, 'docs'); - - await fetchApiDocs('Slack', 'endpoint'); - - for (const call of mockFetch.mock.calls) { - const options = call[1] as { headers: Record }; - expect(options.headers).not.toHaveProperty('Authorization'); - } - }); -}); diff --git a/packages/cli/src/modules/instance-ai/eval/__tests__/mcp-mock-fetch.test.ts b/packages/cli/src/modules/instance-ai/eval/__tests__/mcp-mock-fetch.test.ts index fb4b4e35182..6def62f73ed 100644 --- a/packages/cli/src/modules/instance-ai/eval/__tests__/mcp-mock-fetch.test.ts +++ b/packages/cli/src/modules/instance-ai/eval/__tests__/mcp-mock-fetch.test.ts @@ -9,6 +9,7 @@ const extractText = vi.fn(); vi.mock('@n8n/instance-ai', () => ({ createEvalAgent: vi.fn(() => ({ generate })), extractText: (result: unknown) => extractText(result) as string, + isRetryableEvalError: () => true, })); const logger = mock(); diff --git a/packages/cli/src/modules/instance-ai/eval/__tests__/mock-handler.test.ts b/packages/cli/src/modules/instance-ai/eval/__tests__/mock-handler.test.ts index 7cdd9c61a78..5eec4c4b7fc 100644 --- a/packages/cli/src/modules/instance-ai/eval/__tests__/mock-handler.test.ts +++ b/packages/cli/src/modules/instance-ai/eval/__tests__/mock-handler.test.ts @@ -86,8 +86,6 @@ vi.mock('@n8n/agents/tool', () => ({ }), })); -vi.mock('../api-docs', () => ({ fetchApiDocs: vi.fn().mockResolvedValue('') })); - vi.mock('../node-config', () => ({ extractNodeConfig: vi.fn().mockReturnValue('{}'), })); @@ -114,7 +112,6 @@ import { fileTypeFromBuffer } from 'file-type'; import FormData from 'form-data'; import type { IHttpRequestOptions, INode } from 'n8n-workflow'; -import { fetchApiDocs } from '../api-docs'; import { buildDateAnchors, createLlmMockHandler, @@ -128,7 +125,6 @@ import { extractNodeConfig } from '../node-config'; // matter for tests to pass. Keep in sync with the factory bodies above. function reapplyMockImplementations() { vi.mocked(Container.get).mockReturnValue(mockLogger); - vi.mocked(fetchApiDocs).mockResolvedValue(''); vi.mocked(extractNodeConfig).mockReturnValue('{}'); vi.mocked(createEvalAgent).mockReturnValue(mockAgent as never); vi.mocked(Tool).mockImplementation(function (name: string) { @@ -1031,6 +1027,19 @@ describe('get_endpoint_quirks tool', () => { expect(quirksCapture.handler).toBeDefined(); const result = await quirksCapture.handler!(); expect(result).toContain('No specific quirks'); + expect(result).not.toMatch(/API docs/i); + }); + + it('points the model at its own API knowledge, never at attached docs', async () => { + llmSubmits({ type: 'json', body: {} }); + const handler = createLlmMockHandler(); + + await handler(baseRequest, baseNode); + + const { instructions } = vi.mocked(createEvalAgent).mock.calls.at(-1)![1] as { + instructions: string; + }; + expect(instructions).not.toMatch(/\bdocs\b|documentation/i); }); }); diff --git a/packages/cli/src/modules/instance-ai/eval/__tests__/mock-utils.test.ts b/packages/cli/src/modules/instance-ai/eval/__tests__/mock-utils.test.ts new file mode 100644 index 00000000000..7cb911e1354 --- /dev/null +++ b/packages/cli/src/modules/instance-ai/eval/__tests__/mock-utils.test.ts @@ -0,0 +1,60 @@ +import type { Logger } from '@n8n/backend-common'; +import { mock } from 'vitest-mock-extended'; + +const generate = vi.fn(); + +vi.mock('@n8n/instance-ai', async () => { + const evalAgents = await vi.importActual('@n8n/instance-ai'); + return { + createEvalAgent: () => ({ generate }), + extractText: evalAgents.extractText, + isRetryableEvalError: evalAgents.isRetryableEvalError, + }; +}); + +import { generateJson } from '../mock-utils'; + +const validate = (parsed: unknown) => (parsed && typeof parsed === 'object' ? parsed : undefined); + +describe('generateJson', () => { + beforeEach(() => generate.mockReset()); + + it('does not retry a model error the provider will not recover from', async () => { + generate.mockResolvedValue({ + messages: [], + finishReason: 'error', + error: Object.assign(new Error('invalid x-api-key'), { statusCode: 401, isRetryable: false }), + }); + const logger = mock(); + + expect(await generateJson('mock', 'instructions', 'prompt', validate, logger)).toBeUndefined(); + expect(generate).toHaveBeenCalledTimes(1); + expect(logger.warn).toHaveBeenCalledWith( + expect.stringContaining('Eval model provider call failed (HTTP 401): invalid x-api-key'), + ); + }); + + it('retries a model error the provider can recover from, then gives up', async () => { + generate.mockResolvedValue({ + messages: [], + finishReason: 'error', + error: Object.assign(new Error('Overloaded'), { statusCode: 529, isRetryable: true }), + }); + + expect(await generateJson('mock', 'i', 'p', validate, mock())).toBeUndefined(); + expect(generate).toHaveBeenCalledTimes(2); + }); + + it('retries an unusable shape', async () => { + generate + .mockResolvedValueOnce({ + messages: [{ role: 'assistant', content: [{ type: 'text', text: 'not json' }] }], + }) + .mockResolvedValueOnce({ + messages: [{ role: 'assistant', content: [{ type: 'text', text: '{"ok":true}' }] }], + }); + + expect(await generateJson('mock', 'i', 'p', validate, mock())).toEqual({ ok: true }); + expect(generate).toHaveBeenCalledTimes(2); + }); +}); diff --git a/packages/cli/src/modules/instance-ai/eval/__tests__/thread-credential-allowlist.service.test.ts b/packages/cli/src/modules/instance-ai/eval/__tests__/thread-credential-allowlist.service.test.ts index c71404e821a..f15372c01b0 100644 --- a/packages/cli/src/modules/instance-ai/eval/__tests__/thread-credential-allowlist.service.test.ts +++ b/packages/cli/src/modules/instance-ai/eval/__tests__/thread-credential-allowlist.service.test.ts @@ -55,3 +55,44 @@ describe('EvalThreadCredentialAllowlistService', () => { expect(service.get('thread-1')).toBeUndefined(); }); }); + +describe('EvalThreadCredentialAllowlistService test targets', () => { + let service: EvalThreadCredentialAllowlistService; + const target = { + credentialType: 'slackApi', + baseUrl: 'http://stand-in.test:4100', + urlField: 'url', + }; + + beforeEach(() => { + service = new EvalThreadCredentialAllowlistService(); + }); + + it('returns the target for its credential type only', () => { + service.setTestTarget('thread-1', target); + + expect(service.getTestTarget('thread-1', 'slackApi')).toEqual(target); + expect(service.getTestTarget('thread-1', 'openAiApi')).toBeUndefined(); + expect(service.getTestTarget('thread-2', 'slackApi')).toBeUndefined(); + }); + + it('keeps a target for each credential type', () => { + const openAi = { + credentialType: 'openAiApi', + baseUrl: 'http://stand-in.test:4200', + urlField: 'url', + }; + service.setTestTarget('thread-1', target); + service.setTestTarget('thread-1', openAi); + + expect(service.getTestTarget('thread-1', 'slackApi')).toEqual(target); + expect(service.getTestTarget('thread-1', 'openAiApi')).toEqual(openAi); + }); + + it('forgets the target when the thread is cleared', () => { + service.setTestTarget('thread-1', target); + service.clearThread('thread-1'); + + expect(service.getTestTarget('thread-1', 'slackApi')).toBeUndefined(); + }); +}); diff --git a/packages/cli/src/modules/instance-ai/eval/__tests__/thread-restore.service.test.ts b/packages/cli/src/modules/instance-ai/eval/__tests__/thread-restore.service.test.ts index b7649620ecf..cf04fc4224f 100644 --- a/packages/cli/src/modules/instance-ai/eval/__tests__/thread-restore.service.test.ts +++ b/packages/cli/src/modules/instance-ai/eval/__tests__/thread-restore.service.test.ts @@ -638,6 +638,7 @@ describe('EvalThreadRestoreService', () => { id: 'agent-original', schema: agent.config, skills: agent.skills, + skillCreator: evalUser, }); }); diff --git a/packages/cli/src/modules/instance-ai/eval/__tests__/web-search-mock.test.ts b/packages/cli/src/modules/instance-ai/eval/__tests__/web-search-mock.test.ts index 3011774626f..ee186ac8333 100644 --- a/packages/cli/src/modules/instance-ai/eval/__tests__/web-search-mock.test.ts +++ b/packages/cli/src/modules/instance-ai/eval/__tests__/web-search-mock.test.ts @@ -10,6 +10,7 @@ const extractText = vi.fn(); vi.mock('@n8n/instance-ai', () => ({ createEvalAgent: vi.fn(() => ({ generate })), extractText: (result: unknown) => extractText(result) as string, + isRetryableEvalError: () => true, })); const logger = mock(); diff --git a/packages/cli/src/modules/instance-ai/eval/agent-execution.service.ts b/packages/cli/src/modules/instance-ai/eval/agent-execution.service.ts index 5c6127688cb..9fb89bcbe77 100644 --- a/packages/cli/src/modules/instance-ai/eval/agent-execution.service.ts +++ b/packages/cli/src/modules/instance-ai/eval/agent-execution.service.ts @@ -99,9 +99,10 @@ export function mcpUrlsMatch(configUrl: string, remoteUrl: string): boolean { /** * Resolve canonical tool catalogs for configured MCP servers, so the mock * exposes the tools the real server would: registry entries carry the - * server's declared catalog (matched by remote URL), and an allow-mode - * toolFilter pins names even without a registry match. Best-effort — - * without a match the mock's LLM-designed catalog applies. + * server's declared catalog (matched by remote URL), and a policy with both + * categories blocked pins its explicit non-blocked overrides even without a + * registry match. Best-effort — without a match the mock's LLM-designed + * catalog applies. */ export async function resolveCanonicalMcpCatalogs( mcpServers: NonNullable, @@ -134,11 +135,12 @@ export async function resolveCanonicalMcpCatalogs( for (const server of mcpServers) { if (result[server.name]) continue; - if (server.toolFilter?.mode === 'allow' && server.toolFilter.tools.length > 0) { - result[server.name] = server.toolFilter.tools.map((name) => ({ - name, - description: name, - })); + const permissions = server.toolPermissions; + if (permissions?.categories.read === 'blocked' && permissions.categories.write === 'blocked') { + const allowedTools = Object.entries(permissions.tools ?? {}) + .filter(([, permission]) => permission !== 'blocked') + .map(([name]) => ({ name, description: name })); + if (allowedTools.length > 0) result[server.name] = allowedTools; } } @@ -199,7 +201,8 @@ export class EvalAgentExecutionService { return this.errorResult(`Agent ${agentId} has no JSON config to run.`); } - const skillRefs = await Container.get(AgentSkillRefsService).refsForDraft(agentEntity, {}); + const agentSkillRefs = Container.get(AgentSkillRefsService); + const skillRefs = await agentSkillRefs.refsForDraft(agentEntity, {}); const { config, skippedFeatures } = pruneConfigForEval( toAgentDocument(agentEntity.schema, skillRefs), ); @@ -354,7 +357,11 @@ export class EvalAgentExecutionService { let agent: RuntimeAgent; try { ({ agent } = await reconstruction.reconstructFromAgentEntity( - { agent: agentEntity, skillRefs: pruned.skillRefs }, + { + agent: agentEntity, + skillRefs: pruned.skillRefs, + skills: await agentSkillRefs.skillsForRefs(agentEntity, pruned.skillRefs, {}), + }, credentialProvider, 'test', undefined, diff --git a/packages/cli/src/modules/instance-ai/eval/api-docs.ts b/packages/cli/src/modules/instance-ai/eval/api-docs.ts deleted file mode 100644 index aee8101baf4..00000000000 --- a/packages/cli/src/modules/instance-ai/eval/api-docs.ts +++ /dev/null @@ -1,106 +0,0 @@ -/** - * API documentation fetcher for eval mock generation. - * - * Uses Context7 to fetch real API documentation at runtime so the - * Phase 2 LLM can generate accurate mock responses for any service. - * Results are cached per query to avoid redundant fetches. - */ - -import { Logger } from '@n8n/backend-common'; -import { Container } from '@n8n/di'; - -const CONTEXT7_BASE_URL = 'https://context7.com/api/v2'; -const FETCH_TIMEOUT_MS = 10_000; - -const FALLBACK_INSTRUCTIONS = - 'No API documentation was found for this endpoint. Generate the response based on your knowledge of this API. Follow standard REST conventions for the HTTP method: GET returns resource data, POST returns the created resource, PUT/PATCH returns the updated resource, DELETE returns 204 or confirmation.'; - -const docsCache = new Map(); - -/** Track whether we've warned about context7 issues this session */ -let context7WarningLogged = false; - -async function resolveLibraryId(serviceName: string): Promise { - const cacheKey = `lib:${serviceName}`; - if (docsCache.has(cacheKey)) return docsCache.get(cacheKey); - - try { - const apiKey = process.env.CONTEXT7_API_KEY; - const headers: Record = {}; - if (apiKey) headers.Authorization = `Bearer ${apiKey}`; - - const url = `${CONTEXT7_BASE_URL}/libs/search?libraryName=${encodeURIComponent(serviceName + ' API')}&query=REST+API+endpoints+response+format`; - const res = await fetch(url, { signal: AbortSignal.timeout(FETCH_TIMEOUT_MS), headers }); - - if (!res.ok) { - const body = await res.text().catch(() => ''); - if (body.includes('Quota') || body.includes('quota') || res.status === 429) { - if (!context7WarningLogged) { - Container.get(Logger).warn( - '[EvalMock] Context7 quota exceeded — mock responses will rely on LLM training data. Set CONTEXT7_API_KEY for higher limits.', - ); - context7WarningLogged = true; - } - } - return undefined; - } - - const results = (await res.json()) as Array<{ id: string; trust_score?: number }>; - const best = results.sort((a, b) => (b.trust_score ?? 0) - (a.trust_score ?? 0))[0]; - if (best?.id) { - docsCache.set(cacheKey, best.id); - return best.id; - } - } catch (error) { - Container.get(Logger).debug( - `[EvalMock] Context7 library search failed for "${serviceName}": ${error instanceof Error ? error.message : String(error)}`, - ); - } - return undefined; -} - -/** - * Fetch API documentation for a specific endpoint from Context7. - * Returns plain text ready for LLM consumption. - * When docs aren't available, returns explicit fallback instructions - * so the LLM knows to use its training data. - */ -export async function fetchApiDocs(serviceName: string, endpointQuery: string): Promise { - const cacheKey = `docs:${serviceName}:${endpointQuery}`; - if (docsCache.has(cacheKey)) return docsCache.get(cacheKey)!; - - const libraryId = await resolveLibraryId(serviceName); - if (!libraryId) return FALLBACK_INSTRUCTIONS; - - try { - const apiKey = process.env.CONTEXT7_API_KEY; - const headers: Record = {}; - if (apiKey) headers.Authorization = `Bearer ${apiKey}`; - - const url = `${CONTEXT7_BASE_URL}/context?libraryId=${encodeURIComponent(libraryId)}&query=${encodeURIComponent(endpointQuery)}&type=txt`; - const res = await fetch(url, { signal: AbortSignal.timeout(FETCH_TIMEOUT_MS), headers }); - - if (!res.ok) { - if (res.status === 429) { - if (!context7WarningLogged) { - Container.get(Logger).warn( - '[EvalMock] Context7 quota exceeded — mock responses will rely on LLM training data. Set CONTEXT7_API_KEY for higher limits.', - ); - context7WarningLogged = true; - } - } - return FALLBACK_INSTRUCTIONS; - } - - const text = await res.text(); - if (!text.trim()) return FALLBACK_INSTRUCTIONS; - - docsCache.set(cacheKey, text); - return text; - } catch (error) { - Container.get(Logger).debug( - `[EvalMock] Context7 docs fetch failed for "${serviceName}": ${error instanceof Error ? error.message : String(error)}`, - ); - return FALLBACK_INSTRUCTIONS; - } -} diff --git a/packages/cli/src/modules/instance-ai/eval/mock-handler.ts b/packages/cli/src/modules/instance-ai/eval/mock-handler.ts index 9c1cbb68fac..2a82f6dbd05 100644 --- a/packages/cli/src/modules/instance-ai/eval/mock-handler.ts +++ b/packages/cli/src/modules/instance-ai/eval/mock-handler.ts @@ -18,7 +18,6 @@ import { buildPdfWithText, synthesizeBinaryFixture } from 'n8n-core'; import { OperationalError } from 'n8n-workflow'; import { z } from 'zod'; -import { fetchApiDocs } from './api-docs'; import { buildDateAnchors } from './date-anchors'; import { findMockQuirks } from './mock-quirks'; import { extractNodeConfig } from './node-config'; @@ -39,19 +38,21 @@ export { buildDateAnchors } from './date-anchors'; const MOCK_SYSTEM_PROMPT = `You generate realistic HTTP responses for one specific request, mocking an API in n8n workflow evaluation. -You get everything you need in the user message: the request (service, method, URL, body, query), API docs for the endpoint, the n8n node's parameters, and optional context (globalContext, nodeHint, scenarioHints). +You get everything you need in the user message: the request (service, method, URL, body, query), the n8n node's parameters, and optional context (globalContext, nodeHint, scenarioHints). **Procedure — follow in order:** 1. Call \`get_endpoint_quirks\` first, always. It returns any known guidance specific to this endpoint, or confirms there are none. Treat its output as authoritative. -2. Generate the response that satisfies the API docs, node config, scenario context, and any quirk guidance from step 1. +2. Generate the response that matches the real API, the node config, scenario context, and any quirk guidance from step 1. 3. Call \`submit_response\` to deliver the response. If it returns a message starting with "Invalid:", fix the input and call it again — your response only counts once it is accepted. Do not write the response as text. **Write operations (POST / PUT / PATCH that create or modify a resource):** -Return the FULL resource object the API produces on success — not a minimal acknowledgement-only response. When the docs show multiple response variants for one endpoint, default to the FULL/complete one. Use a partial/minimal variant only if the request body contains the explicit field that triggers it (e.g. \`template\`, \`async: true\`). +Return the FULL resource object the API produces on success — not a minimal acknowledgement-only response. When the API has multiple response variants for one endpoint, default to the FULL/complete one. Use a partial/minimal variant only if the request body contains the explicit field that triggers it (e.g. \`template\`, \`async: true\`). Each request is mocked independently. Even when the same node makes multiple similar calls in a workflow, every call must produce a fully-shaped response on its own — never shortcut later calls. (Byte-identical repeats of a request you already answered are served from a cache and never reach you — any request you DO see is distinct and needs its own full response.) -Response SHAPE comes from the API docs; DATA VALUES come from the node config. Use names/IDs from the config exactly (case-sensitive). +Response SHAPE comes from your knowledge of the real API; DATA VALUES come from the node config. Use names/IDs from the config exactly (case-sensitive). + +**Hints carry data, not layout.** The Data, Hint and Scenario lines were written before the run, without seeing this request. Take facts from them: names, IDs, values, counts, dates, statuses, and which entity fails. Take the response LAYOUT only from the real API: the endpoint quirks and your own knowledge of this endpoint. When a hint describes a layout (JSON, field paths, "return {...}") or what the n8n node outputs after its own processing (simplified records, rows keyed by column header, parsed JSON, json.data), use its values and ignore its layout. A node can send several requests, and its hint can describe another one of them (for example the append when this request reads metadata): use only the facts that fit THIS request. Decide what kind of call this is from the request itself: the HTTP method, the URL path and, when one path serves many kinds of call (for example GraphQL), the operation in the body (a GraphQL \`query\` reads, a \`mutation\` writes). Do not decide from the node's name, the node's operation setting or the hint. Return that call's own response. For example, when a node that appends a row first reads the sheet, that read returns the sheet as it is now, not the append result. **Honor explicit values from the scenario and hints.** When the scenarioHints, nodeHint, or globalContext state a specific value — a quantity with a unit, a percentage, a monetary amount ("$1,200"), a count ("3 rows"), a threshold, an ID, or a name — reproduce that EXACT value in the response. Do NOT round it, soften it toward a "more typical" reading, or substitute your own estimate: the stated value is the test's intent, and downstream nodes (IF/Switch gates, filters, sums) compare against it. Emit the exact number of enumerated items the context describes. This extends to per-item constraints: when the scenario says EVERY/ALL items share a property (a literal substring every title must contain, a minimum every row must exceed), EVERY item you generate must satisfy it — check each item against the constraint character-by-character before responding (near-miss variants of a required literal fail the test). Only invent a value when the context gives none for that field. If a nodeHint and the scenario disagree, the scenario wins. When the context assigns an error or missing-data condition to a specific entity (one channel, one user, one record), compare THIS request's parameters (URL, query, body) against that entity: return the error response ONLY when this request targets it, and a normal success response for every other entity — an error scenario is only tested if the matching request actually fails. @@ -59,14 +60,14 @@ Response SHAPE comes from the API docs; DATA VALUES come from the node config. U **Node response-handling options are not part of the body.** The node config may include options that control how n8n post-processes the response — \`fullResponse\`, \`responseFormat\`, \`outputPropertyName\`, pagination. These are applied AFTER you return and must NOT change the body you produce: always return the raw body the real API sends over the wire. Never reshape the body to mimic them — a body shaped like \`{ statusCode, headers, body }\` (mimicking \`fullResponse\`) or \`{ : ... }\` is wrong. -**Response envelope.** Return the body exactly as the real service sends it over the wire, including any top-level wrapper the API puts around results — e.g. \`{ "data": [...] }\`, \`{ "results": [...] }\`, \`{ "items": [...] }\`, \`{ "ok": true, "result": ... }\`. Match the real API's top-level shape exactly: many list endpoints wrap their items, but plenty return a bare top-level array (e.g. an endpoint that returns an array of IDs). Follow what the real API actually returns per the docs — don't default to wrapping a bare-array response, and don't strip a wrapper the API really uses. +**Response envelope.** Return the body exactly as the real service sends it over the wire, including any top-level wrapper the API puts around results — e.g. \`{ "data": [...] }\`, \`{ "results": [...] }\`, \`{ "items": [...] }\`, \`{ "ok": true, "result": ... }\`. Match the real API's top-level shape exactly: many list endpoints wrap their items, but plenty return a bare top-level array (e.g. an endpoint that returns an array of IDs). Follow what the real API actually returns — don't default to wrapping a bare-array response, and don't strip a wrapper the API really uses. Node-config patterns to know: - "__rl" object: "value" is the selected resource id - "schema" array: each entry's "id" is the response field name (NOT "displayName"). e.g. {id:"timestamp",displayName:"Timestamp"} → response uses "timestamp" - Strings starting with "=" are expressions (ignore) -**Time-relative fields.** The user prompt ends with a "## Date anchors" block listing today's date plus a handful of relative anchors (yesterday, 7 days ago, etc.). EVERY timestamp, date, hourly/daily entry, and time-relative field in your response MUST be derived from those anchors — never from training data or from the example dates in the API documentation. Workflows commonly filter mock responses by today's date; values outside the current window are silently discarded and the scenario fails. +**Time-relative fields.** The user prompt ends with a "## Date anchors" block listing today's date plus a handful of relative anchors (yesterday, 7 days ago, etc.). EVERY timestamp, date, hourly/daily entry, and time-relative field in your response MUST be derived from those anchors — never from training data or from example dates you remember for this API. Workflows commonly filter mock responses by today's date; values outside the current window are silently discarded and the scenario fails. Match THIS request only (URL + method): a node may make multiple sequential calls; reply to the specific one shown. Echo identifiers, placeholders, and reference values from the request back into the response. @@ -93,6 +94,10 @@ const DEFAULT_MAX_RETRIES = 2; const ERROR_PREVIEW_MAX = 400; const ERROR_DETAIL_MAX = 300; +// No docs are fetched: the LLM's own knowledge of the API is the source, the same on every run. +const API_DOCS_NOTE = + 'No API documentation is attached. Generate the response based on your knowledge of this API. Follow standard REST conventions for the HTTP method: GET returns resource data, POST returns the created resource, PUT/PATCH returns the updated resource, DELETE returns 204 or confirmation.'; + /** * Hang guard for a single mock-generation LLM call (including tool turns). * Provider stalls otherwise eat the whole scenario execution budget — the @@ -370,11 +375,7 @@ async function generateMockResponse( ); } - const apiDocs = await fetchApiDocs( - serviceName, - `${request.method ?? 'GET'} ${endpoint} response format`, - ); - sections.push('', '## API documentation', apiDocs); + sections.push('', '## API documentation', API_DOCS_NOTE); if (context.nodeConfig) { sections.push('', '## Node Configuration', context.nodeConfig); @@ -402,7 +403,7 @@ async function generateMockResponse( sections.push(context.pinnedOutputs); } - // Anchors go last — the API docs above carry training-era dates, so these + // Anchors go last — the model's API knowledge carries training-era dates, so these // need to be the freshest context before generation. sections.push('', '## Date anchors', dateAnchors); @@ -780,7 +781,7 @@ function createQuirksLookupTool( .handler(async () => { const guidance = findMockQuirks(serviceName, method, pathname, hostname); if (guidance.length === 0) { - return 'No specific quirks for this endpoint. Follow the API docs and the system rules.'; + return 'No specific quirks for this endpoint. Follow the real API and the system rules.'; } return guidance.join('\n\n'); }) diff --git a/packages/cli/src/modules/instance-ai/eval/mock-utils.ts b/packages/cli/src/modules/instance-ai/eval/mock-utils.ts index cd964786c29..2b7622023f9 100644 --- a/packages/cli/src/modules/instance-ai/eval/mock-utils.ts +++ b/packages/cli/src/modules/instance-ai/eval/mock-utils.ts @@ -1,7 +1,7 @@ import type { FetchFn } from '@n8n/agents'; import { extractJsonCandidate } from '@n8n/ai-utilities/llm-output'; import type { Logger } from '@n8n/backend-common'; -import { createEvalAgent, extractText } from '@n8n/instance-ai'; +import { createEvalAgent, extractText, isRetryableEvalError } from '@n8n/instance-ai'; import { jsonParse } from 'n8n-workflow'; // --------------------------------------------------------------------------- @@ -41,6 +41,7 @@ export async function generateJson( logger.warn( `[EvalMock] ${agentName} attempt ${attempt} failed: ${error instanceof Error ? error.message : String(error)}`, ); + if (!isRetryableEvalError(error)) break; } } return undefined; diff --git a/packages/cli/src/modules/instance-ai/eval/thread-credential-allowlist.service.ts b/packages/cli/src/modules/instance-ai/eval/thread-credential-allowlist.service.ts index 064f6420409..9b609757e69 100644 --- a/packages/cli/src/modules/instance-ai/eval/thread-credential-allowlist.service.ts +++ b/packages/cli/src/modules/instance-ai/eval/thread-credential-allowlist.service.ts @@ -1,10 +1,19 @@ import { Service } from '@n8n/di'; +/** Where the thread's connection tests for one credential type go instead of + * the provider. See `InstanceAiEvalCredentialTestTargetRequest`. */ +export interface EvalCredentialTestTarget { + credentialType: string; + baseUrl: string; + urlField: string; +} + /** - * Per-thread credential visibility for evaluation runs. The eval harness + * Per-thread credential settings for evaluation runs. The eval harness * declares which credentials a build thread may see; the builder context's * credential `list()` is filtered to that set. Threads without an entry see - * the unfiltered instance listing. + * the unfiltered instance listing. The harness can also bypass a credential's + * connection test, or aim it at a provider stand-in. */ @Service() export class EvalThreadCredentialAllowlistService { @@ -13,6 +22,8 @@ export class EvalThreadCredentialAllowlistService { * without contacting the provider — see `bypassCredentialTest` on * `InstanceAiEvalCredentialAllowlistRequest`. */ private readonly testBypassByThread = new Map(); + /** Thread id → credential type → target. */ + private readonly testTargetsByThread = new Map>(); set(threadId: string, credentialIds: string[], bypassCredentialTest?: string[]): void { this.byThread.set(threadId, [...credentialIds]); @@ -41,8 +52,20 @@ export class EvalThreadCredentialAllowlistService { return this.testBypassByThread.get(threadId)?.includes(credentialId) ?? false; } + /** Replaces an earlier target for the same credential type only. */ + setTestTarget(threadId: string, target: EvalCredentialTestTarget): void { + const targets = this.testTargetsByThread.get(threadId) ?? new Map(); + targets.set(target.credentialType, { ...target }); + this.testTargetsByThread.set(threadId, targets); + } + + getTestTarget(threadId: string, credentialType: string): EvalCredentialTestTarget | undefined { + return this.testTargetsByThread.get(threadId)?.get(credentialType); + } + clearThread(threadId: string): void { this.byThread.delete(threadId); this.testBypassByThread.delete(threadId); + this.testTargetsByThread.delete(threadId); } } diff --git a/packages/cli/src/modules/instance-ai/eval/thread-restore.service.ts b/packages/cli/src/modules/instance-ai/eval/thread-restore.service.ts index 095c3ad6acd..0a26d8a6237 100644 --- a/packages/cli/src/modules/instance-ai/eval/thread-restore.service.ts +++ b/packages/cli/src/modules/instance-ai/eval/thread-restore.service.ts @@ -279,8 +279,9 @@ export class EvalThreadRestoreService { } } - /** Recreate each seed agent, config and skill bodies in one insert — an agent is - * a single row, so there are no skill files to write. Rolls back on failure. + /** Recreate each seed agent from its config. A seed skill body becomes a new + * skill of that agent only, and the agent ref points to the new id. Deleting + * the agent deletes the skill, so a rollback on failure leaves no skills behind. * Names are not uniquified as seed data tables' are; see `remapSeedArtifactIds`. */ async restoreAgents( agents: InstanceAiEvalSeedAgent[], @@ -315,7 +316,7 @@ export class EvalThreadRestoreService { actor: { kind: 'user', user }, id: agent.id, schema, - ...(agent.skills ? { skills: agent.skills } : {}), + ...(agent.skills ? { skills: agent.skills, skillCreator: user } : {}), }); created.push(agent.id); } diff --git a/packages/cli/src/modules/instance-ai/eval/workflow-analysis.ts b/packages/cli/src/modules/instance-ai/eval/workflow-analysis.ts index e456d13ddb6..7c25bde42d2 100644 --- a/packages/cli/src/modules/instance-ai/eval/workflow-analysis.ts +++ b/packages/cli/src/modules/instance-ai/eval/workflow-analysis.ts @@ -592,7 +592,7 @@ export const TRIGGER_CONTENT_CORRECTION = const SYSTEM_PROMPT = `You are a test data planner for n8n workflow automation. Your job is to create a consistent data context, trigger output data, and per-node hints that will guide an API mock server to generate realistic, coherent responses across all nodes in a workflow. RULES: -1. Create a "globalContext" that defines the shared world — user IDs, entity names, channel names, email addresses, and relationships that ALL nodes should reference consistently. +1. Create a "globalContext" that defines the shared world — user IDs, entity names, channel names, email addresses, and relationships that ALL nodes should reference consistently. State it as plain facts. Never describe a response layout, JSON, field paths, or what an n8n node outputs. 2. Create a "triggerContent" object that represents the exact output the workflow's trigger/start node would produce. This is used as pin data (the node's output), so it must match what downstream nodes reference: - Look at the trigger node's type to determine the output structure - For webhook triggers: include { headers: {}, query: {}, body: { ...fields } } since downstream nodes reference $json.body.fieldName @@ -603,12 +603,12 @@ RULES: - CRITICAL: check what downstream nodes reference (e.g., $json.body.email, $json.subject, $json.text) and ensure those paths exist in triggerContent - CRITICAL: when the workflow has MULTIPLE trigger nodes, pick the ONE the Test Scenario targets (the trigger whose firing the scenario describes, e.g. "The weekly Schedule Trigger fires") and return its exact node name in a "startNodeName" field. triggerContent must be THAT trigger's output. - CRITICAL: triggerContent must NEVER contain binary file CONTENT — no base64 blobs, no fake file-bytes placeholders. When the trigger carries a file (form upload, email attachment, incoming media), declare it with a METADATA-ONLY binary map instead: "binary": { "": { "mimeType": "", "fileName": "" } } — the harness synthesizes real file bytes from that metadata and attaches them at the item level. For a PDF or text file whose words the scenario states, also add "text": "" to its entry — the harness writes them into the file. The MIME type and file name MUST match the scenario: an image/png upload scenario needs mimeType "image/png" and a .png fileName, never a generic application/octet-stream. Use "data" as the propertyKey unless downstream nodes reference a different binary property name. -3. Create a "nodeHints" object with one entry per node. Each hint describes what data that specific node's API response should contain, referencing entities from the global context. -4. Hints should describe the DATA CONTENT, not the API response format. The mock server already knows the API schema. -5. Ensure data flows logically through the workflow. If node A fetches items that node B processes, the items in A's hint should match what B expects. +3. Create a "nodeHints" object with one entry per node that calls an external service. Each hint states the DATA the service holds for that node: the records, field values, counts, IDs, dates and statuses, using entities from the global context. One node can send several requests (for example it reads a sheet's metadata and rows, then appends a row). Write each hint in two parts: "Before the node runs:" with what the service already holds, then "The node writes:" with what the node adds, changes or sends (or "nothing"). A read that happens before the write sees only the "Before the node runs" data. +4. A hint states data, never a response layout. Do not write JSON, braces, field paths, wrapper keys, status envelopes or "return {...}". Do not describe what the n8n node outputs after its own processing (simplified records, rows keyed by column header, parsed JSON, fields such as json.data or output[0].content[0].text). The mock server writes each response in the real API's wire format and only needs the facts. Write facts as plain sentences, e.g. "Sheet 'Leads' has columns Name, Email, Status and 2 rows: Ann Lee, ann@x.example, new; Bo Chan, bo@x.example, won." +5. Ensure data flows logically through the workflow. If node A fetches items that node B processes, A's hint lists the items B needs. Expressions such as $json.field read the node's OUTPUT, not the API response: use them to know which facts matter, not how to lay them out. 6. Use realistic but clearly fake values (e.g., "jane@example.com", "U_abc123"). 7. **If a "Test Scenario" section is provided, it OVERRIDES your default data generation.** Use the exact names, emails, numeric magnitudes (amounts, percentages, counts, thresholds), and conditions described in the scenario. If the scenario says "no name field", do NOT include a name. If it says "email is not-an-email", use that exact value. The scenario defines the test — follow it precisely. -8. **Allocate scenario error conditions explicitly.** When the Test Scenario describes an error, failure, or missing-data condition for a SPECIFIC subset of the workflow's requests (one channel out of three, one user, one record), the affected node's hint MUST make it unambiguous: name the exact entity and identifier (channel name/ID, user ID), state the exact API error response the mock must return for requests targeting that entity (e.g. Slack conversations.history for #product → { "ok": false, "error": "channel_not_found" }), and state that requests for all OTHER entities succeed normally. The mock server handles one request at a time and can only distinguish requests by their parameters — an error condition left implicit ("one channel fails") never gets simulated, and the scenario cannot be evaluated. +8. **Allocate scenario error conditions explicitly.** When the Test Scenario describes an error, failure, or missing-data condition for a SPECIFIC subset of the workflow's requests (one channel out of three, one user, one record), the affected node's hint MUST make it unambiguous: name the exact entity and identifier (channel name/ID, user ID), name the request that fails and the error as the API reports it (the HTTP status and the API's own error code or message, e.g. Slack conversations.history for #product fails with error channel_not_found), without writing the error body, and state that requests for all OTHER entities succeed normally. The mock server handles one request at a time and can only distinguish requests by their parameters — an error condition left implicit ("one channel fails") never gets simulated, and the scenario cannot be evaluated. 9. **Dates and timestamps.** The user prompt ends with a "## Date anchors" block listing today's real date plus relative anchors. EVERY date or timestamp you emit — in globalContext, triggerContent, and nodeHints — MUST be derived from those anchors, never from training data. Workflows compare mock data against the real execution clock ($now, Date.now()): a "recent" record dated months ago gets silently filtered out and the test fails. When the scenario describes a relative window ("issues from the last 2 weeks", "yesterday's orders"), compute concrete dates from the anchors and place records safely INSIDE the window (e.g. 2-5 days ago), never on its boundary. State those concrete dates in globalContext and nodeHints so every node's mock uses the same ones. 10. Return ONLY valid JSON, no explanation or markdown fencing.`; @@ -662,7 +662,9 @@ function buildUserPrompt( sections.push(' "nodeHints": {'); for (let i = 0; i < Math.min(nodeNames.length, 3); i++) { const comma = i < Math.min(nodeNames.length, 3) - 1 ? ',' : ''; - sections.push(` "${nodeNames[i]}": "What data to return..."${comma}`); + sections.push( + ` "${nodeNames[i]}": "Data this node's service holds and what the node writes..."${comma}`, + ); } if (nodeNames.length > 3) sections.push(' ...'); sections.push(' }', '}', '```'); diff --git a/packages/cli/src/modules/instance-ai/instance-ai-checkpoint-pruning.task.ts b/packages/cli/src/modules/instance-ai/instance-ai-checkpoint-pruning.task.ts index a4373441004..5447985b7f1 100644 --- a/packages/cli/src/modules/instance-ai/instance-ai-checkpoint-pruning.task.ts +++ b/packages/cli/src/modules/instance-ai/instance-ai-checkpoint-pruning.task.ts @@ -1,7 +1,12 @@ import { DatabaseConfig, InstanceAiConfig, statementTimeoutSeconds } from '@n8n/config'; import { Time } from '@n8n/constants'; -import { intervalFromMilliseconds, SystemTask, timeoutAfterLimit } from '@n8n/decorators'; -import type { SystemTaskEffects, SystemTaskPlacement, SystemTaskSchedule } from '@n8n/decorators'; +import { + clusterTarget, + intervalFromMilliseconds, + SystemTask, + timeoutAfterLimit, +} from '@n8n/decorators'; +import type { SystemTaskSchedule } from '@n8n/decorators'; import { InstanceAiService } from './instance-ai.service'; @@ -18,23 +23,22 @@ export class InstanceAiCheckpointPruningTask implements SystemTask { this.instanceAiConfig.pruneInterval, ); - readonly effects: SystemTaskEffects = 'idempotent'; - - readonly placement: SystemTaskPlacement = { - scope: 'cluster', - durable: true, - runOnTakeover: true, - }; - - readonly retryDelaySeconds = 30; - - // The pass runs three statements in a row that ignore the signal, so it can - // take three statement timeouts. A timeout that stops the run before they end - // lets the next run start them again, so it waits for all three first. - readonly timeoutSeconds = timeoutAfterLimit( - 3 * statementTimeoutSeconds(this.databaseConfig), - 5 * Time.minutes.toSeconds, - ); + readonly target = clusterTarget({ + scheduler: { + retryOnFailure: true, + // The pass runs three statements in a row that ignore the signal, so it can + // take three statement timeouts. A timeout that stops the run before they end + // lets the next run start them again, so it waits for all three first. + timeoutSeconds: timeoutAfterLimit( + 3 * statementTimeoutSeconds(this.databaseConfig), + 5 * Time.minutes.toSeconds, + ), + }, + leaderTimer: { + runOnTakeover: true, + retryDelaySeconds: 30, + }, + }); constructor( private readonly instanceAiConfig: InstanceAiConfig, diff --git a/packages/cli/src/modules/instance-ai/instance-ai-credit-display.ts b/packages/cli/src/modules/instance-ai/instance-ai-credit-display.ts deleted file mode 100644 index 5f19b3808df..00000000000 --- a/packages/cli/src/modules/instance-ai/instance-ai-credit-display.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { UNLIMITED_CREDITS, type InstanceAiCredits } from '@n8n/api-types'; - -type ThreadCredits = { threadId: string; totalCreditsUsed: number }; - -/** - * Project a credit balance for the client. - * - * The activation-capped trial cohort must never see a balance — not before the lock and not after - * it. Reporting the unlimited sentinel is what achieves that, and it needs no frontend change: the - * editor already hides the credits dropdown and the per-thread usage line when the quota is - * `UNLIMITED_CREDITS`. - * - * `quotaLocked` survives the masking because it carries no figure, only the fact that the pool is - * spent. The editor needs it to warn the user *before* they type — otherwise the first they hear of - * it is a message that fails. - * - * Absence is preserved rather than normalised to `false`. Not every caller has an opinion on the - * lock: a claim reports a balance and knows nothing about it. Answering `false` on their behalf - * would tell the editor the pool is open, retracting a warning the lock had already raised — and - * claims can arrive after the lock, from a background memory task or a fire-and-forget HITL - * segment. Only a caller that actually checked may speak. - * - * Only the numbers are masked. The ledger, the enforcement and the telemetry all keep running on - * the real figures. - */ -export function maskCreditsForDisplay( - credits: InstanceAiCredits, - activationCapped: boolean, - creditsPerThread?: ThreadCredits, -): InstanceAiCredits & { creditsPerThread?: ThreadCredits } { - if (activationCapped) { - return { - creditsQuota: UNLIMITED_CREDITS, - creditsClaimed: 0, - ...(credits.quotaLocked !== undefined ? { quotaLocked: credits.quotaLocked } : {}), - }; - } - - return { ...credits, ...(creditsPerThread ? { creditsPerThread } : {}) }; -} diff --git a/packages/cli/src/modules/instance-ai/instance-ai-credit.service.ts b/packages/cli/src/modules/instance-ai/instance-ai-credit.service.ts index b200033bf99..8814861123e 100644 --- a/packages/cli/src/modules/instance-ai/instance-ai-credit.service.ts +++ b/packages/cli/src/modules/instance-ai/instance-ai-credit.service.ts @@ -10,12 +10,8 @@ import { nanoid } from 'nanoid'; import { Push } from '@/push'; import { AiService } from '@/services/ai.service'; -import { InstanceActivationService } from '@/services/instance-activation.service'; import { Telemetry } from '@/telemetry'; -import { maskCreditsForDisplay } from './instance-ai-credit-display'; -import { InstanceAiSettingsService } from './instance-ai-settings.service'; -import { InstanceAiMessageRepository } from './repositories/instance-ai-message.repository'; import { InstanceAiThreadRepository } from './repositories/instance-ai-thread.repository'; /** @@ -58,16 +54,6 @@ export class InstanceAiCreditService { this.quotaExhaustedHandlers.add(handler); } - /** - * Set once the service has confirmed the pool is locked, to skip re-asserting on every read. - * Purely an optimisation: the durable state is the activation settings row plus the - * service-side flag, so a fresh process or a lost value just re-fires an idempotent call. - */ - private quotaLockConfirmed = false; - - /** Memoised once the message threshold is met. Monotonic — messages are never un-sent. */ - private messageThresholdReached = false; - constructor( logger: Logger, private readonly aiService: AiService, @@ -75,94 +61,10 @@ export class InstanceAiCreditService { private readonly instanceSettings: InstanceSettings, private readonly push: Push, private readonly threadRepo: InstanceAiThreadRepository, - private readonly settingsService: InstanceAiSettingsService, - private readonly activationService: InstanceActivationService, - private readonly messageRepo: InstanceAiMessageRepository, ) { this.logger = logger.scoped('instance-ai'); } - /** - * Apply the activation lock if this instance is in the capped trial cohort and has met the - * trigger: it has activated (first successful production execution) **and** has sent the - * assistant at least `N8N_INSTANCE_AI_ACTIVATION_LOCK_MESSAGE_THRESHOLD` messages. - * - * Both halves matter. Activation alone would wall a user who activated before ever opening the - * assistant — they would get no use of it at all, which is worse than the control variant and - * makes their conversion signal meaningless. Requiring messages guarantees the cohort actually - * experiences the product before being asked to pay. - * - * Best-effort and idempotent: there is no event-driven trigger, so this runs whenever credits are - * read or a proxy token is minted. A failed call, an evicted Redis record or a restarted process - * all repair themselves on the next interaction. Never throws — a locking failure must not break - * the caller's own work. - */ - async ensureQuotaLockApplied(user: User): Promise { - // Everything is inside the try, including the prerequisite reads: a run awaits this before - // starting, so a blip reading the activation row or the message count must not take the run - // down with it. Whatever fails, the next interaction re-attempts. - try { - if (await this.shouldSkipQuotaLock()) return; - - const activatedAt = await this.activationService.getActivatedAt(); - const result = await this.aiService.lockInstanceAiQuota(user, activatedAt); - this.quotaLockConfirmed = result.quotaLocked; - - this.logger.info('Applied Instance AI activation lock', { - userId: user.id, - activatedAt, - quotaLocked: result.quotaLocked, - creditsQuota: result.creditsQuota, - creditsClaimed: result.creditsClaimed, - }); - - // Tell the editor straight away so it can warn before the user types. The claim path - // can't do this: a locked run is refused at token mint, so it never reaches a claim. - if (result.quotaLocked) { - this.push.sendToUsers( - { - type: 'updateInstanceAiCredits', - data: maskCreditsForDisplay( - { ...result, quotaLocked: true }, - this.settingsService.isActivationCapped(), - ), - }, - [user.id], - ); - } - } catch (error) { - // Left unconfirmed on purpose so the next read retries. - this.logger.warn('Failed to apply Instance AI activation lock', { - error: getErrorMessage(error), - userId: user.id, - }); - } - } - - /** - * Whether the lock can't be applied yet. Ordered cheapest first, so the common cases — already - * locked, not in the cohort, no proxy — settle in memory without touching the database. - */ - private async shouldSkipQuotaLock(): Promise { - if (this.quotaLockConfirmed) return true; - if (!this.settingsService.isActivationCapped()) return true; - // The lock is a credit-pool operation, so it is meaningless without the proxy. Note this - // needs the AI-assistant licence *and* a base URL, not just the base URL. - if (!this.aiService.isProxyEnabled()) return true; - - // Activation alone isn't enough: see the two halves of the trigger above. - if ((await this.activationService.getActivatedAt()) === undefined) return true; - - // Raising the threshold above one needs a look at what these rows are: they come from the - // agent memory layer, so "N rows" is only "N times the user pressed send" if nothing else - // writes a `user` row. At one that assumption costs nothing; above one, over-counting would - // lock earlier than intended. - this.messageThresholdReached ||= await this.messageRepo.hasAtLeastUserMessages( - this.settingsService.getActivationLockMessageThreshold(), - ); - return !this.messageThresholdReached; - } - /** * Claim decimal, token-based credits for one finished run segment. * @@ -268,12 +170,14 @@ export class InstanceAiCreditService { this.push.sendToUsers( { type: 'updateInstanceAiCredits', - data: maskCreditsForDisplay( - { creditsQuota, creditsClaimed }, - this.settingsService.isActivationCapped(), + data: { + creditsQuota, + creditsClaimed, // Only attach the per-thread total when we actually computed one. - totalCreditsUsed !== undefined ? { threadId, totalCreditsUsed } : undefined, - ), + ...(totalCreditsUsed !== undefined + ? { creditsPerThread: { threadId, totalCreditsUsed } } + : {}), + }, }, [user.id], ); diff --git a/packages/cli/src/modules/instance-ai/instance-ai-pending-agent.service.ts b/packages/cli/src/modules/instance-ai/instance-ai-pending-agent.service.ts index e31de820948..11f92295c16 100644 --- a/packages/cli/src/modules/instance-ai/instance-ai-pending-agent.service.ts +++ b/packages/cli/src/modules/instance-ai/instance-ai-pending-agent.service.ts @@ -10,6 +10,7 @@ import { AgentRunnableStateService } from '@/modules/agents/agent-runnable-state import { AgentsService } from '@/modules/agents/agents.service'; import { userHasScopes } from '@/permissions.ee/check-access'; +import { isAgentsAccessEnabled } from './agents-access'; import { InstanceAiMemoryService } from './instance-ai-memory.service'; /** @@ -39,7 +40,7 @@ export class InstanceAiPendingAgentService { * whether or not the agents module is active, and injecting would construct * its services (and their repositories) regardless. */ private agentsModule() { - if (!this.moduleRegistry.isActive('agents')) { + if (!isAgentsAccessEnabled(this.moduleRegistry)) { throw new NotFoundError('Agents are not enabled on this instance'); } return { diff --git a/packages/cli/src/modules/instance-ai/instance-ai-settings.service.ts b/packages/cli/src/modules/instance-ai/instance-ai-settings.service.ts index 1096c3feffa..a86c01c1cd3 100644 --- a/packages/cli/src/modules/instance-ai/instance-ai-settings.service.ts +++ b/packages/cli/src/modules/instance-ai/instance-ai-settings.service.ts @@ -1285,16 +1285,6 @@ export class InstanceAiSettingsService { return this.config.browserUseEnabled; } - /** Whether this instance is in the activation-capped trial cohort. */ - isActivationCapped(): boolean { - return this.config.activationCapped; - } - - /** How many assistant messages must precede the activation lock. `0` means activation alone. */ - getActivationLockMessageThreshold(): number { - return this.config.activationLockMessageThreshold; - } - /** Whether workflow building can use the required sandbox workspace. */ getSandboxStatus(): InstanceAiSandboxStatus { const provider = this.sandboxSettingsService.getProvider(); diff --git a/packages/cli/src/modules/instance-ai/instance-ai.adapter.service.ts b/packages/cli/src/modules/instance-ai/instance-ai.adapter.service.ts index cd77059cd4d..b553d177d1a 100644 --- a/packages/cli/src/modules/instance-ai/instance-ai.adapter.service.ts +++ b/packages/cli/src/modules/instance-ai/instance-ai.adapter.service.ts @@ -171,6 +171,7 @@ import { scopeCredentialProvider, type AgentCredentialProvider, } from './eval/scoped-credential-provider'; +import type { EvalCredentialTestTarget } from './eval/thread-credential-allowlist.service'; import { InstanceAiBuilderDelegateAdapterService } from '@/modules/agents/instance-ai-builder-delegate.adapter'; import { DataTableRepository } from '@/modules/data-table/data-table.repository'; import { DataTableService } from '@/modules/data-table/data-table.service'; @@ -214,6 +215,7 @@ import { WorkflowHistoryService } from '@/workflows/workflow-history/workflow-hi import { WorkflowService } from '@/workflows/workflow.service'; import { EnterpriseWorkflowService } from '@/workflows/workflow.service.ee'; +import { isAgentsAccessEnabled } from './agents-access'; import { extractResolvedNodeParameters } from './extract-resolved-node-parameters'; import { waitForInstanceAiExecution } from './instance-ai-execution-wait'; import { @@ -485,11 +487,13 @@ export class InstanceAiAdapterService { * read on every `list()`: the harness appends credentials it creates * mid-run, after this context is built. */ getCredentialIdAllowlist?: () => string[] | undefined; - resumeAgentBuild?: boolean; /** Eval-only: resolve a credential's connection test as successful without * contacting the provider. A predicate rather than a list because the * harness registers bypasses mid-run, after this context is built. */ shouldBypassCredentialTest?: (credentialId: string) => boolean; + /** Eval-only: the provider stand-in for a credential type's connection test. + * A getter for the same reason as the bypass predicate. */ + getCredentialTestTarget?: (credentialType: string) => EvalCredentialTestTarget | undefined; /** Pre-bound agent for the build-existing-agent flow. When omitted, the * assistant can create one via the build-agent tool. */ agentId?: string; @@ -530,8 +534,8 @@ export class InstanceAiAdapterService { threadId, projectId, getCredentialIdAllowlist, - resumeAgentBuild = false, shouldBypassCredentialTest, + getCredentialTestTarget, agentId, configEvalsEnabled, setupPanelVariant, @@ -551,12 +555,13 @@ export class InstanceAiAdapterService { // underlying config is cached process-wide (1h TTL) so this rarely hits // the network, and telemetry must never block context creation. void this.trackGatewayAvailability(); - const builderDelegateAdapter = this.getBuilderDelegateAdapter(resumeAgentBuild); + const builderDelegateAdapter = this.getBuilderDelegateAdapter(); const credentialService = this.createCredentialAdapter( user, projectId, getCredentialIdAllowlist, shouldBypassCredentialTest, + getCredentialTestTarget, ); return { userId: user.id, @@ -668,15 +673,8 @@ export class InstanceAiAdapterService { * (and the build-agent sub-agent tool it powers) is simply absent from the * context. */ - private getBuilderDelegateAdapter( - resumeAgentBuild: boolean, - ): InstanceAiBuilderDelegateAdapterService | null { - const moduleRegistry = Container.get(ModuleRegistry); - if ( - !moduleRegistry.isActive('agents') || - (!resumeAgentBuild && moduleRegistry.settings.get('agents')?.enabled === false) - ) - return null; + private getBuilderDelegateAdapter(): InstanceAiBuilderDelegateAdapterService | null { + if (!isAgentsAccessEnabled()) return null; try { return Container.get(InstanceAiBuilderDelegateAdapterService); } catch (error) { @@ -888,7 +886,9 @@ export class InstanceAiAdapterService { return { execute: async (request) => { this.assertInstanceNotReadOnly('executions'); - const projectId = await resolveProjectId(['workflow:execute']); + // The caller supplies the node type and parameters, so a standalone run + // authors a workflow. See ADR-20261012-require-create-and-execute-scopes-for-standalone-node-runs. + const projectId = await resolveProjectId(['workflow:create', 'workflow:execute']); const result = await executeNodeService.run(user, { type: request.type, version: request.version, @@ -2753,6 +2753,7 @@ export class InstanceAiAdapterService { boundProjectId?: string, getCredentialIdAllowlist?: () => string[] | undefined, shouldBypassCredentialTest?: (credentialId: string) => boolean, + getCredentialTestTarget?: (credentialType: string) => EvalCredentialTestTarget | undefined, ): InstanceAiCredentialService { const { credentialsService, @@ -2862,15 +2863,18 @@ export class InstanceAiAdapterService { return { success: true, message: 'Connection tested successfully' }; } + const data = await credentialsService.decryptForUse( + credential, + { kind: 'user', user }, + boundProjectId, + ); + // Eval-only: aim the test at the thread's stand-in. + const target = getCredentialTestTarget?.(credential.type); const credentialsToTest: ICredentialsDecrypted = { id: credential.id, name: credential.name, type: credential.type, - data: await credentialsService.decryptForUse( - credential, - { kind: 'user', user }, - boundProjectId, - ), + data: target ? { ...data, [target.urlField]: target.baseUrl } : data, }; const result = await credentialsService.test(user.id, credentialsToTest); diff --git a/packages/cli/src/modules/instance-ai/instance-ai.controller.ts b/packages/cli/src/modules/instance-ai/instance-ai.controller.ts index a6abe0cbaad..2b20cd46fb8 100644 --- a/packages/cli/src/modules/instance-ai/instance-ai.controller.ts +++ b/packages/cli/src/modules/instance-ai/instance-ai.controller.ts @@ -24,6 +24,7 @@ import { InstanceAiEvalExecutionRequest, InstanceAiEvalAgentExecutionRequest, InstanceAiEvalCredentialAllowlistRequest, + InstanceAiEvalCredentialTestTargetRequest, InstanceAiEvalRestoreThreadRequest, InstanceAiEvalSeedDataTableRowsRequest, findSeedFolderIssues, @@ -104,6 +105,8 @@ const KEEP_ALIVE_INTERVAL_MS = 15_000; export class InstanceAiController { private readonly gatewayApiKey: string; + private readonly instanceAiConfig: GlobalConfig['instanceAi']; + constructor( private readonly instanceAiService: InstanceAiService, private readonly gatewayService: InstanceAiGatewayService, @@ -133,6 +136,7 @@ export class InstanceAiController { private readonly threadTabsService: InstanceAiThreadTabsService, ) { this.gatewayApiKey = globalConfig.instanceAi.gatewayApiKey; + this.instanceAiConfig = globalConfig.instanceAi; } private requireInstanceAiEnabled(): void { @@ -1208,6 +1212,29 @@ export class InstanceAiController { return { ok: true }; } + /** + * Send the thread's connection tests for one credential type to a provider + * stand-in, so the agent's own test checks the captured secret. + */ + @Post('/eval/thread-credential-test-target') + @GlobalScope('instanceAi:eval') + async setThreadCredentialTestTarget( + req: AuthenticatedRequest, + _res: Response, + @Body payload: InstanceAiEvalCredentialTestTargetRequest, + ) { + this.requireInstanceAiEnabled(); + // Redirecting a credential test sends its secret elsewhere, so only a + // throwaway eval instance offers it. + if (!this.instanceAiConfig.evalInstance) { + throw new NotFoundError('Credential test targets are only available on an eval instance'); + } + await this.assertThreadAccess(req.user.id, payload.threadId); + const { threadId, ...target } = payload; + this.evalCredentialAllowlists.setTestTarget(threadId, target); + return { ok: true }; + } + /** * Observational memory for a thread, for a context eval to assert on. * diff --git a/packages/cli/src/modules/instance-ai/instance-ai.module.ts b/packages/cli/src/modules/instance-ai/instance-ai.module.ts index cae87052826..1ab59f92396 100644 --- a/packages/cli/src/modules/instance-ai/instance-ai.module.ts +++ b/packages/cli/src/modules/instance-ai/instance-ai.module.ts @@ -96,7 +96,6 @@ export class InstanceAiModule implements ModuleInterface { workflowBuilderAvailable: enabled && sandboxStatus.workflowBuilderAvailable, sandboxUnavailableReason: sandboxStatus.unavailableReason, runDebugEnabled: globalConfig.instanceAi.runDebugEnabled, - activationCapped: settingsService.isActivationCapped(), }; } diff --git a/packages/cli/src/modules/instance-ai/instance-ai.service.ts b/packages/cli/src/modules/instance-ai/instance-ai.service.ts index 33f40aa2cdc..aa7cfcb3bcb 100644 --- a/packages/cli/src/modules/instance-ai/instance-ai.service.ts +++ b/packages/cli/src/modules/instance-ai/instance-ai.service.ts @@ -174,6 +174,7 @@ import { Telemetry } from '@/telemetry'; import { assertNever } from '@/utils'; import { resolveAgentPreviewHandoff } from './agent-preview-handoff'; +import { isAgentsAccessEnabled } from './agents-access'; import { INSTANCE_CONTEXT_CURSOR, InstanceContextService, @@ -190,7 +191,6 @@ import { DurableEventLog } from './event-bus/durable-event-log'; import { InProcessEventBus } from './event-bus/in-process-event-bus'; import { InterruptedRunSweeper } from './event-bus/interrupted-run-sweeper'; import { InstanceAiConversationHistoryService } from './instance-ai-conversation-history.service'; -import { maskCreditsForDisplay } from './instance-ai-credit-display'; import { InstanceAiCreditService } from './instance-ai-credit.service'; import { getAgentErrorSeverity, @@ -564,9 +564,7 @@ function createInertAbortSignal(): AbortSignal { export function isAssistantCreditBalanceExhausted(credits: { creditsQuota: number; creditsClaimed: number; - quotaLocked?: boolean; }): boolean { - if (credits.quotaLocked) return true; return credits.creditsQuota >= 0 && credits.creditsClaimed >= credits.creditsQuota; } @@ -1110,18 +1108,9 @@ export class InstanceAiService { return this.modelService.isProxyEnabled(); } - /** - * Get current credit usage from the AI service proxy. - * - * Doubles as the reconcile point for the activation lock: this runs on every page load, so a - * lock call that was lost to a failed request, an evicted record or a process restart is - * re-asserted here without any scheduled job. - */ + /** Get current credit usage from the AI service proxy. */ async getCredits(user: User): Promise { - await this.creditService.ensureQuotaLockApplied(user); - - const credits = await this.modelService.getCredits(user); - return maskCreditsForDisplay(credits, this.settingsService.isActivationCapped()); + return await this.modelService.getCredits(user); } /** @@ -1216,13 +1205,8 @@ export class InstanceAiService { ): Promise { if (!isMaskedStreamFailure(error)) return error; try { - const { creditsQuota, creditsClaimed, quotaLocked } = - await this.modelService.getCredits(user); - // The activation lock refuses use while the quota still has credits left, so the numbers - // alone wouldn't explain the failure. Read from the proxy, not from n8n's own trigger - // state: that only says the lock *should* apply, so a lock call that failed would turn - // any unrelated stream death into a spurious upgrade wall. - if (!quotaLocked && (creditsQuota < 0 || creditsClaimed < creditsQuota)) return error; + const { creditsQuota, creditsClaimed } = await this.modelService.getCredits(user); + if (creditsQuota < 0 || creditsClaimed < creditsQuota) return error; } catch (creditsError) { this.logger.debug('Masked stream failure credit re-check failed; keeping original error', { error: getErrorMessage(creditsError), @@ -2607,7 +2591,6 @@ export class InstanceAiService { proxyRunConfig?: Awaited>, instanceContextGates?: InstanceContextGates, experimentGates?: Awaited>, - resumeAgentBuild = false, ) { const memory = this.agentMemory; const boundProjectId = await memory.getThreadProjectId(threadId); @@ -2626,8 +2609,6 @@ export class InstanceAiService { ); const userGateway = this.gatewayService.findGateway(user.id); - // There's another ensure lock check at `getCredits`, which only fires when the frontend mounts. - await this.creditService.ensureQuotaLockApplied(user); // Stop before this run resolves a model. A cached proxy token stays valid // after the balance hits zero, so a later token request would not 403. await this.assertAssistantCreditsAvailable(user); @@ -2692,6 +2673,8 @@ export class InstanceAiService { getCredentialIdAllowlist: () => this.evalCredentialAllowlists.get(threadId), shouldBypassCredentialTest: (credentialId: string) => this.evalCredentialAllowlists.shouldBypassTest(threadId, credentialId), + getCredentialTestTarget: (credentialType: string) => + this.evalCredentialAllowlists.getTestTarget(threadId, credentialType), configEvalsEnabled, setupPanelVariant, mcpConnectionsAvailable, @@ -2704,7 +2687,6 @@ export class InstanceAiService { aiPreferencesEnabled, modelId, allowSendingParameterValues, - resumeAgentBuild, }); // Merge both local gateway and direct browser-use into a single @@ -2852,6 +2834,8 @@ export class InstanceAiService { const flagDisabledSkillIds = disabledInstanceAiSkillIds({ configEvalsEnabled, instanceContextEnabled, + // The agent-building skills need the build-agent tool, which needs a builder delegate. + agentBuildingEnabled: context.builderDelegate !== undefined, }); const selectedSkills = await loadInstanceAiPromptSkills(selectedPrompt.profile); const selectedRuntimeSkills = selectedSkills.source; @@ -2919,6 +2903,7 @@ export class InstanceAiService { runtimeSkills = createLazyWorkspaceRuntimeSkillSource({ source: allRuntimeSkills, workspace: runtimeSkillWorkspace, + resolveVerifiedBundles: async () => (await getSandboxEntry())?.verifiedBundles, logger: this.logger, }); } @@ -3020,12 +3005,12 @@ export class InstanceAiService { } /** - * Resolve the agents execution service only when the `agents` module is - * active. Mirrors the builder-delegate gate so agent-preview handoff is - * absent (rather than exploding) when agents are disabled. + * Resolve the agents execution service only when the Assistant can use + * Agents. Mirrors the builder-delegate gate so agent-preview handoff is + * absent (rather than exploding) when Agents are off. */ private getAgentExecutionService(): AgentExecutionService | null { - if (!Container.get(ModuleRegistry).isActive('agents')) return null; + if (!isAgentsAccessEnabled()) return null; try { return Container.get(AgentExecutionService); } catch { @@ -3042,7 +3027,7 @@ export class InstanceAiService { if (!projectId) return; if (!(await userHasScopes(user, ['agent:read'], false, { projectId }))) return; - if (!Container.get(ModuleRegistry).isActive('agents')) return; + if (!isAgentsAccessEnabled()) return; context.agentContextService = Container.get(InstanceAiAgentContextAdapterService).createReader( user, projectId, @@ -3061,6 +3046,10 @@ export class InstanceAiService { await resolveAgentPreviewSession(context); const projectId = context.projectId; if (!context.agentPreviewSession || !projectId) return; + if (!isAgentsAccessEnabled()) { + context.agentPreviewSession = undefined; + return; + } if (!(await this.canAccessAgentPreviewHandoff(user, projectId))) { context.agentPreviewSession = undefined; return; @@ -5342,7 +5331,6 @@ export class InstanceAiService { messageGroupId?: string, pushRef?: string, instanceContextGates?: InstanceContextGates, - resumeAgentBuild = false, ): Promise<{ agent: InstanceAgent; modelId: ModelConfig; @@ -5357,8 +5345,6 @@ export class InstanceAiService { pushRef, undefined, instanceContextGates, - undefined, - resumeAgentBuild, ); const agent = await this.createAgentFromEnvironment( environment, @@ -5374,19 +5360,6 @@ export class InstanceAiService { }; } - private isAgentBuilderSuspension( - toolName: string | undefined, - suspendPayload: Record | undefined, - ): boolean { - if (toolName !== 'build-agent') return false; - const builderCheckpoint = suspendPayload?.builderCheckpoint; - return ( - isRecord(builderCheckpoint) && - typeof builderCheckpoint.runId === 'string' && - typeof builderCheckpoint.toolCallId === 'string' - ); - } - /** * Rebuild the in-memory pieces a suspended run needs (user, agent, * execution environment) from a persisted orphan row + checkpoint, and @@ -5450,8 +5423,6 @@ export class InstanceAiService { this.threadPushRef.get(orphan.threadId), undefined, instanceContext, - undefined, - this.isAgentBuilderSuspension(toolName, suspendPayload), ); } catch (error: unknown) { return { kind: 'env-failure', error }; @@ -5772,7 +5743,6 @@ export class InstanceAiService { runHandoff: OrchestratorRunHandoffState | undefined, messageGroupId?: string, instanceContextGates?: InstanceContextGates, - resumeAgentBuild = false, ): Promise< | { agent: InstanceAgent; @@ -5791,7 +5761,6 @@ export class InstanceAiService { messageGroupId, this.threadPushRef.get(threadId), instanceContextGates, - resumeAgentBuild, ); createOrchestratorRunControl(rebuilt.orchestrationContext, runHandoff ?? {}); return { @@ -5931,7 +5900,6 @@ export class InstanceAiService { runHandoff, messageGroupId, instanceContext, - this.isAgentBuilderSuspension(toolName, suspendPayload), ); if (!rebuilt) { const rebuildFailure = 'Agent rebuild failed'; diff --git a/packages/cli/src/modules/instance-ai/mcp/instance-ai-mcp-registry.service.ts b/packages/cli/src/modules/instance-ai/mcp/instance-ai-mcp-registry.service.ts index 4a3c87c109f..7b6fafceafa 100644 --- a/packages/cli/src/modules/instance-ai/mcp/instance-ai-mcp-registry.service.ts +++ b/packages/cli/src/modules/instance-ai/mcp/instance-ai-mcp-registry.service.ts @@ -13,13 +13,13 @@ import { EventService, CredentialsFinderService } from '@n8n/backend-services'; import { isUniqueConstraintError, type CredentialsEntity, type User } from '@n8n/db'; import { Service } from '@n8n/di'; import type { McpServerConfig } from '@n8n/instance-ai'; -import { isRecord } from '@n8n/utils/is-record'; import type { ICredentialDataDecryptedObject, LiteralMcpRegistryConnection } from 'n8n-workflow'; import { randomUUID } from 'node:crypto'; import { CredentialTypes } from '@/credential-types'; import { CredentialsService } from '@/credentials/credentials.service'; import { BadRequestError, ConflictError, NotFoundError } from '@n8n/errors'; +import { createMcpAuthFetch } from '@/modules/mcp-registry/mcp-auth-fetch'; import { isSupportedMcpRegistryCredentialType, prepareMcpRegistryConnection, @@ -30,7 +30,6 @@ import { McpRegistryService } from '@/modules/mcp-registry/registry/mcp-registry import type { McpRegistryServer } from '@/modules/mcp-registry/registry/mcp-registry.types'; import { OauthService } from '@/oauth/oauth.service'; import { createAiMcpFetch } from '@/utils/ai-proxy-fetch'; -import { createAuthFetch, getBearerTokenRevision } from '@/utils/auth-fetch'; import type { InstanceAiMcpRegistryConnection } from '../entities/instance-ai-mcp-registry-connection.entity'; import { InstanceAiSettingsService } from '../instance-ai-settings.service'; @@ -467,32 +466,14 @@ export class InstanceAiMcpRegistryService { } const projectId = credentialWithData.credential.shared?.[0]?.projectId ?? null; - const storedTokenData = credentialWithData.data.oauthTokenData; - const oauthTokenData = isRecord(storedTokenData) ? { ...storedTokenData } : undefined; - return createAuthFetch({ + return createMcpAuthFetch({ + authentication: credentialType, baseFetch, + credentialData: credentialWithData.data, + credentialId: config.credentialId, initialHeaders: prepared.value.headers, - onUnauthorized: async (currentHeaders) => { - if (!projectId) return null; - const result = await this.oauthService.refreshOAuth2CredentialById( - config.credentialId, - projectId, - getBearerTokenRevision(currentHeaders, oauthTokenData?.n8n_expires_at), - ); - if (result && oauthTokenData) { - if (result.expiresAt === undefined) { - delete oauthTokenData.n8n_expires_at; - } else { - oauthTokenData.n8n_expires_at = String(result.expiresAt); - } - if (result.expiresInSeconds === undefined) { - delete oauthTokenData.expires_in; - } else { - oauthTokenData.expires_in = result.expiresInSeconds; - } - } - return result?.headers ?? null; - }, + oauthService: this.oauthService, + projectId, allowedDomains: { mode: 'domains', domains: prepared.value.allowedDomains, diff --git a/packages/cli/src/modules/instance-ai/repositories/__tests__/instance-ai-message.repository.integration.test.ts b/packages/cli/src/modules/instance-ai/repositories/__tests__/instance-ai-message.repository.integration.test.ts deleted file mode 100644 index d42aff602d2..00000000000 --- a/packages/cli/src/modules/instance-ai/repositories/__tests__/instance-ai-message.repository.integration.test.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { randomUUID } from 'node:crypto'; - -import { createTeamProject, testDb, testModules } from '@n8n/backend-test-utils'; -import type { Project } from '@n8n/db'; -import { Container } from '@n8n/di'; - -import { InstanceAiMessageRepository } from '../instance-ai-message.repository'; -import { InstanceAiThreadRepository } from '../instance-ai-thread.repository'; - -describe('InstanceAiMessageRepository', () => { - let messageRepository: InstanceAiMessageRepository; - let threadRepository: InstanceAiThreadRepository; - let project: Project; - let threadId: string; - - beforeAll(async () => { - await testModules.loadModules(['instance-ai']); - await testDb.init(); - messageRepository = Container.get(InstanceAiMessageRepository); - threadRepository = Container.get(InstanceAiThreadRepository); - project = await createTeamProject(); - }); - - beforeEach(async () => { - await messageRepository.delete({}); - await threadRepository.delete({}); - threadId = randomUUID(); - await threadRepository.save( - threadRepository.create({ - id: threadId, - resourceId: 'user-1', - projectId: project.id, - title: '', - metadata: null, - }), - ); - }); - - afterAll(async () => { - await testDb.terminate(); - }); - - async function saveMessage(role: string) { - await messageRepository.save( - messageRepository.create({ - id: randomUUID(), - threadId, - content: 'hello', - role, - type: null, - resourceId: 'user-1', - }), - ); - } - - describe('hasAtLeastUserMessages', () => { - it('is false on an instance with no messages', async () => { - await expect(messageRepository.hasAtLeastUserMessages(1)).resolves.toBe(false); - }); - - it('is true once the threshold is met exactly', async () => { - await saveMessage('user'); - await saveMessage('user'); - await saveMessage('user'); - - await expect(messageRepository.hasAtLeastUserMessages(3)).resolves.toBe(true); - }); - - it('is false while short of the threshold', async () => { - await saveMessage('user'); - await saveMessage('user'); - - await expect(messageRepository.hasAtLeastUserMessages(3)).resolves.toBe(false); - }); - - it('is true beyond the threshold', async () => { - for (let i = 0; i < 5; i++) await saveMessage('user'); - - await expect(messageRepository.hasAtLeastUserMessages(3)).resolves.toBe(true); - }); - - it.each(['assistant', 'tool', 'system'])('does not count %s messages', async (role) => { - await saveMessage(role); - await saveMessage(role); - await saveMessage(role); - await saveMessage('user'); - - await expect(messageRepository.hasAtLeastUserMessages(3)).resolves.toBe(false); - await expect(messageRepository.hasAtLeastUserMessages(1)).resolves.toBe(true); - }); - - it('counts user messages sitting among other roles', async () => { - await saveMessage('assistant'); - await saveMessage('user'); - await saveMessage('tool'); - await saveMessage('user'); - - await expect(messageRepository.hasAtLeastUserMessages(2)).resolves.toBe(true); - await expect(messageRepository.hasAtLeastUserMessages(3)).resolves.toBe(false); - }); - - // Guards the caller against a misconfigured threshold silently disabling the gate. - it('treats a non-positive threshold as already met', async () => { - await expect(messageRepository.hasAtLeastUserMessages(0)).resolves.toBe(true); - }); - }); -}); diff --git a/packages/cli/src/modules/instance-ai/repositories/instance-ai-message.repository.ts b/packages/cli/src/modules/instance-ai/repositories/instance-ai-message.repository.ts index 9f574bce0df..2f8e9ffdcb0 100644 --- a/packages/cli/src/modules/instance-ai/repositories/instance-ai-message.repository.ts +++ b/packages/cli/src/modules/instance-ai/repositories/instance-ai-message.repository.ts @@ -8,26 +8,4 @@ export class InstanceAiMessageRepository extends Repository { constructor(dataSource: DataSource) { super(InstanceAiMessage, dataSource.manager); } - - /** - * Whether this instance has at least `threshold` user messages to the assistant. - * - * Instance-wide on purpose: the credit pool is per license, not per user, so "has this instance - * used the assistant" is the question the activation lock asks. Only `user` messages count — - * assistant and tool rows could exist for runs the user never initiated. - * - * Bounded by `take` rather than counting: this runs on every credits read and every run until - * the threshold trips, and a full count would scan a table that only grows. - */ - async hasAtLeastUserMessages(threshold: number): Promise { - if (threshold <= 0) return true; - - const rows = await this.find({ - where: { role: 'user' }, - take: threshold, - select: { id: true }, - }); - - return rows.length >= threshold; - } } diff --git a/packages/cli/src/modules/instance-ai/sandbox/instance-ai-sandbox.service.ts b/packages/cli/src/modules/instance-ai/sandbox/instance-ai-sandbox.service.ts index 68c6d493b3c..cfa7c891b87 100644 --- a/packages/cli/src/modules/instance-ai/sandbox/instance-ai-sandbox.service.ts +++ b/packages/cli/src/modules/instance-ai/sandbox/instance-ai-sandbox.service.ts @@ -14,6 +14,7 @@ import { type Logger, type ManagedBackgroundTask, type SandboxConfig, + type VerifiedWorkspaceBundles, } from '@n8n/instance-ai'; import type { ErrorReporter } from 'n8n-core'; import { OperationalError, UnexpectedError } from 'n8n-workflow'; @@ -36,6 +37,8 @@ export type RuntimeSandboxEntry = { sandbox: NonNullable>>; workspace: NonNullable>; configFingerprint: string; + /** Prebaked bundles already verified in this sandbox, shared across runs. */ + verifiedBundles: VerifiedWorkspaceBundles; setupComplete: boolean; setupPromise: Promise | undefined; expiresAt: number; @@ -419,7 +422,9 @@ export class InstanceAiSandboxService { ): Promise { if (entry.setupComplete) return; - entry.setupPromise ??= setupSandboxWorkspace(entry.workspace, context) + entry.setupPromise ??= setupSandboxWorkspace(entry.workspace, context, { + verifiedBundles: entry.verifiedBundles, + }) .then(() => { entry.setupComplete = true; }) @@ -481,6 +486,7 @@ export class InstanceAiSandboxService { sandbox, workspace, configFingerprint: cacheState.fingerprint, + verifiedBundles: new Map(), setupComplete: false, setupPromise: undefined, expiresAt: this.nextSandboxExpiry(), diff --git a/packages/cli/src/modules/instance-registry/__tests__/instance-registry-heartbeat.task.test.ts b/packages/cli/src/modules/instance-registry/__tests__/instance-registry-heartbeat.task.test.ts index 4998c677b7d..c0ea34086e5 100644 --- a/packages/cli/src/modules/instance-registry/__tests__/instance-registry-heartbeat.task.test.ts +++ b/packages/cli/src/modules/instance-registry/__tests__/instance-registry-heartbeat.task.test.ts @@ -16,8 +16,7 @@ describe('InstanceRegistryHeartbeatTask', () => { it('should refresh the entry of its own process every 30 seconds', () => { expect(task.name).toBe('instance-registry-heartbeat'); expect(task.schedule).toEqual({ kind: 'interval', intervalSeconds: 30 }); - expect(task.effects).toBe('idempotent'); - expect(task.placement).toEqual({ + expect(task.target).toEqual({ scope: 'instance', instanceTypes: ['main', 'worker', 'webhook'], }); diff --git a/packages/cli/src/modules/instance-registry/__tests__/instance-registry-reconciliation.task.test.ts b/packages/cli/src/modules/instance-registry/__tests__/instance-registry-reconciliation.task.test.ts index bb2af66cc9a..cff6f97ed4c 100644 --- a/packages/cli/src/modules/instance-registry/__tests__/instance-registry-reconciliation.task.test.ts +++ b/packages/cli/src/modules/instance-registry/__tests__/instance-registry-reconciliation.task.test.ts @@ -16,9 +16,11 @@ describe('InstanceRegistryReconciliationTask', () => { it('should declare the reconciliation cadence', () => { expect(task.name).toBe('instance-registry-reconciliation'); expect(task.schedule).toEqual({ kind: 'interval', intervalSeconds: 180 }); - expect(task.effects).toBe('idempotent'); - expect(task.maxAttempts).toBe(1); - expect(task.placement).toEqual({ scope: 'cluster', durable: true, runOnTakeover: true }); + expect(task.target).toEqual({ + scope: 'cluster', + scheduler: { retryOnFailure: false }, + leaderTimer: { runOnTakeover: true }, + }); }); describe('run', () => { diff --git a/packages/cli/src/modules/instance-registry/__tests__/stale-member-cleanup.task.test.ts b/packages/cli/src/modules/instance-registry/__tests__/stale-member-cleanup.task.test.ts index 85b780c49bb..a9640d864b3 100644 --- a/packages/cli/src/modules/instance-registry/__tests__/stale-member-cleanup.task.test.ts +++ b/packages/cli/src/modules/instance-registry/__tests__/stale-member-cleanup.task.test.ts @@ -18,8 +18,7 @@ describe('StaleMemberCleanupTask', () => { it('should declare the reconciliation cadence', () => { expect(task.name).toBe('instance-registry-stale-member-cleanup'); expect(task.schedule).toEqual({ kind: 'interval', intervalSeconds: 180 }); - expect(task.effects).toBe('idempotent'); - expect(task.placement).toEqual({ scope: 'cluster', durable: true }); + expect(task.target).toEqual({ scope: 'cluster', scheduler: { retryOnFailure: true } }); }); describe('run', () => { diff --git a/packages/cli/src/modules/instance-registry/checks/instance-registry-reconciliation.task.ts b/packages/cli/src/modules/instance-registry/checks/instance-registry-reconciliation.task.ts index 2f9e9d9a319..6e56a6e02d0 100644 --- a/packages/cli/src/modules/instance-registry/checks/instance-registry-reconciliation.task.ts +++ b/packages/cli/src/modules/instance-registry/checks/instance-registry-reconciliation.task.ts @@ -1,5 +1,5 @@ -import { intervalFromSeconds, SystemTask } from '@n8n/decorators'; -import type { SystemTaskEffects, SystemTaskPlacement, SystemTaskSchedule } from '@n8n/decorators'; +import { clusterTarget, intervalFromSeconds, SystemTask } from '@n8n/decorators'; +import type { SystemTaskSchedule } from '@n8n/decorators'; import { CheckService } from './check.service'; import { REGISTRY_CONSTANTS } from '../instance-registry.types'; @@ -17,15 +17,10 @@ export class InstanceRegistryReconciliationTask implements SystemTask { REGISTRY_CONSTANTS.RECONCILIATION_INTERVAL_SECONDS, ); - readonly effects: SystemTaskEffects = 'idempotent'; - - readonly maxAttempts = 1; - - readonly placement: SystemTaskPlacement = { - scope: 'cluster', - durable: true, - runOnTakeover: true, - }; + readonly target = clusterTarget({ + scheduler: { retryOnFailure: false }, + leaderTimer: { runOnTakeover: true }, + }); constructor(private readonly checkService: CheckService) {} diff --git a/packages/cli/src/modules/instance-registry/instance-registry-heartbeat.task.ts b/packages/cli/src/modules/instance-registry/instance-registry-heartbeat.task.ts index 4a4aad41ae8..a9f8b432a6a 100644 --- a/packages/cli/src/modules/instance-registry/instance-registry-heartbeat.task.ts +++ b/packages/cli/src/modules/instance-registry/instance-registry-heartbeat.task.ts @@ -1,5 +1,5 @@ -import { intervalFromMilliseconds, SystemTask } from '@n8n/decorators'; -import type { SystemTaskEffects, SystemTaskPlacement, SystemTaskSchedule } from '@n8n/decorators'; +import { instanceTarget, intervalFromMilliseconds, SystemTask } from '@n8n/decorators'; +import type { SystemTaskSchedule } from '@n8n/decorators'; import { InstanceRegistryService } from './instance-registry.service'; import { REGISTRY_CONSTANTS } from './instance-registry.types'; @@ -15,13 +15,8 @@ export class InstanceRegistryHeartbeatTask implements SystemTask { REGISTRY_CONSTANTS.HEARTBEAT_INTERVAL_MS, ); - readonly effects: SystemTaskEffects = 'idempotent'; - /** Only the owning process can refresh its own entry. */ - readonly placement: SystemTaskPlacement = { - scope: 'instance', - instanceTypes: ['main', 'worker', 'webhook'], - }; + readonly target = instanceTarget(['main', 'worker', 'webhook']); constructor(private readonly instanceRegistryService: InstanceRegistryService) {} diff --git a/packages/cli/src/modules/instance-registry/stale-member-cleanup.task.ts b/packages/cli/src/modules/instance-registry/stale-member-cleanup.task.ts index 1fb5591ed23..70d2ac40bfe 100644 --- a/packages/cli/src/modules/instance-registry/stale-member-cleanup.task.ts +++ b/packages/cli/src/modules/instance-registry/stale-member-cleanup.task.ts @@ -1,6 +1,6 @@ import { Logger } from '@n8n/backend-common'; -import { intervalFromSeconds, SystemTask } from '@n8n/decorators'; -import type { SystemTaskEffects, SystemTaskPlacement, SystemTaskSchedule } from '@n8n/decorators'; +import { clusterTarget, intervalFromSeconds, SystemTask } from '@n8n/decorators'; +import type { SystemTaskSchedule } from '@n8n/decorators'; import { InstanceRegistryService } from './instance-registry.service'; import { REGISTRY_CONSTANTS } from './instance-registry.types'; @@ -17,9 +17,7 @@ export class StaleMemberCleanupTask implements SystemTask { REGISTRY_CONSTANTS.RECONCILIATION_INTERVAL_SECONDS, ); - readonly effects: SystemTaskEffects = 'idempotent'; - - readonly placement: SystemTaskPlacement = { scope: 'cluster', durable: true }; + readonly target = clusterTarget({ scheduler: { retryOnFailure: true } }); private readonly logger: Logger; diff --git a/packages/cli/src/modules/instance-reporting.ee/RETRIES.md b/packages/cli/src/modules/instance-reporting.ee/RETRIES.md index f3783c101b4..f250d8e54aa 100644 --- a/packages/cli/src/modules/instance-reporting.ee/RETRIES.md +++ b/packages/cli/src/modules/instance-reporting.ee/RETRIES.md @@ -43,7 +43,7 @@ flowchart TD C --> N ``` -The report row owns delivery retries. Durable occurrences use `maxAttempts: 1`. +The report row owns delivery retries. Durable occurrences use `retryOnFailure: false`. A delivery error fails that occurrence. The next scheduled pass checks the stored retry delay and budget. It does not get a new delivery budget. diff --git a/packages/cli/src/modules/instance-reporting.ee/__tests__/instance-reporting-multi-main.integration.test.ts b/packages/cli/src/modules/instance-reporting.ee/__tests__/instance-reporting-multi-main.integration.test.ts index c69d11a5277..93f21edc89e 100644 --- a/packages/cli/src/modules/instance-reporting.ee/__tests__/instance-reporting-multi-main.integration.test.ts +++ b/packages/cli/src/modules/instance-reporting.ee/__tests__/instance-reporting-multi-main.integration.test.ts @@ -17,7 +17,10 @@ import { packagedModules } from '@/modules/modules.manifest'; import { DurableJobProvisioner } from '@/scheduling/durable-job-provisioner'; import { buildMaterializerTransaction } from '@/scheduling/durable-scheduler'; import { SystemTaskHandler } from '@/scheduling/system-tasks/system-task-handler'; -import { systemTaskProvisionRequest } from '@/scheduling/system-tasks/system-task-job-registrar'; +import { + systemTaskProvisionRequest, + durableSystemTask, +} from '@/scheduling/system-tasks/system-task-job-registrar'; import { SystemTaskScheduledJobOwner } from '@/scheduling/system-tasks/system-task-scheduled-job-owner'; import { retryUntil } from '@test-integration/retry-until'; @@ -120,7 +123,7 @@ describe('instance reporting across mains', () => { async function provision(task: InstanceReportingTask) { await Container.get(DurableJobProvisioner).provision( systemTaskProvisionRequest( - task, + durableSystemTask(task), Container.get(SystemTaskScheduledJobOwner), 'UTC', new Date(), diff --git a/packages/cli/src/modules/instance-reporting.ee/__tests__/instance-reporting.task.test.ts b/packages/cli/src/modules/instance-reporting.ee/__tests__/instance-reporting.task.test.ts index 36aa8914e53..7cb094291cc 100644 --- a/packages/cli/src/modules/instance-reporting.ee/__tests__/instance-reporting.task.test.ts +++ b/packages/cli/src/modules/instance-reporting.ee/__tests__/instance-reporting.task.test.ts @@ -3,7 +3,7 @@ import { mockLogger } from '@n8n/backend-test-utils'; import type { GlobalConfig } from '@n8n/config'; import { Time } from '@n8n/constants'; import type { ScheduledJobRepository } from '@n8n/db'; -import { resolveSystemTaskRunOptions, SystemTaskMetadata } from '@n8n/decorators'; +import { resolveSystemTask, SystemTaskMetadata } from '@n8n/decorators'; import { Container } from '@n8n/di'; import { Tracing, type ErrorReporter, type InstanceSettings } from 'n8n-core'; import { mock } from 'vitest-mock-extended'; @@ -32,7 +32,7 @@ describe('InstanceReportingTask', () => { it('leaves delivery retries to the report row', () => { const { task } = setup(); - expect(resolveSystemTaskRunOptions(task)).toMatchObject({ maxAttempts: 1 }); + expect(resolveSystemTask(task).runOptions).toMatchObject({ maxAttempts: 1 }); expect(task.schedule).toEqual({ kind: 'interval', intervalSeconds: 15 * Time.minutes.toSeconds, @@ -125,7 +125,7 @@ describe('InstanceReportingTask', () => { await runner.init(); await vi.advanceTimersByTimeAsync(15 * Time.minutes.toMilliseconds); expect(service.sendDueReport).not.toHaveBeenCalled(); - expect(registrar.provision).toHaveBeenCalledWith(task); + expect(registrar.provision).toHaveBeenCalledWith(expect.objectContaining({ task })); expect(scheduler.registerTaskHandler).toHaveBeenCalledWith( 'system:instance-reporting', expect.anything(), diff --git a/packages/cli/src/modules/instance-reporting.ee/instance-reporting.task.ts b/packages/cli/src/modules/instance-reporting.ee/instance-reporting.task.ts index a79fca0721d..cb482fc70cd 100644 --- a/packages/cli/src/modules/instance-reporting.ee/instance-reporting.task.ts +++ b/packages/cli/src/modules/instance-reporting.ee/instance-reporting.task.ts @@ -1,6 +1,6 @@ import { Time } from '@n8n/constants'; -import { intervalFromSeconds, SystemTask } from '@n8n/decorators'; -import type { SystemTaskEffects, SystemTaskPlacement, SystemTaskSchedule } from '@n8n/decorators'; +import { clusterTarget, intervalFromSeconds, SystemTask } from '@n8n/decorators'; +import type { SystemTaskSchedule } from '@n8n/decorators'; import { InstanceReportingService } from './instance-reporting.service'; @@ -10,15 +10,10 @@ export class InstanceReportingTask implements SystemTask { readonly schedule: SystemTaskSchedule = intervalFromSeconds(15 * Time.minutes.toSeconds); - readonly effects: SystemTaskEffects = 'idempotent'; - - readonly placement: SystemTaskPlacement = { - scope: 'cluster', - durable: true, - runOnTakeover: true, - }; - - readonly maxAttempts = 1; + readonly target = clusterTarget({ + scheduler: { retryOnFailure: false }, + leaderTimer: { runOnTakeover: true }, + }); constructor(private readonly reportingService: InstanceReportingService) {} diff --git a/packages/cli/src/modules/mcp-registry/__tests__/mcp-auth-fetch.test.ts b/packages/cli/src/modules/mcp-registry/__tests__/mcp-auth-fetch.test.ts new file mode 100644 index 00000000000..93d80c58e50 --- /dev/null +++ b/packages/cli/src/modules/mcp-registry/__tests__/mcp-auth-fetch.test.ts @@ -0,0 +1,126 @@ +import type { CustomFetch } from '@n8n/backend-network'; +import { UserError } from 'n8n-workflow'; +import { mock } from 'vitest-mock-extended'; + +import type { OauthService } from '@/oauth/oauth.service'; + +import { createMcpAuthFetch, resolveMcpAuthDomainPolicy } from '../mcp-auth-fetch'; + +const baseFetchMock = vi.fn(); +const baseFetch = ((...args: unknown[]) => baseFetchMock(...args)) as unknown as CustomFetch; + +describe('resolveMcpAuthDomainPolicy', () => { + it('limits native OAuth credentials with no explicit policy to the MCP host', () => { + expect( + resolveMcpAuthDomainPolicy( + 'githubOAuth2Api', + { oauthTokenData: { access_token: 'secret' } }, + 'mcp.github.test', + ), + ).toEqual({ mode: 'domains', domains: 'mcp.github.test' }); + }); + + it.each([ + ['none', { mode: 'domains', domains: 'mcp.github.test' }], + ['domains', { mode: 'domains', domains: 'api.github.test' }], + ['all', undefined], + ] as const)('honors the native OAuth %s domain policy', (policy, expected) => { + expect( + resolveMcpAuthDomainPolicy( + 'githubOAuth2Api', + { + allowedHttpRequestDomains: policy, + allowedDomains: 'api.github.test', + }, + 'mcp.github.test', + ), + ).toEqual(expected); + }); + + it('uses the generic credential domain policy for MCP OAuth credentials', () => { + expect( + resolveMcpAuthDomainPolicy( + 'mcpOAuth2Api', + { + allowedHttpRequestDomains: 'domains', + allowedDomains: 'oauth.example.test', + }, + 'mcp.example.test', + ), + ).toEqual({ mode: 'domains', domains: 'oauth.example.test' }); + }); +}); + +describe('createMcpAuthFetch', () => { + const oauthService = mock(); + + beforeEach(() => { + vi.clearAllMocks(); + baseFetchMock.mockReset(); + }); + + it('refreshes an expired OAuth token before the first request', async () => { + baseFetchMock.mockResolvedValue(new Response('ok')); + oauthService.refreshOAuth2CredentialById.mockResolvedValue({ + headers: { Authorization: 'Bearer fresh-token' }, + }); + const fetch = createMcpAuthFetch({ + authentication: 'githubOAuth2Api', + baseFetch, + credentialData: { + grantType: 'authorizationCode', + oauthTokenData: { + access_token: 'stale-token', + refresh_token: 'refresh-token', + n8n_expires_at: '1', + }, + }, + credentialId: 'credential-1', + initialHeaders: { Authorization: 'Bearer stale-token' }, + oauthService, + projectId: 'project-1', + }); + + await fetch('https://mcp.github.test'); + + expect(oauthService.refreshOAuth2CredentialById).toHaveBeenCalledWith( + 'credential-1', + 'project-1', + expect.objectContaining({ accessToken: 'stale-token' }), + ); + expect(new Headers(baseFetchMock.mock.calls[0][1].headers).get('authorization')).toBe( + 'Bearer fresh-token', + ); + }); + + it('does not refresh OAuth without both a credential and project', async () => { + baseFetchMock.mockResolvedValue(new Response('unauthorized', { status: 401 })); + const fetch = createMcpAuthFetch({ + authentication: 'githubOAuth2Api', + baseFetch, + credentialData: { oauthTokenData: { access_token: 'stale-token' } }, + initialHeaders: { Authorization: 'Bearer stale-token' }, + oauthService, + projectId: null, + }); + + await expect(fetch('https://mcp.github.test')).resolves.toHaveProperty('status', 401); + expect(oauthService.refreshOAuth2CredentialById).not.toHaveBeenCalled(); + expect(baseFetchMock).toHaveBeenCalledOnce(); + }); + + it('enforces the supplied discovery domain policy before sending credentials', async () => { + const fetch = createMcpAuthFetch({ + authentication: 'headerAuth', + allowedDomains: { mode: 'domains', domains: 'mcp.example.test' }, + baseFetch, + credentialData: {}, + initialHeaders: { Authorization: 'Bearer secret' }, + oauthService, + projectId: 'project-1', + }); + + await expect(fetch('https://other.example.test/mcp')).rejects.toBeInstanceOf(UserError); + expect(baseFetchMock).not.toHaveBeenCalled(); + }); +}); diff --git a/packages/cli/src/modules/mcp-registry/__tests__/mcp-connection-discovery.service.test.ts b/packages/cli/src/modules/mcp-registry/__tests__/mcp-connection-discovery.service.test.ts new file mode 100644 index 00000000000..ba72d2e0db6 --- /dev/null +++ b/packages/cli/src/modules/mcp-registry/__tests__/mcp-connection-discovery.service.test.ts @@ -0,0 +1,358 @@ +import type { BuiltTool } from '@n8n/agents'; +import type { Logger } from '@n8n/backend-common'; +import type { CustomFetch, OutboundHttp } from '@n8n/backend-network'; +import type { CredentialsFinderService } from '@n8n/backend-services'; +import type { CredentialsEntity, User } from '@n8n/db'; +import { NotFoundError } from '@n8n/errors'; +import type { ICredentialType } from 'n8n-workflow'; +import { mock } from 'vitest-mock-extended'; + +import type { CredentialTypes } from '@/credential-types'; +import type { CredentialsHelper } from '@/credentials-helper'; +import type { OauthService } from '@/oauth/oauth.service'; + +import { McpConnectionDiscoveryService } from '../mcp-connection-discovery.service'; +import type { McpRegistryService } from '../registry/mcp-registry.service'; +import type { McpRegistryServer } from '../registry/mcp-registry.types'; + +const { + mcpClientCloseMock, + mcpClientConfigs, + mcpClientGetConnectionFailuresMock, + mcpClientListToolsMock, +} = vi.hoisted(() => ({ + mcpClientCloseMock: vi.fn<() => Promise>(), + mcpClientConfigs: [] as Array< + Array<{ name: string; fetch: CustomFetch; url: string; transport: string }> + >, + mcpClientGetConnectionFailuresMock: vi.fn(), + mcpClientListToolsMock: vi.fn<() => Promise>(), +})); + +vi.mock('@n8n/agents', () => ({ + McpClient: vi.fn(function ( + configs: Array<{ name: string; fetch: CustomFetch; url: string; transport: string }>, + ) { + mcpClientConfigs.push(configs); + return { + close: mcpClientCloseMock, + getConnectionFailures: mcpClientGetConnectionFailuresMock, + listTools: mcpClientListToolsMock, + }; + }), +})); + +const proxyFetchMock = vi.hoisted(() => vi.fn()); +const proxyFetch = ((...args: unknown[]) => proxyFetchMock(...args)) as unknown as CustomFetch; +const getBaseMock = vi.hoisted(() => vi.fn().mockResolvedValue({})); + +vi.mock('@/utils/ai-proxy-fetch', () => ({ + createAiMcpFetch: () => proxyFetch, +})); + +vi.mock('@/workflow-execute-additional-data.js', () => ({ + getBase: getBaseMock, +})); + +function makeServer(overrides: Partial = {}): McpRegistryServer { + return { + name: 'com.test/github', + slug: 'git hub', + title: 'GitHub', + description: 'Manage repositories', + tagline: 'GitHub tools', + version: '1.0.0', + updatedAt: '2026-09-25T00:00:00.000Z', + icons: [], + authType: 'usesCredentials', + usesCredentials: [{ credentialType: 'githubOAuth2Api', name: 'OAuth2', value: 'oAuth2' }], + remotes: [{ type: 'streamable-http', url: 'https://mcp.github.test/mcp' }], + tools: [ + { name: 'search_repositories', annotations: { readOnlyHint: true } }, + { name: 'remove_repository', annotations: { destructiveHint: true } }, + ], + isOfficial: true, + origin: 'registry', + status: 'active', + ...overrides, + } as McpRegistryServer; +} + +describe('McpConnectionDiscoveryService', () => { + const user = { id: 'user-1' } as User; + const credential = { + id: 'credential-1', + name: 'GitHub OAuth2', + type: 'githubOAuth2Api', + shared: [{ role: 'credential:owner', projectId: 'project-1' }], + } as CredentialsEntity; + + function createService() { + const logger = mock({ scoped: vi.fn().mockReturnThis() }); + const registryService = mock(); + const credentialsFinderService = mock(); + const credentialsHelper = mock(); + const credentialTypes = mock(); + const oauthService = mock(); + const outboundHttp = mock(); + const service = new McpConnectionDiscoveryService( + logger, + registryService, + credentialsFinderService, + credentialsHelper, + credentialTypes, + oauthService, + outboundHttp, + ); + + registryService.get.mockResolvedValue(makeServer()); + credentialsFinderService.findCredentialForUser.mockResolvedValue(credential); + credentialsHelper.getDecrypted.mockResolvedValue({ + oauthTokenData: { access_token: 'token' }, + }); + credentialTypes.recognizes.mockReturnValue(true); + credentialTypes.getByName.mockReturnValue( + mock({ + name: 'githubOAuth2Api', + displayName: 'GitHub OAuth2', + properties: [], + authenticate: undefined, + preAuthentication: undefined, + }), + ); + credentialTypes.getParentTypes.mockReturnValue(['oAuth2Api']); + + return { service, registryService, credentialsFinderService, credentialsHelper }; + } + + beforeEach(() => { + vi.clearAllMocks(); + mcpClientConfigs.length = 0; + mcpClientCloseMock.mockResolvedValue(); + mcpClientGetConnectionFailuresMock.mockReturnValue([]); + }); + + it('returns the discovered connection and classifies tools from live annotations', async () => { + mcpClientListToolsMock.mockResolvedValue([ + { + name: 'git_hub_search_repositories', + description: 'Search repositories', + mcpAnnotations: { readOnlyHint: true }, + } as BuiltTool, + { + name: 'ignored-prefix', + mcpToolName: 'remove_repository', + mcpAnnotations: { destructiveHint: true }, + } as BuiltTool, + ]); + const { service } = createService(); + + await expect( + service.discover(user, { slug: 'git hub', credentialId: 'credential-1' }), + ).resolves.toEqual({ + status: 'connected', + connection: { + url: 'https://mcp.github.test/mcp', + transport: 'streamableHttp', + authentication: 'githubOAuth2Api', + credentialId: 'credential-1', + metadata: { nodeTypeName: '@n8n/mcp-registry.gitHub' }, + }, + tools: [ + { + name: 'search_repositories', + description: 'Search repositories', + category: 'read', + }, + { name: 'remove_repository', category: 'write' }, + ], + }); + expect(mcpClientConfigs[0]?.[0]).toMatchObject({ + name: 'git_hub', + url: 'https://mcp.github.test/mcp', + transport: 'streamableHttp', + connectionTimeoutMs: 10_000, + }); + expect(mcpClientCloseMock).toHaveBeenCalledOnce(); + }); + + it('ignores registry annotations when live annotations are absent', async () => { + mcpClientListToolsMock.mockResolvedValue([ + { name: 'git_hub_custom_widget' } as BuiltTool, + { name: 'git_hub_delete_repository' } as BuiltTool, + ]); + const { service, registryService } = createService(); + registryService.get.mockResolvedValue( + makeServer({ + tools: [ + { name: 'custom_widget', annotations: { readOnlyHint: true } }, + { name: 'delete_repository', annotations: { readOnlyHint: true } }, + ], + }), + ); + + const response = await service.discover(user, { + slug: 'git hub', + credentialId: 'credential-1', + }); + + expect(response.tools).toEqual([ + { name: 'custom_widget', category: 'write' }, + { name: 'delete_repository', category: 'write' }, + ]); + }); + + it('resolves credential data through the credentials helper with project and user context', async () => { + mcpClientListToolsMock.mockResolvedValue([]); + const additionalData = { currentNodeExecutionIndex: 0 }; + getBaseMock.mockResolvedValueOnce(additionalData); + const { service, credentialsHelper } = createService(); + + await service.discover(user, { slug: 'git hub', credentialId: 'credential-1' }); + + expect(getBaseMock).toHaveBeenCalledWith({ + projectId: 'project-1', + userId: 'user-1', + }); + expect(credentialsHelper.getDecrypted).toHaveBeenCalledWith( + additionalData, + { id: 'credential-1', name: 'GitHub OAuth2' }, + 'githubOAuth2Api', + 'internal', + ); + }); + + it('classifies a failed authenticated request and closes the client', async () => { + proxyFetchMock.mockResolvedValue(new Response('unauthorized', { status: 401 })); + mcpClientListToolsMock.mockImplementation(async () => { + await mcpClientConfigs[0]![0]!.fetch('https://mcp.github.test/mcp'); + return []; + }); + mcpClientGetConnectionFailuresMock.mockReturnValue([{ server: 'git_hub' }]); + const { service } = createService(); + + await expect( + service.discover(user, { slug: 'git hub', credentialId: 'credential-1' }), + ).resolves.toEqual({ + status: 'disconnected', + failureReason: 'authentication', + tools: [], + }); + expect(mcpClientCloseMock).toHaveBeenCalledOnce(); + }); + + it('reports transport failures as server unavailable', async () => { + proxyFetchMock.mockRejectedValue(new Error('offline')); + mcpClientListToolsMock.mockImplementation(async () => { + await mcpClientConfigs[0]![0]!.fetch('https://mcp.github.test/mcp'); + return []; + }); + const { service } = createService(); + + await expect( + service.discover(user, { slug: 'git hub', credentialId: 'credential-1' }), + ).resolves.toEqual({ + status: 'disconnected', + failureReason: 'server_unavailable', + tools: [], + }); + expect(mcpClientCloseMock).toHaveBeenCalledOnce(); + }); + + it('keeps an unclassified failure unknown after the server responds', async () => { + proxyFetchMock.mockResolvedValue(new Response('ok')); + mcpClientListToolsMock.mockImplementation(async () => { + await mcpClientConfigs[0]![0]!.fetch('https://mcp.github.test/mcp'); + throw new Error('Invalid MCP response'); + }); + const { service } = createService(); + + await expect( + service.discover(user, { slug: 'git hub', credentialId: 'credential-1' }), + ).resolves.toEqual({ + status: 'disconnected', + failureReason: 'unknown', + tools: [], + }); + expect(mcpClientCloseMock).toHaveBeenCalledOnce(); + }); + + it('reports credential preparation failures as authentication failures', async () => { + const { service, credentialsHelper } = createService(); + credentialsHelper.getDecrypted.mockRejectedValue(new Error('Credential resolution failed')); + + await expect( + service.discover(user, { slug: 'git hub', credentialId: 'credential-1' }), + ).resolves.toEqual({ + status: 'disconnected', + failureReason: 'authentication', + tools: [], + }); + expect(mcpClientListToolsMock).not.toHaveBeenCalled(); + }); + + it('times out tool discovery and closes the client', async () => { + vi.useFakeTimers(); + try { + let notifyListToolsStarted: () => void = () => {}; + const listToolsStarted = new Promise((resolve) => { + notifyListToolsStarted = resolve; + }); + mcpClientListToolsMock.mockImplementation(async () => { + notifyListToolsStarted(); + return await new Promise(() => {}); + }); + const { service } = createService(); + + const resultPromise = service.discover(user, { + slug: 'git hub', + credentialId: 'credential-1', + }); + await listToolsStarted; + await vi.advanceTimersByTimeAsync(10_000); + + await expect(resultPromise).resolves.toEqual({ + status: 'disconnected', + failureReason: 'server_unavailable', + tools: [], + }); + expect(mcpClientCloseMock).toHaveBeenCalledOnce(); + } finally { + vi.useRealTimers(); + } + }); + + it('does not hide an inaccessible registry server as an authentication failure', async () => { + const { service, registryService } = createService(); + registryService.get.mockResolvedValue(undefined); + + await expect( + service.discover(user, { slug: 'missing', credentialId: 'credential-1' }), + ).rejects.toBeInstanceOf(NotFoundError); + expect(mcpClientListToolsMock).not.toHaveBeenCalled(); + }); + + it('requires connect scope for resolvable credentials', async () => { + const { service, credentialsFinderService } = createService(); + const resolvableCredential = mock({ + id: credential.id, + name: credential.name, + type: credential.type, + shared: credential.shared, + isResolvable: true, + }); + credentialsFinderService.findCredentialForUser + .mockResolvedValueOnce(resolvableCredential) + .mockResolvedValueOnce(null); + + await expect( + service.discover(user, { slug: 'git hub', credentialId: 'credential-1' }), + ).rejects.toBeInstanceOf(NotFoundError); + expect(credentialsFinderService.findCredentialForUser).toHaveBeenNthCalledWith( + 2, + 'credential-1', + user, + ['credential:connect'], + ); + }); +}); diff --git a/packages/cli/src/modules/mcp-registry/__tests__/mcp-registry-refresh.task.test.ts b/packages/cli/src/modules/mcp-registry/__tests__/mcp-registry-refresh.task.test.ts index b039500e470..c0f2404e5fa 100644 --- a/packages/cli/src/modules/mcp-registry/__tests__/mcp-registry-refresh.task.test.ts +++ b/packages/cli/src/modules/mcp-registry/__tests__/mcp-registry-refresh.task.test.ts @@ -15,15 +15,17 @@ describe('McpRegistryRefreshTask', () => { it('should refresh every 8 hours on the durable scheduler, once on in-memory takeover, without an early retry', () => { expect(task.name).toBe('mcp-registry-refresh'); expect(task.schedule).toEqual({ kind: 'interval', intervalSeconds: 8 * 3600 }); - expect(task.effects).toBe('idempotent'); - expect(task.placement).toEqual({ scope: 'cluster', durable: true, runOnTakeover: true }); - expect(task.retryDelaySeconds).toBeUndefined(); + expect(task.target).toEqual({ + scope: 'cluster', + scheduler: { retryOnFailure: true }, + leaderTimer: { runOnTakeover: true }, + }); }); it('should refresh the registry on run and hand it the abort signal', async () => { const { signal } = new AbortController(); - await task.run(signal, { durable: true }); + await task.run(signal); expect(mcpRegistryService.refreshFromApi).toHaveBeenCalledExactlyOnceWith(signal); }); @@ -31,8 +33,6 @@ describe('McpRegistryRefreshTask', () => { it('should let a failed refresh propagate to the runner', async () => { mcpRegistryService.refreshFromApi.mockRejectedValue(new Error('api down')); - await expect(task.run(new AbortController().signal, { durable: true })).rejects.toThrow( - 'api down', - ); + await expect(task.run(new AbortController().signal)).rejects.toThrow('api down'); }); }); diff --git a/packages/cli/src/modules/mcp-registry/__tests__/mcp-registry.controller.test.ts b/packages/cli/src/modules/mcp-registry/__tests__/mcp-registry.controller.test.ts index acaa9a2b069..bb343cec4a4 100644 --- a/packages/cli/src/modules/mcp-registry/__tests__/mcp-registry.controller.test.ts +++ b/packages/cli/src/modules/mcp-registry/__tests__/mcp-registry.controller.test.ts @@ -1,5 +1,11 @@ +import type { McpRegistryDiscoveryResponse } from '@n8n/api-types'; +import type { AuthenticatedRequest, User } from '@n8n/db'; +import { ControllerRegistryMetadata } from '@n8n/decorators'; +import { Container } from '@n8n/di'; +import { BadRequestError } from '@n8n/errors'; import { mock } from 'vitest-mock-extended'; +import type { McpConnectionDiscoveryService } from '../mcp-connection-discovery.service'; import { McpRegistryController } from '../mcp-registry.controller'; import type { McpRegistryService } from '../registry/mcp-registry.service'; import { @@ -10,12 +16,26 @@ import { describe('McpRegistryController', () => { const service = mock(); - const controller = new McpRegistryController(service); + const discoveryService = mock(); + const controller = new McpRegistryController(service, discoveryService); + const routes = Container.get(ControllerRegistryMetadata).getControllerMetadata( + McpRegistryController as never, + ).routes; beforeEach(() => { vi.clearAllMocks(); }); + it.each(['listServers', 'discover'])( + '%s requires the existing MCP OAuth scope', + (handlerName) => { + expect(routes.get(handlerName)?.accessScope).toEqual({ + scope: 'mcp:oauth', + globalOnly: true, + }); + }, + ); + describe('listServers', () => { it('returns active servers projected to the public response shape', async () => { service.getAll.mockResolvedValue([notionMockServer, linearMockServer]); @@ -39,14 +59,14 @@ describe('McpRegistryController', () => { expect(notion).not.toHaveProperty('origin'); }); - it('drops a server whose URL is a template', async () => { - // Instance AI fills its connection picker from here and cannot resolve a - // template, so offering the row would end at a refused connection. + it('marks a server whose URL is a template', async () => { service.getAll.mockResolvedValue([notionMockServer, databricksGenieTemplatedMockServer]); const result = await controller.listServers(); - expect(result.map((s) => s.slug)).toEqual(['notion']); + expect(result.map((s) => s.slug)).toEqual(['notion', 'databricks-genie']); + expect(result.find((server) => server.slug === 'notion')?.isTemplated).toBe(false); + expect(result.find((server) => server.slug === 'databricks-genie')?.isTemplated).toBe(true); }); it('returns an empty array when the registry has no servers', async () => { @@ -57,4 +77,46 @@ describe('McpRegistryController', () => { expect(result).toEqual([]); }); }); + + describe('discover', () => { + it('validates and delegates a discovery request for the authenticated user', async () => { + const user = mock(); + const response: McpRegistryDiscoveryResponse = { + status: 'connected', + connection: { + url: 'https://mcp.example.com', + transport: 'streamableHttp', + authentication: 'githubMcpOAuth2Api', + credentialId: 'credential-1', + }, + tools: [{ name: 'list_repositories', category: 'read' }], + }; + discoveryService.discover.mockResolvedValue(response); + + await expect( + controller.discover( + mock({ + user, + body: { slug: ' github ', credentialId: ' cred-1 ' }, + }), + ), + ).resolves.toEqual(response); + expect(discoveryService.discover).toHaveBeenCalledWith(user, { + slug: 'github', + credentialId: 'cred-1', + }); + }); + + it.each([ + {}, + { slug: '', credentialId: 'credential-1' }, + { slug: 'github', credentialId: '' }, + { slug: 'github', credentialId: 'credential-1', extra: true }, + ])('rejects an invalid discovery request without connecting: %o', async (body) => { + await expect( + controller.discover(mock({ body })), + ).rejects.toBeInstanceOf(BadRequestError); + expect(discoveryService.discover).not.toHaveBeenCalled(); + }); + }); }); diff --git a/packages/cli/src/modules/mcp-registry/__tests__/node-description-transform.test.ts b/packages/cli/src/modules/mcp-registry/__tests__/node-description-transform.test.ts index 904a29bdea7..d2a5e63b71d 100644 --- a/packages/cli/src/modules/mcp-registry/__tests__/node-description-transform.test.ts +++ b/packages/cli/src/modules/mcp-registry/__tests__/node-description-transform.test.ts @@ -718,7 +718,7 @@ describe('serverToCredentialDescription', () => { expect(description).toEqual({ name: 'databricksGenieMcpOAuth2Api', - displayName: 'Databricks Genie MCP OAuth2', + displayName: 'Databricks Genie One MCP OAuth2', extends: ['databricksOAuth2Api'], icon: 'node:@n8n/mcp-registry.databricksGenie', properties: [ diff --git a/packages/cli/src/modules/mcp-registry/mcp-auth-fetch.ts b/packages/cli/src/modules/mcp-registry/mcp-auth-fetch.ts new file mode 100644 index 00000000000..4e19f669912 --- /dev/null +++ b/packages/cli/src/modules/mcp-registry/mcp-auth-fetch.ts @@ -0,0 +1,103 @@ +import type { CustomFetch } from '@n8n/backend-network'; +import { isRecord } from '@n8n/utils/is-record'; +import { isMcpOAuth2Authentication, shouldRefreshMcpOAuth2Token } from 'n8n-workflow'; +import type { ICredentialDataDecryptedObject } from 'n8n-workflow'; + +import type { OauthService } from '@/oauth/oauth.service'; +import { + type AuthFetchDomainPolicy, + createAuthFetch, + getBearerTokenRevision, + resolveAllowedDomains, +} from '@/utils/auth-fetch'; + +function isNativeOAuth2Credential(authentication: string): boolean { + return ( + isMcpOAuth2Authentication(authentication) && + authentication !== 'mcpOAuth2Api' && + !authentication.endsWith('McpOAuth2Api') + ); +} + +export function resolveMcpAuthDomainPolicy( + authentication: string, + credentialData: ICredentialDataDecryptedObject, + mcpHostname: string | undefined, +): AuthFetchDomainPolicy | undefined { + // synthetic mcp registry credentials are handled with default logic, + // other types of credentials are handled separately + if (!isNativeOAuth2Credential(authentication) || !mcpHostname) { + return resolveAllowedDomains(credentialData); + } + + switch (credentialData.allowedHttpRequestDomains) { + case 'domains': + return resolveAllowedDomains(credentialData); + case 'all': + return undefined; + default: + // An unset native OAuth policy is limited to the user-provided MCP host. + return { mode: 'domains', domains: mcpHostname }; + } +} + +export function createMcpAuthFetch({ + allowedDomains, + authentication, + baseFetch, + credentialData, + credentialId, + initialHeaders, + oauthService, + projectId, +}: { + allowedDomains?: AuthFetchDomainPolicy; + authentication: string; + baseFetch: CustomFetch; + credentialData: ICredentialDataDecryptedObject; + credentialId?: string; + initialHeaders: Record; + oauthService: OauthService; + projectId: string | null; +}): CustomFetch { + const storedTokenData = credentialData.oauthTokenData; + const oauthTokenData = isRecord(storedTokenData) ? { ...storedTokenData } : undefined; + const refreshable = + isMcpOAuth2Authentication(authentication) && credentialId !== undefined && projectId !== null; + const onUnauthorized = refreshable + ? async (currentHeaders: Record) => { + if (!credentialId || !projectId) return null; + const result = await oauthService.refreshOAuth2CredentialById( + credentialId, + projectId, + getBearerTokenRevision(currentHeaders, oauthTokenData?.n8n_expires_at), + ); + if (result && oauthTokenData) { + if (result.expiresAt === undefined) { + delete oauthTokenData.n8n_expires_at; + } else { + oauthTokenData.n8n_expires_at = String(result.expiresAt); + } + if (result.expiresInSeconds === undefined) { + delete oauthTokenData.expires_in; + } else { + oauthTokenData.expires_in = result.expiresInSeconds; + } + } + return result?.headers ?? null; + } + : undefined; + + return createAuthFetch({ + baseFetch, + initialHeaders, + onUnauthorized, + ...(onUnauthorized + ? { + shouldRefresh: () => + shouldRefreshMcpOAuth2Token(oauthTokenData, credentialData.grantType), + } + : {}), + allowedDomains, + }); +} diff --git a/packages/cli/src/modules/mcp-registry/mcp-connection-discovery.service.ts b/packages/cli/src/modules/mcp-registry/mcp-connection-discovery.service.ts new file mode 100644 index 00000000000..213e2cb2b32 --- /dev/null +++ b/packages/cli/src/modules/mcp-registry/mcp-connection-discovery.service.ts @@ -0,0 +1,285 @@ +import { McpClient, type BuiltTool } from '@n8n/agents'; +import { classifyMcpTool } from '@n8n/ai-utilities/agent-config'; +import type { + McpRegistryDiscoveredConnection, + McpRegistryDiscoveredTool, + McpRegistryDiscoveryFailureReason, + McpRegistryDiscoveryRequest, + McpRegistryDiscoveryResponse, +} from '@n8n/api-types'; +import { isObjectLiteral, Logger } from '@n8n/backend-common'; +import { OutboundHttp, type CustomFetch } from '@n8n/backend-network'; +import { CredentialsFinderService } from '@n8n/backend-services'; +import type { CredentialsEntity, User } from '@n8n/db'; +import { Service } from '@n8n/di'; +import { BadRequestError, NotFoundError } from '@n8n/errors'; +import { ensureError } from '@n8n/utils/errors/ensure-error'; +import type { ICredentialDataDecryptedObject } from 'n8n-workflow'; + +import { CredentialTypes } from '@/credential-types'; +import { CredentialsHelper } from '@/credentials-helper'; +import { OauthService } from '@/oauth/oauth.service'; +import { createAiMcpFetch } from '@/utils/ai-proxy-fetch'; +import type { AuthFetchDomainPolicy } from '@/utils/auth-fetch'; + +import { createMcpAuthFetch } from './mcp-auth-fetch'; +import { + getConfiguredEndpointUrl, + isSupportedMcpRegistryCredentialType, + prepareMcpRegistryConnection, + resolveMcpRegistryConnection, + toAgentMcpTransport, +} from './mcp-registry-connection'; +import { McpRegistryService } from './registry/mcp-registry.service'; + +const discoveryTimeoutMs = 10_000; + +type ResolvedCredential = { + credential: CredentialsEntity; + data: ICredentialDataDecryptedObject; + projectId: string; +}; + +type PreparedDiscovery = { + clientConfig: { + name: string; + url: string; + transport: 'sse' | 'streamableHttp'; + fetch: CustomFetch; + }; + responseConnection: McpRegistryDiscoveredConnection; +}; + +function disconnected( + failureReason: McpRegistryDiscoveryFailureReason, +): McpRegistryDiscoveryResponse { + return { status: 'disconnected', failureReason, tools: [] }; +} + +function stripServerPrefix(toolName: string, serverName: string): string { + const prefix = `${serverName}_`; + return toolName.startsWith(prefix) ? toolName.slice(prefix.length) : toolName; +} + +function safeServerName(name: string): string { + const normalized = name.replace(/[^A-Za-z0-9_-]/g, '_'); + return (normalized || 'mcp_server').slice(0, 64); +} + +function toTool(tool: BuiltTool, serverName: string): McpRegistryDiscoveredTool { + const name = tool.mcpToolName ?? stripServerPrefix(tool.name, serverName); + return { + name, + ...(tool.description ? { description: tool.description } : {}), + category: classifyMcpTool({ name, annotations: tool.mcpAnnotations }), + }; +} + +function classifyResponseFailure( + response: Response, + current: McpRegistryDiscoveryFailureReason, +): McpRegistryDiscoveryFailureReason { + if (response.status === 401 || response.status === 403) return 'authentication'; + if (response.status >= 500) return 'server_unavailable'; + return current; +} + +async function listToolsWithinDeadline( + client: McpClient, + timeoutMs: number, +): Promise>> { + let timeoutId: ReturnType | undefined; + const timeout = new Promise((_, reject) => { + timeoutId = setTimeout( + () => reject(new Error(`MCP discovery timed out after ${timeoutMs}ms`)), + timeoutMs, + ); + }); + + try { + return await Promise.race([client.listTools(), timeout]); + } finally { + if (timeoutId !== undefined) clearTimeout(timeoutId); + } +} + +@Service() +export class McpConnectionDiscoveryService { + private readonly logger: Logger; + + constructor( + logger: Logger, + private readonly registryService: McpRegistryService, + private readonly credentialsFinderService: CredentialsFinderService, + private readonly credentialsHelper: CredentialsHelper, + private readonly credentialTypes: CredentialTypes, + private readonly oauthService: OauthService, + private readonly outboundHttp: OutboundHttp, + ) { + this.logger = logger.scoped('mcp-registry'); + } + + async discover( + user: User, + request: McpRegistryDiscoveryRequest, + ): Promise { + let prepared: PreparedDiscovery; + try { + prepared = await this.prepareRegistrySource(user, request); + } catch (error) { + if (error instanceof NotFoundError) throw error; + this.logger.warn('Failed to prepare MCP discovery', { + errorType: ensureError(error).name, + }); + return disconnected('authentication'); + } + + let failureReason: McpRegistryDiscoveryFailureReason = 'unknown'; + let receivedResponse = false; + const classifiedFetch: CustomFetch = async (input, init) => { + try { + const response = await prepared.clientConfig.fetch(input, init); + receivedResponse = true; + failureReason = classifyResponseFailure(response, failureReason); + return response; + } catch (error) { + failureReason = 'server_unavailable'; + throw error; + } + }; + const client = new McpClient([ + { + ...prepared.clientConfig, + fetch: classifiedFetch, + connectionTimeoutMs: discoveryTimeoutMs, + }, + ]); + + try { + const tools = (await listToolsWithinDeadline(client, discoveryTimeoutMs)).map((tool) => + toTool(tool, prepared.clientConfig.name), + ); + if (client.getConnectionFailures().length > 0) return disconnected(failureReason); + return { + status: 'connected', + connection: prepared.responseConnection, + tools, + }; + } catch (error) { + if (failureReason === 'unknown' && !receivedResponse) failureReason = 'server_unavailable'; + this.logger.warn('MCP discovery connection failed', { + errorType: ensureError(error).name, + }); + return disconnected(failureReason); + } finally { + await client.close().catch((error: unknown) => { + this.logger.warn('Failed to close MCP discovery client', { + errorType: ensureError(error).name, + }); + }); + } + } + + private async prepareRegistrySource( + user: User, + source: McpRegistryDiscoveryRequest, + ): Promise { + const server = await this.registryService.get(source.slug); + if (server?.status !== 'active') { + throw new NotFoundError('MCP registry server not found'); + } + const connection = resolveMcpRegistryConnection(server); + if (!connection) throw new BadRequestError('MCP registry server has no supported connection'); + + const resolvedCredential = await this.resolveCredential(user, source.credentialId); + const { credential, data } = resolvedCredential; + if ( + !isSupportedMcpRegistryCredentialType(this.credentialTypes, credential.type) || + !connection.credentialBindings.some((binding) => binding.credentialType === credential.type) + ) { + throw new BadRequestError('Credential type is not supported by this MCP server'); + } + + const prepared = prepareMcpRegistryConnection({ + connection, + credentialType: credential.type, + credentialData: data, + }); + if (!prepared.ok) throw new BadRequestError('Credential cannot connect to this MCP server'); + + return { + clientConfig: { + name: safeServerName(source.slug), + url: prepared.value.endpointUrl, + transport: toAgentMcpTransport(prepared.value.transport), + fetch: this.createCredentialFetch(resolvedCredential, prepared.value.headers, { + mode: 'domains', + domains: prepared.value.allowedDomains, + }), + }, + responseConnection: { + url: getConfiguredEndpointUrl(connection), + transport: toAgentMcpTransport(connection.transport), + authentication: credential.type, + credentialId: credential.id, + metadata: { nodeTypeName: connection.nodeTypeName }, + }, + }; + } + + private async resolveCredential(user: User, credentialId: string): Promise { + const readableCredential = await this.credentialsFinderService.findCredentialForUser( + credentialId, + user, + ['credential:read'], + ); + if (!readableCredential) { + throw new NotFoundError('Credential not found or not accessible'); + } + if (readableCredential.isResolvable) { + const connectableCredential = await this.credentialsFinderService.findCredentialForUser( + credentialId, + user, + ['credential:connect'], + ); + if (!connectableCredential) { + throw new NotFoundError('Credential not found or not accessible'); + } + } + + const projectId = + readableCredential.shared?.find((share) => share.role === 'credential:owner')?.projectId ?? + readableCredential.shared?.[0]?.projectId; + if (!projectId) throw new BadRequestError('Credential has no owning project'); + + const { getBase } = await import('@/workflow-execute-additional-data.js'); + const additionalData = await getBase({ projectId, userId: user.id }); + const data = await this.credentialsHelper.getDecrypted( + additionalData, + { id: readableCredential.id, name: readableCredential.name }, + readableCredential.type, + 'internal', + ); + if (!isObjectLiteral(data) || Object.keys(data).length === 0) { + throw new BadRequestError('Credential could not be resolved'); + } + return { credential: readableCredential, data, projectId }; + } + + private createCredentialFetch( + resolved: ResolvedCredential, + initialHeaders: Record, + allowedDomains: AuthFetchDomainPolicy | undefined, + ): CustomFetch { + return createMcpAuthFetch({ + authentication: resolved.credential.type, + baseFetch: createAiMcpFetch(this.outboundHttp), + credentialData: resolved.data, + credentialId: resolved.credential.id, + initialHeaders, + oauthService: this.oauthService, + projectId: resolved.projectId, + allowedDomains, + }); + } +} diff --git a/packages/cli/src/modules/mcp-registry/mcp-registry-refresh.task.ts b/packages/cli/src/modules/mcp-registry/mcp-registry-refresh.task.ts index 6e5ebc659a6..d1ee97e8cc4 100644 --- a/packages/cli/src/modules/mcp-registry/mcp-registry-refresh.task.ts +++ b/packages/cli/src/modules/mcp-registry/mcp-registry-refresh.task.ts @@ -1,6 +1,6 @@ import { Time } from '@n8n/constants'; -import { intervalFromSeconds, SystemTask } from '@n8n/decorators'; -import type { SystemTaskEffects, SystemTaskPlacement, SystemTaskSchedule } from '@n8n/decorators'; +import { clusterTarget, intervalFromSeconds, SystemTask } from '@n8n/decorators'; +import type { SystemTaskSchedule } from '@n8n/decorators'; import { McpRegistryService } from './registry/mcp-registry.service'; @@ -18,13 +18,10 @@ export class McpRegistryRefreshTask implements SystemTask { REFRESH_INTERVAL_HOURS * Time.hours.toSeconds, ); - readonly effects: SystemTaskEffects = 'idempotent'; - - readonly placement: SystemTaskPlacement = { - scope: 'cluster', - durable: true, - runOnTakeover: true, - }; + readonly target = clusterTarget({ + scheduler: { retryOnFailure: true }, + leaderTimer: { runOnTakeover: true }, + }); constructor(private readonly mcpRegistryService: McpRegistryService) {} diff --git a/packages/cli/src/modules/mcp-registry/mcp-registry-response.ts b/packages/cli/src/modules/mcp-registry/mcp-registry-response.ts new file mode 100644 index 00000000000..cb2f040764c --- /dev/null +++ b/packages/cli/src/modules/mcp-registry/mcp-registry-response.ts @@ -0,0 +1,39 @@ +import type { McpRegistryServerResponse } from '@n8n/api-types'; + +import { resolveMcpRegistryConnection } from './mcp-registry-connection'; +import { getMcpRegistryCredentialOptions } from './node-description-transform'; +import type { McpRegistryServer } from './registry/mcp-registry.types'; + +export function toMcpRegistryServerResponse( + server: McpRegistryServer, +): McpRegistryServerResponse | null { + const connection = resolveMcpRegistryConnection(server); + if (!connection) return null; + const credentials = getMcpRegistryCredentialOptions(server).filter((option) => + connection.credentialBindings.some( + (binding) => binding.credentialType === option.credentialType, + ), + ); + if (credentials.length === 0) return null; + return { + slug: server.slug, + nodeTypeName: connection.nodeTypeName, + name: server.name, + title: server.title, + description: server.description, + tagline: server.tagline, + version: server.version, + updatedAt: server.updatedAt, + icons: server.icons, + websiteUrl: server.websiteUrl, + credentials, + tools: server.tools.map((tool) => ({ + name: tool.name, + ...(tool.title ? { title: tool.title } : {}), + })), + isTemplated: connection.isTemplated === true, + isOfficial: server.isOfficial, + status: server.status, + tags: server.tags, + }; +} diff --git a/packages/cli/src/modules/mcp-registry/mcp-registry.controller.ts b/packages/cli/src/modules/mcp-registry/mcp-registry.controller.ts index b773b0311a3..f11bdc32083 100644 --- a/packages/cli/src/modules/mcp-registry/mcp-registry.controller.ts +++ b/packages/cli/src/modules/mcp-registry/mcp-registry.controller.ts @@ -1,47 +1,38 @@ -import type { McpRegistryServerResponse } from '@n8n/api-types'; -import { Get, RestController } from '@n8n/decorators'; +import { + mcpRegistryDiscoveryRequestSchema, + type McpRegistryDiscoveryResponse, + type McpRegistryServerResponse, +} from '@n8n/api-types'; +import type { AuthenticatedRequest } from '@n8n/db'; +import { Get, GlobalScope, Post, RestController } from '@n8n/decorators'; +import { BadRequestError } from '@n8n/errors'; -import { resolveMcpRegistryConnection } from './mcp-registry-connection'; -import { getMcpRegistryCredentialOptions } from './node-description-transform'; +import { McpConnectionDiscoveryService } from './mcp-connection-discovery.service'; +import { toMcpRegistryServerResponse } from './mcp-registry-response'; import { McpRegistryService } from './registry/mcp-registry.service'; -import type { McpRegistryServer } from './registry/mcp-registry.types'; @RestController('/mcp-registry') export class McpRegistryController { - constructor(private readonly service: McpRegistryService) {} + constructor( + private readonly service: McpRegistryService, + private readonly discoveryService: McpConnectionDiscoveryService, + ) {} - /** - * Only Instance AI reads this, to fill its tool-connection picker. A - * templated row is dropped: that path cannot resolve the template, so - * `createConnection` refuses it and offering it leads nowhere. - */ @Get('/servers') + @GlobalScope('mcp:oauth') async listServers(): Promise { const servers = await this.service.getAll({ includeDeprecated: false }); - return servers - .filter((server) => !resolveMcpRegistryConnection(server)?.isTemplated) - .map(toResponse); + return servers.flatMap((server) => { + const response = toMcpRegistryServerResponse(server); + return response ? [response] : []; + }); + } + + @Post('/discover') + @GlobalScope('mcp:oauth') + async discover(req: AuthenticatedRequest): Promise { + const payload = mcpRegistryDiscoveryRequestSchema.safeParse(req.body); + if (!payload.success) throw new BadRequestError('Invalid MCP discovery request'); + return await this.discoveryService.discover(req.user, payload.data); } } - -function toResponse(server: McpRegistryServer): McpRegistryServerResponse { - return { - slug: server.slug, - name: server.name, - title: server.title, - description: server.description, - tagline: server.tagline, - version: server.version, - updatedAt: server.updatedAt, - icons: server.icons, - websiteUrl: server.websiteUrl, - credentials: getMcpRegistryCredentialOptions(server), - tools: server.tools.map((tool) => ({ - name: tool.name, - ...(tool.title ? { title: tool.title } : {}), - })), - isOfficial: server.isOfficial, - status: server.status, - tags: server.tags, - }; -} diff --git a/packages/cli/src/modules/mcp-registry/registry/mock-servers.ts b/packages/cli/src/modules/mcp-registry/registry/mock-servers.ts index 67c2d17f3c5..0d5073500b7 100644 --- a/packages/cli/src/modules/mcp-registry/registry/mock-servers.ts +++ b/packages/cli/src/modules/mcp-registry/registry/mock-servers.ts @@ -110,9 +110,9 @@ export const githubUsesCredentialsMockServer = { export const databricksGenieTemplatedMockServer: McpRegistryServer = { name: 'com.databricks/genie-mcp', slug: 'databricks-genie', - title: 'Databricks Genie', - description: 'Databricks Genie MCP server, resolved per-customer from the workspace host.', - tagline: 'Connect to Databricks Genie', + title: 'Databricks Genie One', + description: 'Databricks Genie One MCP server, resolved per-customer from the workspace host.', + tagline: 'Connect to Databricks Genie One', attribution: 'Powered by Genie', version: '1.0.0', updatedAt: '2026-08-20T10:00:00.000Z', diff --git a/packages/cli/src/modules/mcp/__tests__/agent-tools.service.test.ts b/packages/cli/src/modules/mcp/__tests__/agent-tools.service.test.ts index 94f98673cf3..3099718dfb7 100644 --- a/packages/cli/src/modules/mcp/__tests__/agent-tools.service.test.ts +++ b/packages/cli/src/modules/mcp/__tests__/agent-tools.service.test.ts @@ -75,7 +75,6 @@ import { AgentPolicyService } from '@/modules/agents/agent-policy.service'; import { createAgentSkillRefsService, storedAgentConfig, - storedSkillRefs, } from '../../agents/__tests__/test-utils/stored-agent-config'; const userHasScopesMock = userHasScopes as Mock; @@ -134,6 +133,8 @@ const agentEntity = (overrides: Record = {}): Agent => }) as unknown as Agent; describe('McpAgentToolsService', () => { + // One fake skill refs seam for the MCP service and the services it writes through. + const agentSkillRefs = createAgentSkillRefsService(); const telemetry = mockInstance(Telemetry); const credentialsService = mockInstance(CredentialsService); const agentsService = mockInstance(AgentsService); @@ -185,13 +186,14 @@ describe('McpAgentToolsService', () => { urlService, projectScopeService, new McpAgentSlackSetup(slackManagedSetup, slackManualSetup, mockLogger()), - createAgentSkillRefsService(), + agentSkillRefs, ); let tools: Map; let registerResource: Mock; beforeEach(() => { + agentSkillRefs.draftRefs.clear(); vi.clearAllMocks(); userHasScopesMock.mockResolvedValue(true); agentsService.findByIdForUser.mockResolvedValue(agentEntity()); @@ -253,13 +255,12 @@ describe('McpAgentToolsService', () => { mockLogger(), agentRepository, saveCompletion, - createAgentSkillRefsService(agentRepository), + agentSkillRefs, ); const configService = new AgentConfigService( mockLogger(), agentRepository, agentTaskRepository, - mock(), new AgentConfigPreparationService( localCredentialsService, workflowRepository, @@ -269,7 +270,7 @@ describe('McpAgentToolsService', () => { transactionRunner, saveCompletion, new AgentPolicyService(new PolicyEnforcementService()), - createAgentSkillRefsService(agentRepository), + agentSkillRefs, ); agentCustomToolsService.buildCustomTool.mockImplementation( async (agentId, projectId, code, descriptor, context, options) => @@ -1181,6 +1182,33 @@ describe('McpAgentToolsService', () => { }); }); + it('reports skill names that are hard to tell apart as a warning, not an error', async () => { + agentConfigService.validateConfig.mockResolvedValue({ valid: true, config: baseConfig }); + agentValidationService.validateLoadedAgentConfiguration.mockResolvedValue({ + status: 'valid', + issues: [], + warnings: [ + { + code: 'similar_skill_names', + capability: { kind: 'skill' }, + names: ['Brand voice', 'brand-voice'], + }, + ], + }); + + const result = await callTool('validate_agent', { agentId: 'agent-1' }); + + expect(result.structuredContent).toMatchObject({ + ok: true, + valid: true, + errors: [], + missing: [], + warnings: [ + 'Skills "Brand voice", "brand-voice" have names that are hard to tell apart. Rename one of them.', + ], + }); + }); + it('aggregates the schema error and deduplicated missing capability paths', async () => { agentConfigService.validateConfig.mockResolvedValue({ valid: false, @@ -1996,16 +2024,46 @@ describe('McpAgentToolsService', () => { expect(result.structuredContent.config).not.toHaveProperty('integrations'); }); + it('lists the pinned skills that have a newer version', async () => { + const pinnedRef = { + type: 'skill' as const, + id: 'brand_voice', + versionId: '0b2c6f1e-7d3a-4c1b-9f2e-5a6b7c8d9e0f', + }; + const skill = { name: 'Brand voice', description: 'Voice', instructions: 'Old text.' }; + agentsService.findByIdForUser.mockResolvedValue( + agentEntity({ + schema: storedAgentConfig({ ...baseConfig, skills: [pinnedRef] }), + tools: {}, + }), + ); + agentValidationService.validateAgentIsRunnable.mockResolvedValue({ missing: [] } as never); + agentSkillsService.listSkills.mockResolvedValue({ brand_voice: skill }); + agentTaskService.list.mockResolvedValue([] as never); + agentSkillRefs.findOutdatedSkillIds.mockResolvedValueOnce(['brand_voice']); + + const result = await callTool('get_agent', { projectId: 'project-1', agentId: 'agent-1' }); + + expect(result.structuredContent).toMatchObject({ outdatedSkillIds: ['brand_voice'] }); + expect(agentSkillRefs.findOutdatedSkillIds).toHaveBeenCalledWith( + [pinnedRef], + { brand_voice: skill }, + {}, + ); + }); + it('returns the stored skill refs, and config.replace of that config keeps them', async () => { const skillRefs = [ { type: 'skill' as const, id: 'zeta' }, - { type: 'skill' as const, id: 'alpha', enabled: false }, - { type: 'skill' as const, id: 'mid', enabled: true }, + { + type: 'skill' as const, + id: 'alpha', + versionId: '0b2c6f1e-7d3a-4c1b-9f2e-5a6b7c8d9e0f', + }, + { type: 'skill' as const, id: 'mid' }, ]; - const skillBody = { name: 'Skill', description: 'A skill', instructions: 'Do it.' }; const agent = agentEntity({ schema: storedAgentConfig({ ...baseConfig, skills: skillRefs }), - skills: { zeta: skillBody, mid: { ...skillBody, name: 'Mid' } }, tools: {}, }); useRealCustomToolPersistence(agent); @@ -2032,7 +2090,7 @@ describe('McpAgentToolsService', () => { }); expect(written.structuredContent).toMatchObject({ ok: true, configHash }); - expect(storedSkillRefs(agent)).toEqual(skillRefs); + await expect(agentSkillRefs.refsForDraft(agent, {})).resolves.toEqual(skillRefs); }); it('returns an error result for an unknown agent', async () => { diff --git a/packages/cli/src/modules/mcp/__tests__/execution-tools.scopes.integration.test.ts b/packages/cli/src/modules/mcp/__tests__/execution-tools.scopes.integration.test.ts new file mode 100644 index 00000000000..a0b0ba6673f --- /dev/null +++ b/packages/cli/src/modules/mcp/__tests__/execution-tools.scopes.integration.test.ts @@ -0,0 +1,127 @@ +import { + createTeamProject, + createWorkflow, + linkUserToProject, + testDb, +} from '@n8n/backend-test-utils'; +import { ExecutionRepository } from '@n8n/db'; +import type { User, WorkflowEntity } from '@n8n/db'; +import { Container } from '@n8n/di'; +import { mock } from 'vitest-mock-extended'; + +import { ExecutionListService } from '@/executions/execution-list.service'; +import { ExecutionRedactionServiceProxy } from '@/executions/execution-redaction-proxy.service'; +import type { Telemetry } from '@/telemetry'; +import { WorkflowFinderService } from '@/workflows/workflow-finder.service'; +import { createSuccessfulExecution } from '@test-integration/db/executions'; +import { createCustomRoleWithScopeSlugs } from '@test-integration/db/roles'; +import { createMember, createOwner } from '@test-integration/db/users'; + +import { createGetExecutionTool } from '../tools/get-execution.tool'; +import { createSearchExecutionsTool } from '../tools/search-executions.tool'; + +let workflow: WorkflowEntity; +let executionId: string; +let workflowReader: User; +let executionReader: User; + +beforeAll(async () => { + await testDb.init(); + + const owner = await createOwner(); + const project = await createTeamProject('MCP execution scopes', owner); + workflow = await createWorkflow({ settings: { availableInMCP: true } }, project); + executionId = (await createSuccessfulExecution(workflow)).id; + + const workflowOnlyRole = await createCustomRoleWithScopeSlugs(['workflow:read'], { + roleType: 'project', + }); + workflowReader = await createMember(); + await linkUserToProject(workflowReader, project, workflowOnlyRole.slug); + + executionReader = await createMember(); + await linkUserToProject(executionReader, project, 'project:viewer'); +}); + +afterAll(async () => { + await testDb.terminate(); +}); + +const getExecution = async (user: User, includeData: boolean) => + await createGetExecutionTool( + user, + Container.get(ExecutionRepository), + Container.get(WorkflowFinderService), + mock(), + Container.get(ExecutionRedactionServiceProxy), + ).handler( + { + workflowId: workflow.id, + executionId, + includeData, + nodeNames: undefined, + truncateData: undefined, + }, + {} as never, + ); + +const searchExecutions = async (user: User, workflowId?: string) => + await createSearchExecutionsTool( + user, + Container.get(ExecutionListService), + Container.get(WorkflowFinderService), + mock(), + ).handler({ workflowId }, {} as never); + +describe('get_workflow_execution project role scopes', () => { + test.each([true, false])( + 'returns no execution for a role without execution:read (includeData: %s)', + async (includeData) => { + const result = await getExecution(workflowReader, includeData); + + expect(result.structuredContent).toMatchObject({ + execution: null, + error: "Workflow not found or you don't have permission to access it.", + }); + expect(result.structuredContent).not.toHaveProperty('data'); + }, + ); + + test('returns the execution for a role with execution:read', async () => { + const result = await getExecution(executionReader, false); + + expect(result.structuredContent).toMatchObject({ + execution: { id: executionId, workflowId: workflow.id }, + }); + }); +}); + +describe('search_workflow_executions project role scopes', () => { + test('returns an access error for a role without execution:read when filtering by workflow', async () => { + const result = await searchExecutions(workflowReader, workflow.id); + + expect(result.isError).toBe(true); + expect(result.structuredContent).toMatchObject({ + data: [], + error: "Workflow not found or you don't have permission to access it.", + }); + }); + + test('returns no executions for a role without execution:read', async () => { + const result = await searchExecutions(workflowReader); + + expect(result.structuredContent).toMatchObject({ data: [], count: 0 }); + expect(result.structuredContent).not.toHaveProperty('error'); + }); + + test.each([undefined, 'workflow'] as const)( + 'returns the execution for a role with execution:read (filter: %s)', + async (filter) => { + const result = await searchExecutions(executionReader, filter ? workflow.id : undefined); + + expect(result.structuredContent).toMatchObject({ + data: [expect.objectContaining({ id: executionId, workflowId: workflow.id })], + }); + }, + ); +}); diff --git a/packages/cli/src/modules/mcp/__tests__/get-execution.tool.test.ts b/packages/cli/src/modules/mcp/__tests__/get-execution.tool.test.ts index 935e1ab81aa..6b4c6568b8d 100644 --- a/packages/cli/src/modules/mcp/__tests__/get-execution.tool.test.ts +++ b/packages/cli/src/modules/mcp/__tests__/get-execution.tool.test.ts @@ -57,6 +57,74 @@ describe('get-execution MCP tool', () => { }); describe('handler tests', () => { + describe('access checks', () => { + test.each([true, false])( + 'requires workflow:read and execution:read on the workflow (includeData: %s)', + async (includeData) => { + const tool = createGetExecutionTool( + user, + executionRepository, + workflowFinderService, + telemetry, + executionRedactionServiceProxy, + ); + + (workflowFinderService.findWorkflowForUser as Mock).mockResolvedValue(mockWorkflow); + (executionPersistence.findWithUnflattenedData as Mock).mockResolvedValue(null); + (executionRepository.findIfAccessible as Mock).mockResolvedValue(null); + + await tool.handler( + { + workflowId: 'workflow-1', + executionId: 'execution-1', + includeData, + nodeNames: undefined, + truncateData: undefined, + }, + {} as never, + ); + + expect(workflowFinderService.findWorkflowForUser).toHaveBeenCalledWith( + 'workflow-1', + user, + ['workflow:read', 'execution:read'], + {}, + ); + }, + ); + + test.each([true, false])( + 'does not load the execution when the workflow lookup fails (includeData: %s)', + async (includeData) => { + const tool = createGetExecutionTool( + user, + executionRepository, + workflowFinderService, + telemetry, + executionRedactionServiceProxy, + ); + + (workflowFinderService.findWorkflowForUser as Mock).mockResolvedValue(null); + + const result = await tool.handler( + { + workflowId: 'workflow-1', + executionId: 'execution-1', + includeData, + nodeNames: undefined, + truncateData: undefined, + }, + {} as never, + ); + + expect(executionPersistence.findWithUnflattenedData).not.toHaveBeenCalled(); + expect(executionRepository.findIfAccessible).not.toHaveBeenCalled(); + expect(result.structuredContent).toMatchObject({ execution: null }); + expect(result.structuredContent).not.toHaveProperty('data'); + }, + ); + }); + describe('execution retrieval', () => { test('returns generic error when execution is not found for workflow', async () => { const tool = createGetExecutionTool( diff --git a/packages/cli/src/modules/mcp/__tests__/mcp-api-key.service.integration.test.ts b/packages/cli/src/modules/mcp/__tests__/mcp-api-key.service.integration.test.ts index 6f9aeff4fb3..9ffae754d33 100644 --- a/packages/cli/src/modules/mcp/__tests__/mcp-api-key.service.integration.test.ts +++ b/packages/cli/src/modules/mcp/__tests__/mcp-api-key.service.integration.test.ts @@ -9,7 +9,7 @@ import { ScopedJwtStrategy } from '@/modules/token-exchange/services/scoped-jwt. import { TOKEN_EXCHANGE_ISSUER } from '@/modules/token-exchange/token-exchange.types'; import { ApiKeyAuthStrategy } from '@/services/api-key-auth.strategy'; import { AuthStrategyRegistry } from '@/services/auth-strategy.registry'; -import { JwtService } from '@/services/jwt.service'; +import { JwtService } from '@n8n/backend-services'; import { SessionCookieAuthStrategy } from '@/services/session-cookie-auth.strategy'; import { createMember, createOwner, createOwnerWithApiKey } from '@test-integration/db/users'; diff --git a/packages/cli/src/modules/mcp/__tests__/mcp-api-key.service.test.ts b/packages/cli/src/modules/mcp/__tests__/mcp-api-key.service.test.ts index 1402725fc26..0c98cab573e 100644 --- a/packages/cli/src/modules/mcp/__tests__/mcp-api-key.service.test.ts +++ b/packages/cli/src/modules/mcp/__tests__/mcp-api-key.service.test.ts @@ -3,7 +3,7 @@ import type { ApiKeyRepository, User, TokenGrant } from '@n8n/db'; import { mock } from 'vitest-mock-extended'; import type { AuthStrategyRegistry } from '@/services/auth-strategy.registry'; -import type { JwtService } from '@/services/jwt.service'; +import type { JwtService } from '@n8n/backend-services'; import { McpServerApiKeyService } from '../mcp-api-key.service'; diff --git a/packages/cli/src/modules/mcp/__tests__/mcp-server-middleware.service.test.ts b/packages/cli/src/modules/mcp/__tests__/mcp-server-middleware.service.test.ts index e3e4611db33..875c5f903f5 100644 --- a/packages/cli/src/modules/mcp/__tests__/mcp-server-middleware.service.test.ts +++ b/packages/cli/src/modules/mcp/__tests__/mcp-server-middleware.service.test.ts @@ -7,7 +7,7 @@ import { generateKeyPairSync } from 'node:crypto'; import { mock, mockDeep } from 'vitest-mock-extended'; import type { InstanceSettings } from 'n8n-core'; -import { JwtService } from '@/services/jwt.service'; +import { JwtService } from '@n8n/backend-services'; import type { McpCallerAuth } from '@/services/oauth-token-verifier-proxy.service'; import { OAuthTokenVerifierProxy } from '@/services/oauth-token-verifier-proxy.service'; import { Telemetry } from '@/telemetry'; diff --git a/packages/cli/src/modules/mcp/__tests__/search-executions.tool.test.ts b/packages/cli/src/modules/mcp/__tests__/search-executions.tool.test.ts index bec1d288817..07a25a37863 100644 --- a/packages/cli/src/modules/mcp/__tests__/search-executions.tool.test.ts +++ b/packages/cli/src/modules/mcp/__tests__/search-executions.tool.test.ts @@ -35,7 +35,7 @@ describe('search-executions MCP tool', () => { beforeEach(() => { executionListService = mockInstance(ExecutionListService, { buildSharingOptions: vi.fn().mockResolvedValue({ - scopes: ['workflow:read'], + scopes: ['execution:read'], projectRoles: ['project:editor'], workflowRoles: ['workflow:editor'], }), @@ -123,7 +123,7 @@ describe('search-executions MCP tool', () => { expect(workflowFinderService.findWorkflowForUser).toHaveBeenCalledWith( 'wf-1', user, - ['workflow:read'], + ['workflow:read', 'execution:read'], { includeActiveVersion: undefined }, ); @@ -203,10 +203,32 @@ describe('search-executions MCP tool', () => { }); }); + test('returns an access error and runs no query when the workflow lookup fails', async () => { + (workflowFinderService.findWorkflowForUser as Mock).mockResolvedValue(null); + + const result = await createTool().handler({ workflowId: 'wf-1' } as never, {} as never); + + expect(result.isError).toBe(true); + expect(result.structuredContent).toEqual({ + data: [], + count: 0, + estimated: false, + nextCursor: null, + error: "Workflow not found or you don't have permission to access it.", + }); + expect(executionListService.findPageWithCount).not.toHaveBeenCalled(); + }); + test('delegates sharing options to the list service', async () => { await createTool().handler({} as never, {} as never); - expect(executionListService.buildSharingOptions).toHaveBeenCalledWith('workflow:read'); + expect(executionListService.buildSharingOptions).toHaveBeenCalledWith('execution:read'); + const query = (executionListService.findPageWithCount as Mock).mock.calls[0][0]; + expect(query.sharingOptions).toEqual({ + scopes: ['execution:read'], + projectRoles: ['project:editor'], + workflowRoles: ['workflow:editor'], + }); }); test('tracks telemetry on success', async () => { diff --git a/packages/cli/src/modules/mcp/evaluations/README.md b/packages/cli/src/modules/mcp/evaluations/README.md index 36cfa8cc070..000a5fc6cce 100644 --- a/packages/cli/src/modules/mcp/evaluations/README.md +++ b/packages/cli/src/modules/mcp/evaluations/README.md @@ -49,8 +49,6 @@ N8N_INSTANCE_AI_MODEL_API_KEY=sk-ant-... N8N_EVAL_EMAIL=eval@example.com N8N_EVAL_PASSWORD=... -CONTEXT7_API_KEY=ctx7sk-... - # Optional — record this run to LangSmith. Pair with --dataset and # --baseline-prefix (see "Record runs in LangSmith") so MCP runs never touch # the Instance AI dataset or baseline. @@ -332,8 +330,8 @@ dotenvx run -f .env.mcp-evals -- pnpm --filter @n8n/instance-ai run eval:instanc --output-dir /tmp/n8n-mcp-cohort-eval ``` -The eval CLI reads `N8N_EVAL_EMAIL`, `N8N_EVAL_PASSWORD`, model keys, and -Context7 settings from `.env.mcp-evals`. +The eval CLI reads `N8N_EVAL_EMAIL`, `N8N_EVAL_PASSWORD`, and model keys from +`.env.mcp-evals`. ## Evaluate one generated test case diff --git a/packages/cli/src/modules/mcp/mcp-api-key.service.ts b/packages/cli/src/modules/mcp/mcp-api-key.service.ts index b61c208de4f..5ad5327e95e 100644 --- a/packages/cli/src/modules/mcp/mcp-api-key.service.ts +++ b/packages/cli/src/modules/mcp/mcp-api-key.service.ts @@ -6,7 +6,7 @@ import { ensureError } from '@n8n/utils/errors/ensure-error'; import { ApiKeyAudience } from 'n8n-workflow'; import { AuthStrategyRegistry } from '@/services/auth-strategy.registry'; -import { JwtService } from '@/services/jwt.service'; +import { JwtService } from '@n8n/backend-services'; import { UserWithContext } from '@/services/oauth-token-verifier-proxy.service'; const API_KEY_AUDIENCE: ApiKeyAudience = 'mcp-server-api'; diff --git a/packages/cli/src/modules/mcp/mcp-server-middleware.service.ts b/packages/cli/src/modules/mcp/mcp-server-middleware.service.ts index 93998ce2b3a..096614c7d07 100644 --- a/packages/cli/src/modules/mcp/mcp-server-middleware.service.ts +++ b/packages/cli/src/modules/mcp/mcp-server-middleware.service.ts @@ -4,7 +4,7 @@ import { NextFunction, Response, Request } from 'express'; import { ensureError } from '@n8n/utils/errors/ensure-error'; import { AuthError } from '@n8n/errors'; -import { JwtService } from '@/services/jwt.service'; +import { JwtService } from '@n8n/backend-services'; import { OAuthTokenVerifierProxy, type TelemetryAuthContext, diff --git a/packages/cli/src/modules/mcp/tools/agents/agent-reference.ts b/packages/cli/src/modules/mcp/tools/agents/agent-reference.ts index a7f29227ed2..2d45a94cb06 100644 --- a/packages/cli/src/modules/mcp/tools/agents/agent-reference.ts +++ b/packages/cli/src/modules/mcp/tools/agents/agent-reference.ts @@ -95,10 +95,15 @@ directly on that object — there is no \`value\` wrapper. For example: integrations; use update_agent_integration for those. - config.patch: Set \`patch\` to an array of RFC 6902 operations (add, remove, replace, move, copy, test). Paths under /integrations are rejected; use update_agent_integration for those. -- skill.upsert: Set \`skill\` to the complete skill body. Omit \`skillId\` to create and attach a new - skill, or pass it to replace an existing skill body. When replacing, also pass \`baseSkillHash\` - from get_agent's \`skillHashes\` so a skill edited elsewhere in the meantime is not overwritten. -- skill.delete: Set \`skillId\` to the skill to delete; its config reference is removed. +- skill.upsert: Set \`skill\` to the complete skill body. Omit \`skillId\` to create a new skill in + the Agent's project and attach it, or pass it to save the next version of an attached skill. A + skill can be shared: every Agent that uses it runs the new version. When replacing, also pass + \`baseSkillHash\` from get_agent's \`skillHashes\` so a skill edited elsewhere in the meantime is + not overwritten. Skills ignore \`allowedTools\`. +- skill.delete: Set \`skillId\` to the skill to detach. The skill stays available to other Agents. +- A skill ref with \`versionId\` pins that saved version of the skill. get_agent lists the pinned + skills that have a newer version in \`outdatedSkillIds\`. To use the latest version, remove + \`versionId\` from the ref with config.patch. Do not delete and add the skill again. - task.upsert: Set \`task\` to the complete task body. Omit \`taskId\` to create and attach a new scheduled task, or pass it to replace an existing one. \`enabled\` controls the task config reference. On a replace, an omitted \`timezone\` keeps the zone the task already has; send \`null\` to move it @@ -206,10 +211,10 @@ Before writing an entry into mcpServers, call verify_agent_mcp_server with the s transport, authentication, and credential. The server does not need to be attached to the Agent first: verification opens a temporary connection and returns the server's live tools. validate_agent never performs this handshake, so an unverified entry can pass validation and still fail at runtime. -Confirm the returned tools cover the requested capability and use the list to populate toolFilter -instead of guessing tool names. If verification fails, report the error and resolve it with the user -instead of persisting a broken server. Only when the user cannot supply the URL or credential yet, -persist the known fields without inventing values and skip verification. +Confirm the returned tools cover the requested capability and use the verified list instead of +guessing tool names. If verification fails, report the error and resolve it with the user instead of +persisting a broken server. Only when the user cannot supply the URL or credential yet, persist the +known fields without inventing values and skip verification. `; export const AGENT_BUILDER_REFERENCE = `${AGENT_BUILDER_GUIDE} diff --git a/packages/cli/src/modules/mcp/tools/agents/agent-tools.service.ts b/packages/cli/src/modules/mcp/tools/agents/agent-tools.service.ts index 0a0696189c0..e802285a206 100644 --- a/packages/cli/src/modules/mcp/tools/agents/agent-tools.service.ts +++ b/packages/cli/src/modules/mcp/tools/agents/agent-tools.service.ts @@ -102,7 +102,7 @@ function integrationsField(config: unknown): unknown { /** * Collects the credential IDs that `sanitizeUnknownAgentCredentials` rewrote - * to `''` — the only change that sanitizer ever makes. + * to `''` — the only change that sanitizer ever makes. */ function collectClearedCredentialIds( original: unknown, @@ -125,8 +125,8 @@ function collectClearedCredentialIds( /** * True when `next` alters the integrations array relative to `current`. Compared - * structurally rather than by patch path so no operation — including an - * ancestor or whole-document replace — can slip an integrations change through. + * structurally rather than by patch path so no operation — including an + * ancestor or whole-document replace — can slip an integrations change through. */ function integrationsChanged(current: AgentJsonConfig, next: unknown): boolean { return ( @@ -1121,6 +1121,11 @@ export class McpAgentToolsService { this.agentSkillsService.listSkills(agentId, projectId), this.agentTaskService.list(agentId), ]); + const outdatedSkillIds = await this.agentSkillRefs.findOutdatedSkillIds( + config.skills ?? [], + skills, + {}, + ); const taskEnabled = new Map((config.tasks ?? []).map((task) => [task.id, task.enabled])); // The hash covers the full persisted config (integrations included) so it @@ -1148,6 +1153,7 @@ export class McpAgentToolsService { skillHashes: Object.fromEntries( Object.entries(skills).map(([id, skill]) => [id, getAgentSkillHash(skill)]), ), + outdatedSkillIds, tasks: tasks.map((task) => ({ ...task, enabled: taskEnabled.get(task.id) ?? false })), customTools: Object.entries(agent.tools ?? {}).map(([id, tool]) => ({ id, @@ -1527,7 +1533,7 @@ export class McpAgentToolsService { * mutation itself introduced loudly instead of reporting a success that * persisted less than the client sent. Instability inherited unchanged from * the stored config (e.g. a legacy field persisted before the schema - * dropped it) is tolerated — the write path cleans it up. + * dropped it) is tolerated — the write path cleans it up. */ private assertSanitizeStable(config: unknown, baseConfig: AgentJsonConfig): void { const sanitized = sanitizeAgentJsonConfig(config); @@ -1571,8 +1577,8 @@ export class McpAgentToolsService { /** * updateConfig quietly rewrites credential references the calling user * cannot use to `''` before saving. Surfacing that here turns silent - * credential loss — including references already stored on the agent by - * another user — into an explicit error the client can act on. + * credential loss — including references already stored on the agent by + * another user — into an explicit error the client can act on. */ private async assertAccessibleCredentials( config: unknown, @@ -1617,7 +1623,7 @@ export class McpAgentToolsService { } /** - * Publish-scope validation — the same pass `publishAgent` enforces — plus + * Publish-scope validation — the same pass `publishAgent` enforces — plus * the node-tool JSON-Schema checks from `validateConfig`, so validate_agent * and publish_agent cannot drift from the canonical validator. */ @@ -1644,10 +1650,18 @@ export class McpAgentToolsService { ), ), ]; + const warnings = (configuration.warnings ?? []).flatMap((warning) => + warning.code === 'similar_skill_names' + ? [ + `Skills ${warning.names.map((name) => `"${name}"`).join(', ')} have names that are hard to tell apart. Rename one of them.`, + ] + : [], + ); return { valid: errors.length === 0 && missing.length === 0, errors, missing, + ...(warnings.length > 0 ? { warnings } : {}), }; } @@ -1673,8 +1687,8 @@ export class McpAgentToolsService { ...(truncated ? { hint: 'Pass query to filter models by ID.' } : {}), }; } - // The full catalog runs to hundreds of KB — far past MCP client - // token limits — so without a provider return a summary instead. + // The full catalog runs to hundreds of KB — far past MCP client + // token limits — so without a provider return a summary instead. const catalog = filterOfferedAgentModelProviders( await (await import('@n8n/agents')).fetchProviderCatalog(), ); @@ -1745,6 +1759,9 @@ export class McpAgentToolsService { authentication: input.authentication, credential: input.credential, metadata: input.metadata, + toolPermissions: { + categories: { read: 'always_allow', write: 'always_allow' }, + }, ...(input.connectionTimeoutMs !== undefined ? { connectionTimeoutMs: input.connectionTimeoutMs } : {}), diff --git a/packages/cli/src/modules/mcp/tools/get-execution.tool.ts b/packages/cli/src/modules/mcp/tools/get-execution.tool.ts index ae47d464b1e..916e5dbb931 100644 --- a/packages/cli/src/modules/mcp/tools/get-execution.tool.ts +++ b/packages/cli/src/modules/mcp/tools/get-execution.tool.ts @@ -98,7 +98,12 @@ export const createGetExecutionTool = ( }; try { - await getMcpWorkflow(workflowId, user, ['workflow:read'], workflowFinderService); + await getMcpWorkflow( + workflowId, + user, + ['workflow:read', 'execution:read'], + workflowFinderService, + ); // Use lightweight metadata query when data isn't needed; // split into branches so TypeScript can narrow each return type. diff --git a/packages/cli/src/modules/mcp/tools/search-executions.tool.ts b/packages/cli/src/modules/mcp/tools/search-executions.tool.ts index 8b47b195ddb..81bcadb84b5 100644 --- a/packages/cli/src/modules/mcp/tools/search-executions.tool.ts +++ b/packages/cli/src/modules/mcp/tools/search-executions.tool.ts @@ -113,11 +113,16 @@ export const createSearchExecutionsTool = ( try { // Validate workflow access if workflowId is provided if (workflowId) { - await getMcpWorkflow(workflowId, user, ['workflow:read'], workflowFinderService); + await getMcpWorkflow( + workflowId, + user, + ['workflow:read', 'execution:read'], + workflowFinderService, + ); } const safeLimit = Math.min(Math.max(1, limit), MAX_RESULTS); - const sharingOptions = await executionListService.buildSharingOptions('workflow:read'); + const sharingOptions = await executionListService.buildSharingOptions('execution:read'); const parsedCursor = parseExecutionCursor(cursor); const query = { diff --git a/packages/cli/src/modules/modules.manifest.ts b/packages/cli/src/modules/modules.manifest.ts index dbe3ca24424..6142d7b1867 100644 --- a/packages/cli/src/modules/modules.manifest.ts +++ b/packages/cli/src/modules/modules.manifest.ts @@ -6,4 +6,5 @@ import type { PackagedModules } from '@n8n/backend-common'; */ export const packagedModules: PackagedModules = { insights: async () => await import('@n8n/backend-module-insights/module'), + 'quick-connect': async () => await import('@n8n/backend-module-quick-connect/module'), }; diff --git a/packages/cli/src/modules/n8n-packages/CLAUDE.md b/packages/cli/src/modules/n8n-packages/CLAUDE.md index 4db8f2a0825..0ac97ebebfc 100644 --- a/packages/cli/src/modules/n8n-packages/CLAUDE.md +++ b/packages/cli/src/modules/n8n-packages/CLAUDE.md @@ -14,7 +14,7 @@ CLI flag is a silent bug, not a compile error. ```mermaid flowchart LR M["1. Module
(this package)"] --> D["2. DTO
@n8n/api-types"] - D --> A["3. Public API
handler + OpenAPI spec"] + D --> A["3. Public API
controller"] A --> C["4. CLI
@n8n/cli"] ``` @@ -52,11 +52,10 @@ flowchart LR - Add the field to `ImportPackageRequestDto` (zod), **and** add its name to `IMPORT_PACKAGE_REQUEST_FORM_FIELDS` (multipart text fields). - Update `__tests__/import-package-request.dto.test.ts`. -3. **Public API** — `packages/cli/src/public-api/v1/handlers/n8n-packages/` - - `n8n-packages.handler.ts` — pass `payload.data.` into the service. - - `spec/paths/n8n-packages.import.yml` — add the property to the inline - `multipart/form-data` request schema (type/enum/description; update - `required` if needed). **Easy to forget — the spec is hand-written.** +3. **Public API** — `packages/cli/src/public-api/v1/controllers/n8n-packages.public.controller.ts` + - `importPackage` passes the request fields into the service. + - The multipart request schema comes from `ImportPackageRequestDto` (step 2), + so do not edit a YAML file. Run `pnpm build` to regenerate the spec. 4. **CLI** — `packages/@n8n/cli/` - `src/client.ts` — add to `ImportPackageFields`. - `src/commands/package/import.ts` — add a `Flags.string({...})` (with a @@ -69,11 +68,11 @@ flowchart LR `n8n-packages.service.ts` `exportPackage` (+ `io/` writer or `entities/*/` exporter as needed). 2. **DTO** — `@n8n/api-types/src/dto/packages/export-package-request.dto.ts` - (`ExportPackageRequestDto`, zod). -3. **Public API** — `n8n-packages.handler.ts` `exportPackage` reads from - `payload.data`; update the **separate** schema file - `spec/schemas/exportPackageRequest.yml` (export's request schema is a - `$ref`, unlike import's inline schema). + (`ExportPackageRequestDto`, zod). Add the field's OpenAPI wording to + `export-package-request.openapi.ts`. +3. **Public API** — `packages/cli/src/public-api/v1/controllers/n8n-packages.public.controller.ts` + `exportPackage` reads from `body`. The request schema comes from + `ExportPackageRequestDto`, so do not edit a YAML file. 4. **CLI** — `src/client.ts` `exportPackage(...)`, `src/commands/package/export.ts` flag, and the docs/README. diff --git a/packages/cli/src/modules/n8n-packages/__tests__/blocking-issue-schema-contract.test.ts b/packages/cli/src/modules/n8n-packages/__tests__/blocking-issue-schema-contract.test.ts index babc329a7a0..72f0637a1f5 100644 --- a/packages/cli/src/modules/n8n-packages/__tests__/blocking-issue-schema-contract.test.ts +++ b/packages/cli/src/modules/n8n-packages/__tests__/blocking-issue-schema-contract.test.ts @@ -29,6 +29,14 @@ describe('BlockingIssue / ImportBlockingIssue contract', () => { expectTypeOf>().branded.toEqualTypeOf< Extract >(); + expectTypeOf>().branded.toEqualTypeOf< + Extract + >(); + expectTypeOf< + Extract + >().branded.toEqualTypeOf< + Extract + >(); expectTypeOf>().branded.toEqualTypeOf< Extract >(); diff --git a/packages/cli/src/modules/n8n-packages/__tests__/export-agent-package.integration.test.ts b/packages/cli/src/modules/n8n-packages/__tests__/export-agent-package.integration.test.ts index 8a023b63d53..29bfa91b288 100644 --- a/packages/cli/src/modules/n8n-packages/__tests__/export-agent-package.integration.test.ts +++ b/packages/cli/src/modules/n8n-packages/__tests__/export-agent-package.integration.test.ts @@ -9,11 +9,19 @@ import { tmpdir } from 'node:os'; import path from 'node:path'; import { mock } from 'vitest-mock-extended'; +import { setSkillsHubFlag } from '@/modules/agents/__tests__/test-utils/skills-hub-flag'; +import { AgentSkillDependency } from '@/modules/agents/entities/agent-skill-dependency.entity'; +import { AgentVersionSkillDependency } from '@/modules/agents/entities/agent-version-skill-dependency.entity'; import type { Agent } from '@/modules/agents/entities/agent.entity'; +import { SkillFile } from '@/modules/agents/entities/skill-file.entity'; +import { SkillVersion } from '@/modules/agents/entities/skill-version.entity'; import { AgentHistoryRepository } from '@/modules/agents/repositories/agent-history.repository'; import { AgentTaskSnapshotRepository } from '@/modules/agents/repositories/agent-task-snapshot.repository'; import { AgentTaskRepository } from '@/modules/agents/repositories/agent-task.repository'; import { AgentRepository } from '@/modules/agents/repositories/agent.repository'; +import { SkillRepository } from '@/modules/agents/repositories/skill.repository'; +import { withoutLegacySkillRefs } from '@/modules/agents/json-config/agent-document'; +import { toSkillContent } from '@/modules/agents/skills/skill.service'; import type { NodeTypes } from '@/node-types'; import { N8nPackageParser } from '../engine/n8n-package-parser'; @@ -40,22 +48,34 @@ let agentRepository: AgentRepository; let historyRepository: AgentHistoryRepository; let taskRepository: AgentTaskRepository; let taskSnapshotRepository: AgentTaskSnapshotRepository; +let skillRepository: SkillRepository; let directory: string; async function readSourceRecords() { + const { manager } = skillRepository; return await Promise.all([ agentRepository.find({ order: { id: 'ASC' } }), historyRepository.find({ order: { versionId: 'ASC' } }), taskRepository.find({ order: { id: 'ASC' } }), taskSnapshotRepository.find({ order: { versionId: 'ASC', taskId: 'ASC' } }), + // The skills hub rows of the agents, so an export that changes them fails too. + skillRepository.find({ order: { id: 'ASC' } }), + manager.find(SkillVersion, { order: { id: 'ASC' } }), + manager.find(SkillFile, { order: { skillVersionId: 'ASC', path: 'ASC' } }), + manager.find(AgentSkillDependency, { order: { agentId: 'ASC', skillId: 'ASC' } }), + manager.find(AgentVersionSkillDependency, { + order: { agentVersionId: 'ASC', skillId: 'ASC' }, + }), ]); } beforeAll(async () => { + await setSkillsHubFlag(true); await testModules.loadModules(['agents']); await testDb.init(); agentRepository = Container.get(AgentRepository); historyRepository = Container.get(AgentHistoryRepository); + skillRepository = Container.get(SkillRepository); taskRepository = Container.get(AgentTaskRepository); taskSnapshotRepository = Container.get(AgentTaskSnapshotRepository); exporter = Container.get(AgentExporter); @@ -63,13 +83,35 @@ beforeAll(async () => { const fixture = looseAgentsFixture(); for (const entry of fixture.manifest.agents) { const draft = serializedAgentSchema.parse(fixture.files[`${entry.target}/agent.json`]); + // A skill of a saved agent is a skills hub skill: it has its own id, no + // `enabled` flag on the ref, and no `allowedTools`. + const skillId = `${draft.id}_skill`; + const { allowedTools: _dropped, ...draftSkill } = draft.skills['shared-skill']; + draft.skills = { [skillId]: draftSkill }; + draft.config = { + ...AgentJsonConfigSchema.parse(draft.config), + skills: [{ type: 'skill', id: skillId }], + }; const published = structuredClone(draft); published.config = { ...AgentJsonConfigSchema.parse(published.config), instructions: 'Published configuration', integrations: [{ type: 'n8n_chat', credentialId: '' }], }; - published.skills['shared-skill'].instructions = 'Published skill'; + published.skills[skillId].instructions = 'Published skill'; + // v1 is the published text, v2 the text the draft follows. + await skillRepository.createSkill( + { + id: skillId, + target: { projectId: project.id, agentId: null }, + source: 'ui', + createdById: null, + }, + toSkillContent(published.skills[skillId]), + ); + const publishedSkillVersionId = (await skillRepository.findLatestSaved([skillId])).get(skillId)! + .version.id; + await skillRepository.insertSavedVersion(skillId, 2, toSkillContent(draftSkill), null); published.tools.shared_tool.code = 'throw new Error("Published tool must not run");'; published.tasks[`${entry.id}_task`] = { name: 'Published schedule', @@ -81,8 +123,7 @@ beforeAll(async () => { id: draft.id, name: draft.name, projectId: project.id, - schema: draft.config && storedAgentConfig(draft.config), - skills: draft.skills, + schema: draft.config && withoutLegacySkillRefs(storedAgentConfig(draft.config)), tools: draft.tools, availableInMCP: draft.availableInMCP, integrations: [{ type: 'slack', credentialId: 'current-slack' }], @@ -96,11 +137,14 @@ beforeAll(async () => { const history = await historyRepository.saveVersion({ versionId: `${agent.id}_published`, agentId: agent.id, - schema: storedAgentConfig(published.config), - skills: published.skills, + schema: withoutLegacySkillRefs(storedAgentConfig(published.config)), tools: published.tools, publishedBy: 'Package test', }); + await skillRepository.replaceDependencies(agent.id, [{ skillId }]); + await skillRepository.insertPins([ + { agentVersionId: history.versionId, skillId, skillVersionId: publishedSkillVersionId }, + ]); await taskSnapshotRepository.saveForVersion( Object.entries(published.tasks).map(([taskId, task]) => ({ versionId: history.versionId, diff --git a/packages/cli/src/modules/n8n-packages/__tests__/export-agent-selection.integration.test.ts b/packages/cli/src/modules/n8n-packages/__tests__/export-agent-selection.integration.test.ts index c6d2feca7ec..b07166a8dd2 100644 --- a/packages/cli/src/modules/n8n-packages/__tests__/export-agent-selection.integration.test.ts +++ b/packages/cli/src/modules/n8n-packages/__tests__/export-agent-selection.integration.test.ts @@ -101,7 +101,6 @@ async function publish(agent: Agent) { versionId: `${agent.id}_published`, publishedBy: 'Package test', schema: definition.schema && storedAgentConfig(definition.schema), - skills: definition.skills, tools: definition.tools, }); await repository.setActiveVersionFenced(agent.id, agent.revision, { diff --git a/packages/cli/src/modules/n8n-packages/__tests__/export-workflow-with-credentials.integration.test.ts b/packages/cli/src/modules/n8n-packages/__tests__/export-workflow-with-credentials.integration.test.ts index 6361e297110..ea841a7f1db 100644 --- a/packages/cli/src/modules/n8n-packages/__tests__/export-workflow-with-credentials.integration.test.ts +++ b/packages/cli/src/modules/n8n-packages/__tests__/export-workflow-with-credentials.integration.test.ts @@ -125,7 +125,8 @@ describe('workflow package export — with credentials', () => { (e) => e.name === `${manifest.credentials![0].target}/credential.json`, ); const parsed = jsonParse>(credentialFile!.content.toString()); - expect(Object.keys(parsed).sort()).toEqual(['data', 'id', 'name', 'type']); + expect(Object.keys(parsed).sort()).toEqual(['data', 'dataIsComplete', 'id', 'name', 'type']); + expect(parsed.dataIsComplete).toBe(false); expect(parsed.data).toEqual({ value: '={{ $secrets.api.key }}' }); // The literal field value must not appear anywhere in the archive. diff --git a/packages/cli/src/modules/n8n-packages/__tests__/fixtures/agent-package-fixtures.ts b/packages/cli/src/modules/n8n-packages/__tests__/fixtures/agent-package-fixtures.ts index d30d22c28fb..27820d9502b 100644 --- a/packages/cli/src/modules/n8n-packages/__tests__/fixtures/agent-package-fixtures.ts +++ b/packages/cli/src/modules/n8n-packages/__tests__/fixtures/agent-package-fixtures.ts @@ -54,7 +54,7 @@ function agentFiles(entry: ManifestEntry, availableInMCP: boolean): Record & Pick, +): SerializedCredential { + return { name: 'GitHub', type: PACKAGE_GITHUB_CREDENTIAL_TYPE, ...overrides }; +} + +function credentialManifestEntry(credential: SerializedCredential): ManifestEntry { + return { + id: credential.id, + name: credential.name, + target: `credentials/credential-${credential.id}`, + }; +} + export async function buildImportPackageBuffer( workflows: PackageWorkflow[], options: { @@ -235,6 +250,8 @@ export async function buildImportPackageBuffer( sourceId?: string; /** Replaces every metadata file, or leaves it out, so tests can drive the rejections. */ workflowMetadata?: 'omit' | Record; + /** Credential files, written at the top-level `credentials/` folder (simulates export). */ + credentials?: SerializedCredential[]; } = {}, ): Promise { const writer = new TarPackageWriter(); @@ -250,6 +267,11 @@ export async function buildImportPackageBuffer( name: w.name, target: `workflows/wf-${idx}`, })), + ...(options.credentials?.length + ? { + credentials: options.credentials.map((credential) => credentialManifestEntry(credential)), + } + : {}), ...options.manifestExtras, }; @@ -277,6 +299,11 @@ export async function buildImportPackageBuffer( ); } }); + for (const credential of options.credentials ?? []) { + const { target } = credentialManifestEntry(credential); + writer.writeDirectory(target); + writer.writeFile(entityFilePath('credentials', target), JSON.stringify(credential)); + } return await streamToBuffer(writer.finalize()); } @@ -365,8 +392,14 @@ export interface PackageVariableEntry { variable: SerializedVariable; } +export interface PackageCredentialEntry { + target: string; + credential: SerializedCredential; +} + export interface EntityPackageOptions { workflows?: PackageWorkflowEntry[]; + credentials?: PackageCredentialEntry[]; folders?: PackageFolderEntry[]; projects?: PackageProjectEntry[]; dataTables?: PackageDataTableEntry[]; @@ -384,6 +417,7 @@ async function writeEntityPackage( const projects = options.projects ?? []; const dataTables = options.dataTables ?? []; const variables = options.variables ?? []; + const credentials = options.credentials ?? []; const manifest: PackageManifest = { packageFormatVersion: FORMAT_VERSION, @@ -435,6 +469,15 @@ async function writeEntityPackage( })), } : {}), + ...(credentials.length > 0 + ? { + credentials: credentials.map(({ target, credential }) => ({ + id: credential.id, + name: credential.name, + target, + })), + } + : {}), ...options.manifestExtras, }; @@ -462,6 +505,10 @@ async function writeEntityPackage( await writer.writeDirectory(target); await writer.writeFile(entityFilePath('variables', target), JSON.stringify(variable)); } + for (const { target, credential } of credentials) { + await writer.writeDirectory(target); + await writer.writeFile(entityFilePath('credentials', target), JSON.stringify(credential)); + } } /** diff --git a/packages/cli/src/modules/n8n-packages/__tests__/import-credential-conflict.integration.test.ts b/packages/cli/src/modules/n8n-packages/__tests__/import-credential-conflict.integration.test.ts new file mode 100644 index 00000000000..18a3b867a04 --- /dev/null +++ b/packages/cli/src/modules/n8n-packages/__tests__/import-credential-conflict.integration.test.ts @@ -0,0 +1,574 @@ +import { LicenseState } from '@n8n/backend-common'; +import { + createTeamProject, + linkUserToProject, + mockInstance, + testDb, + testModules, +} from '@n8n/backend-test-utils'; +import type { CredentialsEntity, Project, User } from '@n8n/db'; +import { + CredentialsRepository, + FolderRepository, + TagRepository, + WorkflowRepository, +} from '@n8n/db'; +import { Container } from '@n8n/di'; +import { ConflictError, UnprocessableRequestError } from '@n8n/errors'; + +import { ActiveWorkflowManager } from '@/active-workflow-manager'; +import { CredentialTypes } from '@/credential-types'; +import { + affixRoleToSaveCredential, + saveCredential, + shareCredentialWithProjects, +} from '@test-integration/db/credentials'; +import { createCustomRoleWithScopeSlugs } from '@test-integration/db/roles'; +import { createMember, createOwner } from '@test-integration/db/users'; +import { LicenseMocker } from '@test-integration/license'; +import { initNodeTypes } from '@test-integration/utils'; + +import { N8nPackagesService } from '../n8n-packages.service'; +import { importPackageRequest } from './fixtures/import-request'; +import { + buildEntityPackageBuffer, + buildImportPackageBuffer, + credentialRequirementsFromWorkflows, + githubCredentialPayload, + serializedCredential, + serializedProject, + serializedWorkflowWithCredential, +} from './fixtures/package-fixtures'; +import type { BlockingIssue, ImportPackageRequest } from '../n8n-packages.types'; +import type { SerializedCredential } from '../spec/serialized/credential.schema'; + +const EXPRESSION = '={{ $vars.githubToken }}'; +const OTHER_EXPRESSION = '={{ $vars.otherToken }}'; + +const licenseMocker = new LicenseMocker(); +const saveOwnedCredential = affixRoleToSaveCredential('credential:owner'); + +mockInstance(ActiveWorkflowManager); + +async function importPackage( + params: Pick & Partial, +) { + return await Container.get(N8nPackagesService).importPackage(importPackageRequest(params)); +} + +/** A workflow package with one workflow that uses `credential`, and the credential file. */ +async function workflowPackage( + credential: CredentialsEntity, + file: Omit | 'no-file', +): Promise { + return await buildImportPackageBuffer( + [ + serializedWorkflowWithCredential({ + id: 'wf-source', + name: 'Uses credential', + credentialId: credential.id, + credentialName: credential.name, + }), + ], + file === 'no-file' + ? {} + : { credentials: [serializedCredential({ id: credential.id, ...file })] }, + ); +} + +async function blockingIssuesOf( + promise: Promise, + errorClass: typeof ConflictError | typeof UnprocessableRequestError = ConflictError, +): Promise { + const error = await promise.then( + () => undefined, + (e: unknown) => e, + ); + const issues = (error as ConflictError).meta?.issues as BlockingIssue[]; + expect(error, JSON.stringify(issues)).toBeInstanceOf(errorClass); + return issues; +} + +/** Proves the import wrote nothing and left the credential row as it was. */ +async function expectNothingWritten(credential: CredentialsEntity) { + expect(await Container.get(WorkflowRepository).count()).toBe(0); + expect(await Container.get(FolderRepository).count()).toBe(0); + expect(await Container.get(TagRepository).count()).toBe(0); + const stored = await Container.get(CredentialsRepository).findOneByOrFail({ id: credential.id }); + expect(stored.name).toBe(credential.name); + expect(stored.data).toBe(credential.data); +} + +let owner: User; +let project: Project; + +beforeAll(async () => { + await testModules.loadModules(['n8n-packages']); + await testDb.init(); + await initNodeTypes(); + licenseMocker.mockLicenseState(Container.get(LicenseState)); + licenseMocker.setDefaults({ + features: ['feat:projectRole:admin', 'feat:folders'], + quotas: { 'quota:maxTeamProjects': 100 }, + }); + mockInstance(CredentialTypes).recognizes.mockReturnValue(true); +}); + +beforeEach(async () => { + await testDb.truncate([ + 'WorkflowEntity', + 'WorkflowHistory', + 'SharedWorkflow', + 'Folder', + 'TagEntity', + 'Project', + 'ProjectRelation', + 'CredentialsEntity', + 'SharedCredentials', + 'User', + ]); + owner = await createOwner(); + project = await createTeamProject('Target', owner); +}); + +afterAll(async () => { + await testDb.terminate(); +}); + +describe('credentialConflictPolicy', () => { + it('keep-existing (default) imports a differing match and leaves the credential as it is', async () => { + const credential = await saveOwnedCredential( + githubCredentialPayload({ name: 'GitHub', data: { accessToken: 'stored-secret' } }), + { project }, + ); + + await importPackage({ + user: owner, + projectId: project.id, + packageBuffer: await workflowPackage(credential, { + name: 'Renamed', + data: { accessToken: EXPRESSION }, + }), + }); + + expect(await Container.get(WorkflowRepository).count()).toBe(1); + const stored = await Container.get(CredentialsRepository).findOneByOrFail({ + id: credential.id, + }); + expect(stored.name).toBe('GitHub'); + expect(stored.data).toBe(credential.data); + }); + + it('fail blocks a rename and writes nothing', async () => { + const credential = await saveOwnedCredential( + githubCredentialPayload({ name: 'GitHub', data: { accessToken: EXPRESSION } }), + { project }, + ); + + const issues = await blockingIssuesOf( + importPackage({ + user: owner, + projectId: project.id, + credentialConflictPolicy: 'fail', + packageBuffer: await workflowPackage(credential, { + name: 'Renamed', + data: { accessToken: EXPRESSION }, + }), + }), + ); + + expect(issues).toEqual([ + { + type: 'credential-conflict', + kind: 'differs', + targetId: credential.id, + sourceIds: [credential.id], + name: 'GitHub', + usedBy: [{ kind: 'workflow', id: 'wf-source' }], + }, + ]); + await expectNothingWritten(credential); + }); + + it('fail blocks an expression change', async () => { + const credential = await saveOwnedCredential( + githubCredentialPayload({ name: 'GitHub', data: { accessToken: 'stored-secret' } }), + { project }, + ); + + const issues = await blockingIssuesOf( + importPackage({ + user: owner, + projectId: project.id, + credentialConflictPolicy: 'fail', + packageBuffer: await workflowPackage(credential, { + name: 'GitHub', + data: { accessToken: EXPRESSION }, + }), + }), + ); + + expect(issues).toEqual([ + expect.objectContaining({ type: 'credential-conflict', kind: 'differs' }), + ]); + await expectNothingWritten(credential); + }); + + it('fail imports an identical package', async () => { + const credential = await saveOwnedCredential( + githubCredentialPayload({ + name: 'GitHub', + data: { accessToken: EXPRESSION, clientSecret: 'stored-secret' }, + }), + { project }, + ); + + const result = await importPackage({ + user: owner, + projectId: project.id, + credentialConflictPolicy: 'fail', + packageBuffer: await workflowPackage(credential, { + name: 'GitHub', + data: { accessToken: EXPRESSION }, + }), + }); + + expect(result.bindings.credentials).toEqual({ [credential.id]: credential.id }); + }); + + it('fail imports a match without a credential file', async () => { + const credential = await saveOwnedCredential(githubCredentialPayload({ name: 'GitHub' }), { + project, + }); + + const result = await importPackage({ + user: owner, + projectId: project.id, + credentialConflictPolicy: 'fail', + packageBuffer: await workflowPackage(credential, 'no-file'), + }); + + expect(result.bindings.credentials).toEqual({ [credential.id]: credential.id }); + }); + + it('fail only binds a credential owned by a project outside the import', async () => { + const otherProject = await createTeamProject('Other', owner); + const credential = await saveOwnedCredential(githubCredentialPayload({ name: 'GitHub' }), { + project: otherProject, + }); + await shareCredentialWithProjects(credential, [project]); + + const result = await importPackage({ + user: owner, + projectId: project.id, + credentialConflictPolicy: 'fail', + packageBuffer: await workflowPackage(credential, { + name: 'Renamed', + data: { accessToken: EXPRESSION }, + }), + }); + + expect(result.bindings.credentials).toEqual({ [credential.id]: credential.id }); + }); + + it('fail only binds a global credential owned outside the import', async () => { + const credential = await saveCredential( + githubCredentialPayload({ name: 'Global GitHub', isGlobal: true }), + { user: owner, role: 'credential:owner' }, + ); + + const result = await importPackage({ + user: owner, + projectId: project.id, + credentialConflictPolicy: 'fail', + packageBuffer: await workflowPackage(credential, { name: 'Renamed' }), + }); + + expect(result.bindings.credentials).toEqual({ [credential.id]: credential.id }); + }); + + it('overwrite only binds a global credential that a project admin cannot update', async () => { + const member = await createMember(); + await linkUserToProject(member, project, 'project:admin'); + const credential = await saveCredential( + githubCredentialPayload({ name: 'Global GitHub', isGlobal: true }), + { user: owner, role: 'credential:owner' }, + ); + + const result = await importPackage({ + user: member, + projectId: project.id, + credentialConflictPolicy: 'overwrite', + packageBuffer: await workflowPackage(credential, { + name: 'Renamed', + data: { accessToken: EXPRESSION }, + }), + }); + + expect(result.bindings.credentials).toEqual({ [credential.id]: credential.id }); + const stored = await Container.get(CredentialsRepository).findOneByOrFail({ + id: credential.id, + }); + expect(stored.name).toBe('Global GitHub'); + expect(stored.data).toBe(credential.data); + }); + + it('fail blocks a global credential owned by the import project', async () => { + const credential = await saveOwnedCredential( + githubCredentialPayload({ name: 'Global GitHub', isGlobal: true }), + { project }, + ); + + const issues = await blockingIssuesOf( + importPackage({ + user: owner, + projectId: project.id, + credentialConflictPolicy: 'fail', + packageBuffer: await workflowPackage(credential, { name: 'Renamed' }), + }), + ); + + expect(issues).toEqual([ + expect.objectContaining({ + type: 'credential-conflict', + kind: 'differs', + targetId: credential.id, + }), + ]); + await expectNothingWritten(credential); + }); + + describe('credential in scope that the importing user cannot update', () => { + let member: User; + let credential: CredentialsEntity; + + beforeEach(async () => { + member = await createMember(); + // Project editors and admins always hold `credential:update`: only a custom role lacks it. + const role = await createCustomRoleWithScopeSlugs( + [ + 'project:read', + 'project:list', + 'workflow:create', + 'workflow:read', + 'workflow:update', + 'workflow:import', + 'workflow:list', + 'credential:read', + 'credential:list', + ], + { roleType: 'project' }, + ); + await linkUserToProject(member, project, role.slug); + credential = await saveOwnedCredential(githubCredentialPayload({ name: 'GitHub' }), { + project, + }); + }); + + it('fail blocks it and writes nothing', async () => { + const issues = await blockingIssuesOf( + importPackage({ + user: member, + projectId: project.id, + credentialConflictPolicy: 'fail', + packageBuffer: await workflowPackage(credential, { + name: 'Renamed', + data: { accessToken: EXPRESSION }, + }), + }), + UnprocessableRequestError, + ); + + expect(issues).toEqual([ + { + type: 'credential-update-forbidden', + targetId: credential.id, + sourceIds: [credential.id], + name: 'GitHub', + usedBy: [{ kind: 'workflow', id: 'wf-source' }], + }, + ]); + await expectNothingWritten(credential); + }); + + it('overwrite blocks it also when the package would not change it', async () => { + const issues = await blockingIssuesOf( + importPackage({ + user: member, + projectId: project.id, + credentialConflictPolicy: 'overwrite', + packageBuffer: await workflowPackage(credential, { name: 'GitHub' }), + }), + UnprocessableRequestError, + ); + + expect(issues).toEqual([ + expect.objectContaining({ + type: 'credential-update-forbidden', + targetId: credential.id, + }), + ]); + await expectNothingWritten(credential); + }); + + it('keep-existing binds it', async () => { + const result = await importPackage({ + user: member, + projectId: project.id, + credentialConflictPolicy: 'keep-existing', + packageBuffer: await workflowPackage(credential, { name: 'Renamed' }), + }); + + expect(result.bindings.credentials).toEqual({ [credential.id]: credential.id }); + }); + }); + + it('fail only binds a managed credential', async () => { + const credential = await saveOwnedCredential( + githubCredentialPayload({ name: 'Managed GitHub', isManaged: true }), + { project }, + ); + + const result = await importPackage({ + user: owner, + projectId: project.id, + credentialConflictPolicy: 'fail', + packageBuffer: await workflowPackage(credential, { name: 'Renamed' }), + }); + + expect(result.bindings.credentials).toEqual({ [credential.id]: credential.id }); + }); + + it('fail only binds a resolvable credential', async () => { + const credential = await saveOwnedCredential( + githubCredentialPayload({ name: 'Resolvable GitHub', isResolvable: true }), + { project }, + ); + + const result = await importPackage({ + user: owner, + projectId: project.id, + credentialConflictPolicy: 'fail', + packageBuffer: await workflowPackage(credential, { name: 'Renamed' }), + }); + + expect(result.bindings.credentials).toEqual({ [credential.id]: credential.id }); + }); + + it('overwrite blocks two package credentials with different payloads for one destination', async () => { + const credential = await saveOwnedCredential(githubCredentialPayload({ name: 'GitHub' }), { + project, + }); + + const issues = await blockingIssuesOf( + importPackage({ + user: owner, + projectId: project.id, + credentialConflictPolicy: 'overwrite', + bindings: { + credentials: new Map([ + ['source-a', credential.id], + ['source-b', credential.id], + ]), + }, + packageBuffer: await buildImportPackageBuffer( + [ + serializedWorkflowWithCredential({ + id: 'wf-a', + name: 'Uses A', + credentialId: 'source-a', + credentialName: 'A', + }), + serializedWorkflowWithCredential({ + id: 'wf-b', + name: 'Uses B', + credentialId: 'source-b', + credentialName: 'B', + }), + ], + { + credentials: [ + serializedCredential({ + id: 'source-a', + name: 'A', + data: { accessToken: EXPRESSION }, + }), + serializedCredential({ + id: 'source-b', + name: 'B', + data: { accessToken: OTHER_EXPRESSION }, + }), + ], + }, + ), + }), + ); + + expect(issues).toEqual([ + { + type: 'credential-conflict', + kind: 'divergent', + targetId: credential.id, + sourceIds: ['source-a', 'source-b'], + name: 'GitHub', + usedBy: [ + { kind: 'workflow', id: 'wf-a' }, + { kind: 'workflow', id: 'wf-b' }, + ], + }, + ]); + await expectNothingWritten(credential); + }); + + it('fail blocks a credential owned by another project of a project package', async () => { + const secondProject = await createTeamProject('Second', owner); + const credential = await saveOwnedCredential(githubCredentialPayload({ name: 'GitHub' }), { + project: secondProject, + }); + await shareCredentialWithProjects(credential, [project]); + const workflow = serializedWorkflowWithCredential({ + id: 'wf-source', + name: 'Uses credential', + credentialId: credential.id, + credentialName: credential.name, + }); + + const issues = await blockingIssuesOf( + importPackage({ + user: owner, + credentialConflictPolicy: 'fail', + packageBuffer: await buildEntityPackageBuffer({ + projects: [ + { + target: 'projects/target', + project: serializedProject({ id: project.id, name: project.name }), + }, + { + target: 'projects/second', + project: serializedProject({ id: secondProject.id, name: secondProject.name }), + }, + ], + workflows: [{ target: 'projects/target/workflows/wf', workflow }], + credentials: [ + { + target: 'projects/second/credentials/github', + credential: serializedCredential({ id: credential.id, name: 'Renamed' }), + }, + ], + manifestExtras: { + requirements: { credentials: credentialRequirementsFromWorkflows([workflow]) }, + }, + }), + }), + ); + + expect(issues).toEqual([ + expect.objectContaining({ + type: 'credential-conflict', + kind: 'differs', + targetId: credential.id, + }), + ]); + await expectNothingWritten(credential); + }); +}); diff --git a/packages/cli/src/modules/n8n-packages/__tests__/import-package.integration.test.ts b/packages/cli/src/modules/n8n-packages/__tests__/import-package.integration.test.ts index c7b57bd6045..5158d4ab5ea 100644 --- a/packages/cli/src/modules/n8n-packages/__tests__/import-package.integration.test.ts +++ b/packages/cli/src/modules/n8n-packages/__tests__/import-package.integration.test.ts @@ -17,8 +17,10 @@ import { WorkflowHistoryRepository, WorkflowRepository, CredentialsRepository, + SecretsProviderConnectionRepository, } from '@n8n/db'; import { Container } from '@n8n/di'; +import { Credentials } from 'n8n-core'; import { ActiveWorkflowManager } from '@/active-workflow-manager'; import { CredentialTypes } from '@/credential-types'; @@ -140,6 +142,7 @@ beforeEach(async () => { 'Project', 'CredentialsEntity', 'SharedCredentials', + 'SecretsProviderConnection', ]); }); @@ -2215,7 +2218,7 @@ describe('credential-missing-mode: create-stub', () => { ), }); - expect(result.credentials).toEqual({ matched: [], stubbed: ['missing-cred'] }); + expect(result.credentials).toEqual({ matched: [], stubbed: ['missing-cred'], seeded: [] }); expect(result.bindings.credentials['missing-cred']).toBe('missing-cred'); const workflow = await Container.get(WorkflowRepository).findOneOrFail({ @@ -2374,6 +2377,199 @@ describe('credential-missing-mode: create-stub', () => { }); }); +describe('credential-missing-mode: create-with-values', () => { + const sourceId = 'create-with-values-test'; + beforeEach(async () => { + await Container.get(SecretsProviderConnectionRepository).save({ + providerKey: 'github', + type: 'dummy', + encryptedSettings: '{}', + }); + }); + + const scheduleTriggerNodes = () => [ + { + id: 'schedule-trigger', + name: 'Schedule Trigger', + type: 'n8n-nodes-base.scheduleTrigger', + typeVersion: 1, + position: [0, 0] as [number, number], + parameters: {}, + }, + ]; + const credentialNode = (credentialId: string, credentialName: string) => ({ + id: 'http-node', + name: 'HTTP Request', + type: 'n8n-nodes-base.httpRequest', + typeVersion: 1, + position: [300, 0] as [number, number], + parameters: {}, + credentials: { + [PACKAGE_GITHUB_CREDENTIAL_TYPE]: { id: credentialId, name: credentialName }, + }, + }); + + it('creates credentials seeded with the package expression data', async () => { + const owner = await createOwner(); + + const result = await importPackage({ + user: owner, + credentialMissingMode: 'create-with-values', + packageBuffer: await buildImportPackageBuffer( + [ + serializedWorkflowWithCredential({ + id: 'wf-seeded', + name: 'Seeded cred workflow', + credentialId: 'missing-cred', + credentialName: 'Missing GitHub', + }), + ], + { + sourceId, + credentials: [ + { + id: 'missing-cred', + name: 'Missing GitHub', + type: PACKAGE_GITHUB_CREDENTIAL_TYPE, + data: { accessToken: '={{ $secrets.github.token }}' }, + }, + ], + }, + ), + }); + + expect(result.credentials).toEqual({ matched: [], stubbed: [], seeded: ['missing-cred'] }); + + const targetId = result.bindings.credentials['missing-cred']; + const stored = await Container.get(CredentialsRepository).findOneByOrFail({ id: targetId }); + const decrypted = await new Credentials( + { id: stored.id, name: stored.name }, + stored.type, + stored.data, + ).getData(); + expect(decrypted).toEqual({ accessToken: '={{ $secrets.github.token }}' }); + }); + + it('rejects seeded external-secret data when the user lacks externalSecret:list', async () => { + const member = await createMember(); + + await expect( + importPackage({ + user: member, + credentialMissingMode: 'create-with-values', + packageBuffer: await buildImportPackageBuffer( + [ + serializedWorkflowWithCredential({ + id: 'wf-seeded', + name: 'Seeded cred workflow', + credentialId: 'missing-cred', + credentialName: 'Missing GitHub', + }), + ], + { + sourceId, + credentials: [ + { + id: 'missing-cred', + name: 'Missing GitHub', + type: PACKAGE_GITHUB_CREDENTIAL_TYPE, + data: { accessToken: '={{ $secrets.github.token }}' }, + }, + ], + }, + ), + }), + ).rejects.toThrow('Lacking permissions to reference external secrets in credentials'); + }); + + it('publishes workflows with seeded credentials but blocks those with fallback stubs', async () => { + const owner = await createOwner(); + + const result = await importPackage({ + user: owner, + credentialMissingMode: 'create-with-values', + workflowPublishingPolicy: WorkflowPublishingPolicy.PublishAll, + packageBuffer: await buildImportPackageBuffer( + [ + serializedWorkflow({ + id: 'wf-seeded', + name: 'Seeded', + publishedVersionId: WIRE_VERSION_ID, + nodes: [...scheduleTriggerNodes(), credentialNode('seeded-cred', 'Seeded GitHub')], + }), + serializedWorkflow({ + id: 'wf-stubbed', + name: 'Stubbed', + publishedVersionId: WIRE_VERSION_ID, + nodes: [ + ...scheduleTriggerNodes(), + { ...credentialNode('bare-cred', 'Bare GitHub'), id: 'http-node-2' }, + ], + }), + ], + { + sourceId, + credentials: [ + { + id: 'seeded-cred', + name: 'Seeded GitHub', + type: PACKAGE_GITHUB_CREDENTIAL_TYPE, + data: { accessToken: '={{ $secrets.github.token }}' }, + dataIsComplete: true, + }, + ], + }, + ), + }); + + expect(result.credentials.seeded).toEqual(['seeded-cred']); + expect(result.credentials.stubbed).toEqual(['bare-cred']); + + const seeded = result.workflows.find( + ({ sourceWorkflowId }) => sourceWorkflowId === 'wf-seeded', + ); + const stubbed = result.workflows.find( + ({ sourceWorkflowId }) => sourceWorkflowId === 'wf-stubbed', + ); + expect(seeded?.publishing).toEqual({ state: 'published' }); + expect(stubbed?.publishing).toEqual({ state: 'blocked', blockedReason: 'stub-credential' }); + }); + + it('rejects a package whose bundled credential data carries literal values', async () => { + const owner = await createOwner(); + + await expect( + importPackage({ + user: owner, + credentialMissingMode: 'create-with-values', + packageBuffer: await buildImportPackageBuffer( + [ + serializedWorkflowWithCredential({ + id: 'wf-leak', + name: 'Leaky workflow', + credentialId: 'leaky-cred', + credentialName: 'Leaky GitHub', + }), + ], + { + sourceId, + credentials: [ + { + id: 'leaky-cred', + name: 'Leaky GitHub', + type: PACKAGE_GITHUB_CREDENTIAL_TYPE, + data: { accessToken: 'ghp_literal_secret' }, + }, + ], + }, + ), + }), + ).rejects.toThrow('failed schema validation'); + + expect(await Container.get(CredentialsRepository).count()).toBe(0); + }); +}); + describe('Package import workflow publishing policy', () => { // Trigger needed to be able to publish workflows const scheduleTriggerNodes = () => [ diff --git a/packages/cli/src/modules/n8n-packages/__tests__/import-workflow-with-variables.integration.test.ts b/packages/cli/src/modules/n8n-packages/__tests__/import-workflow-with-variables.integration.test.ts index 6f5c6bb8feb..f4d06517c1d 100644 --- a/packages/cli/src/modules/n8n-packages/__tests__/import-workflow-with-variables.integration.test.ts +++ b/packages/cli/src/modules/n8n-packages/__tests__/import-workflow-with-variables.integration.test.ts @@ -121,6 +121,8 @@ describe('variable error consumers', () => { requirements: [], matchingMode: 'id-only', missingMode: 'must-preexist', + conflictPolicy: 'keep-existing', + updateScope: { projectIds: new Set([project.id]) }, }, dataTableRequest: { requirements: [], diff --git a/packages/cli/src/modules/n8n-packages/engine/__tests__/credential-save-policy.test.ts b/packages/cli/src/modules/n8n-packages/engine/__tests__/credential-save-policy.test.ts index 1ded4e6d87c..9e77936b7ed 100644 --- a/packages/cli/src/modules/n8n-packages/engine/__tests__/credential-save-policy.test.ts +++ b/packages/cli/src/modules/n8n-packages/engine/__tests__/credential-save-policy.test.ts @@ -49,6 +49,8 @@ const request = ( requirements, matchingMode: 'id-only', missingMode, + conflictPolicy: 'keep-existing', + updateScope: { projectIds: new Set() }, }); const resolution = (...failures: CredentialResolutionFailure[]): CredentialResolution => ({ diff --git a/packages/cli/src/modules/n8n-packages/engine/__tests__/import-blocked.error.test.ts b/packages/cli/src/modules/n8n-packages/engine/__tests__/import-blocked.error.test.ts index a86ad812809..0379789b2cb 100644 --- a/packages/cli/src/modules/n8n-packages/engine/__tests__/import-blocked.error.test.ts +++ b/packages/cli/src/modules/n8n-packages/engine/__tests__/import-blocked.error.test.ts @@ -61,7 +61,24 @@ const tagUnresolved = ( usedBy: [{ kind: 'workflow', id: 'w1' }], }); +const credentialConflict = (kind: 'differs' | 'divergent'): BlockingIssue => ({ + type: 'credential-conflict', + kind, + targetId: 'c1', + sourceIds: ['s1'], + name: 'GitHub', + usedBy: [{ kind: 'workflow', id: 'w1' }], +}); + describe('toImportBlockedError', () => { + it.each(['differs', 'divergent'] as const)( + 'maps a %s credential-conflict to 409 Conflict', + (kind) => { + const error = toImportBlockedError([credentialConflict(kind), credentialUnresolved]); + expect(error).toBeInstanceOf(ConflictError); + }, + ); + it('maps a folder-conflict to 409 Conflict', () => { const error = toImportBlockedError([folderConflict]); expect(error).toBeInstanceOf(ConflictError); @@ -87,6 +104,19 @@ describe('toImportBlockedError', () => { expect(error).toBeInstanceOf(UnprocessableRequestError); }); + it('maps a credential-update-forbidden to 422', () => { + const error = toImportBlockedError([ + { + type: 'credential-update-forbidden', + targetId: 'c1', + sourceIds: ['s1'], + name: 'GitHub', + usedBy: [{ kind: 'workflow', id: 'w1' }], + }, + ]); + expect(error).toBeInstanceOf(UnprocessableRequestError); + }); + it('maps variable-only blocks to 422', () => { const error = toImportBlockedError([variableUnresolved]); expect(error).toBeInstanceOf(UnprocessableRequestError); diff --git a/packages/cli/src/modules/n8n-packages/engine/__tests__/import-telemetry.test.ts b/packages/cli/src/modules/n8n-packages/engine/__tests__/import-telemetry.test.ts index a7adb357129..2ad1cd62596 100644 --- a/packages/cli/src/modules/n8n-packages/engine/__tests__/import-telemetry.test.ts +++ b/packages/cli/src/modules/n8n-packages/engine/__tests__/import-telemetry.test.ts @@ -145,6 +145,8 @@ const scope = (input: { matchingMode: 'id-only', missingMode: 'create-stub', credentialBindings: undefined, + conflictPolicy: 'overwrite', + updateScope: { projectIds: new Set([context.projectId]) }, }, dataTableRequest: mock({ requirements: dt.requirements === 0 ? undefined : new Array(dt.requirements), @@ -172,6 +174,7 @@ const request = mock({ workflowIdPolicy: 'new', credentialMatchingMode: 'id-only', credentialMissingMode: 'create-stub', + credentialConflictPolicy: 'overwrite', workflowPublishingPolicy: 'preserve-published-state', folderConflictPolicy: 'overwrite', variableMissingMode: 'create-stub', @@ -209,6 +212,7 @@ describe('emitPackageImportedEvent', () => { bindings: new Map([['credA', 'target-a']]), matched: ['credA'], stubbed: [], + seeded: [], }, requirements: [requirement('credA')], dataTable: { matched: 1, created: 0, updated: 1, requirements: 2 }, @@ -219,11 +223,15 @@ describe('emitPackageImportedEvent', () => { projectId: 'P2', outcomes: [outcome('wf3', 'WF3', 'updated')], credentialResult: { - bindings: new Map([['credB', 'stub-b']]), + bindings: new Map([ + ['credB', 'stub-b'], + ['credC', 'seed-c'], + ]), matched: [], stubbed: ['credB'], + seeded: ['credC'], }, - requirements: [requirement('credB')], + requirements: [requirement('credB'), requirement('credC')], dataTable: { matched: 0, created: 2, requirements: 2 }, variables: { matched: 0, @@ -252,15 +260,16 @@ describe('emitPackageImportedEvent', () => { // A multi-scope import has no single folder to attribute the event to. expect(payload.folderId).toBeNull(); // Credential ids are resolved through each scope's binding map (source id -> target id). + // Seeded credentials count as created alongside stubs. expect(payload.credentialIds).toEqual({ matched: ['target-a'], - created: ['stub-b'], + created: ['stub-b', 'seed-c'], updated: [], }); expect(payload.counts).toEqual({ workflows: { created: 1, updated: 1, skipped: 1, archived: 0, deleted: 0 }, folders: { removed: 0 }, - credentials: { matched: 1, created: 1, requirements: 2 }, + credentials: { matched: 1, created: 2, requirements: 3 }, dataTables: { matched: 1, created: 2, updated: 1, requirements: 4 }, // scope 2's two missing requirements were created, so post-apply missing is 0; its // overwritten name matched first but is counted as updated, not matched. @@ -269,6 +278,7 @@ describe('emitPackageImportedEvent', () => { tags: { matched: 1, created: 1, renamed: 1, reconciled: 1, skipped: 1, requirements: 5 }, }); expect(payload.packageSourceId).toBe('src-1'); + expect(payload.options.credentialConflictPolicy).toBe('overwrite'); expect(payload.options.variableMissingMode).toBe('create-stub'); expect(payload.options.variableConflictPolicy).toBe('overwrite'); expect(payload.options.variableParentPolicy).toBe('global'); @@ -286,7 +296,7 @@ describe('emitPackageImportedEvent', () => { scope({ projectId: 'P1', outcomes: [outcome('wf1', 'WF1', 'created')], - credentialResult: { bindings: new Map(), matched: [], stubbed: [] }, + credentialResult: { bindings: new Map(), matched: [], stubbed: [], seeded: [] }, // Of three missing requirements, one was created with a value and one already existed. variables: { matched: 0, missing: 3, requirements: 3, createdWithValue: 1, existing: 1 }, }), @@ -317,13 +327,13 @@ describe('emitPackageImportedEvent', () => { scope({ projectId: 'P1', outcomes: [outcome('wf1', 'WF1', 'created')], - credentialResult: { bindings: new Map(), matched: [], stubbed: [] }, + credentialResult: { bindings: new Map(), matched: [], stubbed: [], seeded: [] }, variables: { matched: 0, missing: 1, requirements: 1, createdWithValue: 1 }, }), scope({ projectId: 'P2', outcomes: [outcome('wf2', 'WF2', 'created')], - credentialResult: { bindings: new Map(), matched: [], stubbed: [] }, + credentialResult: { bindings: new Map(), matched: [], stubbed: [], seeded: [] }, variables: { matched: 0, missing: 1, requirements: 1, existing: 1 }, }), ], @@ -361,7 +371,7 @@ describe('emitPackageImportedEvent', () => { removedFolders: [ { folderId: 'F-stale', name: 'stale', projectId: 'P1', parentFolderId: null }, ], - credentialResult: { bindings: new Map(), matched: [], stubbed: [] }, + credentialResult: { bindings: new Map(), matched: [], stubbed: [], seeded: [] }, }), ], }); @@ -390,7 +400,7 @@ describe('emitPackageImportedEvent', () => { projectId: 'P1', folderId: 'F1', outcomes: [outcome('wf1', 'WF1', 'created')], - credentialResult: { bindings: new Map(), matched: [], stubbed: [] }, + credentialResult: { bindings: new Map(), matched: [], stubbed: [], seeded: [] }, }), ], }); diff --git a/packages/cli/src/modules/n8n-packages/engine/__tests__/n8n-package-parser.agent.test.ts b/packages/cli/src/modules/n8n-packages/engine/__tests__/n8n-package-parser.agent.test.ts index 1614d5e9372..44a053f2a6e 100644 --- a/packages/cli/src/modules/n8n-packages/engine/__tests__/n8n-package-parser.agent.test.ts +++ b/packages/cli/src/modules/n8n-packages/engine/__tests__/n8n-package-parser.agent.test.ts @@ -88,7 +88,7 @@ describe('N8nPackageParser.getAgents', () => { const expected = input.files[`${target}/agent.json`] as SerializedAgent; expect(parsed.config).toMatchObject({ model: '', - skills: [{ id: 'shared-skill', enabled: false }], + skills: [{ id: 'shared-skill' }], tools: [{ id: 'shared_tool', enabled: false, requireApproval: true }], tasks: [{ id: `${parsed.sourceAgentId}_task`, enabled: false }], mcpServers: [{ name: 'Reference', url: '' }], diff --git a/packages/cli/src/modules/n8n-packages/engine/__tests__/n8n-package-parser.credentials.test.ts b/packages/cli/src/modules/n8n-packages/engine/__tests__/n8n-package-parser.credentials.test.ts new file mode 100644 index 00000000000..a2861a308fc --- /dev/null +++ b/packages/cli/src/modules/n8n-packages/engine/__tests__/n8n-package-parser.credentials.test.ts @@ -0,0 +1,271 @@ +import type { Logger } from '@n8n/backend-common'; +import { UserError } from 'n8n-workflow'; +import { mock } from 'vitest-mock-extended'; + +import type { NodeTypes } from '@/node-types'; + +import type { WorkflowSerializer } from '../../entities/workflow/workflow.serializer'; +import type { PackageReader } from '../../io/package-reader'; +import { FORMAT_VERSION } from '../../spec/constants'; +import type { ManifestEntry, PackageManifest } from '../../spec/manifest.schema'; +import { N8nPackageParser } from '../n8n-package-parser'; + +function makeReader(manifest: PackageManifest, files: Record): PackageReader { + return { + readManifest: async () => await Promise.resolve(manifest), + readFile: async (path: string) => { + if (!(path in files)) throw new Error(`missing file ${path}`); + const content = files[path]; + const raw = typeof content === 'string' ? content : JSON.stringify(content); + return await Promise.resolve(Buffer.from(raw, 'utf-8')); + }, + listEntries: async () => await Promise.resolve(Object.keys(files)), + }; +} + +function manifestWith(extras: Partial = {}): PackageManifest { + return { + packageFormatVersion: FORMAT_VERSION, + exportedAt: '2026-01-01T00:00:00.000Z', + sourceN8nVersion: '1.0.0', + sourceId: 'test-source', + ...extras, + } as PackageManifest; +} + +const EXPRESSION = '={{ $vars.githubToken }}'; + +const topLevelEntry: ManifestEntry = { + id: 'cred-1', + name: 'GitHub', + target: 'credentials/github-cred-1', +}; + +describe('N8nPackageParser.getCredentials', () => { + const parser = new N8nPackageParser( + mock(), + mock(), + mock(), + ); + + it('reads a credential file from the top-level credentials folder, keyed by id', async () => { + const credential = { + id: 'cred-1', + name: 'GitHub', + type: 'githubApi', + data: { accessToken: EXPRESSION }, + }; + const reader = makeReader(manifestWith({ credentials: [topLevelEntry] }), { + 'credentials/github-cred-1/credential.json': credential, + }); + + const credentials = await parser.getCredentials(reader); + + expect(credentials).toEqual(new Map([['cred-1', credential]])); + }); + + it('reads a credential file from the owner project folder', async () => { + const credential = { id: 'cred-2', name: 'Slack', type: 'slackApi' }; + const reader = makeReader( + manifestWith({ + projects: [{ id: 'proj-1', name: 'billing', target: 'projects/billing-proj-1' }], + credentials: [ + { + id: 'cred-2', + name: 'Slack', + target: 'projects/billing-proj-1/credentials/slack-cred-2', + }, + ], + }), + { 'projects/billing-proj-1/credentials/slack-cred-2/credential.json': credential }, + ); + + const credentials = await parser.getCredentials(reader); + + expect(credentials.get('cred-2')).toEqual(credential); + }); + + it('reads only the requested credential files', async () => { + const credential = { id: 'cred-1', name: 'GitHub', type: 'githubApi' }; + const reader = makeReader( + manifestWith({ + credentials: [ + topLevelEntry, + { id: 'cred-2', name: 'Slack', target: 'credentials/slack-cred-2' }, + ], + }), + { 'credentials/github-cred-1/credential.json': credential }, + ); + + const credentials = await parser.getCredentials(reader, new Set(['cred-1'])); + + expect(credentials).toEqual(new Map([['cred-1', credential]])); + }); + + it('reads a credential file without data (no-values export)', async () => { + const reader = makeReader(manifestWith({ credentials: [topLevelEntry] }), { + 'credentials/github-cred-1/credential.json': { + id: 'cred-1', + name: 'GitHub', + type: 'githubApi', + }, + }); + + const credentials = await parser.getCredentials(reader); + + expect(credentials.get('cred-1')).toEqual({ id: 'cred-1', name: 'GitHub', type: 'githubApi' }); + expect(credentials.get('cred-1')).not.toHaveProperty('data'); + }); + + it('returns an empty map when the manifest lists no credential files', async () => { + const reader = makeReader( + manifestWith({ + requirements: { + credentials: [ + { + id: 'cred-1', + name: 'GitHub', + type: 'githubApi', + usedBy: [{ kind: 'workflow', id: 'wf-1' }], + }, + ], + }, + }), + {}, + ); + + const credentials = await parser.getCredentials(reader); + + expect(credentials.size).toBe(0); + }); + + it('throws a UserError when a listed credential file is missing', async () => { + const reader = makeReader(manifestWith({ credentials: [topLevelEntry] }), {}); + + const error = await parser.getCredentials(reader).catch((e: unknown) => e); + + expect(error).toBeInstanceOf(UserError); + expect(error).toHaveProperty( + 'message', + 'Package manifest references a missing credential file at credentials/github-cred-1/credential.json.', + ); + }); + + it('throws a UserError when the credential file is not valid JSON', async () => { + const reader = makeReader(manifestWith({ credentials: [topLevelEntry] }), { + 'credentials/github-cred-1/credential.json': '{ not json', + }); + + const error = await parser.getCredentials(reader).catch((e: unknown) => e); + + expect(error).toBeInstanceOf(UserError); + expect(error).toHaveProperty( + 'message', + 'Package credential file at credentials/github-cred-1/credential.json is not valid JSON.', + ); + }); + + it('throws a UserError when a data value is not an expression', async () => { + const reader = makeReader(manifestWith({ credentials: [topLevelEntry] }), { + 'credentials/github-cred-1/credential.json': { + id: 'cred-1', + name: 'GitHub', + type: 'githubApi', + data: { accessToken: 'plain-secret' }, + }, + }); + + const error = await parser.getCredentials(reader).catch((e: unknown) => e); + + expect(error).toBeInstanceOf(UserError); + expect(error).toHaveProperty( + 'message', + 'Package credential file at credentials/github-cred-1/credential.json failed schema validation.', + ); + }); + + it('throws a UserError when the file id does not match the manifest id', async () => { + const reader = makeReader(manifestWith({ credentials: [topLevelEntry] }), { + 'credentials/github-cred-1/credential.json': { + id: 'cred-other', + name: 'GitHub', + type: 'githubApi', + }, + }); + + const error = await parser.getCredentials(reader).catch((e: unknown) => e); + + expect(error).toBeInstanceOf(UserError); + expect(error).toHaveProperty( + 'message', + 'Package credential at credentials/github-cred-1/credential.json declares id "cred-other" but the manifest lists it as "cred-1".', + ); + }); + + it('throws a UserError when the file name does not match the manifest name', async () => { + const reader = makeReader(manifestWith({ credentials: [topLevelEntry] }), { + 'credentials/github-cred-1/credential.json': { + id: 'cred-1', + name: 'Renamed', + type: 'githubApi', + }, + }); + + const error = await parser.getCredentials(reader).catch((e: unknown) => e); + + expect(error).toBeInstanceOf(UserError); + expect(error).toHaveProperty( + 'message', + 'Package credential at credentials/github-cred-1/credential.json declares name "Renamed" but the manifest lists it as "GitHub".', + ); + }); + it('throws a UserError when the file type does not match the requirement type', async () => { + const reader = makeReader( + manifestWith({ + credentials: [topLevelEntry], + requirements: { + credentials: [ + { + id: 'cred-1', + name: 'GitHub', + type: 'githubOAuth2Api', + usedBy: [{ kind: 'workflow', id: 'wf-1' }], + }, + ], + }, + }), + { + 'credentials/github-cred-1/credential.json': { + id: 'cred-1', + name: 'GitHub', + type: 'githubApi', + }, + }, + ); + + const error = await parser.getCredentials(reader).catch((e: unknown) => e); + + expect(error).toBeInstanceOf(UserError); + expect(error).toHaveProperty( + 'message', + 'Package credential at credentials/github-cred-1/credential.json declares type "githubApi" but the requirement lists it as "githubOAuth2Api".', + ); + }); + + it('accepts a credential file whose requirement has no type', async () => { + const credential = { id: 'cred-1', name: 'GitHub', type: 'githubApi' }; + const reader = makeReader( + manifestWith({ + credentials: [topLevelEntry], + requirements: { + credentials: [{ id: 'cred-1', usedBy: [{ kind: 'agent', id: 'agent-1' }] }], + }, + }), + { 'credentials/github-cred-1/credential.json': credential }, + ); + + const credentials = await parser.getCredentials(reader); + + expect(credentials.get('cred-1')).toEqual(credential); + }); +}); diff --git a/packages/cli/src/modules/n8n-packages/engine/__tests__/package-layout.test.ts b/packages/cli/src/modules/n8n-packages/engine/__tests__/package-layout.test.ts index fbf9e19d41c..3d2d034778e 100644 --- a/packages/cli/src/modules/n8n-packages/engine/__tests__/package-layout.test.ts +++ b/packages/cli/src/modules/n8n-packages/engine/__tests__/package-layout.test.ts @@ -1,9 +1,13 @@ import type { ManifestEntry } from '../../spec/manifest.schema'; +import type { PackageCredentialRequirement } from '../../spec/requirements.schema'; +import type { SerializedCredential } from '../../spec/serialized/credential.schema'; import type { SerializedVariable } from '../../spec/serialized/variable.schema'; import { deriveParentFolderId, foldersInScope, + needsBundledCredentialData, placeByLayout, + placeCredentialData, workflowsInScope, } from '../package-layout'; @@ -57,6 +61,53 @@ describe('package-layout', () => { }); }); + describe('credential data placement', () => { + const requirement: PackageCredentialRequirement = { + id: 'cred-1', + name: 'GitHub', + type: 'githubApi', + usedBy: [{ kind: 'workflow', id: 'wf-1' }], + }; + const bundled = (data?: SerializedCredential['data']) => + new Map([ + ['cred-1', { id: 'cred-1', name: 'GitHub', type: 'githubApi', ...(data ? { data } : {}) }], + ]); + + it('attaches bundled data by id', () => { + const placed = placeCredentialData({ + requirements: [requirement], + bundledCredentials: bundled({ token: '={{ $secrets.gh }}' }), + }); + + expect(placed).toEqual([{ ...requirement, packageData: { token: '={{ $secrets.gh }}' } }]); + }); + + it('leaves the requirement bare when the bundle carries no data or no file', () => { + const noData = placeCredentialData({ + requirements: [requirement], + bundledCredentials: bundled(), + }); + const noFile = placeCredentialData({ + requirements: [requirement], + bundledCredentials: new Map(), + }); + + expect(noData).toEqual([requirement]); + expect(noFile).toEqual([requirement]); + }); + + it('needsBundledCredentialData only under create-with-values with requirements present', () => { + const request = (credentialMissingMode: 'create-stub' | 'create-with-values') => ({ + credentialMatchingMode: 'id-only' as const, + credentialMissingMode, + }); + + expect(needsBundledCredentialData(request('create-with-values'), true)).toBe(true); + expect(needsBundledCredentialData(request('create-with-values'), false)).toBe(false); + expect(needsBundledCredentialData(request('create-stub'), true)).toBe(false); + }); + }); + describe('variable placement', () => { const named = (name: string, target: string): ManifestEntry => ({ id: name, name, target }); const placedIn = ( diff --git a/packages/cli/src/modules/n8n-packages/engine/import-blocked.error.ts b/packages/cli/src/modules/n8n-packages/engine/import-blocked.error.ts index 17306f7193b..b644f68c035 100644 --- a/packages/cli/src/modules/n8n-packages/engine/import-blocked.error.ts +++ b/packages/cli/src/modules/n8n-packages/engine/import-blocked.error.ts @@ -20,6 +20,7 @@ export function toImportBlockedError( issue.type === 'project-conflict' || issue.type === 'folder-conflict' || issue.type === 'variable-conflict' || + issue.type === 'credential-conflict' || (issue.type === 'data-table-unresolved' && (issue.kind === 'id-conflict' || issue.kind === 'name-conflict')) || (issue.type === 'tag-unresolved' && diff --git a/packages/cli/src/modules/n8n-packages/engine/import-orchestrator.ts b/packages/cli/src/modules/n8n-packages/engine/import-orchestrator.ts index b1e9d9164cb..0d2f07fe78c 100644 --- a/packages/cli/src/modules/n8n-packages/engine/import-orchestrator.ts +++ b/packages/cli/src/modules/n8n-packages/engine/import-orchestrator.ts @@ -4,11 +4,16 @@ import { Service } from '@n8n/di'; import { NodeTypes } from '@/node-types'; import type { PolicyActor } from '@/policy/policy-enforcement-backend'; +import { + credentialConflicts, + forbiddenCredentialUpdates, +} from '../entities/credential/credential-conflict-policy'; import { CredentialImporter } from '../entities/credential/credential-importer'; import { workflowsBlockedFromPublish } from '../entities/credential/credential-missing-mode'; import type { CredentialApplyResult, CredentialBindingRequest, + CredentialImportPlan, CredentialResolution, CredentialResolutionFailure, } from '../entities/credential/credential.types'; @@ -119,7 +124,7 @@ export interface ImportContentResult { export interface ImportPlan { input: ImportOrchestrationInput; folderContext: FolderImportContext; - credentialPlan: CredentialResolution; + credentialPlan: CredentialImportPlan; workflowPlan: WorkflowImportPlan; folderPlan: FolderImportPlan; dataTablePlan: DataTableImportPlan; @@ -175,7 +180,12 @@ export class ImportOrchestrator { plans.map((plan) => plan.dataTablePlan), ); - for (const { input, variablePlan } of plans) { + for (const { input, variablePlan, credentialPlan } of plans) { + await this.credentialImporter.assertCanCreate( + input.context, + input.credentialRequest, + credentialPlan, + ); if (variablePlan.creations.length > 0) { await this.variableImporter.assertCanCreate( input.context, @@ -218,6 +228,21 @@ export class ImportOrchestrator { ); } + // Across scopes: one destination credential can be reached from several projects. + if (plans.length > 0) { + const credentialPlans = plans.map((plan) => plan.credentialPlan); + for (const forbidden of forbiddenCredentialUpdates(credentialPlans)) { + issues.push({ type: 'credential-update-forbidden', ...forbidden }); + } + const conflicts = credentialConflicts( + plans[0].input.credentialRequest.conflictPolicy, + credentialPlans, + ); + for (const conflict of conflicts) { + issues.push({ type: 'credential-conflict', ...conflict }); + } + } + const quotaFailure = await this.variableImporter.quotaFailure( plans.flatMap((plan) => plan.variablePlan.creations), ); @@ -385,7 +410,14 @@ export class ImportOrchestrator { const blockedFromPublish = new Map(); for (const sourceWorkflowId of workflowsBlockedFromPublish( credentialRequest.requirements, - new Set(credentialResult.stubbed), + new Set([ + ...credentialResult.stubbed, + ...credentialResult.seeded.filter( + (id) => + !credentialRequest.requirements?.find((requirement) => requirement.id === id) + ?.packageDataIsComplete, + ), + ]), )) { blockedFromPublish.set(sourceWorkflowId, 'stub-credential'); } diff --git a/packages/cli/src/modules/n8n-packages/engine/import-telemetry.ts b/packages/cli/src/modules/n8n-packages/engine/import-telemetry.ts index 9cafd2ea4c8..02769525c7d 100644 --- a/packages/cli/src/modules/n8n-packages/engine/import-telemetry.ts +++ b/packages/cli/src/modules/n8n-packages/engine/import-telemetry.ts @@ -1,5 +1,6 @@ import type { EventService } from '@n8n/backend-services'; +import { resolveCredentialConflictPolicy } from '../entities/credential/credential-conflict-policy'; import type { CredentialBindingRequest } from '../entities/credential/credential.types'; import type { DataTableImportRequest } from '../entities/data-table/data-table.types'; import type { TagImportPlan, TagImportRequest } from '../entities/tag/tag.types'; @@ -54,8 +55,8 @@ export function emitPackageImportedEvent( const matchedCredentialIds = credentialResults.flatMap(({ matched, bindings }) => matched.map((sourceId) => bindings.get(sourceId)!), ); - const createdCredentialIds = credentialResults.flatMap(({ stubbed, bindings }) => - stubbed.map((sourceId) => bindings.get(sourceId)!), + const createdCredentialIds = credentialResults.flatMap(({ stubbed, seeded, bindings }) => + [...stubbed, ...seeded].map((sourceId) => bindings.get(sourceId)!), ); const dataTablePlans = scopes.map(({ imported }) => imported.dataTablePlan); @@ -110,6 +111,7 @@ export function emitPackageImportedEvent( workflowIdPolicy: request.workflowIdPolicy, credentialMatchingMode: request.credentialMatchingMode, credentialMissingMode: request.credentialMissingMode, + credentialConflictPolicy: resolveCredentialConflictPolicy(request.credentialConflictPolicy), workflowPublishingPolicy: request.workflowPublishingPolicy, missingNodeTypeMode: request.missingNodeTypeMode, projectConflictPolicy: request.projectConflictPolicy, diff --git a/packages/cli/src/modules/n8n-packages/engine/n8n-package-parser.ts b/packages/cli/src/modules/n8n-packages/engine/n8n-package-parser.ts index fb40f50ebc5..623cc7c98e6 100644 --- a/packages/cli/src/modules/n8n-packages/engine/n8n-package-parser.ts +++ b/packages/cli/src/modules/n8n-packages/engine/n8n-package-parser.ts @@ -29,6 +29,10 @@ import { serializedAgentMetadataSchema, type SerializedAgent, } from '../spec/serialized/agent.schema'; +import { + serializedCredentialSchema, + type SerializedCredential, +} from '../spec/serialized/credential.schema'; import { serializedDataTableSchema } from '../spec/serialized/data-table.schema'; import type { SerializedDataTable } from '../spec/serialized/data-table.schema'; import { serializedFolderSchema, type SerializedFolder } from '../spec/serialized/folder.schema'; @@ -139,6 +143,33 @@ export class N8nPackageParser { return variables; } + /** + * Bundled credential files, keyed by credential id. A credential requirement + * without a file is valid: the exporting user could not read the credential. + */ + async getCredentials( + reader: PackageReader, + sourceIds?: ReadonlySet, + ): Promise> { + const manifest = await this.getManifest(reader); + const credentials = new Map(); + const requiredTypes = new Map( + (manifest.requirements?.credentials ?? []).map(({ id, type }) => [id, type]), + ); + + // The manifest target already points into the owner project folder or the + // top-level `credentials/` folder, so the import scope does not matter here. + for (const entry of manifest.credentials ?? []) { + if (sourceIds && !sourceIds.has(entry.id)) continue; + credentials.set( + entry.id, + await this.readCredential(reader, entry, requiredTypes.get(entry.id)), + ); + } + + return credentials; + } + private async readAgent(reader: PackageReader, entry: ManifestEntry): Promise { const path = entityFilePath('agents', entry.target); const agent = await this.readAgentFile(reader, path, serializedAgentSchema); @@ -415,6 +446,51 @@ export class N8nPackageParser { return variable; } + private async readCredential( + reader: PackageReader, + entry: ManifestEntry, + requiredType: string | undefined, + ): Promise { + const path = entityFilePath('credentials', entry.target); + const wire = await this.readJson(reader, path, 'credential'); + + let credential: SerializedCredential; + try { + credential = serializedCredentialSchema.parse(wire); + } catch (cause) { + if (cause instanceof ZodError) { + throw new UserError(`Package credential file at ${path} failed schema validation.`, { + cause, + }); + } + throw cause; + } + + // Requirements and bindings key off the manifest id, so a file with another + // identity would apply its data to the wrong credential. + if (credential.id !== entry.id) { + throw new UserError( + `Package credential at ${path} declares id "${credential.id}" but the manifest lists it as "${entry.id}".`, + ); + } + + if (credential.name !== entry.name) { + throw new UserError( + `Package credential at ${path} declares name "${credential.name}" but the manifest lists it as "${entry.name}".`, + ); + } + + // Matching binds a destination credential of the requirement type, so data of + // another type would merge into a credential with a different schema. + if (requiredType !== undefined && credential.type !== requiredType) { + throw new UserError( + `Package credential at ${path} declares type "${credential.type}" but the requirement lists it as "${requiredType}".`, + ); + } + + return credential; + } + private async readJson( reader: PackageReader, path: string, diff --git a/packages/cli/src/modules/n8n-packages/engine/package-layout.ts b/packages/cli/src/modules/n8n-packages/engine/package-layout.ts index 28ac4b2d6fa..b078a5fb067 100644 --- a/packages/cli/src/modules/n8n-packages/engine/package-layout.ts +++ b/packages/cli/src/modules/n8n-packages/engine/package-layout.ts @@ -1,11 +1,22 @@ import { UserError } from 'n8n-workflow'; +import { resolveCredentialConflictPolicy } from '../entities/credential/credential-conflict-policy'; +import { credentialMissingModeUsesPackageData } from '../entities/credential/credential-missing-mode'; +import type { PlacedCredentialRequirement } from '../entities/credential/credential.types'; import { variableMissingModeUsesPackageValue } from '../entities/variable/variable-missing-mode'; import type { PlacedVariableRequirement } from '../entities/variable/variable.types'; -import { VariableConflictPolicy, VariableParentPolicy } from '../n8n-packages.types'; -import type { ImportVariableProperties } from '../n8n-packages.types'; +import { + CredentialConflictPolicy, + VariableConflictPolicy, + VariableParentPolicy, +} from '../n8n-packages.types'; +import type { ImportCredentialProperties, ImportVariableProperties } from '../n8n-packages.types'; import type { ManifestEntry } from '../spec/manifest.schema'; -import type { PackageVariableRequirement } from '../spec/requirements.schema'; +import type { + PackageCredentialRequirement, + PackageVariableRequirement, +} from '../spec/requirements.schema'; +import type { SerializedCredential } from '../spec/serialized/credential.schema'; import type { SerializedVariable } from '../spec/serialized/variable.schema'; export function foldersInScope( @@ -26,6 +37,40 @@ export function workflowsInScope( ); } +export function needsBundledCredentialData( + request: ImportCredentialProperties, + hasRequirements: boolean, +): boolean { + return hasRequirements && credentialMissingModeUsesPackageData(request.credentialMissingMode); +} + +/** + * Attaches each requirement's bundled expression data. Lookup is by id: the manifest + * rejects duplicate credential ids, so each requirement has at most one bundle entry — + * scoped or top-level — regardless of which project owns the credential file. + */ +export function placeCredentialData({ + requirements, + bundledCredentials, +}: { + requirements: PackageCredentialRequirement[] | undefined; + /** Package credential files by credential id. */ + bundledCredentials?: ReadonlyMap; +}): PlacedCredentialRequirement[] | undefined { + return requirements?.map((requirement) => { + const credential = bundledCredentials?.get(requirement.id); + const packageData = credential?.data; + + return { + ...requirement, + ...(packageData !== undefined ? { packageData } : {}), + ...(credential?.dataIsComplete !== undefined + ? { packageDataIsComplete: credential.dataIsComplete } + : {}), + }; + }); +} + export function needsBundledVariableValues( request: ImportVariableProperties, hasRequirements: boolean, @@ -37,6 +82,18 @@ export function needsBundledVariableValues( ); } +/** Only an update compares with the package credential files, so `keep-existing` never reads them. */ +export function needsBundledCredentialFiles( + request: Pick, + hasRequirements: boolean, +): boolean { + return ( + hasRequirements && + resolveCredentialConflictPolicy(request.credentialConflictPolicy) !== + CredentialConflictPolicy.KeepExisting + ); +} + /** The entry bundling `name` for one scope: its own variables/ entry beats a top-level one, a tie is ambiguous. */ function variableBundleEntry( entries: ManifestEntry[] | undefined, diff --git a/packages/cli/src/modules/n8n-packages/engine/project-package-importer.ts b/packages/cli/src/modules/n8n-packages/engine/project-package-importer.ts index dcd6de2fb3f..56b3f8bde31 100644 --- a/packages/cli/src/modules/n8n-packages/engine/project-package-importer.ts +++ b/packages/cli/src/modules/n8n-packages/engine/project-package-importer.ts @@ -3,7 +3,15 @@ import { Service } from '@n8n/di'; import { ForbiddenError } from '@n8n/errors'; -import type { CredentialBindingRequest } from '../entities/credential/credential.types'; +import { + credentialUpdateScope, + resolveCredentialConflictPolicy, +} from '../entities/credential/credential-conflict-policy'; +import type { + CredentialBindingRequest, + CredentialUpdateScope, +} from '../entities/credential/credential.types'; +import { canStubNotFoundFailure } from '../entities/credential/credential-missing-mode'; import { removesUnpackagedWorkflows } from '../entities/folder/folder-conflict-policy'; import type { DataTableImportRequest } from '../entities/data-table/data-table.types'; import { ProjectImporter } from '../entities/project/project-importer'; @@ -32,7 +40,13 @@ import { assertTagWritesAllowed, } from './import-gates'; import { toImportBlockedError } from './import-blocked.error'; -import { needsBundledVariableValues, placeByLayout } from './package-layout'; +import { + needsBundledCredentialData, + needsBundledCredentialFiles, + needsBundledVariableValues, + placeByLayout, + placeCredentialData, +} from './package-layout'; import { ImportOrchestrator, type ImportContentResult, @@ -52,6 +66,7 @@ import { import type { ImportOutcome, PackageImportScope } from './import-telemetry'; import { N8nPackageParser } from './n8n-package-parser'; import type { ManifestEntry, PackageManifest } from '../spec/manifest.schema'; +import type { SerializedCredential } from '../spec/serialized/credential.schema'; import type { SerializedVariable } from '../spec/serialized/variable.schema'; @Service() @@ -102,6 +117,15 @@ export class ProjectPackageImporter { ) ? await this.packageParser.getVariables(reader) : undefined; + // Read once for the whole import: every scope looks its credentials up by id. + const packageCredentials = needsBundledCredentialFiles( + request, + (manifest.requirements?.credentials?.length ?? 0) > 0, + ) + ? await this.packageParser.getCredentials(reader) + : undefined; + // Projects match by id, so a package project id is also its destination project id. + const updateScope = credentialUpdateScope(selectedProjects.map(({ id }) => id)); // Projects the user is creating (vs matching an existing one). They will be admin of these, // so publish is always allowed and the project need not exist while its contents are planned. const pendingCreateIds = new Set( @@ -120,13 +144,31 @@ export class ProjectPackageImporter { manifest, project, pendingCreateIds.has(project.id), - bundledVariables, + { bundledVariables, packageCredentials, credentialUpdateScope: updateScope }, importSource, ); const plan = await this.importOrchestrator.plan(input); planned.push({ project, plan }); } + const missingCredentialIds = new Set( + planned.flatMap(({ plan }) => + plan.credentialPlan.failures.filter(canStubNotFoundFailure).map(({ sourceId }) => sourceId), + ), + ); + if (needsBundledCredentialData(request, missingCredentialIds.size > 0)) { + const bundledCredentials = + packageCredentials ?? + (await this.packageParser.getCredentials(reader, missingCredentialIds)); + for (const { plan } of planned) { + const { credentialRequest } = plan.input; + credentialRequest.requirements = placeCredentialData({ + requirements: credentialRequest.requirements, + bundledCredentials, + }); + } + } + assertTagWritesAllowed( request.apiKeyScopes, planned.map(({ plan }) => plan.tagPlan), @@ -183,6 +225,7 @@ export class ProjectPackageImporter { let dataTablesMatched = 0; let dataTablesCreated = 0; let dataTablesUpdated = 0; + const seeded: string[] = []; const variablesMatched: string[] = []; const variablesMissing: string[] = []; const variablesCreated: string[] = []; @@ -205,6 +248,7 @@ export class ProjectPackageImporter { dataTablesMatched += content.dataTablePlan.matchedCount; dataTablesCreated += content.dataTablePlan.creations.length; dataTablesUpdated += content.dataTablePlan.updates.length; + seeded.push(...content.credentialResult.seeded); variablesMatched.push(...content.variablePlan.matched); variablesMissing.push(...content.variablePlan.missing.map(({ name }) => name)); variablesCreated.push(...content.variableResult.created); @@ -230,7 +274,7 @@ export class ProjectPackageImporter { folders, projects: projectSummaries, bindings: mergeBindings(...scopedBindings), - credentials: { matched, stubbed }, + credentials: { matched, stubbed, seeded }, dataTables: { matched: dataTablesMatched, created: dataTablesCreated, @@ -256,7 +300,12 @@ export class ProjectPackageImporter { manifest: PackageManifest, project: ManifestEntry, projectPendingCreation: boolean, - bundledVariables: Map | undefined, + /** Read or resolved once for every scope of the import. */ + importWide: { + bundledVariables: Map | undefined; + packageCredentials: Map | undefined; + credentialUpdateScope: CredentialUpdateScope; + }, importSource: PackageImportSource, ): Promise { const basePrefix = `${project.target}/`; @@ -281,6 +330,9 @@ export class ProjectPackageImporter { request.bindings?.credentials, requirements, ), + conflictPolicy: resolveCredentialConflictPolicy(request.credentialConflictPolicy), + packageCredentials: importWide.packageCredentials, + updateScope: importWide.credentialUpdateScope, }; const dataTableRequest: DataTableImportRequest = { @@ -296,7 +348,7 @@ export class ProjectPackageImporter { requirements: identifyRequirements(manifest.requirements?.variables, workflows), manifestVariables: manifest.variables, scopePrefix: basePrefix, - bundledVariables, + bundledVariables: importWide.bundledVariables, }), missingMode: request.variableMissingMode, conflictPolicy: request.variableConflictPolicy, diff --git a/packages/cli/src/modules/n8n-packages/engine/workflow-package-importer.ts b/packages/cli/src/modules/n8n-packages/engine/workflow-package-importer.ts index cab36b5a59e..adb98060254 100644 --- a/packages/cli/src/modules/n8n-packages/engine/workflow-package-importer.ts +++ b/packages/cli/src/modules/n8n-packages/engine/workflow-package-importer.ts @@ -8,7 +8,12 @@ import { ForbiddenError, NotFoundError } from '@n8n/errors'; import { FolderService } from '@/services/folder.service'; import { ProjectService } from '@/services/project.service.ee'; +import { + credentialUpdateScope, + resolveCredentialConflictPolicy, +} from '../entities/credential/credential-conflict-policy'; import type { CredentialBindingRequest } from '../entities/credential/credential.types'; +import { canStubNotFoundFailure } from '../entities/credential/credential-missing-mode'; import type { DataTableImportRequest } from '../entities/data-table/data-table.types'; import type { TagImportRequest } from '../entities/tag/tag.types'; import type { VariableImportRequest } from '../entities/variable/variable.types'; @@ -32,7 +37,13 @@ import { } from './import-result'; import type { ImportOutcome, PackageImportScope } from './import-telemetry'; import { N8nPackageParser } from './n8n-package-parser'; -import { needsBundledVariableValues, placeByPolicy } from './package-layout'; +import { + needsBundledCredentialData, + needsBundledCredentialFiles, + needsBundledVariableValues, + placeByPolicy, + placeCredentialData, +} from './package-layout'; import type { PackageManifest } from '../spec/manifest.schema'; /** @@ -69,11 +80,23 @@ export class WorkflowPackageImporter { ); const workflows = await this.packageParser.getWorkflows(reader); + const credentialRequirements = identifyRequirements( + manifest.requirements?.credentials, + workflows, + ); const credentialRequest: CredentialBindingRequest = { - requirements: identifyRequirements(manifest.requirements?.credentials, workflows), + requirements: credentialRequirements, matchingMode: request.credentialMatchingMode, missingMode: request.credentialMissingMode, credentialBindings: request.bindings?.credentials, + conflictPolicy: resolveCredentialConflictPolicy(request.credentialConflictPolicy), + packageCredentials: needsBundledCredentialFiles( + request, + (credentialRequirements?.length ?? 0) > 0, + ) + ? await this.packageParser.getCredentials(reader) + : undefined, + updateScope: credentialUpdateScope([context.projectId]), }; const dataTableRequirements = identifyRequirements( @@ -127,6 +150,18 @@ export class WorkflowPackageImporter { subWorkflowRequirements: identifyRequirements(manifest.requirements?.workflows, workflows), }); + const missingCredentialIds = new Set( + plan.credentialPlan.failures.filter(canStubNotFoundFailure).map(({ sourceId }) => sourceId), + ); + if (needsBundledCredentialData(request, missingCredentialIds.size > 0)) { + credentialRequest.requirements = placeCredentialData({ + requirements: credentialRequirements, + bundledCredentials: + credentialRequest.packageCredentials ?? + (await this.packageParser.getCredentials(reader, missingCredentialIds)), + }); + } + assertTagWritesAllowed(request.apiKeyScopes, [plan.tagPlan]); assertArchiveTransitionsAllowed(request.apiKeyScopes, [plan.workflowPlan]); await this.importOrchestrator.assertNotBlocked([plan], { apiKeyScopes: request.apiKeyScopes }); @@ -169,6 +204,7 @@ export class WorkflowPackageImporter { credentials: { matched: content.credentialResult.matched, stubbed: content.credentialResult.stubbed, + seeded: content.credentialResult.seeded, }, dataTables: { matched: content.dataTablePlan.matchedCount, diff --git a/packages/cli/src/modules/n8n-packages/entities/credential/__tests__/credential-conflict-policy.test.ts b/packages/cli/src/modules/n8n-packages/entities/credential/__tests__/credential-conflict-policy.test.ts new file mode 100644 index 00000000000..b06d6ca1258 --- /dev/null +++ b/packages/cli/src/modules/n8n-packages/entities/credential/__tests__/credential-conflict-policy.test.ts @@ -0,0 +1,363 @@ +import type { SharedCredentials } from '@n8n/db'; + +import { + credentialConflicts, + credentialDiffers, + credentialUpdateScope, + divergentCredentials, + differingCredentials, + forbiddenCredentialUpdates, + isUpdateCandidate, + resolveCredentialConflictPolicy, + type UpdatableCredential, +} from '../credential-conflict-policy'; +import type { + CredentialMatch, + CredentialUpdateCandidate, + CredentialUpdateScope, +} from '../credential.types'; + +const EXPRESSION = '={{ $vars.token }}'; +const OTHER_EXPRESSION = '={{ $vars.otherToken }}'; + +const owned = (projectId: string): SharedCredentials[] => [ + { role: 'credential:owner', projectId } as SharedCredentials, + { role: 'credential:user', projectId: 'project-shared' } as SharedCredentials, +]; + +// `isGlobal` is not read, so a test can show that it does not change the scope. +type StoredCredential = UpdatableCredential & { isGlobal: boolean }; + +const credential = (overrides: Partial = {}): StoredCredential => ({ + isManaged: false, + isResolvable: false, + isGlobal: false, + usageScope: 'project', + shared: owned('project-a'), + ...overrides, +}); + +const scope: CredentialUpdateScope = { projectIds: new Set(['project-a', 'project-b']) }; + +const candidate = ( + overrides: Partial = {}, +): CredentialUpdateCandidate => ({ + sourceId: 'source-1', + targetId: 'target-1', + targetName: 'Destination', + name: 'Package', + data: { token: EXPRESSION }, + usedBy: [{ kind: 'workflow', id: 'wf-1' }], + ...overrides, +}); + +describe('resolveCredentialConflictPolicy', () => { + it('defaults to keep-existing', () => { + expect(resolveCredentialConflictPolicy(undefined)).toBe('keep-existing'); + expect(resolveCredentialConflictPolicy('fail')).toBe('fail'); + }); +}); + +describe('credentialUpdateScope', () => { + it('includes every destination project', () => { + expect(credentialUpdateScope(['project-a', 'project-b'])).toEqual(scope); + }); +}); + +describe('isUpdateCandidate', () => { + it('accepts a credential owned by a project of the import', () => { + expect(isUpdateCandidate(credential(), scope)).toBe(true); + expect(isUpdateCandidate(credential({ shared: owned('project-b') }), scope)).toBe(true); + }); + + it('rejects a credential owned by a project outside the import', () => { + expect(isUpdateCandidate(credential({ shared: owned('project-other') }), scope)).toBe(false); + }); + + it('does not count a project the credential is only shared with', () => { + const sharedOnly = credential({ + shared: [{ role: 'credential:user', projectId: 'project-a' } as SharedCredentials], + }); + + expect(isUpdateCandidate(sharedOnly, scope)).toBe(false); + }); + + it('rejects a global credential owned outside the import', () => { + const global = credential({ isGlobal: true, shared: owned('personal-project-of-someone') }); + + expect(isUpdateCandidate(global, scope)).toBe(false); + }); + + it('accepts a global credential owned by a project of the import', () => { + expect(isUpdateCandidate(credential({ isGlobal: true }), scope)).toBe(true); + }); + + it.each<[string, Partial]>([ + ['managed', { isManaged: true }], + ['resolvable', { isResolvable: true }], + ['instance-scoped', { usageScope: 'instance', shared: [] }], + ['managed and global', { isManaged: true, isGlobal: true }], + ])('rejects a %s credential', (_label, overrides) => { + expect(isUpdateCandidate(credential(overrides), scope)).toBe(false); + }); +}); + +describe('credentialDiffers', () => { + it('detects a name change only', () => { + expect( + credentialDiffers( + { name: 'Old', data: { token: EXPRESSION } }, + { name: 'New', data: { token: EXPRESSION } }, + ), + ).toBe(true); + }); + + it('detects an expression change', () => { + expect( + credentialDiffers( + { name: 'Same', data: { token: EXPRESSION } }, + { name: 'Same', data: { token: OTHER_EXPRESSION } }, + ), + ).toBe(true); + }); + + it('detects a package expression that replaces a stored plain value', () => { + expect( + credentialDiffers( + { name: 'Same', data: { token: 'stored-secret' } }, + { name: 'Same', data: { token: EXPRESSION } }, + ), + ).toBe(true); + }); + + it('ignores destination-only keys, including oauthTokenData', () => { + expect( + credentialDiffers( + { + name: 'Same', + data: { + token: EXPRESSION, + clientSecret: 'secret', + oauthTokenData: { access_token: 'token' }, + }, + }, + { name: 'Same', data: { token: EXPRESSION } }, + ), + ).toBe(false); + }); + + it('ignores array changes', () => { + expect( + credentialDiffers( + { name: 'Same', data: { headers: [{ name: 'X-Key', value: 'secret' }] } }, + { name: 'Same', data: { headers: [{ value: EXPRESSION }, { value: OTHER_EXPRESSION }] } }, + ), + ).toBe(false); + }); + + it('ignores an object that holds only arrays when the destination has no such object', () => { + expect( + credentialDiffers( + { name: 'Same', data: { token: 'stored-secret' } }, + { name: 'Same', data: { config: { headers: [EXPRESSION] } } }, + ), + ).toBe(false); + }); + + it('compares only the name for a file without data', () => { + const stored = { name: 'Same', data: { token: 'stored-secret' } }; + + expect(credentialDiffers(stored, { name: 'Same' })).toBe(false); + expect(credentialDiffers(stored, { name: 'Other' })).toBe(true); + }); +}); + +describe('differingCredentials', () => { + it('gives one conflict for each destination, with merged workflows', () => { + expect( + differingCredentials([ + candidate({ usedBy: [{ kind: 'workflow', id: 'wf-2' }] }), + candidate({ + usedBy: [ + { kind: 'workflow', id: 'wf-2' }, + { kind: 'workflow', id: 'wf-1' }, + ], + }), + candidate({ targetId: 'target-2', targetName: 'Second' }), + ]), + ).toEqual([ + { + kind: 'differs', + targetId: 'target-1', + sourceIds: ['source-1'], + name: 'Destination', + usedBy: [ + { kind: 'workflow', id: 'wf-1' }, + { kind: 'workflow', id: 'wf-2' }, + ], + }, + { + kind: 'differs', + targetId: 'target-2', + sourceIds: ['source-1'], + name: 'Second', + usedBy: [{ kind: 'workflow', id: 'wf-1' }], + }, + ]); + }); +}); + +describe('divergentCredentials', () => { + it('reports nothing for the same payload twice', () => { + expect(divergentCredentials([candidate(), candidate({ sourceId: 'source-2' })])).toEqual([]); + }); + + it('reports nothing for the same package credential from two scopes', () => { + expect(divergentCredentials([candidate(), candidate()])).toEqual([]); + }); + + it('reports one conflict for two payloads on one destination', () => { + expect( + divergentCredentials([ + candidate({ sourceId: 'source-2', usedBy: [{ kind: 'workflow', id: 'wf-2' }] }), + candidate({ data: { token: OTHER_EXPRESSION } }), + ]), + ).toEqual([ + { + kind: 'divergent', + targetId: 'target-1', + sourceIds: ['source-1', 'source-2'], + name: 'Destination', + usedBy: [ + { kind: 'workflow', id: 'wf-1' }, + { kind: 'workflow', id: 'wf-2' }, + ], + }, + ]); + }); + + it('reports a name difference', () => { + expect( + divergentCredentials([candidate(), candidate({ sourceId: 'source-2', name: 'Other' })]), + ).toHaveLength(1); + }); + + it('ignores payloads that differ only by arrays', () => { + expect( + divergentCredentials([ + candidate({ data: { token: EXPRESSION, scopes: [EXPRESSION] } }), + candidate({ sourceId: 'source-2', data: { token: EXPRESSION } }), + ]), + ).toEqual([]); + }); + + it('ignores a payload whose only difference is an object that holds only arrays', () => { + expect( + divergentCredentials([ + candidate({ data: { token: EXPRESSION, config: { headers: [EXPRESSION] } } }), + candidate({ sourceId: 'source-2', data: { token: EXPRESSION } }), + ]), + ).toEqual([]); + }); + + it('counts a candidate that equals the destination', () => { + // source-1 equals the destination and is not an update; writing source-2 would drop it. + expect( + divergentCredentials([ + candidate(), + candidate({ sourceId: 'source-2', data: { token: OTHER_EXPRESSION } }), + ]), + ).toEqual([ + expect.objectContaining({ kind: 'divergent', sourceIds: ['source-1', 'source-2'] }), + ]); + }); + + it('does not compare candidates of different destinations', () => { + expect( + divergentCredentials([ + candidate(), + candidate({ sourceId: 'source-2', targetId: 'target-2', name: 'Other' }), + ]), + ).toEqual([]); + }); +}); + +describe('credentialConflicts', () => { + const divergingPlans = [ + { candidates: [candidate()], updates: [candidate()] }, + { + candidates: [candidate({ sourceId: 'source-2', name: 'Other' })], + updates: [candidate({ sourceId: 'source-2', name: 'Other' })], + }, + ]; + + it('reports nothing under keep-existing', () => { + expect(credentialConflicts('keep-existing', divergingPlans)).toEqual([]); + }); + + it('reports differs and no divergence under fail', () => { + expect(credentialConflicts('fail', divergingPlans)).toEqual([ + expect.objectContaining({ kind: 'differs', sourceIds: ['source-1', 'source-2'] }), + ]); + }); + + it('reports divergence and no differs under overwrite', () => { + expect(credentialConflicts('overwrite', divergingPlans)).toEqual([ + expect.objectContaining({ kind: 'divergent', sourceIds: ['source-1', 'source-2'] }), + ]); + }); + + it('dedupes one destination reached from several scopes under fail', () => { + const plans = [ + { candidates: [candidate()], updates: [candidate()] }, + { candidates: [candidate()], updates: [candidate()] }, + ]; + + expect(credentialConflicts('fail', plans)).toHaveLength(1); + expect(credentialConflicts('overwrite', plans)).toEqual([]); + }); +}); + +describe('forbiddenCredentialUpdates', () => { + const match = (overrides: Partial = {}): CredentialMatch => ({ + sourceId: 'source-1', + targetId: 'target-1', + targetName: 'Destination', + usedBy: [{ kind: 'workflow', id: 'wf-1' }], + ...overrides, + }); + + it('gives one issue for each destination across scopes, with merged consumers', () => { + const plans = [ + { forbidden: [match(), match({ targetId: 'target-2', targetName: 'Other' })] }, + { + forbidden: [ + match({ usedBy: [{ kind: 'workflow', id: 'wf-2' }] }), + match({ sourceId: 'source-0' }), + ], + }, + ]; + + expect(forbiddenCredentialUpdates(plans)).toEqual([ + { + targetId: 'target-1', + sourceIds: ['source-0', 'source-1'], + name: 'Destination', + usedBy: [ + { kind: 'workflow', id: 'wf-1' }, + { kind: 'workflow', id: 'wf-2' }, + ], + }, + { + targetId: 'target-2', + sourceIds: ['source-1'], + name: 'Other', + usedBy: [{ kind: 'workflow', id: 'wf-1' }], + }, + ]); + }); + + it('reports nothing without forbidden matches', () => { + expect(forbiddenCredentialUpdates([{ forbidden: [] }])).toEqual([]); + }); +}); diff --git a/packages/cli/src/modules/n8n-packages/entities/credential/__tests__/credential-export-policy.test.ts b/packages/cli/src/modules/n8n-packages/entities/credential/__tests__/credential-export-policy.test.ts index 8060ece0053..5e7f789b007 100644 --- a/packages/cli/src/modules/n8n-packages/entities/credential/__tests__/credential-export-policy.test.ts +++ b/packages/cli/src/modules/n8n-packages/entities/credential/__tests__/credential-export-policy.test.ts @@ -43,22 +43,46 @@ describe('selectCredentialDataForExport', () => { expect(result).toEqual({ formula: '=SUM({{A1}})' }); }); - it('recurses into objects and arrays, pruning emptied containers', async () => { + it('recurses into objects and prunes literal keys, keeping surviving expressions', async () => { const result = await selectCredentialDataForExport( 'expression-values-only', dataThunk({ nested: { deep: { token: '={{ $secrets.t }}', literal: 'x' } }, - headers: [{ name: 'Authorization', value: '={{ $secrets.h }}' }, { name: 'X-Plain' }], + allExpressions: ['={{ $secrets.a }}', '={{ $secrets.b }}'], allLiteral: { a: 'x', b: [1, 2] }, }), ); expect(result).toEqual({ nested: { deep: { token: '={{ $secrets.t }}' } }, - headers: [{ value: '={{ $secrets.h }}' }], + allExpressions: ['={{ $secrets.a }}', '={{ $secrets.b }}'], }); }); + it('drops an array whose entry mixes a literal field with an expression', async () => { + const result = await selectCredentialDataForExport( + 'expression-values-only', + dataThunk({ + headers: [{ name: 'Authorization', value: '={{ $secrets.h }}' }], + token: '={{ $secrets.t }}', + }), + ); + + expect(result).toEqual({ token: '={{ $secrets.t }}' }); + }); + + it('omits an array when any entry filters out, so surviving entries never shift position', async () => { + const result = await selectCredentialDataForExport( + 'expression-values-only', + dataThunk({ + keys: ['literal-key', '={{ $secrets.k }}'], + allExpressions: ['={{ $vars.a }}', '={{ $vars.b }}'], + }), + ); + + expect(result).toEqual({ allExpressions: ['={{ $vars.a }}', '={{ $vars.b }}'] }); + }); + it('drops oauthTokenData at any depth', async () => { const result = await selectCredentialDataForExport( 'expression-values-only', diff --git a/packages/cli/src/modules/n8n-packages/entities/credential/__tests__/credential-importer.test.ts b/packages/cli/src/modules/n8n-packages/entities/credential/__tests__/credential-importer.test.ts index 37ed4083a48..5a9e5a965b2 100644 --- a/packages/cli/src/modules/n8n-packages/entities/credential/__tests__/credential-importer.test.ts +++ b/packages/cli/src/modules/n8n-packages/entities/credential/__tests__/credential-importer.test.ts @@ -1,4 +1,5 @@ -import type { Project, User } from '@n8n/db'; +import type { CredentialsFinderService } from '@n8n/backend-services'; +import type { CredentialsEntity, Project, SharedCredentials, User } from '@n8n/db'; import { Container } from '@n8n/di'; import { mock } from 'vitest-mock-extended'; @@ -9,6 +10,7 @@ import type { CredentialsService } from '@/credentials/credentials.service'; import type { ImportContext } from '../../../n8n-packages.types'; import { CredentialImporter } from '../credential-importer'; import { CredentialMatcherFactory } from '../credential-matcher-factory'; +import type { SerializedCredential } from '../../../spec/serialized/credential.schema'; import type { CredentialBindingRequest, CredentialResolutionFailure } from '../credential.types'; import { IdBasedCredentialMatcher } from '../id-based-credential-matcher'; import type { NameAndTypeCredentialMatcher } from '../name-and-type-credential-matcher'; @@ -24,6 +26,7 @@ const usable = (id: string, type = 'githubApi'): UsableCredential => describe('CredentialImporter', () => { const credentialsService = mock(); + const credentialsFinder = mock(); const credentialTypes = mock(); const targetProject = mock({ id: 'project-target' }); const user = mock({ id: 'user-1' }); @@ -38,12 +41,18 @@ describe('CredentialImporter', () => { credentialBindings?: CredentialBindingRequest['credentialBindings']; missingMode?: CredentialBindingRequest['missingMode']; matchingMode?: CredentialBindingRequest['matchingMode']; + conflictPolicy?: CredentialBindingRequest['conflictPolicy']; + packageCredentials?: CredentialBindingRequest['packageCredentials']; + updateScope?: CredentialBindingRequest['updateScope']; } = {}, ): CredentialBindingRequest => ({ requirements, matchingMode: options.matchingMode ?? 'id-only', missingMode: options.missingMode ?? 'must-preexist', credentialBindings: options.credentialBindings, + conflictPolicy: options.conflictPolicy ?? 'keep-existing', + packageCredentials: options.packageCredentials, + updateScope: options.updateScope ?? { projectIds: new Set([targetProject.id]) }, }); const packageCredential = ( @@ -81,6 +90,7 @@ describe('CredentialImporter', () => { mock(), ), credentialsService, + credentialsFinder, ); }); @@ -245,6 +255,7 @@ describe('CredentialImporter', () => { bindings: new Map([['missing-cred', 'stub-1']]), matched: [], stubbed: ['missing-cred'], + seeded: [], }); }); @@ -265,6 +276,7 @@ describe('CredentialImporter', () => { bindings: new Map(), matched: [], stubbed: [], + seeded: [], }); }); @@ -354,6 +366,7 @@ describe('CredentialImporter', () => { bindings: new Map([['cred-source', 'cred-source']]), matched: ['cred-source'], stubbed: [], + seeded: [], }); }); @@ -380,4 +393,329 @@ describe('CredentialImporter', () => { ).rejects.toBeInstanceOf(ForbiddenError); }); }); + describe('conflict policy', () => { + const EXPRESSION = '={{ $vars.githubToken }}'; + const requirement = packageCredential({ + id: 'cred-1', + usedBy: [ + { kind: 'workflow', id: 'wf-2' }, + { kind: 'workflow', id: 'wf-1' }, + ], + }); + + const packageFile = (overrides: Partial = {}): SerializedCredential => ({ + id: 'cred-1', + name: 'Source GitHub', + type: 'githubApi', + data: { accessToken: EXPRESSION }, + ...overrides, + }); + + const destination = (overrides: Partial = {}) => + mock({ + id: 'cred-1', + name: 'Source GitHub', + type: 'githubApi', + isManaged: false, + isResolvable: false, + isGlobal: false, + usageScope: 'project', + shared: [ + mock({ role: 'credential:owner', projectId: targetProject.id }), + ], + ...overrides, + }); + + beforeEach(() => { + credentialsService.getCredentialsAUserCanUseInAWorkflow.mockResolvedValue([usable('cred-1')]); + credentialsFinder.findCredentialIdsWithScopeForUser.mockImplementation( + async (ids) => await Promise.resolve(new Set(ids)), + ); + }); + + it('keep-existing loads and decrypts nothing', async () => { + const result = await importer.plan( + context, + bindingRequest([requirement], { + conflictPolicy: 'keep-existing', + packageCredentials: new Map([['cred-1', packageFile({ name: 'Renamed' })]]), + }), + ); + + expect(result.successes).toEqual(new Map([['cred-1', 'cred-1']])); + expect(result.candidates).toEqual([]); + expect(result.updates).toEqual([]); + expect(result.forbidden).toEqual([]); + expect(credentialsFinder.findById).not.toHaveBeenCalled(); + expect(credentialsFinder.findCredentialIdsWithScopeForUser).not.toHaveBeenCalled(); + expect(credentialsService.decrypt).not.toHaveBeenCalled(); + }); + + it('plans an update when the package value differs from the stored value', async () => { + credentialsFinder.findById.mockResolvedValue(destination()); + credentialsService.decrypt.mockResolvedValue({ accessToken: 'stored-secret' }); + + const result = await importer.plan( + context, + bindingRequest([requirement], { + conflictPolicy: 'fail', + packageCredentials: new Map([['cred-1', packageFile()]]), + }), + ); + + const candidate = { + sourceId: 'cred-1', + targetId: 'cred-1', + targetName: 'Source GitHub', + name: 'Source GitHub', + data: { accessToken: EXPRESSION }, + usedBy: [ + { kind: 'workflow', id: 'wf-1' }, + { kind: 'workflow', id: 'wf-2' }, + ], + }; + expect(result.candidates).toEqual([candidate]); + expect(result.updates).toEqual([candidate]); + expect(credentialsFinder.findById).toHaveBeenCalledWith('cred-1', { + includeSharedProject: true, + }); + expect(credentialsService.decrypt).toHaveBeenCalledWith(expect.anything(), true); + }); + + it('keeps an equal candidate out of the updates', async () => { + credentialsFinder.findById.mockResolvedValue(destination()); + credentialsService.decrypt.mockResolvedValue({ accessToken: EXPRESSION, other: 'secret' }); + + const result = await importer.plan( + context, + bindingRequest([requirement], { + conflictPolicy: 'overwrite', + packageCredentials: new Map([['cred-1', packageFile()]]), + }), + ); + + expect(result.candidates).toHaveLength(1); + expect(result.updates).toEqual([]); + }); + + it('only binds a match without a package file', async () => { + const result = await importer.plan( + context, + bindingRequest([requirement], { conflictPolicy: 'fail', packageCredentials: new Map() }), + ); + + expect(result.successes).toEqual(new Map([['cred-1', 'cred-1']])); + expect(result.candidates).toEqual([]); + expect(credentialsFinder.findById).not.toHaveBeenCalled(); + }); + + it('only binds a match that is not an update candidate', async () => { + credentialsFinder.findById.mockResolvedValue(destination({ isManaged: true })); + + const result = await importer.plan( + context, + bindingRequest([requirement], { + conflictPolicy: 'fail', + packageCredentials: new Map([['cred-1', packageFile({ name: 'Renamed' })]]), + }), + ); + + expect(result.candidates).toEqual([]); + expect(result.updates).toEqual([]); + expect(credentialsService.decrypt).not.toHaveBeenCalled(); + }); + + it('reports a match in scope that the user cannot update as forbidden, and decrypts nothing', async () => { + credentialsFinder.findById.mockResolvedValue(destination()); + credentialsFinder.findCredentialIdsWithScopeForUser.mockResolvedValue(new Set()); + + const result = await importer.plan( + context, + bindingRequest([requirement], { + conflictPolicy: 'fail', + packageCredentials: new Map([['cred-1', packageFile({ name: 'Renamed' })]]), + }), + ); + + expect(result.successes).toEqual(new Map([['cred-1', 'cred-1']])); + expect(result.candidates).toEqual([]); + expect(result.updates).toEqual([]); + expect(result.forbidden).toEqual([ + { + sourceId: 'cred-1', + targetId: 'cred-1', + targetName: 'Source GitHub', + usedBy: [ + { kind: 'workflow', id: 'wf-1' }, + { kind: 'workflow', id: 'wf-2' }, + ], + }, + ]); + expect(credentialsFinder.findCredentialIdsWithScopeForUser).toHaveBeenCalledWith( + ['cred-1'], + user, + ['credential:update'], + ); + expect(credentialsService.decrypt).not.toHaveBeenCalled(); + }); + + it('only binds a match out of scope, and checks no permission for it', async () => { + credentialsFinder.findById.mockResolvedValue( + destination({ + shared: [ + mock({ role: 'credential:owner', projectId: 'project-other' }), + ], + }), + ); + + const result = await importer.plan( + context, + bindingRequest([requirement], { + conflictPolicy: 'overwrite', + packageCredentials: new Map([['cred-1', packageFile({ name: 'Renamed' })]]), + }), + ); + + expect(result.candidates).toEqual([]); + expect(result.forbidden).toEqual([]); + expect(credentialsFinder.findCredentialIdsWithScopeForUser).not.toHaveBeenCalled(); + expect(credentialsService.decrypt).not.toHaveBeenCalled(); + }); + + it('only binds a match the finder does not return (an instance credential)', async () => { + credentialsFinder.findById.mockResolvedValue(null); + + const result = await importer.plan( + context, + bindingRequest([requirement], { + conflictPolicy: 'overwrite', + packageCredentials: new Map([['cred-1', packageFile()]]), + }), + ); + + expect(result.candidates).toEqual([]); + }); + + it('loads a destination once when two package credentials resolve to it', async () => { + credentialsService.getCredentialsAUserCanUseInAWorkflow.mockResolvedValue([ + usable('cred-target'), + ]); + credentialsFinder.findById.mockResolvedValue(destination({ id: 'cred-target' })); + credentialsService.decrypt.mockResolvedValue({ accessToken: 'stored-secret' }); + const other = packageCredential({ id: 'cred-2' }); + + const result = await importer.plan( + context, + bindingRequest([requirement, other], { + conflictPolicy: 'overwrite', + credentialBindings: new Map([ + ['cred-1', 'cred-target'], + ['cred-2', 'cred-target'], + ]), + packageCredentials: new Map([ + ['cred-1', packageFile()], + ['cred-2', packageFile({ id: 'cred-2' })], + ]), + }), + ); + + expect(result.candidates.map(({ sourceId }) => sourceId)).toEqual(['cred-1', 'cred-2']); + expect(credentialsFinder.findById).toHaveBeenCalledTimes(1); + }); + }); + + describe('create-with-values', () => { + it('apply seeds a created credential from the requirement package data', async () => { + credentialsService.createStubCredential.mockResolvedValue({ id: 'created-1' } as never); + + const missingCredential = packageCredential({ + id: 'missing-cred', + packageData: { token: '={{ $secrets.github.token }}' }, + }); + + const result = await importer.apply( + context, + bindingRequest([missingCredential], { missingMode: 'create-with-values' }), + { + successes: new Map(), + failures: [notFoundFailure(missingCredential)], + }, + ); + + expect(credentialsService.createStubCredential).toHaveBeenCalledWith( + { + id: 'missing-cred', + name: 'Source GitHub', + type: 'githubApi', + projectId: 'project-target', + data: { token: '={{ $secrets.github.token }}' }, + }, + user, + ); + expect(result).toEqual({ + bindings: new Map([['missing-cred', 'created-1']]), + matched: [], + stubbed: [], + seeded: ['missing-cred'], + }); + }); + + it('apply falls back to an empty stub when the package carries no data', async () => { + credentialsService.createStubCredential.mockResolvedValue({ id: 'created-1' } as never); + + const withoutData = packageCredential({ id: 'no-data-cred' }); + const withEmptyData = packageCredential({ id: 'empty-data-cred', packageData: {} }); + + const result = await importer.apply( + context, + bindingRequest([withoutData, withEmptyData], { missingMode: 'create-with-values' }), + { + successes: new Map(), + failures: [notFoundFailure(withoutData), notFoundFailure(withEmptyData)], + }, + ); + + expect(credentialsService.createStubCredential).toHaveBeenCalledWith( + { + id: 'no-data-cred', + name: 'Source GitHub', + type: 'githubApi', + projectId: 'project-target', + }, + user, + ); + expect(result.stubbed).toEqual(['no-data-cred', 'empty-data-cred']); + expect(result.seeded).toEqual([]); + }); + + it('apply never seeds under create-stub even when the package carries data', async () => { + credentialsService.createStubCredential.mockResolvedValue({ id: 'created-1' } as never); + + const missingCredential = packageCredential({ + id: 'missing-cred', + packageData: { token: '={{ $secrets.github.token }}' }, + }); + + const result = await importer.apply( + context, + bindingRequest([missingCredential], { missingMode: 'create-stub' }), + { + successes: new Map(), + failures: [notFoundFailure(missingCredential)], + }, + ); + + expect(credentialsService.createStubCredential).toHaveBeenCalledWith( + { + id: 'missing-cred', + name: 'Source GitHub', + type: 'githubApi', + projectId: 'project-target', + }, + user, + ); + expect(result.stubbed).toEqual(['missing-cred']); + expect(result.seeded).toEqual([]); + }); + }); }); diff --git a/packages/cli/src/modules/n8n-packages/entities/credential/__tests__/credential-missing-mode.test.ts b/packages/cli/src/modules/n8n-packages/entities/credential/__tests__/credential-missing-mode.test.ts index d08fb681036..d412afa1117 100644 --- a/packages/cli/src/modules/n8n-packages/entities/credential/__tests__/credential-missing-mode.test.ts +++ b/packages/cli/src/modules/n8n-packages/entities/credential/__tests__/credential-missing-mode.test.ts @@ -73,6 +73,52 @@ describe('credentialBlockingFailures', () => { ).toEqual([unknownType, sourceNotFound]); }); }); + + describe('create-with-values', () => { + it('rescues the same failures as create-stub', () => { + const rescuable = createFailure( + { id: 'cred-1', name: 'X', type: 'githubApi', usedBy: [{ kind: 'workflow', id: 'wf-1' }] }, + 'not_found', + ); + const blockedBinding = { + ...createFailure( + { + id: 'cred-2', + name: 'Y', + type: 'githubApi', + usedBy: [{ kind: 'workflow', id: 'wf-2' }], + }, + 'not_found', + ), + targetId: 'target-missing', + }; + + expect( + credentialBlockingFailures('create-with-values', { + successes: new Map(), + failures: [rescuable, blockedBinding], + }), + ).toEqual([blockedBinding]); + }); + + it('still blocks unknown_type and source_not_found failures', () => { + const unknownType = createFailure( + { id: 'cred-1', name: 'X', type: 'bad', usedBy: [{ kind: 'workflow', id: 'wf-1' }] }, + 'unknown_type', + ); + const sourceNotFound = createFailure( + { id: 'cred-2', name: 'Y', type: 'githubApi', usedBy: [{ kind: 'workflow', id: 'wf-2' }] }, + 'source_not_found', + ); + + expect( + credentialBlockingFailures('create-with-values', { + successes: new Map(), + failures: [unknownType, sourceNotFound], + }), + ).toEqual([unknownType, sourceNotFound]); + }); + }); }); describe('credentialsToStub', () => { diff --git a/packages/cli/src/modules/n8n-packages/entities/credential/credential-conflict-policy.ts b/packages/cli/src/modules/n8n-packages/entities/credential/credential-conflict-policy.ts new file mode 100644 index 00000000000..d19ea7dc5ef --- /dev/null +++ b/packages/cli/src/modules/n8n-packages/entities/credential/credential-conflict-policy.ts @@ -0,0 +1,190 @@ +import type { CredentialsEntity } from '@n8n/db'; +import isEqual from 'lodash/isEqual'; +import type { ICredentialDataDecryptedObject } from 'n8n-workflow'; + +import { mergeCredentialData } from '@/credentials/credential-data-merge'; + +import type { + CredentialConflict, + CredentialImportPlan, + CredentialMatch, + CredentialUpdateCandidate, + CredentialUpdateForbidden, + CredentialUpdateScope, +} from './credential.types'; +import { CredentialConflictPolicy } from '../../n8n-packages.types'; +import { mergeRequirementConsumers } from '../../spec/requirement-consumers'; +import type { SerializedCredentialData } from '../../spec/serialized/credential.schema'; + +export function resolveCredentialConflictPolicy( + policy: CredentialConflictPolicy | undefined, +): CredentialConflictPolicy { + return policy ?? CredentialConflictPolicy.KeepExisting; +} + +/** + * A credential owned by any destination project of the import can change. Any other credential, + * also a global one, is only bound: a project import must not change a credential that its + * projects do not own. + */ +export function credentialUpdateScope(destinationProjectIds: string[]): CredentialUpdateScope { + return { projectIds: new Set(destinationProjectIds) }; +} + +export type UpdatableCredential = Pick< + CredentialsEntity, + 'isManaged' | 'isResolvable' | 'usageScope' | 'shared' +>; + +/** + * Whether a matched destination credential is in the update scope of the conflict policy. Any + * other match is only bound: it never changes and never blocks. A match in scope also needs + * `credential:update`, else it blocks: see `CredentialImporter`. + */ +export function isUpdateCandidate( + credential: UpdatableCredential, + scope: CredentialUpdateScope, +): boolean { + if (credential.isManaged || credential.isResolvable || credential.usageScope === 'instance') { + return false; + } + + // A credential has no owner column: its owner is the project on the `credential:owner` sharing. + const ownerProjectId = credential.shared?.find( + (sharing) => sharing.role === 'credential:owner', + )?.projectId; + return ownerProjectId !== undefined && scope.projectIds.has(ownerProjectId); +} + +/** Package credentials never carry arrays that can apply, see `credential-export-policy.ts`. */ +function mergeIntoStored( + stored: ICredentialDataDecryptedObject, + incoming: SerializedCredentialData, +): ICredentialDataDecryptedObject { + return mergeCredentialData({ existing: stored, incoming, arrays: 'keep-existing' }); +} + +/** + * Whether `overwrite` would change the destination credential: a different name, or stored + * data that changes when the package values merge into it. Arrays never count. + */ +export function credentialDiffers( + stored: { name: string; data: ICredentialDataDecryptedObject }, + incoming: { name: string; data?: SerializedCredentialData }, +): boolean { + if (stored.name !== incoming.name) return true; + if (incoming.data === undefined) return false; + + return !isEqual(mergeIntoStored(stored.data, incoming.data), stored.data); +} + +/** What a package credential would write, so that two payloads compare by effect. */ +function writtenPayload(candidate: CredentialUpdateCandidate) { + return { name: candidate.name, data: mergeIntoStored({}, candidate.data ?? {}) }; +} + +function uniqueSorted(values: string[]): string[] { + return [...new Set(values)].sort(); +} + +function groupByTarget(candidates: T[]): Map { + const byTarget = new Map(); + for (const candidate of candidates) { + const group = byTarget.get(candidate.targetId) ?? []; + // Scopes of one project package can plan the same package credential more than once, + // each with its own consumers: keep one entry, with the consumers of all scopes. + const index = group.findIndex(({ sourceId }) => sourceId === candidate.sourceId); + if (index === -1) { + group.push(candidate); + } else { + group[index] = { + ...group[index], + usedBy: mergeRequirementConsumers([...group[index].usedBy, ...candidate.usedBy]), + }; + } + byTarget.set(candidate.targetId, group); + } + return byTarget; +} + +function toTargetIssue(targetId: string, group: CredentialMatch[]): CredentialUpdateForbidden { + return { + targetId, + sourceIds: uniqueSorted(group.map(({ sourceId }) => sourceId)), + name: group[0].targetName, + usedBy: mergeRequirementConsumers(group.flatMap(({ usedBy }) => usedBy)), + }; +} + +function toConflict( + kind: CredentialConflict['kind'], + targetId: string, + group: CredentialMatch[], +): CredentialConflict { + return { kind, ...toTargetIssue(targetId, group) }; +} + +/** One `differs` conflict for each destination credential that the package would change. */ +export function differingCredentials(updates: CredentialUpdateCandidate[]): CredentialConflict[] { + return [...groupByTarget(updates)].map(([targetId, group]) => + toConflict('differs', targetId, group), + ); +} + +/** + * Scopes and matchers resolve independently, so two package credentials can land on one + * destination credential. When their payloads differ, the last write would silently win. + * All candidates count, also those equal to the destination: writing another one would drop + * them. + */ +export function divergentCredentials( + candidates: CredentialUpdateCandidate[], +): CredentialConflict[] { + return [...groupByTarget(candidates)] + .filter(([, group]) => { + const [first, ...others] = group.map(writtenPayload); + return others.some((payload) => !isEqual(payload, first)); + }) + .map(([targetId, group]) => toConflict('divergent', targetId, group)); +} + +/** Read-only: classifies which planned credential updates block the import, per policy. */ +/* eslint-disable @typescript-eslint/naming-convention -- API credential conflict policy keys */ +const CONFLICTS: Record< + CredentialConflictPolicy, + ( + candidates: CredentialUpdateCandidate[], + updates: CredentialUpdateCandidate[], + ) => CredentialConflict[] +> = { + 'keep-existing': () => [], + overwrite: (candidates) => divergentCredentials(candidates), + fail: (_candidates, updates) => differingCredentials(updates), +}; +/* eslint-enable @typescript-eslint/naming-convention */ + +/** + * The credential conflicts of a whole import. Takes every scope at once, so that a destination + * credential reached from several scopes gives one conflict. + */ +export function credentialConflicts( + policy: CredentialConflictPolicy, + plans: Array>, +): CredentialConflict[] { + return CONFLICTS[policy]( + plans.flatMap(({ candidates }) => candidates), + plans.flatMap(({ updates }) => updates), + ); +} + +/** + * One issue for each destination credential in the update scope that the user cannot update. + * Takes every scope at once, like {@link credentialConflicts}. + */ +export function forbiddenCredentialUpdates( + plans: Array>, +): CredentialUpdateForbidden[] { + return [...groupByTarget(plans.flatMap(({ forbidden }) => forbidden))].map(([targetId, group]) => + toTargetIssue(targetId, group), + ); +} diff --git a/packages/cli/src/modules/n8n-packages/entities/credential/credential-export-policy.ts b/packages/cli/src/modules/n8n-packages/entities/credential/credential-export-policy.ts index 07fd5807dc5..c9a9efcc167 100644 --- a/packages/cli/src/modules/n8n-packages/entities/credential/credential-export-policy.ts +++ b/packages/cli/src/modules/n8n-packages/entities/credential/credential-export-policy.ts @@ -11,15 +11,31 @@ import type { // oauthTokenData never travels, at any depth — tokens are secrets and the target must reconnect. const NEVER_EXPORTED_KEYS = new Set(['oauthTokenData']); +// Whether every leaf inside the value is an expression, so filtering strips nothing. +function isExpressionOnly(value: unknown): boolean { + if (typeof value === 'string') return containsExpression(value); + if (Array.isArray(value)) return value.length > 0 && value.every(isExpressionOnly); + if (isObject(value)) { + const values = Object.entries(value) + .filter(([key]) => !NEVER_EXPORTED_KEYS.has(key)) + .map(([, entry]) => entry); + return values.length > 0 && values.every(isExpressionOnly); + } + return false; +} + function filterValue(value: unknown): SerializedCredentialDataValue | undefined { if (typeof value === 'string') { return containsExpression(value) ? value : undefined; } if (Array.isArray(value)) { - const kept = value + // Array positions carry meaning and filtering strips literals, so an entry that is + // only partly expressions cannot be reproduced at its slot. The array travels only + // when every entry is expressions end to end; otherwise it is dropped whole. + if (!isExpressionOnly(value)) return undefined; + return value .map(filterValue) .filter((entry): entry is SerializedCredentialDataValue => entry !== undefined); - return kept.length > 0 ? kept : undefined; } if (isObject(value)) { const kept = filterObject(value); diff --git a/packages/cli/src/modules/n8n-packages/entities/credential/credential-importer.ts b/packages/cli/src/modules/n8n-packages/entities/credential/credential-importer.ts index ed871750ea2..25519c50825 100644 --- a/packages/cli/src/modules/n8n-packages/entities/credential/credential-importer.ts +++ b/packages/cli/src/modules/n8n-packages/entities/credential/credential-importer.ts @@ -1,41 +1,145 @@ +import { CredentialsFinderService } from '@n8n/backend-services'; +import type { CredentialsEntity, User } from '@n8n/db'; import { Service } from '@n8n/di'; -import { UnexpectedError } from 'n8n-workflow'; +import { UnexpectedError, type ICredentialDataDecryptedObject } from 'n8n-workflow'; import { CredentialsService } from '@/credentials/credentials.service'; +import { credentialDiffers, isUpdateCandidate } from './credential-conflict-policy'; import { CredentialMatcherFactory } from './credential-matcher-factory'; -import { credentialBlockingFailures, credentialsToStub } from './credential-missing-mode'; +import { + credentialBlockingFailures, + credentialMissingModeUsesPackageData, + credentialsToStub, +} from './credential-missing-mode'; import type { CredentialApplyResult, CredentialBindingRequest, + CredentialImportPlan, + CredentialMatch, CredentialResolution, CredentialResolutionFailure, + CredentialUpdateCandidate, + PlacedCredentialRequirement, } from './credential.types'; import type { ImportBindingMap, ImportContext } from '../../n8n-packages.types'; +import { mergeRequirementConsumers } from '../../spec/requirement-consumers'; +import type { SerializedCredential } from '../../spec/serialized/credential.schema'; @Service() export class CredentialImporter { constructor( private readonly credentialMatcherFactory: CredentialMatcherFactory, private readonly credentialsService: CredentialsService, + private readonly credentialsFinder: CredentialsFinderService, ) {} /** * Resolves which target-project credentials the package's references map to. * Read-only: returns matched `successes` and unresolved `failures` without - * acting on the failures. Mirrors the workflow side's `plan`. + * acting on the failures. Mirrors the workflow side's `plan`. Unless the conflict + * policy is `keep-existing`, also finds the matches the policy can update. */ async plan( context: ImportContext, request: CredentialBindingRequest, - ): Promise { - return await this.credentialMatcherFactory + ): Promise { + const resolution = await this.credentialMatcherFactory .getMatcher(request.matchingMode) .match(request.requirements, { projectId: context.projectId, user: context.user, credentialBindings: request.credentialBindings, }); + + if (request.conflictPolicy === 'keep-existing') { + return { ...resolution, candidates: [], updates: [], forbidden: [] }; + } + + return { ...resolution, ...(await this.planUpdates(context.user, request, resolution)) }; + } + + /** + * Compares each matched credential in the update scope that has a package file with its + * stored state. A match the user cannot update is `forbidden` instead, and is not read. + * Decrypted values stay in this method: the plan keeps only ids and the package payload. + */ + private async planUpdates( + user: User, + request: CredentialBindingRequest, + resolution: CredentialResolution, + ): Promise> { + const requirementsById = new Map( + (request.requirements ?? []).map((requirement) => [requirement.id, requirement]), + ); + const destinations = new Map(); + const inScope: Array<{ + match: CredentialMatch; + packageCredential: SerializedCredential; + destination: CredentialsEntity; + }> = []; + + for (const [sourceId, targetId] of resolution.successes) { + // No file means the exporting user could not read the credential: bind only. + const packageCredential = request.packageCredentials?.get(sourceId); + if (packageCredential === undefined) continue; + + if (!destinations.has(targetId)) { + destinations.set( + targetId, + await this.credentialsFinder.findById(targetId, { includeSharedProject: true }), + ); + } + const destination = destinations.get(targetId); + if (!destination || !isUpdateCandidate(destination, request.updateScope)) continue; + + inScope.push({ + match: { + sourceId, + targetId, + targetName: destination.name, + usedBy: mergeRequirementConsumers(requirementsById.get(sourceId)?.usedBy ?? []), + }, + packageCredential, + destination, + }); + } + + // Matching needs only use access. The comparison reads the stored secret, so a match in + // scope that the user cannot update blocks without being read. + const updatableIds = + inScope.length > 0 + ? await this.credentialsFinder.findCredentialIdsWithScopeForUser( + [...new Set(inScope.map(({ match }) => match.targetId))], + user, + ['credential:update'], + ) + : new Set(); + const candidates: CredentialUpdateCandidate[] = []; + const updates: CredentialUpdateCandidate[] = []; + const forbidden: CredentialMatch[] = []; + + for (const { match, packageCredential, destination } of inScope) { + if (!updatableIds.has(match.targetId)) { + forbidden.push(match); + continue; + } + + const candidate: CredentialUpdateCandidate = { + ...match, + name: packageCredential.name, + ...(packageCredential.data !== undefined ? { data: packageCredential.data } : {}), + }; + candidates.push(candidate); + + const differs = credentialDiffers( + { name: destination.name, data: await this.credentialsService.decrypt(destination, true) }, + packageCredential, + ); + if (differs) updates.push(candidate); + } + + return { candidates, updates, forbidden }; } /** @@ -50,12 +154,26 @@ export class CredentialImporter { return credentialBlockingFailures(request.missingMode, resolution); } - /** - * Creates stub credentials for unresolved `not_found` references under - * `create-stub`, then returns the full source→target binding map. - * {@link CredentialsService.createStubCredential} enforces `credential:create` - * on the target project, and the `credentialSave` policy again after the plan checked it. - */ + async assertCanCreate( + context: ImportContext, + request: CredentialBindingRequest, + resolution: CredentialResolution, + ): Promise { + if (!credentialMissingModeUsesPackageData(request.missingMode)) return; + + const packageData = packageDataBySourceId(request.requirements); + for (const { sourceId } of credentialsToStub(request.missingMode, resolution)) { + const data = packageData.get(sourceId); + if (data !== undefined) { + await this.credentialsService.validateStubCredentialData( + data, + context.user, + context.projectId, + ); + } + } + } + async apply( context: ImportContext, request: CredentialBindingRequest, @@ -64,6 +182,11 @@ export class CredentialImporter { const bindings: ImportBindingMap = new Map(resolution.successes); const matched = [...resolution.successes.keys()]; const stubbed: string[] = []; + const seeded: string[] = []; + + const packageData = credentialMissingModeUsesPackageData(request.missingMode) + ? packageDataBySourceId(request.requirements) + : new Map(); for (const credential of credentialsToStub(request.missingMode, resolution)) { const { sourceId, type, name } = credential; @@ -73,6 +196,7 @@ export class CredentialImporter { ); } + const data = packageData.get(sourceId); const stubCredential = await this.credentialsService.createStubCredential( { // Preserve source identity only when matching by id. @@ -80,14 +204,30 @@ export class CredentialImporter { name: name ?? sourceId, type, projectId: context.projectId, + ...(data !== undefined ? { data } : {}), }, context.user, ); bindings.set(sourceId, stubCredential.id); - stubbed.push(sourceId); + (data !== undefined ? seeded : stubbed).push(sourceId); } - return { bindings, matched, stubbed }; + return { bindings, matched, stubbed, seeded }; } } + +/** Non-empty bundled expression data per source id; empty data means an empty stub. */ +function packageDataBySourceId( + requirements: PlacedCredentialRequirement[] | undefined, +): Map { + const data = new Map(); + for (const requirement of requirements ?? []) { + if (requirement.packageData !== undefined && Object.keys(requirement.packageData).length > 0) { + // Zod-validated plain JSON is what Cipher encrypts at rest, but CredentialInformation + // cannot type a mixed-element array, so the compatibility is asserted, not inferred. + data.set(requirement.id, requirement.packageData as ICredentialDataDecryptedObject); + } + } + return data; +} diff --git a/packages/cli/src/modules/n8n-packages/entities/credential/credential-missing-mode.ts b/packages/cli/src/modules/n8n-packages/entities/credential/credential-missing-mode.ts index 8019235c010..8bc12349840 100644 --- a/packages/cli/src/modules/n8n-packages/entities/credential/credential-missing-mode.ts +++ b/packages/cli/src/modules/n8n-packages/entities/credential/credential-missing-mode.ts @@ -11,14 +11,17 @@ export function canStubNotFoundFailure(failure: CredentialResolutionFailure): bo * Classifies which unresolved credential references block the import, per missing-mode * policy. Read-only — never writes. */ +const rescueStubbable = (resolution: CredentialResolution): CredentialResolutionFailure[] => + resolution.failures.filter((failure) => !canStubNotFoundFailure(failure)); + /* eslint-disable @typescript-eslint/naming-convention -- API credential missing mode keys */ const BLOCKING_FAILURES: Record< CredentialMissingMode, (resolution: CredentialResolution) => CredentialResolutionFailure[] > = { 'must-preexist': (resolution) => resolution.failures, - 'create-stub': (resolution) => - resolution.failures.filter((failure) => !canStubNotFoundFailure(failure)), + 'create-stub': rescueStubbable, + 'create-with-values': rescueStubbable, }; /* eslint-enable @typescript-eslint/naming-convention */ @@ -29,16 +32,11 @@ export function credentialBlockingFailures( return BLOCKING_FAILURES[mode](resolution); } -/** - * The stubs the import creates: one stubbable `not_found` failure per source id (the last one - * seen), and none unless the mode is `create-stub`. Apply writes these and the plan checks them - * against policy, so both read this one list. - */ export function credentialsToStub( mode: CredentialMissingMode, resolution: CredentialResolution, ): CredentialResolutionFailure[] { - if (mode !== 'create-stub') return []; + if (!credentialMissingModeCreates(mode)) return []; return [ ...new Map( @@ -49,6 +47,16 @@ export function credentialsToStub( ]; } +/** Whether the mode fills an unresolved reference by creating the credential. */ +export function credentialMissingModeCreates(mode: CredentialMissingMode): boolean { + return mode === 'create-stub' || mode === 'create-with-values'; +} + +/** Whether the mode seeds created credentials from the package's bundled expression data. */ +export function credentialMissingModeUsesPackageData(mode: CredentialMissingMode): boolean { + return mode === 'create-with-values'; +} + /** Package workflow ids that should not be published because they use stubbed credentials. */ export function workflowsBlockedFromPublish( requirements: PackageCredentialRequirement[] | undefined, diff --git a/packages/cli/src/modules/n8n-packages/entities/credential/credential.exporter.ts b/packages/cli/src/modules/n8n-packages/entities/credential/credential.exporter.ts index 7091c26df55..b6592ca1908 100644 --- a/packages/cli/src/modules/n8n-packages/entities/credential/credential.exporter.ts +++ b/packages/cli/src/modules/n8n-packages/entities/credential/credential.exporter.ts @@ -1,6 +1,8 @@ import type { CredentialsEntity, User } from '@n8n/db'; import { Service } from '@n8n/di'; import { Credentials } from 'n8n-core'; +import type { ICredentialDataDecryptedObject } from 'n8n-workflow'; +import isEqual from 'lodash/isEqual'; import { CredentialsFinderService } from '@n8n/backend-services'; @@ -61,14 +63,17 @@ export class CredentialExporter { }; if (credential) { + let decryptedData: ICredentialDataDecryptedObject | undefined; const data = await selectCredentialDataForExport( request.credentialExportPolicy, - async () => - await new Credentials( + async () => { + decryptedData = await new Credentials( { id: credential.id, name: credential.name }, credential.type, credential.data, - ).getData(), + ).getData(); + return decryptedData; + }, ); entries.push( await writeManifestEntry( @@ -80,7 +85,10 @@ export class CredentialExporter { request.projectTargetsById, ), { id: credential.id, name: credential.name }, - this.credentialSerializer.serialize(credential, { data }), + this.credentialSerializer.serialize(credential, { + data, + ...(data !== undefined ? { dataIsComplete: isEqual(data, decryptedData) } : {}), + }), ), ); } @@ -96,10 +104,7 @@ export class CredentialExporter { return { entries, requirements }; } - /** - * A credential has no owner column: its owner is the project on the - * `credential:owner` sharing. Undefined for a global credential. - */ + /** A credential has no owner column: its owner is the project on the `credential:owner` sharing. */ private ownerProjectId(credential: CredentialsEntity): string | undefined { return credential.shared?.find((sharing) => sharing.role === 'credential:owner')?.projectId; } diff --git a/packages/cli/src/modules/n8n-packages/entities/credential/credential.serializer.ts b/packages/cli/src/modules/n8n-packages/entities/credential/credential.serializer.ts index 7311843a540..c78aa8deae9 100644 --- a/packages/cli/src/modules/n8n-packages/entities/credential/credential.serializer.ts +++ b/packages/cli/src/modules/n8n-packages/entities/credential/credential.serializer.ts @@ -36,7 +36,7 @@ const serializePayload = definePackageSerializationPayload< export class CredentialSerializer { serialize( credential: CredentialsEntity, - { data }: { data?: SerializedCredentialData } = {}, + { data, dataIsComplete }: { data?: SerializedCredentialData; dataIsComplete?: boolean } = {}, ): SerializedCredential { return serializedCredentialSchema.parse( serializePayload({ @@ -44,6 +44,7 @@ export class CredentialSerializer { name: credential.name, type: credential.type, ...(data !== undefined ? { data } : {}), + ...(dataIsComplete !== undefined ? { dataIsComplete } : {}), }), ); } diff --git a/packages/cli/src/modules/n8n-packages/entities/credential/credential.types.ts b/packages/cli/src/modules/n8n-packages/entities/credential/credential.types.ts index e3e2791445e..0be3497f3f0 100644 --- a/packages/cli/src/modules/n8n-packages/entities/credential/credential.types.ts +++ b/packages/cli/src/modules/n8n-packages/entities/credential/credential.types.ts @@ -1,11 +1,25 @@ import type { ImportBindingMap, + CredentialConflictPolicy, CredentialMatchingMode, CredentialMissingMode, } from '../../n8n-packages.types'; -import type { PackageCredentialRequirement } from '../../spec/requirements.schema'; +import type { + PackageCredentialRequirement, + PackageRequirementConsumer, +} from '../../spec/requirements.schema'; +import type { + SerializedCredential, + SerializedCredentialData, +} from '../../spec/serialized/credential.schema'; import type { AgentRequirementSource } from '../requirement-source'; +/** A requirement enriched with the expression data the package bundles for it, when any. */ +export type PlacedCredentialRequirement = PackageCredentialRequirement & { + packageData?: SerializedCredentialData; + packageDataIsComplete?: boolean; +}; + export interface CredentialReference { credentialId: string; credentialName?: string; @@ -43,17 +57,78 @@ export interface CredentialResolution { failures: CredentialResolutionFailure[]; } +/** A package credential and the destination credential it resolves to. */ +export interface CredentialMatch { + sourceId: string; + targetId: string; + /** Destination credential name, for reporting. */ + targetName: string; + usedBy: PackageRequirementConsumer[]; +} + +/** + * A matched destination credential that the conflict policy can update, with the package + * payload for it. Holds no stored values: the write decrypts and merges again. + */ +export interface CredentialUpdateCandidate extends CredentialMatch { + /** Package credential name. */ + name: string; + /** Package expression values. Absent when the package was exported without values. */ + data?: SerializedCredentialData; +} + +export interface CredentialImportPlan extends CredentialResolution { + /** Matched credentials the conflict policy can update. Empty under `keep-existing`. */ + candidates: CredentialUpdateCandidate[]; + /** The candidates that `overwrite` would change. */ + updates: CredentialUpdateCandidate[]; + /** Matches in the update scope that the user cannot update. Empty under `keep-existing`. */ + forbidden: CredentialMatch[]; +} + +/** + * - `differs`: under `fail`, the package would change the destination credential. + * - `divergent`: under `overwrite`, two or more package credentials with different + * payloads resolve to one destination credential. + */ +export interface CredentialConflict { + kind: 'differs' | 'divergent'; + targetId: string; + sourceIds: string[]; + /** Destination credential name. */ + name: string; + usedBy: PackageRequirementConsumer[]; +} + +/** + * A destination credential in the update scope that the importing user cannot update. + * Blocks under `overwrite` and `fail`, also when it would not change: its stored values are + * never read. + */ +export type CredentialUpdateForbidden = Omit; + +/** Which matched destination credentials the conflict policy can update. */ +export interface CredentialUpdateScope { + /** Destination projects of the import. A credential owned by one of them is in scope. */ + projectIds: ReadonlySet; +} + export interface CredentialApplyResult { bindings: ImportBindingMap; matched: string[]; stubbed: string[]; + seeded: string[]; } export interface CredentialBindingRequest { - requirements: PackageCredentialRequirement[] | undefined; + requirements: PlacedCredentialRequirement[] | undefined; matchingMode: CredentialMatchingMode; missingMode: CredentialMissingMode; credentialBindings?: ImportBindingMap; + conflictPolicy: CredentialConflictPolicy; + /** Package credential files by credential id. Read only when the policy is not `keep-existing`. */ + packageCredentials?: ReadonlyMap; + updateScope: CredentialUpdateScope; } export function createFailure( diff --git a/packages/cli/src/modules/n8n-packages/n8n-packages.service.ts b/packages/cli/src/modules/n8n-packages/n8n-packages.service.ts index e1cb036bbc7..79bb895f377 100644 --- a/packages/cli/src/modules/n8n-packages/n8n-packages.service.ts +++ b/packages/cli/src/modules/n8n-packages/n8n-packages.service.ts @@ -103,6 +103,7 @@ const CHERRY_PICK_IMPORT_POLICY = { missingNodeTypeMode: 'fail', credentialMatchingMode: 'id-only', credentialMissingMode: 'must-preexist', + credentialConflictPolicy: 'keep-existing', dataTableMatchingMode: 'by-id', dataTableMissingMode: 'create', variableMissingMode: 'must-preexist', @@ -733,7 +734,7 @@ function emptyImportResult(manifest: PackageManifest): ImportResult { folders: [], projects: [], bindings: createBindings(), - credentials: { matched: [], stubbed: [] }, + credentials: { matched: [], stubbed: [], seeded: [] }, dataTables: { matched: 0, created: 0, updated: 0 }, variables: { matched: [], created: [], stubbed: [], updated: [], missing: [] }, tags: { matched: [], created: [], renamed: [], reconciled: [], skipped: [] }, diff --git a/packages/cli/src/modules/n8n-packages/n8n-packages.types.ts b/packages/cli/src/modules/n8n-packages/n8n-packages.types.ts index b9399f9872d..cfe43d971a4 100644 --- a/packages/cli/src/modules/n8n-packages/n8n-packages.types.ts +++ b/packages/cli/src/modules/n8n-packages/n8n-packages.types.ts @@ -2,6 +2,10 @@ import type { PolicyViolation } from '@n8n/api-types'; import type { User } from '@n8n/db'; import type { Readable } from 'node:stream'; +import type { + CredentialConflict, + CredentialUpdateForbidden, +} from './entities/credential/credential.types'; import type { DataTableResolutionFailure } from './entities/data-table/data-table.types'; import type { TagResolutionFailure } from './entities/tag/tag.types'; import type { @@ -30,7 +34,7 @@ export { WorkflowPublishingPolicy } from './entities/workflow/workflow-publishin export type { WorkflowPublishingOutcome } from './entities/workflow/workflow-publishing-policy.types'; export type CredentialMatchingMode = 'id-only' | 'name-and-type' | 'type-only'; -export type CredentialMissingMode = 'must-preexist' | 'create-stub'; +export type CredentialMissingMode = 'must-preexist' | 'create-stub' | 'create-with-values'; export type PackageFailureReason = 'access-denied' | 'entity-not-found' | 'blocked' | 'validation'; @@ -166,6 +170,15 @@ export const VariableConflictPolicy = { Fail: 'fail', } as const; +export const CredentialConflictPolicy = { + /** Does not change a matched credential, also when the package has a different name or different values. */ + KeepExisting: 'keep-existing', + /** Writes the package name and expression values to a matched credential. Keeps the other stored values. */ + Overwrite: 'overwrite', + /** Blocks the import when `overwrite` would change a matched credential. */ + Fail: 'fail', +} as const; + export const VariableParentPolicy = { Project: 'project', Global: 'global', @@ -224,6 +237,9 @@ export type VariableMissingMode = (typeof VariableMissingMode)[keyof typeof Vari export type VariableConflictPolicy = (typeof VariableConflictPolicy)[keyof typeof VariableConflictPolicy]; +export type CredentialConflictPolicy = + (typeof CredentialConflictPolicy)[keyof typeof CredentialConflictPolicy]; + export type VariableParentPolicy = (typeof VariableParentPolicy)[keyof typeof VariableParentPolicy]; export type TagMissingMode = (typeof TagMissingMode)[keyof typeof TagMissingMode]; @@ -314,6 +330,8 @@ export type ImportPackageSelectionRequest = ImportSelectionRequest & { export type ImportCredentialProperties = { credentialMatchingMode: CredentialMatchingMode; credentialMissingMode: CredentialMissingMode; + /** Omitted means `keep-existing`. */ + credentialConflictPolicy?: CredentialConflictPolicy; }; export type ImportWorkflowProperties = { @@ -379,7 +397,7 @@ export interface ImportContext { folderId: string | null; } -export type ImportPackageEventOptions = ImportCredentialProperties & +export type ImportPackageEventOptions = Required & ImportWorkflowProperties & ImportProjectProperties & ResolvedImportFolderProperties & @@ -563,6 +581,8 @@ export type BlockingIssue = actualType?: string; usedBy: PackageRequirementConsumer[]; } + | ({ type: 'credential-conflict' } & CredentialConflict) + | ({ type: 'credential-update-forbidden' } & CredentialUpdateForbidden) | ({ type: 'project-conflict' } & ProjectConflict) | ({ type: 'folder-conflict' } & FolderConflict) | ({ type: 'workflow-removal-forbidden' } & WorkflowRemovalFailure) @@ -697,6 +717,8 @@ export interface ImportPackageSummary { export interface ImportCredentialSummary { matched: string[]; stubbed: string[]; + /** Source ids of credentials created and seeded from the package's bundled expression data. */ + seeded: string[]; } export interface ImportVariableSummary { diff --git a/packages/cli/src/modules/n8n-packages/spec/serialized/credential.schema.ts b/packages/cli/src/modules/n8n-packages/spec/serialized/credential.schema.ts index f54e0f0d6d9..9e8c3727936 100644 --- a/packages/cli/src/modules/n8n-packages/spec/serialized/credential.schema.ts +++ b/packages/cli/src/modules/n8n-packages/spec/serialized/credential.schema.ts @@ -29,6 +29,7 @@ export const serializedCredentialSchema = z name: z.string().min(1), type: z.string().min(1), data: serializedCredentialDataSchema.optional(), + dataIsComplete: z.boolean().optional(), }) .strict(); diff --git a/packages/cli/src/modules/oauth-server/__tests__/oauth-consent.controller.api.test.ts b/packages/cli/src/modules/oauth-server/__tests__/oauth-consent.controller.api.test.ts index fafd8b4b241..1eefced3671 100644 --- a/packages/cli/src/modules/oauth-server/__tests__/oauth-consent.controller.api.test.ts +++ b/packages/cli/src/modules/oauth-server/__tests__/oauth-consent.controller.api.test.ts @@ -3,9 +3,8 @@ import type { User } from '@n8n/db'; import { Container } from '@n8n/di'; import { McpSettingsService } from '@/modules/mcp/mcp.settings.service'; -import { JwtService } from '@/services/jwt.service'; +import { JwtService, UrlService } from '@n8n/backend-services'; import { ProtectedResourceRegistry } from '@/services/protected-resource.registry'; -import { UrlService } from '@n8n/backend-services'; import { createOwner, createMember } from '@test-integration/db/users'; import { setupTestServer } from '@test-integration/utils'; @@ -313,6 +312,16 @@ describe('POST /rest/consent/approve', () => { ); }); + test('rejects a scope list with duplicates', async () => { + const response = await testServer + .authAgentFor(owner) + .post('/consent/approve') + .set('Cookie', `n8n-oauth-session=${sessionToken}`) + .send({ approved: true, scopes: ['workflow:read', 'workflow:read'] }); + + expect(response.statusCode).toBe(400); + }); + test('should handle consent denial and return error redirect URL', async () => { const response = await testServer .authAgentFor(owner) diff --git a/packages/cli/src/modules/oauth-server/__tests__/oauth-session.service.test.ts b/packages/cli/src/modules/oauth-server/__tests__/oauth-session.service.test.ts index 60ea7162865..ec38e2269c4 100644 --- a/packages/cli/src/modules/oauth-server/__tests__/oauth-session.service.test.ts +++ b/packages/cli/src/modules/oauth-server/__tests__/oauth-session.service.test.ts @@ -3,7 +3,7 @@ import { JsonWebTokenError, TokenExpiredError } from 'jsonwebtoken'; import { mock } from 'vitest-mock-extended'; import { ZodError } from 'zod'; -import { JwtService } from '@/services/jwt.service'; +import { JwtService } from '@n8n/backend-services'; import { OAuthSessionService, type OAuthSessionPayload } from '../oauth-session.service'; diff --git a/packages/cli/src/modules/oauth-server/__tests__/oauth-signing-key.service.integration.test.ts b/packages/cli/src/modules/oauth-server/__tests__/oauth-signing-key.service.integration.test.ts index 65bf8ef8109..34d32f4ff33 100644 --- a/packages/cli/src/modules/oauth-server/__tests__/oauth-signing-key.service.integration.test.ts +++ b/packages/cli/src/modules/oauth-server/__tests__/oauth-signing-key.service.integration.test.ts @@ -7,7 +7,7 @@ import { createLocalJWKSet, jwtVerify } from 'jose'; import { Cipher, InstanceSettings } from 'n8n-core'; import { generateKeyPairSync } from 'node:crypto'; -import { JwtService } from '@/services/jwt.service'; +import { JwtService } from '@n8n/backend-services'; import { OAUTH_SIGNING_ALGORITHM, diff --git a/packages/cli/src/modules/oauth-server/__tests__/oauth-token.service.test.ts b/packages/cli/src/modules/oauth-server/__tests__/oauth-token.service.test.ts index 530b9f1c809..f6c041a93a9 100644 --- a/packages/cli/src/modules/oauth-server/__tests__/oauth-token.service.test.ts +++ b/packages/cli/src/modules/oauth-server/__tests__/oauth-token.service.test.ts @@ -11,7 +11,7 @@ import type { InstanceSettings } from 'n8n-core'; import type { KeyObject } from 'node:crypto'; import { createHmac, createPublicKey, generateKeyPairSync } from 'node:crypto'; -import { JwtService } from '@/services/jwt.service'; +import { JwtService, type UrlService } from '@n8n/backend-services'; import type { AccessToken } from '../database/entities/oauth-access-token.entity'; import type { RefreshToken } from '../database/entities/oauth-refresh-token.entity'; @@ -31,7 +31,6 @@ import { McpProtectedResource } from '@/modules/mcp/mcp-protected-resource'; import type { McpConfig } from '@/modules/mcp/mcp.config'; import type { McpSettingsService } from '@/modules/mcp/mcp.settings.service'; import { ProtectedResourceRegistry } from '@/services/protected-resource.registry'; -import type { UrlService } from '@n8n/backend-services'; import type { WorkflowFinderService } from '@/workflows/workflow-finder.service'; const LEGACY_HMAC_SECRET = 'legacy-hmac-secret'; diff --git a/packages/cli/src/modules/oauth-server/__tests__/oauth.controller.test.ts b/packages/cli/src/modules/oauth-server/__tests__/oauth.controller.test.ts index dd1fa2912a4..a0eb9f0d0c5 100644 --- a/packages/cli/src/modules/oauth-server/__tests__/oauth.controller.test.ts +++ b/packages/cli/src/modules/oauth-server/__tests__/oauth.controller.test.ts @@ -8,6 +8,7 @@ import type { ProtectedResourceRegistry, } from '@/services/protected-resource.registry'; import type { UrlService } from '@n8n/backend-services'; +import type { AuthenticationService } from '@n8n/inbound-auth'; import type { OAuthServerLocalAuthorizationServer } from '../oauth-local-authorization-server'; import { OAuthServerService } from '../oauth-server.service'; @@ -29,6 +30,7 @@ beforeAll(async () => { const urlService = mock(); const registry = mock(); const localServer = mock(); +const authenticationService = mock(); let controller: OAuthControllerClass; const makeRes = () => { @@ -53,10 +55,19 @@ const resource = (scopes: string[], isAvailable?: () => Promise): Prote scopes, }); +const publicApiResource: ProtectedResource = { + surface: 'public-api', + id: 'public-api', + getResourceUrl: () => 'https://n8n.test/api/v1', + getAudiences: () => ['https://n8n.test/api/v1'], + authorize: async () => true, + scopes: [], +}; + beforeEach(() => { vi.resetAllMocks(); urlService.getInstanceBaseUrl.mockReturnValue('https://n8n.test'); - controller = new OAuthController(urlService, registry, localServer); + controller = new OAuthController(urlService, registry, localServer, authenticationService); }); describe('OAuthController', () => { @@ -128,6 +139,33 @@ describe('OAuthController', () => { authorization_servers: ['https://n8n.test'], scopes_supported: scopes, }); + expect(authenticationService.advertise).not.toHaveBeenCalled(); + }); + + test('lists the issuers of the trusted sources accepted on the public-api surface', async () => { + registry.getByResourcePath.mockResolvedValue(publicApiResource); + authenticationService.advertise.mockResolvedValue({ + authorizationServers: ['https://n8n.test', 'https://idp.example'], + challenges: [], + }); + const res = makeRes(); + + await controller.protectedResourceMetadata(makeReq(['api', 'v1']), res); + + expect(authenticationService.advertise).toHaveBeenCalledWith( + expect.objectContaining({ + surface: 'public-api', + resource: { + url: 'https://n8n.test/api/v1', + acceptedAudiences: ['https://n8n.test/api/v1'], + }, + }), + ); + expect(res.json).toHaveBeenCalledWith({ + resource: 'https://n8n.test/api/v1', + bearer_methods_supported: ['header'], + authorization_servers: ['https://n8n.test', 'https://idp.example'], + }); }); test('omits scopes_supported when the resource advertises no scopes', async () => { diff --git a/packages/cli/src/modules/oauth-server/__tests__/signing-key-fixtures.ts b/packages/cli/src/modules/oauth-server/__tests__/signing-key-fixtures.ts index a9672ff47bc..136e92e40db 100644 --- a/packages/cli/src/modules/oauth-server/__tests__/signing-key-fixtures.ts +++ b/packages/cli/src/modules/oauth-server/__tests__/signing-key-fixtures.ts @@ -5,7 +5,7 @@ import type { JsonWebKey, KeyObject } from 'node:crypto'; import { createPrivateKey, sign as cryptoSign } from 'node:crypto'; import { mock } from 'vitest-mock-extended'; -import { JwtService } from '@/services/jwt.service'; +import { JwtService } from '@n8n/backend-services'; import { OAUTH_SIGNING_KEY_TYPE } from '../oauth-signing-key.constants'; import { OAuthSigningKeyService } from '../oauth-signing-key.service'; diff --git a/packages/cli/src/modules/oauth-server/__tests__/workflow-mcp-trigger-authorization.api.test.ts b/packages/cli/src/modules/oauth-server/__tests__/workflow-mcp-trigger-authorization.api.test.ts index 61ce1261da7..e2c9fa0a24d 100644 --- a/packages/cli/src/modules/oauth-server/__tests__/workflow-mcp-trigger-authorization.api.test.ts +++ b/packages/cli/src/modules/oauth-server/__tests__/workflow-mcp-trigger-authorization.api.test.ts @@ -16,9 +16,7 @@ import { setupTestServer } from '@test-integration/utils'; import { MCP_TRIGGER_NODE_TYPE } from '@/constants'; import { OAuthTokenService } from '@/modules/oauth-server/oauth-token.service'; -import { CacheService } from '@n8n/backend-services'; -import { UrlService } from '@n8n/backend-services'; -import { JwtService } from '@/services/jwt.service'; +import { CacheService, UrlService, JwtService } from '@n8n/backend-services'; import { OAuthClientRepository } from '../database/repositories/oauth-client.repository'; import type { OAuthSessionPayload } from '../oauth-session.service'; diff --git a/packages/cli/src/modules/oauth-server/dto/approve-consent-request.dto.ts b/packages/cli/src/modules/oauth-server/dto/approve-consent-request.dto.ts index b0232a40087..66f1adc815a 100644 --- a/packages/cli/src/modules/oauth-server/dto/approve-consent-request.dto.ts +++ b/packages/cli/src/modules/oauth-server/dto/approve-consent-request.dto.ts @@ -3,5 +3,12 @@ import { z } from 'zod'; export class ApproveConsentRequestDto extends Z.class({ approved: z.boolean(), - scopes: z.array(z.string().max(64)).max(32).optional(), + // Granted scopes go into the token verbatim, so a repeated scope only inflates the bearer. + scopes: z + .array(z.string().max(64)) + .max(256) + .refine((scopes) => new Set(scopes).size === scopes.length, { + message: 'scopes must not contain duplicates', + }) + .optional(), }) {} diff --git a/packages/cli/src/modules/oauth-server/oauth-session.service.ts b/packages/cli/src/modules/oauth-server/oauth-session.service.ts index 50a30fcf05a..30d5b4c5bcb 100644 --- a/packages/cli/src/modules/oauth-server/oauth-session.service.ts +++ b/packages/cli/src/modules/oauth-server/oauth-session.service.ts @@ -3,7 +3,7 @@ import { Service } from '@n8n/di'; import { Response } from 'express'; import { z } from 'zod'; -import { JwtService } from '@/services/jwt.service'; +import { JwtService } from '@n8n/backend-services'; const oauthSessionPayloadSchema = z.object({ clientId: z.string(), diff --git a/packages/cli/src/modules/oauth-server/oauth-signing-key.service.ts b/packages/cli/src/modules/oauth-server/oauth-signing-key.service.ts index db2a540ac2f..23bc5a3ef01 100644 --- a/packages/cli/src/modules/oauth-server/oauth-signing-key.service.ts +++ b/packages/cli/src/modules/oauth-server/oauth-signing-key.service.ts @@ -12,7 +12,7 @@ import type { JsonWebKey, KeyObject } from 'node:crypto'; import { createPrivateKey, createPublicKey, generateKeyPair } from 'node:crypto'; import { promisify } from 'node:util'; -import { JwtService, type JwtPayload } from '@/services/jwt.service'; +import { JwtService, type JwtPayload } from '@n8n/backend-services'; import { ACCESS_TOKEN_TYPES, diff --git a/packages/cli/src/modules/oauth-server/oauth-token.service.ts b/packages/cli/src/modules/oauth-server/oauth-token.service.ts index f566d146c02..434ff1ecb60 100644 --- a/packages/cli/src/modules/oauth-server/oauth-token.service.ts +++ b/packages/cli/src/modules/oauth-server/oauth-token.service.ts @@ -15,14 +15,13 @@ import { UnexpectedError } from 'n8n-workflow'; import { randomBytes, randomUUID } from 'node:crypto'; import { authorizeAgainstGrant } from '@/modules/inbound-auth-core/grant-authorization'; -import { JwtService } from '@/services/jwt.service'; +import { JwtService, UrlService } from '@n8n/backend-services'; import type { OAuthTokenVerifier, UserWithContext, } from '@/services/oauth-token-verifier-proxy.service'; import type { ProtectedResource } from '@/services/protected-resource.registry'; import { ProtectedResourceRegistry } from '@/services/protected-resource.registry'; -import { UrlService } from '@n8n/backend-services'; import { WorkflowFinderService } from '@/workflows/workflow-finder.service'; import { AccessTokenRepository } from './database/repositories/oauth-access-token.repository'; diff --git a/packages/cli/src/modules/oauth-server/oauth.controller.ts b/packages/cli/src/modules/oauth-server/oauth.controller.ts index a5dc2562afb..3291bca4dc8 100644 --- a/packages/cli/src/modules/oauth-server/oauth.controller.ts +++ b/packages/cli/src/modules/oauth-server/oauth.controller.ts @@ -13,6 +13,7 @@ import { StaticRouterMetadata, } from '@n8n/decorators'; import { Container } from '@n8n/di'; +import { AuthenticationService } from '@n8n/inbound-auth'; import type { Response, Request, RequestHandler, Router } from 'express'; import type { ProtectedResource } from '@/services/protected-resource.registry'; @@ -149,6 +150,7 @@ export class OAuthController { private readonly urlService: UrlService, private readonly resourceRegistry: ProtectedResourceRegistry, private readonly localServer: OAuthServerLocalAuthorizationServer, + private readonly authenticationService: AuthenticationService, ) {} // Add CORS headers for OAuth discovery endpoints @@ -252,7 +254,7 @@ export class OAuthController { return; } - res.json(this.buildProtectedResourceMetadata(resource)); + res.json(await this.buildProtectedResourceMetadata(resource)); } @Options('/.well-known/oauth-protected-resource', { @@ -297,15 +299,29 @@ export class OAuthController { return; } - res.json(this.buildProtectedResourceMetadata(resource)); + res.json(await this.buildProtectedResourceMetadata(resource)); } - private buildProtectedResourceMetadata(resource: ProtectedResource): Record { - const baseUrl = this.urlService.getInstanceBaseUrl(); + private async buildProtectedResourceMetadata( + resource: ProtectedResource, + ): Promise> { + const authorizationServers = + resource.surface === 'public-api' + ? ( + await this.authenticationService.advertise({ + surface: resource.surface, + resource: { + url: resource.getResourceUrl(), + acceptedAudiences: resource.getAudiences(), + }, + }) + ).authorizationServers + : [this.urlService.getInstanceBaseUrl()]; + const metadata: Record = { resource: resource.getResourceUrl(), bearer_methods_supported: ['header'], - authorization_servers: [baseUrl], + authorization_servers: authorizationServers, }; if (resource.scopes.length > 0) { diff --git a/packages/cli/src/modules/promotions.ee/__tests__/promotion-binding-preflight.integration.test.ts b/packages/cli/src/modules/promotions.ee/__tests__/promotion-binding-preflight.integration.test.ts index 03d5a663c09..f028badc28d 100644 --- a/packages/cli/src/modules/promotions.ee/__tests__/promotion-binding-preflight.integration.test.ts +++ b/packages/cli/src/modules/promotions.ee/__tests__/promotion-binding-preflight.integration.test.ts @@ -355,6 +355,11 @@ describe('PromotionBindingPreflightService (directory + database)', () => { }, ]), }), + { + kind: 'project', + code: 'project-deletion', + project: { id: projectB.id, name: 'Beta' }, + }, ]); expect( result.conflicts.find((conflict) => conflict.code === 'missing-definition')?.consumers, @@ -451,7 +456,13 @@ describe('PromotionBindingPreflightService (directory + database)', () => { const expected = { missingProjects: [], missingBindings: [], - conflicts: [], + conflicts: [ + { + kind: 'project', + code: 'project-deletion', + project: { id: unrelated.id, name: 'Unrelated' }, + }, + ], warnings: [], accessRequirements: [ { diff --git a/packages/cli/src/modules/promotions.ee/__tests__/promotion-binding-preflight.service.test.ts b/packages/cli/src/modules/promotions.ee/__tests__/promotion-binding-preflight.service.test.ts index 2b4867e3cb7..81ea51c93f1 100644 --- a/packages/cli/src/modules/promotions.ee/__tests__/promotion-binding-preflight.service.test.ts +++ b/packages/cli/src/modules/promotions.ee/__tests__/promotion-binding-preflight.service.test.ts @@ -167,6 +167,7 @@ describe('PromotionBindingPreflightService', () => { credentialsRepository.findPromotionBindingAccess.mockResolvedValue([]); variablesRepository.findKeysInProjectsOrGlobal.mockResolvedValue([]); dataTableImporter.findDestructiveChanges.mockResolvedValue([]); + projectRepository.findTeamProjectIds.mockResolvedValue([]); projectRepository.findTypesByIds.mockResolvedValue( [PROJECT_A, PROJECT_B, PROJECT_C].map(({ id }) => ({ id, type: 'team' })), ); diff --git a/packages/cli/src/modules/promotions.ee/__tests__/promotions-git.service.test.ts b/packages/cli/src/modules/promotions.ee/__tests__/promotions-git.service.test.ts index a6467d0bdbd..db1a274e3d8 100644 --- a/packages/cli/src/modules/promotions.ee/__tests__/promotions-git.service.test.ts +++ b/packages/cli/src/modules/promotions.ee/__tests__/promotions-git.service.test.ts @@ -462,16 +462,19 @@ describe('PromotionsGitService (git operations)', () => { }); it('restores HEAD and the index when the push fails', async () => { - mockGit.revparse.mockResolvedValueOnce('before\n').mockResolvedValueOnce('after\n'); + mockGit.raw.mockResolvedValueOnce('before\n'); mockGit.push.mockRejectedValueOnce(new Error('push rejected')); await expect(call({ rollbackOnFailure: true })).rejects.toThrow(BadRequestError); - expect(mockGit.revparse.mock.invocationCallOrder[0]).toBeLessThan( + expect(mockGit.raw.mock.calls).toEqual([ + [['for-each-ref', '--format=%(objectname)', 'refs/heads/main']], + [['reset', '--mixed', 'before']], + ]); + expect(mockGit.raw.mock.invocationCallOrder[0]).toBeLessThan( mockGit.add.mock.invocationCallOrder[0], ); - expect(mockGit.raw).toHaveBeenCalledExactlyOnceWith(['reset', '--mixed', 'before']); - expect(mockGit.raw.mock.invocationCallOrder[0]).toBeGreaterThan( + expect(mockGit.raw.mock.invocationCallOrder[1]).toBeGreaterThan( mockGit.push.mock.invocationCallOrder[0], ); }); @@ -479,7 +482,9 @@ describe('PromotionsGitService (git operations)', () => { it('keeps the push error when rollback fails', async () => { const pushError = new ServiceUnavailableError('Push timed out'); mockGit.push.mockRejectedValueOnce(pushError); - mockGit.raw.mockRejectedValueOnce(new Error('reset failed')); + mockGit.raw + .mockResolvedValueOnce('before\n') + .mockRejectedValueOnce(new Error('reset failed')); await expect(call({ rollbackOnFailure: true })).rejects.toBe(pushError); @@ -490,12 +495,17 @@ describe('PromotionsGitService (git operations)', () => { }); it('keeps the new commit when the push succeeds', async () => { - mockGit.revparse.mockResolvedValueOnce('before\n').mockResolvedValueOnce('after\n'); + mockGit.raw.mockResolvedValueOnce('before\n'); + mockGit.revparse.mockResolvedValueOnce('after\n'); await expect(call({ rollbackOnFailure: true })).resolves.toEqual({ commitSha: 'after' }); expect(mockGit.push).toHaveBeenCalledExactlyOnceWith('origin', 'main'); - expect(mockGit.raw).not.toHaveBeenCalled(); + expect(mockGit.raw).toHaveBeenCalledExactlyOnceWith([ + 'for-each-ref', + '--format=%(objectname)', + 'refs/heads/main', + ]); }); it('redacts a push failure and keeps raw git output out of the log', async () => { diff --git a/packages/cli/src/modules/promotions.ee/__tests__/promotions-package.integration.test.ts b/packages/cli/src/modules/promotions.ee/__tests__/promotions-package.integration.test.ts index f9fd437640d..d27083e6154 100644 --- a/packages/cli/src/modules/promotions.ee/__tests__/promotions-package.integration.test.ts +++ b/packages/cli/src/modules/promotions.ee/__tests__/promotions-package.integration.test.ts @@ -848,7 +848,21 @@ describe('Promote and Apply', () => { ); const removedProject = await createTeamProject('Removed from Git', owner); - const result = await service.apply(connection.id, owner); + const blocked = await service.apply(connection.id, owner); + assert(blocked.status === 'blocked'); + expect(blocked.preflight.conflicts).toEqual([ + { + kind: 'project', + code: 'project-deletion', + project: { id: removedProject.id, name: 'Removed from Git' }, + }, + ]); + expect(await projectRepository.findOneBy({ id: removedProject.id })).not.toBeNull(); + + const result = await service.continueApply(connection.id, owner, { + expectedSource: { configId: blocked.configId, ...blocked.git }, + confirmDestructiveChanges: true, + }); assert(result.status === 'applied'); expect(await projectRepository.findOneBy({ id: removedProject.id })).toBeNull(); @@ -868,6 +882,40 @@ describe('Promote and Apply', () => { expect(result.git).toEqual({ commitSha: remoteHead, branchName: 'main' }); }); + it('keeps a project whose folder is on the branch but missing from the manifest', async () => { + const remote = await createRemote(); + const connection = await createInstanceConnection(remote.bareDir); + await service.clone(connection.id, 'apply'); + const listed = await createTeamProject('Orders', owner); + const unlisted = await createTeamProject('Unlisted', owner); + const exportDir = path.join(remote.workingDir, 'n8n-export'); + await packagesService.exportPackageToDirectory( + { + user: owner, + projectIds: [listed.id, unlisted.id], + includeVariableValues: true, + includeTags: true, + dependencyPolicy: ExportDependencyPolicy.Fail, + versionPolicy: ExportVersionPolicy.Latest, + }, + { targetDir: exportDir }, + ); + // A bad merge can drop a manifest entry and leave the project folder. + const manifestPath = path.join(exportDir, 'manifest.json'); + const manifest = jsonParse<{ projects: Array<{ id: string }> }>( + await readFile(manifestPath, 'utf-8'), + ); + manifest.projects = manifest.projects.filter(({ id }) => id !== unlisted.id); + await writeFile(manifestPath, JSON.stringify(manifest)); + await commitAndPushRemote(remote, 'Drop a manifest entry'); + + const result = await service.apply(connection.id, owner); + + assert(result.status === 'applied', JSON.stringify(result)); + expect(result.counts.projects.deleted).toBe(0); + expect(await projectRepository.findOneBy({ id: unlisted.id })).not.toBeNull(); + }); + it('applies a package whose workflow sits two folders deep', async () => { const remote = await createRemote(); const connection = await createInstanceConnection(remote.bareDir); @@ -951,7 +999,10 @@ describe('Promote and Apply', () => { ); expect(await snapshotApplyState()).toEqual(before); expect(blocked).not.toHaveProperty('counts'); - const request = { expectedSource: { configId: blocked.configId, ...blocked.git } }; + const request = { + expectedSource: { configId: blocked.configId, ...blocked.git }, + confirmDestructiveChanges: true, + }; const stillBlocked = ( await agent @@ -1934,19 +1985,140 @@ describe('Apply data table changes', () => { }); describe('Promote a project selection — branch effects', () => { - it('refuses a selection when the branch has no package yet', async () => { + it('promotes a first selection to a branch without a package, then adds to it', async () => { const remote = await createRemote(); const connection = await createInstanceConnection(remote.bareDir); await service.clone(connection.id, 'promote'); + const { project, workflows } = await setupProjectWithWorkflows('Orders', ['w1', 'w2']); + await setupProjectWithWorkflows('Billing', ['b1']); + const promoteWorkflow = async (workflowId: string) => + await service.promoteProjectSelection(project.id, owner, { + workflowIds: [workflowId], + commitMessage: 'Promote selection', + canExportVariableValues: true, + }); + + await promoteWorkflow(workflows[0].id); + + const first = await inspectBranch(remote.bareDir); + expect((await readBranchEntities(first.dir, 'workflow.json')).map((w) => w.id)).toEqual([ + workflows[0].id, + ]); + expect( + (await readBranchEntities(first.dir, PACKAGE_ENTITY_LAYOUT.projects.fileName)).map( + (p) => p.id, + ), + ).toEqual([project.id]); + await expect(readFile(path.join(first.dir, 'README.md'), 'utf-8')).resolves.toBe( + '# n8n promotions test\n', + ); + + await promoteWorkflow(workflows[1].id); + + const second = await inspectBranch(remote.bareDir); + expect((await readBranchEntities(second.dir, 'workflow.json')).map((w) => w.id).sort()).toEqual( + workflows.map((w) => w.id).sort(), + ); + }); + + it.each(['n8n-export', 'n8n-export/manifest.json'])( + 'refuses a selection when the local copy lost committed %s, until it connects again', + async (lostPath) => { + const remote = await createRemote(); + const connection = await createInstanceConnection(remote.bareDir); + const { configId } = await service.clone(connection.id, 'promote'); + const { project, workflows } = await setupProjectWithWorkflows('Orders', ['w1', 'w2']); + const promoteWorkflow = async (workflowId: string) => + await service.promoteProjectSelection(project.id, owner, { + workflowIds: [workflowId], + commitMessage: 'Promote selection', + canExportVariableValues: true, + }); + await promoteWorkflow(workflows[0].id); + const remoteGit = simpleGit(remote.bareDir); + const promotedCommit = (await remoteGit.revparse(['main'])).trim(); + + const { repositoryFolder } = workingDirectory.paths(configId); + await rm(path.join(repositoryFolder, lostPath), { recursive: true, force: true }); + + await expect(promoteWorkflow(workflows[1].id)).rejects.toThrow( + 'The local copy of the promote branch is incomplete', + ); + expect((await remoteGit.revparse(['main'])).trim()).toBe(promotedCommit); + + await service.clone(connection.id, 'promote'); + await promoteWorkflow(workflows[1].id); + + const { dir } = await inspectBranch(remote.bareDir); + expect((await readBranchEntities(dir, 'workflow.json')).map((w) => w.id).sort()).toEqual( + workflows.map((w) => w.id).sort(), + ); + }, + ); + + it('pushes a first selection to an empty repository after a failed attempt', async () => { + const bareDir = path.join(testRoot, 'empty-remote.git'); + await simpleGit().raw(['init', '--bare', bareDir]); + const connection = await createInstanceConnection(bareDir); + const { configId } = await service.clone(connection.id, 'promote'); + const { repositoryFolder } = workingDirectory.paths(configId); + const checkoutGit = simpleGit(repositoryFolder); + const { project, workflows } = await setupProjectWithWorkflows('Orders', ['w1']); + const request = { + workflowIds: [workflows[0].id], + commitMessage: 'Add w1', + canExportVariableValues: true, + }; + + await rename(bareDir, `${bareDir}.offline`); + await expect(service.promoteProjectSelection(project.id, owner, request)).rejects.toThrow(); + + // The checkout is back to a branch with no commits and no package. + await expect(stat(path.join(repositoryFolder, 'n8n-export'))).rejects.toMatchObject({ + code: 'ENOENT', + }); + expect( + (await checkoutGit.raw(['for-each-ref', '--format=%(objectname)', 'refs/heads/main'])).trim(), + ).toBe(''); + expect((await checkoutGit.status()).isClean()).toBe(true); + + await rename(`${bareDir}.offline`, bareDir); + await service.promoteProjectSelection(project.id, owner, request); + + expect((await simpleGit(bareDir).raw(['rev-list', '--count', 'main'])).trim()).toBe('1'); + const { dir } = await inspectBranch(bareDir); + expect((await readBranchEntities(dir, 'workflow.json')).map((w) => w.id)).toEqual([ + workflows[0].id, + ]); + }); + + it('pushes a first branched selection off a base without a package', async () => { + const remote = await createRemote(); + const connection = await createInstanceConnection( + remote.bareDir, + { apply: 'main', promote: 'main' }, + true, + ); + const { configId } = await service.clone(connection.id, 'promote'); + const baseCommit = (await remote.git.revparse(['main'])).trim(); const { project, workflows } = await setupProjectWithWorkflows('Orders', ['w1']); - await expect( - service.promoteProjectSelection(project.id, owner, { - workflowIds: [workflows[0].id], - commitMessage: 'Add w1', - canExportVariableValues: true, - }), - ).rejects.toThrow('Promote the instance first'); + const result = await service.promoteProjectSelection(project.id, owner, { + workflowIds: [workflows[0].id], + commitMessage: 'Add w1', + canExportVariableValues: true, + }); + + const remoteGit = simpleGit(remote.bareDir); + expect((await remoteGit.revparse([`${result.git.branchName}^`])).trim()).toBe(baseCommit); + expect((await remoteGit.revparse(['main'])).trim()).toBe(baseCommit); + const { repositoryFolder } = workingDirectory.paths(configId); + expect((await simpleGit(repositoryFolder).revparse(['HEAD'])).trim()).toBe(baseCommit); + + const { dir } = await inspectBranch(remote.bareDir, result.git.branchName); + expect((await readBranchEntities(dir, 'workflow.json')).map((w) => w.id)).toEqual([ + workflows[0].id, + ]); }); it('adds only the selected workflow, leaving existing workflows untouched', async () => { diff --git a/packages/cli/src/modules/promotions.ee/__tests__/promotions.service.test.ts b/packages/cli/src/modules/promotions.ee/__tests__/promotions.service.test.ts index 263fe5c8ef8..353d3d31f4a 100644 --- a/packages/cli/src/modules/promotions.ee/__tests__/promotions.service.test.ts +++ b/packages/cli/src/modules/promotions.ee/__tests__/promotions.service.test.ts @@ -34,7 +34,7 @@ import { WorkingCopyUpdater } from '../working-copy-updater'; vi.mock('node:fs/promises', async (importOriginal) => { const fs = await importOriginal(); - return { ...fs, rm: vi.fn(fs.rm) }; + return { ...fs, rm: vi.fn(fs.rm), stat: vi.fn(fs.stat) }; }); const CONFIG_ID = 'cfg1'; @@ -149,6 +149,7 @@ describe('PromotionsService', () => { afterEach(async () => { vi.mocked(rm).mockReset(); + vi.mocked(stat).mockReset(); await rm(n8nFolder, { recursive: true, force: true }); }); @@ -668,17 +669,23 @@ describe('PromotionsService', () => { ); }); - it('refuses a selection when the branch has no package', async () => { - await mkdir(repositoryFolder, { recursive: true }); + it('fails without exporting when the package folder cannot be read', async () => { + const readError = Object.assign(new Error('permission denied'), { code: 'EACCES' }); + const { stat: realStat } = + await vi.importActual('node:fs/promises'); + vi.mocked(stat).mockImplementation(async (target, options) => { + if (target === packageFolder) throw readError; + return await realStat(target, options); + }); ownedByP1('w1'); await expect( service.promoteProjectSelection('p1', actor, { workflowIds: ['w1'], - commitMessage: 'first selective', + commitMessage: 'm', canExportVariableValues: true, }), - ).rejects.toThrow('Promote the instance first'); + ).rejects.toBe(readError); expect(n8nPackagesService.exportPackageToDirectory).not.toHaveBeenCalled(); expect(gitService.commitAndPush).not.toHaveBeenCalled(); }); @@ -1230,6 +1237,7 @@ describe('PromotionsService', () => { missingNodeTypeMode: 'fail', credentialMatchingMode: 'id-only', credentialMissingMode: 'must-preexist', + credentialConflictPolicy: 'keep-existing', folderConflictPolicy: 'overwrite', overwriteDeletionPolicy: 'hard-delete', dataTableMatchingMode: 'by-id', diff --git a/packages/cli/src/modules/promotions.ee/promotion-binding-preflight.service.ts b/packages/cli/src/modules/promotions.ee/promotion-binding-preflight.service.ts index 5af64d317ac..6a0227d4f7f 100644 --- a/packages/cli/src/modules/promotions.ee/promotion-binding-preflight.service.ts +++ b/packages/cli/src/modules/promotions.ee/promotion-binding-preflight.service.ts @@ -150,9 +150,30 @@ export class PromotionBindingPreflightService { this.checkCredentials(credentials, targetCredentials, personalProjectIds, projectOf, result); this.checkVariables(variables, targetVariables, personalProjectIds, projectOf, result); this.checkDataTables(destructiveChanges, projectOf, result); + // Only a full apply deletes projects. + if (!selection) await this.checkProjectDeletions(packageInventory, result); return result; } + /** Reports the team projects that a full apply deletes: the ones that the package does not hold. */ + private async checkProjectDeletions( + inventory: PackageDirectoryInventory, + result: PromotionBindingPreflightResult, + ): Promise { + const packageProjectIds = new Set(inventory.projects.map(({ id }) => id)); + const deletedIds = (await this.projectRepository.findTeamProjectIds()).filter( + (id) => !packageProjectIds.has(id), + ); + if (deletedIds.length === 0) return; + + const projects = await this.projectRepository.findTeamProjectInfoByIds(deletedIds); + for (const { id, name } of projects.sort( + (a, b) => compare(a.name, b.name) || compare(a.id, b.id), + )) { + result.conflicts.push({ kind: 'project', code: 'project-deletion', project: { id, name } }); + } + } + private checkProjects( inventory: PackageDirectoryInventory, personalProjectIds: ReadonlySet, diff --git a/packages/cli/src/modules/promotions.ee/promotions-git.service.ts b/packages/cli/src/modules/promotions.ee/promotions-git.service.ts index a48bb740c46..ce8ffbfe58d 100644 --- a/packages/cli/src/modules/promotions.ee/promotions-git.service.ts +++ b/packages/cli/src/modules/promotions.ee/promotions-git.service.ts @@ -261,8 +261,15 @@ export class PromotionsGitService { }); } + // Empty on a repository with no commits yet. const previousHead = rollbackOnFailure - ? (await git.revparse(['HEAD'])).trim() + ? ( + await git.raw([ + 'for-each-ref', + '--format=%(objectname)', + `refs/heads/${branchName}`, + ]) + ).trim() : undefined; try { // Scope staging to the package while including removed entities. @@ -278,10 +285,16 @@ export class PromotionsGitService { return { commitSha }; } catch (error) { - if (previousHead) { + if (previousHead !== undefined) { try { // Restore Git state. The caller restores the package files. - await git.raw(['reset', '--mixed', previousHead]); + if (previousHead) { + await git.raw(['reset', '--mixed', previousHead]); + } else { + // Remove the first commit and clear the index. + await git.raw(['update-ref', '-d', 'HEAD']); + await git.raw(['read-tree', '--empty']); + } } catch { this.logger.warn( 'Failed to restore the Git revision after a failed promotion', @@ -472,6 +485,29 @@ export class PromotionsGitService { } } + /** Reports whether the local branch's last commit holds this path. False when it has no commits. */ + async hasCommittedPath({ + paths, + branchName, + configId, + pathspec, + }: Pick & { + pathspec: string; + }): Promise { + try { + return await this.lockCheckout(paths.repositoryFolder, async () => { + const git = simpleGit({ ...BASE_GIT_OPTIONS, baseDir: paths.repositoryFolder }); + const head = ( + await git.raw(['for-each-ref', '--format=%(objectname)', `refs/heads/${branchName}`]) + ).trim(); + if (!head) return false; + return (await git.raw(['ls-tree', head, '--', pathspec])).trim() !== ''; + }); + } catch (error) { + throw this.mapGitError(error, { configId, branchName }); + } + } + async readFilesAtCommit({ paths, branchName, diff --git a/packages/cli/src/modules/promotions.ee/promotions.service.ts b/packages/cli/src/modules/promotions.ee/promotions.service.ts index c0534b08a4b..c1846b58329 100644 --- a/packages/cli/src/modules/promotions.ee/promotions.service.ts +++ b/packages/cli/src/modules/promotions.ee/promotions.service.ts @@ -6,6 +6,7 @@ import type { ContinueApplySelectionDto, PromotePackageDto, PromotePackageResultDto, + PromotionBindingConflict, PromoteRequest, PromotionCheckoutPublicDto, PromotionDirection, @@ -28,6 +29,7 @@ import { PackageImportConfig } from '@/modules/n8n-packages/n8n-packages.config' import { N8nPackagesService } from '@/modules/n8n-packages/n8n-packages.service'; import { MANIFEST_FILE } from '@/modules/n8n-packages/spec/constants'; import { + CredentialConflictPolicy, DataTableMissingMode, DataTableSchemaConflictPolicy, ExportDependencyPolicy, @@ -77,6 +79,11 @@ import { WorkingCopyUpdater, type SelectivePushOptions } from './working-copy-up type ProjectReconciliationResult = { deletedProjectIds: string[] }; +/** Conflicts that `confirmDestructiveChanges` lets the apply continue past. */ +function isConfirmableConflict(code: PromotionBindingConflict['code']): boolean { + return code === 'destructive-change' || code === 'project-deletion'; +} + // Apply treats the package as source of truth. Callers cannot override this policy, // but a confirmed Continue uses `overwrite` for data tables. const IMPORT_POLICY: Omit = { @@ -87,6 +94,7 @@ const IMPORT_POLICY: Omit = { missingNodeTypeMode: MissingNodeTypeMode.Fail, credentialMatchingMode: 'id-only', credentialMissingMode: 'must-preexist', + credentialConflictPolicy: CredentialConflictPolicy.KeepExisting, folderConflictPolicy: FolderConflictPolicy.Overwrite, overwriteDeletionPolicy: OverwriteDeletionPolicy.HardDelete, dataTableMatchingMode: 'by-id', @@ -275,9 +283,20 @@ export class PromotionsService { const { repositoryFolder } = this.workingDirectory.paths(input.configId); const packageFolder = path.join(repositoryFolder, PACKAGE_SUBFOLDER); - if (!(await this.hasExportedPackage(packageFolder))) { + // No package yet means this selection becomes the first export. + const packageExisted = await pathExists(packageFolder); + if ( + !(await pathExists(path.join(packageFolder, MANIFEST_FILE))) && + (await this.gitService.hasCommittedPath({ + paths: this.workingDirectory.paths(input.configId), + branchName, + configId: input.configId, + pathspec: `${PACKAGE_SUBFOLDER}/${MANIFEST_FILE}`, + })) + ) { + // The commit holds a manifest the checkout lost. A push would drop branch content or metadata. throw new BadRequestError( - 'The local checkout has no exported package. Promote the instance first, then promote a selection.', + 'The local copy of the promote branch is incomplete. Disconnect and connect it again in the instance connection settings.', ); } @@ -289,9 +308,11 @@ export class PromotionsService { let keepPrePushBackup = false; try { - await rm(prePushBackup, { recursive: true, force: true }); - await cp(packageFolder, prePushBackup, { recursive: true, verbatimSymlinks: true }); - backedUp = true; + if (packageExisted) { + await rm(prePushBackup, { recursive: true, force: true }); + await cp(packageFolder, prePushBackup, { recursive: true, verbatimSymlinks: true }); + backedUp = true; + } // The exporter does the selecting: it writes the selected workflows and // what they need, so nothing has to be filtered out afterwards. @@ -366,10 +387,18 @@ export class PromotionsService { { packageFolder, backupFolder: prePushBackup, error: restoreError }, ); } + } else if (!packageExisted) { + await rm(packageFolder, { recursive: true, force: true }).catch((cleanupError: unknown) => { + this.logger.warn('Failed to remove the first selection after a failed promote', { + packageFolder, + error: cleanupError, + }); + }); } throw error; } finally { - if (!keepPrePushBackup) { + // A first push has no backup of its own. Keep any backup left by an earlier failure. + if (packageExisted && !keepPrePushBackup) { await rm(prePushBackup, { recursive: true, force: true }).catch((error: unknown) => { this.logger.warn('Failed to remove the selection backup', { prePushBackup, error }); }); @@ -601,7 +630,7 @@ export class PromotionsService { }, }); const blockingConflicts = confirmDestructiveChanges - ? preflight.conflicts.filter(({ code }) => code !== 'destructive-change') + ? preflight.conflicts.filter(({ code }) => !isConfirmableConflict(code)) : preflight.conflicts; if ( preflight.missingBindings.length > 0 || @@ -702,7 +731,7 @@ export class PromotionsService { sourceDir: packageFolder, }); const blockingConflicts = confirmDestructiveChanges - ? preflight.conflicts.filter(({ code }) => code !== 'destructive-change') + ? preflight.conflicts.filter(({ code }) => !isConfirmableConflict(code)) : preflight.conflicts; if ( preflight.missingBindings.length > 0 || @@ -739,7 +768,14 @@ export class PromotionsService { { sourceDir: packageFolder }, ); const importedProjectIds = result.projects.map((project) => project.localId); - const projectReconciliation = await this.reconcileTeamProjects(actor, importedProjectIds); + const confirmedProjectIds = preflight.conflicts.flatMap((conflict) => + conflict.code === 'project-deletion' ? conflict.project.id : [], + ); + const projectReconciliation = await this.reconcileTeamProjects( + actor, + importedProjectIds, + confirmedProjectIds, + ); return { status: 'applied', @@ -836,14 +872,6 @@ export class PromotionsService { } } - private async hasExportedPackage(packageFolder: string): Promise { - try { - return (await stat(path.join(packageFolder, MANIFEST_FILE))).isFile(); - } catch { - return false; - } - } - /** * A checkout counts as ready only when it exists and was cloned from the * configuration we just resolved. Another process may have changed the remote or @@ -886,13 +914,18 @@ export class PromotionsService { }); } + /** Deletes only the projects that the user confirmed and that the import did not keep. */ private async reconcileTeamProjects( actor: User, importedProjectIds: string[], + confirmedProjectIds: string[], ): Promise { const imported = new Set(importedProjectIds); + const confirmed = new Set(confirmedProjectIds); const teamProjectIds = await this.projectRepository.findTeamProjectIds(); - const removedProjectIds = teamProjectIds.filter((projectId) => !imported.has(projectId)); + const removedProjectIds = teamProjectIds.filter( + (projectId) => confirmed.has(projectId) && !imported.has(projectId), + ); for (const projectId of removedProjectIds) { await this.projectService.deleteProject(actor, projectId); @@ -968,6 +1001,17 @@ export class PromotionsService { } } +/** Throws on any error except a missing path, so an unreadable package never looks empty. */ +async function pathExists(target: string): Promise { + try { + await stat(target); + return true; + } catch (error) { + if (error instanceof Error && 'code' in error && error.code === 'ENOENT') return false; + throw error; + } +} + async function isDirectory(folder: string): Promise { try { return (await stat(folder)).isDirectory(); diff --git a/packages/cli/src/modules/redaction/executions/__tests__/execution-redaction.service.test.ts b/packages/cli/src/modules/redaction/executions/__tests__/execution-redaction.service.test.ts index 5838e642c98..92bf1b3cc4c 100644 --- a/packages/cli/src/modules/redaction/executions/__tests__/execution-redaction.service.test.ts +++ b/packages/cli/src/modules/redaction/executions/__tests__/execution-redaction.service.test.ts @@ -1050,6 +1050,59 @@ describe('ExecutionRedactionService', () => { expect(context.userCanReveal).toBe(false); }); + it('passes on only the credentials of this execution that the viewer cannot use', async () => { + credentialsPermissionChecker.resolveInaccessibleCredentialIdsForUser.mockResolvedValue([ + 'cred-1', + ]); + const execution = makeExecution({ + policy: 'none', + mode: 'manual', + nodes: [nodeWithCredential('cred-1'), nodeWithCredential('cred-2')], + }); + + await service.processExecution(execution, { user: mockUser }); + + const [, context] = fullItemRedactionStrategy.apply.mock.calls[0]; + expect(context.inaccessibleCredentialIds).toEqual(['cred-1']); + }); + + describe('a sub-workflow credential', () => { + // The parent's own nodes reference no credential; its Execute Workflow task + // carries the credentials the sub-workflow run reported. + const parentCallingSubWorkflow = () => { + const execution = makeExecution({ policy: 'none', mode: 'manual', nodes: [] }); + execution.data.resultData.runData = { + 'Execute Workflow': [ + { startTime: 0, executionTime: 0, usedCredentialIds: ['cred-1'] } as ITaskData, + ], + }; + return execution; + }; + + it('force-redacts the parent when the viewer cannot use it', async () => { + credentialsPermissionChecker.resolveInaccessibleCredentialIdsForUser.mockResolvedValue([ + 'cred-1', + ]); + + await service.processExecution(parentCallingSubWorkflow(), { user: mockUser }); + + expect( + credentialsPermissionChecker.resolveInaccessibleCredentialIdsForUser, + ).toHaveBeenCalledWith(mockUser, ['cred-1'], { ignoreGlobalUseScope: true }); + const [, context] = fullItemRedactionStrategy.apply.mock.calls[0]; + expect(context.enforceCredentialUsabilityRedaction).toBe(true); + expect(context.userCanReveal).toBe(false); + }); + + it('does not redact the parent for a viewer who can use it', async () => { + credentialsPermissionChecker.resolveInaccessibleCredentialIdsForUser.mockResolvedValue([]); + + await service.processExecution(parentCallingSubWorkflow(), { user: mockUser }); + + expect(fullItemRedactionStrategy.apply).not.toHaveBeenCalled(); + }); + }); + it('does not force-redact when the viewer can use every referenced credential', async () => { const execution = makeExecution({ policy: 'none', diff --git a/packages/cli/src/modules/redaction/executions/execution-redaction.interfaces.ts b/packages/cli/src/modules/redaction/executions/execution-redaction.interfaces.ts index 13c56ccd44d..bbb50797e61 100644 --- a/packages/cli/src/modules/redaction/executions/execution-redaction.interfaces.ts +++ b/packages/cli/src/modules/redaction/executions/execution-redaction.interfaces.ts @@ -21,6 +21,9 @@ export interface RedactionContext { * dynamic credentials. Drives the `credential_inaccessible` redaction * reason. */ readonly enforceCredentialUsabilityRedaction: boolean; + /** The credentials behind `enforceCredentialUsabilityRedaction`: those the + * requesting user cannot use. Empty when that redaction does not apply. */ + readonly inaccessibleCredentialIds: readonly string[]; /** Generic memo store — strategies may cache intermediate results here * to avoid redundant computation across requiresRedaction/apply calls. * Keyed by strategy name. */ diff --git a/packages/cli/src/modules/redaction/executions/execution-redaction.service.ts b/packages/cli/src/modules/redaction/executions/execution-redaction.service.ts index 03a9c2ae15c..0a437766ace 100644 --- a/packages/cli/src/modules/redaction/executions/execution-redaction.service.ts +++ b/packages/cli/src/modules/redaction/executions/execution-redaction.service.ts @@ -4,6 +4,7 @@ import type { User } from '@n8n/db'; import { Service } from '@n8n/di'; import { channelsToPolicy, + runDataUsedCredentialIds, runDataUsedDynamicCredentials, WorkflowExecuteMode, WorkflowSettings, @@ -192,7 +193,8 @@ export class ExecutionRedactionService implements ExecutionRedaction { const isOwnDynCreds = hasDynCreds && this.isOwnDynamicCredentialsExecution(execution, options.user.id); const policyAllowsReveal = this.policyAllowsReveal(execution); - const enforceCredentialUsabilityRedaction = credentialInaccessibleExecutions.has(execution); + const inaccessibleCredentialIds = credentialInaccessibleExecutions.get(execution) ?? []; + const enforceCredentialUsabilityRedaction = inaccessibleCredentialIds.length > 0; const userCanReveal = enforceCredentialUsabilityRedaction ? false : hasDynCreds @@ -205,6 +207,7 @@ export class ExecutionRedactionService implements ExecutionRedaction { userCanReveal, enforceDynCredRedaction, enforceCredentialUsabilityRedaction, + inaccessibleCredentialIds, memo: new Map(), }; const pipeline = this.buildPipeline(execution, context, policyAllowsReveal); @@ -310,20 +313,27 @@ export class ExecutionRedactionService implements ExecutionRedaction { private async resolveCredentialInaccessibleExecutions( executions: RedactableExecution[], user: User, - ): Promise> { - if (!isCredSharingEnabled()) return new Set(); + ): Promise> { + if (!isCredSharingEnabled()) return new Map(); const credentialIdsByExecution = new Map(); const allCredentialIds = new Set(); for (const execution of executions) { - const credentialIds = this.credentialsPermissionChecker.getCredentialIdsForNodes( - execution.workflowData.nodes, - ); + // The execution's own nodes, plus what its sub-workflows reported onto the calling + // nodes' tasks: their output is embedded here. + const credentialIds = [ + ...new Set([ + ...this.credentialsPermissionChecker.getCredentialIdsForNodes( + execution.workflowData.nodes, + ), + ...runDataUsedCredentialIds(execution.data.resultData?.runData), + ]), + ]; if (credentialIds.length === 0) continue; credentialIdsByExecution.set(execution, credentialIds); for (const id of credentialIds) allCredentialIds.add(id); } - if (allCredentialIds.size === 0) return new Set(); + if (allCredentialIds.size === 0) return new Map(); const inaccessibleIds = await this.credentialsPermissionChecker.resolveInaccessibleCredentialIdsForUser( @@ -331,12 +341,13 @@ export class ExecutionRedactionService implements ExecutionRedaction { [...allCredentialIds], { ignoreGlobalUseScope: true }, ); - if (inaccessibleIds.length === 0) return new Set(); + if (inaccessibleIds.length === 0) return new Map(); const inaccessibleIdSet = new Set(inaccessibleIds); - const result = new Set(); + const result = new Map(); for (const [execution, credentialIds] of credentialIdsByExecution) { - if (credentialIds.some((id) => inaccessibleIdSet.has(id))) result.add(execution); + const inaccessible = credentialIds.filter((id) => inaccessibleIdSet.has(id)); + if (inaccessible.length > 0) result.set(execution, inaccessible); } return result; } diff --git a/packages/cli/src/modules/redaction/executions/strategies/__tests__/full-item-redaction.strategy.test.ts b/packages/cli/src/modules/redaction/executions/strategies/__tests__/full-item-redaction.strategy.test.ts index 670ff469a64..637829d05dc 100644 --- a/packages/cli/src/modules/redaction/executions/strategies/__tests__/full-item-redaction.strategy.test.ts +++ b/packages/cli/src/modules/redaction/executions/strategies/__tests__/full-item-redaction.strategy.test.ts @@ -12,6 +12,7 @@ const makeContext = (overrides: Partial = {}): RedactionContex userCanReveal: false, enforceDynCredRedaction: false, enforceCredentialUsabilityRedaction: false, + inaccessibleCredentialIds: [], memo: new Map(), ...overrides, }); @@ -235,11 +236,19 @@ describe('FullItemRedactionStrategy', () => { ], }); - await strategy.apply(execution, makeContext({ enforceCredentialUsabilityRedaction: true })); + await strategy.apply( + execution, + makeContext({ + enforceCredentialUsabilityRedaction: true, + inaccessibleCredentialIds: ['alice-gmail'], + }), + ); const item = execution.data.resultData.runData.NodeA[0].data!.main[0]![0]; expect(item.redaction?.reason).toBe('credential_inaccessible'); expect(execution.data.redactionInfo?.reason).toBe('credential_inaccessible'); + // Names the credentials, so the editor can link to where access is granted. + expect(execution.data.redactionInfo?.credentialIds).toEqual(['alice-gmail']); }); it('prefers "dynamic_credentials" over "credential_inaccessible" when both are set', async () => { diff --git a/packages/cli/src/modules/redaction/executions/strategies/__tests__/node-defined-field-redaction.strategy.test.ts b/packages/cli/src/modules/redaction/executions/strategies/__tests__/node-defined-field-redaction.strategy.test.ts index 096a59ad3bf..9cf32df4a46 100644 --- a/packages/cli/src/modules/redaction/executions/strategies/__tests__/node-defined-field-redaction.strategy.test.ts +++ b/packages/cli/src/modules/redaction/executions/strategies/__tests__/node-defined-field-redaction.strategy.test.ts @@ -14,6 +14,7 @@ const makeContext = (overrides: Partial = {}): RedactionContex userCanReveal: false, enforceDynCredRedaction: false, enforceCredentialUsabilityRedaction: false, + inaccessibleCredentialIds: [], memo: new Map(), ...overrides, }); diff --git a/packages/cli/src/modules/redaction/executions/strategies/full-item-redaction.strategy.ts b/packages/cli/src/modules/redaction/executions/strategies/full-item-redaction.strategy.ts index 6f85120a53d..596eac5b304 100644 --- a/packages/cli/src/modules/redaction/executions/strategies/full-item-redaction.strategy.ts +++ b/packages/cli/src/modules/redaction/executions/strategies/full-item-redaction.strategy.ts @@ -76,6 +76,9 @@ export class FullItemRedactionStrategy implements IExecutionRedactionStrategy { isRedacted: true, reason, canReveal: context.userCanReveal, + ...(reason === 'credential_inaccessible' && { + credentialIds: [...context.inaccessibleCredentialIds], + }), }; } diff --git a/packages/cli/src/modules/scim/__tests__/scim-token.service.test.ts b/packages/cli/src/modules/scim/__tests__/scim-token.service.test.ts index 5d1d7741172..ccd9a19afef 100644 --- a/packages/cli/src/modules/scim/__tests__/scim-token.service.test.ts +++ b/packages/cli/src/modules/scim/__tests__/scim-token.service.test.ts @@ -2,8 +2,7 @@ import type { ApiKey, User } from '@n8n/db'; import type { Mocked } from 'vitest'; import { mock } from 'vitest-mock-extended'; -import type { JwtService } from '@/services/jwt.service'; -import type { UrlService } from '@n8n/backend-services'; +import type { JwtService, UrlService } from '@n8n/backend-services'; import type { ScimApiKeyRepository } from '../database/scim-api-key.repository'; import { ScimTokenService } from '../scim-token.service'; diff --git a/packages/cli/src/modules/scim/database/scim-api-key.repository.ts b/packages/cli/src/modules/scim/database/scim-api-key.repository.ts index 39f75ecafea..9cfdc1d3000 100644 --- a/packages/cli/src/modules/scim/database/scim-api-key.repository.ts +++ b/packages/cli/src/modules/scim/database/scim-api-key.repository.ts @@ -2,7 +2,7 @@ import { ApiKey, BaseRepository, TransactionRunner, type OperationContext } from import { Service } from '@n8n/di'; import { DataSource } from '@n8n/typeorm'; -import { TOKEN_PURPOSES } from '@/services/token-purposes'; +import { TOKEN_PURPOSES } from '@n8n/backend-services'; /** * SCIM provisioning keys are ordinary API keys reserved by their audience. diff --git a/packages/cli/src/modules/scim/scim-token.service.ts b/packages/cli/src/modules/scim/scim-token.service.ts index 01a1884183f..c91169849e1 100644 --- a/packages/cli/src/modules/scim/scim-token.service.ts +++ b/packages/cli/src/modules/scim/scim-token.service.ts @@ -2,8 +2,7 @@ import { type OperationContext, type User } from '@n8n/db'; import { Service } from '@n8n/di'; import { randomUUID } from 'crypto'; -import { JwtService } from '@/services/jwt.service'; -import { UrlService } from '@n8n/backend-services'; +import { JwtService, UrlService } from '@n8n/backend-services'; import { ScimApiKeyRepository } from './database/scim-api-key.repository'; diff --git a/packages/cli/src/modules/source-control.ee/__tests__/source-control-import.service.ee.test.ts b/packages/cli/src/modules/source-control.ee/__tests__/source-control-import.service.ee.test.ts index 741509ae3f3..105dc3d0de3 100644 --- a/packages/cli/src/modules/source-control.ee/__tests__/source-control-import.service.ee.test.ts +++ b/packages/cli/src/modules/source-control.ee/__tests__/source-control-import.service.ee.test.ts @@ -4,6 +4,7 @@ import type { PolicyCleared, PolicyViolation } from '@n8n/decorators'; import { type Variables, type VariablesRepository, + Folder, type FolderRepository, CredentialsEntity, type CredentialsRepository, @@ -99,6 +100,7 @@ describe('SourceControlImportService', () => { const executionPersistence = mock(); const credentialsService = mock(); const transactionManager = mock(); + const cascadeManager = mock(); const globalAdminContext = new SourceControlContext( Object.assign(new User(), { role: GLOBAL_ADMIN_ROLE }), @@ -166,6 +168,14 @@ describe('SourceControlImportService', () => { transactionManager.delete.mockImplementation( async (_entity, criteria) => await sharedCredentialsRepository.delete(criteria as never), ); + cascadeManager.delete.mockImplementation(async (entity, criteria) => + entity === Folder + ? await folderRepository.delete(criteria as never) + : await projectRepository.delete(criteria as never), + ); + workflowRepository.runInTransaction.mockImplementation( + async (ctx, fn) => await fn(cascadeManager, ctx), + ); credentialsRepositoryManager.transaction.mockImplementation(async (...args) => { const callback = args.find((arg) => typeof arg === 'function'); if (!callback) throw new Error('Transaction callback is required'); @@ -3463,6 +3473,48 @@ describe('SourceControlImportService', () => { ).toBeGreaterThan(folderRepository.delete.mock.invocationCallOrder[0]); }); + it('should purge caller allowlists in the folder delete transaction', async () => { + const candidates = [mock({ id: 'folder1' })]; + const straggler = Object.assign(new WorkflowEntity(), { + id: 'wf-1', + activeVersionId: null, + }); + folderRepository.getAllFolderIdsInHierarchy.mockResolvedValueOnce([]); + workflowRepository.find.mockResolvedValueOnce([straggler]); + workflowRepository.findOne.mockResolvedValueOnce(straggler); + + await service.deleteFoldersNotInWorkfolder(candidates); + + expect(workflowRepository.runInTransaction).toHaveBeenCalledTimes(1); + expect(workflowRepository.removeMissingFromCallerAllowlists).toHaveBeenCalledWith({}); + expect( + workflowRepository.removeMissingFromCallerAllowlists.mock.invocationCallOrder[0], + ).toBeGreaterThan(folderRepository.delete.mock.invocationCallOrder[0]); + expect( + workflowRepository.removeMissingFromCallerAllowlists.mock.invocationCallOrder[0], + ).toBeLessThan(workflowMutationHooks.afterWorkflowsDeleted.mock.invocationCallOrder[0]); + }); + + it('should fail the folder deletion when the caller allowlist purge fails', async () => { + const candidates = [mock({ id: 'folder1' })]; + const straggler = Object.assign(new WorkflowEntity(), { + id: 'wf-1', + activeVersionId: null, + }); + folderRepository.getAllFolderIdsInHierarchy.mockResolvedValueOnce([]); + workflowRepository.find.mockResolvedValueOnce([straggler]); + workflowRepository.findOne.mockResolvedValueOnce(straggler); + workflowRepository.removeMissingFromCallerAllowlists.mockRejectedValueOnce( + new Error('statement timeout'), + ); + + await expect(service.deleteFoldersNotInWorkfolder(candidates)).rejects.toThrow( + 'statement timeout', + ); + + expect(workflowMutationHooks.afterWorkflowsDeleted).not.toHaveBeenCalled(); + }); + it('should not fire the sweep when the deleted folders contained no workflows', async () => { const candidates = [mock({ id: 'folder1' })]; folderRepository.getAllFolderIdsInHierarchy.mockResolvedValueOnce([]); @@ -4132,6 +4184,32 @@ describe('SourceControlImportService', () => { ).toBeGreaterThan(projectRepository.delete.mock.invocationCallOrder[0]); }); + it('should purge caller allowlists in the project delete transaction', async () => { + const candidates = [mock({ id: 'project-1' })]; + sharedWorkflowRepository.find.mockResolvedValueOnce([ + { workflowId: 'wf-in-folder' }, + { workflowId: 'wf-at-project-root' }, + ] as SharedWorkflow[]); + workflowRepository.findOne + .mockResolvedValueOnce( + Object.assign(new WorkflowEntity(), { id: 'wf-in-folder', activeVersionId: null }), + ) + .mockResolvedValueOnce( + Object.assign(new WorkflowEntity(), { + id: 'wf-at-project-root', + activeVersionId: null, + }), + ); + + await service.deleteTeamProjectsNotInWorkfolder(user, candidates, []); + + expect(workflowRepository.runInTransaction).toHaveBeenCalledTimes(1); + expect(workflowRepository.removeMissingFromCallerAllowlists).toHaveBeenCalledWith({}); + expect( + workflowRepository.removeMissingFromCallerAllowlists.mock.invocationCallOrder[0], + ).toBeGreaterThan(projectRepository.delete.mock.invocationCallOrder[0]); + }); + it('should not fire the sweep when the deleted projects contained no workflows', async () => { const candidates = [mock({ id: 'project-1' })]; sharedWorkflowRepository.find.mockResolvedValueOnce([]); diff --git a/packages/cli/src/modules/source-control.ee/source-control-helper.ee.ts b/packages/cli/src/modules/source-control.ee/source-control-helper.ee.ts index 4afcd8f8d59..d0d48de1b23 100644 --- a/packages/cli/src/modules/source-control.ee/source-control-helper.ee.ts +++ b/packages/cli/src/modules/source-control.ee/source-control-helper.ee.ts @@ -9,7 +9,6 @@ import { deepCopy, jsonParse, UserError, - type CredentialInformation, type DataTableColumnType, type ICredentialDataDecryptedObject, } from 'n8n-workflow'; @@ -17,6 +16,7 @@ import { ok } from 'node:assert/strict'; import { readFile as fsReadFile } from 'node:fs/promises'; import path from 'path'; +import { mergeCredentialData } from '@/credentials/credential-data-merge'; import { License } from '@/license'; import { generateSshKeyPair as generateGitSshKeyPair } from '@/modules/promotions.ee/promotions-git.utils'; import { containsExpression } from '@/utils'; @@ -63,60 +63,6 @@ export function sanitizeCredentialData( return result; } -function isPlainObject(value: unknown): value is Record { - return value !== null && typeof value === 'object' && !Array.isArray(value); -} - -/** - * Recursively merges a single value based on its type. - * Handles strings, numbers, booleans, arrays, and plain objects. - */ -function mergeSingleValue(sanitizedRemoteValue: unknown, localValue: unknown): unknown { - if (typeof sanitizedRemoteValue === 'string') { - if (containsExpression(sanitizedRemoteValue)) { - return sanitizedRemoteValue; - } else if (localValue !== undefined && localValue !== null) { - // Local value is preserved if it exists (secret handling) - return localValue; - } - - // The remote field exists as an empty string (key is part of the schema) - // but local has no value for it. Preserve the empty string so the field - // is not silently dropped from the merged credential. - return ''; - } - - if (typeof sanitizedRemoteValue === 'number' || typeof sanitizedRemoteValue === 'boolean') { - return sanitizedRemoteValue; - } - - if (Array.isArray(sanitizedRemoteValue)) { - // Only merge by index if lengths match, otherwise array structure has changed - // and we can't reliably match items (could be additions/removals/reordering) - if (Array.isArray(localValue) && localValue.length === sanitizedRemoteValue.length) { - return sanitizedRemoteValue.map((sanitizedItem, index) => { - const localItem = localValue[index]; - return mergeSingleValue(sanitizedItem, localItem); - }); - } - - return sanitizedRemoteValue; - } - - if (isPlainObject(sanitizedRemoteValue)) { - if (isPlainObject(localValue)) { - return mergeRemoteCrendetialDataIntoLocalCredentialData({ - local: localValue as ICredentialDataDecryptedObject, - remote: sanitizedRemoteValue as ICredentialDataDecryptedObject, - }); - } - - return sanitizedRemoteValue; - } - - return undefined; -} - /** * Merges remote credential data into local data. * Remote expressions, numbers and boolean values overwrite local values. @@ -128,31 +74,11 @@ export function mergeRemoteCrendetialDataIntoLocalCredentialData({ local: ICredentialDataDecryptedObject; remote: ICredentialDataDecryptedObject; }): ICredentialDataDecryptedObject { - const merged: ICredentialDataDecryptedObject = {}; - - const sanitizedRemote = sanitizeCredentialData(remote); - - for (const [key, sanitizedRemoteValue] of Object.entries(sanitizedRemote)) { - const localValue = local[key]; - const mergedValue = mergeSingleValue(sanitizedRemoteValue, localValue); - - if (mergedValue !== undefined) { - merged[key] = mergedValue as CredentialInformation; - } - } - - // Keep local fields the remote stub does not carry. A field left at its default value - // is not persisted, so it never reaches the stub; an absent field carries the same - // "no value to give" meaning as a present-but-blank one, which is already preserved - // above. Without this it would be dropped on pull and reset to its default. This also - // covers oauthTokenData, which sanitization always strips from the remote. - for (const [key, localValue] of Object.entries(local)) { - if (!(key in sanitizedRemote)) { - merged[key] = localValue; - } - } - - return merged; + return mergeCredentialData({ + existing: local, + incoming: sanitizeCredentialData(remote), + arrays: 'merge-by-index', + }); } export function getWorkflowExportPath(workflowId: string, workflowExportFolder: string): string { diff --git a/packages/cli/src/modules/source-control.ee/source-control-import.service.ee.ts b/packages/cli/src/modules/source-control.ee/source-control-import.service.ee.ts index a5988d2e939..b3fd2dcd451 100644 --- a/packages/cli/src/modules/source-control.ee/source-control-import.service.ee.ts +++ b/packages/cli/src/modules/source-control.ee/source-control-import.service.ee.ts @@ -1,16 +1,11 @@ import type { SourceControlledFile, WorkflowPublishBlockedDetails } from '@n8n/api-types'; import { Logger } from '@n8n/backend-common'; -import type { - FindOptionsWhere, - Project, - TagEntity, - User, - Variables, - WorkflowEntity, -} from '@n8n/db'; +import type { FindOptionsWhere, TagEntity, User, Variables, WorkflowEntity } from '@n8n/db'; import { CredentialsRepository, + Folder, FolderRepository, + Project, ProjectRelationRepository, ProjectRepository, SharedCredentialsRepository, @@ -1916,8 +1911,8 @@ export class SourceControlImportService { workflows.map((workflow) => workflow.id), ); - await this.folderRepository.delete({ - id: In(candidateIds), + await this.deleteWithCallerAllowlistPurge(async (trx) => { + await trx.delete(Folder, { id: In(candidateIds) }); }); await this.sweepAfterWorkflowCascade(cascadedWorkflowIds); @@ -1967,8 +1962,8 @@ export class SourceControlImportService { ownedWorkflows.map((sw) => sw.workflowId), ); - await this.projectRepository.delete({ - id: In(candidateIds), + await this.deleteWithCallerAllowlistPurge(async (trx) => { + await trx.delete(Project, { id: In(candidateIds) }); }); await this.sweepAfterWorkflowCascade(cascadedWorkflowIds); @@ -2080,6 +2075,19 @@ export class SourceControlImportService { await this.workflowMutationHooks.afterWorkflowsDeleted(cascadedWorkflowIds); } + /** + * Run a folder/project row delete and drop every id left without a row from the `callerIds` + * allowlists, in one transaction, so no new workflow can take a freed id first. + */ + private async deleteWithCallerAllowlistPurge(deleteRows: (trx: EntityManager) => Promise) { + await this.workflowRepository.runInTransaction({}, async (trx, ctx) => { + await deleteRows(trx); + // Purge by what is gone rather than by the ids collected before the delete: the cascade + // also removes a workflow moved into a deleted folder since. + await this.workflowRepository.removeMissingFromCallerAllowlists(ctx); + }); + } + /** Contextual error for a failed deletion during pull, so the operator learns which resource to look at. */ private deletionError( type: 'workflow' | 'folder' | 'project', diff --git a/packages/cli/src/modules/sso-oidc/__tests__/oidc.service.ee.test.ts b/packages/cli/src/modules/sso-oidc/__tests__/oidc.service.ee.test.ts index 11a93fa39a3..011ea7b2d22 100644 --- a/packages/cli/src/modules/sso-oidc/__tests__/oidc.service.ee.test.ts +++ b/packages/cli/src/modules/sso-oidc/__tests__/oidc.service.ee.test.ts @@ -31,8 +31,7 @@ vi.mock('openid-client', async (importOriginal) => { import { BadRequestError, ForbiddenError } from '@n8n/errors'; import { type ProvisioningService } from '@/modules/provisioning.ee/provisioning.service.ee'; import { Publisher } from '@/scaling/pubsub/publisher.service'; -import type { JwtService } from '@/services/jwt.service'; -import type { UrlService } from '@n8n/backend-services'; +import type { JwtService, UrlService } from '@n8n/backend-services'; import * as ssoHelpers from '@/sso.ee/sso-helpers'; import { OIDC_PREFERENCES_DB_KEY } from '../constants'; diff --git a/packages/cli/src/modules/sso-oidc/oidc.service.ee.ts b/packages/cli/src/modules/sso-oidc/oidc.service.ee.ts index 7775c46b39c..99174eb2bbd 100644 --- a/packages/cli/src/modules/sso-oidc/oidc.service.ee.ts +++ b/packages/cli/src/modules/sso-oidc/oidc.service.ee.ts @@ -22,8 +22,7 @@ import { inspect } from 'util'; import { BadRequestError, ForbiddenError } from '@n8n/errors'; import { buildOidcClaimsContext } from '@/modules/provisioning.ee/claims-context.builder'; import { ProvisioningService } from '@/modules/provisioning.ee/provisioning.service.ee'; -import { JwtService } from '@/services/jwt.service'; -import { UrlService } from '@n8n/backend-services'; +import { JwtService, UrlService } from '@n8n/backend-services'; import { assertAuthenticationMethodCanBeEnabled, getCurrentAuthenticationMethod, diff --git a/packages/cli/src/modules/token-exchange/services/__tests__/jti-cleanup.task.test.ts b/packages/cli/src/modules/token-exchange/services/__tests__/jti-cleanup.task.test.ts index c0f3085638e..a805c241a6e 100644 --- a/packages/cli/src/modules/token-exchange/services/__tests__/jti-cleanup.task.test.ts +++ b/packages/cli/src/modules/token-exchange/services/__tests__/jti-cleanup.task.test.ts @@ -25,8 +25,7 @@ describe('JtiCleanupTask', () => { it('should declare the configured cadence', () => { expect(task.name).toBe('jti-cleanup'); expect(task.schedule).toEqual({ kind: 'interval', intervalSeconds: 30 }); - expect(task.effects).toBe('idempotent'); - expect(task.placement).toEqual({ scope: 'cluster', durable: true }); + expect(task.target).toEqual({ scope: 'cluster', scheduler: { retryOnFailure: true } }); }); describe('run', () => { diff --git a/packages/cli/src/modules/token-exchange/services/__tests__/scoped-jwt.strategy.integration.test.ts b/packages/cli/src/modules/token-exchange/services/__tests__/scoped-jwt.strategy.integration.test.ts index 80ba88a6530..98556894165 100644 --- a/packages/cli/src/modules/token-exchange/services/__tests__/scoped-jwt.strategy.integration.test.ts +++ b/packages/cli/src/modules/token-exchange/services/__tests__/scoped-jwt.strategy.integration.test.ts @@ -5,7 +5,7 @@ import { Container } from '@n8n/di'; import type { InstanceSettings } from 'n8n-core'; import { mock } from 'vitest-mock-extended'; -import { JwtService } from '@/services/jwt.service'; +import { JwtService } from '@n8n/backend-services'; import { createMember, createOwner } from '@test-integration/db/users'; import { TOKEN_EXCHANGE_ISSUER } from '../../token-exchange.types'; @@ -128,5 +128,6 @@ describe('ScopedJwtStrategy (integration)', () => { expect(req.user.id).toBe(actor.id); expect(req.tokenGrant?.subject.id).toBe(subject.id); expect(req.tokenGrant?.actor?.id).toBe(actor.id); + expect(req.tokenGrant?.apiKeyId).toBeUndefined(); }); }); diff --git a/packages/cli/src/modules/token-exchange/services/__tests__/scoped-jwt.strategy.test.ts b/packages/cli/src/modules/token-exchange/services/__tests__/scoped-jwt.strategy.test.ts index 3cb0a509d7c..3b97b37163a 100644 --- a/packages/cli/src/modules/token-exchange/services/__tests__/scoped-jwt.strategy.test.ts +++ b/packages/cli/src/modules/token-exchange/services/__tests__/scoped-jwt.strategy.test.ts @@ -4,7 +4,7 @@ import type { InstanceSettings } from 'n8n-core'; import type { Mocked } from 'vitest'; import { mock } from 'vitest-mock-extended'; -import { JwtService } from '@/services/jwt.service'; +import { JwtService } from '@n8n/backend-services'; import { TOKEN_EXCHANGE_ISSUER, type IssuedJwtPayload } from '../../token-exchange.types'; import { ScopedJwtStrategy } from '../scoped-jwt.strategy'; diff --git a/packages/cli/src/modules/token-exchange/services/__tests__/token-exchange.service.test.ts b/packages/cli/src/modules/token-exchange/services/__tests__/token-exchange.service.test.ts index 3431ca7fed1..54ed9d31cc5 100644 --- a/packages/cli/src/modules/token-exchange/services/__tests__/token-exchange.service.test.ts +++ b/packages/cli/src/modules/token-exchange/services/__tests__/token-exchange.service.test.ts @@ -4,7 +4,7 @@ import jwt from 'jsonwebtoken'; import { mock } from 'vitest-mock-extended'; import { AuthError, BadRequestError } from '@n8n/errors'; -import type { JwtService } from '@/services/jwt.service'; +import type { JwtService } from '@n8n/backend-services'; import type { TokenExchangeConfig } from '../../token-exchange.config'; import type { ResolvedTrustedKey } from '../../token-exchange.schemas'; diff --git a/packages/cli/src/modules/token-exchange/services/__tests__/trusted-key-refresh.task.test.ts b/packages/cli/src/modules/token-exchange/services/__tests__/trusted-key-refresh.task.test.ts index 64f93785c91..929cc3c6dde 100644 --- a/packages/cli/src/modules/token-exchange/services/__tests__/trusted-key-refresh.task.test.ts +++ b/packages/cli/src/modules/token-exchange/services/__tests__/trusted-key-refresh.task.test.ts @@ -10,8 +10,7 @@ describe('TrustedKeyRefreshTask', () => { it('should declare a durable 60-second poll cadence', () => { expect(task.name).toBe('trusted-key-refresh'); expect(task.schedule).toEqual({ kind: 'interval', intervalSeconds: 60 }); - expect(task.effects).toBe('idempotent'); - expect(task.placement).toEqual({ scope: 'cluster', durable: true }); + expect(task.target).toEqual({ scope: 'cluster', scheduler: { retryOnFailure: true } }); }); it('should refresh the due sources on run', async () => { diff --git a/packages/cli/src/modules/token-exchange/services/jti-cleanup.task.ts b/packages/cli/src/modules/token-exchange/services/jti-cleanup.task.ts index da436609524..bf436313621 100644 --- a/packages/cli/src/modules/token-exchange/services/jti-cleanup.task.ts +++ b/packages/cli/src/modules/token-exchange/services/jti-cleanup.task.ts @@ -1,6 +1,6 @@ import { Logger } from '@n8n/backend-common'; -import { intervalFromSeconds, SystemTask } from '@n8n/decorators'; -import type { SystemTaskEffects, SystemTaskPlacement, SystemTaskSchedule } from '@n8n/decorators'; +import { clusterTarget, intervalFromSeconds, SystemTask } from '@n8n/decorators'; +import type { SystemTaskSchedule } from '@n8n/decorators'; import { TokenExchangeJtiRepository } from '../database/repositories/token-exchange-jti.repository'; import { TokenExchangeConfig } from '../token-exchange.config'; @@ -17,9 +17,7 @@ export class JtiCleanupTask implements SystemTask { this.config.jtiCleanupIntervalSeconds, ); - readonly effects: SystemTaskEffects = 'idempotent'; - - readonly placement: SystemTaskPlacement = { scope: 'cluster', durable: true }; + readonly target = clusterTarget({ scheduler: { retryOnFailure: true } }); private readonly logger: Logger; diff --git a/packages/cli/src/modules/token-exchange/services/scoped-jwt.strategy.ts b/packages/cli/src/modules/token-exchange/services/scoped-jwt.strategy.ts index 148b007b0c8..d8f9cd95d8f 100644 --- a/packages/cli/src/modules/token-exchange/services/scoped-jwt.strategy.ts +++ b/packages/cli/src/modules/token-exchange/services/scoped-jwt.strategy.ts @@ -5,7 +5,7 @@ import { getApiKeyScopesForRole } from '@n8n/permissions'; import { JsonWebTokenError, TokenExpiredError } from 'jsonwebtoken'; import type { AuthStrategy, AuthStrategyOptions } from '@/services/auth-strategy.types'; -import { JwtService } from '@/services/jwt.service'; +import { JwtService } from '@n8n/backend-services'; import { TOKEN_EXCHANGE_ISSUER, type IssuedJwtPayload } from '../token-exchange.types'; diff --git a/packages/cli/src/modules/token-exchange/services/token-exchange.service.ts b/packages/cli/src/modules/token-exchange/services/token-exchange.service.ts index 3489e7187ae..96a56a6fa0f 100644 --- a/packages/cli/src/modules/token-exchange/services/token-exchange.service.ts +++ b/packages/cli/src/modules/token-exchange/services/token-exchange.service.ts @@ -4,7 +4,7 @@ import { Service } from '@n8n/di'; import { randomUUID } from 'crypto'; import jwt from 'jsonwebtoken'; -import { JwtService } from '@/services/jwt.service'; +import { JwtService } from '@n8n/backend-services'; import { TokenExchangeConfig } from '../token-exchange.config'; import { TokenExchangeAuthError, TokenExchangeRequestError } from '../token-exchange.errors'; diff --git a/packages/cli/src/modules/token-exchange/services/trusted-key-refresh.task.ts b/packages/cli/src/modules/token-exchange/services/trusted-key-refresh.task.ts index fa046e5dd83..745e7575d46 100644 --- a/packages/cli/src/modules/token-exchange/services/trusted-key-refresh.task.ts +++ b/packages/cli/src/modules/token-exchange/services/trusted-key-refresh.task.ts @@ -1,5 +1,5 @@ -import { intervalFromSeconds, SystemTask } from '@n8n/decorators'; -import type { SystemTaskEffects, SystemTaskPlacement, SystemTaskSchedule } from '@n8n/decorators'; +import { clusterTarget, intervalFromSeconds, SystemTask } from '@n8n/decorators'; +import type { SystemTaskSchedule } from '@n8n/decorators'; import { TrustedKeyService } from './trusted-key.service'; @@ -16,9 +16,7 @@ export class TrustedKeyRefreshTask implements SystemTask { readonly schedule: SystemTaskSchedule = intervalFromSeconds(REFRESH_POLL_INTERVAL_SECONDS); - readonly effects: SystemTaskEffects = 'idempotent'; - - readonly placement: SystemTaskPlacement = { scope: 'cluster', durable: true }; + readonly target = clusterTarget({ scheduler: { retryOnFailure: true } }); constructor(private readonly trustedKeyService: TrustedKeyService) {} diff --git a/packages/cli/src/modules/type-availability-policies/README.md b/packages/cli/src/modules/type-availability-policies/README.md index 17613dad6dd..504a294aa6f 100644 --- a/packages/cli/src/modules/type-availability-policies/README.md +++ b/packages/cli/src/modules/type-availability-policies/README.md @@ -166,13 +166,24 @@ One violation per blocked type, deduplicated, in the order the types first appea "subject": "n8n-nodes-base.slack", "subjectType": "nodeType", "scope": "instance", - "matchedRuleId": "rule-7" + "matchedRuleId": "rule-7", + "projectId": "project-1", + "optInAvailable": false } ``` `matchedRuleId` is absent when the scope's default action decided and no rule matched. `scope` names the scope whose verdict decided, which is what a user needs to know who to ask. +`projectId` names the project whose policy was evaluated, also for an instance denial. A +sub-workflow is checked against its own project, so its refusal names that project, not the +caller's. It is absent when no project applied. A project denial's message says "a project +policy" and never names the project: the client resolves the name, and only for a project the +user can see. + +`optInAvailable` is `true` when the instance delegated the type, so the project can lift the +block with its own allow rule. It is always `false` when no project applied. + The violations reach the caller as HTTP 403 with `meta.violations`, and a blocked run stores them on the execution's error. Today that error is the whole story a user gets: the builder does not yet read `GET /projects/:projectId/available-types`, so a denied node looks normal diff --git a/packages/cli/src/modules/type-availability-policies/__tests__/credential-type-policy.check.test.ts b/packages/cli/src/modules/type-availability-policies/__tests__/credential-type-policy.check.test.ts index 267b3bb7eb7..deb30480056 100644 --- a/packages/cli/src/modules/type-availability-policies/__tests__/credential-type-policy.check.test.ts +++ b/packages/cli/src/modules/type-availability-policies/__tests__/credential-type-policy.check.test.ts @@ -651,6 +651,8 @@ describe('CredentialTypePolicyCheck', () => { subjectType: 'credentialType', scope: 'instance', matchedRuleId: 'rule-7', + projectId: 'project-1', + optInAvailable: false, }); expect(service.evaluateComposedTypesFor).toHaveBeenCalledWith( 'credential-types', @@ -716,11 +718,13 @@ describe('CredentialTypePolicyCheck', () => { expect(result.violations[0]).toStrictEqual({ kind: 'credential-type-unavailable', checkId: 'credential-type-availability', - message: `Credential type "${SLACK_API}" is blocked by this project's policy`, + message: `Credential type "${SLACK_API}" is blocked by a project policy`, subject: SLACK_API, subjectType: 'credentialType', scope: 'project', matchedRuleId: 'rule-3', + projectId: 'project-1', + optInAvailable: false, }); }); @@ -739,8 +743,54 @@ describe('CredentialTypePolicyCheck', () => { subject: SLACK_API, subjectType: 'credentialType', scope: 'instance', + projectId: 'project-1', + optInAvailable: false, }); }); + + it('carries the projectId from the context on a project-scope denial', async () => { + denying([SLACK_API], { scope: 'project' }); + + const result = await check.onWorkflowStart({ + workflow: workflow([node(SLACK_NODE, { [SLACK_API]: 'cred-1' })]), + projectId: 'project-1', + }); + + expect(result.violations[0].projectId).toBe('project-1'); + }); + + it('also carries the projectId on an instance-scope denial', async () => { + const result = await check.onWorkflowStart({ + workflow: workflow([node(SLACK_NODE, { [SLACK_API]: 'cred-1' })]), + projectId: 'project-1', + }); + + expect(result.violations[0].scope).toBe('instance'); + expect(result.violations[0].projectId).toBe('project-1'); + }); + + it('reports optInAvailable true when the verdict allows it and a project applies', async () => { + denying([SLACK_API], { optInAvailable: true }); + + const result = await check.onWorkflowStart({ + workflow: workflow([node(SLACK_NODE, { [SLACK_API]: 'cred-1' })]), + projectId: 'project-1', + }); + + expect(result.violations[0].optInAvailable).toBe(true); + }); + + it('drops projectId and forces optInAvailable false with no project, even when the verdict allows opt-in', async () => { + denying([SLACK_API], { optInAvailable: true }); + + const result = await check.onCredentialDecrypt({ + ...decryptOf(SLACK_API), + projectId: null, + }); + + expect(Object.keys(result.violations[0])).not.toContain('projectId'); + expect(result.violations[0].optInAvailable).toBe(false); + }); }); describe('when the store is not worth reading', () => { diff --git a/packages/cli/src/modules/type-availability-policies/__tests__/node-type-policy.check.test.ts b/packages/cli/src/modules/type-availability-policies/__tests__/node-type-policy.check.test.ts index e50b2972878..8cb9aa2511e 100644 --- a/packages/cli/src/modules/type-availability-policies/__tests__/node-type-policy.check.test.ts +++ b/packages/cli/src/modules/type-availability-policies/__tests__/node-type-policy.check.test.ts @@ -228,6 +228,8 @@ describe('NodeTypePolicyCheck', () => { subjectType: 'nodeType', scope: 'instance', matchedRuleId: 'rule-7', + projectId: 'project-1', + optInAvailable: false, }); expect(service.evaluateComposedTypesFor).toHaveBeenCalledWith('node-types', 'project-1', [ SLACK, @@ -297,11 +299,13 @@ describe('NodeTypePolicyCheck', () => { expect(result.violations[0]).toStrictEqual({ kind: 'node-type-unavailable', checkId: 'node-type-availability', - message: `Node type "${SLACK}" is blocked by this project's policy`, + message: `Node type "${SLACK}" is blocked by a project policy`, subject: SLACK, subjectType: 'nodeType', scope: 'project', matchedRuleId: 'rule-3', + projectId: 'project-1', + optInAvailable: false, }); }); @@ -320,8 +324,64 @@ describe('NodeTypePolicyCheck', () => { subject: SLACK, subjectType: 'nodeType', scope: 'instance', + projectId: 'project-1', + optInAvailable: false, }); }); + + it('carries the projectId from the context on a project-scope denial', async () => { + denying([SLACK], { scope: 'project' }); + + const result = await check.onWorkflowStart({ + workflow: workflow([node(SLACK)]), + projectId: 'project-1', + }); + + expect(result.violations[0].projectId).toBe('project-1'); + }); + + it('also carries the projectId on an instance-scope denial', async () => { + const result = await check.onWorkflowStart({ + workflow: workflow([node(SLACK)]), + projectId: 'project-1', + }); + + expect(result.violations[0].scope).toBe('instance'); + expect(result.violations[0].projectId).toBe('project-1'); + }); + + it('reports optInAvailable true when the verdict allows it and a project applies', async () => { + denying([SLACK], { optInAvailable: true }); + + const result = await check.onWorkflowStart({ + workflow: workflow([node(SLACK)]), + projectId: 'project-1', + }); + + expect(result.violations[0].optInAvailable).toBe(true); + }); + + it('drops projectId and forces optInAvailable false with no project, even when the verdict allows opt-in', async () => { + denying([SLACK], { optInAvailable: true }); + + const result = await check.onContentImport({ + workflow: workflow([node(SLACK)]), + projectId: null, + transport: 'cli', + }); + + expect(Object.keys(result.violations[0])).not.toContain('projectId'); + expect(result.violations[0].optInAvailable).toBe(false); + }); + + it('names the projectId of the workflow-start context, as when a sub-workflow is checked against its own project', async () => { + const result = await check.onWorkflowStart({ + workflow: workflow([node(SLACK)]), + projectId: 'sub-workflow-project', + }); + + expect(result.violations[0].projectId).toBe('sub-workflow-project'); + }); }); describe('when the store is not worth reading', () => { diff --git a/packages/cli/src/modules/type-availability-policies/__tests__/type-availability-policy.service.test.ts b/packages/cli/src/modules/type-availability-policies/__tests__/type-availability-policy.service.test.ts index 0ed8a9d2d2c..0b8252a6c30 100644 --- a/packages/cli/src/modules/type-availability-policies/__tests__/type-availability-policy.service.test.ts +++ b/packages/cli/src/modules/type-availability-policies/__tests__/type-availability-policy.service.test.ts @@ -686,6 +686,7 @@ describe('TypeAvailabilityPolicyService', () => { { policyId: 'p1', priority: 0, isFloor: false }, { policyId: 'p1', priority: 1, isFloor: false }, ], + 1, 'user-1', ), ).rejects.toThrow('Duplicate policyId'); @@ -703,6 +704,7 @@ describe('TypeAvailabilityPolicyService', () => { { policyId: 'p1', priority: 0, isFloor: false }, { policyId: 'p2', priority: 0, isFloor: false }, ], + 1, 'user-1', ), ).rejects.toThrow('Duplicate (isFloor, priority)'); @@ -718,6 +720,7 @@ describe('TypeAvailabilityPolicyService', () => { KIND, 'missing', [{ policyId: 'p1', priority: 0, isFloor: false }], + 1, 'user-1', ), ).rejects.toThrow(NotFoundError); @@ -731,7 +734,7 @@ describe('TypeAvailabilityPolicyService', () => { scopeRepository.findScopeByIdAndKind.mockResolvedValue(null); await expect( - service.replaceAttachments(CREDENTIAL_TYPES_KIND, 'scope-1', [], 'user-1'), + service.replaceAttachments(CREDENTIAL_TYPES_KIND, 'scope-1', [], 1, 'user-1'), ).rejects.toThrow(NotFoundError); expect(scopeRepository.findScopeByIdAndKind).toHaveBeenCalledWith( @@ -743,7 +746,24 @@ describe('TypeAvailabilityPolicyService', () => { expect(attachmentRepository.replaceAttachmentsForScope).not.toHaveBeenCalled(); }); - it('replaces attachments, bumps the version, and emits once', async () => { + it('throws ConflictError for a stale version and writes nothing', async () => { + const scope = makeScope({ version: 2 }); + scopeRepository.findScopeByIdAndKind.mockResolvedValueOnce(scope); + + const write = service.replaceAttachments(KIND, scope.id, [], 1, 'user-1'); + await expect(write).rejects.toThrow(ConflictError); + await expect(write).rejects.toThrow( + 'Policy scope has changed since it was last read (expected version 1, found 2)', + ); + + expect(scopeRepository.findScopeByIdAndKind).toHaveBeenCalledWith(scope.id, KIND, ROOT, true); + expect(attachmentRepository.replaceAttachmentsForScope).not.toHaveBeenCalled(); + expect(scopeRepository.bumpVersion).not.toHaveBeenCalled(); + expect(cacheService.deleteMany).not.toHaveBeenCalled(); + expect(eventService.emit).not.toHaveBeenCalled(); + }); + + it('replaces attachments with the current version, bumps the version, and emits once', async () => { const scope = makeScope({ version: 1 }); scopeRepository.findScopeByIdAndKind.mockResolvedValueOnce(scope); scopeRepository.findScopeById.mockResolvedValueOnce(makeScope({ version: 2 })); @@ -755,6 +775,7 @@ describe('TypeAvailabilityPolicyService', () => { KIND, scope.id, [{ policyId: 'p1', priority: 0, isFloor: false }], + scope.version, 'user-1', ); @@ -790,6 +811,7 @@ describe('TypeAvailabilityPolicyService', () => { KIND, scope.id, [{ policyId: 'p1', priority: 0, isFloor: false }], + scope.version, 'user-1', ); @@ -811,6 +833,7 @@ describe('TypeAvailabilityPolicyService', () => { { policyId: 'p1', priority: 0, isFloor: false }, { policyId: 'p2', priority: 1, isFloor: false }, ], + 1, 'user-1', ), ).rejects.toThrow(DELEGATE_RULE_AT_PROJECT_SCOPE); @@ -830,6 +853,7 @@ describe('TypeAvailabilityPolicyService', () => { KIND, 'scope-1', [{ policyId: 'p-delegating', priority: 0, isFloor: false }], + 1, 'user-1', ); diff --git a/packages/cli/src/modules/type-availability-policies/credential-type-policy-instance.controller.ts b/packages/cli/src/modules/type-availability-policies/credential-type-policy-instance.controller.ts index adf61020317..cd5f27da477 100644 --- a/packages/cli/src/modules/type-availability-policies/credential-type-policy-instance.controller.ts +++ b/packages/cli/src/modules/type-availability-policies/credential-type-policy-instance.controller.ts @@ -156,6 +156,7 @@ export class CredentialTypePolicyInstanceController { CREDENTIAL_TYPES_KIND, scopeId, dto.attachments, + dto.version, req.user.id, ); } diff --git a/packages/cli/src/modules/type-availability-policies/credential-type-policy.check.ts b/packages/cli/src/modules/type-availability-policies/credential-type-policy.check.ts index 58904f01559..a43a33fec4e 100644 --- a/packages/cli/src/modules/type-availability-policies/credential-type-policy.check.ts +++ b/packages/cli/src/modules/type-availability-policies/credential-type-policy.check.ts @@ -7,7 +7,6 @@ import type { CredentialTransferContext, PolicedWorkflow, PolicyCheckResult, - PolicyViolation, RegisteredPolicyCheck, WorkflowPublishContext, WorkflowSaveContext, @@ -21,10 +20,8 @@ import { getActiveCredentialTypes } from 'n8n-workflow'; import { NodeTypes } from '@/node-types'; import { CREDENTIAL_TYPES_KIND } from './constants'; -import { - TypeAvailabilityPolicyService, - type ComposedTypeVerdict, -} from './type-availability-policy.service'; +import { TypeAvailabilityPolicyService } from './type-availability-policy.service'; +import { CREDENTIAL_TYPE_SUBJECT, toTypeViolation } from './type-violation'; const NO_VIOLATIONS: PolicyCheckResult = { violations: [] }; @@ -33,21 +30,6 @@ const NOTHING_GRANDFATHERED: ReadonlySet = new Set(); const CREDENTIAL_TYPE_PARAMETERS = ['nodeCredentialType', 'genericAuthType'] as const; -function toViolation(checkId: string, verdict: ComposedTypeVerdict): PolicyViolation { - const by = verdict.scope === 'instance' ? 'an instance policy' : "this project's policy"; - - return { - kind: 'credential-type-unavailable', - checkId, - message: `Credential type "${verdict.name}" is blocked by ${by}`, - subject: verdict.name, - subjectType: 'credentialType', - scope: verdict.scope, - // The scope's default action decided when no rule matched, and there is no id to report. - ...(verdict.matchedRuleId !== null && { matchedRuleId: verdict.matchedRuleId }), - }; -} - /** * Enforces credential type availability policies, at every point that handles a workflow and * at both points that handle a credential. @@ -241,7 +223,7 @@ export class CredentialTypePolicyCheck implements RegisteredPolicyCheck { return { violations: verdicts .filter((verdict) => verdict.action === 'deny') - .map((verdict) => toViolation(this.id, verdict)), + .map((verdict) => toTypeViolation(this.id, CREDENTIAL_TYPE_SUBJECT, verdict, projectId)), // Reported even when nothing is denied: the audit line records what a partial run read. policyVersions: versions, }; diff --git a/packages/cli/src/modules/type-availability-policies/node-type-policy.check.ts b/packages/cli/src/modules/type-availability-policies/node-type-policy.check.ts index 9fc0ea9f502..5734804df5e 100644 --- a/packages/cli/src/modules/type-availability-policies/node-type-policy.check.ts +++ b/packages/cli/src/modules/type-availability-policies/node-type-policy.check.ts @@ -5,7 +5,6 @@ import type { CredentialDecryptContext, PolicedWorkflow, PolicyCheckResult, - PolicyViolation, RegisteredPolicyCheck, WorkflowPublishContext, WorkflowSaveContext, @@ -15,10 +14,8 @@ import type { import { PolicyCheck } from '@n8n/decorators'; import { NODE_TYPES_KIND } from './constants'; -import { - TypeAvailabilityPolicyService, - type ComposedTypeVerdict, -} from './type-availability-policy.service'; +import { TypeAvailabilityPolicyService } from './type-availability-policy.service'; +import { NODE_TYPE_SUBJECT, toTypeViolation } from './type-violation'; const NO_VIOLATIONS: PolicyCheckResult = { violations: [] }; @@ -30,21 +27,6 @@ function distinctTypes(nodes: PolicedWorkflow['nodes']): string[] { return [...new Set(nodes.map((node) => node.type))]; } -function toViolation(checkId: string, verdict: ComposedTypeVerdict): PolicyViolation { - const by = verdict.scope === 'instance' ? 'an instance policy' : "this project's policy"; - - return { - kind: 'node-type-unavailable', - checkId, - message: `Node type "${verdict.name}" is blocked by ${by}`, - subject: verdict.name, - subjectType: 'nodeType', - scope: verdict.scope, - // The scope's default action decided when no rule matched, and there is no id to report. - ...(verdict.matchedRuleId !== null && { matchedRuleId: verdict.matchedRuleId }), - }; -} - /** * Enforces node type availability policies at every point that handles a workflow. * @@ -157,7 +139,7 @@ export class NodeTypePolicyCheck implements RegisteredPolicyCheck { return { violations: verdicts .filter((verdict) => verdict.action === 'deny') - .map((verdict) => toViolation(this.id, verdict)), + .map((verdict) => toTypeViolation(this.id, NODE_TYPE_SUBJECT, verdict, projectId)), // Reported even when nothing is denied: the audit line records what a partial run read. policyVersions: versions, }; diff --git a/packages/cli/src/modules/type-availability-policies/type-availability-policy-instance.controller.ts b/packages/cli/src/modules/type-availability-policies/type-availability-policy-instance.controller.ts index ebba89e2517..32c27af3da6 100644 --- a/packages/cli/src/modules/type-availability-policies/type-availability-policy-instance.controller.ts +++ b/packages/cli/src/modules/type-availability-policies/type-availability-policy-instance.controller.ts @@ -156,6 +156,7 @@ export class TypeAvailabilityPolicyInstanceController { NODE_TYPES_KIND, scopeId, dto.attachments, + dto.version, req.user.id, ); } diff --git a/packages/cli/src/modules/type-availability-policies/type-availability-policy.service.ts b/packages/cli/src/modules/type-availability-policies/type-availability-policy.service.ts index 94d30d716be..bae30f94d28 100644 --- a/packages/cli/src/modules/type-availability-policies/type-availability-policy.service.ts +++ b/packages/cli/src/modules/type-availability-policies/type-availability-policy.service.ts @@ -688,19 +688,16 @@ export class TypeAvailabilityPolicyService { * `nodeTypePolicy:manage`) must not reach a scope of a different kind by id, even with an * empty or same-kind-only attachment list that `assertAttachableToScope` would not catch. * - * No `expectedVersion` check: the real `ReplaceAttachmentsDto` from IAM-1328 carries no - * version field (unlike `PutInstancePolicyDto`), so this endpoint is last-write-wins. The - * write still runs in one transaction with the scope's version bump, so a concurrent - * reader never observes the attachments changed without the version moving. + * `expectedVersion` must match the scope's current version. The locked read, attachment + * replacement, and version bump share one transaction. * - * The scope is still locked up front — not for a version check, but so this path takes - * the scope before it touches any policy row (the attachment inserts key-share the - * policies), the same scope → policy order every other write path uses. + * Lock the scope before any policy row to keep the scope → policy order used by other writes. */ async replaceAttachments( kind: string, scopeId: string, attachments: readonly AttachmentInput[], + expectedVersion: number, updatedBy: string, ): Promise<{ attachments: readonly PolicyAttachment[]; version: number }> { assertNoDuplicateAttachmentSlots(attachments); @@ -711,6 +708,12 @@ export class TypeAvailabilityPolicyService { throw new NotFoundError(`Policy scope not found: ${scopeId}`); } + if (scope.version !== expectedVersion) { + throw new ConflictError( + `Policy scope has changed since it was last read (expected version ${expectedVersion}, found ${scope.version})`, + ); + } + // Attaching a document to a project scope makes its rules that project's policy, so // a document carrying `delegate` is rejected the same way a direct project write is. // The documents are read under the same row lock `updatePolicyDocument` takes, so a diff --git a/packages/cli/src/modules/type-availability-policies/type-violation.ts b/packages/cli/src/modules/type-availability-policies/type-violation.ts new file mode 100644 index 00000000000..4231a6e5620 --- /dev/null +++ b/packages/cli/src/modules/type-availability-policies/type-violation.ts @@ -0,0 +1,46 @@ +import type { PolicyViolation } from '@n8n/decorators'; + +import type { ComposedTypeVerdict } from './type-availability-policy.service'; + +/** How one policy kind names what it blocked. */ +export type TypeViolationSubject = { + readonly kind: string; + readonly subjectType: string; + readonly label: string; +}; + +export const NODE_TYPE_SUBJECT: TypeViolationSubject = { + kind: 'node-type-unavailable', + subjectType: 'nodeType', + label: 'Node type', +}; + +export const CREDENTIAL_TYPE_SUBJECT: TypeViolationSubject = { + kind: 'credential-type-unavailable', + subjectType: 'credentialType', + label: 'Credential type', +}; + +/** The message stays neutral about which project: the client names it from `projectId`. */ +export function toTypeViolation( + checkId: string, + subject: TypeViolationSubject, + verdict: ComposedTypeVerdict, + projectId: string | null, +): PolicyViolation { + const by = verdict.scope === 'instance' ? 'an instance policy' : 'a project policy'; + + return { + kind: subject.kind, + checkId, + message: `${subject.label} "${verdict.name}" is blocked by ${by}`, + subject: verdict.name, + subjectType: subject.subjectType, + scope: verdict.scope, + // The scope's default action decided when no rule matched, and there is no id to report. + ...(verdict.matchedRuleId !== null && { matchedRuleId: verdict.matchedRuleId }), + ...(projectId !== null && { projectId }), + // With no project there is nowhere to opt in, whatever the instance delegated. + optInAvailable: projectId !== null && verdict.optInAvailable, + }; +} diff --git a/packages/cli/src/node-execution/__tests__/ephemeral-node-executor.test.ts b/packages/cli/src/node-execution/__tests__/ephemeral-node-executor.test.ts index add50eb08a7..db465c8c6aa 100644 --- a/packages/cli/src/node-execution/__tests__/ephemeral-node-executor.test.ts +++ b/packages/cli/src/node-execution/__tests__/ephemeral-node-executor.test.ts @@ -498,6 +498,7 @@ describe('EphemeralNodeExecutor', () => { expect(result.status).toBe('error'); expect(result.error).toBe('upstream 500'); + expect(result).not.toHaveProperty('violations'); }, ); @@ -662,6 +663,7 @@ describe('EphemeralNodeExecutor', () => { expect(result.status).toBe('error'); expect(result.error).toBe('upstream 500'); + expect(result).not.toHaveProperty('violations'); }, ); @@ -771,13 +773,14 @@ describe('EphemeralNodeExecutor', () => { ); }); - it('returns a tool error and never runs a blocked node', async () => { + it("returns a tool error carrying the refusal's violations, and never runs a blocked node", async () => { const execute = vi.fn(); nodeTypes.getByNameAndVersion.mockReturnValue({ description: toolDescription, execute, } as unknown as INodeType); - policyEnforcementService.enforceWorkflowStart.mockRejectedValueOnce(blocked()); + const refusal = blocked(); + policyEnforcementService.enforceWorkflowStart.mockRejectedValueOnce(refusal); const result = await executor.executeInline({ nodeType: 'n8n-nodes-base.dateTimeTool', @@ -791,16 +794,18 @@ describe('EphemeralNodeExecutor', () => { status: 'error', data: [], error: expect.stringContaining('is blocked by an instance policy'), + violations: refusal.violations, }); expect(execute).not.toHaveBeenCalled(); }); - it('never runs supplyData for a blocked native tool node', async () => { + it("never runs supplyData for a blocked native tool node, and carries the refusal's violations", async () => { const supplyData = vi.fn(); nodeTypes.getByNameAndVersion.mockReturnValue( mockNodeType({ description: toolDescription, supplyData }), ); - policyEnforcementService.enforceWorkflowStart.mockRejectedValueOnce(blocked()); + const refusal = blocked(); + policyEnforcementService.enforceWorkflowStart.mockRejectedValueOnce(refusal); const result = await executor.executeInline({ nodeType: '@n8n/n8n-nodes-langchain.toolWikipedia', @@ -811,6 +816,7 @@ describe('EphemeralNodeExecutor', () => { }); expect(result.status).toBe('error'); + expect(result.violations).toEqual(refusal.violations); expect(supplyData).not.toHaveBeenCalled(); }); diff --git a/packages/cli/src/node-execution/ephemeral-node-executor.ts b/packages/cli/src/node-execution/ephemeral-node-executor.ts index b4c4475fc02..de041eee786 100644 --- a/packages/cli/src/node-execution/ephemeral-node-executor.ts +++ b/packages/cli/src/node-execution/ephemeral-node-executor.ts @@ -28,6 +28,7 @@ import { v4 as uuid } from 'uuid'; import { NodeTypes } from '@/node-types'; import { PolicyEnforcementService } from '@/policy/policy-enforcement.service'; +import { findPolicyViolations, type NonEmptyViolations } from '@/policy/policy-violation.error'; import { withExpressionIsolate } from '@/utils'; import { getBase } from '@/workflow-execute-additional-data'; @@ -71,6 +72,23 @@ export interface NodeExecutionResult { status: 'success' | 'error'; data: INodeExecutionData[]; error?: string; + /** Set when a policy refused the run. */ + violations?: NonEmptyViolations; +} + +type SupplyDataToolOutcome = + | { ok: true; value: T } + | { ok: false; error: string; violations?: NonEmptyViolations }; + +/** The `{ status: 'error' }` result for a caught error, keeping a refusal's violations. */ +function errorResult(error: unknown): NodeExecutionResult { + const violations = findPolicyViolations(error); + return { + status: 'error', + data: [], + error: getErrorMessage(error), + ...(violations && { violations }), + }; } /** @@ -392,9 +410,9 @@ export class EphemeralNodeExecutor { ); return executionResult; } catch (error) { - const message = getErrorMessage(error); - this.logger.debug('Node execution failed', { nodeType: tool.nodeType, error: message }); - return { status: 'error', data: [], error: message }; + const result = errorResult(error); + this.logger.debug('Node execution failed', { nodeType: tool.nodeType, error: result.error }); + return result; } } @@ -514,7 +532,7 @@ export class EphemeralNodeExecutor { tool: EphemeralWorkflowToolLike, inputItems: INodeExecutionData[], onTool: (response: LangChainToolType | StructuredToolkit) => Promise | T, - ): Promise<{ ok: true; value: T } | { ok: false; error: string }> { + ): Promise> { const closeFunctions: CloseFunction[] = []; try { @@ -560,8 +578,8 @@ export class EphemeralNodeExecutor { }; }); } catch (error) { - const message = getErrorMessage(error); - return { ok: false, error: message }; + const violations = findPolicyViolations(error); + return { ok: false, error: getErrorMessage(error), ...(violations && { violations }) }; } finally { for (const closeFunction of closeFunctions) { try { @@ -611,7 +629,12 @@ export class EphemeralNodeExecutor { nodeType: tool.nodeType, error: result.error, }); - return { status: 'error', data: [], error: result.error }; + return { + status: 'error', + data: [], + error: result.error, + ...(result.violations && { violations: result.violations }), + }; } return { diff --git a/packages/cli/src/output-schema-parameter-defaults.ts b/packages/cli/src/output-schema-parameter-defaults.ts new file mode 100644 index 00000000000..9d79acf4091 --- /dev/null +++ b/packages/cli/src/output-schema-parameter-defaults.ts @@ -0,0 +1,38 @@ +import type { INodeProperties, NodeParameterValueType } from 'n8n-workflow'; + +interface SchemaContext { + resource?: string; + operation?: string; +} + +/** A property whose `displayOptions.show` lists other values than ours is not shown. */ +function isShownFor(property: INodeProperties, context: SchemaContext): boolean { + const show = property.displayOptions?.show; + if (!show) return true; + + return (['resource', 'operation'] as const).every((key) => { + const shownValues = show[key]; + const value = context[key]; + return !Array.isArray(shownValues) || value === undefined || shownValues.includes(value); + }); +} + +/** + * Defaults of the parameters that apply to one resource/operation, so a + * parameter missing from a saved node can still pick its schema variant. + * The first matching property wins when a name repeats per operation. + */ +export function getParameterDefaults( + properties: INodeProperties[] | undefined, + context: SchemaContext, +): Record { + // A Map keeps names such as `constructor` and `__proto__` as plain keys. + const defaults = new Map(); + + for (const property of properties ?? []) { + if (defaults.has(property.name) || !isShownFor(property, context)) continue; + defaults.set(property.name, property.default); + } + + return Object.fromEntries(defaults); +} diff --git a/packages/cli/src/policy/__tests__/policy-violation.error.test.ts b/packages/cli/src/policy/__tests__/policy-violation.error.test.ts index ce3099a48ae..96cd822d4fe 100644 --- a/packages/cli/src/policy/__tests__/policy-violation.error.test.ts +++ b/packages/cli/src/policy/__tests__/policy-violation.error.test.ts @@ -1,10 +1,13 @@ import type { PolicyViolation } from '@n8n/decorators'; -import { UserError } from 'n8n-workflow'; +import { NodeOperationError, UserError } from 'n8n-workflow'; +import type { INode } from 'n8n-workflow'; +import { mock } from 'vitest-mock-extended'; import { classifyRestError, RestErrorKind } from '@n8n/backend-services'; import { serializeInternalRestError } from '@n8n/backend-services'; import { + findPolicyViolations, isPolicyRefusal, PolicyViolationError, type NonEmptyViolations, @@ -122,4 +125,42 @@ describe('PolicyViolationError', () => { expect(isPolicyRefusal(value)).toBe(false); }); }); + + describe('findPolicyViolations', () => { + function wrapWithCauses(innermost: Error, wrapperCount: number): Error { + let current = innermost; + for (let i = 0; i < wrapperCount; i++) { + current = new Error(`wrapper ${i}`, { cause: current }); + } + return current; + } + + const violations: NonEmptyViolations = [violation()]; + + it('returns the violations of a direct refusal', () => { + expect(findPolicyViolations(new PolicyViolationError(violations))).toEqual(violations); + }); + + it('returns the violations of a refusal a node error wraps', () => { + const nodeError = new NodeOperationError(mock(), new PolicyViolationError(violations)); + + expect(findPolicyViolations(nodeError)).toEqual(violations); + }); + + it('walks at most five errors down the cause chain', () => { + const refusal = new PolicyViolationError(violations); + + expect(findPolicyViolations(wrapWithCauses(refusal, 4))).toEqual(violations); + expect(findPolicyViolations(wrapWithCauses(refusal, 5))).toBeUndefined(); + }); + + it.each([ + ['a plain error chain', wrapWithCauses(new Error('root cause'), 3)], + ['a plain object', { violations }], + ['a string', 'boom'], + ['undefined', undefined], + ])('returns undefined for %s', (_label, value) => { + expect(findPolicyViolations(value)).toBeUndefined(); + }); + }); }); diff --git a/packages/cli/src/policy/policy-violation.error.ts b/packages/cli/src/policy/policy-violation.error.ts index 59df5d96c73..3421e75e218 100644 --- a/packages/cli/src/policy/policy-violation.error.ts +++ b/packages/cli/src/policy/policy-violation.error.ts @@ -63,3 +63,18 @@ export class PolicyViolationError extends UserError { export function isPolicyRefusal(error: unknown): boolean { return error instanceof PolicyViolationError || hasPolicyRefusalMarker(error); } + +/** Bounds the `cause` walk, so a cyclic chain cannot loop. */ +const MAX_CAUSE_DEPTH = 5; + +/** The violations of a refusal, also when a node error wraps it as its `cause`. */ +export function findPolicyViolations(error: unknown): NonEmptyViolations | undefined { + let current = error; + for (let depth = 0; depth < MAX_CAUSE_DEPTH && current instanceof Error; depth++) { + if (current instanceof PolicyViolationError && hasViolations(current.violations)) { + return current.violations; + } + current = current.cause; + } + return undefined; +} diff --git a/packages/cli/src/public-api/__tests__/public-api-controller.registry.test.ts b/packages/cli/src/public-api/__tests__/public-api-controller.registry.test.ts index 482fdb674dd..57c315d97df 100644 --- a/packages/cli/src/public-api/__tests__/public-api-controller.registry.test.ts +++ b/packages/cli/src/public-api/__tests__/public-api-controller.registry.test.ts @@ -75,6 +75,103 @@ describe('PublicApiControllerRegistry', () => { Container.set(ControllerRegistryMetadata, new ControllerRegistryMetadata()); }); + it('answers 405 for a known path that no controller serves with the method', async () => { + @Service() + class WidgetsPublicController { + @Get('/') + @ApiResponse(200) + method() { + return { ok: true }; + } + } + markPublicApiController(WidgetsPublicController as Controller, '/widgets'); + + const app = activate(); + + await request(app).put('/api/v1/widgets').expect(405, { message: 'PUT method not allowed' }); + await request(app).get('/api/v1/widgets').expect(200, { ok: true }); + }); + + it('answers 405 for a nested path with an ID that no controller serves with the method', async () => { + @Service() + class PartsPublicController { + @Get('/') + @ApiResponse(200) + method() { + return { ok: true }; + } + } + markPublicApiController(PartsPublicController as Controller, '/widgets/:widgetId/parts'); + + const app = activate(); + + await request(app) + .put('/api/v1/widgets/w-1/parts') + .expect(405, { message: 'PUT method not allowed' }); + await request(app).get('/api/v1/widgets/w-1/parts').expect(200, { ok: true }); + }); + + it('lists every method the path serves in the Allow header of its 405 response', async () => { + @Service() + class WidgetsPublicController { + @Get('/') + @ApiResponse(200) + list() { + return { ok: true }; + } + + @Post('/') + @ApiResponse(201) + create() { + return { ok: true }; + } + } + markPublicApiController(WidgetsPublicController as Controller, '/widgets'); + + await request(activate()).put('/api/v1/widgets').expect(405).expect('Allow', 'GET, POST'); + }); + + it('lists the methods of every route template that matches the URL in Allow', async () => { + @Service() + class WidgetsPublicController { + @Get('/:widgetId/:versionId') + @ApiResponse(200) + version() { + return { ok: true }; + } + + @Post('/:widgetId/archive') + @ApiResponse(200) + archive() { + return { ok: true }; + } + } + markPublicApiController(WidgetsPublicController as Controller, '/widgets'); + + await request(activate()) + .put('/api/v1/widgets/w-1/archive') + .expect(405) + .expect('Allow', 'GET, POST'); + }); + + it('rejects HEAD with 405 without running the GET handler, and omits HEAD from Allow', async () => { + const handler = vi.fn(() => ({ ok: true })); + + @Service() + class WidgetsPublicController { + @Get('/') + @ApiResponse(200) + method() { + return handler(); + } + } + markPublicApiController(WidgetsPublicController as Controller, '/widgets'); + + await request(activate()).head('/api/v1/widgets').expect(405).expect('Allow', 'GET'); + await request(activate()).head('/api/v1/WIDGETS').expect(405).expect('Allow', 'GET'); + expect(handler).not.toHaveBeenCalled(); + }); + it('emits the Deprecation header for a route marked @Deprecated', async () => { const since = new Date('2026-07-23T00:00:00Z'); diff --git a/packages/cli/src/public-api/__tests__/public-api-route-resolver.test.ts b/packages/cli/src/public-api/__tests__/public-api-route-resolver.test.ts index 65ca0a7b1f9..7beaf679370 100644 --- a/packages/cli/src/public-api/__tests__/public-api-route-resolver.test.ts +++ b/packages/cli/src/public-api/__tests__/public-api-route-resolver.test.ts @@ -31,7 +31,6 @@ import { apiKeyScopesSatisfy, resolvePublicApiRoutes, resolveRouteArgs, - scopeRequirementFromString, scopeRequirementToString, scopesInRequirement, } from '../public-api-route-resolver'; @@ -215,29 +214,6 @@ describe('public-api-route-resolver', () => { }); }); - describe('scopeRequirementFromString', () => { - it('returns a plain scope for a single entry', () => { - expect(scopeRequirementFromString('tag:list')).toBe('tag:list'); - }); - - it('reads a comma-joined eov scope string as anyOf', () => { - expect(scopeRequirementFromString('project:export,workflow:export')).toEqual({ - anyOf: ['project:export', 'workflow:export'], - }); - }); - - it('tolerates surrounding whitespace', () => { - expect(scopeRequirementFromString('project:export, workflow:export')).toEqual({ - anyOf: ['project:export', 'workflow:export'], - }); - }); - - it('round-trips through scopeRequirementToString', () => { - const serialized = 'project:export,workflow:export'; - expect(scopeRequirementToString(scopeRequirementFromString(serialized))).toBe(serialized); - }); - }); - describe('scopesInRequirement', () => { it('enumerates every scope regardless of any/all semantics', () => { expect(scopesInRequirement('tag:list')).toEqual(['tag:list']); diff --git a/packages/cli/src/public-api/idempotency-key-cleanup.task.ts b/packages/cli/src/public-api/idempotency-key-cleanup.task.ts index 55f5da2ed09..603eb1da394 100644 --- a/packages/cli/src/public-api/idempotency-key-cleanup.task.ts +++ b/packages/cli/src/public-api/idempotency-key-cleanup.task.ts @@ -1,8 +1,8 @@ import { Logger } from '@n8n/backend-common'; import { Time } from '@n8n/constants'; import { IDEMPOTENCY_KEY_TTL_MS } from '@n8n/db'; -import { intervalFromSeconds, SystemTask } from '@n8n/decorators'; -import type { SystemTaskEffects, SystemTaskPlacement, SystemTaskSchedule } from '@n8n/decorators'; +import { intervalFromSeconds, leaderTimerTarget, SystemTask } from '@n8n/decorators'; +import type { SystemTaskSchedule } from '@n8n/decorators'; import { IdempotencyKeyService } from '@/public-api/idempotency-key.service'; @@ -12,13 +12,8 @@ export class IdempotencyKeyCleanupTask implements SystemTask { readonly schedule: SystemTaskSchedule = intervalFromSeconds(Time.hours.toSeconds); - readonly effects: SystemTaskEffects = 'idempotent'; - - readonly placement: SystemTaskPlacement = { - scope: 'cluster', - durable: false, - runOnTakeover: true, - }; + // oxlint-disable-next-line typescript/no-deprecated -- not yet moved to the durable scheduler + readonly target = leaderTimerTarget({ runOnTakeover: true }); constructor( private readonly logger: Logger, diff --git a/packages/cli/src/public-api/index.ts b/packages/cli/src/public-api/index.ts index 1d28abb0109..8117598aed9 100644 --- a/packages/cli/src/public-api/index.ts +++ b/packages/cli/src/public-api/index.ts @@ -1,23 +1,16 @@ -import { Logger } from '@n8n/backend-common'; -import { EventService, UrlService } from '@n8n/backend-services'; +import { UrlService } from '@n8n/backend-services'; import { GlobalConfig } from '@n8n/config'; -import type { AuthenticatedRequest } from '@n8n/db'; import { Container } from '@n8n/di'; import type { Router, ErrorRequestHandler, RequestHandler } from 'express'; import express from 'express'; import fs from 'fs/promises'; -import { UnexpectedError } from 'n8n-workflow'; import path from 'path'; import type { JsonObject } from 'swagger-ui-express'; -import validator from 'validator'; import { PublicApiControllerRegistry } from './public-api-controller.registry'; import { sendPublicApiErrorResponse } from './v1/public-api-error-response'; -import { AUTH_COOKIE_NAME } from '@/constants'; import { License } from '@/license'; -import { AuthStrategyRegistry } from '@/services/auth-strategy.registry'; -import { LastActiveAtService } from '@/services/last-active-at.service'; import './v1/controllers'; @@ -122,221 +115,15 @@ function createLazySwaggerMiddleware( }; } -// Minimal shapes of the express-openapi-validator resolver arguments we depend on. -interface EovRoute { - basePath: string; - expressRoute: string; - openApiRoute: string; - method: string; -} -interface EovOperation { - operationId?: string; - // eslint-disable-next-line @typescript-eslint/naming-convention -- OpenAPI vendor extension keys - 'x-eov-operation-id'?: string; - // eslint-disable-next-line @typescript-eslint/naming-convention -- OpenAPI vendor extension keys - 'x-eov-operation-handler'?: string; -} -interface EovApiDoc { - paths?: Record>; -} - -/** - * Test-only express-openapi-validator operation-handler resolver. It is wired in **only** under - * Vitest (see `operationHandlers` below); production and e2e keep a sync `require()` resolver - * so runtime behaviour stays on Node's CJS loader. - * - * Why it's needed in tests: eov's default resolver `require()`s each handler module, but under - * Vitest only the `.ts` handler sources exist on disk (no `.js`) and they're served by Vite, not - * Node's `require` — so `require()` throws and every route 500s. - * - * Both resolvers return a no-op when `x-eov-operation-handler` is absent — those routes are - * owned by `@PublicApiController` (mounted before eov). - */ -async function importOperationHandlerResolver( - handlersPath: string, - routeArg: unknown, - apiDocArg: unknown, -): Promise { - return resolveOperationHandler(handlersPath, routeArg, apiDocArg, 'import'); -} - -function requireOperationHandlerResolver( - handlersPath: string, - routeArg: unknown, - apiDocArg: unknown, -): unknown { - return resolveOperationHandler(handlersPath, routeArg, apiDocArg, 'require'); -} - -function controllerOwnedNoopHandler() { - return [ - (_req: unknown, _res: unknown, next: (error?: unknown) => void) => { - next(); - }, - ]; -} - -function resolveOperationHandler( - handlersPath: string, - routeArg: unknown, - apiDocArg: unknown, - loader: 'import' | 'require', -): unknown | Promise { - const route = routeArg as EovRoute; - const apiDoc = apiDocArg as EovApiDoc; - const pathKey = route.openApiRoute.substring(route.basePath.length); - const operation = apiDoc.paths?.[pathKey]?.[route.method.toLowerCase()]; - const operationId = operation?.['x-eov-operation-id'] ?? operation?.operationId; - const handlerModule = operation?.['x-eov-operation-handler']; - - if (!handlerModule) { - return controllerOwnedNoopHandler(); - } - - if (!operationId) { - throw new UnexpectedError(`Missing operation id for [${route.method}] ${route.expressRoute}`); - } - - const modulePath = path.join(handlersPath, handlerModule); - - if (loader === 'require') { - // eslint-disable-next-line @typescript-eslint/no-require-imports - const imported = require(modulePath) as Record & { - default?: Record; - }; - const handler = imported[operationId] ?? imported.default?.[operationId] ?? imported.default; - if (!handler) { - throw new UnexpectedError( - `Could not find handler '${operationId}' in module '${modulePath}'`, - ); - } - return handler; - } - - return (async () => { - const imported = (await import(/* @vite-ignore */ modulePath)) as Record & { - default?: Record; - }; - const handler = imported[operationId] ?? imported.default?.[operationId] ?? imported.default; - if (!handler) { - throw new UnexpectedError( - `Could not find handler '${operationId}' in module '${modulePath}'`, - ); - } - return handler; - })(); -} - function createPublicControllerMiddleware(version: string): RequestHandler { const router = express.Router({ mergeParams: true }); Container.get(PublicApiControllerRegistry).activate(router, version); return router; } -function createLazyValidatorMiddleware( - openApiSpecPath: string, - handlersDirectory: string, - version: string, -): RequestHandler { - let cachedRouter: Router | undefined; - let initPromise: Promise | undefined; - - return async (req, res, next) => { - if (!cachedRouter) { - initPromise ??= (async () => { - const { middleware: openApiValidatorMiddleware } = await import( - 'express-openapi-validator' - ); - - const authStrategyRegistry = Container.get(AuthStrategyRegistry); - const eventService = Container.get(EventService); - const lastActiveAtService = Container.get(LastActiveAtService); - const logger = Container.get(Logger); - - const authenticate = async (req: AuthenticatedRequest) => { - const authenticated = await authStrategyRegistry.authenticate(req); - - if (authenticated) { - lastActiveAtService.updateLastActiveIfStale(req.user.id).catch((error: unknown) => { - logger.error('Failed to update last active timestamp', { error }); - }); - eventService.emit('public-api-invoked', { - userId: req.user.id, - path: req.path, - method: req.method, - apiVersion: version, - userAgent: req.headers['user-agent'], - }); - } - - return authenticated; - }; - - const router = express.Router(); - router.use( - openApiValidatorMiddleware({ - apiSpec: openApiSpecPath, - // Production/e2e use eov's default resolver (synchronous `require`). Under Vitest, - // where handler modules are `.ts` served by Vite, swap in an `import()`-based - // resolver so route handlers can load. See `importOperationHandlerResolver`. - operationHandlers: { - basePath: handlersDirectory, - resolver: process.env.VITEST - ? importOperationHandlerResolver - : requireOperationHandlerResolver, - }, - validateRequests: true, - validateApiSpec: true, - fileUploader: false, - formats: { - email: { - type: 'string', - validate: (email: string) => validator.isEmail(email), - }, - identifier: { - type: 'string', - validate: (identifier: string) => - validator.isUUID(identifier) || validator.isEmail(identifier), - }, - jsonString: { - validate: (data: string) => { - try { - JSON.parse(data); - return true; - } catch (e) { - return false; - } - }, - }, - nanoid: { - type: 'string', - validate: (id: string) => { - return /^[A-Za-z0-9]{16}$/.test(id); - }, - }, - }, - validateSecurity: { - handlers: { - ApiKeyAuth: authenticate, - BearerAuth: authenticate, - CookieAuth: authenticate, - }, - }, - }), - ); - return router; - })(); - cachedRouter = await initPromise; - } - - void cachedRouter(req, res, next); - }; -} - function createApiRouter( version: string, openApiSpecPath: string, - handlersDirectory: string, publicApiEndpoint: string, ): Router { const globalConfig = Container.get(GlobalConfig); @@ -368,23 +155,26 @@ function createApiRouter( next(error); }; + // No route matched: the path is not part of the public API. + const notFoundHandler: RequestHandler = (_req, res) => { + res.status(404).json({ message: 'not found' }); + }; + apiController.use( `/${publicApiEndpoint}/${version}`, express.json({ limit: payloadLimit }), jsonParseErrorHandler, createPublicControllerMiddleware(version), - createLazyValidatorMiddleware(openApiSpecPath, handlersDirectory, version), + notFoundHandler, ); const publicApiErrorHandler: ErrorRequestHandler = ( error: Error, - req: express.Request, + _req: express.Request, res: express.Response, _next: express.NextFunction, ) => { - sendPublicApiErrorResponse(res, error, { - hasSessionCookie: Boolean(req.cookies?.[AUTH_COOKIE_NAME]), - }); + sendPublicApiErrorResponse(res, error); }; apiController.use(publicApiErrorHandler); @@ -400,7 +190,7 @@ export const loadPublicApiVersions = async ( const apiRouters = versions.map((version) => { const openApiPath = path.join(__dirname, version, 'openapi.yml'); - return createApiRouter(version, openApiPath, __dirname, publicApiEndpoint); + return createApiRouter(version, openApiPath, publicApiEndpoint); }); const version = versions.pop()?.charAt(1); diff --git a/packages/cli/src/public-api/media-types/content-type.ts b/packages/cli/src/public-api/media-types/content-type.ts index 10162bb1045..b33fedc8b69 100644 --- a/packages/cli/src/public-api/media-types/content-type.ts +++ b/packages/cli/src/public-api/media-types/content-type.ts @@ -10,8 +10,8 @@ function readMediaType(header: string): { mediaType: string; reported: string } const mediaType = rawMediaType.trim().toLowerCase(); const parameters = new Map(); - // Parameter sorting and returning of the reported string is kept only for parity with the - // EOV handler — we may be able to remove and simplify this method in future. + // Sorts the parameters and rebuilds the reported string, so the reported media type stays + // unchanged. This method may be simplified in future. for (const part of parameterParts) { const separator = part.indexOf('='); if (separator === -1) { diff --git a/packages/cli/src/public-api/media-types/request-body/multipart-parser.ts b/packages/cli/src/public-api/media-types/request-body/multipart-parser.ts index 02f4b2775ba..4bcb4cffa80 100644 --- a/packages/cli/src/public-api/media-types/request-body/multipart-parser.ts +++ b/packages/cli/src/public-api/media-types/request-body/multipart-parser.ts @@ -2,8 +2,7 @@ import type { MultipartUploadLimits } from '@n8n/decorators'; import type { RequestHandler } from 'express'; /** - * Builds the multer middleware that parses a `multipart/form-data` body, mirroring - * express-openapi-validator's `fileUploader`. + * Builds the multer middleware that parses a `multipart/form-data` body. */ export async function loadMultipartParser(limits: MultipartUploadLimits): Promise { const { default: multer } = await import('multer'); diff --git a/packages/cli/src/public-api/media-types/request-body/multipart.request-body.ts b/packages/cli/src/public-api/media-types/request-body/multipart.request-body.ts index 5ba23c812ef..4dccdb7a2a5 100644 --- a/packages/cli/src/public-api/media-types/request-body/multipart.request-body.ts +++ b/packages/cli/src/public-api/media-types/request-body/multipart.request-body.ts @@ -13,7 +13,7 @@ import { formatValidationError } from '@/public-api/public-api-validation-error' import { loadMultipartParser } from './multipart-parser'; import type { RequestBodyHandler } from './types'; -// Same regexes express-openapi-validator 5.5.3 used in legacy EOV handlers. +// Multer error codes and messages that map to public API statuses. const PAYLOAD_TOO_BIG_CODE = /LIMIT_(FILE|PART)_(SIZE|COUNT)/; const UNEXPECTED_FILE_CODE = /LIMIT_UNEXPECTED_FILE/; const MISSING_BOUNDARY = /Multipart: Boundary not found/i; @@ -23,7 +23,7 @@ function isMulterError(error: unknown): error is MulterError { } /** - * Maps a multer parsing error to a serializable public API error matching the legacy EOV handlers. + * Maps a multer parsing error to a serializable public API error. */ export function toPublicApiError(error: unknown): Error { if (isMulterError(error)) { diff --git a/packages/cli/src/public-api/public-api-controller.registry.ts b/packages/cli/src/public-api/public-api-controller.registry.ts index 5006c18c633..1f4ba238807 100644 --- a/packages/cli/src/public-api/public-api-controller.registry.ts +++ b/packages/cli/src/public-api/public-api-controller.registry.ts @@ -8,6 +8,7 @@ import type { AccessScope, ApiKeyScopeRequirement, Controller, + DeprecationInfo, RequestBodyMedia, } from '@n8n/decorators'; import { Container, Service } from '@n8n/di'; @@ -30,11 +31,11 @@ import { findBodyArg, findValidatedParamArgs, isRequestBodyRequired, + resolvePublicApiRoutes, resolveRouteArgs, resolveSuccessStatus, } from '@/public-api/public-api-route-resolver'; import { formatValidationError } from '@/public-api/public-api-validation-error'; -import { deprecated } from '@/public-api/v1/shared/middlewares/global.middleware'; import { sendPublicApiErrorResponse } from '@/public-api/v1/public-api-error-response'; import { AuthStrategyRegistry } from '@/services/auth-strategy.registry'; import { LastActiveAtService } from '@/services/last-active-at.service'; @@ -49,6 +50,24 @@ function parsePathParam(key: string, schema: ZodTypeAny, params: Request['params return output.data[key]; } +/** + * Whether an Express route template (`/widgets/:widgetId`) matches a request path. A `:param` + * segment matches any single segment. Any other segment must be equal. + */ +function matchesPathTemplate(template: string, path: string): boolean { + const templateSegments = template.split('/'); + const pathSegments = (path.length > 1 && path.endsWith('/') ? path.slice(0, -1) : path).split( + '/', + ); + return ( + templateSegments.length === pathSegments.length && + templateSegments.every( + (segment, i) => + segment.startsWith(':') || segment.toLowerCase() === pathSegments[i].toLowerCase(), + ) + ); +} + // Match the legacy version-less route. req.path drops the prefix, req.baseUrl adds /api/v1 function routePath(prefix: string, req: Request): string { const path = (prefix === '/' ? '' : prefix) + req.path; @@ -65,11 +84,57 @@ export class PublicApiControllerRegistry { ) {} activate(router: Router, apiVersion: string) { + const methodsByTemplate = new Map(); + for (const route of resolvePublicApiRoutes()) { + const methods = methodsByTemplate.get(route.path) ?? []; + methods.push(route.method.toUpperCase()); + methodsByTemplate.set(route.path, methods); + } + + // A URL can match several templates, for example `/:id/archive` and `/:id/:versionId`. + // Allow lists the methods of every template that matches this URL. + const allowedMethodsFor = (path: string): string[] => { + const allowed = new Set(); + for (const [template, methods] of methodsByTemplate) { + if (!matchesPathTemplate(template, path)) { + continue; + } + for (const method of methods) { + allowed.add(method); + } + } + return [...allowed]; + }; + + // HEAD is not supported. Express would otherwise run the GET handler for it. + router.use((req, res, next) => { + if (req.method !== 'HEAD') { + return next(); + } + + const allowed = allowedMethodsFor(req.path); + if (allowed.length === 0) { + return next(); + } + + res.set('Allow', allowed.join(', ')); + res.status(405).json({ message: 'HEAD method not allowed' }); + }); + for (const controllerClass of this.metadata.controllerClasses) { const metadata = this.metadata.getControllerMetadata(controllerClass); if (!metadata.isPublicApi) continue; this.activateController(router, controllerClass, apiVersion); } + + // A known path with a method no controller serves. + // Registered after every controller, so it only runs when no route matched. + for (const path of methodsByTemplate.keys()) { + router.all(path, (req, res) => { + res.set('Allow', allowedMethodsFor(req.path).join(', ')); + res.status(405).json({ message: `${req.method} method not allowed` }); + }); + } } private activateController(parent: Router, controllerClass: Controller, apiVersion: string) { @@ -150,7 +215,7 @@ export class PublicApiControllerRegistry { const middlewares: RequestHandler[] = []; if (route.deprecated) { - middlewares.push(deprecated(route.deprecated)); + middlewares.push(this.createDeprecationMiddleware(route.deprecated)); } middlewares.push(this.createAuthMiddleware(apiVersion, prefix)); @@ -232,6 +297,19 @@ export class PublicApiControllerRegistry { }; } + /** + * Sets the RFC 9745 `Deprecation` header. The wire format (`@`) is built here, so + * call sites pass a `Date`. `since` is fixed per route, so the header is the same on every request. + */ + private createDeprecationMiddleware({ since }: DeprecationInfo): RequestHandler { + const deprecation = `@${Math.floor(since.getTime() / 1000)}`; + + return (_req, res, next) => { + res.setHeader('Deprecation', deprecation); + next(); + }; + } + private createApiKeyScopeMiddleware(requirement: ApiKeyScopeRequirement): RequestHandler { return (req, res, next) => { const { tokenGrant } = req as AuthenticatedRequest; diff --git a/packages/cli/src/public-api/public-api-route-resolver.ts b/packages/cli/src/public-api/public-api-route-resolver.ts index 3de183b4ab4..b0f4504d743 100644 --- a/packages/cli/src/public-api/public-api-route-resolver.ts +++ b/packages/cli/src/public-api/public-api-route-resolver.ts @@ -24,18 +24,6 @@ import { REQUEST_BODY_HANDLERS, } from '@/public-api/media-types/request-body'; -export const HTTP_METHODS = [ - 'get', - 'post', - 'put', - 'patch', - 'delete', - 'options', - 'head', - 'trace', -] as const; -export type HttpMethod = (typeof HTTP_METHODS)[number]; - export type ParamArg = { type: 'param'; key: string; schema?: ZodTypeAny }; export type BodyArg = { type: 'body'; @@ -218,25 +206,8 @@ export function scopesInRequirement(requirement: ApiKeyScopeRequirement): readon } /** - * Parses the comma-joined `x-required-scope` form back into a requirement. Legacy eov routes tag - * their middleware with a flat string (see `publicApiCompositeScope`), which doesn't record whether - * the scopes are any/all - the one composite route today defers the choice to the handler based on - * the request payload, so a caller holding any listed scope can use it. `anyOf` matches that. - */ -export function scopeRequirementFromString(serialized: string): ApiKeyScopeRequirement { - const scopes = serialized - .split(',') - .map((scope) => scope.trim()) - .filter(Boolean) as ApiKeyScope[]; - - return scopes.length === 1 ? scopes[0] : { anyOf: scopes }; -} - -/** - * Renders an `ApiKeyScopeRequirement` as the flat, comma-joined string the hand-written - * `x-required-scope` YAML convention already uses (see `scope-parity.test.ts`'s `requiredScope` - * parsing) — `anyOf`/`allOf` semantics aren't distinguished there today, so this doesn't invent a - * new format, just matches the existing one. + * Renders an `ApiKeyScopeRequirement` as the flat, comma-joined string of the spec's + * `x-required-scope`. The string does not show if the scopes are `anyOf` or `allOf`. */ export function scopeRequirementToString(requirement: ApiKeyScopeRequirement): string { if (typeof requirement === 'string') { diff --git a/packages/cli/src/public-api/types.ts b/packages/cli/src/public-api/types.ts index dfef73a7f85..4a8696b8ddb 100644 --- a/packages/cli/src/public-api/types.ts +++ b/packages/cli/src/public-api/types.ts @@ -1,59 +1,3 @@ -import type { - UpdateOtelSettingsDto, - TestOtelTraceDto, - UpdateSamlConfigurationDto, -} from '@n8n/api-types'; -import type { AuthenticatedRequest } from '@n8n/db'; - -import type { AuthlessRequest } from '@/requests'; - -export type PaginatedRequest = AuthenticatedRequest< - {}, - {}, - {}, - { - limit?: number; - cursor?: string; - offset?: number; - lastId?: string; - } ->; -export declare namespace UserRequest { - export type Invite = AuthenticatedRequest<{}, {}, Array<{ email: string }>>; - - export type ResolveSignUp = AuthlessRequest< - {}, - {}, - {}, - { inviterId?: string; inviteeId?: string } - >; - - export type SignUp = AuthenticatedRequest< - { id: string }, - { inviterId?: string; inviteeId?: string } - >; - - export type Delete = AuthenticatedRequest< - { id: string; email: string }, - {}, - {}, - { transferId?: string; includeRole: boolean } - >; - - export type Reinvite = AuthenticatedRequest<{ id: string }>; - - export type Update = AuthlessRequest< - { id: string }, - {}, - { - inviterId: string; - firstName: string; - lastName: string; - password: string; - } - >; -} - type PaginationBase = { limit: number }; export type PaginationOffsetDecoded = PaginationBase & { offset: number }; @@ -63,7 +7,8 @@ export type PaginationCursorDecoded = PaginationBase & { lastId: string }; export type OffsetPagination = PaginationBase & { offset: number; numberOfTotalRecords: number }; export type CursorPagination = PaginationBase & { lastId: string; numberOfNextRecords: number }; -export interface IRequired { + +interface IRequired { required?: string[]; } export interface IDependency { @@ -78,32 +23,3 @@ export interface IJsonSchema { allOf?: IDependency[]; required: string[]; } - -// ---------------------------------- -// /community-packages -// ---------------------------------- - -export declare namespace CommunityPackageRequest { - type Install = AuthenticatedRequest<{}, {}, { name: string; version?: string }>; - type List = AuthenticatedRequest; - type Update = AuthenticatedRequest<{ name: string }, {}, { version?: string }>; - type Uninstall = AuthenticatedRequest<{ name: string }>; -} - -// ---------------------------------- -// /settings/otel -// ---------------------------------- - -export declare namespace OtelSettingsRequest { - type Update = AuthenticatedRequest<{}, {}, UpdateOtelSettingsDto>; - type Test = AuthenticatedRequest<{}, {}, TestOtelTraceDto>; -} - -// ---------------------------------- -// /settings/sso/saml -// ---------------------------------- - -export declare namespace SsoSamlRequest { - type Get = AuthenticatedRequest; - type Update = AuthenticatedRequest<{}, {}, UpdateSamlConfigurationDto>; -} diff --git a/packages/cli/src/public-api/v1/__tests__/global.middleware.test.ts b/packages/cli/src/public-api/v1/__tests__/global.middleware.test.ts deleted file mode 100644 index 7c1ca6444d6..00000000000 --- a/packages/cli/src/public-api/v1/__tests__/global.middleware.test.ts +++ /dev/null @@ -1,114 +0,0 @@ -import type { AuthenticatedRequest, TokenGrant, User } from '@n8n/db'; -import type { ApiKeyScope } from '@n8n/permissions'; -import type { NextFunction, Response } from 'express'; -import type { Mocked, MockedFunction } from 'vitest'; -import { mock, mockDeep } from 'vitest-mock-extended'; - -import * as middlewares from '../shared/middlewares/global.middleware'; - -function buildReq(tokenGrant?: TokenGrant): AuthenticatedRequest { - return { headers: {}, query: {}, params: {}, tokenGrant } as unknown as AuthenticatedRequest; -} - -describe('publicApiScope', () => { - let res: Mocked; - let next: MockedFunction; - - beforeEach(() => { - res = mockDeep(); - res.status.mockReturnThis(); - res.json.mockReturnThis(); - next = vi.fn() as MockedFunction; - }); - - it('tags the returned middleware with the provided scope', () => { - const mw = middlewares.publicApiScope('credential:create' as ApiKeyScope); - expect(mw.__apiKeyScope).toBe('credential:create'); - }); - - it('returns 403 when tokenGrant is absent', async () => { - await middlewares.publicApiScope('workflow:read' as ApiKeyScope)( - buildReq(undefined) as any, - res, - next, - ); - expect(next).not.toHaveBeenCalled(); - expect(res.status).toHaveBeenCalledWith(403); - expect(res.json).toHaveBeenCalledWith({ message: 'Forbidden' }); - }); - - it('calls next() when the required scope is present in tokenGrant.apiKeyScopes', async () => { - const grant: TokenGrant = { - scopes: [], - apiKeyScopes: ['workflow:read'], - subject: mock(), - }; - await middlewares.publicApiScope('workflow:read' as ApiKeyScope)( - buildReq(grant) as any, - res, - next, - ); - expect(next).toHaveBeenCalled(); - }); - - it('returns 403 when the required scope is not in tokenGrant.apiKeyScopes', async () => { - const grant: TokenGrant = { - scopes: ['workflow:create'], - apiKeyScopes: ['workflow:read'], - subject: mock(), - }; - await middlewares.publicApiScope('workflow:create' as ApiKeyScope)( - buildReq(grant) as any, - res, - next, - ); - expect(next).not.toHaveBeenCalled(); - expect(res.status).toHaveBeenCalledWith(403); - expect(res.json).toHaveBeenCalledWith({ message: 'Forbidden' }); - }); - - it('returns 403 when tokenGrant.apiKeyScopes is empty', async () => { - const grant: TokenGrant = { - scopes: ['workflow:read'], - apiKeyScopes: [], - subject: mock(), - }; - await middlewares.publicApiScope('workflow:read' as ApiKeyScope)( - buildReq(grant) as any, - res, - next, - ); - expect(next).not.toHaveBeenCalled(); - expect(res.status).toHaveBeenCalledWith(403); - expect(res.json).toHaveBeenCalledWith({ message: 'Forbidden' }); - }); - - it('returns 403 when apiKeyScopes is absent even if scopes contains the required scope', async () => { - const grant: TokenGrant = { scopes: ['workflow:read'], subject: mock() }; - await middlewares.publicApiScope('workflow:read' as ApiKeyScope)( - buildReq(grant) as any, - res, - next, - ); - expect(next).not.toHaveBeenCalled(); - expect(res.status).toHaveBeenCalledWith(403); - expect(res.json).toHaveBeenCalledWith({ message: 'Forbidden' }); - }); -}); - -describe('apiKeyHasScopeWithGlobalScopeFallback', () => { - it('returns tagged middleware with the scope from { scope } config', () => { - const mw = middlewares.apiKeyHasScopeWithGlobalScopeFallback({ - scope: 'credential:create' as any, - }); - expect(mw.__apiKeyScope).toBe('credential:create'); - }); - - it('returns tagged middleware with the apiKeyScope from { apiKeyScope, globalScope } config', () => { - const mw = middlewares.apiKeyHasScopeWithGlobalScopeFallback({ - apiKeyScope: 'credential:create' as any, - globalScope: 'credential:create' as any, - }); - expect(mw.__apiKeyScope).toBe('credential:create'); - }); -}); diff --git a/packages/cli/src/public-api/v1/__tests__/public-api-error-response.test.ts b/packages/cli/src/public-api/v1/__tests__/public-api-error-response.test.ts index 48f7fbe9591..032866da93e 100644 --- a/packages/cli/src/public-api/v1/__tests__/public-api-error-response.test.ts +++ b/packages/cli/src/public-api/v1/__tests__/public-api-error-response.test.ts @@ -1,5 +1,4 @@ import type { Response } from 'express'; -import { BadRequest, Unauthorized } from 'express-openapi-validator/dist/framework/types'; import { UnexpectedError, UserError, OperationalError } from 'n8n-workflow'; import { BadRequestError, ConflictError, NotFoundError } from '@n8n/errors'; @@ -86,25 +85,6 @@ describe('sendPublicApiErrorResponse', () => { expect(res._payload.body).toEqual({ message: 'Internal server error' }); }); - it('maps express-openapi-validator HttpError using status', () => { - const res = createMockRes(); - const err = new BadRequest({ path: '/x', message: 'schema failed' }); - sendPublicApiErrorResponse(res, err); - expect(res._payload.statusCode).toBe(400); - expect(res._payload.body).toEqual({ message: 'schema failed' }); - }); - - it('forwards classifier context so session-cookie Unauthorized is serialized as a generic 401', () => { - const res = createMockRes(); - const err = new Unauthorized({ - path: '/api/v1/insights/summary', - message: "'X-N8N-API-KEY' header required", - }); - sendPublicApiErrorResponse(res, err, { hasSessionCookie: true }); - expect(res._payload.statusCode).toBe(401); - expect(res._payload.body).toEqual({ message: 'Unauthorized' }); - }); - it('maps unknown errors to 500 with a generic message', () => { const res = createMockRes(); sendPublicApiErrorResponse(res, new Error('plain')); diff --git a/packages/cli/src/public-api/v1/__tests__/public-api-scope-lookup.test.ts b/packages/cli/src/public-api/v1/__tests__/public-api-scope-lookup.test.ts deleted file mode 100644 index d80352bb3b6..00000000000 --- a/packages/cli/src/public-api/v1/__tests__/public-api-scope-lookup.test.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { publicApiRouteKey } from '../shared/public-api-scope-lookup'; - -describe('publicApiRouteKey', () => { - test.each([ - ['GET', '/workflows/{id}/history', 'get /workflows/{}/history'], - ['GET', '/workflows/:workflowId/history', 'get /workflows/{}/history'], - ['Post', '/tags/', 'post /tags'], - ['get', '/', 'get /'], - ['GET', '', 'get /'], - ['PATCH', '/workflows//{id}//versions', 'patch /workflows/{}/versions'], - ])('normalizes %s %s', (method, pathStr, expected) => { - expect(publicApiRouteKey(method, pathStr)).toBe(expected); - }); - - test('OpenAPI and Express param styles produce the same key', () => { - expect(publicApiRouteKey('GET', '/workflows/{id}/history')).toBe( - publicApiRouteKey('GET', '/workflows/:workflowId/history'), - ); - }); -}); diff --git a/packages/cli/src/public-api/v1/__tests__/scope-parity.test.ts b/packages/cli/src/public-api/v1/__tests__/scope-parity.test.ts index 7f2d36463f3..1c4a1701df6 100644 --- a/packages/cli/src/public-api/v1/__tests__/scope-parity.test.ts +++ b/packages/cli/src/public-api/v1/__tests__/scope-parity.test.ts @@ -1,22 +1,9 @@ -import RefParser from '@apidevtools/json-schema-ref-parser'; -import { API_KEY_RESOURCES, type ApiKeyScope } from '@n8n/permissions'; +import { API_KEY_RESOURCES } from '@n8n/permissions'; import fs from 'node:fs'; import path from 'node:path'; import yaml from 'yaml'; -import { - HTTP_METHODS, - type HttpMethod, - resolvePublicApiRoutes, - scopeRequirementToString, - toOpenApiPathTemplate, -} from '../../public-api-route-resolver'; -import { - extractScopeFromEovHandlerChain, - loadPublicControllerScopeMap, - publicApiRouteKey, - resolvePublicApiImplementedScope, -} from '../shared/public-api-scope-lookup'; +import { resolvePublicApiRoutes, scopesInRequirement } from '../../public-api-route-resolver'; import '../controllers'; @@ -25,101 +12,7 @@ vi.unmock('node:fs'); const PUBLIC_API_ROOT = path.resolve(__dirname, '..', '..'); const OPENAPI_SPEC_PATH = path.join(PUBLIC_API_ROOT, 'v1', 'openapi.yml'); -type Operation = { - pathStr: string; - method: HttpMethod; - operationId: string; - handlerPath: string | null; - requiredScope: string | null; -}; - -type RawOperation = { - operationId?: string; - 'x-eov-operation-id'?: string; - 'x-eov-operation-handler'?: string; - 'x-required-scope'?: string; - 'x-decorator-routed'?: boolean; -}; - -async function loadEovOperations(): Promise { - const spec = await RefParser.dereference(OPENAPI_SPEC_PATH); - const paths = (spec as { paths?: Record> }).paths ?? {}; - const ops: Operation[] = []; - for (const [pathStr, methods] of Object.entries(paths)) { - for (const method of HTTP_METHODS) { - const op = methods[method]; - if (!op) continue; - if (op['x-decorator-routed'] === true) continue; - - const operationId = op['x-eov-operation-id'] ?? op.operationId; - if (!operationId) { - throw new Error( - `Missing operationId / x-eov-operation-id for ${method.toUpperCase()} ${pathStr}`, - ); - } - - ops.push({ - pathStr, - method, - operationId, - handlerPath: op['x-eov-operation-handler'] ?? null, - requiredScope: op['x-required-scope'] ?? null, - }); - } - } - return ops; -} - -function loadDecoratorOperations(): Operation[] { - return resolvePublicApiRoutes().map((route) => ({ - pathStr: toOpenApiPathTemplate(route.path), - method: route.method, - operationId: route.handlerName, - handlerPath: null, - requiredScope: route.apiKeyScope ? scopeRequirementToString(route.apiKeyScope) : 'none', - })); -} - -async function loadOperations(): Promise { - return [...(await loadEovOperations()), ...loadDecoratorOperations()]; -} - -async function loadEovHandlerScope( - handlerPath: string, - operationId: string, -): Promise { - const resolved = path.join(PUBLIC_API_ROOT, `${handlerPath}.ts`); - // Vitest can't `require()` a `.ts` handler (its `export =` form fails Node's - // strip-only loader); import it and unwrap the CJS-interop default. - const imported = (await import(resolved)) as { - default?: Record; - } & Record; - const mod = imported.default ?? imported; - const middlewares = mod[operationId]; - if (!Array.isArray(middlewares)) return undefined; - return extractScopeFromEovHandlerChain(middlewares); -} - -/** Compare scopes as an unordered set so `a,b`, `b,a`, and `a, b` all match. */ -function normalizeScopeSet(scope: string | undefined): string { - if (!scope) return ''; - return scope - .split(',') - .map((s) => s.trim()) - .filter(Boolean) - .sort() - .join(','); -} - describe('Public API scope parity', () => { - let ops: Operation[]; - let controllerScopes: Map; - - beforeAll(async () => { - ops = await loadOperations(); - controllerScopes = loadPublicControllerScopeMap(); - }); - test('openapi.yml tags are sorted alphabetically by name', () => { const spec = yaml.parse(fs.readFileSync(OPENAPI_SPEC_PATH, 'utf8')) as { tags?: Array<{ name: string }>; @@ -129,58 +22,11 @@ describe('Public API scope parity', () => { expect(tagNames).toEqual(sorted); }); - test('every operation declares x-required-scope', () => { - const missing = ops.filter((op) => op.requiredScope === null); - expect(missing.map((m) => `${m.method.toUpperCase()} ${m.pathStr}`)).toEqual([]); - }); - - test('every x-required-scope matches eov handler or @PublicApiController @ApiKeyScope', async () => { - const mismatches: string[] = []; - for (const op of ops) { - if (op.requiredScope === null) continue; - - // A route must be defined by the eov handler XOR a @PublicApiController, - // never both — otherwise the enforced scope is ambiguous. - if ( - op.handlerPath !== null && - controllerScopes.has(publicApiRouteKey(op.method, op.pathStr)) - ) { - throw new Error( - `${op.method.toUpperCase()} ${op.pathStr} is defined by both an eov handler and a @PublicApiController. ` + - 'Remove the eov handler (its `x-eov-operation-handler` in the OpenAPI spec and the handler middleware) and keep the @PublicApiController.', - ); - } - - const eovHandlerScope = - op.handlerPath !== null - ? await loadEovHandlerScope(op.handlerPath, op.operationId) - : undefined; - - const implemented = resolvePublicApiImplementedScope( - controllerScopes, - op.method, - op.pathStr, - eovHandlerScope, - ); - - const expected = op.requiredScope === 'none' ? undefined : op.requiredScope; - if (normalizeScopeSet(implemented) !== normalizeScopeSet(expected)) { - mismatches.push( - `${op.method.toUpperCase()} ${op.pathStr}: YAML says "${op.requiredScope}", implemented scope is "${ - implemented ?? 'none' - }"`, - ); - } - } - expect(mismatches).toEqual([]); - }, 30_000); - test('every API key scope in API_KEY_RESOURCES is consumed by at least one endpoint', () => { - const consumed = new Set( - ops.flatMap((op) => { - if (op.requiredScope === null || op.requiredScope === 'none') return []; - return op.requiredScope.split(',').map((scope) => scope.trim()); - }), + const consumed = new Set( + resolvePublicApiRoutes().flatMap((route) => + route.apiKeyScope ? scopesInRequirement(route.apiKeyScope) : [], + ), ); const declared = new Set(); for (const [resource, operations] of Object.entries(API_KEY_RESOURCES)) { diff --git a/packages/cli/src/public-api/v1/controllers/__tests__/n8n-packages.public.controller.test.ts b/packages/cli/src/public-api/v1/controllers/__tests__/n8n-packages.public.controller.test.ts new file mode 100644 index 00000000000..88a772e2ef7 --- /dev/null +++ b/packages/cli/src/public-api/v1/controllers/__tests__/n8n-packages.public.controller.test.ts @@ -0,0 +1,438 @@ +import { ExportPackageRequestDto } from '@n8n/api-types'; +import type { EventService } from '@n8n/backend-services'; +import type { AuthenticatedRequest } from '@n8n/db'; +import { BadRequestError, ForbiddenError, NotFoundError } from '@n8n/errors'; +import type { Response } from 'express'; +import { UserError } from 'n8n-workflow'; +import { Readable } from 'node:stream'; +import { mock } from 'vitest-mock-extended'; + +import type { RelayEventMap } from '@/events/maps/relay.event-map'; +import { + PackageEntityAccessDeniedError, + PackageEntityNotFoundError, + PackageExportBlockedError, +} from '@/modules/n8n-packages/entities/package-export.errors'; +import type { N8nPackagesService } from '@/modules/n8n-packages/n8n-packages.service'; + +import { N8nPackagesPublicController } from '../n8n-packages.public.controller'; + +const EXPORT_COUNTS = { + agents: 0, + workflows: 2, + folders: 1, + credentials: 0, + dataTables: 0, + variables: 0, + tags: 0, +}; + +const DEFAULT_SERVICE_OPTIONS = { + user: { id: 'user-1' }, + agentIds: [], + workflowIds: [], + folderIds: [], + projectIds: [], + includeVariableValues: true, + canExportVariableValues: false, + includeTags: true, + dependencyPolicy: 'fail', + versionPolicy: 'latest', + credentialExportPolicy: 'expression-values-only', + includeArchivedWorkflows: false, +}; + +describe('N8nPackagesPublicController', () => { + let controller: N8nPackagesPublicController; + const mockService = mock(); + const mockEventService = mock(); + + function makeRequest(apiKeyScopes?: string[]) { + return { + user: { id: 'user-1' }, + tokenGrant: apiKeyScopes ? { apiKeyScopes } : undefined, + } as unknown as AuthenticatedRequest; + } + + function mockExportStream() { + mockService.exportPackage.mockResolvedValue({ + stream: Readable.from([Buffer.from('package-bytes')]), + counts: EXPORT_COUNTS, + }); + } + + async function runAndCatch( + body: Record, + apiKeyScopes?: string[], + res: Response = mock(), + ) { + try { + await controller.exportPackage( + makeRequest(apiKeyScopes), + res, + ExportPackageRequestDto.parse(body), + ); + return undefined; + } catch (error) { + return error; + } + } + + function emittedEvent(name: 'n8n-package-export-failed' | 'n8n-package-import-failed') { + const call = mockEventService.emit.mock.calls.find(([eventName]) => eventName === name); + return call?.[1] as RelayEventMap[typeof name] | undefined; + } + + beforeEach(() => { + vi.clearAllMocks(); + mockService.exportPackage.mockReset(); + controller = new N8nPackagesPublicController(mockService, mockEventService); + }); + + describe('exportPackage', () => { + it('throws BadRequestError when both workflowIds and projectIds are provided', async () => { + const caught = await runAndCatch({ workflowIds: ['wf-1'], projectIds: ['project-1'] }, [ + 'workflow:export', + 'project:export', + ]); + + expect(caught).toBeInstanceOf(BadRequestError); + expect(caught).toMatchObject({ + message: 'Provide either agentIds/workflowIds/folderIds or projectIds, not both', + }); + expect(mockService.exportPackage).not.toHaveBeenCalled(); + }); + + it('throws BadRequestError when folderIds and projectIds are both provided', async () => { + const caught = await runAndCatch({ folderIds: ['fld-1'], projectIds: ['project-1'] }, [ + 'workflow:export', + 'project:export', + ]); + + expect(caught).toBeInstanceOf(BadRequestError); + expect(caught).toMatchObject({ + message: 'Provide either agentIds/workflowIds/folderIds or projectIds, not both', + }); + expect(mockService.exportPackage).not.toHaveBeenCalled(); + }); + + it('throws BadRequestError when neither workflowIds, folderIds nor projectIds are provided', async () => { + const caught = await runAndCatch({}, ['workflow:export']); + + expect(caught).toBeInstanceOf(BadRequestError); + expect(caught).toMatchObject({ + message: 'At least one agentId, workflowId, folderId, or projectId is required', + }); + expect(mockService.exportPackage).not.toHaveBeenCalled(); + }); + + it('throws ForbiddenError when the API key carries no scopes', async () => { + const caught = await runAndCatch({ workflowIds: ['wf-1'] }); + + expect(caught).toBeInstanceOf(ForbiddenError); + expect(mockService.exportPackage).not.toHaveBeenCalled(); + expect(emittedEvent('n8n-package-export-failed')).toMatchObject({ + reason: 'access-denied', + workflowIds: ['wf-1'], + }); + }); + + it('throws ForbiddenError when exporting workflows without workflow:export scope', async () => { + const caught = await runAndCatch({ workflowIds: ['wf-1'] }, ['project:export']); + + expect(caught).toBeInstanceOf(ForbiddenError); + expect(mockService.exportPackage).not.toHaveBeenCalled(); + }); + + it('throws ForbiddenError when exporting projects without project:export scope', async () => { + const caught = await runAndCatch({ projectIds: ['project-1'] }, ['workflow:export']); + + expect(caught).toBeInstanceOf(ForbiddenError); + expect(mockService.exportPackage).not.toHaveBeenCalled(); + }); + + it('throws ForbiddenError when exporting folders without workflow:export scope', async () => { + const caught = await runAndCatch({ folderIds: ['fld-1'] }, ['project:export']); + + expect(caught).toBeInstanceOf(ForbiddenError); + expect(mockService.exportPackage).not.toHaveBeenCalled(); + }); + + it('does not reject upfront without variable:list scope; forwards canExportVariableValues=false for the service to enforce', async () => { + mockExportStream(); + + const caught = await runAndCatch({ workflowIds: ['wf-1'] }, ['workflow:export']); + + expect(caught).toBeUndefined(); + expect(mockService.exportPackage).toHaveBeenCalledWith({ + ...DEFAULT_SERVICE_OPTIONS, + workflowIds: ['wf-1'], + }); + }); + + it('allows value-less export without variable:list scope', async () => { + mockExportStream(); + + const caught = await runAndCatch({ workflowIds: ['wf-1'], includeVariableValues: false }, [ + 'workflow:export', + ]); + + expect(caught).toBeUndefined(); + expect(mockService.exportPackage).toHaveBeenCalledWith({ + ...DEFAULT_SERVICE_OPTIONS, + workflowIds: ['wf-1'], + includeVariableValues: false, + }); + }); + + it('propagates the ForbiddenError thrown by the service scope gate and emits access-denied', async () => { + mockService.exportPackage.mockRejectedValue( + new ForbiddenError('missing the variable:list scope'), + ); + + const caught = await runAndCatch({ workflowIds: ['wf-1'] }, ['workflow:export']); + + expect(caught).toBeInstanceOf(ForbiddenError); + expect(emittedEvent('n8n-package-export-failed')).toMatchObject({ + reason: 'access-denied', + workflowIds: ['wf-1'], + }); + }); + + it('emits n8n-package-export-failed with reason=entity-not-found when the service rejects with NotFoundError', async () => { + mockService.exportPackage.mockRejectedValue(new NotFoundError('not found')); + + await runAndCatch({ workflowIds: ['wf-1'] }, ['workflow:export', 'variable:list']); + + expect(emittedEvent('n8n-package-export-failed')).toEqual({ + user: { id: 'user-1' }, + reason: 'entity-not-found', + workflowIds: ['wf-1'], + }); + }); + + it('emits n8n-package-export-failed with reason=blocked when the service rejects a blocked export', async () => { + mockService.exportPackage.mockRejectedValue(new PackageExportBlockedError('Export blocked')); + + await runAndCatch({ workflowIds: ['wf-1'] }, ['workflow:export', 'variable:list']); + + expect(emittedEvent('n8n-package-export-failed')).toEqual({ + user: { id: 'user-1' }, + reason: 'blocked', + workflowIds: ['wf-1'], + }); + }); + + it.each([ + [ + 'access-denied', + new PackageEntityAccessDeniedError('workflows denied', { description: 'x' }), + ], + [ + 'entity-not-found', + new PackageEntityNotFoundError('workflows missing', { description: 'y' }), + ], + ])( + 'rethrows %s as a generic UserError with the same message, hiding which case occurred', + async (reason, thrownError) => { + mockService.exportPackage.mockRejectedValue(thrownError); + + const caught = await runAndCatch({ workflowIds: ['wf-1'] }, [ + 'workflow:export', + 'variable:list', + ]); + + expect(caught).toBeInstanceOf(UserError); + expect(caught).not.toBeInstanceOf(PackageEntityAccessDeniedError); + expect(caught).not.toBeInstanceOf(PackageEntityNotFoundError); + expect(caught).toMatchObject({ message: thrownError.message }); + expect(emittedEvent('n8n-package-export-failed')).toMatchObject({ reason }); + }, + ); + + it('returns the export stream and headers for a valid workflow request', async () => { + mockExportStream(); + + const result = await controller.exportPackage( + makeRequest(['workflow:export', 'variable:list']), + mock(), + ExportPackageRequestDto.parse({ workflowIds: ['wf-1', 'wf-2'] }), + ); + + expect(mockService.exportPackage).toHaveBeenCalledWith({ + ...DEFAULT_SERVICE_OPTIONS, + workflowIds: ['wf-1', 'wf-2'], + canExportVariableValues: true, + }); + expect(result.body).toBeInstanceOf(Readable); + expect(result.headers).toEqual({ + 'Content-Disposition': 'attachment; filename="export.n8np"', + 'X-N8n-Export-Counts': JSON.stringify(EXPORT_COUNTS), + 'Access-Control-Expose-Headers': 'X-N8n-Export-Counts', + }); + expect(mockEventService.emit).not.toHaveBeenCalled(); + }); + + it('does not emit n8n-package-export-failed when the client disconnects after the stream is returned', async () => { + const prematureClose = Object.assign(new Error('Premature close'), { + code: 'ERR_STREAM_PREMATURE_CLOSE', + }); + const stream = new Readable({ read() {} }); + mockService.exportPackage.mockResolvedValue({ stream, counts: EXPORT_COUNTS }); + + await controller.exportPackage( + makeRequest(['workflow:export']), + mock(), + ExportPackageRequestDto.parse({ workflowIds: ['wf-1'] }), + ); + // The response reads the stream after the controller returns, so the disconnect happens here. + stream.on('error', () => undefined); + stream.destroy(prematureClose); + await new Promise((resolve) => setImmediate(resolve)); + + expect(mockEventService.emit).not.toHaveBeenCalled(); + }); + + it('forwards a non-default dependency policy', async () => { + mockExportStream(); + + const caught = await runAndCatch( + { workflowIds: ['wf-1'], dependencyPolicy: 'reference-only' }, + ['workflow:export'], + ); + + expect(caught).toBeUndefined(); + expect(mockService.exportPackage).toHaveBeenCalledWith({ + ...DEFAULT_SERVICE_OPTIONS, + workflowIds: ['wf-1'], + dependencyPolicy: 'reference-only', + }); + }); + + it('forwards a non-default version policy', async () => { + mockExportStream(); + + const caught = await runAndCatch( + { workflowIds: ['wf-1'], versionPolicy: 'published-strict' }, + ['workflow:export'], + ); + + expect(caught).toBeUndefined(); + expect(mockService.exportPackage).toHaveBeenCalledWith( + expect.objectContaining({ versionPolicy: 'published-strict' }), + ); + }); + + it('forwards agentIds and requires the agent:export scope for them', async () => { + mockExportStream(); + + const caught = await runAndCatch({ agentIds: ['agent-1'] }, [ + 'agent:export', + 'variable:list', + ]); + + expect(caught).toBeUndefined(); + expect(mockService.exportPackage).toHaveBeenCalledWith({ + ...DEFAULT_SERVICE_OPTIONS, + agentIds: ['agent-1'], + canExportVariableValues: true, + }); + }); + + it('throws ForbiddenError when exporting agents without agent:export scope', async () => { + const caught = await runAndCatch({ agentIds: ['agent-1'] }, ['workflow:export']); + + expect(caught).toBeInstanceOf(ForbiddenError); + expect(mockService.exportPackage).not.toHaveBeenCalled(); + }); + + it('forwards a non-default credential export policy', async () => { + mockExportStream(); + + const caught = await runAndCatch( + { workflowIds: ['wf-1'], credentialExportPolicy: 'no-values' }, + ['workflow:export'], + ); + + expect(caught).toBeUndefined(); + expect(mockService.exportPackage).toHaveBeenCalledWith( + expect.objectContaining({ credentialExportPolicy: 'no-values' }), + ); + }); + + it('forwards includeArchivedWorkflows', async () => { + mockExportStream(); + + const caught = await runAndCatch({ workflowIds: ['wf-1'], includeArchivedWorkflows: true }, [ + 'workflow:export', + ]); + + expect(caught).toBeUndefined(); + expect(mockService.exportPackage).toHaveBeenCalledWith( + expect.objectContaining({ includeArchivedWorkflows: true }), + ); + }); + + it('streams the export for a valid project request', async () => { + mockExportStream(); + + const caught = await runAndCatch({ projectIds: ['project-1'] }, [ + 'project:export', + 'variable:list', + ]); + + expect(caught).toBeUndefined(); + expect(mockService.exportPackage).toHaveBeenCalledWith({ + ...DEFAULT_SERVICE_OPTIONS, + projectIds: ['project-1'], + canExportVariableValues: true, + }); + }); + + it('streams the export for a valid folder request', async () => { + mockExportStream(); + + const caught = await runAndCatch({ folderIds: ['fld-1'] }, [ + 'workflow:export', + 'variable:list', + ]); + + expect(caught).toBeUndefined(); + expect(mockService.exportPackage).toHaveBeenCalledWith({ + ...DEFAULT_SERVICE_OPTIONS, + folderIds: ['fld-1'], + canExportVariableValues: true, + }); + }); + + it('forwards includeVariableValues=false to the service', async () => { + mockExportStream(); + + const caught = await runAndCatch({ workflowIds: ['wf-1'], includeVariableValues: false }, [ + 'workflow:export', + ]); + + expect(caught).toBeUndefined(); + expect(mockService.exportPackage).toHaveBeenCalledWith({ + ...DEFAULT_SERVICE_OPTIONS, + workflowIds: ['wf-1'], + includeVariableValues: false, + }); + }); + + it('forwards includeTags=false to the service', async () => { + mockExportStream(); + + const caught = await runAndCatch({ workflowIds: ['wf-1'], includeTags: false }, [ + 'workflow:export', + ]); + + expect(caught).toBeUndefined(); + expect(mockService.exportPackage).toHaveBeenCalledWith({ + ...DEFAULT_SERVICE_OPTIONS, + workflowIds: ['wf-1'], + includeTags: false, + }); + }); + }); +}); diff --git a/packages/cli/src/public-api/v1/controllers/credential-type-policies.public.controller.ts b/packages/cli/src/public-api/v1/controllers/credential-type-policies.public.controller.ts index 6db6ad98369..736c0642491 100644 --- a/packages/cli/src/public-api/v1/controllers/credential-type-policies.public.controller.ts +++ b/packages/cli/src/public-api/v1/controllers/credential-type-policies.public.controller.ts @@ -86,9 +86,9 @@ export class CredentialTypePoliciesPublicController { @Licensed(LICENSE_FEATURES.TYPE_AVAILABILITY_POLICIES) @ApiKeyScope('credentialTypePolicy:manage') @GlobalScope('credentialTypePolicy:manage') - @ApiSummary('Retrieve the instance credential type policy') + @ApiSummary('Preview: Retrieve the instance credential type policy') @ApiDescription( - 'Returns the composed instance-scope policy: its default action and the rules of every attached policy document in evaluation order. An instance that was never configured reports `scopeId: null`, no rules, `defaultAction: allow`, and `version: 0`.', + '**Preview** — breaking changes may still occur without major version bump.\n\nReturns the composed instance-scope policy: its default action and the rules of every attached policy document in evaluation order. An instance that was never configured reports `scopeId: null`, no rules, `defaultAction: allow`, and `version: 0`.', ) @ApiTags(tags) @ApiResponse(200, CredentialTypePolicyEffectivePublicDto) @@ -108,9 +108,9 @@ export class CredentialTypePoliciesPublicController { @Licensed(LICENSE_FEATURES.TYPE_AVAILABILITY_POLICIES) @ApiKeyScope('credentialTypePolicy:manage') @GlobalScope('credentialTypePolicy:manage') - @ApiSummary('Replace the instance credential type policy') + @ApiSummary('Preview: Replace the instance credential type policy') @ApiDescription( - 'Sets the instance default action and replaces the rules of its single policy document, creating both on first write. `version` must equal the version last read; a stale value is rejected with 409. Rule ids must be unique within the list.', + '**Preview** — breaking changes may still occur without major version bump.\n\nSets the instance default action and replaces the rules of its single policy document, creating both on first write. `version` must equal the version last read; a stale value is rejected with 409. Rule ids must be unique within the list.', ) @ApiTags(tags) @ApiResponse(200, CredentialTypePolicyEffectiveWriteResultPublicDto) @@ -142,9 +142,9 @@ export class CredentialTypePoliciesPublicController { @Licensed(LICENSE_FEATURES.TYPE_AVAILABILITY_POLICIES) @ApiKeyScope('credentialTypePolicy:manage') @ProjectScope('credentialTypePolicy:manage') - @ApiSummary("Retrieve a project's credential type policy") + @ApiSummary("Preview: Retrieve a project's credential type policy") @ApiDescription( - "Returns the project's own composed policy, not the result of combining it with the instance policy. A project that was never configured reports `scopeId: null`, no rules, `defaultAction: allow`, and `version: 0`.", + "**Preview** — breaking changes may still occur without major version bump.\n\nReturns the project's own composed policy, not the result of combining it with the instance policy. A project that was never configured reports `scopeId: null`, no rules, `defaultAction: allow`, and `version: 0`.", ) @ApiTags(tags) @ApiResponse(200, CredentialTypePolicyEffectivePublicDto) @@ -171,9 +171,9 @@ export class CredentialTypePoliciesPublicController { @Licensed(LICENSE_FEATURES.TYPE_AVAILABILITY_POLICIES) @ApiKeyScope('credentialTypePolicy:manage') @ProjectScope('credentialTypePolicy:manage') - @ApiSummary("Replace a project's credential type policy") + @ApiSummary("Preview: Replace a project's credential type policy") @ApiDescription( - "Sets the project's default action and replaces the rules of its single policy document, creating both on first write. The `delegate` action is not accepted at project scope. `version` must equal the version last read; a stale value is rejected with 409, as is a project document that is shared with another scope.", + "**Preview** — breaking changes may still occur without major version bump.\n\nSets the project's default action and replaces the rules of its single policy document, creating both on first write. The `delegate` action is not accepted at project scope. `version` must equal the version last read; a stale value is rejected with 409, as is a project document that is shared with another scope.", ) @ApiTags(tags) @ApiResponse(200, CredentialTypePolicyEffectiveWriteResultPublicDto) @@ -206,8 +206,10 @@ export class CredentialTypePoliciesPublicController { @Licensed(LICENSE_FEATURES.TYPE_AVAILABILITY_POLICIES) @ApiKeyScope('credentialTypePolicy:manage') @GlobalScope('credentialTypePolicy:manage') - @ApiSummary('List credential type policy documents') - @ApiDescription('Returns a cursor-paginated list of reusable policy documents.') + @ApiSummary('Preview: List credential type policy documents') + @ApiDescription( + '**Preview** — breaking changes may still occur without major version bump.\n\nReturns a cursor-paginated list of reusable policy documents.', + ) @ApiTags(tags) @ApiResponse(200, CredentialTypePolicyDocumentListPublicDto) @ApiErrorResponse(503) @@ -234,9 +236,9 @@ export class CredentialTypePoliciesPublicController { @Licensed(LICENSE_FEATURES.TYPE_AVAILABILITY_POLICIES) @ApiKeyScope('credentialTypePolicy:manage') @GlobalScope('credentialTypePolicy:manage') - @ApiSummary('Create a credential type policy document') + @ApiSummary('Preview: Create a credential type policy document') @ApiDescription( - 'Creates a reusable policy document that is not yet attached to any scope. Rule ids must be unique within the list. `warnings` lists rules that an earlier rule already shadows.', + '**Preview** — breaking changes may still occur without major version bump.\n\nCreates a reusable policy document that is not yet attached to any scope. Rule ids must be unique within the list. `warnings` lists rules that an earlier rule already shadows.', ) @ApiTags(tags) @ApiResponse(201, CredentialTypePolicyDocumentWriteResultPublicDto) @@ -259,7 +261,8 @@ export class CredentialTypePoliciesPublicController { @Licensed(LICENSE_FEATURES.TYPE_AVAILABILITY_POLICIES) @ApiKeyScope('credentialTypePolicy:manage') @GlobalScope('credentialTypePolicy:manage') - @ApiSummary('Retrieve a credential type policy document') + @ApiSummary('Preview: Retrieve a credential type policy document') + @ApiDescription('**Preview** — breaking changes may still occur without major version bump.') @ApiTags(tags) @ApiResponse(200, CredentialTypePolicyDocumentPublicDto) @ApiErrorResponse(404) @@ -281,9 +284,9 @@ export class CredentialTypePoliciesPublicController { @Licensed(LICENSE_FEATURES.TYPE_AVAILABILITY_POLICIES) @ApiKeyScope('credentialTypePolicy:manage') @GlobalScope('credentialTypePolicy:manage') - @ApiSummary('Replace the rules of a credential type policy document') + @ApiSummary('Preview: Replace the rules of a credential type policy document') @ApiDescription( - "Replaces the document's whole rule list. `version` must equal the version last read; a stale value is rejected with 409. Every scope the document is attached to has its version bumped. A `delegate` rule is rejected when the document is attached to a project scope.", + "**Preview** — breaking changes may still occur without major version bump.\n\nReplaces the document's whole rule list. `version` must equal the version last read; a stale value is rejected with 409. Every scope the document is attached to has its version bumped. A `delegate` rule is rejected when the document is attached to a project scope.", ) @ApiTags(tags) @ApiResponse(200, CredentialTypePolicyDocumentWriteResultPublicDto) @@ -311,9 +314,9 @@ export class CredentialTypePoliciesPublicController { @Licensed(LICENSE_FEATURES.TYPE_AVAILABILITY_POLICIES) @ApiKeyScope('credentialTypePolicy:manage') @GlobalScope('credentialTypePolicy:manage') - @ApiSummary('Delete a credential type policy document') + @ApiSummary('Preview: Delete a credential type policy document') @ApiDescription( - 'Deletes a policy document. A document that is still attached to a scope is rejected with 409; detach it first.', + '**Preview** — breaking changes may still occur without major version bump.\n\nDeletes a policy document. A document that is still attached to a scope is rejected with 409; detach it first.', ) @ApiTags(tags) @ApiResponse(204) @@ -332,13 +335,14 @@ export class CredentialTypePoliciesPublicController { @Licensed(LICENSE_FEATURES.TYPE_AVAILABILITY_POLICIES) @ApiKeyScope('credentialTypePolicy:manage') @GlobalScope('credentialTypePolicy:manage') - @ApiSummary("Replace a scope's attached policy documents") + @ApiSummary("Preview: Replace a scope's attached policy documents") @ApiDescription( - "Replaces every attachment on a scope. `scopeId` comes from the scope's `GET` response once it has been written. Each `policyId` and each `(isFloor, priority)` pair must be unique within the list. Last write wins; the scope's version is bumped.", + "**Preview** — breaking changes may still occur without major version bump.\n\nReplaces every attachment on a scope. `scopeId` comes from the scope's `GET` response once it has been written. Each `policyId` and each `(isFloor, priority)` pair must be unique within the list. `version` must match the current scope version. A stale version returns 409 without changes. A successful write bumps the scope's version.", ) @ApiTags(tags) @ApiResponse(200, CredentialTypePolicyAttachmentsPublicDto) @ApiErrorResponse(404) + @ApiErrorResponse(409) @ApiErrorResponse(503) async replaceCredentialTypePolicyAttachments( req: AuthenticatedRequest, @@ -350,6 +354,7 @@ export class CredentialTypePoliciesPublicController { CREDENTIAL_TYPES_KIND, scopeId, dto.attachments, + dto.version, req.user.id, ); diff --git a/packages/cli/src/public-api/v1/controllers/credentials.public.controller.ts b/packages/cli/src/public-api/v1/controllers/credentials.public.controller.ts index 3bee5ce2edd..ff2f62c11df 100644 --- a/packages/cli/src/public-api/v1/controllers/credentials.public.controller.ts +++ b/packages/cli/src/public-api/v1/controllers/credentials.public.controller.ts @@ -92,7 +92,7 @@ function toCredentialPublicDto( }; } -/** The delete response adds `usageScope` to the standard credential fields. Carry over from legacy EOV handler. */ +/** The delete response adds `usageScope` to the standard credential fields. */ function toDeleteCredentialPublicDto( credential: CredentialsEntity, includeDescription: boolean, diff --git a/packages/cli/src/public-api/v1/controllers/data-tables.public.controller.ts b/packages/cli/src/public-api/v1/controllers/data-tables.public.controller.ts index 11001283350..97393d1e014 100644 --- a/packages/cli/src/public-api/v1/controllers/data-tables.public.controller.ts +++ b/packages/cli/src/public-api/v1/controllers/data-tables.public.controller.ts @@ -64,7 +64,7 @@ import { ProjectNotFoundError } from '@/services/project.service.ee'; const tags = ['DataTable']; -/** The domain errors the data table service raises, mapped to the public statuses the eov handler sent. */ +/** The domain errors the data table service raises, mapped to public statuses. */ function handleError(error: unknown): never { if (error instanceof DataTableValidationError) { throw new BadRequestError(error.message); diff --git a/packages/cli/src/public-api/v1/controllers/n8n-packages.public.controller.ts b/packages/cli/src/public-api/v1/controllers/n8n-packages.public.controller.ts index 8cf4493f0a7..4eacab8c851 100644 --- a/packages/cli/src/public-api/v1/controllers/n8n-packages.public.controller.ts +++ b/packages/cli/src/public-api/v1/controllers/n8n-packages.public.controller.ts @@ -1,4 +1,5 @@ import { + ExportPackageRequestDto, ImportBlockedErrorDto, ImportPackageRequestDto, ImportPackageSelectionRequestDto, @@ -18,11 +19,18 @@ import { Body, Post, PublicApiController, + type BinaryResult, } from '@n8n/decorators'; +import { BadRequestError, ForbiddenError } from '@n8n/errors'; import type { Response } from 'express'; +import { UserError } from 'n8n-workflow'; +import { + PackageEntityAccessDeniedError, + PackageEntityNotFoundError, +} from '@/modules/n8n-packages/entities/package-export.errors'; import { N8nPackagesService } from '@/modules/n8n-packages/n8n-packages.service'; -import type { ImportResult } from '@/modules/n8n-packages/n8n-packages.types'; +import type { ExportPackageResult, ImportResult } from '@/modules/n8n-packages/n8n-packages.types'; import { classifyPackageFailure } from '@/modules/n8n-packages/package-failure-classifier'; import { IMPORT_PACKAGE_FIELD_SIZE_BYTES, @@ -31,6 +39,10 @@ import { } from '@/modules/n8n-packages/utils/import-package-upload'; import { + EXPORT_200_DESCRIPTION, + EXPORT_COUNTS_HEADER_DESCRIPTION, + EXPORT_DESCRIPTION, + EXPORT_SUMMARY, IMPORT_409_DESCRIPTION, IMPORT_422_DESCRIPTION, IMPORT_DESCRIPTION, @@ -39,9 +51,11 @@ import { IMPORT_SELECTION_DESCRIPTION, IMPORT_SELECTION_SUMMARY, IMPORT_SUMMARY, - IMPORT_TAGS, + PACKAGE_TAGS, } from './openapi/n8n-packages.openapi'; +const EXPORT_COUNTS_HEADER = 'X-N8n-Export-Counts'; + function uploadLimits(maxParts: number) { const maxFileSizeBytes = Container.get(GlobalConfig).endpoints.payloadSizeMax * 1024 * 1024; return { @@ -52,6 +66,38 @@ function uploadLimits(maxParts: number) { }; } +function assertPackageExportApiKeyScopes( + apiKeyScopes: string[] | undefined, + agentIds: string[], + workflowIds: string[], + folderIds: string[], + projectIds: string[], +): string[] { + if (!apiKeyScopes) { + throw new ForbiddenError('Forbidden'); + } + + const requiredScopes: string[] = []; + if (agentIds.length > 0) { + requiredScopes.push('agent:export'); + } + // Folders are exported as a workflow-organization concern, so they share the workflow:export scope. + if (workflowIds.length > 0 || folderIds.length > 0) { + requiredScopes.push('workflow:export'); + } + if (projectIds.length > 0) { + requiredScopes.push('project:export'); + } + + for (const scope of requiredScopes) { + if (!apiKeyScopes.includes(scope)) { + throw new ForbiddenError('Forbidden'); + } + } + + return apiKeyScopes; +} + @PublicApiController('/n8n-packages') export class N8nPackagesPublicController { constructor( @@ -63,7 +109,7 @@ export class N8nPackagesPublicController { @ApiKeyScope('workflow:import') @ApiSummary(IMPORT_SUMMARY) @ApiDescription(IMPORT_DESCRIPTION) - @ApiTags(IMPORT_TAGS) + @ApiTags(PACKAGE_TAGS) @ApiResponse(200, ImportResultDto) @ApiErrorResponse(404) @ApiErrorResponse(409, { dto: ImportBlockedErrorDto, description: IMPORT_409_DESCRIPTION }) @@ -106,7 +152,7 @@ export class N8nPackagesPublicController { @ApiKeyScope('workflow:import') @ApiSummary(IMPORT_SELECTION_SUMMARY) @ApiDescription(IMPORT_SELECTION_DESCRIPTION) - @ApiTags(IMPORT_TAGS) + @ApiTags(PACKAGE_TAGS) @ApiResponse(200, ImportResultDto) @ApiErrorResponse(404) @ApiErrorResponse(409, { @@ -156,4 +202,90 @@ export class N8nPackagesPublicController { throw error; } } + + @Post('/export') + @ApiKeyScope({ anyOf: ['project:export', 'workflow:export', 'agent:export'] }) + @ApiSummary(EXPORT_SUMMARY) + @ApiDescription(EXPORT_DESCRIPTION) + @ApiTags(PACKAGE_TAGS) + @ApiResponse(200, { + mediaType: 'application/gzip', + description: EXPORT_200_DESCRIPTION, + headers: { [EXPORT_COUNTS_HEADER]: { description: EXPORT_COUNTS_HEADER_DESCRIPTION } }, + }) + @ApiErrorResponse(404) + async exportPackage( + req: AuthenticatedRequest, + _res: Response, + @Body({ required: true }) body: ExportPackageRequestDto, + ): Promise { + const { agentIds = [], workflowIds = [], folderIds = [], projectIds = [] } = body; + + let exportResult: ExportPackageResult; + + try { + const hasLooseSelection = [agentIds, workflowIds, folderIds].some((ids) => ids.length > 0); + if (projectIds.length > 0 && hasLooseSelection) { + throw new BadRequestError( + 'Provide either agentIds/workflowIds/folderIds or projectIds, not both', + ); + } + + if (!hasLooseSelection && projectIds.length === 0) { + throw new BadRequestError( + 'At least one agentId, workflowId, folderId, or projectId is required', + ); + } + + const apiKeyScopes = assertPackageExportApiKeyScopes( + req.tokenGrant?.apiKeyScopes, + agentIds, + workflowIds, + folderIds, + projectIds, + ); + + exportResult = await this.n8nPackagesService.exportPackage({ + user: req.user, + agentIds, + workflowIds, + folderIds, + projectIds, + includeVariableValues: body.includeVariableValues, + canExportVariableValues: apiKeyScopes.includes('variable:list'), + includeTags: body.includeTags, + dependencyPolicy: body.dependencyPolicy, + versionPolicy: body.versionPolicy, + credentialExportPolicy: body.credentialExportPolicy, + includeArchivedWorkflows: body.includeArchivedWorkflows, + }); + } catch (error) { + this.eventService.emit('n8n-package-export-failed', { + user: req.user, + reason: classifyPackageFailure(error), + ...(agentIds.length ? { agentIds } : {}), + ...(workflowIds.length ? { workflowIds } : {}), + ...(folderIds.length ? { folderIds } : {}), + ...(projectIds.length ? { projectIds } : {}), + }); + + if ( + error instanceof PackageEntityAccessDeniedError || + error instanceof PackageEntityNotFoundError + ) { + throw new UserError(error.message, { description: error.description }); + } + throw error; + } + + return { + body: exportResult.stream, + headers: { + 'Content-Disposition': 'attachment; filename="export.n8np"', + [EXPORT_COUNTS_HEADER]: JSON.stringify(exportResult.counts), + // Cross-origin browser clients can only read the counts header if it is exposed. + 'Access-Control-Expose-Headers': EXPORT_COUNTS_HEADER, + }, + }; + } } diff --git a/packages/cli/src/public-api/v1/controllers/node-type-policies.public.controller.ts b/packages/cli/src/public-api/v1/controllers/node-type-policies.public.controller.ts index ae6f3b1ad56..80a6ddf9dfe 100644 --- a/packages/cli/src/public-api/v1/controllers/node-type-policies.public.controller.ts +++ b/packages/cli/src/public-api/v1/controllers/node-type-policies.public.controller.ts @@ -98,9 +98,9 @@ export class NodeTypePoliciesPublicController { @Licensed(LICENSE_FEATURES.TYPE_AVAILABILITY_POLICIES) @ApiKeyScope('nodeTypePolicy:manage') @GlobalScope('nodeTypePolicy:manage') - @ApiSummary('Retrieve the instance node type policy') + @ApiSummary('Preview: Retrieve the instance node type policy') @ApiDescription( - 'Returns the composed instance-scope policy: its default action and the rules of every attached policy document in evaluation order. An instance that was never configured reports `scopeId: null`, no rules, `defaultAction: allow`, and `version: 0`.', + '**Preview** — breaking changes may still occur without major version bump.\n\nReturns the composed instance-scope policy: its default action and the rules of every attached policy document in evaluation order. An instance that was never configured reports `scopeId: null`, no rules, `defaultAction: allow`, and `version: 0`.', ) @ApiTags(tags) @ApiResponse(200, PolicyEffectivePublicDto) @@ -120,9 +120,9 @@ export class NodeTypePoliciesPublicController { @Licensed(LICENSE_FEATURES.TYPE_AVAILABILITY_POLICIES) @ApiKeyScope('nodeTypePolicy:manage') @GlobalScope('nodeTypePolicy:manage') - @ApiSummary('Replace the instance node type policy') + @ApiSummary('Preview: Replace the instance node type policy') @ApiDescription( - 'Sets the instance default action and replaces the rules of its single policy document, creating both on first write. `version` must equal the version last read; a stale value is rejected with 409. Rule ids must be unique within the list.', + '**Preview** — breaking changes may still occur without major version bump.\n\nSets the instance default action and replaces the rules of its single policy document, creating both on first write. `version` must equal the version last read; a stale value is rejected with 409. Rule ids must be unique within the list.', ) @ApiTags(tags) @ApiResponse(200, PolicyEffectiveWriteResultPublicDto) @@ -154,9 +154,9 @@ export class NodeTypePoliciesPublicController { @Licensed(LICENSE_FEATURES.TYPE_AVAILABILITY_POLICIES) @ApiKeyScope('nodeTypePolicy:manage') @ProjectScope('nodeTypePolicy:manage') - @ApiSummary("Retrieve a project's node type policy") + @ApiSummary("Preview: Retrieve a project's node type policy") @ApiDescription( - "Returns the project's own composed policy, not the result of combining it with the instance policy. A project that was never configured reports `scopeId: null`, no rules, `defaultAction: allow`, and `version: 0`.", + "**Preview** — breaking changes may still occur without major version bump.\n\nReturns the project's own composed policy, not the result of combining it with the instance policy. A project that was never configured reports `scopeId: null`, no rules, `defaultAction: allow`, and `version: 0`.", ) @ApiTags(tags) @ApiResponse(200, PolicyEffectivePublicDto) @@ -180,9 +180,9 @@ export class NodeTypePoliciesPublicController { @Licensed(LICENSE_FEATURES.TYPE_AVAILABILITY_POLICIES) @ApiKeyScope('nodeTypePolicy:manage') @ProjectScope('nodeTypePolicy:manage') - @ApiSummary("Replace a project's node type policy") + @ApiSummary("Preview: Replace a project's node type policy") @ApiDescription( - "Sets the project's default action and replaces the rules of its single policy document, creating both on first write. The `delegate` action is not accepted at project scope. `version` must equal the version last read; a stale value is rejected with 409, as is a project document that is shared with another scope.", + "**Preview** — breaking changes may still occur without major version bump.\n\nSets the project's default action and replaces the rules of its single policy document, creating both on first write. The `delegate` action is not accepted at project scope. `version` must equal the version last read; a stale value is rejected with 409, as is a project document that is shared with another scope.", ) @ApiTags(tags) @ApiResponse(200, PolicyEffectiveWriteResultPublicDto) @@ -215,8 +215,10 @@ export class NodeTypePoliciesPublicController { @Licensed(LICENSE_FEATURES.TYPE_AVAILABILITY_POLICIES) @ApiKeyScope('nodeTypePolicy:manage') @GlobalScope('nodeTypePolicy:manage') - @ApiSummary('List node type policy documents') - @ApiDescription('Returns a cursor-paginated list of reusable policy documents.') + @ApiSummary('Preview: List node type policy documents') + @ApiDescription( + '**Preview** — breaking changes may still occur without major version bump.\n\nReturns a cursor-paginated list of reusable policy documents.', + ) @ApiTags(tags) @ApiResponse(200, PolicyDocumentListPublicDto) @ApiErrorResponse(503) @@ -243,9 +245,9 @@ export class NodeTypePoliciesPublicController { @Licensed(LICENSE_FEATURES.TYPE_AVAILABILITY_POLICIES) @ApiKeyScope('nodeTypePolicy:manage') @GlobalScope('nodeTypePolicy:manage') - @ApiSummary('Create a node type policy document') + @ApiSummary('Preview: Create a node type policy document') @ApiDescription( - 'Creates a reusable policy document that is not yet attached to any scope. Rule ids must be unique within the list. `warnings` lists rules that an earlier rule already shadows.', + '**Preview** — breaking changes may still occur without major version bump.\n\nCreates a reusable policy document that is not yet attached to any scope. Rule ids must be unique within the list. `warnings` lists rules that an earlier rule already shadows.', ) @ApiTags(tags) @ApiResponse(201, PolicyDocumentWriteResultPublicDto) @@ -268,7 +270,8 @@ export class NodeTypePoliciesPublicController { @Licensed(LICENSE_FEATURES.TYPE_AVAILABILITY_POLICIES) @ApiKeyScope('nodeTypePolicy:manage') @GlobalScope('nodeTypePolicy:manage') - @ApiSummary('Retrieve a node type policy document') + @ApiSummary('Preview: Retrieve a node type policy document') + @ApiDescription('**Preview** — breaking changes may still occur without major version bump.') @ApiTags(tags) @ApiResponse(200, PolicyDocumentPublicDto) @ApiErrorResponse(404) @@ -290,9 +293,9 @@ export class NodeTypePoliciesPublicController { @Licensed(LICENSE_FEATURES.TYPE_AVAILABILITY_POLICIES) @ApiKeyScope('nodeTypePolicy:manage') @GlobalScope('nodeTypePolicy:manage') - @ApiSummary('Replace the rules of a node type policy document') + @ApiSummary('Preview: Replace the rules of a node type policy document') @ApiDescription( - "Replaces the document's whole rule list. `version` must equal the version last read; a stale value is rejected with 409. Every scope the document is attached to has its version bumped. A `delegate` rule is rejected when the document is attached to a project scope.", + "**Preview** — breaking changes may still occur without major version bump.\n\nReplaces the document's whole rule list. `version` must equal the version last read; a stale value is rejected with 409. Every scope the document is attached to has its version bumped. A `delegate` rule is rejected when the document is attached to a project scope.", ) @ApiTags(tags) @ApiResponse(200, PolicyDocumentWriteResultPublicDto) @@ -320,9 +323,9 @@ export class NodeTypePoliciesPublicController { @Licensed(LICENSE_FEATURES.TYPE_AVAILABILITY_POLICIES) @ApiKeyScope('nodeTypePolicy:manage') @GlobalScope('nodeTypePolicy:manage') - @ApiSummary('Delete a node type policy document') + @ApiSummary('Preview: Delete a node type policy document') @ApiDescription( - 'Deletes a policy document. A document that is still attached to a scope is rejected with 409; detach it first.', + '**Preview** — breaking changes may still occur without major version bump.\n\nDeletes a policy document. A document that is still attached to a scope is rejected with 409; detach it first.', ) @ApiTags(tags) @ApiResponse(204) @@ -341,13 +344,14 @@ export class NodeTypePoliciesPublicController { @Licensed(LICENSE_FEATURES.TYPE_AVAILABILITY_POLICIES) @ApiKeyScope('nodeTypePolicy:manage') @GlobalScope('nodeTypePolicy:manage') - @ApiSummary("Replace a scope's attached policy documents") + @ApiSummary("Preview: Replace a scope's attached policy documents") @ApiDescription( - "Replaces every attachment on a scope. `scopeId` comes from the scope's `GET` response once it has been written. Each `policyId` and each `(isFloor, priority)` pair must be unique within the list. Last write wins; the scope's version is bumped.", + "**Preview** — breaking changes may still occur without major version bump.\n\nReplaces every attachment on a scope. `scopeId` comes from the scope's `GET` response once it has been written. Each `policyId` and each `(isFloor, priority)` pair must be unique within the list. `version` must match the current scope version. A stale version returns 409 without changes. A successful write bumps the scope's version.", ) @ApiTags(tags) @ApiResponse(200, PolicyAttachmentsPublicDto) @ApiErrorResponse(404) + @ApiErrorResponse(409) @ApiErrorResponse(503) async replaceNodeTypePolicyAttachments( req: AuthenticatedRequest, @@ -359,6 +363,7 @@ export class NodeTypePoliciesPublicController { NODE_TYPES_KIND, scopeId, dto.attachments, + dto.version, req.user.id, ); diff --git a/packages/cli/src/public-api/v1/controllers/openapi/n8n-packages.openapi.ts b/packages/cli/src/public-api/v1/controllers/openapi/n8n-packages.openapi.ts index 8bac76a7df0..3b44a43f881 100644 --- a/packages/cli/src/public-api/v1/controllers/openapi/n8n-packages.openapi.ts +++ b/packages/cli/src/public-api/v1/controllers/openapi/n8n-packages.openapi.ts @@ -1,4 +1,37 @@ -export const IMPORT_TAGS = ['N8nPackage']; +export const PACKAGE_TAGS = ['N8nPackage']; + +export const EXPORT_SUMMARY = + 'Beta: Export agents, workflows, folders, or projects as an n8n package'; +export const EXPORT_DESCRIPTION = + '**Beta** — breaking changes may still occur without major version bump.\n\n' + + 'Export agents, workflows, and folders, or whole projects, as a gzipped tar\n' + + 'archive (.n8np). Provide `agentIds`/`workflowIds`/`folderIds`, or `projectIds`.\n' + + 'Do not combine these two groups. Each exported folder includes its nested\n' + + 'folders. Whole projects include their agents when the agents module is enabled.\n' + + 'Explicit agent selections require the agents module. Empty projects export\n' + + 'project metadata only. `versionPolicy` selects the version for both agents and\n' + + 'workflows and defaults to `latest`. `dependencyPolicy` applies to both entity\n' + + 'types and defaults to `fail` when a required definition is absent from the\n' + + 'package. The response is streamed as `application/gzip` with a `Content-Disposition`\n' + + 'attachment header. Requires the n8n Packages feature to be licensed.\n\n' + + 'API key scopes: `agent:export` is required for explicitly selected agents.\n' + + '`workflow:export` is required for explicitly selected workflows or folders.\n' + + '`project:export` is sufficient for whole-project exports, including their\n' + + 'agents and workflows. Included dependencies need no additional API key scope.\n' + + "The caller's project permissions apply to all included entities. When\n" + + '`includeVariableValues` is true (the default) and exported entities reference\n' + + 'variables, `variable:list` is also required. Exports that reference no variables\n' + + 'do not need it.\n\n' + + 'Agent definitions include referenced skills, custom tools, and schedules.\n' + + 'Knowledge base files and runtime data are excluded. Agent package imports\n' + + 'remain unavailable.\n'; + +export const EXPORT_200_DESCRIPTION = + 'A gzipped tar archive containing the exported package contents.'; +export const EXPORT_COUNTS_HEADER_DESCRIPTION = + 'JSON-serialized per-entity counts of what actually ended up in the\n' + + 'package (after folder bundling and auto-inclusion), e.g.\n' + + '`{"agents":1,"workflows":2,"folders":1,"credentials":0,"dataTables":0,"variables":0,"tags":0}`.\n'; export const IMPORT_SUMMARY = 'Beta: Import an n8n package into a project'; export const IMPORT_DESCRIPTION = diff --git a/packages/cli/src/public-api/v1/controllers/promotions.public.controller.ts b/packages/cli/src/public-api/v1/controllers/promotions.public.controller.ts index cc7d2c21a7b..195a34c6da4 100644 --- a/packages/cli/src/public-api/v1/controllers/promotions.public.controller.ts +++ b/packages/cli/src/public-api/v1/controllers/promotions.public.controller.ts @@ -540,7 +540,7 @@ export class PromotionsPublicController { @GlobalScope('gitConnection:pull') @ApiSummary('Apply a package to the instance') @ApiDescription( - 'Checks the full package at the configured branch tip. Optionally send expectedSource with the configId, branchName, and full commitSha from the reviewed change preview; status `source-changed` means the branch moved since that review and nothing was imported. Returns status `blocked` before import writes if bindings need setup. Retain configId and git for Continue. Status `applied` includes counts and warnings. Inspect status before reading counts. Existing target variable values, including empty strings, are preserved. Requires a cloned Apply direction on an instance connection. The API key needs the gitConnection:pull scope. The importer checks user write permissions; granular API-key write scopes are not passed to it.', + 'Checks the full package at the configured branch tip. Optionally send expectedSource with the configId, branchName, and full commitSha from the reviewed change preview; status `source-changed` means the branch moved since that review and nothing was imported. Returns status `blocked` before import writes if bindings need setup or if the apply would delete team projects that the package does not hold. Retain configId and git for Continue. Status `applied` includes counts and warnings. Inspect status before reading counts. Existing target variable values, including empty strings, are preserved. Requires a cloned Apply direction on an instance connection. The API key needs the gitConnection:pull scope. The importer checks user write permissions; granular API-key write scopes are not passed to it.', ) @ApiTags(tags) @ApiResponse(200, ApplyPackageResultDto) @@ -569,7 +569,7 @@ export class PromotionsPublicController { @GlobalScope('gitConnection:pull') @ApiSummary('Continue Apply after binding setup') @ApiDescription( - 'Rechecks the configured source and current target bindings. Send expectedSource with the configId, branchName, and full commitSha from the reviewed Apply result. Send `confirmDestructiveChanges: true` to also apply destructive data table changes. Status `source-changed` requires a new Apply review. Status `blocked` returns fresh binding details without import writes. Status `applied` includes counts and warnings. Inspect status before reading counts. Existing target variable values are preserved. Requires the same cloned instance connection and permissions as Apply. The importer checks user write permissions; granular API-key write scopes are not passed to it. No server session or exactly-once guarantee is provided.', + 'Rechecks the configured source and current target bindings. Send expectedSource with the configId, branchName, and full commitSha from the reviewed Apply result. Send `confirmDestructiveChanges: true` to also apply destructive data table changes and delete the reported team projects. Status `source-changed` requires a new Apply review. Status `blocked` returns fresh binding details without import writes. Status `applied` includes counts and warnings. Inspect status before reading counts. Existing target variable values are preserved. Requires the same cloned instance connection and permissions as Apply. The importer checks user write permissions; granular API-key write scopes are not passed to it. No server session or exactly-once guarantee is provided.', ) @ApiTags(tags) @ApiResponse(200, ApplyPackageResultDto) diff --git a/packages/cli/src/public-api/v1/handlers/audit/spec/paths/generateAudit.generated.yml b/packages/cli/src/public-api/v1/handlers/audit/spec/paths/generateAudit.generated.yml index 1180889f860..6d1220cfdec 100644 --- a/packages/cli/src/public-api/v1/handlers/audit/spec/paths/generateAudit.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/audit/spec/paths/generateAudit.generated.yml @@ -4,9 +4,6 @@ tags: summary: Generate an audit description: Generate a security audit for your n8n instance. x-required-scope: securityAudit:generate -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true requestBody: content: application/json: diff --git a/packages/cli/src/public-api/v1/handlers/community-packages/spec/paths/getInstalledPackages.generated.yml b/packages/cli/src/public-api/v1/handlers/community-packages/spec/paths/getInstalledPackages.generated.yml index c1d054d9b0d..05084de170a 100644 --- a/packages/cli/src/public-api/v1/handlers/community-packages/spec/paths/getInstalledPackages.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/community-packages/spec/paths/getInstalledPackages.generated.yml @@ -4,9 +4,6 @@ tags: summary: List installed community packages description: Retrieve all installed community packages with pending update info. x-required-scope: communityPackage:list -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true responses: '200': description: Operation successful. diff --git a/packages/cli/src/public-api/v1/handlers/community-packages/spec/paths/installPackage.generated.yml b/packages/cli/src/public-api/v1/handlers/community-packages/spec/paths/installPackage.generated.yml index 8ef12043332..9105aa98d9b 100644 --- a/packages/cli/src/public-api/v1/handlers/community-packages/spec/paths/installPackage.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/community-packages/spec/paths/installPackage.generated.yml @@ -4,9 +4,6 @@ tags: summary: Install a community package description: Install a community package by npm name and optional version. x-required-scope: communityPackage:install -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true requestBody: required: true content: diff --git a/packages/cli/src/public-api/v1/handlers/community-packages/spec/paths/uninstallPackage.generated.yml b/packages/cli/src/public-api/v1/handlers/community-packages/spec/paths/uninstallPackage.generated.yml index c3fb6d539b7..026209e5ede 100644 --- a/packages/cli/src/public-api/v1/handlers/community-packages/spec/paths/uninstallPackage.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/community-packages/spec/paths/uninstallPackage.generated.yml @@ -4,9 +4,6 @@ tags: summary: Uninstall a community package description: Uninstall a community package by name. x-required-scope: communityPackage:uninstall -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/community-packages/spec/paths/updatePackage.generated.yml b/packages/cli/src/public-api/v1/handlers/community-packages/spec/paths/updatePackage.generated.yml index 38d457cce4c..ce063c7d0fa 100644 --- a/packages/cli/src/public-api/v1/handlers/community-packages/spec/paths/updatePackage.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/community-packages/spec/paths/updatePackage.generated.yml @@ -4,9 +4,6 @@ tags: summary: Update a community package description: Update an installed community package to a new version. x-required-scope: communityPackage:update -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/createCredentialTypePolicyDocument.generated.yml b/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/createCredentialTypePolicyDocument.generated.yml index cb1e1d64dec..437a14de566 100644 --- a/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/createCredentialTypePolicyDocument.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/createCredentialTypePolicyDocument.generated.yml @@ -1,12 +1,12 @@ operationId: createCredentialTypePolicyDocument tags: - CredentialTypePolicy -summary: Create a credential type policy document -description: Creates a reusable policy document that is not yet attached to any scope. Rule ids must be unique within the list. `warnings` lists rules that an earlier rule already shadows. +summary: 'Preview: Create a credential type policy document' +description: |- + **Preview** — breaking changes may still occur without major version bump. + + Creates a reusable policy document that is not yet attached to any scope. Rule ids must be unique within the list. `warnings` lists rules that an earlier rule already shadows. x-required-scope: credentialTypePolicy:manage -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true requestBody: required: true content: diff --git a/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/deleteCredentialTypePolicyDocument.generated.yml b/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/deleteCredentialTypePolicyDocument.generated.yml index da7a75a16b1..6a247a113b4 100644 --- a/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/deleteCredentialTypePolicyDocument.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/deleteCredentialTypePolicyDocument.generated.yml @@ -1,12 +1,12 @@ operationId: deleteCredentialTypePolicyDocument tags: - CredentialTypePolicy -summary: Delete a credential type policy document -description: Deletes a policy document. A document that is still attached to a scope is rejected with 409; detach it first. +summary: 'Preview: Delete a credential type policy document' +description: |- + **Preview** — breaking changes may still occur without major version bump. + + Deletes a policy document. A document that is still attached to a scope is rejected with 409; detach it first. x-required-scope: credentialTypePolicy:manage -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/getCredentialTypeInstancePolicy.generated.yml b/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/getCredentialTypeInstancePolicy.generated.yml index 11ea98f050e..e2520926b1b 100644 --- a/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/getCredentialTypeInstancePolicy.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/getCredentialTypeInstancePolicy.generated.yml @@ -1,12 +1,12 @@ operationId: getCredentialTypeInstancePolicy tags: - CredentialTypePolicy -summary: Retrieve the instance credential type policy -description: 'Returns the composed instance-scope policy: its default action and the rules of every attached policy document in evaluation order. An instance that was never configured reports `scopeId: null`, no rules, `defaultAction: allow`, and `version: 0`.' +summary: 'Preview: Retrieve the instance credential type policy' +description: |- + **Preview** — breaking changes may still occur without major version bump. + + Returns the composed instance-scope policy: its default action and the rules of every attached policy document in evaluation order. An instance that was never configured reports `scopeId: null`, no rules, `defaultAction: allow`, and `version: 0`. x-required-scope: credentialTypePolicy:manage -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true responses: '200': description: Operation successful. diff --git a/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/getCredentialTypePolicyDocument.generated.yml b/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/getCredentialTypePolicyDocument.generated.yml index af9fa26ad74..11927292622 100644 --- a/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/getCredentialTypePolicyDocument.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/getCredentialTypePolicyDocument.generated.yml @@ -1,11 +1,9 @@ operationId: getCredentialTypePolicyDocument tags: - CredentialTypePolicy -summary: Retrieve a credential type policy document +summary: 'Preview: Retrieve a credential type policy document' +description: '**Preview** — breaking changes may still occur without major version bump.' x-required-scope: credentialTypePolicy:manage -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/getCredentialTypeProjectPolicy.generated.yml b/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/getCredentialTypeProjectPolicy.generated.yml index 1689cee24cb..26e4166be3d 100644 --- a/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/getCredentialTypeProjectPolicy.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/getCredentialTypeProjectPolicy.generated.yml @@ -1,12 +1,12 @@ operationId: getCredentialTypeProjectPolicy tags: - CredentialTypePolicy -summary: Retrieve a project's credential type policy -description: "Returns the project's own composed policy, not the result of combining it with the instance policy. A project that was never configured reports `scopeId: null`, no rules, `defaultAction: allow`, and `version: 0`." +summary: "Preview: Retrieve a project's credential type policy" +description: |- + **Preview** — breaking changes may still occur without major version bump. + + Returns the project's own composed policy, not the result of combining it with the instance policy. A project that was never configured reports `scopeId: null`, no rules, `defaultAction: allow`, and `version: 0`. x-required-scope: credentialTypePolicy:manage -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/listCredentialTypePolicyDocuments.generated.yml b/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/listCredentialTypePolicyDocuments.generated.yml index bc59adb2354..0476fa57bd4 100644 --- a/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/listCredentialTypePolicyDocuments.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/listCredentialTypePolicyDocuments.generated.yml @@ -1,15 +1,15 @@ operationId: listCredentialTypePolicyDocuments tags: - CredentialTypePolicy -summary: List credential type policy documents -description: Returns a cursor-paginated list of reusable policy documents. +summary: 'Preview: List credential type policy documents' +description: |- + **Preview** — breaking changes may still occur without major version bump. + + Returns a cursor-paginated list of reusable policy documents. x-required-scope: credentialTypePolicy:manage parameters: - $ref: ../../../../shared/spec/parameters/limit.yml - $ref: ../../../../shared/spec/parameters/cursor.yml -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true responses: '200': description: Operation successful. diff --git a/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/putCredentialTypeInstancePolicy.generated.yml b/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/putCredentialTypeInstancePolicy.generated.yml index fd44ea11c79..4751441eeec 100644 --- a/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/putCredentialTypeInstancePolicy.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/putCredentialTypeInstancePolicy.generated.yml @@ -1,12 +1,12 @@ operationId: putCredentialTypeInstancePolicy tags: - CredentialTypePolicy -summary: Replace the instance credential type policy -description: Sets the instance default action and replaces the rules of its single policy document, creating both on first write. `version` must equal the version last read; a stale value is rejected with 409. Rule ids must be unique within the list. +summary: 'Preview: Replace the instance credential type policy' +description: |- + **Preview** — breaking changes may still occur without major version bump. + + Sets the instance default action and replaces the rules of its single policy document, creating both on first write. `version` must equal the version last read; a stale value is rejected with 409. Rule ids must be unique within the list. x-required-scope: credentialTypePolicy:manage -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true requestBody: required: true content: diff --git a/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/putCredentialTypeProjectPolicy.generated.yml b/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/putCredentialTypeProjectPolicy.generated.yml index 83f5209ccba..4188314cf62 100644 --- a/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/putCredentialTypeProjectPolicy.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/putCredentialTypeProjectPolicy.generated.yml @@ -1,12 +1,12 @@ operationId: putCredentialTypeProjectPolicy tags: - CredentialTypePolicy -summary: Replace a project's credential type policy -description: Sets the project's default action and replaces the rules of its single policy document, creating both on first write. The `delegate` action is not accepted at project scope. `version` must equal the version last read; a stale value is rejected with 409, as is a project document that is shared with another scope. +summary: "Preview: Replace a project's credential type policy" +description: |- + **Preview** — breaking changes may still occur without major version bump. + + Sets the project's default action and replaces the rules of its single policy document, creating both on first write. The `delegate` action is not accepted at project scope. `version` must equal the version last read; a stale value is rejected with 409, as is a project document that is shared with another scope. x-required-scope: credentialTypePolicy:manage -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/replaceCredentialTypePolicyAttachments.generated.yml b/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/replaceCredentialTypePolicyAttachments.generated.yml index 706b823f40f..27cfa44eb81 100644 --- a/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/replaceCredentialTypePolicyAttachments.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/replaceCredentialTypePolicyAttachments.generated.yml @@ -1,12 +1,12 @@ operationId: replaceCredentialTypePolicyAttachments tags: - CredentialTypePolicy -summary: Replace a scope's attached policy documents -description: Replaces every attachment on a scope. `scopeId` comes from the scope's `GET` response once it has been written. Each `policyId` and each `(isFloor, priority)` pair must be unique within the list. Last write wins; the scope's version is bumped. +summary: "Preview: Replace a scope's attached policy documents" +description: |- + **Preview** — breaking changes may still occur without major version bump. + + Replaces every attachment on a scope. `scopeId` comes from the scope's `GET` response once it has been written. Each `policyId` and each `(isFloor, priority)` pair must be unique within the list. `version` must match the current scope version. A stale version returns 409 without changes. A successful write bumps the scope's version. x-required-scope: credentialTypePolicy:manage -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string @@ -37,8 +37,12 @@ requestBody: - policyId - priority - isFloor + version: + type: integer + minimum: 0 required: - attachments + - version responses: '200': description: Operation successful. @@ -136,6 +140,8 @@ responses: $ref: ../../../../shared/spec/responses/forbidden.yml '404': $ref: ../../../../shared/spec/responses/notFound.yml + '409': + $ref: ../../../../shared/spec/responses/conflict.yml '415': $ref: ../../../../shared/spec/responses/unsupportedMediaType.yml '503': diff --git a/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/updateCredentialTypePolicyDocument.generated.yml b/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/updateCredentialTypePolicyDocument.generated.yml index 7ad573bd944..e823e4ced2a 100644 --- a/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/updateCredentialTypePolicyDocument.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/credential-type-policies/spec/paths/updateCredentialTypePolicyDocument.generated.yml @@ -1,12 +1,12 @@ operationId: updateCredentialTypePolicyDocument tags: - CredentialTypePolicy -summary: Replace the rules of a credential type policy document -description: Replaces the document's whole rule list. `version` must equal the version last read; a stale value is rejected with 409. Every scope the document is attached to has its version bumped. A `delegate` rule is rejected when the document is attached to a project scope. +summary: 'Preview: Replace the rules of a credential type policy document' +description: |- + **Preview** — breaking changes may still occur without major version bump. + + Replaces the document's whole rule list. `version` must equal the version last read; a stale value is rejected with 409. Every scope the document is attached to has its version bumped. A `delegate` rule is rejected when the document is attached to a project scope. x-required-scope: credentialTypePolicy:manage -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/credentials/spec/paths/createCredential.generated.yml b/packages/cli/src/public-api/v1/handlers/credentials/spec/paths/createCredential.generated.yml index 938a549e692..c1409353263 100644 --- a/packages/cli/src/public-api/v1/handlers/credentials/spec/paths/createCredential.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/credentials/spec/paths/createCredential.generated.yml @@ -4,9 +4,6 @@ tags: summary: Create a credential description: Creates a credential that can be used by nodes of the specified type. x-required-scope: credential:create -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true requestBody: required: true content: diff --git a/packages/cli/src/public-api/v1/handlers/credentials/spec/paths/deleteCredential.generated.yml b/packages/cli/src/public-api/v1/handlers/credentials/spec/paths/deleteCredential.generated.yml index 85b5709b31a..d8dbc479693 100644 --- a/packages/cli/src/public-api/v1/handlers/credentials/spec/paths/deleteCredential.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/credentials/spec/paths/deleteCredential.generated.yml @@ -4,9 +4,6 @@ tags: summary: Delete credential by ID description: Deletes a credential from your instance. You must be the owner of the credential. x-required-scope: credential:delete -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/credentials/spec/paths/getCredential.generated.yml b/packages/cli/src/public-api/v1/handlers/credentials/spec/paths/getCredential.generated.yml index 7d1d41ecb70..31da45c206d 100644 --- a/packages/cli/src/public-api/v1/handlers/credentials/spec/paths/getCredential.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/credentials/spec/paths/getCredential.generated.yml @@ -4,9 +4,6 @@ tags: summary: Get credential by ID description: Retrieves a credential by ID. Credential data (secrets) is not included. x-required-scope: credential:read -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/credentials/spec/paths/getCredentialType.generated.yml b/packages/cli/src/public-api/v1/handlers/credentials/spec/paths/getCredentialType.generated.yml index 6534e74f44c..7f4017c68ad 100644 --- a/packages/cli/src/public-api/v1/handlers/credentials/spec/paths/getCredentialType.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/credentials/spec/paths/getCredentialType.generated.yml @@ -2,9 +2,6 @@ operationId: getCredentialType tags: - Credential summary: Show credential data schema -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/credentials/spec/paths/getCredentials.generated.yml b/packages/cli/src/public-api/v1/handlers/credentials/spec/paths/getCredentials.generated.yml index 6c462b011c9..47a2ad420d8 100644 --- a/packages/cli/src/public-api/v1/handlers/credentials/spec/paths/getCredentials.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/credentials/spec/paths/getCredentials.generated.yml @@ -7,9 +7,6 @@ x-required-scope: credential:list parameters: - $ref: ../../../../shared/spec/parameters/limit.yml - $ref: ../../../../shared/spec/parameters/cursor.yml -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true responses: '200': description: Operation successful. diff --git a/packages/cli/src/public-api/v1/handlers/credentials/spec/paths/testCredential.generated.yml b/packages/cli/src/public-api/v1/handlers/credentials/spec/paths/testCredential.generated.yml index 6b2dcdf829d..4b2d71ed982 100644 --- a/packages/cli/src/public-api/v1/handlers/credentials/spec/paths/testCredential.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/credentials/spec/paths/testCredential.generated.yml @@ -4,9 +4,6 @@ tags: summary: Test credential by ID description: Tests a credential by ID using the stored credential data. x-required-scope: credential:read -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/credentials/spec/paths/transferCredential.generated.yml b/packages/cli/src/public-api/v1/handlers/credentials/spec/paths/transferCredential.generated.yml index 21e24e6ef2b..fa8f7208559 100644 --- a/packages/cli/src/public-api/v1/handlers/credentials/spec/paths/transferCredential.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/credentials/spec/paths/transferCredential.generated.yml @@ -4,9 +4,6 @@ tags: summary: Transfer a credential to another project. description: Transfer a credential to another project. x-required-scope: credential:move -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/credentials/spec/paths/updateCredential.generated.yml b/packages/cli/src/public-api/v1/handlers/credentials/spec/paths/updateCredential.generated.yml index 7a0d2cbac32..e53558daeaa 100644 --- a/packages/cli/src/public-api/v1/handlers/credentials/spec/paths/updateCredential.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/credentials/spec/paths/updateCredential.generated.yml @@ -4,9 +4,6 @@ tags: summary: Update credential by ID description: Updates an existing credential. You must be the owner of the credential. x-required-scope: credential:update -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/clearDataTableRows.generated.yml b/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/clearDataTableRows.generated.yml index e14fdf94745..4e5c0db89dc 100644 --- a/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/clearDataTableRows.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/clearDataTableRows.generated.yml @@ -4,9 +4,6 @@ tags: summary: Clear all rows from a data table description: Permanently delete all rows from a data table. The table structure is retained. This action cannot be undone. x-required-scope: dataTableRow:delete -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/createDataTable.generated.yml b/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/createDataTable.generated.yml index 8899acfe035..5d26004501e 100644 --- a/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/createDataTable.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/createDataTable.generated.yml @@ -4,9 +4,6 @@ tags: summary: Create a new data table description: Create a new data table in your personal project or a team project you have access to. x-required-scope: dataTable:create -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true requestBody: required: true content: diff --git a/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/createDataTableColumn.generated.yml b/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/createDataTableColumn.generated.yml index 60e4191ba4d..21f181ae6ff 100644 --- a/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/createDataTableColumn.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/createDataTableColumn.generated.yml @@ -4,9 +4,6 @@ tags: summary: Add a column to a data table description: Add a new column to an existing data table. x-required-scope: dataTableColumn:create -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/createDataTableRows.generated.yml b/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/createDataTableRows.generated.yml index e32a082f39f..04832e75f1f 100644 --- a/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/createDataTableRows.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/createDataTableRows.generated.yml @@ -4,9 +4,6 @@ tags: summary: Insert rows into a data table description: Insert one or more rows into a data table. x-required-scope: dataTableRow:create -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/deleteDataTable.generated.yml b/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/deleteDataTable.generated.yml index 6f9c11d8046..bd425e3d14d 100644 --- a/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/deleteDataTable.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/deleteDataTable.generated.yml @@ -4,9 +4,6 @@ tags: summary: Delete a data table description: Delete a data table. This will also delete all rows in the table. x-required-scope: dataTable:delete -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/deleteDataTableColumn.generated.yml b/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/deleteDataTableColumn.generated.yml index f0c5227057f..d2cc5f05b0f 100644 --- a/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/deleteDataTableColumn.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/deleteDataTableColumn.generated.yml @@ -4,9 +4,6 @@ tags: summary: Delete a column description: Remove a column from a data table. This will also delete all data in the column. x-required-scope: dataTableColumn:delete -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/deleteDataTableRows.generated.yml b/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/deleteDataTableRows.generated.yml index 9e70a4ff3ba..e0c428defdd 100644 --- a/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/deleteDataTableRows.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/deleteDataTableRows.generated.yml @@ -4,9 +4,6 @@ tags: summary: Delete rows from a data table description: Delete rows matching filter conditions from a data table. Filter is required to prevent accidental deletion of all data. x-required-scope: dataTableRow:delete -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/getDataTable.generated.yml b/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/getDataTable.generated.yml index 86ebb79382c..91cbf1803a4 100644 --- a/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/getDataTable.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/getDataTable.generated.yml @@ -4,9 +4,6 @@ tags: summary: Get a data table description: Retrieve a specific data table by ID. x-required-scope: dataTable:read -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/listDataTableColumns.generated.yml b/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/listDataTableColumns.generated.yml index 1d914eab6a7..c750d74a04f 100644 --- a/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/listDataTableColumns.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/listDataTableColumns.generated.yml @@ -4,9 +4,6 @@ tags: summary: List columns of a data table description: Retrieve all columns for a specific data table. x-required-scope: dataTableColumn:read -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/listDataTableRows.generated.yml b/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/listDataTableRows.generated.yml index 4b46102a032..add32b2fae8 100644 --- a/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/listDataTableRows.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/listDataTableRows.generated.yml @@ -36,9 +36,6 @@ parameters: description: Search text across all string columns name: search in: query -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true responses: '200': description: Operation successful. diff --git a/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/listDataTables.generated.yml b/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/listDataTables.generated.yml index 3388d065698..d7457c557c9 100644 --- a/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/listDataTables.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/listDataTables.generated.yml @@ -31,9 +31,6 @@ parameters: example: name:asc name: sortBy in: query -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true responses: '200': description: Operation successful. diff --git a/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/updateDataTable.generated.yml b/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/updateDataTable.generated.yml index 05f540ca857..0295f14f8c5 100644 --- a/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/updateDataTable.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/updateDataTable.generated.yml @@ -4,9 +4,6 @@ tags: summary: Update a data table description: Update a data table's name. x-required-scope: dataTable:update -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/updateDataTableColumn.generated.yml b/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/updateDataTableColumn.generated.yml index 50a689c0c3c..30fda93c6a3 100644 --- a/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/updateDataTableColumn.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/updateDataTableColumn.generated.yml @@ -4,9 +4,6 @@ tags: summary: Update a column description: Rename and/or reorder a column in a data table. x-required-scope: dataTableColumn:update -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/updateDataTableRows.generated.yml b/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/updateDataTableRows.generated.yml index 4f264fd1bc8..5ad03bbc9dd 100644 --- a/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/updateDataTableRows.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/updateDataTableRows.generated.yml @@ -4,9 +4,6 @@ tags: summary: Update rows in a data table description: Update rows matching filter conditions in a data table. x-required-scope: dataTableRow:update -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/upsertDataTableRow.generated.yml b/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/upsertDataTableRow.generated.yml index 779657cc9e3..ad687552198 100644 --- a/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/upsertDataTableRow.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/data-tables/spec/paths/upsertDataTableRow.generated.yml @@ -4,9 +4,6 @@ tags: summary: Upsert a row in a data table description: Update an existing row, or insert a new one if no row matches the filter conditions. x-required-scope: dataTableRow:upsert -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/data-tables/spec/schemas/parameters/dataTableId.yml b/packages/cli/src/public-api/v1/handlers/data-tables/spec/schemas/parameters/dataTableId.yml deleted file mode 100644 index 5f1027b24a7..00000000000 --- a/packages/cli/src/public-api/v1/handlers/data-tables/spec/schemas/parameters/dataTableId.yml +++ /dev/null @@ -1,7 +0,0 @@ -name: dataTableId -in: path -description: The ID of the data table -required: true -schema: - type: string - format: nanoid diff --git a/packages/cli/src/public-api/v1/handlers/decorator-routed.handler.ts b/packages/cli/src/public-api/v1/handlers/decorator-routed.handler.ts deleted file mode 100644 index fd249f93e1a..00000000000 --- a/packages/cli/src/public-api/v1/handlers/decorator-routed.handler.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { RequestHandler } from 'express'; - -/** - * A stub for decorator-routed operations in the eov OpenAPI spec. - * These operations are routed by the runtime registry, not express-openapi-validator, so they don't have a real handler to point at. - * The stub is required so express-openapi-validator's operation-handler installer doesn't error on them. - * Example in `packages/cli/src/public-api/v1/handlers/tags/spec/paths/getTags.generated.yml`. - */ -export const unreachable: RequestHandler = (_req, res) => { - res.status(500).json({ - message: - 'Unexpected: this operation should have been handled by PublicApiControllerRegistry before reaching express-openapi-validator', - }); -}; diff --git a/packages/cli/src/public-api/v1/handlers/discover/__tests__/discover.service.test.ts b/packages/cli/src/public-api/v1/handlers/discover/__tests__/discover.service.test.ts index 0af4321298a..d7736ba3dd2 100644 --- a/packages/cli/src/public-api/v1/handlers/discover/__tests__/discover.service.test.ts +++ b/packages/cli/src/public-api/v1/handlers/discover/__tests__/discover.service.test.ts @@ -1,48 +1,7 @@ import type { ApiKeyScope } from '@n8n/permissions'; import { isRecord } from '@n8n/utils/is-record'; -import * as middlewares from '@/public-api/v1/shared/middlewares/global.middleware'; - -// Mock middleware factories before any handler is loaded via require() -// The tagged wrapper must still have __apiKeyScope for introspection -const createMockMiddleware = (_req: unknown, _res: unknown, next: unknown) => (next as Function)(); -vi.spyOn(middlewares, 'publicApiScope').mockImplementation((scope: ApiKeyScope) => { - return Object.assign( - (req: unknown, res: unknown, next: unknown) => createMockMiddleware(req, res, next), - { __apiKeyScope: scope }, - ) as middlewares.ScopeTaggedMiddleware; -}); -vi.spyOn(middlewares, 'apiKeyHasScopeWithGlobalScopeFallback').mockImplementation( - (config: { scope: ApiKeyScope } | { apiKeyScope: ApiKeyScope; globalScope: unknown }) => { - const scope = 'scope' in config ? config.scope : config.apiKeyScope; - return Object.assign( - (req: unknown, res: unknown, next: unknown) => createMockMiddleware(req, res, next), - { __apiKeyScope: scope }, - ) as middlewares.ScopeTaggedMiddleware; - }, -); - -// Also mock other middleware that handlers import -vi.spyOn(middlewares, 'projectScope').mockReturnValue(createMockMiddleware as any); -vi.spyOn(middlewares, 'validCursor').mockReturnValue(createMockMiddleware as any); -vi.spyOn(middlewares, 'globalScope').mockReturnValue(createMockMiddleware as any); -vi.spyOn(middlewares, 'validLicenseWithUserQuota').mockReturnValue(createMockMiddleware as any); -vi.spyOn(middlewares, 'isLicensed').mockReturnValue(createMockMiddleware as any); - -// `discover.service` builds its endpoint registry at module-evaluation time by -// reading middleware metadata, so it must be imported *after* the spies above -// are installed. A static import is hoisted above them, so load it dynamically. -let buildDiscoverResponse: typeof import('../discover.service.js').buildDiscoverResponse; -let _resetCache: typeof import('../discover.service.js')._resetCache; - -beforeAll(async () => { - ({ buildDiscoverResponse, _resetCache } = await import('../discover.service.js')); - // Warm the registry once. The first call cold-loads and transforms all - // handler modules (and their transitive graph) through Vite, which can - // approach the default 5s test timeout. Paying it here in the hook keeps - // the individual tests fast and non-flaky. - await buildDiscoverResponse([] as ApiKeyScope[]); -}, 30_000); +import { buildDiscoverResponse, _resetCache } from '../discover.service'; beforeEach(() => { _resetCache(); diff --git a/packages/cli/src/public-api/v1/handlers/discover/discover.service.ts b/packages/cli/src/public-api/v1/handlers/discover/discover.service.ts index 08bb111e383..abcbe059446 100644 --- a/packages/cli/src/public-api/v1/handlers/discover/discover.service.ts +++ b/packages/cli/src/public-api/v1/handlers/discover/discover.service.ts @@ -1,19 +1,13 @@ -import RefParser from '@apidevtools/json-schema-ref-parser'; import type { DiscoverDataPublic } from '@n8n/api-types'; import type { ApiKeyScopeRequirement } from '@n8n/decorators'; -import { isRecord } from '@n8n/utils/is-record'; -import path from 'path'; import { apiKeyScopesSatisfy, - HTTP_METHODS, resolvePublicApiRoutes, - scopeRequirementFromString, scopesInRequirement, toOpenApiPathTemplate, } from '../../../public-api-route-resolver'; import { buildRequestBodyJsonSchema } from '../../openapi-gen/decorator-routes'; -import { extractScopeFromEovHandlerChain } from '../../shared/public-api-scope-lookup'; import '../../controllers'; @@ -44,95 +38,9 @@ export interface DiscoverOptions { operation?: string; } -let cachedEndpointsPromise: Promise | undefined; +let cachedEndpoints: EndpointInfo[] | undefined; -/** - * Extract the request body schema from an operation. - * The spec is already fully dereferenced by RefParser.dereference(). - */ -function extractRequestSchema( - operation: Record, -): Record | undefined { - if (!isRecord(operation.requestBody)) return undefined; - const content = operation.requestBody.content; - if (!isRecord(content)) return undefined; - const json = content['application/json']; - if (!isRecord(json)) return undefined; - const schema = json.schema; - return isRecord(schema) ? schema : undefined; -} - -async function parseEndpointsFromSpec(): Promise { - cachedEndpointsPromise ??= buildAllEndpoints(); - return await cachedEndpointsPromise; -} - -async function buildAllEndpoints(): Promise { - return [...(await buildEovEndpoints()), ...buildDecoratorEndpoints()]; -} - -async function buildEovEndpoints(): Promise { - const specPath = path.join(__dirname, '..', '..', 'openapi.yml'); - const publicApiRoot = path.join(__dirname, '..', '..', '..'); - - const spec = await RefParser.dereference(specPath); - - if (!isRecord(spec) || !isRecord(spec.paths)) return []; - - const endpoints: EndpointInfo[] = []; - const handlerCache = new Map>(); - - for (const [pathKey, pathValue] of Object.entries(spec.paths)) { - if (!isRecord(pathValue)) continue; - - for (const method of HTTP_METHODS) { - const operation = pathValue[method]; - if (!isRecord(operation)) continue; - if (operation['x-decorator-routed'] === true) continue; - - const operationId = operation['x-eov-operation-id']; - const handlerPath = operation['x-eov-operation-handler']; - if (typeof operationId !== 'string' || typeof handlerPath !== 'string') continue; - - const tags = Array.isArray(operation.tags) ? operation.tags : []; - const tag = typeof tags[0] === 'string' ? tags[0] : 'Other'; - - let handlerModule = handlerCache.get(handlerPath); - if (!handlerModule) { - try { - const fullHandlerPath = path.join(publicApiRoot, `${handlerPath}.js`); - const imported: unknown = await import(fullHandlerPath); - if (!isRecord(imported)) continue; - const loaded = isRecord(imported.default) ? imported.default : imported; - if (!isRecord(loaded)) continue; - handlerModule = loaded; - handlerCache.set(handlerPath, handlerModule); - } catch { - continue; - } - } - - const middlewareChain = handlerModule[operationId]; - const scope = Array.isArray(middlewareChain) - ? extractScopeFromEovHandlerChain(middlewareChain) - : undefined; - - endpoints.push({ - method: method.toUpperCase(), - path: `/api/v1${pathKey}`, - operationId, - tag, - // eov middleware tags itself with a flat, possibly comma-joined scope string. - scope: scope ? scopeRequirementFromString(scope) : null, - requestSchema: extractRequestSchema(operation), - }); - } - } - - return endpoints; -} - -function buildDecoratorEndpoints(): EndpointInfo[] { +function buildEndpoints(): EndpointInfo[] { return resolvePublicApiRoutes().map((route) => ({ method: route.method.toUpperCase(), path: `/api/v1${toOpenApiPathTemplate(route.path)}`, @@ -151,7 +59,11 @@ export async function buildDiscoverResponse( callerScopes: readonly string[], options?: DiscoverOptions, ): Promise { - const allEndpoints = await parseEndpointsFromSpec(); + if (!cachedEndpoints) { + cachedEndpoints = buildEndpoints(); + } + + const allEndpoints = cachedEndpoints; const includeSchemas = options?.includeSchemas === true; // Same any/all matching the registry enforces, so /discover shows exactly what the caller may call. @@ -253,5 +165,5 @@ export async function buildDiscoverResponse( /** Exported for testing — resets the cached endpoints */ export function _resetCache(): void { - cachedEndpointsPromise = undefined; + cachedEndpoints = undefined; } diff --git a/packages/cli/src/public-api/v1/handlers/discover/spec/paths/getDiscover.generated.yml b/packages/cli/src/public-api/v1/handlers/discover/spec/paths/getDiscover.generated.yml index 283f33487e3..256ac317cf5 100644 --- a/packages/cli/src/public-api/v1/handlers/discover/spec/paths/getDiscover.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/discover/spec/paths/getDiscover.generated.yml @@ -3,9 +3,6 @@ tags: - Discover summary: Discover available API capabilities description: Returns a filtered capability map based on the caller's API key scopes. Each resource includes the operations and endpoints accessible to the authenticated API key. Use query parameters to narrow the response. -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/executions/spec/paths/deleteExecution.generated.yml b/packages/cli/src/public-api/v1/handlers/executions/spec/paths/deleteExecution.generated.yml index 6de8193312f..4f92bf03563 100644 --- a/packages/cli/src/public-api/v1/handlers/executions/spec/paths/deleteExecution.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/executions/spec/paths/deleteExecution.generated.yml @@ -4,9 +4,6 @@ tags: summary: Delete an execution description: Deletes an execution from your instance. x-required-scope: execution:delete -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: integer diff --git a/packages/cli/src/public-api/v1/handlers/executions/spec/paths/getExecution.generated.yml b/packages/cli/src/public-api/v1/handlers/executions/spec/paths/getExecution.generated.yml index 329097122a6..100a38f6f6c 100644 --- a/packages/cli/src/public-api/v1/handlers/executions/spec/paths/getExecution.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/executions/spec/paths/getExecution.generated.yml @@ -4,9 +4,6 @@ tags: summary: Retrieve an execution description: Retrieve an execution from your instance. x-required-scope: execution:read -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: integer diff --git a/packages/cli/src/public-api/v1/handlers/executions/spec/paths/getExecutionTags.generated.yml b/packages/cli/src/public-api/v1/handlers/executions/spec/paths/getExecutionTags.generated.yml index 5e2fa5c64b6..a6ac18448f0 100644 --- a/packages/cli/src/public-api/v1/handlers/executions/spec/paths/getExecutionTags.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/executions/spec/paths/getExecutionTags.generated.yml @@ -4,9 +4,6 @@ tags: summary: Get execution tags description: Get annotation tags for an execution. x-required-scope: executionTags:list -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: integer diff --git a/packages/cli/src/public-api/v1/handlers/executions/spec/paths/getExecutions.generated.yml b/packages/cli/src/public-api/v1/handlers/executions/spec/paths/getExecutions.generated.yml index b0d04f98ec8..493eeae0461 100644 --- a/packages/cli/src/public-api/v1/handlers/executions/spec/paths/getExecutions.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/executions/spec/paths/getExecutions.generated.yml @@ -80,9 +80,6 @@ parameters: required: false name: startedBefore in: query -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true responses: '200': description: Operation successful. diff --git a/packages/cli/src/public-api/v1/handlers/executions/spec/paths/retryExecution.generated.yml b/packages/cli/src/public-api/v1/handlers/executions/spec/paths/retryExecution.generated.yml index 39db4feb77f..8defd0a7d26 100644 --- a/packages/cli/src/public-api/v1/handlers/executions/spec/paths/retryExecution.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/executions/spec/paths/retryExecution.generated.yml @@ -4,9 +4,6 @@ tags: summary: Retry an execution description: Retry an execution from your instance. x-required-scope: execution:retry -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: integer diff --git a/packages/cli/src/public-api/v1/handlers/executions/spec/paths/stopExecution.generated.yml b/packages/cli/src/public-api/v1/handlers/executions/spec/paths/stopExecution.generated.yml index 9c0a97f4cc2..ffa848f555a 100644 --- a/packages/cli/src/public-api/v1/handlers/executions/spec/paths/stopExecution.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/executions/spec/paths/stopExecution.generated.yml @@ -4,9 +4,6 @@ tags: summary: Stop an execution description: Stop an execution by id. x-required-scope: execution:stop -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: integer diff --git a/packages/cli/src/public-api/v1/handlers/executions/spec/paths/stopManyExecutions.generated.yml b/packages/cli/src/public-api/v1/handlers/executions/spec/paths/stopManyExecutions.generated.yml index e580c0df326..8f72bac434b 100644 --- a/packages/cli/src/public-api/v1/handlers/executions/spec/paths/stopManyExecutions.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/executions/spec/paths/stopManyExecutions.generated.yml @@ -4,9 +4,6 @@ tags: summary: Stop multiple executions description: Stop multiple executions from your instance based on filter criteria. x-required-scope: execution:stop -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true requestBody: required: true content: diff --git a/packages/cli/src/public-api/v1/handlers/executions/spec/paths/updateExecutionTags.generated.yml b/packages/cli/src/public-api/v1/handlers/executions/spec/paths/updateExecutionTags.generated.yml index 2dd4508e6b4..32477fcfa9d 100644 --- a/packages/cli/src/public-api/v1/handlers/executions/spec/paths/updateExecutionTags.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/executions/spec/paths/updateExecutionTags.generated.yml @@ -4,9 +4,6 @@ tags: summary: Update tags of an execution description: Update annotation tags of an execution. x-required-scope: executionTags:update -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: integer diff --git a/packages/cli/src/public-api/v1/handlers/insights/spec/paths/getInsightsSummary.generated.yml b/packages/cli/src/public-api/v1/handlers/insights/spec/paths/getInsightsSummary.generated.yml index 939ff350b3a..e7d2d66bb97 100644 --- a/packages/cli/src/public-api/v1/handlers/insights/spec/paths/getInsightsSummary.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/insights/spec/paths/getInsightsSummary.generated.yml @@ -4,9 +4,6 @@ tags: summary: Retrieve insights summary description: Retrieve the insights summary for the selected date range. x-required-scope: insights:read -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/n8n-packages/__tests__/n8n-packages.handler.test.ts b/packages/cli/src/public-api/v1/handlers/n8n-packages/__tests__/n8n-packages.handler.test.ts deleted file mode 100644 index 26ac8efc7a8..00000000000 --- a/packages/cli/src/public-api/v1/handlers/n8n-packages/__tests__/n8n-packages.handler.test.ts +++ /dev/null @@ -1,591 +0,0 @@ -import { EventService } from '@n8n/backend-services'; -import { mockInstance } from '@n8n/backend-test-utils'; -import type { AuthenticatedRequest } from '@n8n/db'; -import { Container } from '@n8n/di'; -import type { Response } from 'express'; -import { UserError } from 'n8n-workflow'; -import { PassThrough } from 'node:stream'; -import type { Mocked } from 'vitest'; - -import { BadRequestError, ForbiddenError, NotFoundError } from '@n8n/errors'; -import type { RelayEventMap } from '@/events/maps/relay.event-map'; -import { - PackageEntityAccessDeniedError, - PackageEntityNotFoundError, - PackageExportBlockedError, -} from '@/modules/n8n-packages/entities/package-export.errors'; -import { N8nPackagesService } from '@/modules/n8n-packages/n8n-packages.service'; -import * as middlewares from '@/public-api/v1/shared/middlewares/global.middleware'; - -const mockMiddleware = vi.fn(async (_req: unknown, _res: unknown, next: unknown) => - (next as () => void)(), -) as unknown as middlewares.ScopeTaggedMiddleware; -vi.spyOn(middlewares, 'publicApiCompositeScope').mockReturnValue(mockMiddleware); -vi.spyOn(middlewares, 'publicApiScope').mockReturnValue(mockMiddleware); - -// Loaded after the middleware spies above are installed (the handler captures -// middleware at module-evaluation time). Typed loosely to invoke route entries. -let handler: Record unknown>>; -// exportPackage = [middleware(...), businessLogic]; index 1 is the handler under test. -let exportPackage: (...args: unknown[]) => unknown; - -beforeAll(async () => { - handler = (await import('../n8n-packages.handler.js')) as unknown as typeof handler; - exportPackage = handler.exportPackage[1]; -}); - -const EXPORT_COUNTS = { - agents: 0, - workflows: 2, - folders: 1, - credentials: 0, - dataTables: 0, - variables: 0, - tags: 0, -}; - -describe('n8n-packages handler', () => { - let mockService: Mocked; - let mockEventService: Mocked; - - function makeRequest( - body: { - workflowIds?: string[]; - folderIds?: string[]; - projectIds?: string[]; - includeVariableValues?: boolean; - includeTags?: boolean; - dependencyPolicy?: string; - versionPolicy?: string; - credentialExportPolicy?: string; - includeArchivedWorkflows?: boolean; - }, - apiKeyScopes?: string[], - ) { - return { - user: { id: 'user-1' }, - body, - tokenGrant: apiKeyScopes ? { apiKeyScopes } : undefined, - } as unknown as AuthenticatedRequest; - } - - function makeResponse() { - const res = new PassThrough() as unknown as Response & PassThrough; - res.setHeader = vi.fn().mockReturnValue(res); - return res; - } - - async function run(req: AuthenticatedRequest, res: Response) { - let caught: unknown; - try { - await exportPackage(req, res); - } catch (error) { - caught = error; - } - return caught; - } - - function emittedEvent(name: 'n8n-package-export-failed' | 'n8n-package-import-failed') { - const call = mockEventService.emit.mock.calls.find(([eventName]) => eventName === name); - return call?.[1] as RelayEventMap[typeof name] | undefined; - } - - beforeEach(() => { - vi.clearAllMocks(); - mockService = mockInstance(N8nPackagesService); - mockEventService = mockInstance(EventService); - - vi.spyOn(Container, 'get').mockImplementation((serviceClass) => { - if ( - serviceClass === N8nPackagesService || - (typeof serviceClass === 'function' && serviceClass.name === 'N8nPackagesService') - ) { - return mockService; - } - if ( - serviceClass === EventService || - (typeof serviceClass === 'function' && serviceClass.name === 'EventService') - ) { - return mockEventService; - } - return {} as never; - }); - }); - - describe('exportPackage', () => { - it('throws BadRequestError when the payload fails DTO validation', async () => { - const caught = await run( - makeRequest({ workflowIds: [''] }, ['workflow:export']), - makeResponse(), - ); - - expect(caught).toBeInstanceOf(BadRequestError); - expect(mockService.exportPackage).not.toHaveBeenCalled(); - expect(emittedEvent('n8n-package-export-failed')).toMatchObject({ reason: 'validation' }); - }); - - it('throws BadRequestError when both workflowIds and projectIds are provided', async () => { - const caught = await run( - makeRequest({ workflowIds: ['wf-1'], projectIds: ['project-1'] }, [ - 'workflow:export', - 'project:export', - ]), - makeResponse(), - ); - - expect(caught).toBeInstanceOf(BadRequestError); - expect(caught).toMatchObject({ - message: 'Provide either agentIds/workflowIds/folderIds or projectIds, not both', - }); - expect(mockService.exportPackage).not.toHaveBeenCalled(); - }); - - it('throws BadRequestError when folderIds and projectIds are both provided', async () => { - const caught = await run( - makeRequest({ folderIds: ['fld-1'], projectIds: ['project-1'] }, [ - 'workflow:export', - 'project:export', - ]), - makeResponse(), - ); - - expect(caught).toBeInstanceOf(BadRequestError); - expect(caught).toMatchObject({ - message: 'Provide either agentIds/workflowIds/folderIds or projectIds, not both', - }); - expect(mockService.exportPackage).not.toHaveBeenCalled(); - }); - - it('throws BadRequestError when neither workflowIds, folderIds nor projectIds are provided', async () => { - const caught = await run(makeRequest({}, ['workflow:export']), makeResponse()); - - expect(caught).toBeInstanceOf(BadRequestError); - expect(caught).toMatchObject({ - message: 'At least one agentId, workflowId, folderId, or projectId is required', - }); - expect(mockService.exportPackage).not.toHaveBeenCalled(); - }); - - it('throws ForbiddenError when the API key carries no scopes', async () => { - const caught = await run(makeRequest({ workflowIds: ['wf-1'] }), makeResponse()); - - expect(caught).toBeInstanceOf(ForbiddenError); - expect(mockService.exportPackage).not.toHaveBeenCalled(); - expect(emittedEvent('n8n-package-export-failed')).toMatchObject({ - reason: 'access-denied', - workflowIds: ['wf-1'], - }); - }); - - it('throws ForbiddenError when exporting workflows without workflow:export scope', async () => { - const caught = await run( - makeRequest({ workflowIds: ['wf-1'] }, ['project:export']), - makeResponse(), - ); - - expect(caught).toBeInstanceOf(ForbiddenError); - expect(mockService.exportPackage).not.toHaveBeenCalled(); - }); - - it('throws ForbiddenError when exporting projects without project:export scope', async () => { - const caught = await run( - makeRequest({ projectIds: ['project-1'] }, ['workflow:export']), - makeResponse(), - ); - - expect(caught).toBeInstanceOf(ForbiddenError); - expect(mockService.exportPackage).not.toHaveBeenCalled(); - }); - - it('throws ForbiddenError when exporting folders without workflow:export scope', async () => { - const caught = await run( - makeRequest({ folderIds: ['fld-1'] }, ['project:export']), - makeResponse(), - ); - - expect(caught).toBeInstanceOf(ForbiddenError); - expect(mockService.exportPackage).not.toHaveBeenCalled(); - }); - - it('does not reject upfront without variable:list scope; forwards canExportVariableValues=false for the service to enforce', async () => { - const stream = new PassThrough(); - mockService.exportPackage.mockResolvedValue({ stream, counts: EXPORT_COUNTS }); - const res = makeResponse(); - - const resultPromise = run(makeRequest({ workflowIds: ['wf-1'] }, ['workflow:export']), res); - stream.end(Buffer.from('package-bytes')); - const caught = await resultPromise; - - expect(caught).toBeUndefined(); - expect(mockService.exportPackage).toHaveBeenCalledWith({ - agentIds: [], - user: { id: 'user-1' }, - workflowIds: ['wf-1'], - folderIds: [], - projectIds: [], - includeVariableValues: true, - canExportVariableValues: false, - includeTags: true, - dependencyPolicy: 'fail', - versionPolicy: 'latest', - credentialExportPolicy: 'expression-values-only', - includeArchivedWorkflows: false, - }); - }); - - it('allows value-less export without variable:list scope', async () => { - const stream = new PassThrough(); - mockService.exportPackage.mockResolvedValue({ stream, counts: EXPORT_COUNTS }); - const res = makeResponse(); - - const resultPromise = run( - makeRequest({ workflowIds: ['wf-1'], includeVariableValues: false }, ['workflow:export']), - res, - ); - stream.end(Buffer.from('package-bytes')); - const caught = await resultPromise; - - expect(caught).toBeUndefined(); - expect(mockService.exportPackage).toHaveBeenCalledWith({ - agentIds: [], - user: { id: 'user-1' }, - workflowIds: ['wf-1'], - folderIds: [], - projectIds: [], - includeVariableValues: false, - canExportVariableValues: false, - includeTags: true, - dependencyPolicy: 'fail', - versionPolicy: 'latest', - credentialExportPolicy: 'expression-values-only', - includeArchivedWorkflows: false, - }); - }); - - it('propagates the ForbiddenError thrown by the service scope gate and emits access-denied', async () => { - mockService.exportPackage.mockRejectedValue( - new ForbiddenError('missing the variable:list scope'), - ); - - const caught = await run( - makeRequest({ workflowIds: ['wf-1'] }, ['workflow:export']), - makeResponse(), - ); - - expect(caught).toBeInstanceOf(ForbiddenError); - expect(emittedEvent('n8n-package-export-failed')).toMatchObject({ - reason: 'access-denied', - workflowIds: ['wf-1'], - }); - }); - - it('emits n8n-package-export-failed with reason=entity-not-found when the service rejects with NotFoundError', async () => { - mockService.exportPackage.mockRejectedValue(new NotFoundError('not found')); - - await run( - makeRequest({ workflowIds: ['wf-1'] }, ['workflow:export', 'variable:list']), - makeResponse(), - ); - - expect(emittedEvent('n8n-package-export-failed')).toEqual({ - user: { id: 'user-1' }, - reason: 'entity-not-found', - workflowIds: ['wf-1'], - }); - }); - - it('emits n8n-package-export-failed with reason=blocked when the service rejects a blocked export', async () => { - mockService.exportPackage.mockRejectedValue(new PackageExportBlockedError('Export blocked')); - - await run( - makeRequest({ workflowIds: ['wf-1'] }, ['workflow:export', 'variable:list']), - makeResponse(), - ); - - expect(emittedEvent('n8n-package-export-failed')).toEqual({ - user: { id: 'user-1' }, - reason: 'blocked', - workflowIds: ['wf-1'], - }); - }); - - it.each([ - [ - 'access-denied', - new PackageEntityAccessDeniedError('workflows denied', { description: 'x' }), - ], - [ - 'entity-not-found', - new PackageEntityNotFoundError('workflows missing', { description: 'y' }), - ], - ])( - 'rethrows %s as a generic UserError with the same message, hiding which case occurred', - async (reason, thrownError) => { - mockService.exportPackage.mockRejectedValue(thrownError); - - const caught = await run( - makeRequest({ workflowIds: ['wf-1'] }, ['workflow:export', 'variable:list']), - makeResponse(), - ); - - expect(caught).toBeInstanceOf(UserError); - expect(caught).not.toBeInstanceOf(PackageEntityAccessDeniedError); - expect(caught).not.toBeInstanceOf(PackageEntityNotFoundError); - expect(caught).toMatchObject({ message: thrownError.message }); - expect(emittedEvent('n8n-package-export-failed')).toMatchObject({ reason }); - }, - ); - - it('streams the export for a valid workflow request', async () => { - const stream = new PassThrough(); - mockService.exportPackage.mockResolvedValue({ stream, counts: EXPORT_COUNTS }); - const res = makeResponse(); - - const resultPromise = run( - makeRequest({ workflowIds: ['wf-1', 'wf-2'] }, ['workflow:export', 'variable:list']), - res, - ); - stream.end(Buffer.from('package-bytes')); - const caught = await resultPromise; - - expect(caught).toBeUndefined(); - expect(mockService.exportPackage).toHaveBeenCalledWith({ - agentIds: [], - user: { id: 'user-1' }, - workflowIds: ['wf-1', 'wf-2'], - folderIds: [], - projectIds: [], - includeVariableValues: true, - canExportVariableValues: true, - includeTags: true, - dependencyPolicy: 'fail', - versionPolicy: 'latest', - credentialExportPolicy: 'expression-values-only', - includeArchivedWorkflows: false, - }); - expect(res.setHeader).toHaveBeenCalledWith('Content-Type', 'application/gzip'); - expect(res.setHeader).toHaveBeenCalledWith( - 'Content-Disposition', - 'attachment; filename="export.n8np"', - ); - expect(res.setHeader).toHaveBeenCalledWith( - 'X-N8n-Export-Counts', - JSON.stringify(EXPORT_COUNTS), - ); - expect(res.setHeader).toHaveBeenCalledWith( - 'Access-Control-Expose-Headers', - 'X-N8n-Export-Counts', - ); - expect(mockEventService.emit).not.toHaveBeenCalled(); - }); - - it('forwards a non-default missing workflow dependency policy', async () => { - const stream = new PassThrough(); - mockService.exportPackage.mockResolvedValue({ stream, counts: EXPORT_COUNTS }); - const res = makeResponse(); - - const resultPromise = run( - makeRequest( - { - workflowIds: ['wf-1'], - dependencyPolicy: 'reference-only', - }, - ['workflow:export'], - ), - res, - ); - stream.end(Buffer.from('package-bytes')); - const caught = await resultPromise; - - expect(caught).toBeUndefined(); - expect(mockService.exportPackage).toHaveBeenCalledWith({ - agentIds: [], - user: { id: 'user-1' }, - workflowIds: ['wf-1'], - folderIds: [], - projectIds: [], - includeVariableValues: true, - canExportVariableValues: false, - includeTags: true, - dependencyPolicy: 'reference-only', - versionPolicy: 'latest', - credentialExportPolicy: 'expression-values-only', - includeArchivedWorkflows: false, - }); - }); - - it('forwards a non-default workflow version policy', async () => { - const stream = new PassThrough(); - mockService.exportPackage.mockResolvedValue({ stream, counts: EXPORT_COUNTS }); - const res = makeResponse(); - - const resultPromise = run( - makeRequest({ workflowIds: ['wf-1'], versionPolicy: 'published-strict' }, [ - 'workflow:export', - ]), - res, - ); - stream.end(Buffer.from('package-bytes')); - const caught = await resultPromise; - - expect(caught).toBeUndefined(); - expect(mockService.exportPackage).toHaveBeenCalledWith( - expect.objectContaining({ versionPolicy: 'published-strict' }), - ); - }); - - it('forwards a non-default credential export policy', async () => { - const stream = new PassThrough(); - mockService.exportPackage.mockResolvedValue({ stream, counts: EXPORT_COUNTS }); - const res = makeResponse(); - - const resultPromise = run( - makeRequest({ workflowIds: ['wf-1'], credentialExportPolicy: 'no-values' }, [ - 'workflow:export', - ]), - res, - ); - stream.end(Buffer.from('package-bytes')); - const caught = await resultPromise; - - expect(caught).toBeUndefined(); - expect(mockService.exportPackage).toHaveBeenCalledWith( - expect.objectContaining({ credentialExportPolicy: 'no-values' }), - ); - }); - - it('forwards includeArchivedWorkflows', async () => { - const stream = new PassThrough(); - mockService.exportPackage.mockResolvedValue({ stream, counts: EXPORT_COUNTS }); - const res = makeResponse(); - - const resultPromise = run( - makeRequest({ workflowIds: ['wf-1'], includeArchivedWorkflows: true }, ['workflow:export']), - res, - ); - stream.end(Buffer.from('package-bytes')); - const caught = await resultPromise; - - expect(caught).toBeUndefined(); - expect(mockService.exportPackage).toHaveBeenCalledWith( - expect.objectContaining({ includeArchivedWorkflows: true }), - ); - }); - - it('streams the export for a valid project request', async () => { - const stream = new PassThrough(); - mockService.exportPackage.mockResolvedValue({ stream, counts: EXPORT_COUNTS }); - const res = makeResponse(); - - const resultPromise = run( - makeRequest({ projectIds: ['project-1'] }, ['project:export', 'variable:list']), - res, - ); - stream.end(Buffer.from('package-bytes')); - const caught = await resultPromise; - - expect(caught).toBeUndefined(); - expect(mockService.exportPackage).toHaveBeenCalledWith({ - agentIds: [], - user: { id: 'user-1' }, - workflowIds: [], - folderIds: [], - projectIds: ['project-1'], - includeVariableValues: true, - canExportVariableValues: true, - includeTags: true, - dependencyPolicy: 'fail', - versionPolicy: 'latest', - credentialExportPolicy: 'expression-values-only', - includeArchivedWorkflows: false, - }); - }); - - it('streams the export for a valid folder request', async () => { - const stream = new PassThrough(); - mockService.exportPackage.mockResolvedValue({ stream, counts: EXPORT_COUNTS }); - const res = makeResponse(); - - const resultPromise = run( - makeRequest({ folderIds: ['fld-1'] }, ['workflow:export', 'variable:list']), - res, - ); - stream.end(Buffer.from('package-bytes')); - const caught = await resultPromise; - - expect(caught).toBeUndefined(); - expect(mockService.exportPackage).toHaveBeenCalledWith({ - agentIds: [], - user: { id: 'user-1' }, - workflowIds: [], - folderIds: ['fld-1'], - projectIds: [], - includeVariableValues: true, - canExportVariableValues: true, - includeTags: true, - dependencyPolicy: 'fail', - versionPolicy: 'latest', - credentialExportPolicy: 'expression-values-only', - includeArchivedWorkflows: false, - }); - }); - - it('forwards includeVariableValues=false to the service', async () => { - const stream = new PassThrough(); - mockService.exportPackage.mockResolvedValue({ stream, counts: EXPORT_COUNTS }); - const res = makeResponse(); - - const resultPromise = run( - makeRequest({ workflowIds: ['wf-1'], includeVariableValues: false }, ['workflow:export']), - res, - ); - stream.end(Buffer.from('package-bytes')); - const caught = await resultPromise; - - expect(caught).toBeUndefined(); - expect(mockService.exportPackage).toHaveBeenCalledWith({ - agentIds: [], - user: { id: 'user-1' }, - workflowIds: ['wf-1'], - folderIds: [], - projectIds: [], - includeVariableValues: false, - canExportVariableValues: false, - includeTags: true, - dependencyPolicy: 'fail', - versionPolicy: 'latest', - credentialExportPolicy: 'expression-values-only', - includeArchivedWorkflows: false, - }); - }); - - it('forwards includeTags=false to the service', async () => { - const stream = new PassThrough(); - mockService.exportPackage.mockResolvedValue({ stream, counts: EXPORT_COUNTS }); - const res = makeResponse(); - - const resultPromise = run( - makeRequest({ workflowIds: ['wf-1'], includeTags: false }, ['workflow:export']), - res, - ); - stream.end(Buffer.from('package-bytes')); - const caught = await resultPromise; - - expect(caught).toBeUndefined(); - expect(mockService.exportPackage).toHaveBeenCalledWith({ - agentIds: [], - user: { id: 'user-1' }, - workflowIds: ['wf-1'], - folderIds: [], - projectIds: [], - includeVariableValues: true, - canExportVariableValues: false, - includeTags: false, - dependencyPolicy: 'fail', - versionPolicy: 'latest', - credentialExportPolicy: 'expression-values-only', - includeArchivedWorkflows: false, - }); - }); - }); -}); diff --git a/packages/cli/src/public-api/v1/handlers/n8n-packages/n8n-packages.handler.ts b/packages/cli/src/public-api/v1/handlers/n8n-packages/n8n-packages.handler.ts deleted file mode 100644 index 0d7f89fa2d0..00000000000 --- a/packages/cli/src/public-api/v1/handlers/n8n-packages/n8n-packages.handler.ts +++ /dev/null @@ -1,167 +0,0 @@ -import { ExportPackageRequestDto } from '@n8n/api-types'; -import { EventService } from '@n8n/backend-services'; -import type { AuthenticatedRequest } from '@n8n/db'; -import { Container } from '@n8n/di'; -import type { ApiKeyScope } from '@n8n/permissions'; -import type { Response } from 'express'; -import { UserError } from 'n8n-workflow'; - -import { BadRequestError, ForbiddenError } from '@n8n/errors'; -import { - PackageEntityAccessDeniedError, - PackageEntityNotFoundError, -} from '@/modules/n8n-packages/entities/package-export.errors'; -import { N8nPackagesService } from '@/modules/n8n-packages/n8n-packages.service'; -import type { ExportPackageResult } from '@/modules/n8n-packages/n8n-packages.types'; -import { classifyPackageFailure } from '@/modules/n8n-packages/package-failure-classifier'; - -import type { PublicAPIEndpoint } from '../../shared/handler.types'; -import { publicApiCompositeScope } from '../../shared/middlewares/global.middleware'; - -const PACKAGE_EXPORT_SCOPES = 'project:export,workflow:export,agent:export'; - -/** Header carrying the JSON-serialized true per-entity counts of the exported package. */ -const EXPORT_COUNTS_HEADER = 'X-N8n-Export-Counts'; - -type ExportPackageRequest = AuthenticatedRequest<{}, {}, ExportPackageRequestDto>; - -type N8nPackagesHandlers = { - exportPackage: PublicAPIEndpoint; -}; - -function assertPackageExportApiKeyScopes( - req: AuthenticatedRequest, - agentIds: string[], - workflowIds: string[], - folderIds: string[], - projectIds: string[], -): string[] { - const apiKeyScopes = req.tokenGrant?.apiKeyScopes; - if (!apiKeyScopes) { - throw new ForbiddenError('Forbidden'); - } - - const requiredScopes: ApiKeyScope[] = []; - if (agentIds.length > 0) { - requiredScopes.push('agent:export'); - } - // Folders are exported as a workflow-organization concern, so they share the workflow:export scope. - if (workflowIds.length > 0 || folderIds.length > 0) { - requiredScopes.push('workflow:export'); - } - if (projectIds.length > 0) { - requiredScopes.push('project:export'); - } - - for (const scope of requiredScopes) { - if (!apiKeyScopes.includes(scope)) { - throw new ForbiddenError('Forbidden'); - } - } - - return apiKeyScopes; -} - -async function streamPackageExport( - res: Response, - { stream, counts }: ExportPackageResult, -): Promise { - res.setHeader('Content-Type', 'application/gzip'); - res.setHeader('Content-Disposition', 'attachment; filename="export.n8np"'); - res.setHeader(EXPORT_COUNTS_HEADER, JSON.stringify(counts)); - // Cross-origin browser clients can only read the counts header if it's exposed. - res.setHeader('Access-Control-Expose-Headers', EXPORT_COUNTS_HEADER); - - return await new Promise((resolve, reject) => { - stream.on('error', reject); - res.on('finish', () => resolve(res)); - res.on('close', () => { - if (!res.writableFinished) stream.destroy(); - resolve(res); - }); - stream.pipe(res); - }); -} - -const n8nPackagesHandlers: N8nPackagesHandlers = { - exportPackage: [ - publicApiCompositeScope(PACKAGE_EXPORT_SCOPES), - async (req, res) => { - let agentIds: string[] = []; - let workflowIds: string[] = []; - let folderIds: string[] = []; - let projectIds: string[] = []; - let includeVariableValues: boolean = true; - - try { - const payload = ExportPackageRequestDto.safeParse(req.body); - if (!payload.success) { - throw new BadRequestError(payload.error.errors.map(({ message }) => message).join('; ')); - } - - agentIds = payload.data.agentIds ?? []; - workflowIds = payload.data.workflowIds ?? []; - folderIds = payload.data.folderIds ?? []; - projectIds = payload.data.projectIds ?? []; - includeVariableValues = payload.data.includeVariableValues; - - const hasLooseSelection = [agentIds, workflowIds, folderIds].some((ids) => ids.length > 0); - if (projectIds.length > 0 && hasLooseSelection) { - throw new BadRequestError( - 'Provide either agentIds/workflowIds/folderIds or projectIds, not both', - ); - } - - if (!hasLooseSelection && projectIds.length === 0) { - throw new BadRequestError( - 'At least one agentId, workflowId, folderId, or projectId is required', - ); - } - - const apiKeyScopes = assertPackageExportApiKeyScopes( - req, - agentIds, - workflowIds, - folderIds, - projectIds, - ); - - const exportResult = await Container.get(N8nPackagesService).exportPackage({ - user: req.user, - agentIds, - workflowIds, - folderIds, - projectIds, - includeVariableValues, - canExportVariableValues: apiKeyScopes.includes('variable:list'), - includeTags: payload.data.includeTags, - dependencyPolicy: payload.data.dependencyPolicy, - versionPolicy: payload.data.versionPolicy, - credentialExportPolicy: payload.data.credentialExportPolicy, - includeArchivedWorkflows: payload.data.includeArchivedWorkflows, - }); - - return await streamPackageExport(res, exportResult); - } catch (error) { - Container.get(EventService).emit('n8n-package-export-failed', { - user: req.user, - reason: classifyPackageFailure(error), - ...(agentIds.length ? { agentIds } : {}), - ...(workflowIds.length ? { workflowIds } : {}), - ...(folderIds.length ? { folderIds } : {}), - ...(projectIds.length ? { projectIds } : {}), - }); - - if ( - error instanceof PackageEntityAccessDeniedError || - error instanceof PackageEntityNotFoundError - ) { - throw new UserError(error.message, { description: error.description }); - } - throw error; - } - }, - ], -}; - -export = n8nPackagesHandlers; diff --git a/packages/cli/src/public-api/v1/handlers/n8n-packages/spec/paths/exportPackage.generated.yml b/packages/cli/src/public-api/v1/handlers/n8n-packages/spec/paths/exportPackage.generated.yml new file mode 100644 index 00000000000..89631b03dbc --- /dev/null +++ b/packages/cli/src/public-api/v1/handlers/n8n-packages/spec/paths/exportPackage.generated.yml @@ -0,0 +1,146 @@ +operationId: exportPackage +tags: + - N8nPackage +summary: 'Beta: Export agents, workflows, folders, or projects as an n8n package' +description: | + **Beta** — breaking changes may still occur without major version bump. + + Export agents, workflows, and folders, or whole projects, as a gzipped tar + archive (.n8np). Provide `agentIds`/`workflowIds`/`folderIds`, or `projectIds`. + Do not combine these two groups. Each exported folder includes its nested + folders. Whole projects include their agents when the agents module is enabled. + Explicit agent selections require the agents module. Empty projects export + project metadata only. `versionPolicy` selects the version for both agents and + workflows and defaults to `latest`. `dependencyPolicy` applies to both entity + types and defaults to `fail` when a required definition is absent from the + package. The response is streamed as `application/gzip` with a `Content-Disposition` + attachment header. Requires the n8n Packages feature to be licensed. + + API key scopes: `agent:export` is required for explicitly selected agents. + `workflow:export` is required for explicitly selected workflows or folders. + `project:export` is sufficient for whole-project exports, including their + agents and workflows. Included dependencies need no additional API key scope. + The caller's project permissions apply to all included entities. When + `includeVariableValues` is true (the default) and exported entities reference + variables, `variable:list` is also required. Exports that reference no variables + do not need it. + + Agent definitions include referenced skills, custom tools, and schedules. + Knowledge base files and runtime data are excluded. Agent package imports + remain unavailable. +x-required-scope: project:export,workflow:export,agent:export +requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + agentIds: + type: array + items: + type: string + minLength: 1 + minItems: 1 + maxItems: 300 + description: IDs of the agents to include. Requires the agents module. + example: + - uT9LdQx7rK2MvB4f + workflowIds: + type: array + items: + type: string + minLength: 1 + minItems: 1 + maxItems: 300 + description: IDs of the workflows to include in the exported package. + example: + - 2tUt1wbLX592XDdX + folderIds: + type: array + items: + type: string + minLength: 1 + minItems: 1 + maxItems: 300 + description: IDs of the folders to include in the exported package. Each folder is exported with its nested folders. + example: + - 9xKp2mNqRzAbCdEf + projectIds: + type: array + items: + type: string + minLength: 1 + minItems: 1 + maxItems: 300 + description: IDs of the projects to include in the exported package. Includes their agents when the agents module is enabled. + example: + - Ox8O54VQrmBrb4qL + includeVariableValues: + type: boolean + default: true + description: Whether values of variables referenced by the exported entities are bundled into the package. When `false`, variables still travel as name/type files and are listed in the package requirements, but no values travel with the package. + includeTags: + type: boolean + default: true + description: Whether tags assigned to the exported workflows are bundled into the package. When `false`, no tag files, tag references, or tag requirements travel with the package. + dependencyPolicy: + type: string + enum: + - fail + - reference-only + - include-in-package + default: fail + description: Policy for workflow and agent dependencies outside the selected package contents. Includes static workflow references and disabled agent references. `fail` aborts when a required workflow or agent is absent from the package. `include-in-package` adds accessible dependencies recursively. `reference-only` records external requirements without including those definitions. The same policy applies to workflows and agents. + example: fail + versionPolicy: + type: string + enum: + - published-strict + - prefer-published + - ignore-unpublished + - latest + default: latest + description: Which version of each workflow and agent travels in the package. `latest` exports the current draft. `published-strict` requires a published version. `prefer-published` uses the published version when available and the draft otherwise. `ignore-unpublished` skips unpublished selections. Dependencies that cannot be included cause the export to fail only when `dependencyPolicy` is `fail` or `include-in-package`. With `reference-only`, the export records them as external requirements. The selected version supplies the definition and its references. Workflow names, settings, and tags always use their current values. Agent IDs, names, and MCP availability always use their current values. + example: latest + credentialExportPolicy: + type: string + enum: + - expression-values-only + - no-values + default: expression-values-only + description: Whether expression values from credential data are bundled into the package. `expression-values-only` includes credential fields whose value is an n8n expression (for example `={{ $secrets.apiKey }}`); literal values never travel either way. `no-values` keeps credential data out of the package entirely, so each credential file carries only its id, name and type. + example: expression-values-only + includeArchivedWorkflows: + type: boolean + default: false + description: 'Whether folder and project exports include their archived workflows. When `false` (default) they are left out. When `true` they travel with `isArchived: true` and are archived on import. Workflows listed in `workflowIds` always export, also when archived.' + example: false + additionalProperties: false +responses: + '200': + description: A gzipped tar archive containing the exported package contents. + headers: + X-N8n-Export-Counts: + description: | + JSON-serialized per-entity counts of what actually ended up in the + package (after folder bundling and auto-inclusion), e.g. + `{"agents":1,"workflows":2,"folders":1,"credentials":0,"dataTables":0,"variables":0,"tags":0}`. + required: true + schema: + type: string + content: + application/gzip: + schema: + type: string + format: binary + '400': + $ref: ../../../../shared/spec/responses/badRequest.yml + '401': + $ref: ../../../../shared/spec/responses/unauthorized.yml + '403': + $ref: ../../../../shared/spec/responses/forbidden.yml + '404': + $ref: ../../../../shared/spec/responses/notFound.yml + '415': + $ref: ../../../../shared/spec/responses/unsupportedMediaType.yml diff --git a/packages/cli/src/public-api/v1/handlers/n8n-packages/spec/paths/importPackage.generated.yml b/packages/cli/src/public-api/v1/handlers/n8n-packages/spec/paths/importPackage.generated.yml index 19377706039..5d541f4472e 100644 --- a/packages/cli/src/public-api/v1/handlers/n8n-packages/spec/paths/importPackage.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/n8n-packages/spec/paths/importPackage.generated.yml @@ -11,9 +11,6 @@ description: |- Credential references are resolved before any workflow is written. x-required-scope: workflow:import -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true requestBody: required: true content: @@ -44,8 +41,9 @@ requestBody: enum: - must-preexist - create-stub + - create-with-values default: create-stub - description: What to do when a credential reference cannot be resolved. `create-stub` (default) creates empty credential placeholders in the target project for missing references. `must-preexist` requires every referenced credential to already exist. + description: What to do when a credential reference cannot be resolved. `create-stub` (default) creates empty credential placeholders in the target project for missing references. `create-with-values` also creates them, seeded from the expression data bundled in the package (see the export option `credentialExportPolicy`); a reference the package carries no data for falls back to an empty stub. Seeded credentials are listed under `credentials.seeded` and only allow workflow publishing when the package confirms that all source data was retained. Partial or unverified data blocks publishing with `stub-credential`. `must-preexist` requires every referenced credential to already exist. bindings: type: string description: 'Optional JSON object of explicit source→target id bindings, keyed by entity type. Only `credentials` is supported today: send `{"credentials":{"":""}}` to map credential ids from the package to credential ids on the target instance. These explicit bindings are validated on type and applied before `credentialMatchingMode` resolution runs.' diff --git a/packages/cli/src/public-api/v1/handlers/n8n-packages/spec/paths/importPackageSelection.generated.yml b/packages/cli/src/public-api/v1/handlers/n8n-packages/spec/paths/importPackageSelection.generated.yml index f37161cc418..d82f7d17330 100644 --- a/packages/cli/src/public-api/v1/handlers/n8n-packages/spec/paths/importPackageSelection.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/n8n-packages/spec/paths/importPackageSelection.generated.yml @@ -11,9 +11,6 @@ description: |- The package must be a project package (a workflow package is rejected with a 400). The cherry-pick conflict policies (folder, tag, and project) are fixed and are not accepted here; only `workflowConflictPolicy`, `workflowIdPolicy`, and `overwriteDeletionPolicy` are configurable. Maximum upload size is `N8N_ENDPOINTS_PAYLOAD_SIZE_MAX` MB (default 16). The caller is authorised through the `workflow:import` scope. x-required-scope: workflow:import -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true requestBody: required: true content: diff --git a/packages/cli/src/public-api/v1/handlers/n8n-packages/spec/paths/n8n-packages.export.yml b/packages/cli/src/public-api/v1/handlers/n8n-packages/spec/paths/n8n-packages.export.yml deleted file mode 100644 index e149915b24d..00000000000 --- a/packages/cli/src/public-api/v1/handlers/n8n-packages/spec/paths/n8n-packages.export.yml +++ /dev/null @@ -1,64 +0,0 @@ -post: - x-eov-operation-id: exportPackage - x-required-scope: project:export,workflow:export,agent:export - x-eov-operation-handler: v1/handlers/n8n-packages/n8n-packages.handler - tags: - - N8nPackage - summary: 'Beta: Export agents, workflows, folders, or projects as an n8n package' - description: | - **Beta** — breaking changes may still occur without major version bump. - - Export agents, workflows, and folders, or whole projects, as a gzipped tar - archive (.n8np). Provide `agentIds`/`workflowIds`/`folderIds`, or `projectIds`. - Do not combine these two groups. Each exported folder includes its nested - folders. Whole projects include their agents when the agents module is enabled. - Explicit agent selections require the agents module. Empty projects export - project metadata only. `versionPolicy` selects the version for both agents and - workflows and defaults to `latest`. `dependencyPolicy` applies to both entity - types and defaults to `fail` when a required definition is absent from the - package. The response is streamed as `application/gzip` with a `Content-Disposition` - attachment header. Requires the n8n Packages feature to be licensed. - - API key scopes: `agent:export` is required for explicitly selected agents. - `workflow:export` is required for explicitly selected workflows or folders. - `project:export` is sufficient for whole-project exports, including their - agents and workflows. Included dependencies need no additional API key scope. - The caller's project permissions apply to all included entities. When - `includeVariableValues` is true (the default) and exported entities reference - variables, `variable:list` is also required. Exports that reference no variables - do not need it. - - Agent definitions include referenced skills, custom tools, and schedules. - Knowledge base files and runtime data are excluded. Agent package imports - remain unavailable. - requestBody: - description: Agents, workflows, folders, or projects to include in the exported package. - required: true - content: - application/json: - schema: - $ref: '../schemas/exportPackageRequest.yml' - responses: - '200': - description: A gzipped tar archive containing the exported package contents. - headers: - X-N8n-Export-Counts: - description: | - JSON-serialized per-entity counts of what actually ended up in the - package (after folder bundling and auto-inclusion), e.g. - `{"agents":1,"workflows":2,"folders":1,"credentials":0,"dataTables":0,"variables":0,"tags":0}`. - schema: - type: string - content: - application/gzip: - schema: - type: string - format: binary - '400': - $ref: '../../../../shared/spec/responses/badRequest.yml' - '401': - $ref: '../../../../shared/spec/responses/unauthorized.yml' - '403': - $ref: '../../../../shared/spec/responses/forbidden.yml' - '404': - $ref: '../../../../shared/spec/responses/notFound.yml' diff --git a/packages/cli/src/public-api/v1/handlers/n8n-packages/spec/schemas/exportPackageRequest.yml b/packages/cli/src/public-api/v1/handlers/n8n-packages/spec/schemas/exportPackageRequest.yml deleted file mode 100644 index cb779494897..00000000000 --- a/packages/cli/src/public-api/v1/handlers/n8n-packages/spec/schemas/exportPackageRequest.yml +++ /dev/null @@ -1,120 +0,0 @@ -type: object -additionalProperties: false -description: >- - Selects what to export. Provide `agentIds`, `workflowIds`, and/or `folderIds` - to export loose entities, or `projectIds` to export whole projects. - Do not combine these two groups. Supply at least one ID. -properties: - agentIds: - type: array - minItems: 1 - maxItems: 300 - description: IDs of the agents to include. Requires the agents module. - items: - type: string - minLength: 1 - example: - - uT9LdQx7rK2MvB4f - workflowIds: - type: array - maxItems: 300 - description: IDs of the workflows to include in the exported package. - items: - type: string - minLength: 1 - example: - - 2tUt1wbLX592XDdX - folderIds: - type: array - maxItems: 300 - description: >- - IDs of the folders to include in the exported package. Each folder is - exported with its nested folders. - items: - type: string - minLength: 1 - example: - - 9xKp2mNqRzAbCdEf - projectIds: - type: array - description: >- - IDs of the projects to include in the exported package. - Includes their agents when the agents module is enabled. - items: - type: string - minLength: 1 - example: - - Ox8O54VQrmBrb4qL - includeVariableValues: - type: boolean - default: true - description: >- - Whether values of variables referenced by the exported entities are - bundled into the package. When `false`, variables still travel as - name/type files and are listed in the package requirements, but no - values travel with the package. - includeTags: - type: boolean - default: true - description: >- - Whether tags assigned to the exported workflows are bundled into the - package. When `false`, no tag files, tag references, or tag - requirements travel with the package. - dependencyPolicy: - type: string - enum: - - fail - - reference-only - - include-in-package - description: >- - Policy for workflow and agent dependencies outside the selected package - contents. Includes static workflow references and disabled agent references. - `fail` aborts when a required workflow or agent is absent from the package. - `include-in-package` adds accessible dependencies recursively. - `reference-only` records external requirements without including those - definitions. The same policy applies to workflows and agents. - example: fail - default: fail - versionPolicy: - type: string - enum: - - published-strict - - prefer-published - - ignore-unpublished - - latest - description: >- - Which version of each workflow and agent travels in the package. `latest` - exports the current draft. `published-strict` requires a published version. - `prefer-published` uses the published version when available and the draft - otherwise. `ignore-unpublished` skips unpublished selections. - Dependencies that cannot be included cause the export to fail only when - `dependencyPolicy` is `fail` or `include-in-package`. With `reference-only`, - the export records them as external requirements. - The selected version supplies the definition and its references. - Workflow names, settings, and tags always use their current values. - Agent IDs, names, and MCP availability always use their current values. - example: latest - default: latest - credentialExportPolicy: - type: string - enum: - - expression-values-only - - no-values - description: >- - Whether expression values from credential data are bundled into the - package. `expression-values-only` includes credential fields whose value - is an n8n expression (for example `={{ $secrets.apiKey }}`); literal - values never travel either way. `no-values` keeps credential data out of - the package entirely, so each credential file carries only its id, name - and type. - example: expression-values-only - default: expression-values-only - includeArchivedWorkflows: - type: boolean - description: >- - Whether folder and project exports include their archived workflows. When - `false` (default) they are left out. When `true` they travel with - `isArchived: true` and are archived on import. Workflows listed in - `workflowIds` always export, also when archived. - example: false - default: false diff --git a/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/createNodeTypePolicyDocument.generated.yml b/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/createNodeTypePolicyDocument.generated.yml index f5e1a509e7a..04669ff4a6e 100644 --- a/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/createNodeTypePolicyDocument.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/createNodeTypePolicyDocument.generated.yml @@ -1,12 +1,12 @@ operationId: createNodeTypePolicyDocument tags: - NodeTypePolicy -summary: Create a node type policy document -description: Creates a reusable policy document that is not yet attached to any scope. Rule ids must be unique within the list. `warnings` lists rules that an earlier rule already shadows. +summary: 'Preview: Create a node type policy document' +description: |- + **Preview** — breaking changes may still occur without major version bump. + + Creates a reusable policy document that is not yet attached to any scope. Rule ids must be unique within the list. `warnings` lists rules that an earlier rule already shadows. x-required-scope: nodeTypePolicy:manage -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true requestBody: required: true content: diff --git a/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/deleteNodeTypePolicyDocument.generated.yml b/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/deleteNodeTypePolicyDocument.generated.yml index aaf603f037a..f0583f6192f 100644 --- a/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/deleteNodeTypePolicyDocument.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/deleteNodeTypePolicyDocument.generated.yml @@ -1,12 +1,12 @@ operationId: deleteNodeTypePolicyDocument tags: - NodeTypePolicy -summary: Delete a node type policy document -description: Deletes a policy document. A document that is still attached to a scope is rejected with 409; detach it first. +summary: 'Preview: Delete a node type policy document' +description: |- + **Preview** — breaking changes may still occur without major version bump. + + Deletes a policy document. A document that is still attached to a scope is rejected with 409; detach it first. x-required-scope: nodeTypePolicy:manage -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/getNodeTypeInstancePolicy.generated.yml b/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/getNodeTypeInstancePolicy.generated.yml index 8f3a1ec3f69..933bf7f4242 100644 --- a/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/getNodeTypeInstancePolicy.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/getNodeTypeInstancePolicy.generated.yml @@ -1,12 +1,12 @@ operationId: getNodeTypeInstancePolicy tags: - NodeTypePolicy -summary: Retrieve the instance node type policy -description: 'Returns the composed instance-scope policy: its default action and the rules of every attached policy document in evaluation order. An instance that was never configured reports `scopeId: null`, no rules, `defaultAction: allow`, and `version: 0`.' +summary: 'Preview: Retrieve the instance node type policy' +description: |- + **Preview** — breaking changes may still occur without major version bump. + + Returns the composed instance-scope policy: its default action and the rules of every attached policy document in evaluation order. An instance that was never configured reports `scopeId: null`, no rules, `defaultAction: allow`, and `version: 0`. x-required-scope: nodeTypePolicy:manage -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true responses: '200': description: Operation successful. diff --git a/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/getNodeTypePolicyDocument.generated.yml b/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/getNodeTypePolicyDocument.generated.yml index 273f23c3c56..e0ded935f7a 100644 --- a/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/getNodeTypePolicyDocument.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/getNodeTypePolicyDocument.generated.yml @@ -1,11 +1,9 @@ operationId: getNodeTypePolicyDocument tags: - NodeTypePolicy -summary: Retrieve a node type policy document +summary: 'Preview: Retrieve a node type policy document' +description: '**Preview** — breaking changes may still occur without major version bump.' x-required-scope: nodeTypePolicy:manage -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/getNodeTypeProjectPolicy.generated.yml b/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/getNodeTypeProjectPolicy.generated.yml index 9be25845780..e3b2554bd66 100644 --- a/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/getNodeTypeProjectPolicy.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/getNodeTypeProjectPolicy.generated.yml @@ -1,12 +1,12 @@ operationId: getNodeTypeProjectPolicy tags: - NodeTypePolicy -summary: Retrieve a project's node type policy -description: "Returns the project's own composed policy, not the result of combining it with the instance policy. A project that was never configured reports `scopeId: null`, no rules, `defaultAction: allow`, and `version: 0`." +summary: "Preview: Retrieve a project's node type policy" +description: |- + **Preview** — breaking changes may still occur without major version bump. + + Returns the project's own composed policy, not the result of combining it with the instance policy. A project that was never configured reports `scopeId: null`, no rules, `defaultAction: allow`, and `version: 0`. x-required-scope: nodeTypePolicy:manage -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/listNodeTypePolicyDocuments.generated.yml b/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/listNodeTypePolicyDocuments.generated.yml index 63880492eea..22d1bfa9f43 100644 --- a/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/listNodeTypePolicyDocuments.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/listNodeTypePolicyDocuments.generated.yml @@ -1,15 +1,15 @@ operationId: listNodeTypePolicyDocuments tags: - NodeTypePolicy -summary: List node type policy documents -description: Returns a cursor-paginated list of reusable policy documents. +summary: 'Preview: List node type policy documents' +description: |- + **Preview** — breaking changes may still occur without major version bump. + + Returns a cursor-paginated list of reusable policy documents. x-required-scope: nodeTypePolicy:manage parameters: - $ref: ../../../../shared/spec/parameters/limit.yml - $ref: ../../../../shared/spec/parameters/cursor.yml -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true responses: '200': description: Operation successful. diff --git a/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/putNodeTypeInstancePolicy.generated.yml b/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/putNodeTypeInstancePolicy.generated.yml index 4f7e2dcac0e..5f7176676b5 100644 --- a/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/putNodeTypeInstancePolicy.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/putNodeTypeInstancePolicy.generated.yml @@ -1,12 +1,12 @@ operationId: putNodeTypeInstancePolicy tags: - NodeTypePolicy -summary: Replace the instance node type policy -description: Sets the instance default action and replaces the rules of its single policy document, creating both on first write. `version` must equal the version last read; a stale value is rejected with 409. Rule ids must be unique within the list. +summary: 'Preview: Replace the instance node type policy' +description: |- + **Preview** — breaking changes may still occur without major version bump. + + Sets the instance default action and replaces the rules of its single policy document, creating both on first write. `version` must equal the version last read; a stale value is rejected with 409. Rule ids must be unique within the list. x-required-scope: nodeTypePolicy:manage -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true requestBody: required: true content: diff --git a/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/putNodeTypeProjectPolicy.generated.yml b/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/putNodeTypeProjectPolicy.generated.yml index 74282000425..72a8619ec8b 100644 --- a/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/putNodeTypeProjectPolicy.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/putNodeTypeProjectPolicy.generated.yml @@ -1,12 +1,12 @@ operationId: putNodeTypeProjectPolicy tags: - NodeTypePolicy -summary: Replace a project's node type policy -description: Sets the project's default action and replaces the rules of its single policy document, creating both on first write. The `delegate` action is not accepted at project scope. `version` must equal the version last read; a stale value is rejected with 409, as is a project document that is shared with another scope. +summary: "Preview: Replace a project's node type policy" +description: |- + **Preview** — breaking changes may still occur without major version bump. + + Sets the project's default action and replaces the rules of its single policy document, creating both on first write. The `delegate` action is not accepted at project scope. `version` must equal the version last read; a stale value is rejected with 409, as is a project document that is shared with another scope. x-required-scope: nodeTypePolicy:manage -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/replaceNodeTypePolicyAttachments.generated.yml b/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/replaceNodeTypePolicyAttachments.generated.yml index 90669dec38c..6cec17206a9 100644 --- a/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/replaceNodeTypePolicyAttachments.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/replaceNodeTypePolicyAttachments.generated.yml @@ -1,12 +1,12 @@ operationId: replaceNodeTypePolicyAttachments tags: - NodeTypePolicy -summary: Replace a scope's attached policy documents -description: Replaces every attachment on a scope. `scopeId` comes from the scope's `GET` response once it has been written. Each `policyId` and each `(isFloor, priority)` pair must be unique within the list. Last write wins; the scope's version is bumped. +summary: "Preview: Replace a scope's attached policy documents" +description: |- + **Preview** — breaking changes may still occur without major version bump. + + Replaces every attachment on a scope. `scopeId` comes from the scope's `GET` response once it has been written. Each `policyId` and each `(isFloor, priority)` pair must be unique within the list. `version` must match the current scope version. A stale version returns 409 without changes. A successful write bumps the scope's version. x-required-scope: nodeTypePolicy:manage -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string @@ -37,8 +37,12 @@ requestBody: - policyId - priority - isFloor + version: + type: integer + minimum: 0 required: - attachments + - version responses: '200': description: Operation successful. @@ -123,6 +127,8 @@ responses: $ref: ../../../../shared/spec/responses/forbidden.yml '404': $ref: ../../../../shared/spec/responses/notFound.yml + '409': + $ref: ../../../../shared/spec/responses/conflict.yml '415': $ref: ../../../../shared/spec/responses/unsupportedMediaType.yml '503': diff --git a/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/updateNodeTypePolicyDocument.generated.yml b/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/updateNodeTypePolicyDocument.generated.yml index 0e3bc34ef61..0051a64baeb 100644 --- a/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/updateNodeTypePolicyDocument.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/node-type-policies/spec/paths/updateNodeTypePolicyDocument.generated.yml @@ -1,12 +1,12 @@ operationId: updateNodeTypePolicyDocument tags: - NodeTypePolicy -summary: Replace the rules of a node type policy document -description: Replaces the document's whole rule list. `version` must equal the version last read; a stale value is rejected with 409. Every scope the document is attached to has its version bumped. A `delegate` rule is rejected when the document is attached to a project scope. +summary: 'Preview: Replace the rules of a node type policy document' +description: |- + **Preview** — breaking changes may still occur without major version bump. + + Replaces the document's whole rule list. `version` must equal the version last read; a stale value is rejected with 409. Every scope the document is attached to has its version bumped. A `delegate` rule is rejected when the document is attached to a project scope. x-required-scope: nodeTypePolicy:manage -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/projects/spec/paths/addUsersToProject.generated.yml b/packages/cli/src/public-api/v1/handlers/projects/spec/paths/addUsersToProject.generated.yml index 6b5d7007342..ec95ef80aad 100644 --- a/packages/cli/src/public-api/v1/handlers/projects/spec/paths/addUsersToProject.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/projects/spec/paths/addUsersToProject.generated.yml @@ -4,9 +4,6 @@ tags: summary: Add one or more users to a project description: Add one or more users to a project on your instance. x-required-scope: project:manageMembers -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/projects/spec/paths/changeUserRoleInProject.generated.yml b/packages/cli/src/public-api/v1/handlers/projects/spec/paths/changeUserRoleInProject.generated.yml index 950217cc2fb..7dfc86d6e37 100644 --- a/packages/cli/src/public-api/v1/handlers/projects/spec/paths/changeUserRoleInProject.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/projects/spec/paths/changeUserRoleInProject.generated.yml @@ -4,9 +4,6 @@ tags: summary: Change a user's role in a project description: Change a user's role in a project. x-required-scope: project:manageMembers -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/projects/spec/paths/createFolder.generated.yml b/packages/cli/src/public-api/v1/handlers/projects/spec/paths/createFolder.generated.yml index 4b344d0f52e..dfa89020501 100644 --- a/packages/cli/src/public-api/v1/handlers/projects/spec/paths/createFolder.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/projects/spec/paths/createFolder.generated.yml @@ -4,9 +4,6 @@ tags: summary: Create a folder description: Create a folder within a project. x-required-scope: folder:create -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/projects/spec/paths/createProject.generated.yml b/packages/cli/src/public-api/v1/handlers/projects/spec/paths/createProject.generated.yml index 2fa14c5ac95..33aac3690fc 100644 --- a/packages/cli/src/public-api/v1/handlers/projects/spec/paths/createProject.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/projects/spec/paths/createProject.generated.yml @@ -4,9 +4,6 @@ tags: summary: Create a project description: Create a team project on your instance. x-required-scope: project:create -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true requestBody: required: true content: diff --git a/packages/cli/src/public-api/v1/handlers/projects/spec/paths/deleteFolder.generated.yml b/packages/cli/src/public-api/v1/handlers/projects/spec/paths/deleteFolder.generated.yml index e247ff78f9c..c4f46b7bf74 100644 --- a/packages/cli/src/public-api/v1/handlers/projects/spec/paths/deleteFolder.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/projects/spec/paths/deleteFolder.generated.yml @@ -4,9 +4,6 @@ tags: summary: Delete a folder description: Delete a folder within a project. When `transferToFolderId` is provided, workflows and sub-folders are moved to the target folder before deletion. When omitted, workflows are moved to the project root and archived, and child folders are deleted. x-required-scope: folder:delete -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/projects/spec/paths/deleteProject.generated.yml b/packages/cli/src/public-api/v1/handlers/projects/spec/paths/deleteProject.generated.yml index 0d365bd4e63..1a18aa31706 100644 --- a/packages/cli/src/public-api/v1/handlers/projects/spec/paths/deleteProject.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/projects/spec/paths/deleteProject.generated.yml @@ -4,9 +4,6 @@ tags: summary: Delete a project description: Delete a project from your instance. x-required-scope: project:delete -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/projects/spec/paths/deleteUserFromProject.generated.yml b/packages/cli/src/public-api/v1/handlers/projects/spec/paths/deleteUserFromProject.generated.yml index 5d23fc8f16a..bb4dae4b07e 100644 --- a/packages/cli/src/public-api/v1/handlers/projects/spec/paths/deleteUserFromProject.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/projects/spec/paths/deleteUserFromProject.generated.yml @@ -4,9 +4,6 @@ tags: summary: Delete a user from a project description: Delete a user from a project on your instance. x-required-scope: project:manageMembers -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/projects/spec/paths/getFolder.generated.yml b/packages/cli/src/public-api/v1/handlers/projects/spec/paths/getFolder.generated.yml index c072a1407ba..712d2e8cae0 100644 --- a/packages/cli/src/public-api/v1/handlers/projects/spec/paths/getFolder.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/projects/spec/paths/getFolder.generated.yml @@ -4,9 +4,6 @@ tags: summary: Get folder details description: Get folder details including sub-folder and workflow counts. x-required-scope: folder:read -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/projects/spec/paths/getProjectUsers.generated.yml b/packages/cli/src/public-api/v1/handlers/projects/spec/paths/getProjectUsers.generated.yml index 89e080ce580..11c0b6ed1fe 100644 --- a/packages/cli/src/public-api/v1/handlers/projects/spec/paths/getProjectUsers.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/projects/spec/paths/getProjectUsers.generated.yml @@ -13,9 +13,6 @@ parameters: description: The ID of the project. name: projectId in: path -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true responses: '200': description: Operation successful. diff --git a/packages/cli/src/public-api/v1/handlers/projects/spec/paths/getProjects.generated.yml b/packages/cli/src/public-api/v1/handlers/projects/spec/paths/getProjects.generated.yml index b7de0f010fa..38fb78c848f 100644 --- a/packages/cli/src/public-api/v1/handlers/projects/spec/paths/getProjects.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/projects/spec/paths/getProjects.generated.yml @@ -7,9 +7,6 @@ x-required-scope: project:list parameters: - $ref: ../../../../shared/spec/parameters/limit.yml - $ref: ../../../../shared/spec/parameters/cursor.yml -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true responses: '200': description: Operation successful. diff --git a/packages/cli/src/public-api/v1/handlers/projects/spec/paths/listFolders.generated.yml b/packages/cli/src/public-api/v1/handlers/projects/spec/paths/listFolders.generated.yml index 3c94e60c73b..537149ac20c 100644 --- a/packages/cli/src/public-api/v1/handlers/projects/spec/paths/listFolders.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/projects/spec/paths/listFolders.generated.yml @@ -4,9 +4,6 @@ tags: summary: Retrieve folders description: Retrieve folders within a project. Supports filtering, sorting, field selection, and pagination. x-required-scope: folder:list -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/projects/spec/paths/updateFolder.generated.yml b/packages/cli/src/public-api/v1/handlers/projects/spec/paths/updateFolder.generated.yml index 9ee2479d8f8..9ac57267548 100644 --- a/packages/cli/src/public-api/v1/handlers/projects/spec/paths/updateFolder.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/projects/spec/paths/updateFolder.generated.yml @@ -4,9 +4,6 @@ tags: summary: Update a folder description: Update folder name or parent folder. x-required-scope: folder:update -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/projects/spec/paths/updateProject.generated.yml b/packages/cli/src/public-api/v1/handlers/projects/spec/paths/updateProject.generated.yml index 5e76e28cd56..f82f037a884 100644 --- a/packages/cli/src/public-api/v1/handlers/projects/spec/paths/updateProject.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/projects/spec/paths/updateProject.generated.yml @@ -4,9 +4,6 @@ tags: summary: Update a project description: Update a project on your instance. x-required-scope: project:update -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/addProjectToPromotionConnection.generated.yml b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/addProjectToPromotionConnection.generated.yml index f811f29a455..f7e764dac5b 100644 --- a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/addProjectToPromotionConnection.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/addProjectToPromotionConnection.generated.yml @@ -4,9 +4,6 @@ tags: summary: Link a project to a promotion connection description: Links a team project to a project-scoped connection. A project can be linked to only one connection. x-required-scope: gitConnection:manageProjects -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/applyPackage.generated.yml b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/applyPackage.generated.yml index 4b6efbb1d9a..8dd6b1fcb3c 100644 --- a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/applyPackage.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/applyPackage.generated.yml @@ -2,11 +2,8 @@ operationId: applyPackage tags: - Promotions summary: Apply a package to the instance -description: Checks the full package at the configured branch tip. Optionally send expectedSource with the configId, branchName, and full commitSha from the reviewed change preview; status `source-changed` means the branch moved since that review and nothing was imported. Returns status `blocked` before import writes if bindings need setup. Retain configId and git for Continue. Status `applied` includes counts and warnings. Inspect status before reading counts. Existing target variable values, including empty strings, are preserved. Requires a cloned Apply direction on an instance connection. The API key needs the gitConnection:pull scope. The importer checks user write permissions; granular API-key write scopes are not passed to it. +description: Checks the full package at the configured branch tip. Optionally send expectedSource with the configId, branchName, and full commitSha from the reviewed change preview; status `source-changed` means the branch moved since that review and nothing was imported. Returns status `blocked` before import writes if bindings need setup or if the apply would delete team projects that the package does not hold. Retain configId and git for Continue. Status `applied` includes counts and warnings. Inspect status before reading counts. Existing target variable values, including empty strings, are preserved. Requires a cloned Apply direction on an instance connection. The API key needs the gitConnection:pull scope. The importer checks user write permissions; granular API-key write scopes are not passed to it. x-required-scope: gitConnection:pull -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/applyProjectSelection.generated.yml b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/applyProjectSelection.generated.yml index 0fa965c973c..190f609c6c6 100644 --- a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/applyProjectSelection.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/applyProjectSelection.generated.yml @@ -4,9 +4,6 @@ tags: summary: Apply a selection of a project's workflows description: Applies selected workflow changes from the project's Apply branch. Send the selected change-list IDs in workflowIds. The server imports IDs present on the branch for this project. It removes instance workflows owned by this project when their IDs are absent from the branch. Duplicate or invalid IDs reject the whole request. Unselected content stays unchanged. Optionally send expectedSource with the configId, branchName, and full commitSha from the reviewed change preview. Status `source-changed` means the source changed since that review and nothing was imported. Status `blocked` returns binding details before import writes when the selection needs binding setup. Retain configId and git for Continue. Status `applied` includes counts and warnings. Inspect status before reading counts. Requires a cloned Apply direction for the project's resolved promotion connection. The API key needs the gitConnection:pull scope. The importer checks user write permissions. x-required-scope: gitConnection:pull -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/clonePromotionCheckout.generated.yml b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/clonePromotionCheckout.generated.yml index f57616cf559..dca5b0423e2 100644 --- a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/clonePromotionCheckout.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/clonePromotionCheckout.generated.yml @@ -4,9 +4,6 @@ tags: summary: Clone one direction's repository description: Clones the configured branch into local storage on the instance that handles the request. Safe to call repeatedly. Cloning one direction does not make the other ready. x-required-scope: gitConnection:clone -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/continueApplyPackage.generated.yml b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/continueApplyPackage.generated.yml index fa0870b7971..02ab1e311d7 100644 --- a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/continueApplyPackage.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/continueApplyPackage.generated.yml @@ -2,11 +2,8 @@ operationId: continueApplyPackage tags: - Promotions summary: Continue Apply after binding setup -description: 'Rechecks the configured source and current target bindings. Send expectedSource with the configId, branchName, and full commitSha from the reviewed Apply result. Send `confirmDestructiveChanges: true` to also apply destructive data table changes. Status `source-changed` requires a new Apply review. Status `blocked` returns fresh binding details without import writes. Status `applied` includes counts and warnings. Inspect status before reading counts. Existing target variable values are preserved. Requires the same cloned instance connection and permissions as Apply. The importer checks user write permissions; granular API-key write scopes are not passed to it. No server session or exactly-once guarantee is provided.' +description: 'Rechecks the configured source and current target bindings. Send expectedSource with the configId, branchName, and full commitSha from the reviewed Apply result. Send `confirmDestructiveChanges: true` to also apply destructive data table changes and delete the reported team projects. Status `source-changed` requires a new Apply review. Status `blocked` returns fresh binding details without import writes. Status `applied` includes counts and warnings. Inspect status before reading counts. Existing target variable values are preserved. Requires the same cloned instance connection and permissions as Apply. The importer checks user write permissions; granular API-key write scopes are not passed to it. No server session or exactly-once guarantee is provided.' x-required-scope: gitConnection:pull -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string @@ -41,7 +38,7 @@ requestBody: additionalProperties: false confirmDestructiveChanges: type: boolean - description: 'Also applies destructive data table changes, which a `destructive-change` conflict reports: removed or retyped columns. The values in those columns are removed. Rows and other columns are kept. The confirmation covers every such change when Continue runs, including changes that are not in the reviewed result.' + description: 'Also applies destructive data table changes, which a `destructive-change` conflict reports: removed or retyped columns. The values in those columns are removed. Rows and other columns are kept. On a full apply, also deletes the team projects that a `project-deletion` conflict reports, with everything in them. The confirmation covers every such change and deletion when Continue runs, including those that are not in the reviewed result.' required: - expectedSource additionalProperties: false diff --git a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/continueApplyProjectSelection.generated.yml b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/continueApplyProjectSelection.generated.yml index 48ad5bbb6ac..3750e28023d 100644 --- a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/continueApplyProjectSelection.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/continueApplyProjectSelection.generated.yml @@ -4,9 +4,6 @@ tags: summary: Continue applying a selection after binding setup description: "Rechecks the project's Apply source and the current bindings for the selection. Resend the full selection in workflowIds. Send the required expectedSource with the configId, branchName, and full commitSha from the reviewed Apply result. Send `confirmDestructiveChanges: true` to also apply destructive data table changes. The server does not keep a session. Status `source-changed` requires a new Apply review. Status `blocked` returns fresh binding details before import writes. Status `applied` includes counts and warnings. Inspect status before reading counts. Unselected content stays unchanged. Requires the same cloned Apply direction and permissions as the initial selection apply. The API key needs the gitConnection:pull scope. The importer checks user write permissions." x-required-scope: gitConnection:pull -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string @@ -48,7 +45,7 @@ requestBody: additionalProperties: false confirmDestructiveChanges: type: boolean - description: 'Also applies destructive data table changes, which a `destructive-change` conflict reports: removed or retyped columns. The values in those columns are removed. Rows and other columns are kept. The confirmation covers every such change when Continue runs, including changes that are not in the reviewed result.' + description: 'Also applies destructive data table changes, which a `destructive-change` conflict reports: removed or retyped columns. The values in those columns are removed. Rows and other columns are kept. On a full apply, also deletes the team projects that a `project-deletion` conflict reports, with everything in them. The confirmation covers every such change and deletion when Continue runs, including those that are not in the reviewed result.' required: - workflowIds - expectedSource diff --git a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/createPromotionConnection.generated.yml b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/createPromotionConnection.generated.yml index a359f436281..1d252b09885 100644 --- a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/createPromotionConnection.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/createPromotionConnection.generated.yml @@ -4,9 +4,6 @@ tags: summary: Create a promotion connection description: Creates a connection on an existing provider, with up to one initial configuration for each direction. Only one instance connection can exist. x-required-scope: gitConnection:create -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true requestBody: required: true content: diff --git a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/createPromotionProvider.generated.yml b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/createPromotionProvider.generated.yml index f3396d97118..ec5ba0a268f 100644 --- a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/createPromotionProvider.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/createPromotionProvider.generated.yml @@ -4,9 +4,6 @@ tags: summary: Create a promotion provider description: Creates a provider and its authentication material. A Git host provider validates authenticated API access before it saves. For GitLab, the service uses n8n as the Git transport username. Its auth.username is optional. The service ignores any supplied username. Plain Git token authentication requires auth.username. An SSH provider returns the generated public key; add it to the remote as a deploy key. x-required-scope: gitConnection:create -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true requestBody: required: true content: diff --git a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/deletePromotionConfig.generated.yml b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/deletePromotionConfig.generated.yml index 10e5caede0f..d353b056397 100644 --- a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/deletePromotionConfig.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/deletePromotionConfig.generated.yml @@ -4,9 +4,6 @@ tags: summary: Remove one direction description: Deletes the configuration and its local checkout. Nothing in Git changes. x-required-scope: gitConnection:update -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/deletePromotionConnection.generated.yml b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/deletePromotionConnection.generated.yml index d9a9079d54b..2696ccaadbc 100644 --- a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/deletePromotionConnection.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/deletePromotionConnection.generated.yml @@ -4,9 +4,6 @@ tags: summary: Delete a promotion connection description: Deletes the connection with its configurations, project links, and local checkouts. Its provider is kept. x-required-scope: gitConnection:delete -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/deletePromotionProvider.generated.yml b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/deletePromotionProvider.generated.yml index ed7de628d91..de9e36d842c 100644 --- a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/deletePromotionProvider.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/deletePromotionProvider.generated.yml @@ -4,9 +4,6 @@ tags: summary: Delete a promotion provider description: A provider used by a connection cannot be deleted. x-required-scope: gitConnection:delete -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/disconnectPromotionCheckout.generated.yml b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/disconnectPromotionCheckout.generated.yml index b8f5b779996..61a71eebc43 100644 --- a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/disconnectPromotionCheckout.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/disconnectPromotionCheckout.generated.yml @@ -4,9 +4,6 @@ tags: summary: Remove one direction's local checkout description: Removes the local checkout and keeps the configuration, its credentials, and the trusted SSH host keys. x-required-scope: gitConnection:clone -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/getPromotionChanges.generated.yml b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/getPromotionChanges.generated.yml index 065da3f13f9..be60b026c1f 100644 --- a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/getPromotionChanges.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/getPromotionChanges.generated.yml @@ -4,9 +4,6 @@ tags: summary: List the changes of a project in one direction description: Compares a team project on this instance with the branch of its promotion configuration and lists the workflows that differ. For `promote` the rows are what a promotion sends to the branch, and the key needs the gitConnection:push scope. For `apply` the rows are what applying the branch changes on this instance, and the key needs the gitConnection:pull scope. `commitSha` is the commit the rows were read from. Requires the direction to be cloned first. x-required-scope: gitConnection:push,gitConnection:pull -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/getPromotionConnection.generated.yml b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/getPromotionConnection.generated.yml index 60ad0327199..b3666ffa936 100644 --- a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/getPromotionConnection.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/getPromotionConnection.generated.yml @@ -4,9 +4,6 @@ tags: summary: Retrieve a promotion connection description: Returns the connection with its provider summary and its configurations. x-required-scope: gitConnection:read -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/getPromotionConnectionProjects.generated.yml b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/getPromotionConnectionProjects.generated.yml index daf05c8dbd9..5cb31c1d474 100644 --- a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/getPromotionConnectionProjects.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/getPromotionConnectionProjects.generated.yml @@ -3,9 +3,6 @@ tags: - Promotions summary: List projects linked to a promotion connection x-required-scope: gitConnection:read -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/getPromotionConnections.generated.yml b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/getPromotionConnections.generated.yml index da309cde619..a330fe5811f 100644 --- a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/getPromotionConnections.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/getPromotionConnections.generated.yml @@ -22,9 +22,6 @@ parameters: required: false name: providerId in: query -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true responses: '200': description: Operation successful. diff --git a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/getPromotionProvider.generated.yml b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/getPromotionProvider.generated.yml index 961ca6a77ae..2321d975cd4 100644 --- a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/getPromotionProvider.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/getPromotionProvider.generated.yml @@ -4,9 +4,6 @@ tags: summary: Retrieve a promotion provider description: Returns the provider with its public configuration. Secrets are never returned. x-required-scope: gitConnection:read -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/getPromotionProviders.generated.yml b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/getPromotionProviders.generated.yml index 38dadaadb18..b24dc3873fe 100644 --- a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/getPromotionProviders.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/getPromotionProviders.generated.yml @@ -7,9 +7,6 @@ x-required-scope: gitConnection:list parameters: - $ref: ../../../../shared/spec/parameters/limit.yml - $ref: ../../../../shared/spec/parameters/cursor.yml -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true responses: '200': description: Operation successful. diff --git a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/promotePackage.generated.yml b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/promotePackage.generated.yml index 6c1a3ed5ee8..5ae0d1782d2 100644 --- a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/promotePackage.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/promotePackage.generated.yml @@ -4,9 +4,6 @@ tags: summary: Promote all team projects description: Exports every team project, commits it, and pushes to the configured base branch or a new timestamped branch. The response reports the target branch in `git.branchName`. Personal projects are ignored. Requires the Promote direction to be cloned first, and is available on the instance connection only. The API key also needs variable:list when the workflows reference variables. x-required-scope: gitConnection:push -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/promoteProjectSelection.generated.yml b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/promoteProjectSelection.generated.yml index 29705044190..6c9477d58e5 100644 --- a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/promoteProjectSelection.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/promoteProjectSelection.generated.yml @@ -4,9 +4,6 @@ tags: summary: Promote a selection of a project's workflows description: Promotes a chosen set of a team project's workflows to the Promote branch of the project's promotion configuration. Send workflow ids only; the server reads each one now, so the push carries the current state. Live and archived workflows the project owns are exported, so an archived id stays on the branch as archived; an id the project no longer owns (its workflow is gone, or moved to another project) leaves the branch, matching the project's change list. A deletion the branch does not hold under this project rejects the whole request before any write. Requires the Promote direction to be cloned first, and a promotion connection to resolve for the project (its own connection, otherwise the instance connection). The API key also needs variable:list when the workflows reference variables. x-required-scope: gitConnection:push -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/removeProjectFromPromotionConnection.generated.yml b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/removeProjectFromPromotionConnection.generated.yml index 8c4efd015e1..4695b82fd0a 100644 --- a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/removeProjectFromPromotionConnection.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/removeProjectFromPromotionConnection.generated.yml @@ -3,9 +3,6 @@ tags: - Promotions summary: Unlink a project from a promotion connection x-required-scope: gitConnection:manageProjects -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/updatePromotionConnection.generated.yml b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/updatePromotionConnection.generated.yml index 343a2986097..fa2fada28ba 100644 --- a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/updatePromotionConnection.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/updatePromotionConnection.generated.yml @@ -4,9 +4,6 @@ tags: summary: Update a promotion connection description: Updates the name, target, or provider. Scope cannot change, and configurations have their own routes. x-required-scope: gitConnection:update -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/updatePromotionProvider.generated.yml b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/updatePromotionProvider.generated.yml index 76a406f2764..acfef4eaf1b 100644 --- a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/updatePromotionProvider.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/updatePromotionProvider.generated.yml @@ -4,9 +4,6 @@ tags: summary: Update a promotion provider description: Renames the provider, and replaces its credentials when `auth` is sent. A Git host provider can also update its base URL. A different API destination requires `auth` in the same request. Changed credentials and host settings are validated before they save. If another request changes the credentials or configuration before this update saves, the update returns 409. Reload the provider and try again. For GitLab, the service uses n8n as the Git transport username. Its auth.username is optional. The service ignores any supplied username. Plain Git token authentication requires auth.username. New credentials apply to every connection that uses this provider. The authentication method cannot change. x-required-scope: gitConnection:update -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/upsertPromotionApplyConfig.generated.yml b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/upsertPromotionApplyConfig.generated.yml index e7e0b1a69b7..1c03daa12b2 100644 --- a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/upsertPromotionApplyConfig.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/upsertPromotionApplyConfig.generated.yml @@ -4,9 +4,6 @@ tags: summary: Create or replace the Apply configuration description: Replaces the whole configuration, so an omitted name resets it to "Apply". Answers 200 whether it created or replaced. x-required-scope: gitConnection:update -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/upsertPromotionPromoteConfig.generated.yml b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/upsertPromotionPromoteConfig.generated.yml index 70707abb350..311c00d209a 100644 --- a/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/upsertPromotionPromoteConfig.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/promotions/spec/paths/upsertPromotionPromoteConfig.generated.yml @@ -4,9 +4,6 @@ tags: summary: Create or replace the Promote configuration description: Replaces the whole configuration, so an omitted name resets it to "Promote" and `createBranchOnPromotion` is always required. Answers 200 whether it created or replaced. x-required-scope: gitConnection:update -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/role-mapping-rules/spec/paths/createRoleMappingRule.generated.yml b/packages/cli/src/public-api/v1/handlers/role-mapping-rules/spec/paths/createRoleMappingRule.generated.yml index b744ea9da5b..c6cec4d550c 100644 --- a/packages/cli/src/public-api/v1/handlers/role-mapping-rules/spec/paths/createRoleMappingRule.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/role-mapping-rules/spec/paths/createRoleMappingRule.generated.yml @@ -4,9 +4,6 @@ tags: summary: Create a role-mapping rule description: Creates a rule that maps an identity-provider claim expression to a role. Set `type` to `instance` for a rule granting a global role, or `project` for a rule granting a project role on the projects named in `projectIds`. Omitting `order` appends the rule to the end of the evaluation order for its type. x-required-scope: roleMappingRule:create -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true requestBody: required: true content: diff --git a/packages/cli/src/public-api/v1/handlers/role-mapping-rules/spec/paths/deleteRoleMappingRule.generated.yml b/packages/cli/src/public-api/v1/handlers/role-mapping-rules/spec/paths/deleteRoleMappingRule.generated.yml index 2a2be903b36..886a03de424 100644 --- a/packages/cli/src/public-api/v1/handlers/role-mapping-rules/spec/paths/deleteRoleMappingRule.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/role-mapping-rules/spec/paths/deleteRoleMappingRule.generated.yml @@ -4,9 +4,6 @@ tags: summary: Delete a role-mapping rule description: Deletes a role-mapping rule. The remaining rules of the same type close the gap, so their `order` values stay a contiguous sequence starting at 0. x-required-scope: roleMappingRule:delete -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/role-mapping-rules/spec/paths/getRoleMappingRules.generated.yml b/packages/cli/src/public-api/v1/handlers/role-mapping-rules/spec/paths/getRoleMappingRules.generated.yml index 0d8b50bdf75..2f03af77da9 100644 --- a/packages/cli/src/public-api/v1/handlers/role-mapping-rules/spec/paths/getRoleMappingRules.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/role-mapping-rules/spec/paths/getRoleMappingRules.generated.yml @@ -15,9 +15,6 @@ parameters: required: false name: type in: query -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true responses: '200': description: Operation successful. diff --git a/packages/cli/src/public-api/v1/handlers/role-mapping-rules/spec/paths/moveRoleMappingRule.generated.yml b/packages/cli/src/public-api/v1/handlers/role-mapping-rules/spec/paths/moveRoleMappingRule.generated.yml index 2e3ac5ef31d..f807c367709 100644 --- a/packages/cli/src/public-api/v1/handlers/role-mapping-rules/spec/paths/moveRoleMappingRule.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/role-mapping-rules/spec/paths/moveRoleMappingRule.generated.yml @@ -4,9 +4,6 @@ tags: summary: Move a role-mapping rule description: Changes a rule's position in the evaluation order for its type. `targetIndex` is the desired 0-based position within the rule's own `type` sequence; a value beyond the last position moves the rule to the end. x-required-scope: roleMappingRule:update -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/role-mapping-rules/spec/paths/updateRoleMappingRule.generated.yml b/packages/cli/src/public-api/v1/handlers/role-mapping-rules/spec/paths/updateRoleMappingRule.generated.yml index 30750e5bc21..bffbbd93a3d 100644 --- a/packages/cli/src/public-api/v1/handlers/role-mapping-rules/spec/paths/updateRoleMappingRule.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/role-mapping-rules/spec/paths/updateRoleMappingRule.generated.yml @@ -4,9 +4,6 @@ tags: summary: Update a role-mapping rule description: Updates a rule's claim expression, role, and/or project assignments. A rule's type cannot be changed once created, so `type` isn't accepted here, and reordering is handled by the move endpoint. x-required-scope: roleMappingRule:update -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/roles/spec/paths/createRole.generated.yml b/packages/cli/src/public-api/v1/handlers/roles/spec/paths/createRole.generated.yml index 094d85d4a25..143b577e7ec 100644 --- a/packages/cli/src/public-api/v1/handlers/roles/spec/paths/createRole.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/roles/spec/paths/createRole.generated.yml @@ -4,9 +4,6 @@ tags: summary: Create a custom role description: Creates a custom role. Set `roleType` to `global` for an instance-wide role or `project` for a project role. x-required-scope: role:manage,role:manageProject -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true requestBody: required: true content: diff --git a/packages/cli/src/public-api/v1/handlers/roles/spec/paths/deleteRole.generated.yml b/packages/cli/src/public-api/v1/handlers/roles/spec/paths/deleteRole.generated.yml index 59a02aa31e8..e8dcf3c4d3f 100644 --- a/packages/cli/src/public-api/v1/handlers/roles/spec/paths/deleteRole.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/roles/spec/paths/deleteRole.generated.yml @@ -4,9 +4,6 @@ tags: summary: Delete a custom role description: Deletes a custom role. System roles cannot be deleted. A role with users assigned cannot be deleted unless `reassignRoleSlug` is set to move those users to another role first. x-required-scope: role:manage,role:manageProject -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/roles/spec/paths/getAllRoles.generated.yml b/packages/cli/src/public-api/v1/handlers/roles/spec/paths/getAllRoles.generated.yml index e59037f61ae..ef8bda7346f 100644 --- a/packages/cli/src/public-api/v1/handlers/roles/spec/paths/getAllRoles.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/roles/spec/paths/getAllRoles.generated.yml @@ -4,9 +4,6 @@ tags: summary: Retrieve all roles description: Returns all roles grouped by type (global and project). Set `withUsageCount` to include how many users and projects use each role. x-required-scope: role:list -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/roles/spec/paths/getRole.generated.yml b/packages/cli/src/public-api/v1/handlers/roles/spec/paths/getRole.generated.yml index 83330119e91..25ad646d8de 100644 --- a/packages/cli/src/public-api/v1/handlers/roles/spec/paths/getRole.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/roles/spec/paths/getRole.generated.yml @@ -4,9 +4,6 @@ tags: summary: Retrieve a role description: Returns a single role with its scopes. Set `withUsageCount` to include how many users and projects use the role. x-required-scope: role:read -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/roles/spec/paths/updateRole.generated.yml b/packages/cli/src/public-api/v1/handlers/roles/spec/paths/updateRole.generated.yml index 3e6cfe08cf2..06944479366 100644 --- a/packages/cli/src/public-api/v1/handlers/roles/spec/paths/updateRole.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/roles/spec/paths/updateRole.generated.yml @@ -4,9 +4,6 @@ tags: summary: Update a custom role description: Replaces a custom role's display name, description, and scopes. System roles cannot be updated. x-required-scope: role:manage,role:manageProject -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/createLogStreamingDestination.generated.yml b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/createLogStreamingDestination.generated.yml index 7bceb368b0c..64bcc2f3d7b 100644 --- a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/createLogStreamingDestination.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/createLogStreamingDestination.generated.yml @@ -4,9 +4,6 @@ tags: summary: Create a log streaming destination description: Create a log streaming destination. The destination takes effect exactly as it would from the UI, using the same validation. Requires the `eventBusDestination:create` scope and the Log Streaming feature to be licensed. When destinations are managed via environment variables, the write is rejected with 409 and nothing is created; reads still return the current values. x-required-scope: eventBusDestination:create -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true requestBody: required: true content: diff --git a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/deleteLogStreamingDestination.generated.yml b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/deleteLogStreamingDestination.generated.yml index 6315cd7e437..17c413a2669 100644 --- a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/deleteLogStreamingDestination.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/deleteLogStreamingDestination.generated.yml @@ -4,9 +4,6 @@ tags: summary: Delete a log streaming destination description: Remove a log streaming destination. Requires the `eventBusDestination:delete` scope and the Log Streaming feature to be licensed. When destinations are managed via environment variables, the delete is rejected with 409 and nothing is removed; reads still return the current values. x-required-scope: eventBusDestination:delete -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getLdapConfiguration.generated.yml b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getLdapConfiguration.generated.yml index 33ce1a8f9b9..10ad614e46d 100644 --- a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getLdapConfiguration.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getLdapConfiguration.generated.yml @@ -4,9 +4,6 @@ tags: summary: Retrieve the LDAP configuration description: Retrieve the current LDAP configuration, including every field exposed in the UI. The binding admin password is redacted on read. Requires the `ldap:manage` scope and the LDAP feature to be licensed. x-required-scope: ldap:manage -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true responses: '200': description: Operation successful. diff --git a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getLdapSync.generated.yml b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getLdapSync.generated.yml index 74c4bb2b53f..61e51666939 100644 --- a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getLdapSync.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getLdapSync.generated.yml @@ -7,9 +7,6 @@ x-required-scope: ldap:sync parameters: - $ref: ../../../../shared/spec/parameters/limit.yml - $ref: ../../../../shared/spec/parameters/cursor.yml -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true responses: '200': description: Operation successful. diff --git a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getLogStreamingDestination.generated.yml b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getLogStreamingDestination.generated.yml index dbf8c647ac6..94e8f877c1b 100644 --- a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getLogStreamingDestination.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getLogStreamingDestination.generated.yml @@ -4,9 +4,6 @@ tags: summary: Retrieve a log streaming destination description: Retrieve a single log streaming destination by id. Requires the `eventBusDestination:read` scope and the Log Streaming feature to be licensed. x-required-scope: eventBusDestination:read -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getLogStreamingDestinations.generated.yml b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getLogStreamingDestinations.generated.yml index bc8710856a9..861f16e80f8 100644 --- a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getLogStreamingDestinations.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getLogStreamingDestinations.generated.yml @@ -4,9 +4,6 @@ tags: summary: List log streaming destinations description: List the configured log streaming destinations. Requires the `eventBusDestination:list` scope and the Log Streaming feature to be licensed. x-required-scope: eventBusDestination:list -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true responses: '200': description: Operation successful. diff --git a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getLogStreamingEventTypes.generated.yml b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getLogStreamingEventTypes.generated.yml index 05e8b7c4042..26dc6420df1 100644 --- a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getLogStreamingEventTypes.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getLogStreamingEventTypes.generated.yml @@ -4,9 +4,6 @@ tags: summary: List streamable event types description: List the event types that can be streamed to a log streaming destination. Requires the `eventBusDestination:list` scope and the Log Streaming feature to be licensed. x-required-scope: eventBusDestination:list -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true responses: '200': description: Operation successful. diff --git a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getOidcConfiguration.generated.yml b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getOidcConfiguration.generated.yml index 0573eee3cf9..091ae402d20 100644 --- a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getOidcConfiguration.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getOidcConfiguration.generated.yml @@ -4,9 +4,6 @@ tags: summary: Retrieve the OIDC SSO configuration description: Retrieve the current OIDC SSO configuration, including every field exposed in the UI. The client secret is redacted on read and is never echoed back in plaintext. Requires the `oidc:manage` scope and the OIDC feature to be licensed. x-required-scope: oidc:manage -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true responses: '200': description: Operation successful. diff --git a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getOtelSettings.generated.yml b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getOtelSettings.generated.yml index 5ba5b3b7f9a..fa861bf3551 100644 --- a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getOtelSettings.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getOtelSettings.generated.yml @@ -4,9 +4,6 @@ tags: summary: Retrieve the OpenTelemetry configuration description: Retrieve the current OpenTelemetry configuration, including every field exposed in the UI. Requires the `otel:manage` scope. x-required-scope: otel:manage -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true responses: '200': description: Operation successful. diff --git a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getSamlConfiguration.generated.yml b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getSamlConfiguration.generated.yml index f62e440cc82..1fb4a3c0295 100644 --- a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getSamlConfiguration.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getSamlConfiguration.generated.yml @@ -4,9 +4,6 @@ tags: summary: Retrieve the SAML SSO configuration description: Retrieve the current SAML SSO configuration, including every field exposed in the UI plus the service provider entity ID and ACS return URL. Signing private keys, signing certificates, and identity provider metadata are redacted on read. Requires the `saml:manage` scope and the SAML feature to be licensed. x-required-scope: saml:manage -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true responses: '200': description: Operation successful. diff --git a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getSecurityPolicy.generated.yml b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getSecurityPolicy.generated.yml index 008b8e95d4e..2e49a35a7c2 100644 --- a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getSecurityPolicy.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/getSecurityPolicy.generated.yml @@ -4,9 +4,6 @@ tags: summary: Retrieve the security policy description: 'Retrieve the instance security policy: personal-space publishing and sharing, the execution-data redaction enforcement floor, and the read-only usage counts shown in the UI. Requires the `securitySettings:manage` scope and the Personal Space Policy feature to be licensed.' x-required-scope: securitySettings:manage -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true responses: '200': description: Operation successful. diff --git a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/runLdapSync.generated.yml b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/runLdapSync.generated.yml index 66aaea7d1f1..b0e49031599 100644 --- a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/runLdapSync.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/runLdapSync.generated.yml @@ -4,9 +4,6 @@ tags: summary: Trigger an LDAP synchronization description: Manually trigger an LDAP synchronization. The response returns the new sync history record. Requires the `ldap:sync` scope and the LDAP feature to be licensed. x-required-scope: ldap:sync -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true requestBody: required: true content: diff --git a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/setOidcConfiguration.generated.yml b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/setOidcConfiguration.generated.yml index 98cae9705e6..f04e904d052 100644 --- a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/setOidcConfiguration.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/setOidcConfiguration.generated.yml @@ -4,9 +4,6 @@ tags: summary: Set the OIDC SSO configuration description: Set the OIDC SSO configuration. The update takes effect exactly as it would from the UI, using the same validation. `clientId`, `clientSecret` and `discoveryEndpoint` are required; submit the redacted client secret sentinel to keep the stored secret unchanged. Requires the `oidc:manage` scope and the OIDC feature to be licensed. The client secret is redacted in the response. When the configuration is managed declaratively (via environment variables), the write is rejected with 409 and no changes are made. x-required-scope: oidc:manage -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true requestBody: required: true content: diff --git a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/testLogStreamingDestination.generated.yml b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/testLogStreamingDestination.generated.yml index 03bc5ba171d..40910893d0d 100644 --- a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/testLogStreamingDestination.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/testLogStreamingDestination.generated.yml @@ -4,9 +4,6 @@ tags: summary: Send a test message to a log streaming destination description: Send a test message to the destination to verify it is reachable and configured correctly. Requires the `eventBusDestination:test` scope and the Log Streaming feature to be licensed. x-required-scope: eventBusDestination:test -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/testOtelTrace.generated.yml b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/testOtelTrace.generated.yml index 2c714dcdff9..6efb82bb461 100644 --- a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/testOtelTrace.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/testOtelTrace.generated.yml @@ -4,9 +4,6 @@ tags: summary: Test the connection to an OTLP collector description: Send a single test span to the given OTLP collector and report whether it was accepted. This tests the supplied connection details without changing the stored configuration. Fields managed declaratively via environment variables are overridden with their effective value before the test is sent. Requires the `otel:manage` scope. x-required-scope: otel:manage -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true requestBody: required: true content: diff --git a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/updateLdapConfiguration.generated.yml b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/updateLdapConfiguration.generated.yml index 4d8e69591b6..7e0755140cf 100644 --- a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/updateLdapConfiguration.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/updateLdapConfiguration.generated.yml @@ -4,9 +4,6 @@ tags: summary: Set the LDAP configuration description: Replace the LDAP configuration with the provided full object (partial updates are not supported). For bindingAdminPassword, submit the blanking placeholder from a prior GET to keep the stored password unchanged. Requires the `ldap:manage` scope and the LDAP feature to be licensed. Setting loginEnabled to false is destructive and it deletes all stored LDAP user identities and disables synchronization. x-required-scope: ldap:manage -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true requestBody: required: true content: diff --git a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/updateLogStreamingDestination.generated.yml b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/updateLogStreamingDestination.generated.yml index e8286afb0ba..4d1341cbfd1 100644 --- a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/updateLogStreamingDestination.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/updateLogStreamingDestination.generated.yml @@ -4,9 +4,6 @@ tags: summary: Update a log streaming destination description: Replace an existing log streaming destination. The update takes effect exactly as it would from the UI, using the same validation. Requires the `eventBusDestination:update` scope and the Log Streaming feature to be licensed. When destinations are managed via environment variables, the write is rejected with 409 and nothing is changed; reads still return the current values. x-required-scope: eventBusDestination:update -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/updateOtelSettings.generated.yml b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/updateOtelSettings.generated.yml index 464f7ef36c4..93a4759e84f 100644 --- a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/updateOtelSettings.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/updateOtelSettings.generated.yml @@ -4,9 +4,6 @@ tags: summary: Set the OpenTelemetry configuration description: 'Set the OpenTelemetry configuration. This is a full replacement: every field must be provided, and a partial body is rejected. The exceptions are `exporterProtocol`, which defaults to `http/protobuf` when omitted, and `emitWorkflowStartSpan` and `emitNodeStartSpan`, which default to `false` when omitted. The update takes effect exactly as it would from the UI, using the same validation, and is applied to the running instance immediately. Fields managed declaratively via environment variables are read-only: attempting to change one is rejected with 409, while re-submitting its current value (as returned by GET) is accepted. Requires the `otel:manage` scope.' x-required-scope: otel:manage -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true requestBody: required: true content: diff --git a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/updateSamlConfiguration.generated.yml b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/updateSamlConfiguration.generated.yml index 007b0842f46..8fd55808cb3 100644 --- a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/updateSamlConfiguration.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/updateSamlConfiguration.generated.yml @@ -4,9 +4,6 @@ tags: summary: Set the SAML SSO configuration description: Replace the SAML SSO configuration with the provided full object. Every writable field must be sent; use empty strings or empty arrays when a value is unset. Read-only `entityID` / `returnUrl` from GET are ignored if included, so a GET response can be sent back as a PUT body. Redacted secret placeholders keep the stored values unchanged. The update takes effect exactly as it would from the UI, using the same validation. Requires the `saml:manage` scope and the SAML feature to be licensed. When the configuration is managed via environment variables, the write is rejected with 409 and no changes are made. x-required-scope: saml:manage -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true requestBody: required: true content: diff --git a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/updateSecurityPolicy.generated.yml b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/updateSecurityPolicy.generated.yml index 9603e1005ed..b9a1ebe342e 100644 --- a/packages/cli/src/public-api/v1/handlers/settings/spec/paths/updateSecurityPolicy.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/settings/spec/paths/updateSecurityPolicy.generated.yml @@ -4,9 +4,6 @@ tags: summary: Set the security policy description: Replace the instance security policy with the provided full object. Every writable field must be sent. Read-only usage counts from GET are ignored if included, so a GET response can be sent back as a PUT body. The update takes effect exactly as it would from the UI, using the same validation. Requires the `securitySettings:manage` scope and the Personal Space Policy feature to be licensed. When the group is managed via environment variables, the write is rejected with 409 and no changes are made; a read still returns the current values. x-required-scope: securitySettings:manage -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true requestBody: required: true content: diff --git a/packages/cli/src/public-api/v1/handlers/source-control/spec/paths/getSourceControlStatus.generated.yml b/packages/cli/src/public-api/v1/handlers/source-control/spec/paths/getSourceControlStatus.generated.yml index 6569bc009c2..c0c44d5a7ac 100644 --- a/packages/cli/src/public-api/v1/handlers/source-control/spec/paths/getSourceControlStatus.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/source-control/spec/paths/getSourceControlStatus.generated.yml @@ -4,9 +4,6 @@ tags: summary: Preview pending source control changes description: Previews the pending changes between the instance and the connected Git branch in either the `push` or `pull` direction. x-required-scope: sourceControl:read -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string @@ -143,6 +140,10 @@ responses: type: string matchedRuleId: type: string + projectId: + type: string + optInAvailable: + type: boolean required: - kind - checkId diff --git a/packages/cli/src/public-api/v1/handlers/source-control/spec/paths/pullSourceControl.generated.yml b/packages/cli/src/public-api/v1/handlers/source-control/spec/paths/pullSourceControl.generated.yml index c1002e339d7..9bbb09c177d 100644 --- a/packages/cli/src/public-api/v1/handlers/source-control/spec/paths/pullSourceControl.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/source-control/spec/paths/pullSourceControl.generated.yml @@ -4,9 +4,6 @@ tags: summary: Pull changes from the remote repository description: Fetches changes from the connected Git branch into the instance. x-required-scope: sourceControl:pull -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true requestBody: required: true content: @@ -153,6 +150,10 @@ responses: type: string matchedRuleId: type: string + projectId: + type: string + optInAvailable: + type: boolean required: - kind - checkId @@ -310,6 +311,10 @@ responses: type: string matchedRuleId: type: string + projectId: + type: string + optInAvailable: + type: boolean required: - kind - checkId diff --git a/packages/cli/src/public-api/v1/handlers/source-control/spec/paths/pushSourceControl.generated.yml b/packages/cli/src/public-api/v1/handlers/source-control/spec/paths/pushSourceControl.generated.yml index c02d6fb4e28..aceacf52052 100644 --- a/packages/cli/src/public-api/v1/handlers/source-control/spec/paths/pushSourceControl.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/source-control/spec/paths/pushSourceControl.generated.yml @@ -4,9 +4,6 @@ tags: summary: Push local source control changes description: Commits and pushes the selected files to the connected Git branch. Each entry in `fileNames` is resolved against a fresh preview of the pending changes. x-required-scope: sourceControl:push -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true requestBody: required: true content: @@ -173,6 +170,10 @@ responses: type: string matchedRuleId: type: string + projectId: + type: string + optInAvailable: + type: boolean required: - kind - checkId @@ -337,6 +338,10 @@ responses: type: string matchedRuleId: type: string + projectId: + type: string + optInAvailable: + type: boolean required: - kind - checkId diff --git a/packages/cli/src/public-api/v1/handlers/tags/spec/paths/createTag.generated.yml b/packages/cli/src/public-api/v1/handlers/tags/spec/paths/createTag.generated.yml index 3f4a4cbbb02..99fe89bd952 100644 --- a/packages/cli/src/public-api/v1/handlers/tags/spec/paths/createTag.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/tags/spec/paths/createTag.generated.yml @@ -4,9 +4,6 @@ tags: summary: Create a tag description: Create a tag in your instance. x-required-scope: tag:create -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true requestBody: required: true content: diff --git a/packages/cli/src/public-api/v1/handlers/tags/spec/paths/deleteTag.generated.yml b/packages/cli/src/public-api/v1/handlers/tags/spec/paths/deleteTag.generated.yml index 148332bb6a7..545d53b0e9e 100644 --- a/packages/cli/src/public-api/v1/handlers/tags/spec/paths/deleteTag.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/tags/spec/paths/deleteTag.generated.yml @@ -4,9 +4,6 @@ tags: summary: Delete a tag description: Deletes a tag. x-required-scope: tag:delete -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/tags/spec/paths/getTag.generated.yml b/packages/cli/src/public-api/v1/handlers/tags/spec/paths/getTag.generated.yml index 3baa50e6714..4946ad7bd3e 100644 --- a/packages/cli/src/public-api/v1/handlers/tags/spec/paths/getTag.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/tags/spec/paths/getTag.generated.yml @@ -4,9 +4,6 @@ tags: summary: Retrieves a tag description: Retrieves a tag. x-required-scope: tag:read -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/tags/spec/paths/getTags.generated.yml b/packages/cli/src/public-api/v1/handlers/tags/spec/paths/getTags.generated.yml index 64421dc4333..581229e8179 100644 --- a/packages/cli/src/public-api/v1/handlers/tags/spec/paths/getTags.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/tags/spec/paths/getTags.generated.yml @@ -7,9 +7,6 @@ x-required-scope: tag:list parameters: - $ref: ../../../../shared/spec/parameters/limit.yml - $ref: ../../../../shared/spec/parameters/cursor.yml -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true responses: '200': description: Operation successful. diff --git a/packages/cli/src/public-api/v1/handlers/tags/spec/paths/updateTag.generated.yml b/packages/cli/src/public-api/v1/handlers/tags/spec/paths/updateTag.generated.yml index 24571c5f42a..932d730cfad 100644 --- a/packages/cli/src/public-api/v1/handlers/tags/spec/paths/updateTag.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/tags/spec/paths/updateTag.generated.yml @@ -4,9 +4,6 @@ tags: summary: Update a tag description: Update a tag. x-required-scope: tag:update -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/tags/spec/schemas/tag.yml b/packages/cli/src/public-api/v1/handlers/tags/spec/schemas/tag.yml deleted file mode 100644 index d0df086574e..00000000000 --- a/packages/cli/src/public-api/v1/handlers/tags/spec/schemas/tag.yml +++ /dev/null @@ -1,20 +0,0 @@ -type: object -additionalProperties: false -required: - - name -properties: - id: - type: string - readOnly: true - example: 2tUt1wbLX592XDdX - name: - type: string - example: Production - createdAt: - type: string - format: date-time - readOnly: true - updatedAt: - type: string - format: date-time - readOnly: true diff --git a/packages/cli/src/public-api/v1/handlers/users/spec/paths/changeRole.generated.yml b/packages/cli/src/public-api/v1/handlers/users/spec/paths/changeRole.generated.yml index 6a8106653f2..4198ece363b 100644 --- a/packages/cli/src/public-api/v1/handlers/users/spec/paths/changeRole.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/users/spec/paths/changeRole.generated.yml @@ -4,9 +4,6 @@ tags: summary: Change a user's global role description: Change a user's global role x-required-scope: user:changeRole -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/users/spec/paths/createUser.generated.yml b/packages/cli/src/public-api/v1/handlers/users/spec/paths/createUser.generated.yml index f21b0bfadc7..0eb8a6436f0 100644 --- a/packages/cli/src/public-api/v1/handlers/users/spec/paths/createUser.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/users/spec/paths/createUser.generated.yml @@ -4,9 +4,6 @@ tags: summary: Create multiple users description: Create one or more users. x-required-scope: user:create -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true requestBody: required: true content: diff --git a/packages/cli/src/public-api/v1/handlers/users/spec/paths/deleteUser.generated.yml b/packages/cli/src/public-api/v1/handlers/users/spec/paths/deleteUser.generated.yml index e92478c5849..3e72a00ec82 100644 --- a/packages/cli/src/public-api/v1/handlers/users/spec/paths/deleteUser.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/users/spec/paths/deleteUser.generated.yml @@ -4,9 +4,6 @@ tags: summary: Delete user description: Delete a user from your instance. x-required-scope: user:delete -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/users/spec/paths/getUser.generated.yml b/packages/cli/src/public-api/v1/handlers/users/spec/paths/getUser.generated.yml index 5ba9b6ebe32..8c811dd33fa 100644 --- a/packages/cli/src/public-api/v1/handlers/users/spec/paths/getUser.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/users/spec/paths/getUser.generated.yml @@ -4,9 +4,6 @@ tags: summary: Get user by ID/Email description: Retrieve a user from your instance. Only available for the instance owner. x-required-scope: user:read -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/users/spec/paths/getUsers.generated.yml b/packages/cli/src/public-api/v1/handlers/users/spec/paths/getUsers.generated.yml index 26e6277e1d6..7a08f70a807 100644 --- a/packages/cli/src/public-api/v1/handlers/users/spec/paths/getUsers.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/users/spec/paths/getUsers.generated.yml @@ -21,9 +21,6 @@ parameters: required: false name: projectId in: query -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true responses: '200': description: Operation successful. diff --git a/packages/cli/src/public-api/v1/handlers/variables/spec/paths/createVariable.generated.yml b/packages/cli/src/public-api/v1/handlers/variables/spec/paths/createVariable.generated.yml index 640aef1cc91..fe65d3b0af1 100644 --- a/packages/cli/src/public-api/v1/handlers/variables/spec/paths/createVariable.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/variables/spec/paths/createVariable.generated.yml @@ -4,9 +4,6 @@ tags: summary: Create a variable description: Create a variable in your instance. x-required-scope: variable:create -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true requestBody: required: true content: diff --git a/packages/cli/src/public-api/v1/handlers/variables/spec/paths/deleteVariable.generated.yml b/packages/cli/src/public-api/v1/handlers/variables/spec/paths/deleteVariable.generated.yml index 4ae910be9c5..a52a55aa286 100644 --- a/packages/cli/src/public-api/v1/handlers/variables/spec/paths/deleteVariable.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/variables/spec/paths/deleteVariable.generated.yml @@ -4,9 +4,6 @@ tags: summary: Delete a variable description: Delete a variable from your instance. x-required-scope: variable:delete -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/variables/spec/paths/getVariables.generated.yml b/packages/cli/src/public-api/v1/handlers/variables/spec/paths/getVariables.generated.yml index 4bb4464e408..5c08ef8a684 100644 --- a/packages/cli/src/public-api/v1/handlers/variables/spec/paths/getVariables.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/variables/spec/paths/getVariables.generated.yml @@ -20,9 +20,6 @@ parameters: required: false name: state in: query -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true responses: '200': description: Operation successful. diff --git a/packages/cli/src/public-api/v1/handlers/variables/spec/paths/updateVariable.generated.yml b/packages/cli/src/public-api/v1/handlers/variables/spec/paths/updateVariable.generated.yml index f513500f3a2..7422c0b25d2 100644 --- a/packages/cli/src/public-api/v1/handlers/variables/spec/paths/updateVariable.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/variables/spec/paths/updateVariable.generated.yml @@ -4,9 +4,6 @@ tags: summary: Update a variable description: Update a variable from your instance. x-required-scope: variable:update -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/workflows/__tests__/workflow-publish-blocked.openapi.test.ts b/packages/cli/src/public-api/v1/handlers/workflows/__tests__/workflow-publish-blocked.openapi.test.ts index efccac7e027..968041d893c 100644 --- a/packages/cli/src/public-api/v1/handlers/workflows/__tests__/workflow-publish-blocked.openapi.test.ts +++ b/packages/cli/src/public-api/v1/handlers/workflows/__tests__/workflow-publish-blocked.openapi.test.ts @@ -23,21 +23,6 @@ describe('workflow publication blocker in OpenAPI', () => { }, ); - test('documents the review reason and request ID as optional', () => { - const schema = readSpec('schemas/workflowPublishBlockedError.yml'); - - expect(schema).toMatchObject({ - properties: { - reason: { - enum: ['review_pending', 'changes_requested'], - }, - workflowReviewRequestId: { - type: 'string', - }, - }, - }); - }); - // The update route replaces the shared 403 with its own body, because a refused // re-publication still saved a draft the caller needs to be told about. test('documents the permission refusal separately, naming the saved draft', () => { @@ -52,13 +37,4 @@ describe('workflow publication blocker in OpenAPI', () => { ]); expect(schema.properties.versionId.type).toBe('string'); }); - - // the same 409 also carries webhook conflicts, whose body is - // `message`-only - test('stays satisfiable by a message-only conflict body', () => { - const schema = readSpec('schemas/workflowPublishBlockedError.yml'); - - expect(schema.required).toEqual(['message']); - expect(schema.additionalProperties).toBeUndefined(); - }); }); diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/activateWorkflow.generated.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/activateWorkflow.generated.yml index 9dbbe84472c..989802539ae 100644 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/activateWorkflow.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/activateWorkflow.generated.yml @@ -5,9 +5,6 @@ summary: Publish a workflow description: 'Deprecated: use POST /workflows/{id}/publish instead. Publish a workflow. In n8n v1, this action was termed activating a workflow.' x-required-scope: workflow:activate deprecated: true -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/archiveWorkflow.generated.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/archiveWorkflow.generated.yml index d4612319bfe..89cad8873dc 100644 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/archiveWorkflow.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/archiveWorkflow.generated.yml @@ -4,9 +4,6 @@ tags: summary: Archive a workflow description: 'Soft-deletes a workflow by archiving it. Idempotent: archiving an already archived workflow returns 200 with the current workflow.' x-required-scope: workflow:delete -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/cancelTestRun.generated.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/cancelTestRun.generated.yml index 3e587e93845..278b4029ec1 100644 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/cancelTestRun.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/cancelTestRun.generated.yml @@ -4,9 +4,6 @@ tags: summary: Cancel a test run description: Cancel a running evaluation test run of a workflow. Requires the `workflow:execute` project scope in addition to the `testRun:cancel` API key scope. x-required-scope: testRun:cancel -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/createTestRun.generated.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/createTestRun.generated.yml index 774ef72b049..c9f0b496644 100644 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/createTestRun.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/createTestRun.generated.yml @@ -4,9 +4,6 @@ tags: summary: Trigger a test run description: Start a new evaluation test run for a workflow. The workflow must contain a configured evaluation trigger. Requires the `workflow:execute` project scope in addition to the `testRun:create` API key scope. x-required-scope: testRun:create -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/createWorkflow.generated.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/createWorkflow.generated.yml index 489e16574db..ec91be3641e 100644 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/createWorkflow.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/createWorkflow.generated.yml @@ -4,9 +4,6 @@ tags: summary: Create a workflow description: Create a workflow in your instance. x-required-scope: workflow:create -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true requestBody: required: true content: diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/deactivateWorkflow.generated.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/deactivateWorkflow.generated.yml index de3a43aa0e2..aab5822cc35 100644 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/deactivateWorkflow.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/deactivateWorkflow.generated.yml @@ -5,9 +5,6 @@ summary: Deactivate a workflow description: 'Deprecated: use POST /workflows/{id}/unpublish instead. Deactivate a workflow.' x-required-scope: workflow:deactivate deprecated: true -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/deleteWorkflow.generated.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/deleteWorkflow.generated.yml index da6e3338c9b..b277e5d3466 100644 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/deleteWorkflow.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/deleteWorkflow.generated.yml @@ -4,9 +4,6 @@ tags: summary: Delete a workflow description: Delete a workflow. x-required-scope: workflow:delete -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getDeprecatedWorkflowVersion.generated.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getDeprecatedWorkflowVersion.generated.yml index 94cccaeeb97..c84aec4b739 100644 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getDeprecatedWorkflowVersion.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getDeprecatedWorkflowVersion.generated.yml @@ -5,9 +5,6 @@ summary: Retrieves a specific version of a workflow description: 'Deprecated: use GET /workflows/{workflowId}/versions/{workflowVersionId} instead. Retrieves a specific version of a workflow from workflow history.' x-required-scope: workflow:read deprecated: true -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getTestCases.generated.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getTestCases.generated.yml index 486822b13cb..2e5d80a5b6b 100644 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getTestCases.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getTestCases.generated.yml @@ -19,9 +19,6 @@ parameters: description: The ID of the test run. name: runId in: path -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true responses: '200': description: Operation successful. diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getTestRun.generated.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getTestRun.generated.yml index bac49df64b4..43b014b79c9 100644 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getTestRun.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getTestRun.generated.yml @@ -4,9 +4,6 @@ tags: summary: Retrieve a test run description: Retrieve a single evaluation test run of a workflow, including its aggregated metrics and final result. x-required-scope: testRun:read -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getTestRuns.generated.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getTestRuns.generated.yml index da42197e3d1..a4f6dd9bb65 100644 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getTestRuns.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getTestRuns.generated.yml @@ -25,9 +25,6 @@ parameters: required: false name: status in: query -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true responses: '200': description: Operation successful. diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getWorkflow.generated.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getWorkflow.generated.yml index c225e1ec933..75641b8d14e 100644 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getWorkflow.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getWorkflow.generated.yml @@ -4,9 +4,6 @@ tags: summary: Retrieve a workflow description: Retrieve a workflow. x-required-scope: workflow:read -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getWorkflowHistory.generated.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getWorkflowHistory.generated.yml index 97b4e792564..18a23aedc06 100644 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getWorkflowHistory.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getWorkflowHistory.generated.yml @@ -13,9 +13,6 @@ parameters: description: The ID of the workflow. name: workflowId in: path -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true responses: '200': description: Operation successful. diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getWorkflowTags.generated.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getWorkflowTags.generated.yml index 325e7422782..9971c46b3ef 100644 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getWorkflowTags.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getWorkflowTags.generated.yml @@ -4,9 +4,6 @@ tags: summary: Get workflow tags description: Get workflow tags. x-required-scope: workflowTags:list -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getWorkflowVersion.generated.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getWorkflowVersion.generated.yml index fd732e10073..de897060b5a 100644 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getWorkflowVersion.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getWorkflowVersion.generated.yml @@ -4,9 +4,6 @@ tags: summary: Retrieve a workflow version description: Retrieve a single version of a workflow from its version history. x-required-scope: workflow:read -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getWorkflows.generated.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getWorkflows.generated.yml index 495d33ccf6e..04af352abb9 100644 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getWorkflows.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/getWorkflows.generated.yml @@ -40,9 +40,6 @@ parameters: required: false name: excludePinnedData in: query -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true responses: '200': description: Operation successful. diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/publishWorkflow.generated.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/publishWorkflow.generated.yml index 80959308c42..00fcf45c950 100644 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/publishWorkflow.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/publishWorkflow.generated.yml @@ -4,9 +4,6 @@ tags: summary: Publish a workflow description: Publish a workflow. In n8n v1, this action was termed activating a workflow. x-required-scope: workflow:activate -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/transferWorkflow.generated.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/transferWorkflow.generated.yml index 2b5a39f0828..32c31e08155 100644 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/transferWorkflow.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/transferWorkflow.generated.yml @@ -4,9 +4,6 @@ tags: summary: Transfer a workflow to another project description: Transfer a workflow to another project. x-required-scope: workflow:move -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/unarchiveWorkflow.generated.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/unarchiveWorkflow.generated.yml index 9b4ac64813a..847e8e0ac43 100644 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/unarchiveWorkflow.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/unarchiveWorkflow.generated.yml @@ -4,9 +4,6 @@ tags: summary: Unarchive a workflow description: Restores an archived workflow. x-required-scope: workflow:delete -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/unpublishWorkflow.generated.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/unpublishWorkflow.generated.yml index f7d05957438..c2d7123a24e 100644 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/unpublishWorkflow.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/unpublishWorkflow.generated.yml @@ -4,9 +4,6 @@ tags: summary: Unpublish a workflow description: Unpublish a workflow. In n8n v1, this action was termed deactivating a workflow. x-required-scope: workflow:deactivate -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/updateWorkflow.generated.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/updateWorkflow.generated.yml index c08ea8cdccf..dbeb36d65d0 100644 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/updateWorkflow.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/updateWorkflow.generated.yml @@ -4,9 +4,6 @@ tags: summary: Update a workflow description: 'Update a workflow. If the workflow is published, the updated version will be automatically re-published unless `publishIfActive` is set to `false`. Because that re-publication puts a new version live, it additionally requires the `workflow:activate` API key scope and the `workflow:publish` project permission. A caller without either can still save: the new version is stored as a draft and the response is a `403` naming the missing permission, leaving the published version live. Saving an unpublished workflow, or saving with `publishIfActive=false`, only needs `workflow:update`.' x-required-scope: workflow:update -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/updateWorkflowTags.generated.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/updateWorkflowTags.generated.yml index 3f1b95a474c..0eea035f76e 100644 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/updateWorkflowTags.generated.yml +++ b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/updateWorkflowTags.generated.yml @@ -4,9 +4,6 @@ tags: summary: Update tags of a workflow description: Update tags of a workflow. x-required-scope: workflowTags:update -x-eov-operation-id: unreachable -x-eov-operation-handler: v1/handlers/decorator-routed.handler -x-decorator-routed: true parameters: - schema: type: string diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/schemas/activeVersion.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/schemas/activeVersion.yml deleted file mode 100644 index 880c682fd5a..00000000000 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/schemas/activeVersion.yml +++ /dev/null @@ -1,58 +0,0 @@ -type: object -readOnly: true -nullable: true -additionalProperties: false -properties: - versionId: - type: string - readOnly: true - description: Unique identifier for this workflow version - example: 7c6b9e3f-8d4a-4b2c-9f1e-6a5d3b8c7e4f - workflowId: - type: string - readOnly: true - description: The workflow this version belongs to - example: 2tUt1wbLX592XDdX - nodes: - type: array - readOnly: true - items: - $ref: './node.yml' - connections: - type: object - readOnly: true - example: { Jira: { main: [[{ node: 'Jira', type: 'main', index: 0 }]] } } - nodeGroups: - type: array - readOnly: true - description: Visual groupings of nodes shown as frames on the canvas - items: - $ref: './workflowNodeGroup.yml' - authors: - type: string - readOnly: true - description: Comma-separated list of author IDs who contributed to this version - example: 1,2,3 - name: - type: string - nullable: true - readOnly: true - description: Optional name for this workflow version - example: Production release - description: - type: string - nullable: true - readOnly: true - description: Optional description for this workflow version - autosaved: - type: boolean - readOnly: true - description: Whether this version was created by autosave - createdAt: - type: string - format: date-time - readOnly: true - updatedAt: - type: string - format: date-time - readOnly: true diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/schemas/node.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/schemas/node.yml deleted file mode 100644 index 847f876ca3a..00000000000 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/schemas/node.yml +++ /dev/null @@ -1,81 +0,0 @@ -type: object -additionalProperties: false -properties: - id: - type: string - example: 0f5532f9-36ba-4bef-86c7-30d607400b15 - name: - type: string - example: Jira - webhookId: - type: string - disabled: - type: boolean - notesInFlow: - type: boolean - notes: - type: string - type: - type: string - example: n8n-nodes-base.jira - typeVersion: - type: number - example: 1 - executeOnce: - type: boolean - example: false - alwaysOutputData: - type: boolean - example: false - retryOnFail: - type: boolean - example: false - maxTries: - type: number - waitBetweenTries: - type: number - continueOnFail: - type: boolean - example: false - description: 'use onError instead' - deprecated: true - onError: - type: string - example: 'stopWorkflow' - position: - type: array - items: - type: number - example: [-100, 80] - parameters: - type: object - additionalProperties: true - example: { additionalProperties: {} } - credentials: - type: object - example: { jiraSoftwareCloudApi: { id: '35', name: 'jiraApi' } } - customTelemetryTags: - type: object - additionalProperties: false - properties: - tag: - type: array - items: - type: object - additionalProperties: false - required: - - key - - value - properties: - key: - type: string - value: - type: string - createdAt: - type: string - format: date-time - readOnly: true - updatedAt: - type: string - format: date-time - readOnly: true diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/schemas/parameters/workflowId.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/schemas/parameters/workflowId.yml deleted file mode 100644 index e8389a78b05..00000000000 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/schemas/parameters/workflowId.yml +++ /dev/null @@ -1,6 +0,0 @@ -name: id -in: path -description: The ID of the workflow. -required: true -schema: - type: string diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/schemas/sharedWorkflow.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/schemas/sharedWorkflow.yml deleted file mode 100644 index 9db8a51a6c7..00000000000 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/schemas/sharedWorkflow.yml +++ /dev/null @@ -1,31 +0,0 @@ -type: object -additionalProperties: false -properties: - role: - type: string - example: 'workflow:owner' - workflowId: - type: string - example: '2tUt1wbLX592XDdX' - projectId: - type: string - example: '2tUt1wbLX592XDdX' - project: - type: object - properties: - id: - type: string - readOnly: true - name: - type: string - type: - type: string - readOnly: true - createdAt: - type: string - format: date-time - readOnly: true - updatedAt: - type: string - format: date-time - readOnly: true diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/schemas/workflow.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/schemas/workflow.yml deleted file mode 100644 index 0eb571b2164..00000000000 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/schemas/workflow.yml +++ /dev/null @@ -1,104 +0,0 @@ -type: object -additionalProperties: false -required: - - name - - nodes - - connections - - settings -properties: - id: - type: string - readOnly: true - example: 2tUt1wbLX592XDdX - name: - type: string - example: Workflow 1 - description: - type: string - description: Description of the workflow - example: My workflow description - parentFolderId: - type: string - nullable: true - writeOnly: true - description: ID of the folder to move the workflow into. Pass null to move it to the project root; omit to leave its current folder unchanged. - example: X8ovzm8lTQjcXRZQ - active: - type: boolean - readOnly: true - deprecated: true - description: Deprecated. Check whether `activeVersionId` is not null instead. - activeVersionId: - type: string - nullable: true - readOnly: true - createdAt: - type: string - format: date-time - readOnly: true - updatedAt: - type: string - format: date-time - readOnly: true - isArchived: - type: boolean - readOnly: true - versionId: - type: string - readOnly: true - description: Current version identifier used for optimistic locking - triggerCount: - type: integer - readOnly: true - description: Number of active trigger nodes in the workflow - nodes: - type: array - items: - $ref: './node.yml' - connections: - type: object - example: { Jira: { main: [[{ node: 'Jira', type: 'main', index: 0 }]] } } - nodeGroups: - type: array - description: Visual groupings of nodes shown as frames on the canvas - items: - $ref: './workflowNodeGroup.yml' - settings: - $ref: './workflowSettings.yml' - staticData: - example: { lastId: 1 } - anyOf: - - type: string - format: 'jsonString' - nullable: true - - type: object - nullable: true - pinData: - type: object - nullable: true - description: Pinned sample data for nodes, keyed by node name - meta: - type: object - nullable: true - readOnly: true - description: Workflow metadata such as template information - properties: - onboardingId: - type: string - templateId: - type: string - instanceId: - type: string - templateCredsSetupCompleted: - type: boolean - tags: - type: array - items: - $ref: '../../../tags/spec/schemas/tag.yml' - readOnly: true - shared: - type: array - items: - $ref: './sharedWorkflow.yml' - activeVersion: - $ref: './activeVersion.yml' diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/schemas/workflowList.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/schemas/workflowList.yml deleted file mode 100644 index d5e455ee954..00000000000 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/schemas/workflowList.yml +++ /dev/null @@ -1,11 +0,0 @@ -type: object -properties: - data: - type: array - items: - $ref: './workflow.yml' - nextCursor: - type: string - description: Paginate through workflows by setting the cursor parameter to a nextCursor attribute returned by a previous request. Default value fetches the first "page" of the collection. - nullable: true - example: MTIzZTQ1NjctZTg5Yi0xMmQzLWE0NTYtNDI2NjE0MTc0MDA diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/schemas/workflowNodeGroup.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/schemas/workflowNodeGroup.yml deleted file mode 100644 index d067a31001f..00000000000 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/schemas/workflowNodeGroup.yml +++ /dev/null @@ -1,25 +0,0 @@ -type: object -additionalProperties: false -required: - - id - - name - - nodeIds -properties: - id: - type: string - description: Unique identifier for the node group - example: 9b1c8e2a-4d3f-4a6b-8c7d-1e2f3a4b5c6d - name: - type: string - description: Display name of the node group - example: Data processing - description: - type: string - maxLength: 155 - description: Optional plain-text description of the node group - example: Cleans and normalizes incoming records - nodeIds: - type: array - description: IDs of the nodes that belong to this group - items: - type: string diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/schemas/workflowPublishBlockedError.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/schemas/workflowPublishBlockedError.yml deleted file mode 100644 index 78303775f62..00000000000 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/schemas/workflowPublishBlockedError.yml +++ /dev/null @@ -1,16 +0,0 @@ -type: object -description: >- - Conflict response. `reason` and `workflowReviewRequestId` are present only - when the conflict is an open workflow review blocking publication. -required: - - message -properties: - message: - type: string - reason: - type: string - enum: - - review_pending - - changes_requested - workflowReviewRequestId: - type: string diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/schemas/workflowSettings.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/schemas/workflowSettings.yml deleted file mode 100644 index 5bf0d7a29e5..00000000000 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/schemas/workflowSettings.yml +++ /dev/null @@ -1,129 +0,0 @@ -type: object -additionalProperties: false -properties: - saveExecutionProgress: - type: boolean - saveManualExecutions: - type: boolean - saveDataErrorExecution: - type: string - enum: ['all', 'none'] - saveDataSuccessExecution: - type: string - enum: ['all', 'none'] - executionTimeout: - type: number - example: 3600 - maxLength: 3600 - errorWorkflow: - type: string - example: 'VzqKEW0ShTXA5vPj' - description: The ID of the workflow that contains the error trigger node. - timezone: - type: string - example: America/New_York - executionOrder: - type: string - example: v1 - binaryMode: - type: string - enum: ['separate', 'combined'] - description: | - Controls how binary data is resolved from a node's input. This is a derived, - internal setting rather than something intended to be set programmatically. - It is included in workflow responses for reference, but any value sent when - creating or updating a workflow is ignored. - callerPolicy: - type: string - enum: ['any', 'none', 'workflowsFromAList', 'workflowsFromSameOwner'] - description: | - Controls which workflows are allowed to call this workflow using the Execute Workflow node. - Defaults to workflowsFromSameOwner. - - Available options: - - `any`: Any workflow can call this workflow (no restrictions) - - `none`: No other workflows can call this workflow (completely blocked) - - `workflowsFromSameOwner` (default): Only workflows owned by the same project can call this workflow - * For personal projects: Only workflows created by the same user - * For team projects: Only workflows within the same team project - - `workflowsFromAList`: Only specific workflows listed in the `callerIds` field can call this workflow - * Requires the `callerIds` field to specify which workflow IDs are allowed - * See `callerIds` field documentation for usage - example: workflowsFromSameOwner - callerIds: - type: string - description: Comma-separated list of workflow IDs allowed to call this workflow (only used with workflowsFromAList policy) - example: '14, 18, 23' - timeSavedMode: - type: string - enum: ['fixed', 'dynamic'] - description: | - Controls how the time saved per execution is calculated. - Available options: - - `fixed`: Uses a predetermined time value specified in the `timeSavedPerExecution` field. - * Requires the `timeSavedPerExecution` field to be set - * Use when the time saved is consistent across all executions - - `dynamic`: Automatically calculates time saved based on actual execution metrics - * The `timeSavedPerExecution` field is ignored when this mode is active - * Use when time saved varies between executions - timeSavedPerExecution: - type: number - description: Estimated time saved per execution in minutes - redactionPolicy: - type: string - enum: ['none', 'non-manual', 'manual-only', 'all'] - description: | - Controls whether execution data is redacted for this workflow. - - Available options: - - `none` (default): No redaction — all execution data is stored. - - `non-manual`: Redact production (non-manually triggered) executions only. - - `manual-only`: Redact manually triggered executions only. - - `all`: Redact all executions (manual and production). - - When the instance has a redaction floor configured, the policy must be equal to - or stricter than the floor. A policy weaker than the floor is rejected with 422 - on create, and on update when it changes the stored policy; an unchanged - pre-existing below-floor policy is preserved (the floor is not applied - retroactively). Omitting this field when creating a workflow seeds it to the - instance floor instead. - example: non-manual - availableInMCP: - type: boolean - description: | - Controls whether this workflow is accessible via the Model Context Protocol (MCP). - Defaults to false. - - When enabled, this workflow can be called by MCP clients (AI assistants and other tools - that support MCP). This allows external AI tools to discover and execute this workflow - as part of their capabilities. - - Requirements for enabling MCP access: - - The workflow must be active (not deactivated) - - The workflow must contain at least one active Webhook node - - Only webhook-triggered workflows can be exposed via MCP - - Security note: When a workflow is available in MCP, it can be discovered and executed - by any MCP client that has the appropriate API credentials for your n8n instance. - example: false - customTelemetryTags: - type: array - items: - type: object - additionalProperties: false - required: - - key - - value - properties: - key: - type: string - value: - type: string - credentialResolverId: - type: string - description: | - ID of the credential resolver used to resolve credentials for this workflow. - This is a derived, internal setting managed via the workflow's credential - resolver configuration rather than something intended to be set programmatically. - It is included in workflow responses for reference, but any value sent when - creating or updating a workflow is ignored. diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/schemas/workflowVersionListItem.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/schemas/workflowVersionListItem.yml deleted file mode 100644 index aef22b7de18..00000000000 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/schemas/workflowVersionListItem.yml +++ /dev/null @@ -1,41 +0,0 @@ -type: object -additionalProperties: false -required: - - versionId - - workflowId - - authors -properties: - versionId: - type: string - readOnly: true - description: The version ID of this workflow snapshot - example: abc123-def456 - workflowId: - type: string - readOnly: true - description: The workflow ID this version belongs to - example: 2tUt1wbLX592XDdX - authors: - type: string - readOnly: true - description: Authors who created this version - example: John Doe - name: - type: string - nullable: true - description: Workflow name at this version - example: Workflow 1 - description: - type: string - nullable: true - description: Workflow description at this version - createdAt: - type: string - format: date-time - readOnly: true - description: When this version was created - updatedAt: - type: string - format: date-time - readOnly: true - description: When this version was last updated diff --git a/packages/cli/src/public-api/v1/openapi-gen/__tests__/decorator-routes.test.ts b/packages/cli/src/public-api/v1/openapi-gen/__tests__/decorator-routes.test.ts index 268fd806d49..c4141d78377 100644 --- a/packages/cli/src/public-api/v1/openapi-gen/__tests__/decorator-routes.test.ts +++ b/packages/cli/src/public-api/v1/openapi-gen/__tests__/decorator-routes.test.ts @@ -172,7 +172,7 @@ describe('getDecoratorGeneratedOperations', () => { expect(params?.shape.widgetId).toBeInstanceOf(z.ZodString); }); - it('bare route: omits every optional field, but always adds success/auth responses and eov routing headers', () => { + it('bare route: omits every optional field, but always adds success/auth responses', () => { class WidgetsPublicController { @Get('/') @ApiResponse(200) @@ -194,11 +194,7 @@ describe('getDecoratorGeneratedOperations', () => { expect(operation.config.responses[401]).toEqual({ $ref: '../../../../shared/spec/responses/unauthorized.yml', }); - expect(operation.config['x-eov-operation-id']).toBe('unreachable'); - expect(operation.config['x-eov-operation-handler']).toBe( - 'v1/handlers/decorator-routed.handler', - ); - expect(operation.config['x-decorator-routed']).toBe(true); + expect(Object.keys(operation.config).filter((key) => key.startsWith('x-'))).toEqual([]); }); it('documents a bare-array response DTO as an array schema, not an object envelope', () => { diff --git a/packages/cli/src/public-api/v1/openapi-gen/__tests__/generate.test.ts b/packages/cli/src/public-api/v1/openapi-gen/__tests__/generate.test.ts index 49d43b358ee..b45b83212ae 100644 --- a/packages/cli/src/public-api/v1/openapi-gen/__tests__/generate.test.ts +++ b/packages/cli/src/public-api/v1/openapi-gen/__tests__/generate.test.ts @@ -1,11 +1,19 @@ import { OpenAPIRegistry } from '@asteasolutions/zod-to-openapi'; import { Z } from '@n8n/api-types'; +import { ApiResponse, ControllerRegistryMetadata, Get, Patch } from '@n8n/decorators'; +import type { Controller } from '@n8n/decorators'; +import { Container } from '@n8n/di'; import { UnexpectedError } from 'n8n-workflow'; +import { parse } from 'yaml'; import { z } from 'zod'; +import { markPublicApiController } from '@/public-api/__tests__/public-api-controller-test-utils'; + import { + assembleSpec, buildArtifactsFromRegistry, - mergeDecoratorDocument, + DECORATOR_ROOT_FILENAME, + getGeneratedArtifacts, registerSharedSchemas, type OpenApiDocument, } from '../generate'; @@ -15,130 +23,125 @@ function makeNamedResponseDto(className: string, shape: Parameters { - it('adds a decorator-only path that the eov spec does not define', () => { - const eov: OpenApiDocument = { paths: { '/tags': { post: { operationId: 'createTag' } } } }; - const decorator: OpenApiDocument = { - paths: { '/workflows/{id}/history': { get: { operationId: 'getWorkflowHistory' } } }, - }; - - const merged = mergeDecoratorDocument(eov, decorator); - - expect(merged.paths?.['/tags']).toEqual({ post: { operationId: 'createTag' } }); - expect(merged.paths?.['/workflows/{id}/history']).toEqual({ - get: { operationId: 'getWorkflowHistory' }, - }); +describe('getGeneratedArtifacts path parameter names', () => { + beforeEach(() => { + Container.set(ControllerRegistryMetadata, new ControllerRegistryMetadata()); }); - it('merges a decorator method into a path the eov spec also serves', () => { - const eov: OpenApiDocument = { paths: { '/tags': { post: { operationId: 'createTag' } } } }; - const decorator: OpenApiDocument = { paths: { '/tags': { get: { operationId: 'getTags' } } } }; - - const merged = mergeDecoratorDocument(eov, decorator); - - expect(merged.paths?.['/tags']).toEqual({ - post: { operationId: 'createTag' }, - get: { operationId: 'getTags' }, - }); - }); - - it('throws when the same path+method is declared by both sides', () => { - const eov: OpenApiDocument = { paths: { '/tags': { get: { operationId: 'listTagsEov' } } } }; - const decorator: OpenApiDocument = { paths: { '/tags': { get: { operationId: 'getTags' } } } }; - - expect(() => mergeDecoratorDocument(eov, decorator)).toThrow(UnexpectedError); - expect(() => mergeDecoratorDocument(eov, decorator)).toThrow(/GET \/tags/); - }); - - it.each([ - ['/credentials/{id}', '/credentials/{credentialId}'], - ['/tags/{id}', '/tags/{tagId}'], - ['/projects/{projectId}/credentials/{id}', '/projects/{projectId}/credentials/{credentialId}'], - ])('rejects conflicting parameter names in %s and %s', (legacyPath, decoratorPath) => { - const eov: OpenApiDocument = { - paths: { [legacyPath]: { patch: { operationId: 'updateResource' } } }, - }; - const decorator: OpenApiDocument = { - paths: { [decoratorPath]: { get: { operationId: 'getResource' } } }, - }; - - expect(() => mergeDecoratorDocument(eov, decorator)).toThrow(UnexpectedError); - expect(() => mergeDecoratorDocument(eov, decorator)).toThrow( - `Equivalent OpenAPI paths use different parameter names: '${legacyPath}' and '${decoratorPath}'.`, - ); - }); - - it.each(['eov', 'decorator'])( - 'rejects conflicting parameter names within the %s document', - (side) => { - const conflictingPaths: OpenApiDocument['paths'] = { - '/credentials/{id}': { patch: { operationId: 'updateCredential' } }, - '/credentials/{credentialId}': { get: { operationId: 'getCredential' } }, - }; - const eov: OpenApiDocument = { paths: side === 'eov' ? conflictingPaths : {} }; - const decorator: OpenApiDocument = { paths: side === 'decorator' ? conflictingPaths : {} }; - - expect(() => mergeDecoratorDocument(eov, decorator)).toThrow( - /Equivalent OpenAPI paths use different parameter names/, - ); - }, - ); - - it('merges methods with matching path parameters without changing either input', () => { - const patch = { - operationId: 'updateCredential', - parameters: [{ name: 'id', in: 'path', required: true, schema: { type: 'string' } }], - }; - const get = { operationId: 'getCredential' }; - const eov: OpenApiDocument = { paths: { '/credentials/{id}': { patch } } }; - const decorator: OpenApiDocument = { paths: { '/credentials/{id}': { get } } }; - - const merged = mergeDecoratorDocument(eov, decorator); - - expect(merged.paths).toEqual({ '/credentials/{id}': { patch, get } }); - expect(eov.paths).toEqual({ '/credentials/{id}': { patch } }); - expect(decorator.paths).toEqual({ '/credentials/{id}': { get } }); - }); + const getRootPaths = (): string[] => { + const root = getGeneratedArtifacts().find((a) => a.outputPath === DECORATOR_ROOT_FILENAME); + const document = parse(root?.content ?? '') as OpenApiDocument; + return Object.keys(document.paths ?? {}).sort(); + }; it('keeps different static paths with the same parameter positions separate', () => { - const patch = { operationId: 'updateCredential' }; - const get = { operationId: 'getCredentialType' }; - const eov: OpenApiDocument = { paths: { '/credentials/{id}': { patch } } }; - const decorator: OpenApiDocument = { paths: { '/credential-types/{name}': { get } } }; + class CredentialsPublicController { + @Get('/:id') + @ApiResponse(200) + method() {} + } + class CredentialTypesPublicController { + @Get('/:name') + @ApiResponse(200) + method() {} + } + markPublicApiController(CredentialsPublicController as Controller, '/credentials'); + markPublicApiController(CredentialTypesPublicController as Controller, '/credential-types'); - expect(mergeDecoratorDocument(eov, decorator).paths).toEqual({ - '/credentials/{id}': { patch }, - '/credential-types/{name}': { get }, + expect(getRootPaths()).toEqual(['/credential-types/{name}', '/credentials/{id}']); + }); + + it('throws when equivalent paths use different parameter names', () => { + class CredentialsGetController { + @Get('/:id') + @ApiResponse(200) + method() {} + } + class CredentialsPatchController { + @Patch('/:credentialId') + @ApiResponse(200) + method() {} + } + markPublicApiController(CredentialsGetController as Controller, '/credentials'); + markPublicApiController(CredentialsPatchController as Controller, '/credentials'); + + expect(() => getGeneratedArtifacts()).toThrow(UnexpectedError); + expect(() => getGeneratedArtifacts()).toThrow( + /Equivalent OpenAPI paths use different parameter names/, + ); + }); +}); + +describe('assembleSpec', () => { + it('takes paths and components from the generated document', () => { + const envelope: OpenApiDocument = { openapi: '3.0.0', paths: {} }; + const generated: OpenApiDocument = { + paths: { '/tags': { get: { operationId: 'getTags' } } }, + components: { schemas: { Tag: { type: 'object' } } }, + }; + + const assembled = assembleSpec(envelope, generated); + + expect(assembled.paths).toEqual({ '/tags': { get: { operationId: 'getTags' } } }); + expect(assembled.components).toEqual({ schemas: { Tag: { type: 'object' } } }); + }); + + it('keeps the envelope keys and its security schemes', () => { + const envelope: OpenApiDocument = { + openapi: '3.0.0', + info: { title: 'n8n Public API', version: '1.1.1' }, + security: [{ ApiKeyAuth: [] }], + tags: [{ name: 'Tags' }], + paths: {}, + components: { securitySchemes: { ApiKeyAuth: { type: 'apiKey', in: 'header' } } }, + }; + + const assembled = assembleSpec(envelope, { + paths: { '/tags': { get: { operationId: 'getTags' } } }, + components: { schemas: { Tag: { type: 'object' } } }, + }); + + expect(assembled).toMatchObject({ + openapi: '3.0.0', + info: { title: 'n8n Public API', version: '1.1.1' }, + security: [{ ApiKeyAuth: [] }], + tags: [{ name: 'Tags' }], + }); + expect(assembled.components).toEqual({ + schemas: { Tag: { type: 'object' } }, + securitySchemes: { ApiKeyAuth: { type: 'apiKey', in: 'header' } }, }); }); - it('dedupes an identical component that both sides hoisted from the same shared file', () => { - const unauthorized = { description: 'Unauthorized' }; - const eov: OpenApiDocument = { - paths: {}, - components: { responses: { Unauthorized: unauthorized } }, - }; - const decorator: OpenApiDocument = { - paths: {}, - components: { responses: { Unauthorized: { ...unauthorized } } }, - }; - - const merged = mergeDecoratorDocument(eov, decorator); - - expect(merged.components?.responses).toEqual({ Unauthorized: unauthorized }); - }); - - it('throws when a component name resolves to different definitions', () => { - const eov: OpenApiDocument = { - paths: {}, - components: { schemas: { Tag: { type: 'object', properties: { id: {} } } } }, - }; - const decorator: OpenApiDocument = { + it('throws when the envelope and the generated document define the same component', () => { + const envelope: OpenApiDocument = { paths: {}, components: { schemas: { Tag: { type: 'string' } } }, }; + const generated: OpenApiDocument = { + paths: { '/tags': { get: { operationId: 'getTags' } } }, + components: { schemas: { Tag: { type: 'object' } } }, + }; - expect(() => mergeDecoratorDocument(eov, decorator)).toThrow(/components\.schemas\.Tag/); + expect(() => assembleSpec(envelope, generated)).toThrow(UnexpectedError); + expect(() => assembleSpec(envelope, generated)).toThrow(/components\.schemas\.Tag/); + }); + + it('throws when the envelope declares paths', () => { + const envelope: OpenApiDocument = { paths: { '/tags': { get: {} } } }; + const generated: OpenApiDocument = { + paths: { '/tags': { get: { operationId: 'getTags' } } }, + }; + + expect(() => assembleSpec(envelope, generated)).toThrow(UnexpectedError); + expect(() => assembleSpec(envelope, generated)).toThrow(/still declares paths \(\/tags\)/); + }); + + it('throws when the generated spec has no paths', () => { + const envelope: OpenApiDocument = { paths: {} }; + + expect(() => assembleSpec(envelope, { paths: {} })).toThrow(UnexpectedError); + expect(() => assembleSpec(envelope, { paths: {} })).toThrow(/has no paths/); }); }); diff --git a/packages/cli/src/public-api/v1/openapi-gen/decorator-routes.ts b/packages/cli/src/public-api/v1/openapi-gen/decorator-routes.ts index 3aebd9147cf..7f30d28a084 100644 --- a/packages/cli/src/public-api/v1/openapi-gen/decorator-routes.ts +++ b/packages/cli/src/public-api/v1/openapi-gen/decorator-routes.ts @@ -321,8 +321,7 @@ export interface GeneratedDecoratorOperation { /** * Builds one `RouteConfig` per route discovered on a `@PublicApiController` class. - * A new `@PublicApiController` shows up here automatically; a legacy eov-routed endpoint (still hand-written YAML) - * is untouched until it's migrated to the controller pattern. + * A new `@PublicApiController` shows up here automatically. * * Output path convention: `handlers//spec/paths/.generated.yml` */ @@ -360,11 +359,6 @@ export function getDecoratorGeneratedOperations( } : {}), responses: buildResponses(route, resolveSchema), - // Satisfies express-openapi-validator's operation-handler installer, which requires - // every operation in the spec to resolve to something. - 'x-eov-operation-id': 'unreachable', - 'x-eov-operation-handler': 'v1/handlers/decorator-routed.handler', - 'x-decorator-routed': true, }; return { diff --git a/packages/cli/src/public-api/v1/openapi-gen/generate.ts b/packages/cli/src/public-api/v1/openapi-gen/generate.ts index e8d2282723b..d52f3f366cc 100644 --- a/packages/cli/src/public-api/v1/openapi-gen/generate.ts +++ b/packages/cli/src/public-api/v1/openapi-gen/generate.ts @@ -3,12 +3,9 @@ import type { RouteConfig } from '@asteasolutions/zod-to-openapi'; import { UnexpectedError } from 'n8n-workflow'; import fs from 'node:fs'; import path from 'node:path'; -import { isDeepStrictEqual } from 'node:util'; import { stringify } from 'yaml'; import type { z } from 'zod'; -import { HTTP_METHODS } from '@/public-api/public-api-route-resolver'; - import { getDecoratorGeneratedOperations, getSharedResponseSchemas, @@ -21,11 +18,12 @@ const COMPONENT_SCHEMA_REF = /^#\/components\/schemas\/(.+)$/; const SHARED_SCHEMA_DIR = 'shared/spec/schemas'; const YAML_OPTS = { aliasDuplicateObjects: false, singleQuote: true, lineWidth: 0 } as const; -// Generated root that registers every decorator-routed operation, sitting next to `openapi.yml` so -// its `$ref`s to the fragment files resolve on the same relative basis. +// Generated root that registers every operation. It sits next to `openapi.yml`, so its `$ref`s to +// the fragment files resolve from the same directory. The build bundles it and assembles it into +// the envelope (see `assembleSpec`). export const DECORATOR_ROOT_FILENAME = 'openapi.decorator-routes.generated.yml'; -/** The subset of an OpenAPI document this module reads/merges. Everything else passes through. */ +/** The subset of an OpenAPI document this module reads or assembles. Everything else passes through. */ export interface OpenApiDocument { paths?: Record>; components?: Record>; @@ -39,7 +37,7 @@ export interface GeneratedArtifact { } /** - * Lower-cased first char matches the existing hand-written schema-file convention (`tag.yml`) + * Lower-cases the first character of the component name, e.g. `Tag` becomes `tag.generated.yml`. */ function schemaFileName(componentName: string): string { return `${componentName[0].toLowerCase()}${componentName.slice(1)}.generated.yml`; @@ -148,8 +146,8 @@ export function registerSharedSchemas( } /** - * The decorator-routes root: `paths` `$ref`ing each operation fragment by its file path. Bundling - * this (see build.mjs) yields a resolved document whose paths are merged into the hand-written spec. + * The generated root: `paths` `$ref`ing each operation fragment by its file path. Bundling this + * (see build.mjs) yields a resolved document, which `assembleSpec` puts into the envelope. */ function buildDecoratorRootDocument( operations: Array<{ pathKey: string; method: string; outputPath: string }>, @@ -165,6 +163,7 @@ function buildDecoratorRootDocument( // `./` — the root sits at the v1 dir root and outputPath is relative to that dir. pathItem[method] = { $ref: `./${outputPath}` }; }); + assertConsistentPathParameterNames(paths); return { openapi: '3.0.0', info: { title: 'decorator-routes', version: '0.0.0' }, paths }; } @@ -207,85 +206,60 @@ export function generateDocs(v1Dir: string): void { }); } -function mergeComponents( - base: OpenApiDocument['components'], - extra: OpenApiDocument['components'], -): OpenApiDocument['components'] { - if (!extra) return base; - const merged: NonNullable = { ...base }; - for (const [section, items] of Object.entries(extra)) { - const target = { ...(merged[section] ?? {}) }; - for (const [name, definition] of Object.entries(items)) { - // A component may legitimately appear in both bundles (the same shared file hoisted - // independently) — that's a harmless duplicate. Only differing definitions are a clash. - if (name in target && !isDeepStrictEqual(target[name], definition)) { - throw new UnexpectedError( - `OpenAPI component components.${section}.${name} is defined differently by a hand-written ` + - 'path and a @PublicApiController route — rename one so they no longer collide.', - ); - } - target[name] = definition; - } - merged[section] = target; - } - return merged; -} - -function assertConsistentPathParameterNames( - ...pathCollections: Array -): void { +function assertConsistentPathParameterNames(paths: OpenApiDocument['paths']): void { // Matches path parameters such as '{credentialId}'. const PATH_PARAMETER_REGEX = /\{([^}]+)\}/g; const pathByShape = new Map(); - for (const paths of pathCollections) { - for (const pathKey of Object.keys(paths ?? {})) { - const pathShape = pathKey.replace(PATH_PARAMETER_REGEX, '{}'); - const equivalentPath = pathByShape.get(pathShape); - if (equivalentPath && equivalentPath !== pathKey) { - throw new UnexpectedError( - `Equivalent OpenAPI paths use different parameter names: '${equivalentPath}' and ` + - `'${pathKey}'. Use the same parameter name in both paths.`, - ); - } - pathByShape.set(pathShape, pathKey); + for (const pathKey of Object.keys(paths ?? {})) { + const pathShape = pathKey.replace(PATH_PARAMETER_REGEX, '{}'); + const equivalentPath = pathByShape.get(pathShape); + if (equivalentPath && equivalentPath !== pathKey) { + throw new UnexpectedError( + `Equivalent OpenAPI paths use different parameter names: '${equivalentPath}' and ` + + `'${pathKey}'. Use the same parameter name in both paths.`, + ); } + pathByShape.set(pathShape, pathKey); } } /** - * Merges the decorator-routed document into the hand-written (eov) one at *method* granularity, so a - * path served partly by eov and partly by a controller (e.g. eov `POST /tags` + decorator `GET - * /tags`) ends up whole. A path+method declared on both sides is a hard error — the same operation - * can't have two definitions. Both inputs are expected to be already-bundled (all `$ref`s resolved), - * so their `components` are merged too, deduping the shared files each side hoisted independently. + * Builds the published spec: the hand-written envelope (`openapi.yml`) with the paths and + * components of the bundled generated root. */ -export function mergeDecoratorDocument( - base: OpenApiDocument, - decorator: OpenApiDocument, +export function assembleSpec( + envelope: OpenApiDocument, + generated: OpenApiDocument, ): OpenApiDocument { - assertConsistentPathParameterNames(base.paths, decorator.paths); - - const paths: Record> = { ...(base.paths ?? {}) }; - - for (const [pathKey, methods] of Object.entries(decorator.paths ?? {})) { - const existing = paths[pathKey]; - if (!existing) { - paths[pathKey] = methods; - continue; - } - const combined = { ...existing }; - for (const [method, operation] of Object.entries(methods)) { - if (HTTP_METHODS.some((m) => m === method) && combined[method] !== undefined) { - throw new UnexpectedError( - `Duplicate OpenAPI operation ${method.toUpperCase()} ${pathKey}: it is declared by both a ` + - 'hand-written (eov) path and a @PublicApiController route — remove the hand-written one.', - ); - } - combined[method] = operation; - } - paths[pathKey] = combined; + // Ensure the envelope itself does not declare any paths. + const envelopePaths = Object.keys(envelope.paths ?? {}); + if (envelopePaths.length > 0) { + throw new UnexpectedError( + `openapi.yml still declares paths (${envelopePaths.join(', ')}). Paths come from the generated spec.`, + ); } - return { ...base, paths, components: mergeComponents(base.components, decorator.components) }; + // Ensure the generated root has at least one path. + const generatedPaths = generated.paths ?? {}; + if (Object.keys(generatedPaths).length === 0) { + throw new UnexpectedError('The bundled generated spec has no paths.'); + } + + const components: Record> = { ...generated.components }; + + for (const [section, items] of Object.entries(envelope.components ?? {})) { + const target = { ...(components[section] ?? {}) }; + for (const name of Object.keys(items)) { + if (name in target) { + throw new UnexpectedError( + `OpenAPI component components.${section}.${name} is defined by both the envelope and a ` + + 'generated route. Remove one of them.', + ); + } + } + components[section] = { ...target, ...items }; + } + + return { ...envelope, paths: generatedPaths, components }; } diff --git a/packages/cli/src/public-api/v1/openapi.decorator-routes.generated.yml b/packages/cli/src/public-api/v1/openapi.decorator-routes.generated.yml index 298ca71846c..237e36d7cad 100644 --- a/packages/cli/src/public-api/v1/openapi.decorator-routes.generated.yml +++ b/packages/cli/src/public-api/v1/openapi.decorator-routes.generated.yml @@ -189,6 +189,9 @@ paths: /n8n-packages/import-selection: post: $ref: ./handlers/n8n-packages/spec/paths/importPackageSelection.generated.yml + /n8n-packages/export: + post: + $ref: ./handlers/n8n-packages/spec/paths/exportPackage.generated.yml /node-type-policies/instance: get: $ref: ./handlers/node-type-policies/spec/paths/getNodeTypeInstancePolicy.generated.yml diff --git a/packages/cli/src/public-api/v1/openapi.yml b/packages/cli/src/public-api/v1/openapi.yml index 1ae532f6a7f..7558b55c3b9 100644 --- a/packages/cli/src/public-api/v1/openapi.yml +++ b/packages/cli/src/public-api/v1/openapi.yml @@ -30,7 +30,7 @@ tags: - name: Credential description: Operations about credentials - name: CredentialTypePolicy - description: Operations about credential type availability policies + description: Preview — breaking changes may still occur without major version bump. - name: DataTable description: Operations about data tables and their rows - name: Discover @@ -48,7 +48,7 @@ tags: - name: N8nPackage description: Beta — breaking changes may still occur without major version bump. - name: NodeTypePolicy - description: Operations about node type availability policies + description: Preview — breaking changes may still occur without major version bump. - name: Projects description: Operations about projects - name: Promotions @@ -78,16 +78,9 @@ tags: - name: Workflow description: Operations about workflows -paths: - /n8n-packages/export: - $ref: './handlers/n8n-packages/spec/paths/n8n-packages.export.yml' +# Paths and components are generated from @PublicApiController routes. See openapi-gen/generate.ts. +paths: {} components: - schemas: - $ref: './shared/spec/schemas/_index.yml' - responses: - $ref: './shared/spec/responses/_index.yml' - parameters: - $ref: './shared/spec/parameters/_index.yml' securitySchemes: ApiKeyAuth: type: apiKey diff --git a/packages/cli/src/public-api/v1/public-api-error-response.ts b/packages/cli/src/public-api/v1/public-api-error-response.ts index ed5f6bf8b0a..fd03e3cffd6 100644 --- a/packages/cli/src/public-api/v1/public-api-error-response.ts +++ b/packages/cli/src/public-api/v1/public-api-error-response.ts @@ -1,21 +1,13 @@ import type { Response } from 'express'; -import { - classifyRestError, - serializePublicApiError, - type RestErrorClassifierContext, -} from '@n8n/backend-services'; +import { classifyRestError, serializePublicApiError } from '@n8n/backend-services'; /** * Maps errors from the public API stack to HTTP responses. Used by the * Express error middleware in `index.ts`. */ -export function sendPublicApiErrorResponse( - res: Response, - error: Error, - context?: RestErrorClassifierContext, -): void { - const descriptor = classifyRestError(error, context); +export function sendPublicApiErrorResponse(res: Response, error: Error): void { + const descriptor = classifyRestError(error); const { status, body } = serializePublicApiError(descriptor); res.status(status).json(body); } diff --git a/packages/cli/src/public-api/v1/shared/handler.types.ts b/packages/cli/src/public-api/v1/shared/handler.types.ts deleted file mode 100644 index 5899aa8d8cf..00000000000 --- a/packages/cli/src/public-api/v1/shared/handler.types.ts +++ /dev/null @@ -1,23 +0,0 @@ -import type { AuthenticatedRequest } from '@n8n/db'; -import type { Response } from 'express'; - -import type { Middleware } from './middlewares/global.middleware'; - -/** - * Final handler in a public API route tuple. `TReq` must be an `AuthenticatedRequest` - * instantiation (including aliases like `WorkflowRequest.Create`). - */ -type PublicAPIEndpointHandler = ( - req: TReq, - res: Response, -) => Promise; - -/** - * A public API route: any number of middlewares (see `Middleware` in `global.middleware.ts`), - * then a typed handler. Middleware typing is intentionally loose; the handler is what we - * type-check strictly. - */ -export type PublicAPIEndpoint = readonly [ - ...Middleware[], - PublicAPIEndpointHandler, -]; diff --git a/packages/cli/src/public-api/v1/shared/middlewares/global.middleware.ts b/packages/cli/src/public-api/v1/shared/middlewares/global.middleware.ts deleted file mode 100644 index d70acf3c4e7..00000000000 --- a/packages/cli/src/public-api/v1/shared/middlewares/global.middleware.ts +++ /dev/null @@ -1,191 +0,0 @@ -/* eslint-disable @typescript-eslint/no-invalid-void-type */ -import { type BooleanLicenseFeature, UNLIMITED_LICENSE_QUOTA } from '@n8n/constants'; -import type { AuthenticatedRequest } from '@n8n/db'; -import type { DeprecationInfo } from '@n8n/decorators'; -import { Container } from '@n8n/di'; -import type { ApiKeyScope, Scope } from '@n8n/permissions'; -import type express from 'express'; -import type { NextFunction, Request, Response } from 'express'; - -import { FeatureNotLicensedError } from '@/errors/feature-not-licensed.error'; -import { NotFoundError } from '@n8n/errors'; -import { License } from '@/license'; -import { userHasScopes } from '@/permissions.ee/check-access'; -import { USER_QUOTA_FORBIDDEN_MESSAGE } from '@/public-api/constants'; -import type { PaginatedRequest } from '@/public-api/types'; - -import { decodeCursor } from '../services/pagination.service'; - -export type ProjectScopeResource = 'workflow' | 'credential' | 'dataTable'; - -const buildScopeMiddleware = ( - scopes: Scope[], - resource?: ProjectScopeResource, - { globalOnly } = { globalOnly: false }, -) => { - return async ( - req: AuthenticatedRequest<{ id?: string; dataTableId?: string }>, - res: express.Response, - next: express.NextFunction, - ): Promise => { - const params: { credentialId?: string; workflowId?: string; dataTableId?: string } = {}; - if (req.params.id) { - if (resource === 'workflow') { - params.workflowId = req.params.id; - } else if (resource === 'credential') { - params.credentialId = req.params.id; - } - } else if (req.params.dataTableId && resource === 'dataTable') { - params.dataTableId = req.params.dataTableId; - } - - try { - if (!(await userHasScopes(req.user, scopes, globalOnly, params))) { - return res.status(403).json({ message: 'Forbidden' }); - } - } catch (error) { - if (error instanceof NotFoundError) { - return res.status(404).json({ message: error.message }); - } - throw error; - } - - return next(); - }; -}; - -export const globalScope = (scopes: Scope | Scope[]) => - buildScopeMiddleware(Array.isArray(scopes) ? scopes : [scopes], undefined, { globalOnly: true }); - -export const projectScope = (scopes: Scope | Scope[], resource: ProjectScopeResource) => - buildScopeMiddleware(Array.isArray(scopes) ? scopes : [scopes], resource, { globalOnly: false }); - -export const validCursor = ( - req: Request, - res: express.Response, - next: express.NextFunction, -): express.Response | void => { - const paginatedReq = req as unknown as PaginatedRequest; - - if (paginatedReq.query.cursor) { - const { cursor } = paginatedReq.query; - try { - const paginationData = decodeCursor(cursor); - if ('offset' in paginationData) { - paginatedReq.query.offset = paginationData.offset; - paginatedReq.query.limit = paginationData.limit; - } else { - paginatedReq.query.lastId = paginationData.lastId; - paginatedReq.query.limit = paginationData.limit; - } - } catch (error) { - return res.status(400).json({ - message: 'An invalid cursor was provided', - }); - } - } - - return next(); -}; - -/** - * Signals that an endpoint is deprecated via the RFC 9745 `Deprecation` response header. Callers - * pass a semantic `Date`; this middleware owns the on-the-wire formatting so the wire syntax - * (an RFC 9651 structured-field Date, `@`) never leaks to call sites. - * - * `since` is a fixed value owned by the caller — never derive it from `Date.now()`, so the header - * stays deterministic across requests. - */ -export const deprecated = ({ since }: DeprecationInfo) => { - const deprecation = `@${Math.floor(since.getTime() / 1000)}`; - - return (_req: Request, res: express.Response, next: express.NextFunction): void => { - res.setHeader('Deprecation', deprecation); - next(); - }; -}; - -export type ScopeTaggedMiddleware = Middleware & { - __apiKeyScope: ApiKeyScope; -}; - -export type Middleware = (req: Request, res: Response, next: NextFunction) => unknown; - -function tagMiddleware(middleware: Middleware, apiKeyScope: ApiKeyScope): ScopeTaggedMiddleware { - const tagged: ScopeTaggedMiddleware = Object.assign( - (req: Request, res: Response, next: NextFunction) => middleware(req, res, next), - { __apiKeyScope: apiKeyScope }, - ); - return tagged; -} - -function makePublicApiScopeEnforcementMiddleware(endpointScope: ApiKeyScope) { - return async ( - req: AuthenticatedRequest, - res: express.Response, - next: express.NextFunction, - ): Promise => { - const { tokenGrant } = req; - - if (!tokenGrant) { - res.status(403).json({ message: 'Forbidden' }); - return; - } - - if (!tokenGrant.apiKeyScopes?.includes(endpointScope)) { - res.status(403).json({ message: 'Forbidden' }); - return; - } - - next(); - return; - }; -} - -export const publicApiScope = (apiKeyScope: ApiKeyScope) => - tagMiddleware(makePublicApiScopeEnforcementMiddleware(apiKeyScope), apiKeyScope); - -/** - * Tags an endpoint with a composite `x-required-scope` value (comma-separated). - * Actual scope enforcement is deferred to the handler, which picks the required - * scope based on the request payload. - */ -export function publicApiCompositeScope(requiredScopes: string): ScopeTaggedMiddleware { - return Object.assign( - (_req: Request, _res: Response, next: NextFunction) => { - next(); - }, - { __apiKeyScope: requiredScopes as ApiKeyScope }, - ); -} - -export const apiKeyHasScopeWithGlobalScopeFallback = ( - config: { scope: ApiKeyScope & Scope } | { apiKeyScope: ApiKeyScope; globalScope: Scope }, -) => { - const scope = 'scope' in config ? config.scope : config.apiKeyScope; - return tagMiddleware(makePublicApiScopeEnforcementMiddleware(scope), scope); -}; - -export const validLicenseWithUserQuota = ( - _: express.Request, - res: express.Response, - next: express.NextFunction, -): express.Response | void => { - const license = Container.get(License); - // oxlint-disable-next-line typescript/no-deprecated - if (license.getUsersLimit() !== UNLIMITED_LICENSE_QUOTA) { - return res.status(403).json({ - message: USER_QUOTA_FORBIDDEN_MESSAGE, - }); - } - - return next(); -}; - -export const isLicensed = (feature: BooleanLicenseFeature) => { - return async (_: AuthenticatedRequest, res: express.Response, next: express.NextFunction) => { - if (Container.get(License).isLicensed(feature)) return next(); - - return res.status(403).json({ message: new FeatureNotLicensedError(feature).message }); - }; -}; diff --git a/packages/cli/src/public-api/v1/shared/public-api-scope-lookup.ts b/packages/cli/src/public-api/v1/shared/public-api-scope-lookup.ts deleted file mode 100644 index bcdcb3a3e71..00000000000 --- a/packages/cli/src/public-api/v1/shared/public-api-scope-lookup.ts +++ /dev/null @@ -1,83 +0,0 @@ -import type { ApiKeyScopeRequirement } from '@n8n/decorators'; -import { ControllerRegistryMetadata } from '@n8n/decorators'; -import { Container } from '@n8n/di'; -import type { ApiKeyScope } from '@n8n/permissions'; - -import type { ScopeTaggedMiddleware } from './middlewares/global.middleware'; - -/** Collapse OpenAPI `{id}` / Express `:id` params so controller and YAML paths can match. */ -function normalizePath(pathStr: string): string { - return ( - pathStr - .replace(/\{[^}]+\}/g, '{}') - .replace(/:[^/]+/g, '{}') - .replace(/\/+/g, '/') - .replace(/\/$/, '') || '/' - ); -} - -function joinPaths(basePath: string, routePath: string): string { - const base = basePath.replace(/\/$/, '') || ''; - if (routePath === '/' || routePath === '') { - return base || '/'; - } - return `${base}${routePath.startsWith('/') ? routePath : `/${routePath}`}`; -} - -function serializeScope(requirement: ApiKeyScopeRequirement | undefined): string | undefined { - if (requirement === undefined) return undefined; - if (typeof requirement === 'string') return requirement; - return ('anyOf' in requirement ? requirement.anyOf : requirement.allOf).join(','); -} - -export function publicApiRouteKey(method: string, pathStr: string): string { - return `${method.toLowerCase()} ${normalizePath(pathStr)}`; -} - -/** - * Map of `method path` → serialized `@ApiKeyScope` for every `@PublicApiController` route. - * Controllers must already be side-effect-imported so their metadata is registered. - * - * Value `undefined` means the route exists and declares no API-key scope (`none`). - */ -export function loadPublicControllerScopeMap(): Map { - const map = new Map(); - const metadata = Container.get(ControllerRegistryMetadata); - - for (const controllerClass of metadata.controllerClasses) { - const controller = metadata.getControllerMetadata(controllerClass); - if (!controller.isPublicApi) continue; - - for (const route of controller.routes.values()) { - if (!route.method || route.path === undefined) continue; - map.set( - publicApiRouteKey(route.method, joinPaths(controller.basePath, route.path)), - serializeScope(route.apiKeyScope), - ); - } - } - - return map; -} - -export function extractScopeFromEovHandlerChain(handlerChain: unknown[]): ApiKeyScope | undefined { - for (const middleware of handlerChain) { - if (typeof middleware !== 'function' || !('__apiKeyScope' in middleware)) continue; - return (middleware as ScopeTaggedMiddleware).__apiKeyScope; - } - return undefined; -} - -/** - * Prefer `@PublicApiController` `@ApiKeyScope`, then fall back to eov `__apiKeyScope`. - * Uses `.has()` so a controller route with scope `none` (`undefined`) is not overridden by eov. - */ -export function resolvePublicApiImplementedScope( - controllerScopes: Map, - method: string, - pathStr: string, - eovHandlerScope?: ApiKeyScope, -): string | undefined { - const key = publicApiRouteKey(method, pathStr); - return controllerScopes.has(key) ? controllerScopes.get(key) : eovHandlerScope; -} diff --git a/packages/cli/src/public-api/v1/shared/spec/parameters/_index.yml b/packages/cli/src/public-api/v1/shared/spec/parameters/_index.yml deleted file mode 100644 index 3ef11d25474..00000000000 --- a/packages/cli/src/public-api/v1/shared/spec/parameters/_index.yml +++ /dev/null @@ -1,10 +0,0 @@ -Cursor: - $ref: './cursor.yml' -Limit: - $ref: './limit.yml' -Offset: - $ref: './offset.yml' -WorkflowId: - $ref: '../../../handlers/workflows/spec/schemas/parameters/workflowId.yml' -dataTableId: - $ref: '../../../handlers/data-tables/spec/schemas/parameters/dataTableId.yml' diff --git a/packages/cli/src/public-api/v1/shared/spec/responses/_index.yml b/packages/cli/src/public-api/v1/shared/spec/responses/_index.yml deleted file mode 100644 index d465ce964f3..00000000000 --- a/packages/cli/src/public-api/v1/shared/spec/responses/_index.yml +++ /dev/null @@ -1,22 +0,0 @@ -NotFound: - $ref: './notFound.yml' -Unauthorized: - $ref: './unauthorized.yml' -BadRequest: - $ref: './badRequest.yml' -Conflict: - $ref: './conflict.yml' -Forbidden: - $ref: './forbidden.yml' -PaymentRequired: - $ref: './paymentRequired.yml' -UnsupportedMediaType: - $ref: './unsupportedMediaType.yml' -ContentTooLarge: - $ref: './contentTooLarge.yml' -UnprocessableEntity: - $ref: './unprocessableEntity.yml' -InternalServerError: - $ref: './internalServerError.yml' -ServiceUnavailable: - $ref: './serviceUnavailable.yml' diff --git a/packages/cli/src/public-api/v1/shared/spec/schemas/_index.yml b/packages/cli/src/public-api/v1/shared/spec/schemas/_index.yml deleted file mode 100644 index c580ffb0bfc..00000000000 --- a/packages/cli/src/public-api/v1/shared/spec/schemas/_index.yml +++ /dev/null @@ -1,14 +0,0 @@ -Error: - $ref: './error.yml' -Node: - $ref: './../../../handlers/workflows/spec/schemas/node.yml' -WorkflowNodeGroup: - $ref: './../../../handlers/workflows/spec/schemas/workflowNodeGroup.yml' -Tag: - $ref: './../../../handlers/tags/spec/schemas/tag.yml' -Workflow: - $ref: './../../../handlers/workflows/spec/schemas/workflow.yml' -WorkflowSettings: - $ref: './../../../handlers/workflows/spec/schemas/workflowSettings.yml' -WorkflowList: - $ref: './../../../handlers/workflows/spec/schemas/workflowList.yml' diff --git a/packages/cli/src/public-api/v1/shared/spec/schemas/applyPackageResultDto.generated.yml b/packages/cli/src/public-api/v1/shared/spec/schemas/applyPackageResultDto.generated.yml index 2131494f563..0d6aa633dd3 100644 --- a/packages/cli/src/public-api/v1/shared/spec/schemas/applyPackageResultDto.generated.yml +++ b/packages/cli/src/public-api/v1/shared/spec/schemas/applyPackageResultDto.generated.yml @@ -1090,6 +1090,31 @@ oneOf: - project - filePath - workflows + - type: object + properties: + kind: + type: string + enum: + - project + code: + type: string + enum: + - project-deletion + project: + type: object + properties: + id: + type: string + minLength: 1 + name: + type: string + required: + - id + - name + required: + - kind + - code + - project - type: object properties: kind: diff --git a/packages/cli/src/public-api/v1/shared/spec/schemas/error.yml b/packages/cli/src/public-api/v1/shared/spec/schemas/error.yml deleted file mode 100644 index 4d5507dfbd9..00000000000 --- a/packages/cli/src/public-api/v1/shared/spec/schemas/error.yml +++ /dev/null @@ -1,10 +0,0 @@ -required: - - message -type: object -properties: - code: - type: string - message: - type: string - description: - type: string diff --git a/packages/cli/src/public-api/v1/shared/spec/schemas/importBlockingIssue.generated.yml b/packages/cli/src/public-api/v1/shared/spec/schemas/importBlockingIssue.generated.yml index 7fd9ecbc6f2..8ba969d2e7a 100644 --- a/packages/cli/src/public-api/v1/shared/spec/schemas/importBlockingIssue.generated.yml +++ b/packages/cli/src/public-api/v1/shared/spec/schemas/importBlockingIssue.generated.yml @@ -165,6 +165,71 @@ oneOf: - sourceId - usedBy description: A credential reference that could not be resolved in the target project. + - type: object + properties: + type: + type: string + enum: + - credential-conflict + kind: + type: string + enum: + - differs + - divergent + description: '`differs`: under `credentialConflictPolicy=fail`, the package would change the name or values of the destination credential. `divergent`: under `overwrite`, two or more package credentials with different names or values resolve to one destination credential. The import does not select one of them.' + targetId: + type: string + description: Id of the destination credential. + sourceIds: + type: array + items: + type: string + description: Ids of the package credentials that resolve to the destination credential. For `differs`, the package credentials that would change it. + name: + type: string + description: Name of the destination credential. + usedBy: + type: array + items: + $ref: packageRequirementConsumer.generated.yml + description: Package consumers that use the listed package credentials. + required: + - type + - kind + - targetId + - sourceIds + - name + - usedBy + description: 'A matched credential that the credential conflict policy does not let the import change. Only a credential that the import can update is checked: a credential owned by a project of the import. Values are never reported.' + - type: object + properties: + type: + type: string + enum: + - credential-update-forbidden + targetId: + type: string + description: Id of the destination credential. + sourceIds: + type: array + items: + type: string + description: Ids of the package credentials that resolve to it. + name: + type: string + description: Name of the destination credential. + usedBy: + type: array + items: + $ref: packageRequirementConsumer.generated.yml + description: Package consumers that use the listed package credentials. + required: + - type + - targetId + - sourceIds + - name + - usedBy + description: A matched credential that the import can update, but the caller has no `credential:update` permission on it. Only under `credentialConflictPolicy` `overwrite` or `fail`. The import does not read its values, so this blocks also when the package would not change it. Use `keep-existing` to bind it without a change. - type: object properties: type: @@ -652,6 +717,10 @@ oneOf: type: string matchedRuleId: type: string + projectId: + type: string + optInAvailable: + type: boolean required: - kind - checkId @@ -699,6 +768,10 @@ oneOf: type: string matchedRuleId: type: string + projectId: + type: string + optInAvailable: + type: boolean required: - kind - checkId diff --git a/packages/cli/src/public-api/v1/shared/spec/schemas/importResultDto.generated.yml b/packages/cli/src/public-api/v1/shared/spec/schemas/importResultDto.generated.yml index 1d071517d22..3156f3b9ae3 100644 --- a/packages/cli/src/public-api/v1/shared/spec/schemas/importResultDto.generated.yml +++ b/packages/cli/src/public-api/v1/shared/spec/schemas/importResultDto.generated.yml @@ -50,7 +50,7 @@ properties: - unchanged - blocked - failed - description: '`blocked` means the imported version could not be published and no version is active (for example because the workflow uses a stubbed credential, or uses a node type this instance does not have). When a prior published version remains active, `state` is `unchanged` with `skippedPublishReason` instead. `failed` means publish or unpublish was attempted but did not succeed.' + description: '`blocked` means the imported version could not be published and no version is active (for example because the workflow uses an empty or partially seeded credential, or uses a node type this instance does not have). When a prior published version remains active, `state` is `unchanged` with `skippedPublishReason` instead. `failed` means publish or unpublish was attempted but did not succeed.' error: type: string description: Present when `state` is `failed`. Explains why publish or unpublish could not be applied. @@ -65,7 +65,7 @@ properties: enum: - stub-credential - missing-node-type - description: 'Present when `state` is `unchanged` but the policy wanted to publish the imported version: a prior published version is still active (for example after an update with stubbed credentials).' + description: 'Present when `state` is `unchanged` but the policy wanted to publish the imported version: a prior published version is still active (for example after an update with incomplete credentials).' required: - state description: Outcome of applying the selected publishing policy to this workflow. @@ -223,10 +223,16 @@ properties: items: type: string description: Source credential ids for which empty placeholder credentials were created in the target project. + seeded: + type: array + items: + type: string + description: Source credential ids for which credentials were created with bundled expression values in the target project. Partial or unverified bundled data still blocks workflow publishing. required: - matched - stubbed - description: Source credential ids grouped by whether they matched an existing credential or were created as stubs. Full source→target id mapping is in `bindings.credentials`. + - seeded + description: Source credential ids grouped by whether they matched an existing credential or were created as empty stubs or seeded credentials. Full source→target id mapping is in `bindings.credentials`. dataTables: type: object properties: diff --git a/packages/cli/src/public-api/v1/shared/spec/schemas/policyViolation.yml b/packages/cli/src/public-api/v1/shared/spec/schemas/policyViolation.yml deleted file mode 100644 index 38a4133312c..00000000000 --- a/packages/cli/src/public-api/v1/shared/spec/schemas/policyViolation.yml +++ /dev/null @@ -1,31 +0,0 @@ -type: object -description: > - One reason a policy check objected. `kind`, `subjectType` and `scope` are open - strings, not enums, so later policy features can add values — a reader must - cope with values it does not recognise. -required: - - kind - - checkId - - message -properties: - kind: - type: string - description: 'e.g. `node-type-unavailable`. Do not assume you know every value.' - checkId: - type: string - description: Id of the check that objected. - message: - type: string - description: Readable on its own. Do not parse details out of it — use the fields below. - subject: - type: string - description: 'What was objected to: a node type name, a credential type name, …' - subjectType: - type: string - description: What kind of name `subject` is — node and credential type names can look alike. - scope: - type: string - description: Which level objected. Usually `instance` or `project`, but treat it as open. - matchedRuleId: - type: string - description: The rule that decided, if a rule did rather than a fallback default. diff --git a/packages/cli/src/requests.ts b/packages/cli/src/requests.ts index b36f775287e..39c9dabc6f5 100644 --- a/packages/cli/src/requests.ts +++ b/packages/cli/src/requests.ts @@ -114,7 +114,7 @@ export declare namespace CredentialRequest { {}, {}, {}, - { workflowId: string } | { projectId: string } + ({ workflowId: string } | { projectId: string }) & { forAgent?: 'true' | 'false' } >; } @@ -189,7 +189,20 @@ export declare namespace OAuthRequest { namespace OAuth2Credential { type Auth = AuthenticatedRequest<{}, {}, {}, { id: string }>; - type Callback = AuthenticatedRequest<{}, {}, {}, { code: string; state: string }>; + type Callback = AuthenticatedRequest< + {}, + {}, + {}, + // `admin_consent` and its error pair arrive when an administrator approves + // the app for an organisation, which reuses the same reply URL. + { + code: string; + state: string; + admin_consent?: string; + error?: string; + error_description?: string; + } + >; } } diff --git a/packages/cli/src/response-helper.ts b/packages/cli/src/response-helper.ts index 92726737720..ffca1dc10ec 100644 --- a/packages/cli/src/response-helper.ts +++ b/packages/cli/src/response-helper.ts @@ -14,7 +14,7 @@ import { FORM_TRIGGER_PATH_IDENTIFIER, NodeApiError } from 'n8n-workflow'; import { Readable } from 'node:stream'; import picocolors from 'picocolors'; -import { applyFormSandboxCSP } from './webhooks/webhook-response-headers'; +import { applySandboxCSP } from './webhooks/webhook-response-headers'; export function sendSuccessResponse( res: Response, @@ -65,7 +65,8 @@ export function sendErrorResponse(res: Response, error: Error) { if (isFormTrigger || isLegacyFormTrigger) { const isTestWebhook = basePath.includes('test'); res.status(404); - applyFormSandboxCSP(res); + // The setting of the route decides: a webhook path can look like a form path. + applySandboxCSP(res, 'form'); return res.render('form-trigger-404', { isTestWebhook }); } } @@ -73,7 +74,7 @@ export function sendErrorResponse(res: Response, error: Error) { if (error.errorCode === 409 && originalUrl && originalUrl.includes('form-waiting')) { //codes other than 200 breaks redirection to form-waiting page from form trigger //render form page instead of json - applyFormSandboxCSP(res); + applySandboxCSP(res, 'form'); return res.render('form-trigger-409', { message: error.message, }); @@ -95,6 +96,8 @@ export function sendErrorResponse(res: Response, error: Error) { response.stacktrace = error.stack; } + // res.json() does not override a Content-Type set earlier; force JSON here. + res.setHeader('Content-Type', 'application/json'); res.status(status).json(response); } diff --git a/packages/cli/src/scaling/__tests__/job-processor.service.test.ts b/packages/cli/src/scaling/__tests__/job-processor.service.test.ts index b1f99116265..b8db75d702a 100644 --- a/packages/cli/src/scaling/__tests__/job-processor.service.test.ts +++ b/packages/cli/src/scaling/__tests__/job-processor.service.test.ts @@ -58,6 +58,7 @@ import { WorkflowStaticDataService } from '@/workflows/workflow-static-data.serv import { JobProcessor } from '../job-processor'; import type { Job } from '../scaling.types'; import { WebhookResponseRelay } from '../webhook-response-relay'; +import { CHAT_TRIGGER_NODE_TYPE } from 'n8n-workflow'; mockInstance(WorkflowPublishHistoryRepository); mockInstance(VariablesService, { @@ -75,6 +76,7 @@ mockInstance(OwnershipService, { }); const processRunExecutionDataMock = vi.fn(); +const workflowExecuteSuspendMock = vi.fn(); vi.mock('n8n-core', async () => { const original = await vi.importActual('n8n-core'); @@ -82,7 +84,10 @@ vi.mock('n8n-core', async () => { return { ...original, WorkflowExecute: vi.fn(function () { - return { processRunExecutionData: processRunExecutionDataMock }; + return { + processRunExecutionData: processRunExecutionDataMock, + suspend: workflowExecuteSuspendMock, + }; }), }; }); @@ -373,6 +378,325 @@ describe('JobProcessor', () => { }); }); + describe('suspension', () => { + beforeEach(() => { + workflowExecuteSuspendMock.mockClear(); + logger.info.mockClear(); + }); + + const createJobProcessor = (executionPersistence: ExecutionPersistence) => + new JobProcessor( + logger, + mock(), + executionPersistence, + mock(), + mock(), + mock(), + createManualExecutionServiceMock(), + executionsConfig, + mock(), + mock(), + ); + + it('should wire a suspend handle to the engine for a suspendable job', async () => { + const executionPersistence = mock(); + executionPersistence.findSingleExecution.mockResolvedValue( + mock({ + mode: 'webhook', + workflowData: { nodes: [], staticData: {} }, + data: mock(), + }), + ); + vi.spyOn(WorkflowExecuteAdditionalData, 'getBase').mockResolvedValue( + mock(), + ); + const jobProcessor = createJobProcessor(executionPersistence); + + let resolveRun!: (run: IRun) => void; + processRunExecutionDataMock.mockReturnValue(new Promise((r) => (resolveRun = r))); + + const job = mock({ + id: 'job-1', + data: { + executionId: 'exec-1', + loadStaticData: false, + streamingEnabled: false, + isMcpExecution: false, + callerAwaitsOutcome: 'none', + }, + }); + + const processPromise = jobProcessor.processJob(job); + await vi.waitFor(() => expect(jobProcessor.getRunningJobsSummary()).not.toEqual([])); + + jobProcessor.suspendRunningJobs(); + expect(workflowExecuteSuspendMock).toHaveBeenCalledTimes(1); + expect(logger.info).toHaveBeenCalledWith( + expect.stringContaining('Requested suspension of 1 execution(s)'), + ); + expect(logger.info).toHaveBeenCalledWith(expect.stringContaining('exec-1')); + + resolveRun(successRun()); + await processPromise; + }); + + it('should suspend a suspendable job that registers after suspension was requested', async () => { + const executionPersistence = mock(); + let resolveExecution!: (execution: IExecutionResponse) => void; + executionPersistence.findSingleExecution.mockReturnValue( + new Promise((r) => (resolveExecution = r)), + ); + vi.spyOn(WorkflowExecuteAdditionalData, 'getBase').mockResolvedValue( + mock(), + ); + const jobProcessor = createJobProcessor(executionPersistence); + + let resolveRun!: (run: IRun) => void; + processRunExecutionDataMock.mockReturnValue(new Promise((r) => (resolveRun = r))); + + const job = mock({ + id: 'job-1', + data: { + executionId: 'exec-1', + loadStaticData: false, + streamingEnabled: false, + isMcpExecution: false, + callerAwaitsOutcome: 'none', + }, + }); + + const processPromise = jobProcessor.processJob(job); + + // Shutdown arrives while the job is still in its preflight reads. + jobProcessor.suspendRunningJobs(); + expect(workflowExecuteSuspendMock).not.toHaveBeenCalled(); + + resolveExecution( + mock({ + mode: 'webhook', + workflowData: { nodes: [], staticData: {} }, + data: mock(), + }), + ); + await vi.waitFor(() => expect(jobProcessor.getRunningJobsSummary()).not.toEqual([])); + expect(workflowExecuteSuspendMock).toHaveBeenCalledTimes(1); + + resolveRun(successRun()); + await processPromise; + }); + + const startWebhookJob = async ( + jobData: Partial, + mode: IExecutionResponse['mode'] = 'webhook', + ) => { + const executionPersistence = mock(); + executionPersistence.findSingleExecution.mockResolvedValue( + mock({ + mode, + workflowData: { nodes: [], staticData: {} }, + data: mock(), + }), + ); + const additionalData = mock(); + vi.spyOn(WorkflowExecuteAdditionalData, 'getBase').mockResolvedValue(additionalData); + const jobProcessor = createJobProcessor(executionPersistence); + + let resolveRun!: (run: IRun) => void; + processRunExecutionDataMock.mockReturnValue(new Promise((r) => (resolveRun = r))); + + const job = mock({ + id: 'job-1', + data: { + executionId: 'exec-1', + loadStaticData: false, + streamingEnabled: false, + isMcpExecution: false, + ...jobData, + }, + }); + const processPromise = jobProcessor.processJob(job); + await vi.waitFor(() => expect(jobProcessor.getRunningJobsSummary()).not.toEqual([])); + + const finish = async () => { + resolveRun(successRun()); + await processPromise; + }; + return { jobProcessor, hooks: additionalData.hooks!, finish }; + }; + + it('should not suspend a webhook job while its response is still pending', async () => { + const { jobProcessor, finish } = await startWebhookJob({ callerAwaitsOutcome: 'response' }); + + jobProcessor.suspendRunningJobs(); + expect(workflowExecuteSuspendMock).not.toHaveBeenCalled(); + expect(logger.info).not.toHaveBeenCalledWith(expect.stringContaining('Requested suspension')); + + await finish(); + }); + + it.each(['webhook', 'trigger'] as const)( + 'should treat a %s job without the flag (older main) as awaited to completion', + async (mode) => { + const { jobProcessor, hooks, finish } = await startWebhookJob( + { callerAwaitsOutcome: undefined }, + mode, + ); + + jobProcessor.suspendRunningJobs(); + await hooks.runHook('sendResponse', [{ body: {}, headers: {}, statusCode: 200 }]); + expect(workflowExecuteSuspendMock).not.toHaveBeenCalled(); + + await finish(); + }, + ); + + it('should suspend a webhook job once it has relayed its response', async () => { + const { jobProcessor, hooks, finish } = await startWebhookJob({ + callerAwaitsOutcome: 'response', + }); + + jobProcessor.suspendRunningJobs(); + expect(workflowExecuteSuspendMock).not.toHaveBeenCalled(); + + await hooks.runHook('sendResponse', [{ body: {}, headers: {}, statusCode: 200 }]); + expect(workflowExecuteSuspendMock).toHaveBeenCalledTimes(1); + + await finish(); + }); + + it('should not suspend a trigger job whose outcome is awaited on main', async () => { + const { jobProcessor, finish } = await startWebhookJob( + { callerAwaitsOutcome: 'completion' }, + 'trigger', + ); + + jobProcessor.suspendRunningJobs(); + expect(workflowExecuteSuspendMock).not.toHaveBeenCalled(); + + await finish(); + }); + + it('should not treat a relayed response as satisfying a trigger done promise', async () => { + const { jobProcessor, hooks, finish } = await startWebhookJob( + { callerAwaitsOutcome: 'completion' }, + 'trigger', + ); + + jobProcessor.suspendRunningJobs(); + await hooks.runHook('sendResponse', [{ body: {}, headers: {}, statusCode: 200 }]); + expect(workflowExecuteSuspendMock).not.toHaveBeenCalled(); + + await finish(); + }); + + it('should suspend a fire-and-forget trigger job', async () => { + const { jobProcessor, finish } = await startWebhookJob( + { callerAwaitsOutcome: 'none' }, + 'trigger', + ); + + jobProcessor.suspendRunningJobs(); + expect(workflowExecuteSuspendMock).toHaveBeenCalledTimes(1); + + await finish(); + }); + + it('should not attach a suspend handle to a non-suspendable job', async () => { + const executionPersistence = mock(); + executionPersistence.findSingleExecution.mockResolvedValue( + mock({ + mode: 'webhook', + workflowData: { nodes: [], staticData: {} }, + data: mock(), + }), + ); + vi.spyOn(WorkflowExecuteAdditionalData, 'getBase').mockResolvedValue( + mock(), + ); + const jobProcessor = createJobProcessor(executionPersistence); + + let resolveRun!: (run: IRun) => void; + processRunExecutionDataMock.mockReturnValue(new Promise((r) => (resolveRun = r))); + + const job = mock({ + id: 'job-1', + data: { + executionId: 'exec-1', + loadStaticData: false, + streamingEnabled: true, + isMcpExecution: false, + }, + }); + + const processPromise = jobProcessor.processJob(job); + await vi.waitFor(() => expect(jobProcessor.getRunningJobsSummary()).not.toEqual([])); + + jobProcessor.suspendRunningJobs(); + expect(workflowExecuteSuspendMock).not.toHaveBeenCalled(); + expect(logger.info).not.toHaveBeenCalledWith(expect.stringContaining('Requested suspension')); + + resolveRun(successRun()); + await processPromise; + }); + + describe('isJobSuspendable', () => { + const jobProcessor = createJobProcessor(mock()); + const cleanJob = mock({ + data: { streamingEnabled: false, isMcpExecution: false }, + }); + const cleanExecution = mock({ + mode: 'webhook', + workflowData: { nodes: [] }, + data: mock(), + }); + // @ts-expect-error private method + const isJobSuspendable = jobProcessor.isJobSuspendable.bind(jobProcessor) as ( + job: Job, + execution: IExecutionResponse, + ) => boolean; + + it.each(['webhook', 'trigger', 'retry'] as const)( + 'should allow a clean %s execution', + (mode) => { + expect(isJobSuspendable(cleanJob, { ...cleanExecution, mode })).toBe(true); + }, + ); + + it.each(['manual', 'evaluation', 'integrated', 'error'] as const)( + 'should refuse a %s execution', + (mode) => { + expect(isJobSuspendable(cleanJob, { ...cleanExecution, mode })).toBe(false); + }, + ); + + it('should refuse a streaming execution', () => { + const job = mock({ data: { streamingEnabled: true, isMcpExecution: false } }); + expect(isJobSuspendable(job, cleanExecution)).toBe(false); + }); + + it('should refuse an MCP execution', () => { + const job = mock({ data: { streamingEnabled: false, isMcpExecution: true } }); + expect(isJobSuspendable(job, cleanExecution)).toBe(false); + }); + + it('should refuse a workflow with a chat trigger', () => { + const execution = { + ...cleanExecution, + workflowData: { nodes: [{ type: CHAT_TRIGGER_NODE_TYPE, disabled: false }] }, + } as unknown as IExecutionResponse; + expect(isJobSuspendable(cleanJob, execution)).toBe(false); + }); + + it('should refuse an execution without run state', () => { + const execution = { + ...cleanExecution, + data: mock({ executionData: undefined }), + }; + expect(isJobSuspendable(cleanJob, execution)).toBe(false); + }); + }); + }); + it('should send job-finished with success=false when execution has errors', async () => { const executionRepository = mock(); const executionPersistence = mock(); diff --git a/packages/cli/src/scaling/__tests__/scaling.service.test.ts b/packages/cli/src/scaling/__tests__/scaling.service.test.ts index c353d9c2927..7133079ed90 100644 --- a/packages/cli/src/scaling/__tests__/scaling.service.test.ts +++ b/packages/cli/src/scaling/__tests__/scaling.service.test.ts @@ -449,6 +449,34 @@ describe('ScalingService', () => { expect(stopQueueRecoverySpy).not.toHaveBeenCalled(); }); + afterEach(() => { + globalConfig.queue.suspendExecutionsOnShutdown = false; + }); + + it('should suspend running jobs when suspension is enabled', async () => { + // @ts-expect-error readonly property + instanceSettings.instanceType = 'worker'; + await scalingService.setupQueue(); + globalConfig.queue.suspendExecutionsOnShutdown = true; + jobProcessor.getTrackedJobIds.mockReturnValue([]); + + await scalingService.stop(); + + expect(jobProcessor.suspendRunningJobs).toHaveBeenCalledTimes(1); + }); + + it('should not suspend running jobs when suspension is disabled', async () => { + // @ts-expect-error readonly property + instanceSettings.instanceType = 'worker'; + await scalingService.setupQueue(); + globalConfig.queue.suspendExecutionsOnShutdown = false; + jobProcessor.getTrackedJobIds.mockReturnValue([]); + + await scalingService.stop(); + + expect(jobProcessor.suspendRunningJobs).not.toHaveBeenCalled(); + }); + it('should log the execution IDs it is waiting for while draining', async () => { vi.useFakeTimers(); // @ts-expect-error readonly property diff --git a/packages/cli/src/scaling/job-processor.ts b/packages/cli/src/scaling/job-processor.ts index 6f393cbfb3e..d3308331196 100644 --- a/packages/cli/src/scaling/job-processor.ts +++ b/packages/cli/src/scaling/job-processor.ts @@ -4,6 +4,7 @@ import { Logger } from '@n8n/backend-common'; import { EventService } from '@n8n/backend-services'; import { ExecutionsConfig } from '@n8n/config'; import { MAX_INTEGER_32BITS_SIGNED } from '@n8n/constants'; +import type { IExecutionResponse } from '@n8n/db'; import { ExecutionRepository, WorkflowRepository } from '@n8n/db'; import { Service } from '@n8n/di'; import { InstanceSettings, WorkflowExecute, SupplyDataContext, StructuredToolkit } from 'n8n-core'; @@ -14,12 +15,14 @@ import { TimeoutExecutionCancelledError, Workflow, UnexpectedError, + CHAT_TRIGGER_NODE_TYPE, runDataAttemptedDynamicCredentials, runDataUsedDynamicCredentials, } from 'n8n-workflow'; import type { CancellationReason, ExecutionStatus, + WorkflowExecuteMode, IDataObject, IExecuteData, IExecuteFunctions, @@ -86,6 +89,9 @@ function scheduleAt(timestamp: number, fn: () => void): () => void { return () => clearTimeout(timer); } +/** Production runs that may be parked at worker shutdown and resumed elsewhere. */ +const SUSPENDABLE_EXECUTION_MODES = new Set(['webhook', 'trigger', 'retry']); + /** * Responsible for processing jobs from the queue, i.e. running enqueued executions. */ @@ -99,6 +105,9 @@ export class JobProcessor { /** Cause of the cancellation of each job cancelled so far, kept until its run settles. */ private readonly cancellationReasons: Record = {}; + /** Set once at shutdown; jobs that register afterwards suspend right away. */ + private suspensionRequested = false; + constructor( private readonly logger: Logger, private readonly executionRepository: ExecutionRepository, @@ -239,6 +248,10 @@ export class JobProcessor { }); } + // An older main sends no value. Assume the strictest, so nothing is parked + // until every main is upgraded. + let callerAwaitsOutcome = job.data.callerAwaitsOutcome ?? 'completion'; + lifecycleHooks.addHandler('sendResponse', async (response): Promise => { // An MCP Service call takes its result from the execution's stored data, so a // response relayed to main has no reader. Relaying one would also reach main @@ -277,6 +290,11 @@ export class JobProcessor { }; await job.progress(msg); + + // Only a webhook caller is satisfied by a relayed response; a done promise waits for the end. + if (callerAwaitsOutcome !== 'response') return; + callerAwaitsOutcome = 'none'; + if (this.suspensionRequested) this.runningJobs[job.id]?.suspend?.(); }); lifecycleHooks.addHandler('sendChunk', async (chunk: StructuredChunk): Promise => { @@ -307,7 +325,7 @@ export class JobProcessor { ); }; - let workflowExecute: WorkflowExecute; + let workflowExecute: WorkflowExecute | undefined; let workflowRun: PCancelable; const { startData, resultData, manualData } = execution.data; @@ -355,6 +373,18 @@ export class JobProcessor { status: execution.status, }; + if (workflowExecute && this.isJobSuspendable(job, execution)) { + const suspendable = workflowExecute; + runningJob.suspend = () => { + if (callerAwaitsOutcome !== 'none') return false; + suspendable.suspend(); + return true; + }; + // A job that was still in its preflight reads when shutdown asked the + // running jobs to suspend would otherwise run to completion unasked. + if (this.suspensionRequested) runningJob.suspend(); + } + this.runningJobs[job.id] = runningJob; // The engine only checks `executionTimeoutTimestamp` between node executions, so it cannot @@ -580,6 +610,45 @@ export class JobProcessor { .map(([jobId, executionId]) => ({ jobId, executionId })); } + /** + * Whether a job may be suspended at worker shutdown. Only production + * executions qualify: manual and evaluation runs are tied to a session, + * streaming responses cannot migrate mid-stream, and MCP executions are + * pinned to their session, and so is a chat conversation, whose client polls + * the waiting state and would mistake a parked run for a reply. A pending + * webhook response is checked at suspend time, since the run may still send it. + */ + private isJobSuspendable(job: Job, execution: IExecutionResponse): boolean { + const hasChatTrigger = execution.workflowData.nodes.some( + (node) => node.type === CHAT_TRIGGER_NODE_TYPE && !node.disabled, + ); + + return ( + SUSPENDABLE_EXECUTION_MODES.has(execution.mode) && + !job.data.streamingEnabled && + !job.data.isMcpExecution && + !hasChatTrigger && + execution.data.executionData !== undefined + ); + } + + /** Ask every suspendable running job to stop at its next node boundary. */ + suspendRunningJobs() { + this.suspensionRequested = true; + const executionIds: string[] = []; + + for (const runningJob of Object.values(this.runningJobs)) { + if (!runningJob.suspend?.()) continue; + executionIds.push(runningJob.executionId); + } + + if (executionIds.length > 0) { + this.logger.info( + `Requested suspension of ${executionIds.length} execution(s) at the next node boundary (execution IDs: ${executionIds.join(', ')})`, + ); + } + } + getRunningJobsSummary(): RunningJobSummary[] { return Object.values(this.runningJobs).map(({ run, ...summary }) => summary); } diff --git a/packages/cli/src/scaling/scaling.service.ts b/packages/cli/src/scaling/scaling.service.ts index 9943aeafa91..b09ef31169c 100644 --- a/packages/cli/src/scaling/scaling.service.ts +++ b/packages/cli/src/scaling/scaling.service.ts @@ -284,6 +284,10 @@ export class ScalingService { const isWithinDrainBudget = () => Date.now() - start < drainTimeoutMs; const getRemainingWindowMs = () => Math.max(0, shutdownWindowMs - (Date.now() - start)); + if (this.globalConfig.queue.suspendExecutionsOnShutdown) { + this.jobProcessor.suspendRunningJobs(); + } + let count = 0; while (hasQueuedJobsToDrain() || (hasInProcessExecutionsToDrain() && isWithinDrainBudget())) { diff --git a/packages/cli/src/scaling/scaling.types.ts b/packages/cli/src/scaling/scaling.types.ts index cabf438f4d2..c1f95bc15b6 100644 --- a/packages/cli/src/scaling/scaling.types.ts +++ b/packages/cli/src/scaling/scaling.types.ts @@ -149,6 +149,11 @@ export type AbortJobMessage = { export type RunningJob = RunningJobSummary & { run: PCancelable; + /** + * Present only when the job may be suspended at worker shutdown. Returns + * false while the run still owes its webhook caller a response. + */ + suspend?: () => boolean; }; export type QueueRecoveryContext = { diff --git a/packages/cli/src/scheduling/durable-scheduler.ts b/packages/cli/src/scheduling/durable-scheduler.ts index 607798582ee..e37bf650852 100644 --- a/packages/cli/src/scheduling/durable-scheduler.ts +++ b/packages/cli/src/scheduling/durable-scheduler.ts @@ -51,6 +51,7 @@ export class DurableScheduler implements Scheduler { eventService: EventService, ) { const config = globalConfig.scheduler; + // oxlint-disable-next-line typescript/no-deprecated -- the in-memory scheduler will be removed in a future version const enabled = config.enabled && instanceSettings.instanceType === 'main'; const tracer = createSchedulerTracer(tracing); this.scheduler = enabled diff --git a/packages/cli/src/scheduling/poll-trigger-node/durable-poller-chain.ts b/packages/cli/src/scheduling/poll-trigger-node/durable-poller-chain.ts index 837220286f1..05b5bfac569 100644 --- a/packages/cli/src/scheduling/poll-trigger-node/durable-poller-chain.ts +++ b/packages/cli/src/scheduling/poll-trigger-node/durable-poller-chain.ts @@ -14,6 +14,7 @@ export function isDurablePollerChainEnabled( workflowsConfig: WorkflowsConfig, ): boolean { return ( + // oxlint-disable-next-line typescript/no-deprecated -- the in-memory scheduler will be removed in a future version schedulerConfig.enabled && schedulerConfig.enabledForPollTriggers && workflowsConfig.useWorkflowPublicationService diff --git a/packages/cli/src/scheduling/poll-trigger-node/poll-job-provider.ts b/packages/cli/src/scheduling/poll-trigger-node/poll-job-provider.ts index 2a3a02903f2..a5802e5626b 100644 --- a/packages/cli/src/scheduling/poll-trigger-node/poll-job-provider.ts +++ b/packages/cli/src/scheduling/poll-trigger-node/poll-job-provider.ts @@ -28,6 +28,7 @@ export class PollJobProvider { const active = isDurablePollerChainEnabled(this.globalConfig.scheduler, this.workflowsConfig); if ( + // oxlint-disable-next-line typescript/no-deprecated -- the in-memory scheduler will be removed in a future version this.globalConfig.scheduler.enabled && !this.workflowsConfig.useWorkflowPublicationService ) { diff --git a/packages/cli/src/scheduling/schedule-trigger-node/__tests__/schedule-trigger-job-registrar.test.ts b/packages/cli/src/scheduling/schedule-trigger-node/__tests__/schedule-trigger-job-registrar.test.ts index a9ab7f15c1d..c714412a0d2 100644 --- a/packages/cli/src/scheduling/schedule-trigger-node/__tests__/schedule-trigger-job-registrar.test.ts +++ b/packages/cli/src/scheduling/schedule-trigger-node/__tests__/schedule-trigger-job-registrar.test.ts @@ -85,15 +85,11 @@ describe('ScheduleTriggerJobRegistrar', () => { const lastProvisionedGrace = () => lastRequest().misfireGraceSeconds; - const makeRegistrar = ({ - schedulerEnabled = true, - publicationEnabled = true, - allowSkipDurableScheduler = false, - } = {}) => + const makeRegistrar = ({ schedulerEnabled = true, publicationEnabled = true } = {}) => new ScheduleTriggerJobRegistrar( mockLogger(), mock({ - scheduler: { enabled: schedulerEnabled, allowSkipDurableScheduler }, + scheduler: { enabled: schedulerEnabled }, generic: { timezone: 'UTC' }, }), mock({ useWorkflowPublicationService: publicationEnabled }), @@ -139,39 +135,13 @@ describe('ScheduleTriggerJobRegistrar', () => { expect(makeRegistrar().interceptsNode(other)).toBe(false); }); - // Only the Schedule Trigger declares `skipDurableScheduler`; the Workflow - // constructor strips it from any other node, so the toggle cases use that type. - it('does not intercept a node opted out via skip when the escape hatch is enabled', () => { - const skippingNode = mock({ + it('ignores a stale saved skipDurableScheduler parameter', () => { + const staleNode = mock({ id: NODE_ID, type: SCHEDULE_TRIGGER_NODE_TYPE, parameters: { skipDurableScheduler: true }, }); - expect(makeRegistrar({ allowSkipDurableScheduler: true }).interceptsNode(skippingNode)).toBe( - false, - ); - }); - - it('still intercepts a skipping node when the escape hatch is disabled', () => { - const skippingNode = mock({ - id: NODE_ID, - type: SCHEDULE_TRIGGER_NODE_TYPE, - parameters: { skipDurableScheduler: true }, - }); - expect(makeRegistrar({ allowSkipDurableScheduler: false }).interceptsNode(skippingNode)).toBe( - true, - ); - }); - - it('intercepts a node that has not opted out even when the escape hatch is enabled', () => { - const keepingNode = mock({ - id: NODE_ID, - type: SCHEDULE_TRIGGER_NODE_TYPE, - parameters: { skipDurableScheduler: false }, - }); - expect(makeRegistrar({ allowSkipDurableScheduler: true }).interceptsNode(keepingNode)).toBe( - true, - ); + expect(makeRegistrar().interceptsNode(staleNode)).toBe(true); }); }); @@ -821,7 +791,7 @@ describe('ScheduleTriggerJobRegistrar', () => { const registrar = new ScheduleTriggerJobRegistrar( mock({ scoped: vi.fn().mockReturnValue(scopedLogger) }), mock({ - scheduler: { enabled: true, allowSkipDurableScheduler: false }, + scheduler: { enabled: true }, generic: { timezone: 'UTC' }, }), mock({ useWorkflowPublicationService: true }), diff --git a/packages/cli/src/scheduling/schedule-trigger-node/schedule-trigger-job-registrar.ts b/packages/cli/src/scheduling/schedule-trigger-node/schedule-trigger-job-registrar.ts index 3d7ec793ec5..208eb646f6f 100644 --- a/packages/cli/src/scheduling/schedule-trigger-node/schedule-trigger-job-registrar.ts +++ b/packages/cli/src/scheduling/schedule-trigger-node/schedule-trigger-job-registrar.ts @@ -111,9 +111,6 @@ export class ScheduleTriggerJobRegistrar { /** How a fixed second/minute interval is represented (see `SchedulerConfig`). */ private readonly triggerNodeMode: 'legacy' | 'new'; - /** Whether a node's "Skip Durable Scheduler" toggle is honored (see `SchedulerConfig`). */ - private readonly allowSkipDurableScheduler: boolean; - constructor( private readonly logger: Logger, globalConfig: GlobalConfig, @@ -122,12 +119,14 @@ export class ScheduleTriggerJobRegistrar { private readonly owner: WorkflowScheduledJobOwner, ) { this.intercepting = + // oxlint-disable-next-line typescript/no-deprecated -- the in-memory scheduler will be removed in a future version globalConfig.scheduler.enabled && workflowsConfig.useWorkflowPublicationService; this.defaultTimezone = globalConfig.generic.timezone; + // oxlint-disable-next-line typescript/no-deprecated -- the in-memory scheduler will be removed in a future version this.triggerNodeMode = globalConfig.scheduler.triggerNodeMode; - this.allowSkipDurableScheduler = globalConfig.scheduler.allowSkipDurableScheduler; this.logger = this.logger.scoped('scheduler'); + // oxlint-disable-next-line typescript/no-deprecated -- the in-memory scheduler will be removed in a future version if (globalConfig.scheduler.enabled && !workflowsConfig.useWorkflowPublicationService) { this.logger.warn( 'N8N_SCHEDULER_ENABLED is set but the workflow publication service is disabled. The durable scheduler cannot take over schedule and cron triggers, which keep using the legacy in-memory engine.', @@ -145,8 +144,7 @@ export class ScheduleTriggerJobRegistrar { interceptsNode(node: INode): boolean { if ( !this.intercepting || - (node.type !== SCHEDULE_TRIGGER_NODE_TYPE && node.type !== CRON_NODE_TYPE) || - (this.allowSkipDurableScheduler && node.parameters?.skipDurableScheduler === true) + (node.type !== SCHEDULE_TRIGGER_NODE_TYPE && node.type !== CRON_NODE_TYPE) ) { return false; } diff --git a/packages/cli/src/scheduling/system-tasks/README.md b/packages/cli/src/scheduling/system-tasks/README.md new file mode 100644 index 00000000000..bd1550656b5 --- /dev/null +++ b/packages/cli/src/scheduling/system-tasks/README.md @@ -0,0 +1,100 @@ +# System tasks + +A system task is background work that n8n runs on a schedule, such as a cleanup, +a refresh or a report. No workflow owns it. + +Use a system task instead of `setInterval`, a cron library or +`@OnLeaderTakeover`. The runner then handles leadership, shutdown, metrics and +tracing for you. The scheduler also runs a failed occurrence again while +attempts remain. + +## Write one + +```ts +@SystemTask() +export class ExpiredTokenCleanupTask implements SystemTask { + readonly name = 'expired-token-cleanup'; + + readonly schedule: SystemTaskSchedule = intervalFromSeconds(60); + + readonly target = { scope: 'cluster', scheduler: { retryOnFailure: true } } satisfies SystemTaskTarget; + + constructor(private readonly tokens: TokenRepository) {} + + async run(signal: AbortSignal): Promise { + await this.tokens.deleteExpired(signal); + } +} +``` + +1. `name` is unique across all system tasks. A duplicate stops startup. +2. `schedule` is an interval (`intervalFromSeconds`, `intervalFromMilliseconds`) + or a cron expression. +3. `target` says where the task runs. See below. +4. `run` does one occurrence. Honor `signal`: it aborts on shutdown, on lease + loss and at the timeout. + +## Make it safe to run twice + +The cluster runs each occurrence once, in the normal case. It does not guarantee +this. Two runs can overlap, or one occurrence can run again: + +1. A main stops during a run. Its lease expires, and another main runs the + occurrence again while attempts remain. +2. A run ignores its `signal` after a timeout or a lease loss. It keeps going + while the next run starts. + +So write `run()` to tolerate a second run at the same time: + +1. Change rows with a condition, for example "delete the rows that expired", + not "delete the rows I read before". +2. Work in small batches and check `signal` between them. +3. Set `retryOnFailure: false` when a repeat sends something twice, such as an + email or a report. This stops scheduler retries, but it does not stop an + overlap with a stalled run. + +See [Aiming for exactly-once across a cluster](../../../../@n8n/scheduler/README.md#aiming-for-exactly-once-across-a-cluster) +for how the scheduler gets there. + +## Choose where it runs + +| The work... | Use | +|---|---| +| touches shared state, so one run for the whole cluster is enough | `scope: 'cluster'` with `scheduler` | +| touches the memory or disk of each process | `scope: 'instance'` with `instanceTypes` | + +A cluster task runs on the durable scheduler. While the scheduler is disabled +(`N8N_SCHEDULER_SYSTEM_TASKS_ENABLED=false`), it runs on the leader's timer. +`leaderTimer` only tunes that fallback. It is deprecated and goes away when the +scheduler is the only runner. + +## Scheduler options + +| Option | Default | Set it when | +|---|---|---| +| `retryOnFailure` | required | Always. `true` runs a failed occurrence up to three times. Set `false` if running twice for one occurrence is not safe. | +| `missedAfterSeconds` | 60 | A late run is still useful for longer than a minute. | +| `catchUp` | `true` | A late run has no value after downtime. Set `false`. | +| `concurrencyLimit` | 1 | Occurrences may overlap. Use a number or `'unlimited'`. | +| `timeoutSeconds` | `N8N_SCHEDULER_TASK_TIMEOUT_SECONDS` | A run takes longer than 5 minutes. | + +Example of a late occurrence, with an interval of 10 minutes and +`missedAfterSeconds: 60`: + +1. The previous run is still going at 10:01. The 10:00 occurrence is dropped. +2. No main was up from 09:55 to 10:25. With `catchUp: true`, the 10:20 + occurrence runs once at 10:25. With `catchUp: false`, the next run is 10:30. + +## Register it + +1. In a backend module, return the class from `systemTasks()`. +2. Otherwise, add it to `mainSystemTasks()` or `instanceSystemTasks()` in this + folder. + +Load the class with `await import()` so a disabled feature costs nothing. + +## Test it + +1. Unit: assert `target` and `schedule`, then call `run()` with mocks. +2. A task that moves to the scheduler needs an integration test that proves two + parallel runs are safe. See `test/integration/scheduling/`. diff --git a/packages/cli/src/scheduling/system-tasks/__tests__/dummy.task.ts b/packages/cli/src/scheduling/system-tasks/__tests__/dummy.task.ts index 75742ce50cd..36c020e5d62 100644 --- a/packages/cli/src/scheduling/system-tasks/__tests__/dummy.task.ts +++ b/packages/cli/src/scheduling/system-tasks/__tests__/dummy.task.ts @@ -1,5 +1,5 @@ import { intervalFromSeconds, SystemTask } from '@n8n/decorators'; -import type { SystemTaskEffects, SystemTaskPlacement, SystemTaskSchedule } from '@n8n/decorators'; +import type { SystemTaskTarget, SystemTaskSchedule } from '@n8n/decorators'; @SystemTask() export class DummySystemTask implements SystemTask { @@ -7,15 +7,7 @@ export class DummySystemTask implements SystemTask { schedule: SystemTaskSchedule = intervalFromSeconds(60); - effects: SystemTaskEffects = 'idempotent'; - - placement: SystemTaskPlacement = { scope: 'cluster', durable: false }; - - retryDelaySeconds?: number; - - maxAttempts?: number; - - misfireGraceSeconds?: number; + target: SystemTaskTarget = { scope: 'cluster', leaderTimer: {} }; runCount = 0; @@ -37,7 +29,7 @@ export class OtherDummySystemTask extends DummySystemTask { export class PerInstanceDummySystemTask extends DummySystemTask { name = 'per-instance-dummy'; - placement: SystemTaskPlacement = { + target: SystemTaskTarget = { scope: 'instance', instanceTypes: ['main', 'worker', 'webhook'], }; diff --git a/packages/cli/src/scheduling/system-tasks/__tests__/system-task-handler.test.ts b/packages/cli/src/scheduling/system-tasks/__tests__/system-task-handler.test.ts index 8eb219f1024..246e9bc686d 100644 --- a/packages/cli/src/scheduling/system-tasks/__tests__/system-task-handler.test.ts +++ b/packages/cli/src/scheduling/system-tasks/__tests__/system-task-handler.test.ts @@ -13,9 +13,8 @@ const runOf = (signal: AbortSignal): TaskRun => ({ signal, remainingMs: () => 60 describe('SystemTaskHandler', () => { const claimed = mock({ id: 'task-1', jobId: 2 }); - function setup(effects: DummySystemTask['effects']) { + function setup() { const task = new DummySystemTask(); - task.effects = effects; const report = mock(); const onRunError = vi.fn(); const eventService = mock(); @@ -41,7 +40,7 @@ describe('SystemTaskHandler', () => { } it('runs the task', async () => { - const { task, report, handler } = setup('idempotent'); + const { task, report, handler } = setup(); await handler.execute(claimed, report, runOf(new AbortController().signal)); @@ -51,7 +50,7 @@ describe('SystemTaskHandler', () => { it.each(['shutdownController', 'leaseController'] as const)( 'hands the run a signal that aborts with the %s', async (source) => { - const context = setup('idempotent'); + const context = setup(); let seenSignal: AbortSignal | undefined; context.task.onRun = async (signal) => { seenSignal = signal; @@ -66,7 +65,7 @@ describe('SystemTaskHandler', () => { ); it('does not report a run that rejects once the claim was lost', async () => { - const { task, report, handler, onRunError, leaseController } = setup('idempotent'); + const { task, report, handler, onRunError, leaseController } = setup(); task.onRun = async (signal) => await new Promise((_, reject) => { signal.addEventListener('abort', () => reject(new Error('aborted'))); @@ -80,8 +79,7 @@ describe('SystemTaskHandler', () => { }); it('propagates the lease error when the run resolves after its claim is lost', async () => { - const { task, report, handler, onRunError, eventService, leaseController } = - setup('idempotent'); + const { task, report, handler, onRunError, eventService, leaseController } = setup(); task.onRun = async (signal) => await new Promise((resolve) => { signal.addEventListener('abort', () => resolve(), { once: true }); @@ -100,44 +98,37 @@ describe('SystemTaskHandler', () => { ); }); - it.each(['idempotent', 'non-idempotent'] as const)( - 'marks %s work dispatched only after the run', - async (effects) => { - const { task, handler } = setup(effects); - const runCountsAtDispatch: number[] = []; - const report = createDispatchReporter(() => { - runCountsAtDispatch.push(task.runCount); - }); + it('marks the occurrence dispatched only after the run', async () => { + const { task, handler } = setup(); + const runCountsAtDispatch: number[] = []; + const report = createDispatchReporter(() => { + runCountsAtDispatch.push(task.runCount); + }); - await handler.execute(claimed, report, runOf(new AbortController().signal)); + await handler.execute(claimed, report, runOf(new AbortController().signal)); - expect(runCountsAtDispatch).toEqual([1]); - }, - ); + expect(runCountsAtDispatch).toEqual([1]); + }); - it.each(['idempotent', 'non-idempotent'] as const)( - 'returns the dispatched token for %s work', - async (effects) => { - const task = new DummySystemTask(); - task.effects = effects; - const report = createDispatchReporter(vi.fn()); - const handler = new SystemTaskHandler( - task, - new AbortController().signal, - mockLogger(), - mock(), - new Tracing(), - vi.fn(), - ); + it('returns the dispatched token', async () => { + const task = new DummySystemTask(); + const report = createDispatchReporter(vi.fn()); + const handler = new SystemTaskHandler( + task, + new AbortController().signal, + mockLogger(), + mock(), + new Tracing(), + vi.fn(), + ); - const returned = await handler.execute(claimed, report, runOf(new AbortController().signal)); + const returned = await handler.execute(claimed, report, runOf(new AbortController().signal)); - expect(returned).toBe(report.dispatched()); - }, - ); + expect(returned).toBe(report.dispatched()); + }); it('lets a failing run reach the executor', async () => { - const { task, report, handler } = setup('idempotent'); + const { task, report, handler } = setup(); task.onRun = async () => { throw new Error('failed'); }; @@ -147,25 +138,22 @@ describe('SystemTaskHandler', () => { ).rejects.toThrow('failed'); }); - it.each(['idempotent', 'non-idempotent'] as const)( - 'reports a failing run of %s work, which the executor would not', - async (effects) => { - const { task, report, handler, onRunError } = setup(effects); - const error = new Error('failed'); - task.onRun = async () => { - throw error; - }; + it('reports a failing run, which the executor would not', async () => { + const { task, report, handler, onRunError } = setup(); + const error = new Error('failed'); + task.onRun = async () => { + throw error; + }; - await expect( - handler.execute(claimed, report, runOf(new AbortController().signal)), - ).rejects.toThrow(error); + await expect( + handler.execute(claimed, report, runOf(new AbortController().signal)), + ).rejects.toThrow(error); - expect(onRunError).toHaveBeenCalledWith(error); - }, - ); + expect(onRunError).toHaveBeenCalledWith(error); + }); it('does not report a run that rejects once shutdown aborted its signal', async () => { - const { task, report, handler, onRunError, shutdownController } = setup('idempotent'); + const { task, report, handler, onRunError, shutdownController } = setup(); task.onRun = async (signal) => await new Promise((_, reject) => { signal.addEventListener('abort', () => reject(new Error('aborted'))); @@ -179,7 +167,7 @@ describe('SystemTaskHandler', () => { }); it('runs the task and reports nothing although a metrics listener throws', async () => { - const { task, report, handler, onRunError, eventService } = setup('idempotent'); + const { task, report, handler, onRunError, eventService } = setup(); eventService.emit.mockImplementation(() => { throw new Error('sink'); }); @@ -191,7 +179,7 @@ describe('SystemTaskHandler', () => { }); it('does not report a run that succeeds', async () => { - const { report, handler, onRunError } = setup('idempotent'); + const { report, handler, onRunError } = setup(); await handler.execute(claimed, report, runOf(new AbortController().signal)); @@ -208,7 +196,7 @@ describe('SystemTaskHandler', () => { }); it('emits a durable run as started, then settled as a success with its duration', async () => { - const { task, report, handler, eventService } = setup('idempotent'); + const { task, report, handler, eventService } = setup(); task.onRun = async () => { await vi.advanceTimersByTimeAsync(250); }; @@ -225,7 +213,7 @@ describe('SystemTaskHandler', () => { }); it('settles a failing run as a failure', async () => { - const { task, report, handler, eventService } = setup('idempotent'); + const { task, report, handler, eventService } = setup(); task.onRun = async () => { throw new Error('failed'); }; @@ -241,7 +229,7 @@ describe('SystemTaskHandler', () => { }); it('settles a run that resolves once shutdown aborted its signal as aborted', async () => { - const { task, report, handler, eventService, shutdownController } = setup('idempotent'); + const { task, report, handler, eventService, shutdownController } = setup(); task.onRun = async (signal) => await new Promise((resolve) => { signal.addEventListener('abort', () => resolve()); @@ -258,7 +246,7 @@ describe('SystemTaskHandler', () => { }); it('settles a run that rejects once shutdown aborted its signal as aborted', async () => { - const { task, report, handler, eventService, shutdownController } = setup('idempotent'); + const { task, report, handler, eventService, shutdownController } = setup(); task.onRun = async (signal) => await new Promise((_, reject) => { signal.addEventListener('abort', () => reject(new Error('aborted'))); @@ -275,7 +263,7 @@ describe('SystemTaskHandler', () => { }); it('settles a run that rejects once its claim was lost as lease_lost', async () => { - const { task, report, handler, eventService, leaseController } = setup('idempotent'); + const { task, report, handler, eventService, leaseController } = setup(); task.onRun = async (signal) => await new Promise((_, reject) => { signal.addEventListener('abort', () => reject(new Error('aborted'))); diff --git a/packages/cli/src/scheduling/system-tasks/__tests__/system-task-job-registrar.test.ts b/packages/cli/src/scheduling/system-tasks/__tests__/system-task-job-registrar.test.ts index ee21f283a6d..392687254e5 100644 --- a/packages/cli/src/scheduling/system-tasks/__tests__/system-task-job-registrar.test.ts +++ b/packages/cli/src/scheduling/system-tasks/__tests__/system-task-job-registrar.test.ts @@ -3,7 +3,7 @@ import type { EventService } from '@n8n/backend-services'; import type { GlobalConfig } from '@n8n/config'; import { DEFAULT_MISFIRE_GRACE_SECONDS, ScheduledJobMisfirePolicy } from '@n8n/constants'; import type { ScheduledJobRepository } from '@n8n/db'; -import type { SystemTask, SystemTaskSchedule } from '@n8n/decorators'; +import type { SchedulerOptions, SystemTask, SystemTaskSchedule } from '@n8n/decorators'; import type { ProvisionSummary } from '@n8n/scheduler'; import type { ErrorReporter } from 'n8n-core'; import { inc } from 'semver'; @@ -12,7 +12,11 @@ import { mock } from 'vitest-mock-extended'; import { N8N_VERSION } from '@/constants'; import type { DurableJobProvisioner } from '../../durable-job-provisioner'; -import { SystemTaskJobRegistrar, systemTaskProvisionRequest } from '../system-task-job-registrar'; +import { + SystemTaskJobRegistrar, + systemTaskProvisionRequest, + durableSystemTask, +} from '../system-task-job-registrar'; import { SystemTaskScheduledJobOwner } from '../system-task-scheduled-job-owner'; const NOW = new Date('2026-01-05T09:00:00.000Z'); @@ -24,19 +28,40 @@ const emptySummary: ProvisionSummary = { removed: [], }; -const task = (over: Partial = {}): SystemTask => ({ +type TaskOverrides = { schedule?: SystemTaskSchedule; scheduler?: Partial }; + +const task = ({ schedule, scheduler }: TaskOverrides = {}): SystemTask => ({ name: 'prune-executions', - schedule: { kind: 'interval', intervalSeconds: 60 }, - effects: 'idempotent', - placement: { scope: 'cluster', durable: true }, + schedule: schedule ?? { kind: 'interval', intervalSeconds: 60 }, + target: { scope: 'cluster', scheduler: { retryOnFailure: true, ...scheduler } }, run: async () => {}, - ...over, +}); + +describe('durableSystemTask', () => { + it('resolves the schedule and the run options of a scheduler task', () => { + expect(durableSystemTask(task())).toEqual({ + task: expect.objectContaining({ name: 'prune-executions' }), + schedule: { kind: 'interval', intervalSeconds: 60 }, + runOptions: expect.objectContaining({ maxAttempts: 3 }), + }); + }); + + it('rejects a task that does not run on the scheduler', () => { + const leaderOnly = { ...task(), target: { scope: 'cluster', leaderTimer: {} } } as const; + + expect(() => durableSystemTask(leaderOnly)).toThrow( + expect.objectContaining({ + message: 'A system task does not run on the durable scheduler', + extra: { name: 'prune-executions' }, + }), + ); + }); }); describe('systemTaskProvisionRequest', () => { const owner = new SystemTaskScheduledJobOwner(mock()); - const request = (over: Partial = {}, defaultTimezone = 'UTC') => - systemTaskProvisionRequest(task(over), owner, defaultTimezone, NOW); + const request = (over: TaskOverrides = {}, defaultTimezone = 'UTC') => + systemTaskProvisionRequest(durableSystemTask(task(over)), owner, defaultTimezone, NOW); it('owns the job by task name, with no member', () => { expect(request().owner).toEqual({ @@ -99,16 +124,16 @@ describe('systemTaskProvisionRequest', () => { expect(desired[0]?.schedule).toEqual({ kind: 'interval', intervalSeconds: 90 }); }); - it('coalesces and retries idempotent work', () => { - expect(request({ effects: 'idempotent' })).toMatchObject({ + it('catches up, keeps the default grace and retries when the task states only its retry', () => { + expect(request()).toMatchObject({ misfirePolicy: ScheduledJobMisfirePolicy.Coalesce, misfireGraceSeconds: DEFAULT_MISFIRE_GRACE_SECONDS, maxAttempts: 3, }); }); - it('skips and never retries non-idempotent work, even where the task asks for retries', () => { - expect(request({ effects: 'non-idempotent', maxAttempts: 5 })).toMatchObject({ + it('stores no catch-up and a single attempt when the task asks for them', () => { + expect(request({ scheduler: { retryOnFailure: false, catchUp: false } })).toMatchObject({ misfirePolicy: ScheduledJobMisfirePolicy.Skip, maxAttempts: 1, }); @@ -118,8 +143,11 @@ describe('systemTaskProvisionRequest', () => { expect(request().concurrencyLimit).toBe(1); }); - it.each([null, 4])('honours a declared concurrency limit of %s', (concurrencyLimit) => { - expect(request({ concurrencyLimit }).concurrencyLimit).toBe(concurrencyLimit); + it.each([ + ['unlimited', null], + [4, 4], + ] as const)('honours a declared concurrency limit of %s', (concurrencyLimit, stored) => { + expect(request({ scheduler: { concurrencyLimit } }).concurrencyLimit).toBe(stored); }); it('leaves the timeout to the instance setting when the task declares none', () => { @@ -127,20 +155,13 @@ describe('systemTaskProvisionRequest', () => { }); it("honours a task's own timeout", () => { - expect(request({ timeoutSeconds: 600 }).timeoutSeconds).toBe(600); + expect(request({ scheduler: { timeoutSeconds: 600 } }).timeoutSeconds).toBe(600); }); - it("honours a task's own policy, grace and attempts", () => { - expect( - request({ - misfirePolicy: ScheduledJobMisfirePolicy.Skip, - misfireGraceSeconds: 300, - maxAttempts: 7, - }), - ).toMatchObject({ + it("honours a task's own catch-up and missed delay", () => { + expect(request({ scheduler: { catchUp: false, missedAfterSeconds: 300 } })).toMatchObject({ misfirePolicy: ScheduledJobMisfirePolicy.Skip, misfireGraceSeconds: 300, - maxAttempts: 7, }); }); }); @@ -191,7 +212,7 @@ describe('SystemTaskJobRegistrar', () => { it('provisions the one job of a task, owned by the task and seeded at now', async () => { const { registrar, durableJobProvisioner } = setup(); - await registrar.provision(task()); + await registrar.provision(durableSystemTask(task())); expect(durableJobProvisioner.provision).toHaveBeenCalledExactlyOnceWith({ owner: { ownerType: 'system-task', ownerId: 'prune-executions', ownerMemberId: null }, @@ -216,7 +237,7 @@ describe('SystemTaskJobRegistrar', () => { const { registrar, durableJobProvisioner, errorReporter, logger } = setup(); durableJobProvisioner.provision.mockRejectedValueOnce(error); - await expect(registrar.provision(task())).resolves.toBeUndefined(); + await expect(registrar.provision(durableSystemTask(task()))).resolves.toBeUndefined(); expect(errorReporter.error).toHaveBeenCalledExactlyOnceWith(error, { extra: { systemTask: 'prune-executions' }, @@ -232,11 +253,11 @@ describe('SystemTaskJobRegistrar', () => { it('emits a scheduling failure for a task it cannot provision, and nothing for one it can', async () => { const { registrar, durableJobProvisioner, eventService } = setup(); - await registrar.provision(task()); + await registrar.provision(durableSystemTask(task())); expect(eventService.emit).not.toHaveBeenCalled(); durableJobProvisioner.provision.mockRejectedValueOnce(new Error('connection lost')); - await registrar.provision(task()); + await registrar.provision(durableSystemTask(task())); expect(eventService.emit).toHaveBeenCalledExactlyOnceWith('system-task-scheduling-failed', { name: 'prune-executions', @@ -253,7 +274,7 @@ describe('SystemTaskJobRegistrar', () => { removed: [], }); - await registrar.provision(task()); + await registrar.provision(durableSystemTask(task())); expect(logger.debug).toHaveBeenCalledWith('Provisioned the durable job of a system task', { name: 'prune-executions', diff --git a/packages/cli/src/scheduling/system-tasks/__tests__/system-task-run-observer.test.ts b/packages/cli/src/scheduling/system-tasks/__tests__/system-task-run-observer.test.ts index 9569963ac4f..ec3f112bc66 100644 --- a/packages/cli/src/scheduling/system-tasks/__tests__/system-task-run-observer.test.ts +++ b/packages/cli/src/scheduling/system-tasks/__tests__/system-task-run-observer.test.ts @@ -37,24 +37,23 @@ describe('observeSystemTaskRun', () => { throw error; }; - it.each([ - { mode: 'durable' as const, durable: true }, - { mode: 'leader_timer' as const, durable: false }, - { mode: 'instance_timer' as const, durable: false }, - ])('tells a $mode run whether it is durable', async ({ mode, durable }) => { - const run = vi.fn(resolves); - const signal = new AbortController().signal; + it.each(['durable', 'leader_timer', 'instance_timer'] as const)( + 'passes the signal to a %s run', + async (mode) => { + const run = vi.fn(resolves); + const signal = new AbortController().signal; - await observeSystemTaskRun( - mock(), - setupTracing().tracing, - taskThat(run), - mode, - signal, - ); + await observeSystemTaskRun( + mock(), + setupTracing().tracing, + taskThat(run), + mode, + signal, + ); - expect(run).toHaveBeenCalledExactlyOnceWith(signal, { durable }); - }); + expect(run).toHaveBeenCalledExactlyOnceWith(signal); + }, + ); it('settles a run that throws synchronously as a failure, rather than rejecting', async () => { const eventService = mock(); diff --git a/packages/cli/src/scheduling/system-tasks/__tests__/system-task-runner.test.ts b/packages/cli/src/scheduling/system-tasks/__tests__/system-task-runner.test.ts index 14681b48f6b..f5e9b797ad1 100644 --- a/packages/cli/src/scheduling/system-tasks/__tests__/system-task-runner.test.ts +++ b/packages/cli/src/scheduling/system-tasks/__tests__/system-task-runner.test.ts @@ -177,7 +177,7 @@ describe('SystemTaskRunner', () => { it('runs a takeover task at once when the timers start', async () => { const { runner, metadata } = setup({ isLeader: true }); - dummy.placement = { scope: 'cluster', durable: false, runOnTakeover: true }; + dummy.target = { scope: 'cluster', leaderTimer: { runOnTakeover: true } }; metadata.register(DummySystemTask); await initRunner(runner); @@ -189,7 +189,7 @@ describe('SystemTaskRunner', () => { it('runs a takeover task registered after takeover at once', async () => { const { runner, metadata } = setup({ isLeader: true }); - dummy.placement = { scope: 'cluster', durable: false, runOnTakeover: true }; + dummy.target = { scope: 'cluster', leaderTimer: { runOnTakeover: true } }; await initRunner(runner); metadata.register(DummySystemTask); @@ -199,7 +199,7 @@ describe('SystemTaskRunner', () => { it('does not run a takeover task on a follower', async () => { const { runner, metadata } = setup({ isLeader: false }); - dummy.placement = { scope: 'cluster', durable: false, runOnTakeover: true }; + dummy.target = { scope: 'cluster', leaderTimer: { runOnTakeover: true } }; metadata.register(DummySystemTask); await initRunner(runner); @@ -210,7 +210,7 @@ describe('SystemTaskRunner', () => { it('runs a takeover task again on a later takeover', async () => { const { runner, metadata } = setup({ isLeader: true }); - dummy.placement = { scope: 'cluster', durable: false, runOnTakeover: true }; + dummy.target = { scope: 'cluster', leaderTimer: { runOnTakeover: true } }; metadata.register(DummySystemTask); await initRunner(runner); @@ -289,7 +289,7 @@ describe('SystemTaskRunner', () => { it('retries a failed run sooner when the task asks for it', async () => { const { runner, metadata } = setup(); - dummy.retryDelaySeconds = 5; + dummy.target = { scope: 'cluster', leaderTimer: { retryDelaySeconds: 5 } }; dummy.onRun = async () => { if (dummy.runCount === 1) { throw new Error('failed'); @@ -310,7 +310,7 @@ describe('SystemTaskRunner', () => { it('keeps retrying while the runs keep failing', async () => { const { runner, metadata } = setup(); - dummy.retryDelaySeconds = 5; + dummy.target = { scope: 'cluster', leaderTimer: { retryDelaySeconds: 5 } }; dummy.onRun = async () => { throw new Error('failed'); }; @@ -324,7 +324,7 @@ describe('SystemTaskRunner', () => { it('does not retry a successful run', async () => { const { runner, metadata } = setup(); - dummy.retryDelaySeconds = 5; + dummy.target = { scope: 'cluster', leaderTimer: { retryDelaySeconds: 5 } }; metadata.register(DummySystemTask); await initRunner(runner); @@ -335,7 +335,7 @@ describe('SystemTaskRunner', () => { it('drops a pending retry once a newer occurrence runs', async () => { const { runner, metadata } = setup(); - dummy.retryDelaySeconds = 90; + dummy.target = { scope: 'cluster', leaderTimer: { retryDelaySeconds: 90 } }; dummy.onRun = async () => { if (dummy.runCount === 1) { throw new Error('failed'); @@ -354,21 +354,6 @@ describe('SystemTaskRunner', () => { expect(dummy.runCount).toBe(2); }); - it('does not retry non-idempotent work', async () => { - const { runner, metadata } = setup(); - dummy.effects = 'non-idempotent'; - dummy.retryDelaySeconds = 5; - dummy.onRun = async () => { - throw new Error('failed'); - }; - metadata.register(DummySystemTask); - await initRunner(runner); - - await vi.advanceTimersByTimeAsync(ONE_INTERVAL_MS + 30 * Time.seconds.toMilliseconds); - - expect(dummy.runCount).toBe(1); - }); - it('logs a failing run as well as reporting it', async () => { const { runner, metadata, logger } = setup(); const error = new Error('failed'); @@ -407,8 +392,11 @@ describe('SystemTaskRunner', () => { describe('in-memory runs of a task provisioned elsewhere', () => { it('skips the run when a durable job is stored for the task', async () => { const { runner, metadata, jobRegistrar, logger } = setup(); - dummy.placement = { scope: 'cluster', durable: true }; - dummy.retryDelaySeconds = 1; + dummy.target = { + scope: 'cluster', + scheduler: { retryOnFailure: true }, + leaderTimer: { retryDelaySeconds: 1 }, + }; jobRegistrar.isProvisioned.mockResolvedValue(true); metadata.register(DummySystemTask); await initRunner(runner); @@ -425,7 +413,11 @@ describe('SystemTaskRunner', () => { it('skips a takeover run when a durable job is stored for the task', async () => { const { runner, metadata, jobRegistrar } = setup(); - dummy.placement = { scope: 'cluster', durable: true, runOnTakeover: true }; + dummy.target = { + scope: 'cluster', + scheduler: { retryOnFailure: true }, + leaderTimer: { runOnTakeover: true }, + }; jobRegistrar.isProvisioned.mockResolvedValue(true); metadata.register(DummySystemTask); @@ -436,7 +428,7 @@ describe('SystemTaskRunner', () => { it('runs when no durable job is stored for the task', async () => { const { runner, metadata, jobRegistrar } = setup(); - dummy.placement = { scope: 'cluster', durable: true }; + dummy.target = { scope: 'cluster', scheduler: { retryOnFailure: true } }; jobRegistrar.isProvisioned.mockResolvedValue(false); metadata.register(DummySystemTask); await initRunner(runner); @@ -448,7 +440,7 @@ describe('SystemTaskRunner', () => { it('does not run a task whose store check settles after stepdown', async () => { const { runner, metadata, jobRegistrar } = setup(); - dummy.placement = { scope: 'cluster', durable: true }; + dummy.target = { scope: 'cluster', scheduler: { retryOnFailure: true } }; let settleCheck!: (exists: boolean) => void; jobRegistrar.isProvisioned.mockReturnValue( new Promise((resolve) => { @@ -468,7 +460,7 @@ describe('SystemTaskRunner', () => { it('does not run a task whose store check settles after stepdown and takeover', async () => { const { runner, metadata, jobRegistrar, eventService } = setup(); - dummy.placement = { scope: 'cluster', durable: true }; + dummy.target = { scope: 'cluster', scheduler: { retryOnFailure: true } }; let settleCheck!: (exists: boolean) => void; jobRegistrar.isProvisioned.mockReturnValueOnce( new Promise((resolve) => { @@ -518,7 +510,7 @@ describe('SystemTaskRunner', () => { }); it('does not touch the durable jobs on a worker', async () => { - dummy.placement = { scope: 'cluster', durable: true }; + dummy.target = { scope: 'cluster', scheduler: { retryOnFailure: true } }; const { runner, metadata, jobRegistrar } = setup({ isLeader: false, instanceRole: 'unset', @@ -620,7 +612,7 @@ describe('SystemTaskRunner', () => { it('drops a pending retry on stepdown', async () => { const { runner, metadata } = setup(); - dummy.retryDelaySeconds = 5; + dummy.target = { scope: 'cluster', leaderTimer: { retryDelaySeconds: 5 } }; dummy.onRun = async () => { throw new Error('failed'); }; @@ -666,9 +658,9 @@ describe('SystemTaskRunner', () => { const durably = { schedulerActive: true, enabledForSystemTasks: true }; it('hands each durable task to the job registrar', async () => { - dummy.placement = { scope: 'cluster', durable: true }; + dummy.target = { scope: 'cluster', scheduler: { retryOnFailure: true } }; const other = new OtherDummySystemTask(); - other.placement = { scope: 'cluster', durable: true }; + other.target = { scope: 'cluster', scheduler: { retryOnFailure: true } }; Container.set(OtherDummySystemTask, other); const { runner, metadata, jobRegistrar } = setup(durably); metadata.register(DummySystemTask); @@ -676,7 +668,10 @@ describe('SystemTaskRunner', () => { await initRunner(runner); - expect(jobRegistrar.provision.mock.calls).toEqual([[dummy], [other]]); + expect(jobRegistrar.provision.mock.calls).toEqual([ + [expect.objectContaining({ task: dummy })], + [expect.objectContaining({ task: other })], + ]); }); it('leaves a task on an in-memory timer unprovisioned', async () => { @@ -698,7 +693,7 @@ describe('SystemTaskRunner', () => { ])( 'leaves a durable task unprovisioned while $case', async ({ schedulerActive, enabledForSystemTasks }) => { - dummy.placement = { scope: 'cluster', durable: true }; + dummy.target = { scope: 'cluster', scheduler: { retryOnFailure: true } }; const { runner, metadata, jobRegistrar } = setup({ schedulerActive, enabledForSystemTasks, @@ -716,7 +711,7 @@ describe('SystemTaskRunner', () => { const durably = { schedulerActive: true, enabledForSystemTasks: true }; it('removes stale jobs once, after provisioning the wanted ones', async () => { - dummy.placement = { scope: 'cluster', durable: true }; + dummy.target = { scope: 'cluster', scheduler: { retryOnFailure: true } }; const { runner, metadata, jobRegistrar } = setup(durably); metadata.register(DummySystemTask); @@ -748,7 +743,7 @@ describe('SystemTaskRunner', () => { const durably = { schedulerActive: true, enabledForSystemTasks: true }; it('hands a durable task to the durable scheduler', async () => { - dummy.placement = { scope: 'cluster', durable: true }; + dummy.target = { scope: 'cluster', scheduler: { retryOnFailure: true } }; const { runner, metadata, durableScheduler } = setup(durably); metadata.register(DummySystemTask); @@ -763,7 +758,7 @@ describe('SystemTaskRunner', () => { }); it('hands a durable task registered after it took over the registry to the scheduler', async () => { - dummy.placement = { scope: 'cluster', durable: true }; + dummy.target = { scope: 'cluster', scheduler: { retryOnFailure: true } }; const { runner, metadata, durableScheduler } = setup(durably); await initRunner(runner); @@ -778,7 +773,7 @@ describe('SystemTaskRunner', () => { }); it('reports a failing durable run, which the executor would not', async () => { - dummy.placement = { scope: 'cluster', durable: true }; + dummy.target = { scope: 'cluster', scheduler: { retryOnFailure: true } }; const error = new Error('failed'); dummy.onRun = async () => { throw error; @@ -804,7 +799,7 @@ describe('SystemTaskRunner', () => { }); it('aborts the signal of a durable run on shutdown', async () => { - dummy.placement = { scope: 'cluster', durable: true }; + dummy.target = { scope: 'cluster', scheduler: { retryOnFailure: true } }; const { runner, metadata, durableScheduler } = setup(durably); let runSignal: AbortSignal | undefined; let releaseRun = () => {}; @@ -842,7 +837,7 @@ describe('SystemTaskRunner', () => { ])( 'keeps a durable task on its timer while $case', async ({ schedulerActive, enabledForSystemTasks }) => { - dummy.placement = { scope: 'cluster', durable: true }; + dummy.target = { scope: 'cluster', scheduler: { retryOnFailure: true } }; const { runner, metadata, durableScheduler } = setup({ schedulerActive, enabledForSystemTasks, @@ -869,7 +864,7 @@ describe('SystemTaskRunner', () => { }); it('runs a durable cron task on its timer, in the instance timezone, while the scheduler is inactive', async () => { - dummy.placement = { scope: 'cluster', durable: true }; + dummy.target = { scope: 'cluster', scheduler: { retryOnFailure: true } }; dummy.schedule = { kind: 'cron', cronExpression: '0 3 * * *', timezone: null }; const { runner, metadata, durableScheduler } = setup({ timezone: 'Europe/Berlin' }); metadata.register(DummySystemTask); @@ -885,7 +880,7 @@ describe('SystemTaskRunner', () => { }); it('declares a task it hands to the durable scheduler to the job owner', async () => { - dummy.placement = { scope: 'cluster', durable: true }; + dummy.target = { scope: 'cluster', scheduler: { retryOnFailure: true } }; const { runner, metadata, systemTaskOwner } = setup(durably); metadata.register(DummySystemTask); @@ -895,7 +890,7 @@ describe('SystemTaskRunner', () => { }); it('does not declare a task it keeps on a timer to the job owner', async () => { - dummy.placement = { scope: 'cluster', durable: true }; + dummy.target = { scope: 'cluster', scheduler: { retryOnFailure: true } }; const { runner, metadata, systemTaskOwner } = setup({ enabledForSystemTasks: false }); metadata.register(DummySystemTask); @@ -907,7 +902,7 @@ describe('SystemTaskRunner', () => { it.each([0, -5, 2.5, NaN, Infinity, 2_147_484])( 'rejects a task declaring a retry delay of %s', async (retryDelaySeconds) => { - dummy.retryDelaySeconds = retryDelaySeconds; + dummy.target = { scope: 'cluster', leaderTimer: { retryDelaySeconds } }; const { runner, metadata } = setup(); metadata.register(DummySystemTask); @@ -922,7 +917,7 @@ describe('SystemTaskRunner', () => { ); it('accepts the longest retry delay a timeout honors', async () => { - dummy.retryDelaySeconds = 2_147_483; + dummy.target = { scope: 'cluster', leaderTimer: { retryDelaySeconds: 2_147_483 } }; const { runner, metadata } = setup(); metadata.register(DummySystemTask); @@ -930,10 +925,10 @@ describe('SystemTaskRunner', () => { }); it.each([ - { field: 'maxAttempts', value: 0 }, - { field: 'misfireGraceSeconds', value: 0 }, - ])('rejects a task declaring $field as $value', async ({ field, value }) => { - Object.assign(dummy, { [field]: value }); + { field: 'concurrencyLimit', scheduler: { retryOnFailure: true, concurrencyLimit: 0 } }, + { field: 'missedAfterSeconds', scheduler: { retryOnFailure: true, missedAfterSeconds: 0 } }, + ])('rejects a task declaring $field out of range', async ({ field, scheduler }) => { + dummy.target = { scope: 'cluster', scheduler }; const { runner, metadata } = setup(); metadata.register(DummySystemTask); @@ -948,7 +943,7 @@ describe('SystemTaskRunner', () => { }); it('rejects a task declaring a bad option on an instance kind that does not run it', async () => { - dummy.retryDelaySeconds = 0; + dummy.target = { scope: 'cluster', leaderTimer: { retryDelaySeconds: 0 } }; const { runner, metadata } = setup({ isLeader: false, instanceRole: 'unset', @@ -1041,7 +1036,7 @@ describe('SystemTaskRunner', () => { }); it('emits a durable task as routed', async () => { - dummy.placement = { scope: 'cluster', durable: true }; + dummy.target = { scope: 'cluster', scheduler: { retryOnFailure: true } }; const { runner, metadata, eventService } = setup(durably); metadata.register(DummySystemTask); @@ -1148,7 +1143,7 @@ describe('SystemTaskRunner', () => { it('stays stopped when an early takeover is followed by stepdown before init', async () => { const { runner, metadata, eventService, instanceSettings } = setup(); - dummy.placement = { scope: 'cluster', durable: false, runOnTakeover: true }; + dummy.target = { scope: 'cluster', leaderTimer: { runOnTakeover: true } }; metadata.register(DummySystemTask); runner.startLeaderTimers(); @@ -1206,7 +1201,7 @@ describe('SystemTaskRunner', () => { it('settles a failing run as a failure and emits the retry it schedules', async () => { const { runner, metadata, eventService } = setup(); - dummy.retryDelaySeconds = 5; + dummy.target = { scope: 'cluster', leaderTimer: { retryDelaySeconds: 5 } }; dummy.onRun = async () => { throw new Error('failed'); }; @@ -1272,7 +1267,7 @@ describe('SystemTaskRunner', () => { it('emits a run skipped for a durable job provisioned elsewhere, without starting it', async () => { const { runner, metadata, jobRegistrar, eventService } = setup(); - dummy.placement = { scope: 'cluster', durable: true }; + dummy.target = { scope: 'cluster', scheduler: { retryOnFailure: true } }; jobRegistrar.isProvisioned.mockResolvedValue(true); metadata.register(DummySystemTask); await initRunner(runner); @@ -1288,7 +1283,7 @@ describe('SystemTaskRunner', () => { it('emits a run skipped when its store check settles after stepdown', async () => { const { runner, metadata, jobRegistrar, eventService } = setup(); - dummy.placement = { scope: 'cluster', durable: true }; + dummy.target = { scope: 'cluster', scheduler: { retryOnFailure: true } }; let settleCheck!: (exists: boolean) => void; jobRegistrar.isProvisioned.mockReturnValue( new Promise((resolve) => { @@ -1335,7 +1330,7 @@ describe('SystemTaskRunner', () => { }); it('emits the runs of a durable task as durable', async () => { - dummy.placement = { scope: 'cluster', durable: true }; + dummy.target = { scope: 'cluster', scheduler: { retryOnFailure: true } }; const { runner, metadata, durableScheduler, eventService } = setup(durably); metadata.register(DummySystemTask); await initRunner(runner); @@ -1468,14 +1463,13 @@ describe('SystemTaskRunner', () => { ); }); - it('reports a failing instance-scoped run and retries it on the instance timer', async () => { + it('reports a failing instance-scoped run and runs it again at its next occurrence', async () => { const { runner, metadata, eventService, errorReporter } = setup({ isLeader: false, instanceRole: 'unset', instanceType: 'worker', }); const error = new Error('failed'); - perInstance.retryDelaySeconds = 5; perInstance.onRun = async () => { throw error; }; @@ -1490,12 +1484,15 @@ describe('SystemTaskRunner', () => { shouldBeLogged: false, shouldIsolate: true, }); - expect(eventService.emit).toHaveBeenCalledWith('system-task-retry-scheduled', { - name: 'per-instance-dummy', - }); + expect(eventService.emit).not.toHaveBeenCalledWith( + 'system-task-retry-scheduled', + expect.anything(), + ); - await vi.advanceTimersByTimeAsync(5 * Time.seconds.toMilliseconds); + await vi.advanceTimersByTimeAsync(ONE_INTERVAL_MS - 1); + expect(perInstance.runCount).toBe(1); + await vi.advanceTimersByTimeAsync(1); expect(perInstance.runCount).toBe(2); }); @@ -1569,7 +1566,7 @@ describe('SystemTaskRunner', () => { ); expect(logger.debug).toHaveBeenCalledWith( expect.stringContaining('does not run on this kind of instance'), - { name: 'dummy', placement: { scope: 'cluster', durable: false } }, + { name: 'dummy', target: { scope: 'cluster', leaderTimer: {} } }, ); }); }); diff --git a/packages/cli/src/scheduling/system-tasks/in-memory-system-task-runner.ts b/packages/cli/src/scheduling/system-tasks/in-memory-system-task-runner.ts index b9d92e1a556..a9624d8c28e 100644 --- a/packages/cli/src/scheduling/system-tasks/in-memory-system-task-runner.ts +++ b/packages/cli/src/scheduling/system-tasks/in-memory-system-task-runner.ts @@ -28,6 +28,8 @@ export type InMemorySystemTaskHooks = { export type InMemorySystemTaskOptions = { /** Runs the task once on start, on top of its schedule. */ runOnStart?: boolean; + /** How long after a failed run the task runs again, instead of at its next occurrence. */ + retryDelaySeconds?: number; /** Skips a run when it returns `true`. It reports the skip itself. */ shouldSkipRun?: () => Promise; }; @@ -225,8 +227,8 @@ export class InMemorySystemTaskRunner { } private scheduleRetry(entry: Entry): void { - const { retryDelaySeconds, effects } = entry.task; - if (retryDelaySeconds !== undefined && effects !== 'non-idempotent' && this.started) { + const { retryDelaySeconds } = entry; + if (retryDelaySeconds !== undefined && this.started) { this.cancelRetry(entry); entry.retryTimer = setTimeout(() => { void this.run(entry); diff --git a/packages/cli/src/scheduling/system-tasks/system-task-job-registrar.ts b/packages/cli/src/scheduling/system-tasks/system-task-job-registrar.ts index d6902f427bf..14a5ecf3c58 100644 --- a/packages/cli/src/scheduling/system-tasks/system-task-job-registrar.ts +++ b/packages/cli/src/scheduling/system-tasks/system-task-job-registrar.ts @@ -3,11 +3,12 @@ import { EventService } from '@n8n/backend-services'; import { GlobalConfig } from '@n8n/config'; import type { ScheduledJob } from '@n8n/db'; import { ScheduledJobRepository } from '@n8n/db'; -import type { SystemTask } from '@n8n/decorators'; -import { resolveSystemTaskRunOptions, resolveSystemTaskSchedule } from '@n8n/decorators'; +import type { SystemTask, SystemTaskRunOptions, SystemTaskSchedule } from '@n8n/decorators'; +import { resolveSystemTask } from '@n8n/decorators'; import { Service } from '@n8n/di'; import { computeFirstRunAt, scheduleFromDefinition } from '@n8n/scheduler'; import { ErrorReporter } from 'n8n-core'; +import { UnexpectedError } from 'n8n-workflow'; import { DurableJobProvisioner } from '../durable-job-provisioner'; import type { ProvisionRequest } from '../durable-job-provisioner'; @@ -19,6 +20,29 @@ import { versionStamp } from './system-task-version-stamp'; /** A system task's stored job as listed, pinned to the payload read at the time. */ export type StaleSystemTaskJob = Pick; +/** A system task that runs on the durable scheduler, with what it resolved to. */ +export interface DurableSystemTask { + readonly task: SystemTask; + readonly schedule: SystemTaskSchedule; + readonly runOptions: SystemTaskRunOptions; +} + +/** + * Resolves a task that runs on the durable scheduler. + * + * @throws {UnexpectedError} when the task does not run on the scheduler + * @throws {UnexpectedError} when the task declares an out-of-range option + */ +export function durableSystemTask(task: SystemTask): DurableSystemTask { + const { schedule, runOptions } = resolveSystemTask(task); + if (runOptions === undefined) { + throw new UnexpectedError('A system task does not run on the durable scheduler', { + extra: { name: task.name }, + }); + } + return { task, schedule, runOptions }; +} + /** * The one durable job a system task owns, ready to provision. The schedule is * stored as declared, so `defaultTimezone` seeds the first run only: baking it @@ -26,19 +50,18 @@ export type StaleSystemTaskJob = Pick { + async provision(durableTask: DurableSystemTask): Promise { + const { task } = durableTask; try { const summary = await this.durableJobProvisioner.provision( systemTaskProvisionRequest( - task, + durableTask, this.systemTaskOwner, this.globalConfig.generic.timezone, new Date(), diff --git a/packages/cli/src/scheduling/system-tasks/system-task-run-observer.ts b/packages/cli/src/scheduling/system-tasks/system-task-run-observer.ts index d817c0b529b..38f77541fd2 100644 --- a/packages/cli/src/scheduling/system-tasks/system-task-run-observer.ts +++ b/packages/cli/src/scheduling/system-tasks/system-task-run-observer.ts @@ -20,12 +20,8 @@ const SYSTEM_TASK_ATTRIBUTES = { * tick, so an abort that follows the call cannot preempt the run, and rejects * rather than throws if `run` throws synchronously. */ -async function startRun( - task: Pick, - signal: AbortSignal, - mode: SystemTaskMode, -): Promise { - await task.run(signal, { durable: mode === 'durable' }); +async function startRun(task: Pick, signal: AbortSignal): Promise { + await task.run(signal); } /** How one observed run ended. A rejected run carries its error. */ @@ -74,7 +70,7 @@ export async function observeSystemTaskRun( return await startSpan(spanOptions, async (span: Span) => { const startedAt = performance.now(); emitSystemTaskMetric(eventService, 'system-task-run-started', { name, mode }); - const outcome = await startRun(task, runSignal, mode).then( + const outcome = await startRun(task, runSignal).then( (): SystemTaskRunOutcome => ({ result: abortResult() ?? 'success', rejected: false, diff --git a/packages/cli/src/scheduling/system-tasks/system-task-runner.ts b/packages/cli/src/scheduling/system-tasks/system-task-runner.ts index f68ce4482ab..7cb6a879a7c 100644 --- a/packages/cli/src/scheduling/system-tasks/system-task-runner.ts +++ b/packages/cli/src/scheduling/system-tasks/system-task-runner.ts @@ -2,19 +2,13 @@ import { Logger } from '@n8n/backend-common'; import { EventService } from '@n8n/backend-services'; import { GlobalConfig } from '@n8n/config'; import type { InstanceType } from '@n8n/constants'; -import type { - SystemTask, - SystemTaskClass, - SystemTaskPlacement, - SystemTaskSchedule, -} from '@n8n/decorators'; +import type { SystemTask, SystemTaskClass, SystemTaskTarget } from '@n8n/decorators'; import { OnLeaderStepdown, OnLeaderTakeover, OnShutdown, SystemTaskMetadata, - resolveSystemTaskSchedule, - validateSystemTask, + resolveSystemTask, } from '@n8n/decorators'; import { Container, Service } from '@n8n/di'; import { ErrorReporter, InstanceSettings, Tracing } from 'n8n-core'; @@ -24,13 +18,11 @@ import { strict } from 'node:assert'; import { DurableScheduler } from '../durable-scheduler'; import { emitSystemTaskMetric } from './emit-system-task-metric'; import { SystemTaskHandler } from './system-task-handler'; -import { SystemTaskJobRegistrar } from './system-task-job-registrar'; +import { SystemTaskJobRegistrar, type DurableSystemTask } from './system-task-job-registrar'; import { SystemTaskScheduledJobOwner } from './system-task-scheduled-job-owner'; import { InMemorySystemTaskRunner } from './in-memory-system-task-runner'; import { systemTaskType } from './system-task-type'; -type ClusterPlacement = Extract; - /** * Routes each registered system task to the durable scheduler, to the timers * the leader runs, or to the timers every eligible instance runs. Starts and @@ -41,7 +33,7 @@ export class SystemTaskRunner { /** Includes the dropped tasks, so a name stays unique across instance kinds. */ private readonly registeredNames = new Set(); - private readonly durableTasks: SystemTask[] = []; + private readonly durableTasks: DurableSystemTask[] = []; private readonly logger: Logger; @@ -121,8 +113,8 @@ export class SystemTaskRunner { this.startLeaderTimers(); } - for (const task of this.durableTasks) { - await this.jobRegistrar.provision(task); + for (const durableTask of this.durableTasks) { + await this.jobRegistrar.provision(durableTask); } await this.jobRegistrar.removeStale(); } @@ -161,44 +153,48 @@ export class SystemTaskRunner { }); } this.registeredNames.add(task.name); - validateSystemTask(task); + const { schedule, runOptions } = resolveSystemTask(task); - const { placement } = task; - if (!runsOn(placement, this.instanceSettings.instanceType)) { + const { target } = task; + if (!runsOnInstanceType(target, this.instanceSettings.instanceType)) { this.logger.debug('System task does not run on this kind of instance', { name: task.name, - placement, + target, }); return; } - const schedule = resolveSystemTaskSchedule(task); - - if (placement.scope === 'instance') { + if (target.scope === 'instance') { this.logger.debug('System task will run on a per-instance timer', { name: task.name, schedule, }); this.instanceTaskRunner.add(task, schedule); - } else if (this.runsDurably(placement)) { - this.handOverToDurableScheduler(task, schedule); + } else if (runOptions !== undefined && this.schedulerEnabled()) { + this.handOverToDurableScheduler({ task, schedule, runOptions }); } else { this.logger.debug('System task will run on an in-memory timer', { name: task.name, schedule, }); + // The leader timer is deprecated for task authors, but it still runs their tasks. + // oxlint-disable-next-line typescript/no-deprecated + const { leaderTimer } = target; this.leaderTaskRunner.add(task, schedule, { - runOnStart: placement.runOnTakeover, + runOnStart: leaderTimer?.runOnTakeover, + retryDelaySeconds: leaderTimer?.retryDelaySeconds, // Another main can run this task durably. Skip while its job is stored. - shouldSkipRun: placement.durable - ? async () => await this.isProvisionedElsewhere(task) - : undefined, + shouldSkipRun: + runOptions !== undefined + ? async () => await this.isProvisionedElsewhere(task) + : undefined, }); } } - private handOverToDurableScheduler(task: SystemTask, schedule: SystemTaskSchedule): void { - this.durableTasks.push(task); + private handOverToDurableScheduler(durableTask: DurableSystemTask): void { + const { task, schedule } = durableTask; + this.durableTasks.push(durableTask); this.systemTaskOwner.declareDurable(task.name); this.durableScheduler.registerTaskHandler( systemTaskType(task.name), @@ -233,12 +229,8 @@ export class SystemTaskRunner { return provisioned; } - private runsDurably(placement: ClusterPlacement): boolean { - return ( - placement.durable && - this.globalConfig.scheduler.enabledForSystemTasks && - this.durableScheduler.isActive() - ); + private schedulerEnabled(): boolean { + return this.globalConfig.scheduler.enabledForSystemTasks && this.durableScheduler.isActive(); } private reportFailure(message: string, task: Pick, error: unknown): void { @@ -251,8 +243,8 @@ export class SystemTaskRunner { } } -function runsOn(placement: SystemTaskPlacement, instanceType: InstanceType): boolean { - return placement.scope === 'cluster' +function runsOnInstanceType(target: SystemTaskTarget, instanceType: InstanceType): boolean { + return target.scope === 'cluster' ? instanceType === 'main' - : placement.instanceTypes.includes(instanceType); + : target.instanceTypes.includes(instanceType); } diff --git a/packages/cli/src/services/__tests__/active-workflows.service.test.ts b/packages/cli/src/services/__tests__/active-workflows.service.test.ts index bc40e251902..560b6e80c81 100644 --- a/packages/cli/src/services/__tests__/active-workflows.service.test.ts +++ b/packages/cli/src/services/__tests__/active-workflows.service.test.ts @@ -1,11 +1,14 @@ -import { GLOBAL_ADMIN_ROLE, GLOBAL_MEMBER_ROLE, WorkflowEntity } from '@n8n/db'; +import type { WorkflowsConfig } from '@n8n/config'; +import { GLOBAL_ADMIN_ROLE, GLOBAL_MEMBER_ROLE, GLOBAL_OWNER_ROLE, WorkflowEntity } from '@n8n/db'; import type { User, WorkflowRepository } from '@n8n/db'; +import type { INode } from 'n8n-workflow'; import { mock } from 'vitest-mock-extended'; import type { ActivationErrorsService } from '@/activation-errors.service'; import { BadRequestError } from '@n8n/errors'; import type { ProjectScopeService, WorkflowSharingService } from '@n8n/backend-services'; import { ActiveWorkflowsService } from '@/services/active-workflows.service'; +import type { WorkflowPublicationStatusService } from '@/workflows/publication/workflow-publication-status.service'; import type { WorkflowFinderService } from '@/workflows/workflow-finder.service'; describe('ActiveWorkflowsService', () => { @@ -15,12 +18,16 @@ describe('ActiveWorkflowsService', () => { const workflowFinderService = mock(); const activationErrorsService = mock(); const projectScopeService = mock(); + const workflowsConfig = mock({ useWorkflowPublicationService: false }); + const workflowPublicationStatusService = mock(); const service = new ActiveWorkflowsService( mock(), workflowRepository, workflowSharingService, activationErrorsService, workflowFinderService, + workflowsConfig, + workflowPublicationStatusService, ); const activeIds = ['1', '2', '3', '4']; @@ -33,6 +40,7 @@ describe('ActiveWorkflowsService', () => { const ids = await service.getAllActiveIdsInStorage(); expect(ids).toEqual(['2', '3', '4']); + expect(workflowPublicationStatusService.getListStatusesByWorkflowIds).not.toHaveBeenCalled(); }); }); @@ -53,6 +61,7 @@ describe('ActiveWorkflowsService', () => { it.each([ { accessible: ['3'], expected: ['3'] }, + { accessible: ['1', '3'], expected: ['3'] }, { accessible: [], expected: [] }, ])( 'should return only workflow ids the member has access to (accessible: $accessible)', @@ -93,6 +102,120 @@ describe('ActiveWorkflowsService', () => { 'workflow:read', ]); expect(activationErrorsService.get).toHaveBeenCalledWith(workflowId); + expect(workflowPublicationStatusService.getFailedActivationError).not.toHaveBeenCalled(); + }); + }); + + describe('with the publication service on', () => { + beforeEach(() => { + workflowsConfig.useWorkflowPublicationService = true; + activationErrorsService.getAll.mockResolvedValue({ 1: 'some error' }); + workflowRepository.getActiveIds.mockResolvedValue(['1', '2', '3', '4', '5']); + workflowPublicationStatusService.getListStatusesByWorkflowIds.mockResolvedValue( + new Map([ + ['2', 'failed'], + ['3', 'partial'], + ['5', 'published'], + ]), + ); + }); + + afterEach(() => { + workflowsConfig.useWorkflowPublicationService = false; + }); + + it.each([ + { + entry: 'getAllActiveIdsInStorage', + read: async () => await service.getAllActiveIdsInStorage(), + }, + { + entry: 'getAllActiveIdsFor as an owner', + read: async () => { + user.role = GLOBAL_OWNER_ROLE; + return await service.getAllActiveIdsFor(user); + }, + }, + ])('should drop workflows whose publication failed from $entry', async ({ read }) => { + expect(await read()).toEqual(['3', '4', '5']); + expect(workflowPublicationStatusService.getListStatusesByWorkflowIds).toHaveBeenCalledWith([ + '2', + '3', + '4', + '5', + ]); + }); + + it('should check only the workflows a member can read', async () => { + user.role = GLOBAL_MEMBER_ROLE; + workflowSharingService.getSharedWorkflowIds.mockResolvedValue(['2', '3']); + + const ids = await service.getAllActiveIdsFor(user); + + expect(ids).toEqual(['3']); + expect(workflowSharingService.getSharedWorkflowIds).toHaveBeenCalledWith(user, { + scopes: ['workflow:read'], + }); + expect(workflowPublicationStatusService.getListStatusesByWorkflowIds).toHaveBeenCalledWith([ + '2', + '3', + ]); + }); + + describe('getActivationError', () => { + const workflowId = 'workflowId'; + const nodes: INode[] = [ + { + id: 'node-1', + name: 'Webhook', + type: 'n8n-nodes-base.webhook', + typeVersion: 1, + position: [0, 0], + parameters: {}, + }, + ]; + + beforeEach(() => { + workflowFinderService.findWorkflowForUser.mockResolvedValue( + Object.assign(new WorkflowEntity(), { nodes }), + ); + }); + + it('should consult neither source when the user has no access', async () => { + workflowFinderService.findWorkflowForUser.mockResolvedValue(null); + + await expect(service.getActivationError(workflowId, user)).rejects.toThrow(BadRequestError); + expect(workflowPublicationStatusService.getFailedActivationError).not.toHaveBeenCalled(); + expect(activationErrorsService.get).not.toHaveBeenCalled(); + }); + + it('should return the publication error before the legacy one', async () => { + workflowPublicationStatusService.getFailedActivationError.mockResolvedValue( + 'publication error', + ); + activationErrorsService.get.mockResolvedValue('runtime error'); + + expect(await service.getActivationError(workflowId, user)).toBe('publication error'); + expect(activationErrorsService.get).not.toHaveBeenCalled(); + }); + + it('should fall back to the legacy error when the publication did not fail', async () => { + workflowPublicationStatusService.getFailedActivationError.mockResolvedValue(null); + activationErrorsService.get.mockResolvedValue('runtime error'); + + expect(await service.getActivationError(workflowId, user)).toBe('runtime error'); + expect(workflowPublicationStatusService.getFailedActivationError).toHaveBeenCalledWith( + workflowId, + nodes, + ); + }); + + it('should return null when neither source holds an error', async () => { + workflowPublicationStatusService.getFailedActivationError.mockResolvedValue(null); + activationErrorsService.get.mockResolvedValue(null); + + expect(await service.getActivationError(workflowId, user)).toBeNull(); + }); }); }); }); diff --git a/packages/cli/src/services/__tests__/api-key-auth.strategy.integration.test.ts b/packages/cli/src/services/__tests__/api-key-auth.strategy.integration.test.ts index a082ff766fc..615889fceca 100644 --- a/packages/cli/src/services/__tests__/api-key-auth.strategy.integration.test.ts +++ b/packages/cli/src/services/__tests__/api-key-auth.strategy.integration.test.ts @@ -14,7 +14,7 @@ import { createOwnerWithApiKey } from '@test-integration/db/users'; import { retryUntil } from '@test-integration/retry-until'; import { ApiKeyAuthStrategy } from '../api-key-auth.strategy'; -import { JwtService } from '../jwt.service'; +import { JwtService } from '@n8n/backend-services'; import { API_KEY_ISSUER } from '../public-api-key.service'; const mockReqWith = (apiKey: string): AuthenticatedRequest => @@ -75,7 +75,7 @@ describe('ApiKeyAuthStrategy', () => { describe('buildTokenGrant', () => { it('returns a grant with subject, role scopes, and apiKeyScopes for a valid public API key', async () => { const owner = await createOwnerWithApiKey({ scopes: ['workflow:read', 'workflow:list'] }); - const [{ apiKey }] = owner.apiKeys; + const [{ id: apiKeyId, apiKey }] = owner.apiKeys; const grant = await strategy.buildTokenGrant(apiKey); @@ -85,6 +85,7 @@ describe('ApiKeyAuthStrategy', () => { // role scopes come from the user's role and are independent of the key's apiKeyScopes expect(grant.scopes.length).toBeGreaterThan(1); expect(grant.apiKeyScopes).toEqual(['workflow:read', 'workflow:list']); + expect(grant.apiKeyId).toBe(apiKeyId); }); it('accepts legacy (non-JWT) api keys by looking up the record directly', async () => { diff --git a/packages/cli/src/services/__tests__/deployment-signing-secrets.integration.test.ts b/packages/cli/src/services/__tests__/deployment-signing-secrets.integration.test.ts index b4060c7e745..631fd22438f 100644 --- a/packages/cli/src/services/__tests__/deployment-signing-secrets.integration.test.ts +++ b/packages/cli/src/services/__tests__/deployment-signing-secrets.integration.test.ts @@ -7,7 +7,7 @@ import jsonwebtoken from 'jsonwebtoken'; import { Cipher, InstanceSettings } from 'n8n-core'; import { mock } from 'vitest-mock-extended'; -import { JwtService } from '@/services/jwt.service'; +import { JwtService } from '@n8n/backend-services'; const INSTANCE_ENCRYPTION_KEY = 'signing-secrets-instance-key'; diff --git a/packages/cli/src/services/__tests__/instance-activation.service.test.ts b/packages/cli/src/services/__tests__/instance-activation.service.test.ts deleted file mode 100644 index d36d884b7ec..00000000000 --- a/packages/cli/src/services/__tests__/instance-activation.service.test.ts +++ /dev/null @@ -1,76 +0,0 @@ -import type { Settings, SettingsRepository } from '@n8n/db'; -import { mock } from 'vitest-mock-extended'; - -import { - INSTANCE_ACTIVATED_SETTINGS_KEY, - InstanceActivationService, -} from '@/services/instance-activation.service'; - -const settingsRow = (value: string) => - mock({ key: INSTANCE_ACTIVATED_SETTINGS_KEY, value }); - -describe('InstanceActivationService', () => { - const settingsRepository = mock(); - let service: InstanceActivationService; - - beforeEach(() => { - vi.resetAllMocks(); - service = new InstanceActivationService(settingsRepository); - }); - - describe('when the instance has not activated', () => { - beforeEach(() => { - settingsRepository.findByKey.mockResolvedValue(null); - }); - - it('reports not activated', async () => { - await expect(service.isActivated()).resolves.toBe(false); - await expect(service.getActivatedAt()).resolves.toBeUndefined(); - }); - - // Deliberately not memoised: an instance can activate at any moment, so a negative answer - // has to stay fresh. - it('re-reads the row on every call', async () => { - await service.isActivated(); - await service.isActivated(); - - expect(settingsRepository.findByKey).toHaveBeenCalledTimes(2); - expect(settingsRepository.findByKey).toHaveBeenCalledWith(INSTANCE_ACTIVATED_SETTINGS_KEY); - }); - }); - - describe('when the instance has activated', () => { - it('reports the recorded timestamp', async () => { - settingsRepository.findByKey.mockResolvedValue( - settingsRow(JSON.stringify({ workflowId: 'w1', timestamp: 1_700_000_000 })), - ); - - await expect(service.getActivatedAt()).resolves.toBe(1_700_000_000); - await expect(service.isActivated()).resolves.toBe(true); - }); - - // Activation is monotonic, so the read is worth caching for the life of the process. - it('reads the row only once', async () => { - settingsRepository.findByKey.mockResolvedValue( - settingsRow(JSON.stringify({ timestamp: 1_700_000_000 })), - ); - - await service.getActivatedAt(); - await service.getActivatedAt(); - await service.isActivated(); - - expect(settingsRepository.findByKey).toHaveBeenCalledTimes(1); - }); - - // The row's existence is the signal; a malformed value must not read as "never activated". - it.each([['not json'], [JSON.stringify({})], [JSON.stringify({ timestamp: 'nope' })]])( - 'still reports activated for the unparseable value %p', - async (value) => { - settingsRepository.findByKey.mockResolvedValue(settingsRow(value)); - - await expect(service.isActivated()).resolves.toBe(true); - await expect(service.getActivatedAt()).resolves.toBe(0); - }, - ); - }); -}); diff --git a/packages/cli/src/services/__tests__/ownership.service.test.ts b/packages/cli/src/services/__tests__/ownership.service.test.ts index db116cf4894..d9194907637 100644 --- a/packages/cli/src/services/__tests__/ownership.service.test.ts +++ b/packages/cli/src/services/__tests__/ownership.service.test.ts @@ -70,6 +70,20 @@ describe('OwnershipService', () => { expect(returnedProject).toBe(mockProject); }); + test('should ignore a cached project without an id and read the project from the database', async () => { + const mockProject = Object.assign(new Project(), { id: 'project-id' }); + // A cached value without an id, as a lookup of the key `__proto__` used to return + cacheService.getHashValue.mockResolvedValueOnce({}); + sharedWorkflowRepository.findOneOrFail.mockResolvedValueOnce( + Object.assign(new SharedWorkflow(), { role: 'workflow:owner', project: mockProject }), + ); + + const returnedProject = await ownershipService.getWorkflowProjectCached('some-workflow-id'); + + expect(returnedProject).toBe(mockProject); + expect(sharedWorkflowRepository.findOneOrFail).toHaveBeenCalled(); + }); + test('should throw if no workflow owner project found', async () => { sharedWorkflowRepository.findOneOrFail.mockRejectedValue(new Error()); diff --git a/packages/cli/src/services/__tests__/public-api-key.service.integration.test.ts b/packages/cli/src/services/__tests__/public-api-key.service.integration.test.ts index c45943ca125..aa4bb565990 100644 --- a/packages/cli/src/services/__tests__/public-api-key.service.integration.test.ts +++ b/packages/cli/src/services/__tests__/public-api-key.service.integration.test.ts @@ -11,7 +11,7 @@ import { mock } from 'vitest-mock-extended'; import { createAdminWithApiKey, createOwnerWithApiKey } from '@test-integration/db/users'; -import { JwtService } from '../jwt.service'; +import { JwtService } from '@n8n/backend-services'; import { PublicApiKeyService } from '../public-api-key.service'; const instanceSettings = mock({ encryptionKey: 'test-key' }); diff --git a/packages/cli/src/services/__tests__/public-api-key.service.test.ts b/packages/cli/src/services/__tests__/public-api-key.service.test.ts index 29aab9fb506..bacd15732cd 100644 --- a/packages/cli/src/services/__tests__/public-api-key.service.test.ts +++ b/packages/cli/src/services/__tests__/public-api-key.service.test.ts @@ -6,7 +6,7 @@ import { mock } from 'vitest-mock-extended'; import { BadRequestError, NotFoundError } from '@n8n/errors'; import type { UserManagementMailer } from '@/user-management/email'; -import type { JwtService } from '../jwt.service'; +import type { JwtService } from '@n8n/backend-services'; import { PublicApiKeyService } from '../public-api-key.service'; vi.mock('@n8n/permissions', async () => ({ diff --git a/packages/cli/src/services/__tests__/session-cookie-auth.strategy.integration.test.ts b/packages/cli/src/services/__tests__/session-cookie-auth.strategy.integration.test.ts index 1bef088ef3e..60fe435ac9e 100644 --- a/packages/cli/src/services/__tests__/session-cookie-auth.strategy.integration.test.ts +++ b/packages/cli/src/services/__tests__/session-cookie-auth.strategy.integration.test.ts @@ -63,6 +63,7 @@ describe('SessionCookieAuthStrategy', () => { expect(req.tokenGrant?.subject.id).toBe(owner.id); expect(req.tokenGrant?.scopes.length).toBeGreaterThan(0); expect(req.tokenGrant?.apiKeyScopes?.length).toBeGreaterThan(0); + expect(req.tokenGrant?.apiKeyId).toBeUndefined(); }); it('returns false for an invalid session cookie', async () => { diff --git a/packages/cli/src/services/__tests__/user.service.test.ts b/packages/cli/src/services/__tests__/user.service.test.ts index 959f6ff01cc..024d685f0a9 100644 --- a/packages/cli/src/services/__tests__/user.service.test.ts +++ b/packages/cli/src/services/__tests__/user.service.test.ts @@ -1,5 +1,5 @@ import { InviteUsersRequestDto } from '@n8n/api-types'; -import { type EventService, UrlService, type RoleService } from '@n8n/backend-services'; +import { type EventService, UrlService, type RoleService, JwtService } from '@n8n/backend-services'; import { mockInstance } from '@n8n/backend-test-utils'; import { GlobalConfig } from '@n8n/config'; import { @@ -30,7 +30,6 @@ import { UserService } from '@/services/user.service'; import * as ssoHelpers from '@/sso.ee/sso-helpers'; import type { UserManagementMailer } from '@/user-management/email'; -import { JwtService } from '../jwt.service'; import type { OwnershipTransferService } from '../ownership-transfer/ownership-transfer.service'; import type { OwnershipService } from '../ownership.service'; import type { ProjectService } from '../project.service.ee'; diff --git a/packages/cli/src/services/__tests__/workflow-statistics-rollup.task.test.ts b/packages/cli/src/services/__tests__/workflow-statistics-rollup.task.test.ts index 2fe8ec64d03..f041fcf8774 100644 --- a/packages/cli/src/services/__tests__/workflow-statistics-rollup.task.test.ts +++ b/packages/cli/src/services/__tests__/workflow-statistics-rollup.task.test.ts @@ -21,8 +21,11 @@ describe('WorkflowStatisticsRollupTask', () => { expect(task.name).toBe('workflow-statistics-rollup'); expect(task.schedule).toEqual({ kind: 'interval', intervalSeconds: 5 }); - expect(task.effects).toBe('idempotent'); - expect(task.placement).toEqual({ scope: 'cluster', durable: true, runOnTakeover: true }); + expect(task.target).toEqual({ + scope: 'cluster', + scheduler: { retryOnFailure: true }, + leaderTimer: { runOnTakeover: true }, + }); }); it.each([ @@ -31,23 +34,14 @@ describe('WorkflowStatisticsRollupTask', () => { { leaseDurationSeconds: 2, runBudgetMs: 1000 }, { leaseDurationSeconds: 1, runBudgetMs: 0 }, ])( - 'should pass the signal and a $runBudgetMs ms budget to a durable run with a $leaseDurationSeconds second lease', + 'should pass the signal and a $runBudgetMs ms budget with a $leaseDurationSeconds second lease', async ({ leaseDurationSeconds, runBudgetMs }) => { const task = makeTask({ leaseDurationSeconds }); const signal = new AbortController().signal; - await task.run(signal, { durable: true }); + await task.run(signal); expect(rollupService.rollup).toHaveBeenCalledExactlyOnceWith(signal, runBudgetMs); }, ); - - it('should pass a budget below the interval to an in-memory run, whatever the lease', async () => { - const task = makeTask({ leaseDurationSeconds: 1 }); - const signal = new AbortController().signal; - - await task.run(signal, { durable: false }); - - expect(rollupService.rollup).toHaveBeenCalledExactlyOnceWith(signal, 4000); - }); }); diff --git a/packages/cli/src/services/__tests__/workflow-statistics.service.integration.test.ts b/packages/cli/src/services/__tests__/workflow-statistics.service.integration.test.ts index a3d8c78bc84..c3131929eb3 100644 --- a/packages/cli/src/services/__tests__/workflow-statistics.service.integration.test.ts +++ b/packages/cli/src/services/__tests__/workflow-statistics.service.integration.test.ts @@ -29,7 +29,6 @@ import { type WorkflowExecutionSource, } from 'n8n-workflow'; -import { INSTANCE_ACTIVATED_SETTINGS_KEY } from '@/services/instance-activation.service'; import { OwnershipService } from '@/services/ownership.service'; import { UserService } from '@/services/user.service'; import { WorkflowStatisticsService } from '@/services/workflow-statistics.service'; @@ -97,11 +96,9 @@ describe('WorkflowStatisticsService', () => { beforeEach(async () => { vi.restoreAllMocks(); await testDb.truncate(['WorkflowStatistics', 'WorkflowStatisticsDelta']); - // Clear the instance-level milestone settings; without this the first test to reach a - // milestone leaves the row behind and every later test silently skips emitting it. + // Clear first production failure setting const settingsRepository = Container.get(SettingsRepository); await settingsRepository.delete({ key: 'instance.firstProductionFailure' }); - await settingsRepository.delete({ key: INSTANCE_ACTIVATED_SETTINGS_KEY }); }); test.each(['cli', 'retry', 'trigger', 'webhook', 'evaluation'])( @@ -380,15 +377,6 @@ describe('WorkflowStatisticsService', () => { workflowId: workflow.id, userId: user.id, }); - const activationRow = await Container.get(SettingsRepository).findByKey( - INSTANCE_ACTIVATED_SETTINGS_KEY, - ); - expect(JSON.parse(activationRow!.value)).toEqual({ - projectId: personalProject.id, - workflowId: workflow.id, - userId: user.id, - timestamp: isPostgres ? expect.any(Number) : runData.startedAt.getTime(), - }); }); test('does not update user settings and does not emit first-production-workflow-succeeded for failing executions', async () => { @@ -634,43 +622,6 @@ describe('WorkflowStatisticsService', () => { workflowId: teamWorkflow.id, userId: null, }); - // The activation row is the only signal here — `userActivated` skips team projects. - const activationRow = await Container.get(SettingsRepository).findByKey( - INSTANCE_ACTIVATED_SETTINGS_KEY, - ); - expect(JSON.parse(activationRow!.value)).toEqual({ - projectId: teamProject.id, - workflowId: teamWorkflow.id, - userId: null, - timestamp: expect.any(Number), - }); - }); - - test('records the instance activation exactly once, whatever runs next', async () => { - // ARRANGE - const settingsRepository = Container.get(SettingsRepository); - const secondWorkflow = await createWorkflow({}, user); - const runData: IRun = { - finished: true, - status: 'success', - data: createEmptyRunExecutionData(), - mode: 'internal', - startedAt: new Date(), - storedAt: 'db', - }; - - // ACT - await completeAndFlush(workflowStatisticsService, workflow, runData); - const afterFirst = await settingsRepository.findByKey(INSTANCE_ACTIVATED_SETTINGS_KEY); - - await completeAndFlush(workflowStatisticsService, secondWorkflow, runData); - - // ASSERT — the row still names the *first* workflow, so the second run left it alone - expect(afterFirst).not.toBeNull(); - expect(JSON.parse(afterFirst!.value)).toMatchObject({ workflowId: workflow.id }); - - const afterSecond = await settingsRepository.findByKey(INSTANCE_ACTIVATED_SETTINGS_KEY); - expect(JSON.parse(afterSecond!.value)).toMatchObject({ workflowId: workflow.id }); }); test('emits instance-first-production-workflow-failed with instance owner for team project', async () => { @@ -782,20 +733,6 @@ describe('WorkflowStatisticsService', () => { ); expect(failureEvents).toHaveLength(1); }); - - test('keeps the first value when the instance activation key is inserted twice', async () => { - const settingsRepository = Container.get(SettingsRepository); - - await expect( - settingsRepository.insertIfAbsent(INSTANCE_ACTIVATED_SETTINGS_KEY, 'a'), - ).resolves.toBe(true); - await expect( - settingsRepository.insertIfAbsent(INSTANCE_ACTIVATED_SETTINGS_KEY, 'b'), - ).resolves.toBe(false); - - const row = await settingsRepository.findByKey(INSTANCE_ACTIVATED_SETTINGS_KEY); - expect(row?.value).toBe('a'); - }); }); // The fold is Postgres-only (raw CTE). These exercise its mechanics directly via the repository. diff --git a/packages/cli/src/services/active-workflows.service.ts b/packages/cli/src/services/active-workflows.service.ts index b00079e5505..42fb3e9a8c2 100644 --- a/packages/cli/src/services/active-workflows.service.ts +++ b/packages/cli/src/services/active-workflows.service.ts @@ -1,4 +1,5 @@ import { Logger } from '@n8n/backend-common'; +import { WorkflowsConfig } from '@n8n/config'; import type { User } from '@n8n/db'; import { WorkflowRepository } from '@n8n/db'; import { Service } from '@n8n/di'; @@ -6,6 +7,7 @@ import { hasGlobalScope } from '@n8n/permissions'; import { ActivationErrorsService } from '@/activation-errors.service'; import { BadRequestError } from '@n8n/errors'; +import { WorkflowPublicationStatusService } from '@/workflows/publication/workflow-publication-status.service'; import { WorkflowFinderService } from '@/workflows/workflow-finder.service'; import { WorkflowSharingService } from '@n8n/backend-services'; @@ -17,21 +19,20 @@ export class ActiveWorkflowsService { private readonly workflowSharingService: WorkflowSharingService, private readonly activationErrorsService: ActivationErrorsService, private readonly workflowFinderService: WorkflowFinderService, + private readonly workflowsConfig: WorkflowsConfig, + private readonly workflowPublicationStatusService: WorkflowPublicationStatusService, ) {} async getAllActiveIdsInStorage() { - const activationErrors = await this.activationErrorsService.getAll(); - const activeWorkflowIds = await this.workflowRepository.getActiveIds(); - return activeWorkflowIds.filter((workflowId) => !activationErrors[workflowId]); + return await this.dropActivationFailures(await this.workflowRepository.getActiveIds()); } async getAllActiveIdsFor(user: User) { - const activationErrors = await this.activationErrorsService.getAll(); const activeWorkflowIds = await this.workflowRepository.getActiveIds(); const hasFullAccess = hasGlobalScope(user, 'workflow:read'); if (hasFullAccess) { - return activeWorkflowIds.filter((workflowId) => !activationErrors[workflowId]); + return await this.dropActivationFailures(activeWorkflowIds); } // Every ID here is a workflow the requesting user specifically has @@ -39,8 +40,8 @@ export class ActiveWorkflowsService { const accessibleWorkflowIds = new Set( await this.workflowSharingService.getSharedWorkflowIds(user, { scopes: ['workflow:read'] }), ); - return activeWorkflowIds.filter( - (workflowId) => accessibleWorkflowIds.has(workflowId) && !activationErrors[workflowId], + return await this.dropActivationFailures( + activeWorkflowIds.filter((workflowId) => accessibleWorkflowIds.has(workflowId)), ); } @@ -57,6 +58,32 @@ export class ActiveWorkflowsService { throw new BadRequestError(`Workflow with ID "${workflowId}" could not be found.`); } + // A failed republish never clears the legacy cache. Read the publication error first + // so a stale runtime error cannot mask it. + if (this.workflowsConfig.useWorkflowPublicationService) { + const publicationError = await this.workflowPublicationStatusService.getFailedActivationError( + workflowId, + workflow.nodes, + ); + if (publicationError !== null) return publicationError; + } return await this.activationErrorsService.get(workflowId); } + + /** + * Drops the ids with a recorded activation failure. A partial publication keeps + * its triggers running, so only a failed publication is dropped. Its rows mean + * zero live triggers on every path but one. A policy-refused republish marks + * every trigger failed, and the previous version keeps running until a restart + * or the next publish. + */ + private async dropActivationFailures(workflowIds: string[]) { + const activationErrors = await this.activationErrorsService.getAll(); + const candidates = workflowIds.filter((workflowId) => !activationErrors[workflowId]); + if (!this.workflowsConfig.useWorkflowPublicationService) return candidates; + + const statuses = + await this.workflowPublicationStatusService.getListStatusesByWorkflowIds(candidates); + return candidates.filter((workflowId) => statuses.get(workflowId) !== 'failed'); + } } diff --git a/packages/cli/src/services/ai.service.ts b/packages/cli/src/services/ai.service.ts index b255efd74f0..ce35ba2bc3f 100644 --- a/packages/cli/src/services/ai.service.ts +++ b/packages/cli/src/services/ai.service.ts @@ -91,10 +91,4 @@ export class AiService { { retryOnTimeout: false }, ); } - - /** Forfeit the remaining Instance AI quota for this instance. Idempotent server-side. */ - async lockInstanceAiQuota(user: IUser, activatedAt?: number) { - const client = await this.getClient(); - return await client.lockInstanceAiQuota(user, { activatedAt }); - } } diff --git a/packages/cli/src/services/api-key-auth.strategy.ts b/packages/cli/src/services/api-key-auth.strategy.ts index 71a9059fee1..df7d713e173 100644 --- a/packages/cli/src/services/api-key-auth.strategy.ts +++ b/packages/cli/src/services/api-key-auth.strategy.ts @@ -8,8 +8,7 @@ import { TokenExpiredError } from 'jsonwebtoken'; import { isApiKeyAuthEnabled } from '@/public-api'; import type { AuthStrategy, AuthStrategyOptions } from './auth-strategy.types'; -import { JwtService } from './jwt.service'; -import { API_KEY_PURPOSES } from './token-purposes'; +import { JwtService, API_KEY_PURPOSES } from '@n8n/backend-services'; import { API_KEY_AUDIENCE, API_KEY_ISSUER, PREFIX_LEGACY_API_KEY } from './public-api-key.service'; const API_KEY_HEADER = 'x-n8n-api-key'; @@ -66,6 +65,7 @@ export class ApiKeyAuthStrategy implements AuthStrategy { scopes: apiKeyRecord.user.role.scopes.map((s) => s.slug), subject: apiKeyRecord.user, apiKeyScopes: apiKeyRecord.scopes ?? [], + apiKeyId: apiKeyRecord.id, }; } diff --git a/packages/cli/src/services/instance-activation.service.ts b/packages/cli/src/services/instance-activation.service.ts deleted file mode 100644 index b0178b8ed02..00000000000 --- a/packages/cli/src/services/instance-activation.service.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { SettingsRepository } from '@n8n/db'; -import { Service } from '@n8n/di'; - -/** Settings key written once by {@link WorkflowStatisticsService} at the instance's activation. */ -export const INSTANCE_ACTIVATED_SETTINGS_KEY = 'instance.firstProductionSuccess'; - -type ActivationRecord = { timestamp?: number }; - -/** - * Reads the instance's activation moment: its first successful production execution, for any - * project type. Written exactly once by {@link WorkflowStatisticsService}; this is the read side. - * - * Activation is monotonic — an instance never de-activates — so a `true` answer is memoised for - * the life of the process. A `false` answer is not, since it can change at any moment. - */ -@Service() -export class InstanceActivationService { - /** Set once activation is observed; `undefined` means "not observed yet", never "not activated". */ - private activatedAt: number | undefined; - - constructor(private readonly settingsRepository: SettingsRepository) {} - - async isActivated(): Promise { - return (await this.getActivatedAt()) !== undefined; - } - - async getActivatedAt(): Promise { - if (this.activatedAt !== undefined) return this.activatedAt; - - const row = await this.settingsRepository.findByKey(INSTANCE_ACTIVATED_SETTINGS_KEY); - if (!row) return undefined; - - this.activatedAt = this.parseTimestamp(row.value); - return this.activatedAt; - } - - /** - * The row's timestamp, or a non-undefined fallback. The row's existence is what marks the - * instance activated, so a malformed value must not read as "never activated" — it only costs - * the precise moment, which is used for telemetry. - */ - private parseTimestamp(value: string): number { - try { - const parsed = JSON.parse(value) as ActivationRecord; - if (typeof parsed?.timestamp === 'number') return parsed.timestamp; - } catch { - // Fall through to the sentinel below. - } - return 0; - } -} diff --git a/packages/cli/src/services/ownership-transfer/ownership-transfer.manifest.json b/packages/cli/src/services/ownership-transfer/ownership-transfer.manifest.json index 4fba8b13d67..c51720acc76 100644 --- a/packages/cli/src/services/ownership-transfer/ownership-transfer.manifest.json +++ b/packages/cli/src/services/ownership-transfer/ownership-transfer.manifest.json @@ -89,6 +89,11 @@ "path": "packages/cli/src/modules/promotions.ee/database/entities/promotion-connection-project.entity.ts", "reason": "Promotion configuration for the project (which connection it is linked to), not user data. Dropped via the projectId FK cascade when the source project is deleted, as in ownership-transfer flows." }, + { + "name": "Skill", + "path": "packages/cli/src/modules/agents/entities/skill.entity.ts", + "reason": "Project-scoped skills belong to the project's agents, which are not transferred either (see Agent); both are dropped via FK cascade. Instance skills carry no projectId." + }, { "name": "AiPreference", "path": "packages/@n8n/db/src/entities/ai-preference.ts", diff --git a/packages/cli/src/services/ownership.service.ts b/packages/cli/src/services/ownership.service.ts index f772df8d066..0288167fa49 100644 --- a/packages/cli/src/services/ownership.service.ts +++ b/packages/cli/src/services/ownership.service.ts @@ -34,6 +34,23 @@ export class OwnershipService { private settingsRepository: SettingsRepository, ) {} + // To make use of the cache service we should store POJOs, these + // methods should be used to create copies of the entities + // converting them into plain JavaScript objects + // Ideally our data entities wouldn't be classes, but plain + // interfaces and therefore pojos adhering to these interfaces + copyProject(project: Project): Partial { + return { + ...project, + }; + } + + reconstructProject(project: Partial): Project | undefined { + if (typeof project?.id !== 'string') { + return undefined; + } + return Object.assign(new Project(), project); + } copyUser(user: User): Partial { return { ...user, diff --git a/packages/cli/src/services/pruning/__tests__/activity-pruning.task.test.ts b/packages/cli/src/services/pruning/__tests__/activity-pruning.task.test.ts index 96ffed27949..427630dcce6 100644 --- a/packages/cli/src/services/pruning/__tests__/activity-pruning.task.test.ts +++ b/packages/cli/src/services/pruning/__tests__/activity-pruning.task.test.ts @@ -25,10 +25,10 @@ describe('ActivityPruningTask', () => { }); it('runs durably, on any main, and on the fallback timer as soon as a leader takes over', () => { - expect(taskWith().placement).toEqual({ + expect(taskWith().target).toEqual({ scope: 'cluster', - durable: true, - runOnTakeover: true, + scheduler: { retryOnFailure: true }, + leaderTimer: { runOnTakeover: true }, }); }); diff --git a/packages/cli/src/services/pruning/__tests__/execution-pruning-hard-delete.task.test.ts b/packages/cli/src/services/pruning/__tests__/execution-pruning-hard-delete.task.test.ts index ccd99a75000..5c696ed0ae6 100644 --- a/packages/cli/src/services/pruning/__tests__/execution-pruning-hard-delete.task.test.ts +++ b/packages/cli/src/services/pruning/__tests__/execution-pruning-hard-delete.task.test.ts @@ -17,10 +17,11 @@ describe('ExecutionPruningHardDeleteTask', () => { it('should declare the configured hard-delete cadence', () => { expect(task.name).toBe('execution-pruning-hard-delete'); expect(task.schedule).toEqual({ kind: 'interval', intervalSeconds: 900 }); - expect(task.effects).toBe('idempotent'); - expect(task.placement).toEqual({ scope: 'cluster', durable: true }); - expect(task.timeoutSeconds).toBe(900); - expect(task.retryDelaySeconds).toBe(1); + expect(task.target).toEqual({ + scope: 'cluster', + scheduler: { retryOnFailure: true, timeoutSeconds: 900 }, + leaderTimer: { retryDelaySeconds: 1 }, + }); }); it('should hard-delete with the run signal', async () => { diff --git a/packages/cli/src/services/pruning/__tests__/execution-pruning-soft-delete.task.test.ts b/packages/cli/src/services/pruning/__tests__/execution-pruning-soft-delete.task.test.ts index 41abbf4eddb..be7b2fa2571 100644 --- a/packages/cli/src/services/pruning/__tests__/execution-pruning-soft-delete.task.test.ts +++ b/packages/cli/src/services/pruning/__tests__/execution-pruning-soft-delete.task.test.ts @@ -22,8 +22,10 @@ describe('ExecutionPruningSoftDeleteTask', () => { it('should declare the configured soft-delete cadence', () => { expect(task.name).toBe('execution-pruning-soft-delete'); expect(task.schedule).toEqual({ kind: 'interval', intervalSeconds: 3600 }); - expect(task.effects).toBe('idempotent'); - expect(task.placement).toEqual({ scope: 'cluster', durable: true }); + expect(task.target).toEqual({ + scope: 'cluster', + scheduler: { retryOnFailure: true, timeoutSeconds: 600 }, + }); }); it.each([ @@ -37,7 +39,8 @@ describe('ExecutionPruningSoftDeleteTask', () => { const database = mock({ type, postgresdb: { statementTimeoutMs } }); expect( - new ExecutionPruningSoftDeleteTask(config, database, pruningService).timeoutSeconds, + new ExecutionPruningSoftDeleteTask(config, database, pruningService).target.scheduler + .timeoutSeconds, ).toBe(timeoutSeconds); }, ); diff --git a/packages/cli/src/services/pruning/__tests__/workflow-history-compaction-optimize.task.test.ts b/packages/cli/src/services/pruning/__tests__/workflow-history-compaction-optimize.task.test.ts index ecdf3a90bb5..79d749fdb26 100644 --- a/packages/cli/src/services/pruning/__tests__/workflow-history-compaction-optimize.task.test.ts +++ b/packages/cli/src/services/pruning/__tests__/workflow-history-compaction-optimize.task.test.ts @@ -17,12 +17,14 @@ describe('WorkflowHistoryCompactionOptimizeTask', () => { it('should declare a cadence of half the optimizing window', () => { expect(task.name).toBe('workflow-history-compaction-optimize'); expect(task.schedule).toEqual({ kind: 'interval', intervalSeconds: 3600 }); - expect(task.effects).toBe('idempotent'); - expect(task.placement).toEqual({ scope: 'cluster', durable: true }); + expect(task.target).toEqual({ + scope: 'cluster', + scheduler: { retryOnFailure: true, timeoutSeconds: 1800 }, + }); }); it('should outlast the default task timeout', () => { - expect(task.timeoutSeconds).toBe(1800); + expect(task.target.scheduler?.timeoutSeconds).toBe(1800); }); it('should optimize histories on run, handing the pass its abort signal', async () => { diff --git a/packages/cli/src/services/pruning/__tests__/workflow-history-compaction-trim.task.test.ts b/packages/cli/src/services/pruning/__tests__/workflow-history-compaction-trim.task.test.ts index 8454d0f3311..b64577e9fc1 100644 --- a/packages/cli/src/services/pruning/__tests__/workflow-history-compaction-trim.task.test.ts +++ b/packages/cli/src/services/pruning/__tests__/workflow-history-compaction-trim.task.test.ts @@ -11,16 +11,18 @@ describe('WorkflowHistoryCompactionTrimTask', () => { it('should declare a daily cron in the instance timezone and run durably', () => { expect(task.name).toBe('workflow-history-compaction-trim'); expect(task.schedule).toEqual({ kind: 'cron', cronExpression: '0 3 * * *', timezone: null }); - expect(task.effects).toBe('idempotent'); - expect(task.placement).toEqual({ scope: 'cluster', durable: true }); + expect(task.target).toEqual({ + scope: 'cluster', + scheduler: { retryOnFailure: true, missedAfterSeconds: 3600, timeoutSeconds: 3600 }, + }); }); it('should keep a missed occurrence claimable for an hour', () => { - expect(task.misfireGraceSeconds).toBe(Time.hours.toSeconds); + expect(task.target.scheduler?.missedAfterSeconds).toBe(Time.hours.toSeconds); }); it('should outlast the default task timeout', () => { - expect(task.timeoutSeconds).toBe(3600); + expect(task.target.scheduler?.timeoutSeconds).toBe(3600); }); it('should trim on run, handing the pass its abort signal', async () => { diff --git a/packages/cli/src/services/pruning/__tests__/workflow-history-compaction.service.test.ts b/packages/cli/src/services/pruning/__tests__/workflow-history-compaction.service.test.ts index 1a32a3eff96..fb7ede7076f 100644 --- a/packages/cli/src/services/pruning/__tests__/workflow-history-compaction.service.test.ts +++ b/packages/cli/src/services/pruning/__tests__/workflow-history-compaction.service.test.ts @@ -2,16 +2,12 @@ import type { EventService } from '@n8n/backend-services'; import { mockLogger } from '@n8n/backend-test-utils'; import type { GlobalConfig, WorkflowHistoryCompactionConfig } from '@n8n/config'; import { Time } from '@n8n/constants'; -import type { DbConnection, WorkflowHistoryRepository } from '@n8n/db'; -import type { InstanceSettings } from 'n8n-core'; +import type { WorkflowHistoryRepository } from '@n8n/db'; import { mock } from 'vitest-mock-extended'; import { WorkflowHistoryCompactionService } from '../workflow-history-compaction.service'; describe('WorkflowHistoryCompactionService', () => { - const dbConnection = mock({ - connectionState: { migrated: true }, - }); const config = mock({ batchDelayMs: 1000, batchSize: 1000, @@ -19,8 +15,6 @@ describe('WorkflowHistoryCompactionService', () => { optimizingTimeWindowHours: 2, trimmingMinimumAgeDays: 7, trimmingTimeWindowDays: 2, - trimOnStartUp: false, - skipOnStartUp: false, }); const globalConfig = mock({ generic: { timezone: 'Europe/Berlin' }, @@ -38,167 +32,13 @@ describe('WorkflowHistoryCompactionService', () => { vi.useRealTimers(); }); - describe('init', () => { - it('should start compacting on main instance that is the leader', () => { - const compactingService = new WorkflowHistoryCompactionService( - config, - globalConfig, - mockLogger(), - mock({ isLeader: true, isMultiMain: true }), - dbConnection, - mock(), - mock(), - ); - const runStartupCompaction = vi.spyOn(compactingService, 'runStartupCompaction'); - - compactingService.init(); - - expect(runStartupCompaction).toHaveBeenCalled(); - }); - - it('should not start pruning on main instance that is a follower', () => { - const compactingService = new WorkflowHistoryCompactionService( - config, - globalConfig, - mockLogger(), - mock({ isLeader: false, isMultiMain: true }), - dbConnection, - mock(), - mock(), - ); - const runStartupCompaction = vi.spyOn(compactingService, 'runStartupCompaction'); - - compactingService.init(); - - expect(runStartupCompaction).not.toHaveBeenCalled(); - }); - }); - - it('should skip trimming if pruneTime < trimAge', () => { - const compactingService = new WorkflowHistoryCompactionService( - { ...config, trimOnStartUp: true }, - { ...globalConfig, workflowHistory: { pruneTime: 24 } }, - mockLogger(), - mock({ isLeader: true, instanceType: 'main', isMultiMain: true }), - dbConnection, - mock(), - mock(), - ); - - vi.spyOn(compactingService, 'compactHistories').mockImplementation((() => {}) as never); - - const trimLongRunningHistoriesSpy = vi.spyOn(compactingService, 'trimLongRunningHistories'); - - compactingService.runStartupCompaction(); - - expect(trimLongRunningHistoriesSpy).not.toBeCalled(); - }); - it('should not skip trimming if pruneTime > trimAge', () => { - const compactingService = new WorkflowHistoryCompactionService( - { ...config, trimOnStartUp: true }, - { ...globalConfig, workflowHistory: { pruneTime: 8 * 24 } }, - mockLogger(), - mock({ isLeader: true, instanceType: 'main', isMultiMain: true }), - dbConnection, - mock(), - mock(), - ); - - vi.spyOn(compactingService, 'optimizeHistories').mockImplementation((() => {}) as never); - const trimLongRunningHistoriesSpy = vi - .spyOn(compactingService, 'trimLongRunningHistories') - .mockImplementation((() => {}) as never); - - compactingService.runStartupCompaction(); - - expect(trimLongRunningHistoriesSpy).toBeCalled(); - }); - - it('should compact on start up ', () => { - const compactingService = new WorkflowHistoryCompactionService( - config, - globalConfig, - mockLogger(), - mock({ isLeader: true, instanceType: 'main', isMultiMain: true }), - dbConnection, - mock(), - mock(), - ); - - const optimizeHistoriesSpy = vi - .spyOn(compactingService, 'optimizeHistories') - .mockImplementation((() => {}) as never); - const trimLongRunningHistoriesSpy = vi - .spyOn(compactingService, 'trimLongRunningHistories') - .mockImplementation((() => {}) as never); - - compactingService.runStartupCompaction(); - - expect(optimizeHistoriesSpy).toHaveBeenCalled(); - expect(trimLongRunningHistoriesSpy).not.toHaveBeenCalled(); - }); - - it('should not compact on start up if skipOnStartUp is set', () => { - const compactingService = new WorkflowHistoryCompactionService( - { ...config, skipOnStartUp: true, trimOnStartUp: true }, - globalConfig, - mockLogger(), - mock({ isLeader: true, instanceType: 'main', isMultiMain: true }), - dbConnection, - mock(), - mock(), - ); - - const optimizeHistoriesSpy = vi - .spyOn(compactingService, 'optimizeHistories') - .mockImplementation((() => {}) as never); - const trimLongRunningHistoriesSpy = vi - .spyOn(compactingService, 'trimLongRunningHistories') - .mockImplementation((() => {}) as never); - - compactingService.runStartupCompaction(); - - expect(optimizeHistoriesSpy).not.toHaveBeenCalled(); - expect(trimLongRunningHistoriesSpy).not.toHaveBeenCalled(); - }); - - it('should trim on start up if flag is provided', () => { - const compactingService = new WorkflowHistoryCompactionService( - { ...config, trimOnStartUp: true }, - globalConfig, - mockLogger(), - mock({ isLeader: true, instanceType: 'main', isMultiMain: true }), - dbConnection, - mock(), - mock(), - ); - - const optimizeHistoriesSpy = vi - .spyOn(compactingService, 'optimizeHistories') - .mockImplementation((() => {}) as never); - const trimLongRunningHistoriesSpy = vi - .spyOn(compactingService, 'trimLongRunningHistories') - .mockImplementation((() => {}) as never); - - compactingService.runStartupCompaction(); - - expect(trimLongRunningHistoriesSpy).toHaveBeenCalled(); - // should still call recent history compaction - expect(optimizeHistoriesSpy).toHaveBeenCalled(); - }); - describe('compactHistories', () => { - const createService = ( - workflowHistoryRepository: WorkflowHistoryRepository, - isLeader = true, - ) => { + const createService = (workflowHistoryRepository: WorkflowHistoryRepository) => { const eventService = mock(); const compactingService = new WorkflowHistoryCompactionService( config, globalConfig, mockLogger(), - mock({ isLeader, instanceType: 'main', isMultiMain: true }), - dbConnection, workflowHistoryRepository, eventService, ); @@ -219,17 +59,6 @@ describe('WorkflowHistoryCompactionService', () => { ); }); - it('should optimize on a main that is not the leader', async () => { - const workflowHistoryRepository = mock(); - workflowHistoryRepository.getWorkflowIdsInRange.mockResolvedValue(['wf-1']); - workflowHistoryRepository.pruneHistory.mockResolvedValue({ seen: 2, deleted: 1 }); - const { compactingService } = createService(workflowHistoryRepository, false); - - await compactingService.optimizeHistories(new AbortController().signal); - - expect(workflowHistoryRepository.pruneHistory).toHaveBeenCalledOnce(); - }); - it('should trim over the window between trimmingMinimumAge and the time window, anchored to the start of the day in the instance timezone', async () => { // 03:00 UTC on 10 November is 04:00 in Berlin, whose day started at 23:00 UTC the day before. vi.setSystemTime(new Date('2026-11-10T03:00:00.000Z')); @@ -291,8 +120,6 @@ describe('WorkflowHistoryCompactionService', () => { config, mock({ generic: { timezone }, workflowHistory: { pruneTime: -1 } }), mockLogger(), - mock({ isLeader: true, instanceType: 'main', isMultiMain: true }), - dbConnection, workflowHistoryRepository, mock(), ); @@ -366,8 +193,6 @@ describe('WorkflowHistoryCompactionService', () => { abortConfig, globalConfig, mockLogger(), - mock({ isLeader: true, instanceType: 'main', isMultiMain: true }), - dbConnection, workflowHistoryRepository, eventService, ); @@ -425,21 +250,5 @@ describe('WorkflowHistoryCompactionService', () => { expect.objectContaining({ workflowsProcessed: 2 }), ); }); - - it('should hand a detached startup pass a signal that stepdown aborts', () => { - const { compactingService } = setupService([]); - const optimizeHistories = vi - .spyOn(compactingService, 'optimizeHistories') - .mockResolvedValue(undefined); - - compactingService.runStartupCompaction(); - - const signal = optimizeHistories.mock.calls[0][0]; - expect(signal.aborted).toBe(false); - - compactingService.stopStartupCompaction(); - - expect(signal.aborted).toBe(true); - }); }); }); diff --git a/packages/cli/src/services/pruning/__tests__/workflow-history-pruning.task.test.ts b/packages/cli/src/services/pruning/__tests__/workflow-history-pruning.task.test.ts index 2c8a34fcd48..410413569eb 100644 --- a/packages/cli/src/services/pruning/__tests__/workflow-history-pruning.task.test.ts +++ b/packages/cli/src/services/pruning/__tests__/workflow-history-pruning.task.test.ts @@ -17,8 +17,11 @@ describe('WorkflowHistoryPruningTask', () => { it('should declare an hourly idempotent durable cluster task that runs on takeover', () => { expect(task.name).toBe('workflow-history-pruning'); expect(task.schedule).toEqual({ kind: 'interval', intervalSeconds: 3600 }); - expect(task.effects).toBe('idempotent'); - expect(task.placement).toEqual({ scope: 'cluster', durable: true, runOnTakeover: true }); + expect(task.target).toEqual({ + scope: 'cluster', + scheduler: { retryOnFailure: true, timeoutSeconds: 600 }, + leaderTimer: { runOnTakeover: true }, + }); }); it.each([ @@ -31,9 +34,10 @@ describe('WorkflowHistoryPruningTask', () => { ({ type, statementTimeoutMs, timeoutSeconds }) => { const database = mock({ type, postgresdb: { statementTimeoutMs } }); - expect(new WorkflowHistoryPruningTask(database, workflowHistoryManager).timeoutSeconds).toBe( - timeoutSeconds, - ); + expect( + new WorkflowHistoryPruningTask(database, workflowHistoryManager).target.scheduler + .timeoutSeconds, + ).toBe(timeoutSeconds); }, ); diff --git a/packages/cli/src/services/pruning/activity-pruning.task.ts b/packages/cli/src/services/pruning/activity-pruning.task.ts index 0955d5a5b43..cbbbf7fba46 100644 --- a/packages/cli/src/services/pruning/activity-pruning.task.ts +++ b/packages/cli/src/services/pruning/activity-pruning.task.ts @@ -2,8 +2,8 @@ import { Logger } from '@n8n/backend-common'; import { ActivityLogConfig } from '@n8n/config'; import { Time } from '@n8n/constants'; import { ActivityEventRepository } from '@n8n/db'; -import { intervalFromSeconds, SystemTask } from '@n8n/decorators'; -import type { SystemTaskEffects, SystemTaskPlacement, SystemTaskSchedule } from '@n8n/decorators'; +import { clusterTarget, intervalFromSeconds, SystemTask } from '@n8n/decorators'; +import type { SystemTaskSchedule } from '@n8n/decorators'; /** Activity accrues steadily rather than in bursts, so an hourly sweep is enough to bound it. */ const sweepIntervalSeconds = 1 * Time.hours.toSeconds; @@ -19,15 +19,16 @@ export class ActivityPruningTask implements SystemTask { schedule: SystemTaskSchedule = intervalFromSeconds(sweepIntervalSeconds); - /** Deleting rows already deleted is a no-op, so a repeated or retried run is harmless. */ - effects: SystemTaskEffects = 'idempotent'; - - placement: SystemTaskPlacement = { - scope: 'cluster', - durable: true, - /** A new leader inherits whatever backlog built up while nobody was sweeping. */ - runOnTakeover: true, - }; + target = clusterTarget({ + scheduler: { + /** Deleting rows already deleted is a no-op, so a repeated or retried run is harmless. */ + retryOnFailure: true, + }, + leaderTimer: { + /** A new leader inherits whatever backlog built up while nobody was sweeping. */ + runOnTakeover: true, + }, + }); constructor( private readonly logger: Logger, diff --git a/packages/cli/src/services/pruning/execution-pruning-hard-delete.task.ts b/packages/cli/src/services/pruning/execution-pruning-hard-delete.task.ts index 89d5b22036f..4f9847d1eda 100644 --- a/packages/cli/src/services/pruning/execution-pruning-hard-delete.task.ts +++ b/packages/cli/src/services/pruning/execution-pruning-hard-delete.task.ts @@ -1,7 +1,7 @@ import { ExecutionsConfig } from '@n8n/config'; import { Time } from '@n8n/constants'; -import { intervalFromSeconds, SystemTask } from '@n8n/decorators'; -import type { SystemTaskEffects, SystemTaskPlacement, SystemTaskSchedule } from '@n8n/decorators'; +import { clusterTarget, intervalFromSeconds, SystemTask } from '@n8n/decorators'; +import type { SystemTaskSchedule } from '@n8n/decorators'; import { ExecutionsPruningService } from './executions-pruning.service'; @@ -18,16 +18,18 @@ export class ExecutionPruningHardDeleteTask implements SystemTask { readonly schedule: SystemTaskSchedule = intervalFromSeconds(this.intervalSeconds); - readonly effects: SystemTaskEffects = 'idempotent'; - - readonly placement: SystemTaskPlacement = { scope: 'cluster', durable: true }; - - // A run that is behind ends before the next occurrence is due. The drain stops - // at the pause and returns, so the occurrence completes with result `timed_out`. - readonly timeoutSeconds = this.intervalSeconds; - - // The in-memory timer retries a failed run after one second, as the old timer did. - readonly retryDelaySeconds = 1; + readonly target = clusterTarget({ + scheduler: { + retryOnFailure: true, + // A run that is behind ends before the next occurrence is due. The drain stops + // at the pause and returns, so the occurrence completes with result `timed_out`. + timeoutSeconds: this.intervalSeconds, + }, + leaderTimer: { + // A failed run retries after one second, as the old timer did. + retryDelaySeconds: 1, + }, + }); constructor( private readonly executionsConfig: ExecutionsConfig, diff --git a/packages/cli/src/services/pruning/execution-pruning-soft-delete.task.ts b/packages/cli/src/services/pruning/execution-pruning-soft-delete.task.ts index 5551b1e28ca..d095730039b 100644 --- a/packages/cli/src/services/pruning/execution-pruning-soft-delete.task.ts +++ b/packages/cli/src/services/pruning/execution-pruning-soft-delete.task.ts @@ -1,7 +1,7 @@ import { DatabaseConfig, ExecutionsConfig, statementTimeoutSeconds } from '@n8n/config'; import { Time } from '@n8n/constants'; -import { intervalFromSeconds, SystemTask, timeoutAfterLimit } from '@n8n/decorators'; -import type { SystemTaskEffects, SystemTaskPlacement, SystemTaskSchedule } from '@n8n/decorators'; +import { clusterTarget, intervalFromSeconds, SystemTask, timeoutAfterLimit } from '@n8n/decorators'; +import type { SystemTaskSchedule } from '@n8n/decorators'; import { ExecutionsPruningService } from './executions-pruning.service'; @@ -17,17 +17,18 @@ export class ExecutionPruningSoftDeleteTask implements SystemTask { this.executionsConfig.pruneDataIntervals.softDelete * Time.minutes.toSeconds, ); - readonly effects: SystemTaskEffects = 'idempotent'; - - readonly placement: SystemTaskPlacement = { scope: 'cluster', durable: true }; - - // One UPDATE that ignores the signal. A timeout that stops the run before the - // UPDATE ends lets the next run start a second one, so it waits for the - // statement timeout first. - readonly timeoutSeconds = timeoutAfterLimit( - statementTimeoutSeconds(this.databaseConfig), - 5 * Time.minutes.toSeconds, - ); + readonly target = clusterTarget({ + scheduler: { + retryOnFailure: true, + // One UPDATE that ignores the signal. A timeout that stops the run before the + // UPDATE ends lets the next run start a second one, so it waits for the + // statement timeout first. + timeoutSeconds: timeoutAfterLimit( + statementTimeoutSeconds(this.databaseConfig), + 5 * Time.minutes.toSeconds, + ), + }, + }); constructor( private readonly executionsConfig: ExecutionsConfig, diff --git a/packages/cli/src/services/pruning/workflow-history-compaction-optimize.task.ts b/packages/cli/src/services/pruning/workflow-history-compaction-optimize.task.ts index b40bf5d0d31..bd06692caf4 100644 --- a/packages/cli/src/services/pruning/workflow-history-compaction-optimize.task.ts +++ b/packages/cli/src/services/pruning/workflow-history-compaction-optimize.task.ts @@ -1,7 +1,7 @@ import { WorkflowHistoryCompactionConfig } from '@n8n/config'; import { Time } from '@n8n/constants'; -import { intervalFromSeconds, SystemTask } from '@n8n/decorators'; -import type { SystemTaskEffects, SystemTaskPlacement, SystemTaskSchedule } from '@n8n/decorators'; +import { clusterTarget, intervalFromSeconds, SystemTask } from '@n8n/decorators'; +import type { SystemTaskSchedule } from '@n8n/decorators'; import { WorkflowHistoryCompactionService } from './workflow-history-compaction.service'; @@ -19,13 +19,14 @@ export class WorkflowHistoryCompactionOptimizeTask implements SystemTask { (this.config.optimizingTimeWindowHours / 2) * Time.hours.toSeconds, ); - readonly effects: SystemTaskEffects = 'idempotent'; - - readonly placement: SystemTaskPlacement = { scope: 'cluster', durable: true }; - - // A run takes 7 to 13 minutes on a large instance, and the workflows it does not - // reach get only one more run. - readonly timeoutSeconds = 30 * Time.minutes.toSeconds; + readonly target = clusterTarget({ + scheduler: { + retryOnFailure: true, + // A run takes 7 to 13 minutes on a large instance, and the workflows it does not + // reach get only one more run. + timeoutSeconds: 30 * Time.minutes.toSeconds, + }, + }); constructor( private readonly config: WorkflowHistoryCompactionConfig, diff --git a/packages/cli/src/services/pruning/workflow-history-compaction-trim.task.ts b/packages/cli/src/services/pruning/workflow-history-compaction-trim.task.ts index d7eabbe6b3c..c204876f19f 100644 --- a/packages/cli/src/services/pruning/workflow-history-compaction-trim.task.ts +++ b/packages/cli/src/services/pruning/workflow-history-compaction-trim.task.ts @@ -1,6 +1,6 @@ import { Time } from '@n8n/constants'; -import { SystemTask } from '@n8n/decorators'; -import type { SystemTaskEffects, SystemTaskPlacement, SystemTaskSchedule } from '@n8n/decorators'; +import { clusterTarget, SystemTask } from '@n8n/decorators'; +import type { SystemTaskSchedule } from '@n8n/decorators'; import { WorkflowHistoryCompactionService } from './workflow-history-compaction.service'; @@ -19,16 +19,16 @@ export class WorkflowHistoryCompactionTrimTask implements SystemTask { timezone: null, }; - readonly effects: SystemTaskEffects = 'idempotent'; - - // A late run on the same day reads the same window, so an hour carries the - // occurrence across a restart at 03:00 instead of losing the day's trim. - readonly misfireGraceSeconds = Time.hours.toSeconds; - - readonly placement: SystemTaskPlacement = { scope: 'cluster', durable: true }; - - // Runs the same pass as the optimize task, over a window many times wider. - readonly timeoutSeconds = Time.hours.toSeconds; + readonly target = clusterTarget({ + scheduler: { + retryOnFailure: true, + // A late run on the same day reads the same window, so an hour carries the + // occurrence across a restart at 03:00 instead of losing the day's trim. + missedAfterSeconds: Time.hours.toSeconds, + // Runs the same pass as the optimize task, over a window many times wider. + timeoutSeconds: Time.hours.toSeconds, + }, + }); constructor(private readonly compactionService: WorkflowHistoryCompactionService) {} diff --git a/packages/cli/src/services/pruning/workflow-history-compaction.service.ts b/packages/cli/src/services/pruning/workflow-history-compaction.service.ts index d215de08826..b45af2bcb82 100644 --- a/packages/cli/src/services/pruning/workflow-history-compaction.service.ts +++ b/packages/cli/src/services/pruning/workflow-history-compaction.service.ts @@ -2,19 +2,16 @@ import { Logger } from '@n8n/backend-common'; import { EventService } from '@n8n/backend-services'; import { GlobalConfig, WorkflowHistoryCompactionConfig } from '@n8n/config'; import { Time } from '@n8n/constants'; -import { DbConnection, WorkflowHistoryRepository } from '@n8n/db'; -import { OnLeaderStepdown, OnLeaderTakeover, OnShutdown } from '@n8n/decorators'; +import { WorkflowHistoryRepository } from '@n8n/db'; import { Service } from '@n8n/di'; -import { InstanceSettings } from 'n8n-core'; import { ensureError } from '@n8n/utils/errors/ensure-error'; import { sleep } from '@n8n/utils/sleep'; import { DateTime } from 'luxon'; import { DiffMetaData, DiffRule, RULES, SKIP_RULES } from 'n8n-workflow'; -import { strict } from 'node:assert'; import { RelayEventMap } from '@/events/maps/relay.event-map'; -import { getCompactionWindowDeltas, isTrimmingEnabled } from './workflow-history-compaction.utils'; +import { getCompactionWindowDeltas } from './workflow-history-compaction.utils'; /** * Responsible for compacting auto saved workflow history entries in the database. @@ -51,62 +48,16 @@ export class WorkflowHistoryCompactionService { private isOptimizingHistories = false; private isTrimmingHistories = false; - /** Aborts the detached startup passes, which no system task run owns. */ - private startupAbort = new AbortController(); - constructor( private readonly config: WorkflowHistoryCompactionConfig, private readonly globalConfig: GlobalConfig, private readonly logger: Logger, - private readonly instanceSettings: InstanceSettings, - private readonly dbConnection: DbConnection, private readonly workflowHistoryRepository: WorkflowHistoryRepository, private readonly eventService: EventService, ) { this.logger = this.logger.scoped('workflow-history-compaction'); } - init() { - strict(this.instanceSettings.instanceRole !== 'unset', 'Instance role is not set'); - - if (this.instanceSettings.isLeader) this.runStartupCompaction(); - } - - get isEnabled() { - return this.instanceSettings.instanceType === 'main' && this.instanceSettings.isLeader; - } - - // One-shot catch-up pass on startup and on leader change, so a gap between - // leaders is compacted without waiting a full task interval. Not `runOnTakeover` - // on the tasks: `trimOnStartUp` forces a trim only here, and a task run cannot - // tell a takeover from a scheduled tick. - @OnLeaderTakeover() - runStartupCompaction() { - const { connectionState } = this.dbConnection; - if (!this.isEnabled || !connectionState.migrated) return; - if (this.config.skipOnStartUp) return; - - this.startupAbort = new AbortController(); - const { signal } = this.startupAbort; - - void this.optimizeHistories(signal); - - if ( - this.config.trimOnStartUp && - isTrimmingEnabled(this.globalConfig.workflowHistory, this.config) - ) { - void this.trimLongRunningHistories(signal); - } - } - - // A startup pass runs detached, so losing leadership has to reach it here. - // The task-driven passes get their signal from the system task runner. - @OnLeaderStepdown() - @OnShutdown() - stopStartupCompaction(): void { - this.startupAbort.abort(); - } - /** * One trimming pass over long-running histories. A pass overlapping a running * one is skipped, and an aborted `signal` stops the pass at the next workflow. diff --git a/packages/cli/src/services/pruning/workflow-history-pruning.task.ts b/packages/cli/src/services/pruning/workflow-history-pruning.task.ts index 0347581fbe6..1075e724e40 100644 --- a/packages/cli/src/services/pruning/workflow-history-pruning.task.ts +++ b/packages/cli/src/services/pruning/workflow-history-pruning.task.ts @@ -1,7 +1,7 @@ import { DatabaseConfig, statementTimeoutSeconds } from '@n8n/config'; import { Time } from '@n8n/constants'; -import { intervalFromSeconds, SystemTask, timeoutAfterLimit } from '@n8n/decorators'; -import type { SystemTaskEffects, SystemTaskPlacement, SystemTaskSchedule } from '@n8n/decorators'; +import { clusterTarget, intervalFromSeconds, SystemTask, timeoutAfterLimit } from '@n8n/decorators'; +import type { SystemTaskSchedule } from '@n8n/decorators'; import { WorkflowHistoryManager } from '@/workflows/workflow-history/workflow-history-manager'; @@ -12,22 +12,22 @@ export class WorkflowHistoryPruningTask implements SystemTask { readonly schedule: SystemTaskSchedule = intervalFromSeconds(Time.hours.toSeconds); - readonly effects: SystemTaskEffects = 'idempotent'; - - readonly placement: SystemTaskPlacement = { - scope: 'cluster', - durable: true, - // Only the leader prunes, so a new leader runs once at takeover instead of waiting an hour. - runOnTakeover: true, - }; - - // One DELETE that ignores the signal. A timeout that stops the run before the - // DELETE ends lets the next run start a second one, so it waits for the - // statement timeout first. - readonly timeoutSeconds = timeoutAfterLimit( - statementTimeoutSeconds(this.databaseConfig), - 5 * Time.minutes.toSeconds, - ); + readonly target = clusterTarget({ + scheduler: { + retryOnFailure: true, + // One DELETE that ignores the signal. A timeout that stops the run before the + // DELETE ends lets the next run start a second one, so it waits for the + // statement timeout first. + timeoutSeconds: timeoutAfterLimit( + statementTimeoutSeconds(this.databaseConfig), + 5 * Time.minutes.toSeconds, + ), + }, + leaderTimer: { + // Only the leader prunes, so a new leader runs once at takeover instead of waiting an hour. + runOnTakeover: true, + }, + }); constructor( private readonly databaseConfig: DatabaseConfig, diff --git a/packages/cli/src/services/public-api-key.service.ts b/packages/cli/src/services/public-api-key.service.ts index d98dcc5764f..a50b49dd758 100644 --- a/packages/cli/src/services/public-api-key.service.ts +++ b/packages/cli/src/services/public-api-key.service.ts @@ -24,7 +24,7 @@ import { randomUUID } from 'crypto'; import { BadRequestError, NotFoundError } from '@n8n/errors'; import { UserManagementMailer } from '@/user-management/email'; -import { JwtService } from './jwt.service'; +import { JwtService } from '@n8n/backend-services'; export const API_KEY_AUDIENCE: ApiKeyAudience = 'public-api'; export const API_KEY_ISSUER = 'n8n'; diff --git a/packages/cli/src/services/user.service.ts b/packages/cli/src/services/user.service.ts index 5093bdd90e5..9ebaf94cd83 100644 --- a/packages/cli/src/services/user.service.ts +++ b/packages/cli/src/services/user.service.ts @@ -1,6 +1,6 @@ import type { RoleChangeRequestDto } from '@n8n/api-types'; import { Logger } from '@n8n/backend-common'; -import { EventService, UrlService, RoleService } from '@n8n/backend-services'; +import { EventService, UrlService, RoleService, JwtService } from '@n8n/backend-services'; import { GlobalConfig } from '@n8n/config'; import type { PublicUser } from '@n8n/db'; import { @@ -30,7 +30,6 @@ import type { IUserSettings } from 'n8n-workflow'; import { UserError } from 'n8n-workflow'; import { validate as uuidValidate } from 'uuid'; -import { JwtService } from './jwt.service'; import { OwnershipService } from './ownership.service'; import { ProjectService } from './project.service.ee'; import { PublicApiKeyService } from './public-api-key.service'; diff --git a/packages/cli/src/services/workflow-statistics-rollup.task.ts b/packages/cli/src/services/workflow-statistics-rollup.task.ts index 085d74910aa..e1dea3141be 100644 --- a/packages/cli/src/services/workflow-statistics-rollup.task.ts +++ b/packages/cli/src/services/workflow-statistics-rollup.task.ts @@ -1,20 +1,12 @@ import { SchedulerConfig } from '@n8n/config'; import { Time } from '@n8n/constants'; -import { intervalFromSeconds, SystemTask } from '@n8n/decorators'; -import type { - SystemTaskEffects, - SystemTaskPlacement, - SystemTaskRunContext, - SystemTaskSchedule, -} from '@n8n/decorators'; +import { clusterTarget, intervalFromSeconds, SystemTask } from '@n8n/decorators'; +import type { SystemTaskSchedule } from '@n8n/decorators'; import { WorkflowStatisticsRollupService } from './workflow-statistics-rollup.service'; const ROLLUP_INTERVAL_SECONDS = 5; -/** Ends a run before the next occurrence, so a backlog does not cause overlap skips. */ -const IN_MEMORY_RUN_BUDGET_MS = (ROLLUP_INTERVAL_SECONDS - 1) * Time.seconds.toMilliseconds; - /** * Folds the pending workflow statistics increments into the counters, and * fires the first-occurrence milestone events. @@ -25,31 +17,28 @@ export class WorkflowStatisticsRollupTask implements SystemTask { readonly schedule: SystemTaskSchedule = intervalFromSeconds(ROLLUP_INTERVAL_SECONDS); - readonly effects: SystemTaskEffects = 'idempotent'; + readonly target = clusterTarget({ + scheduler: { retryOnFailure: true }, + leaderTimer: { + /** Increments pile up while no instance is the leader, so a backlog is waiting. */ + runOnTakeover: true, + }, + }); - readonly placement: SystemTaskPlacement = { - scope: 'cluster', - durable: true, - /** Increments pile up while no instance is the leader, so a backlog is waiting. */ - runOnTakeover: true, - }; - - private readonly durableRunBudgetMs: number; + private readonly runBudgetMs: number; constructor( private readonly rollupService: WorkflowStatisticsRollupService, schedulerConfig: SchedulerConfig, ) { - // Leave one second for a slower batch. The durable lease is not renewed during a run. - this.durableRunBudgetMs = + // Ends a run before the next occurrence, so a backlog does not cause overlap skips. + // It also ends before a lease too short for the heartbeat to renew in time. + this.runBudgetMs = (Math.min(ROLLUP_INTERVAL_SECONDS, schedulerConfig.leaseDurationSeconds) - 1) * Time.seconds.toMilliseconds; } - async run(signal: AbortSignal, { durable }: SystemTaskRunContext): Promise { - await this.rollupService.rollup( - signal, - durable ? this.durableRunBudgetMs : IN_MEMORY_RUN_BUDGET_MS, - ); + async run(signal: AbortSignal): Promise { + await this.rollupService.rollup(signal, this.runBudgetMs); } } diff --git a/packages/cli/src/services/workflow-statistics.service.ts b/packages/cli/src/services/workflow-statistics.service.ts index a54ce777972..65b4a605221 100644 --- a/packages/cli/src/services/workflow-statistics.service.ts +++ b/packages/cli/src/services/workflow-statistics.service.ts @@ -22,7 +22,6 @@ import { import { UserService } from '@/services/user.service'; -import { INSTANCE_ACTIVATED_SETTINGS_KEY } from './instance-activation.service'; import { OwnershipService } from './ownership.service'; type CompletedRunOutcome = { @@ -246,28 +245,6 @@ export class WorkflowStatisticsService extends TypedEmitter { - await this.settingsRepository.insertIfAbsent( - INSTANCE_ACTIVATED_SETTINGS_KEY, - JSON.stringify({ workflowId, projectId, userId, timestamp: activatedAt }), - ); } private async emitInstanceFirstProductionWorkflowFailed( diff --git a/packages/cli/src/telemetry/__tests__/telemetry-buffer-flush.task.test.ts b/packages/cli/src/telemetry/__tests__/telemetry-buffer-flush.task.test.ts index 998c0cefc99..e928fffa80b 100644 --- a/packages/cli/src/telemetry/__tests__/telemetry-buffer-flush.task.test.ts +++ b/packages/cli/src/telemetry/__tests__/telemetry-buffer-flush.task.test.ts @@ -16,8 +16,7 @@ describe('TelemetryBufferFlushTask', () => { it('should flush in every kind of instance every 6 hours', () => { expect(task.name).toBe('telemetry-buffer-flush'); expect(task.schedule).toEqual({ kind: 'interval', intervalSeconds: 21600 }); - expect(task.effects).toBe('non-idempotent'); - expect(task.placement).toEqual({ + expect(task.target).toEqual({ scope: 'instance', instanceTypes: ['main', 'worker', 'webhook'], }); diff --git a/packages/cli/src/telemetry/__tests__/telemetry-pulse.task.test.ts b/packages/cli/src/telemetry/__tests__/telemetry-pulse.task.test.ts index f69f1fd66f9..26870bf174f 100644 --- a/packages/cli/src/telemetry/__tests__/telemetry-pulse.task.test.ts +++ b/packages/cli/src/telemetry/__tests__/telemetry-pulse.task.test.ts @@ -1,5 +1,5 @@ import { ScheduledJobMisfirePolicy } from '@n8n/constants'; -import { resolveSystemTaskRunOptions } from '@n8n/decorators'; +import { resolveSystemTask } from '@n8n/decorators'; import { mock } from 'vitest-mock-extended'; import type { Telemetry } from '@/telemetry'; @@ -18,13 +18,15 @@ describe('TelemetryPulseTask', () => { it('should send one packet for the whole cluster every 6 hours', () => { expect(task.name).toBe('telemetry-pulse'); expect(task.schedule).toEqual({ kind: 'interval', intervalSeconds: 21600 }); - expect(task.effects).toBe('non-idempotent'); - expect(task.placement).toEqual({ scope: 'cluster', durable: true }); + expect(task.target).toEqual({ + scope: 'cluster', + scheduler: { retryOnFailure: false, missedAfterSeconds: 3600, catchUp: true }, + }); }); it('should keep a missed occurrence for an hour, coalesce a longer backlog and never retry a failed one', () => { - expect(task.misfireGraceSeconds).toBe(3600); - expect(resolveSystemTaskRunOptions(task)).toEqual({ + expect(task.target.scheduler?.missedAfterSeconds).toBe(3600); + expect(resolveSystemTask(task).runOptions).toEqual({ misfirePolicy: ScheduledJobMisfirePolicy.Coalesce, misfireGraceSeconds: 3600, maxAttempts: 1, diff --git a/packages/cli/src/telemetry/telemetry-buffer-flush.task.ts b/packages/cli/src/telemetry/telemetry-buffer-flush.task.ts index 94dec6394f0..6f129a522d6 100644 --- a/packages/cli/src/telemetry/telemetry-buffer-flush.task.ts +++ b/packages/cli/src/telemetry/telemetry-buffer-flush.task.ts @@ -1,6 +1,6 @@ import { Time } from '@n8n/constants'; -import { intervalFromSeconds, SystemTask } from '@n8n/decorators'; -import type { SystemTaskEffects, SystemTaskPlacement, SystemTaskSchedule } from '@n8n/decorators'; +import { instanceTarget, intervalFromSeconds, SystemTask } from '@n8n/decorators'; +import type { SystemTaskSchedule } from '@n8n/decorators'; import { Telemetry } from '@/telemetry'; @@ -13,14 +13,8 @@ export class TelemetryBufferFlushTask implements SystemTask { readonly schedule: SystemTaskSchedule = intervalFromSeconds(6 * Time.hours.toSeconds); - /** A flush sends what it drains, so a repeat can report the same events twice. */ - readonly effects: SystemTaskEffects = 'non-idempotent'; - /** The buffer belongs to this process, so no other instance can drain it. */ - readonly placement: SystemTaskPlacement = { - scope: 'instance', - instanceTypes: ['main', 'worker', 'webhook'], - }; + readonly target = instanceTarget(['main', 'worker', 'webhook']); constructor(private readonly telemetry: Telemetry) {} diff --git a/packages/cli/src/telemetry/telemetry-pulse.task.ts b/packages/cli/src/telemetry/telemetry-pulse.task.ts index 53e316307ce..ab7b83832a5 100644 --- a/packages/cli/src/telemetry/telemetry-pulse.task.ts +++ b/packages/cli/src/telemetry/telemetry-pulse.task.ts @@ -1,6 +1,6 @@ -import { ScheduledJobMisfirePolicy, Time } from '@n8n/constants'; -import { intervalFromSeconds, SystemTask } from '@n8n/decorators'; -import type { SystemTaskEffects, SystemTaskPlacement, SystemTaskSchedule } from '@n8n/decorators'; +import { Time } from '@n8n/constants'; +import { clusterTarget, intervalFromSeconds, SystemTask } from '@n8n/decorators'; +import type { SystemTaskSchedule } from '@n8n/decorators'; import { Telemetry } from '@/telemetry'; @@ -13,20 +13,20 @@ export class TelemetryPulseTask implements SystemTask { readonly schedule: SystemTaskSchedule = intervalFromSeconds(6 * Time.hours.toSeconds); - /** The packet carries instance-wide counters, so a repeat over-reports them. */ - readonly effects: SystemTaskEffects = 'non-idempotent'; - - /** - * A late packet still describes the instance correctly. An hour carries the - * occurrence across a restart or a failover, rather than losing the six-hour - * window to the default grace of a minute. - */ - readonly misfireGraceSeconds = Time.hours.toSeconds; - - /** An outage past the grace still sends one catch-up packet, not none. */ - readonly misfirePolicy = ScheduledJobMisfirePolicy.Coalesce; - - readonly placement: SystemTaskPlacement = { scope: 'cluster', durable: true }; + readonly target = clusterTarget({ + scheduler: { + /** The packet carries instance-wide counters, so a repeat over-reports them. */ + retryOnFailure: false, + /** + * A late packet still describes the instance correctly. An hour carries the + * occurrence across a restart or a failover, rather than losing the six-hour + * window to the default grace of a minute. + */ + missedAfterSeconds: Time.hours.toSeconds, + /** An outage past the grace still sends one catch-up packet, not none. */ + catchUp: true, + }, + }); constructor(private readonly telemetry: Telemetry) {} diff --git a/packages/cli/src/user-management/email/__tests__/user-management-mailer.test.ts b/packages/cli/src/user-management/email/__tests__/user-management-mailer.test.ts index 17b6318d13d..74e8afb88bc 100644 --- a/packages/cli/src/user-management/email/__tests__/user-management-mailer.test.ts +++ b/packages/cli/src/user-management/email/__tests__/user-management-mailer.test.ts @@ -283,6 +283,36 @@ describe('UserManagementMailer', () => { }); }); + it('should send a migration findings email with one link per workflow', async () => { + const result = await userManagementMailer.migrationFindings({ + email, + firstName: 'Grace', + notifierName: 'Ada Lovelace', + ruleTitle: 'Removed nodes', + targetVersion: 'v3', + workflows: [ + { id: 'wf-1', name: 'Billing sync' }, + { id: 'wf-2', name: 'Lead intake' }, + ], + reportUrl: 'https://n8n.url/settings/migration-report/removed-nodes-v3', + }); + + expect(result.emailSent).toBe(true); + expect(nodeMailer.sendMail).toHaveBeenCalledWith({ + body: expect.stringContaining( + 'href="https://n8n.url/settings/migration-report/removed-nodes-v3"', + ), + emailRecipients: email, + subject: 'Your workflows need changes before the upgrade to n8n v3', + }); + const callBody = nodeMailer.sendMail.mock.calls[0][0].body; + expect(callBody).toContain('Hi Grace,'); + expect(callBody).toContain('Ada Lovelace asked you'); + expect(callBody).toContain('Removed nodes'); + expect(callBody).toContain('Billing sync'); + expect(callBody).toContain('Lead intake'); + }); + it('should send an agent budget alert email', async () => { const result = await userManagementMailer.agentBudgetAlert({ email, diff --git a/packages/cli/src/user-management/email/templates/migration-findings.mjml b/packages/cli/src/user-management/email/templates/migration-findings.mjml new file mode 100644 index 00000000000..5f47c554c67 --- /dev/null +++ b/packages/cli/src/user-management/email/templates/migration-findings.mjml @@ -0,0 +1,23 @@ + + + + + + + Your workflows need changes before the upgrade to n8n {{ targetVersion }} + Hi {{ firstName }}, + {{ notifierName }} asked you to resolve the migration finding "{{ ruleTitle }}" on the workflows you own. The upgrade to n8n {{ targetVersion }} changes how these workflows behave. + + + + Open the migration report for the details and the steps to fix them. + Open Migration Report + + + + + diff --git a/packages/cli/src/user-management/email/user-management-mailer.ts b/packages/cli/src/user-management/email/user-management-mailer.ts index 6b182a7caaa..88c4a468ae9 100644 --- a/packages/cli/src/user-management/email/user-management-mailer.ts +++ b/packages/cli/src/user-management/email/user-management-mailer.ts @@ -56,7 +56,8 @@ type TemplateName = | 'mcp-client-revoked' | 'email-change-requested' | 'email-change-completed' - | 'agent-budget-alert'; + | 'agent-budget-alert' + | 'migration-findings'; @Service() export class UserManagementMailer { @@ -207,6 +208,38 @@ export class UserManagementMailer { }); } + /** Asks the owner of the listed workflows to resolve one migration finding on them. */ + async migrationFindings(data: { + email: string; + firstName?: string | null; + notifierName: string; + ruleTitle: string; + targetVersion: string; + workflows: Array<{ id: string; name: string }>; + reportUrl: string; + }): Promise { + if (!this.mailer) return { emailSent: false }; + + const baseUrl = this.urlService.getInstanceBaseUrl(); + const template = await this.getTemplate('migration-findings'); + return await this.mailer.sendMail({ + emailRecipients: data.email, + subject: `Your workflows need changes before the upgrade to n8n ${data.targetVersion}`, + body: template({ + ...this.basePayload, + firstName: data.firstName || 'there', + notifierName: data.notifierName, + ruleTitle: data.ruleTitle, + targetVersion: data.targetVersion, + workflows: data.workflows.map((workflow) => ({ + name: workflow.name, + url: `${baseUrl}/workflow/${workflow.id}`, + })), + reportUrl: data.reportUrl, + }), + }); + } + async workflowFailure(data: { email: string; firstName?: string; diff --git a/packages/cli/src/utils.ts b/packages/cli/src/utils.ts index a8c50f3be15..a9f41f2438a 100644 --- a/packages/cli/src/utils.ts +++ b/packages/cli/src/utils.ts @@ -31,13 +31,15 @@ export function satisfiesToolCapability(syntheticToolName: string, nodeType: INo function findWorkflowStart(executionMode: 'integrated' | 'cli') { return function (nodes: INode[]) { - const executeWorkflowTriggerNode = nodes.find( + const eligibleNodes = + executionMode === 'cli' ? nodes.filter((node) => node.disabled !== true) : nodes; + const executeWorkflowTriggerNode = eligibleNodes.find( (node) => node.type === 'n8n-nodes-base.executeWorkflowTrigger', ); if (executeWorkflowTriggerNode) return executeWorkflowTriggerNode; - const startNode = nodes.find((node) => STARTING_NODES.includes(node.type)); + const startNode = eligibleNodes.find((node) => STARTING_NODES.includes(node.type)); if (startNode) return startNode; @@ -159,7 +161,10 @@ export function setMicrosoftObservabilityDefaults(): void { } export function containsExpression(testString: string): boolean { - return /^=.*\{\{.+\}\}/.test(testString); + if (!testString.startsWith('=')) return false; + const firstLine = testString.split(/[\r\n\u2028\u2029]/, 1)[0]; + const opening = firstLine.indexOf('{{', 1); + return opening !== -1 && firstLine.lastIndexOf('}}') > opening + 2; } export function isObject(value: unknown): value is Record { diff --git a/packages/cli/src/utils/__tests__/object-to-error.test.ts b/packages/cli/src/utils/__tests__/object-to-error.test.ts index 1256eebfe12..a7656cdf076 100644 --- a/packages/cli/src/utils/__tests__/object-to-error.test.ts +++ b/packages/cli/src/utils/__tests__/object-to-error.test.ts @@ -40,4 +40,40 @@ describe('objectToError', () => { expect(result.message).toBe('Test error'); }); }); + + describe('policy violations', () => { + it('should copy `violations` from the error object', () => { + const violation = { + kind: 'node-type-unavailable', + checkId: 'node-type-availability', + message: 'Node type "n8n-nodes-base.set" is blocked by a project policy', + subject: 'n8n-nodes-base.set', + subjectType: 'nodeType', + scope: 'project', + projectId: 'project-1', + optInAvailable: false, + }; + const errorObject = { + message: 'Test error', + violations: [violation], + }; + const workflow = mock(); + + const result = objectToError(errorObject, workflow); + + expect((result as unknown as { violations: unknown[] }).violations).toEqual([violation]); + }); + + it('should not copy `isPolicyRefusal`', () => { + const errorObject = { + message: 'Test error', + isPolicyRefusal: true, + }; + const workflow = mock(); + + const result = objectToError(errorObject, workflow); + + expect(Object.hasOwn(result, 'isPolicyRefusal')).toBe(false); + }); + }); }); diff --git a/packages/cli/src/utils/object-to-error.ts b/packages/cli/src/utils/object-to-error.ts index 9fb6d57ed5e..fc2157afdea 100644 --- a/packages/cli/src/utils/object-to-error.ts +++ b/packages/cli/src/utils/object-to-error.ts @@ -4,8 +4,11 @@ import type { Workflow } from 'n8n-workflow'; /** * Optional properties that should be propagated from an error object to the new Error instance. + * + * `violations` keeps a sub-workflow's policy refusal readable in the parent. The + * `isPolicyRefusal` marker is left out: the parent's own graph was not refused. */ -const errorProperties = ['description', 'stack', 'executionId', 'workflowId']; +const errorProperties = ['description', 'stack', 'executionId', 'workflowId', 'violations']; export function objectToError(errorObject: unknown, workflow: Workflow): Error { // TODO: Expand with other error types diff --git a/packages/cli/src/webhooks/__tests__/slack-interaction-webhooks.test.ts b/packages/cli/src/webhooks/__tests__/slack-interaction-webhooks.test.ts index 3d7c208ff6d..598bbc57ec0 100644 --- a/packages/cli/src/webhooks/__tests__/slack-interaction-webhooks.test.ts +++ b/packages/cli/src/webhooks/__tests__/slack-interaction-webhooks.test.ts @@ -193,6 +193,25 @@ describe('SlackInteractionWebhooks', () => { expect(slackInteractionWebhooks.getWebhookExecutionDataArgs).toBeNull(); }); + it('responds 409 when the execution was parked at a node boundary', async () => { + const reference = buildHitlCallbackReference('exec-1', 'a', TEST_HMAC_SECRET); + const req = createRequest(reference); + const { res, status } = createResponse(); + executionPersistence.findSingleExecution.mockResolvedValue( + mock({ + status: 'waiting', + finished: false, + data: { waitReason: 'suspended', resultData: { error: undefined } }, + }), + ); + + const result = await slackInteractionWebhooks.executeWebhook(req, res); + + expect(status).toHaveBeenCalledWith(409); + expect(result).toEqual({ noWebhookResponse: true }); + expect(slackInteractionWebhooks.getWebhookExecutionDataArgs).toBeNull(); + }); + it('responds 409 when the execution has already finished', async () => { const reference = buildHitlCallbackReference('exec-1', 'a', TEST_HMAC_SECRET); const req = createRequest(reference); diff --git a/packages/cli/src/webhooks/__tests__/waiting-forms.test.ts b/packages/cli/src/webhooks/__tests__/waiting-forms.test.ts index edd92c508dd..3747c02b44f 100644 --- a/packages/cli/src/webhooks/__tests__/waiting-forms.test.ts +++ b/packages/cli/src/webhooks/__tests__/waiting-forms.test.ts @@ -229,6 +229,57 @@ describe('WaitingForms', () => { expect(result).toBe('Form2'); }); + it('should not render a form for an execution parked at a node boundary', async () => { + const execution = mock({ + status: 'waiting', + data: { waitReason: 'suspended', resumeToken: undefined, resultData: { error: undefined } }, + }); + executionPersistence.findSingleExecution.mockResolvedValue(execution); + + const req = mock({ + headers: {}, + params: { path: '123', suffix: undefined }, + }); + const res = mock(); + + const result = await waitingForms.executeWebhook(req, res); + + expect(result).toEqual({ noWebhookResponse: true }); + expect(res.render).not.toHaveBeenCalled(); + }); + + const statusPoll = async (waitReason?: 'suspended') => { + const execution = mock({ + status: 'waiting', + data: { + waitReason, + resumeToken: undefined, + executionData: { + nodeExecutionStack: [{ node: { type: FORM_NODE_TYPE, parameters: {} } }], + }, + }, + }); + executionPersistence.findSingleExecution.mockResolvedValue(execution); + const req = mock({ + headers: {}, + params: { path: '123', suffix: WAITING_FORMS_EXECUTION_STATUS }, + }); + const res = mock(); + + await waitingForms.executeWebhook(req, res); + return res; + }; + + it('should report form-waiting when the run paused at a form node', async () => { + const res = await statusPoll(); + expect(res.send).toHaveBeenCalledWith('form-waiting'); + }); + + it('should report plain waiting for a run parked before a form node', async () => { + const res = await statusPoll('suspended'); + expect(res.send).toHaveBeenCalledWith('waiting'); + }); + it('should return status of execution if suffix is WAITING_FORMS_EXECUTION_STATUS', async () => { const execution = mock({ status: 'success', diff --git a/packages/cli/src/webhooks/__tests__/waiting-webhooks.test.ts b/packages/cli/src/webhooks/__tests__/waiting-webhooks.test.ts index 328191f779c..249cb1d9bae 100644 --- a/packages/cli/src/webhooks/__tests__/waiting-webhooks.test.ts +++ b/packages/cli/src/webhooks/__tests__/waiting-webhooks.test.ts @@ -79,6 +79,26 @@ describe('WaitingWebhooks', () => { await expect(promise).rejects.toThrowError(NotFoundError); }); + it('should throw ConflictError if the execution to resume was parked at a node boundary', async () => { + executionPersistence.findSingleExecution.mockResolvedValue( + mock({ + status: 'waiting', + data: { + waitReason: 'suspended', + resumeToken: undefined, + resultData: { lastNodeExecuted: undefined, error: undefined }, + }, + }), + ); + + const promise = waitingWebhooks.executeWebhook( + mock(), + mock(), + ); + + await expect(promise).rejects.toThrowError(ConflictError); + }); + it('should throw ConflictError if the execution to resume is already running', async () => { /** * Arrange diff --git a/packages/cli/src/webhooks/__tests__/webhook-request-handler.test.ts b/packages/cli/src/webhooks/__tests__/webhook-request-handler.test.ts index 63e4aef1258..36dcefcbe88 100644 --- a/packages/cli/src/webhooks/__tests__/webhook-request-handler.test.ts +++ b/packages/cli/src/webhooks/__tests__/webhook-request-handler.test.ts @@ -1,7 +1,11 @@ import { Logger } from '@n8n/backend-common'; import { mockInstance } from '@n8n/backend-test-utils'; import { type Response } from 'express'; -import { isWebhookHtmlSandboxingDisabled, getHtmlSandboxCSP } from 'n8n-core'; +import { + isFormHtmlSandboxingDisabled, + isWebhookHtmlSandboxingDisabled, + getHtmlSandboxCSP, +} from 'n8n-core'; import { OperationalError, randomString } from 'n8n-workflow'; import type { IHttpRequestMethods } from 'n8n-workflow'; import { mock } from 'vitest-mock-extended'; @@ -18,6 +22,7 @@ import type { vi.mock('n8n-core', async () => ({ ...(await vi.importActual('n8n-core')), isWebhookHtmlSandboxingDisabled: vi.fn().mockReturnValue(false), + isFormHtmlSandboxingDisabled: vi.fn().mockReturnValue(false), getHtmlSandboxCSP: vi.fn().mockReturnValue('sandbox allow-downloads allow-forms allow-modals'), })); @@ -335,7 +340,7 @@ describe('WebhookRequestHandler', () => { }); it('should not set CSP sandbox header when sandboxing is disabled', async () => { - vi.mocked(isWebhookHtmlSandboxingDisabled).mockReturnValueOnce(true); + vi.mocked(isWebhookHtmlSandboxingDisabled).mockReturnValue(true); const req = mock({ path: '/', @@ -354,7 +359,174 @@ describe('WebhookRequestHandler', () => { await handler(req, res); - expect(res.setHeader).not.toHaveBeenCalledWith('Content-Security-Policy', expect.anything()); + expect(res.setHeader).not.toHaveBeenCalledWith( + 'Content-Security-Policy', + getHtmlSandboxCSP(), + ); + }); + + describe('on every exit path', () => { + const sandboxCSP = 'sandbox allow-scripts'; + + const cspSetBefore = (res: ReturnType>, writer: 'json' | 'send') => { + const cspCall = res.setHeader.mock.calls.findIndex( + ([name]) => name === 'Content-Security-Policy', + ); + expect(cspCall).not.toBe(-1); + expect(res.setHeader.mock.calls[cspCall][1]).toBe(sandboxCSP); + expect(res.setHeader.mock.invocationCallOrder[cspCall]).toBeLessThan( + res[writer].mock.invocationCallOrder[0], + ); + }; + + beforeEach(() => { + vi.mocked(getHtmlSandboxCSP).mockReturnValue(sandboxCSP); + }); + + it('should set the sandbox header before an error response is sent', async () => { + const req = mock({ path: '/', method: 'GET', params: { path: 'test' } }); + const res = mock(); + res.status.mockReturnValue(res); + webhookManager.executeWebhook.mockRejectedValueOnce(new OperationalError('Test error')); + + await handler(req, res); + + expect(res.status).toHaveBeenCalledWith(500); + cspSetBefore(res, 'json'); + }); + + it('should set the sandbox header on a legacy response without headers', async () => { + const req = mock({ path: '/', method: 'GET', params: { path: 'test' } }); + const res = mock(); + // A node can pass a plain string body to `sendResponse()`, without a headers object. + webhookManager.executeWebhook.mockResolvedValueOnce({ + responseCode: 200, + data: '

text

', + } as unknown as IWebhookResponseCallbackData); + + await handler(req, res); + + expect(res.send).toHaveBeenCalledWith('

text

'); + cspSetBefore(res, 'send'); + }); + + it('should set the sandbox header for an unsupported method', async () => { + const req = mock({ + path: '/', + method: 'CONNECT' as IHttpRequestMethods, + }); + const res = mock(); + res.status.mockReturnValue(res); + + await handler(req, res); + + cspSetBefore(res, 'json'); + }); + + it('should set the sandbox header when the node writes the response', async () => { + const req = mock({ path: '/', method: 'GET', params: { path: 'test' } }); + const res = mock(); + webhookManager.executeWebhook.mockImplementationOnce(async (_req, response) => { + response.send('

text

'); + return { noWebhookResponse: true }; + }); + + await handler(req, res); + + cspSetBefore(res, 'send'); + }); + }); + + describe('sandbox setting of the route', () => { + const formHandlers = [ + ['a form route', createWebhookHandlerFor(webhookManager, 'form')], + [ + 'a route that selects the form setting', + createWebhookHandlerFor(webhookManager, undefined, 'form'), + ], + ] as const; + + test.each(formHandlers)('should follow the form setting on %s', async (_, formHandler) => { + vi.mocked(isFormHtmlSandboxingDisabled).mockReturnValue(true); + vi.mocked(isWebhookHtmlSandboxingDisabled).mockReturnValue(false); + vi.mocked(getHtmlSandboxCSP).mockReturnValue('sandbox allow-scripts'); + + const req = mock({ path: '/', method: 'GET', params: { path: 'test' } }); + const res = mock(); + webhookManager.executeWebhook.mockResolvedValueOnce({ noWebhookResponse: true }); + + await (formHandler as typeof handler)(req, res); + + expect(res.setHeader).not.toHaveBeenCalledWith( + 'Content-Security-Policy', + 'sandbox allow-scripts', + ); + }); + + it('should not sandbox a form response when only form sandboxing is disabled', async () => { + vi.mocked(isFormHtmlSandboxingDisabled).mockReturnValue(true); + vi.mocked(isWebhookHtmlSandboxingDisabled).mockReturnValue(false); + vi.mocked(getHtmlSandboxCSP).mockReturnValue('sandbox allow-scripts'); + const formHandler = createWebhookHandlerFor(webhookManager, 'form') as typeof handler; + + const req = mock({ path: '/', method: 'GET', params: { path: 'test' } }); + const res = mock(); + webhookManager.executeWebhook.mockResolvedValueOnce({ + responseCode: 200, + data: '

text

', + headers: { 'content-type': 'text/html' }, + } as unknown as IWebhookResponseCallbackData); + + await formHandler(req, res); + + expect(res.setHeaders).toHaveBeenCalled(); + expect(res.setHeader).not.toHaveBeenCalledWith( + 'Content-Security-Policy', + 'sandbox allow-scripts', + ); + expect(res.send).toHaveBeenCalledWith('

text

'); + }); + + it('should keep the form sandbox on a form response when webhook sandboxing is disabled', async () => { + vi.mocked(isFormHtmlSandboxingDisabled).mockReturnValue(false); + vi.mocked(isWebhookHtmlSandboxingDisabled).mockReturnValue(true); + vi.mocked(getHtmlSandboxCSP).mockReturnValue('sandbox allow-scripts'); + const formHandler = createWebhookHandlerFor(webhookManager, 'form') as typeof handler; + + const req = mock({ path: '/', method: 'GET', params: { path: 'test' } }); + const res = mock(); + webhookManager.executeWebhook.mockResolvedValueOnce({ + responseCode: 200, + data: { ok: true }, + headers: { 'content-type': 'text/html' }, + }); + + await formHandler(req, res); + + expect(res.setHeader).toHaveBeenCalledWith( + 'Content-Security-Policy', + 'sandbox allow-scripts', + ); + expect(res.removeHeader).not.toHaveBeenCalled(); + expect(res.json).toHaveBeenCalledWith({ ok: true }); + }); + + it('should follow the webhook setting on other routes', async () => { + vi.mocked(isFormHtmlSandboxingDisabled).mockReturnValue(true); + vi.mocked(isWebhookHtmlSandboxingDisabled).mockReturnValue(false); + vi.mocked(getHtmlSandboxCSP).mockReturnValue('sandbox allow-scripts'); + + const req = mock({ path: '/', method: 'GET', params: { path: 'test' } }); + const res = mock(); + webhookManager.executeWebhook.mockResolvedValueOnce({ noWebhookResponse: true }); + + await handler(req, res); + + expect(res.setHeader).toHaveBeenCalledWith( + 'Content-Security-Policy', + 'sandbox allow-scripts', + ); + }); }); }); }); diff --git a/packages/cli/src/webhooks/__tests__/webhook-response-headers.test.ts b/packages/cli/src/webhooks/__tests__/webhook-response-headers.test.ts index 17ee7619248..6750ca7b098 100644 --- a/packages/cli/src/webhooks/__tests__/webhook-response-headers.test.ts +++ b/packages/cli/src/webhooks/__tests__/webhook-response-headers.test.ts @@ -6,7 +6,12 @@ import type { Response } from 'express'; import { getHtmlSandboxCSP } from 'n8n-core'; import { mock } from 'vitest-mock-extended'; -import { applyFormSandboxCSP, WebhookResponseHeaders } from '@/webhooks/webhook-response-headers'; +import { + applyFormSandboxCSP, + applySandboxCSP, + setRouteSandboxSetting, + WebhookResponseHeaders, +} from '@/webhooks/webhook-response-headers'; describe('WebhookResponseHeaders', () => { const logger = mockInstance(Logger); @@ -353,13 +358,75 @@ describe('WebhookResponseHeaders', () => { expect(res.setHeader).toHaveBeenCalledWith('Content-Security-Policy', getHtmlSandboxCSP()); }); - it('should set no policy when form sandboxing is disabled', () => { + it('should remove the policy when form sandboxing is disabled', () => { securityConfig.disableFormHtmlSandboxing = true; const res = mock(); applyFormSandboxCSP(res); expect(res.setHeader).not.toHaveBeenCalled(); + expect(res.removeHeader).toHaveBeenCalledWith('Content-Security-Policy'); + }); + }); + + describe('applySandboxCSP', () => { + const securityConfig = Container.get(SecurityConfig); + + afterEach(() => { + securityConfig.disableWebhookHtmlSandboxing = false; + }); + + it('should set the sandbox policy', () => { + const res = mock(); + + applySandboxCSP(res); + + expect(res.setHeader).toHaveBeenCalledWith('Content-Security-Policy', getHtmlSandboxCSP()); + }); + + it('should leave the policy unchanged when webhook sandboxing is disabled', () => { + securityConfig.disableWebhookHtmlSandboxing = true; + const res = mock(); + + applySandboxCSP(res); + + expect(res.setHeader).not.toHaveBeenCalled(); + expect(res.removeHeader).not.toHaveBeenCalled(); + }); + + describe('on a form route', () => { + afterEach(() => { + securityConfig.disableFormHtmlSandboxing = false; + }); + + it('should follow the form setting instead of the webhook setting', () => { + securityConfig.disableFormHtmlSandboxing = true; + const res = mock({ locals: {} }); + setRouteSandboxSetting(res, 'form'); + + applySandboxCSP(res); + + expect(res.setHeader).not.toHaveBeenCalled(); + }); + + it('should set the policy when only webhook sandboxing is disabled', () => { + securityConfig.disableWebhookHtmlSandboxing = true; + const res = mock({ locals: {} }); + setRouteSandboxSetting(res, 'form'); + + applySandboxCSP(res); + + expect(res.setHeader).toHaveBeenCalledWith('Content-Security-Policy', getHtmlSandboxCSP()); + }); + }); + + it('should use the fallback setting outside webhook and form routes', () => { + securityConfig.disableWebhookHtmlSandboxing = true; + const res = mock({ locals: {} }); + + applySandboxCSP(res, 'form'); + + expect(res.setHeader).toHaveBeenCalledWith('Content-Security-Policy', getHtmlSandboxCSP()); }); }); }); diff --git a/packages/cli/src/webhooks/hitl-interaction-webhooks.ts b/packages/cli/src/webhooks/hitl-interaction-webhooks.ts index efca2ab3554..2ed3b47a161 100644 --- a/packages/cli/src/webhooks/hitl-interaction-webhooks.ts +++ b/packages/cli/src/webhooks/hitl-interaction-webhooks.ts @@ -58,8 +58,14 @@ export abstract class HitlInteractionWebhooks extends WaitingWebhooks { const execution = await this.getExecution(parsed.executionId); if (!execution) return { ok: false, status: 404 }; - // oxlint-disable-next-line typescript/no-deprecated - if (execution.status === 'running' || execution.finished || execution.data?.resultData?.error) { + if ( + execution.status === 'running' || + // oxlint-disable-next-line typescript/no-deprecated + execution.finished || + execution.data?.resultData?.error || + // A run parked at a node boundary is not waiting for this interaction. + execution.data?.waitReason === 'suspended' + ) { // Replayed or late interaction: nothing left to resume. return { ok: false, status: 409 }; } diff --git a/packages/cli/src/webhooks/waiting-forms.ts b/packages/cli/src/webhooks/waiting-forms.ts index dc1e16df8d3..51a1ae1d9ae 100644 --- a/packages/cli/src/webhooks/waiting-forms.ts +++ b/packages/cli/src/webhooks/waiting-forms.ts @@ -103,7 +103,9 @@ export class WaitingForms extends WaitingWebhooks { throw new ConflictError(message); } - if (execution.status === 'running') { + // A run parked at a node boundary is not waiting for a form page. Treated + // like a running run, so the page keeps polling until the run resumes. + if (execution.status === 'running' || execution.data.waitReason === 'suspended') { return { noWebhookResponse: true }; } @@ -160,7 +162,10 @@ export class WaitingForms extends WaitingWebhooks { let status: string = execution?.status ?? 'null'; const { node } = execution?.data.executionData?.nodeExecutionStack[0] ?? {}; - if (node && status === 'waiting' && this.isFormResumeNode(node)) { + // A run parked at a node boundary has its next, unexecuted node at the stack + // head. Even when that is a form node, no form is being served yet. + const isParked = execution?.data.waitReason === 'suspended'; + if (node && status === 'waiting' && !isParked && this.isFormResumeNode(node)) { status = 'form-waiting'; } diff --git a/packages/cli/src/webhooks/waiting-webhooks.ts b/packages/cli/src/webhooks/waiting-webhooks.ts index f565d904f52..73a07ce110f 100644 --- a/packages/cli/src/webhooks/waiting-webhooks.ts +++ b/packages/cli/src/webhooks/waiting-webhooks.ts @@ -304,6 +304,12 @@ export class WaitingWebhooks implements IWebhookManager { throw new ConflictError(`The execution "${executionId}" is running already.`); } + // A run parked at a node boundary is not waiting for this webhook: resuming + // it here would hand the webhook payload to a node that never asked for it. + if (execution.data?.waitReason === 'suspended') { + throw new ConflictError(`The execution "${executionId}" is about to resume.`); + } + if (execution.data?.resultData?.error) { const message = `The execution "${executionId}" has finished with error.`; this.logger.debug(message, { error: execution.data.resultData.error }); diff --git a/packages/cli/src/webhooks/webhook-request-handler.ts b/packages/cli/src/webhooks/webhook-request-handler.ts index c15ff0803df..5db87425445 100644 --- a/packages/cli/src/webhooks/webhook-request-handler.ts +++ b/packages/cli/src/webhooks/webhook-request-handler.ts @@ -21,7 +21,12 @@ import { isWebhookResponse, isWebhookStreamResponse, } from '@/webhooks/webhook-response'; -import { applySandboxCSP, WebhookResponseHeaders } from '@/webhooks/webhook-response-headers'; +import { + applySandboxCSP, + setRouteSandboxSetting, + WebhookResponseHeaders, + type WebhookSandboxSetting, +} from '@/webhooks/webhook-response-headers'; import type { IWebhookManager, WebhookOptionsRequest, @@ -34,6 +39,7 @@ class WebhookRequestHandler { constructor( private readonly webhookManager: IWebhookManager, private readonly expectedNodeType?: ExpectedWebhookNodeType, + private readonly sandboxSetting: WebhookSandboxSetting = 'webhook', ) {} /** @@ -43,6 +49,12 @@ class WebhookRequestHandler { async handleRequest(req: WebhookRequest | WebhookOptionsRequest, res: express.Response) { const method = req.method; + // Set the sandbox before any writer runs, so that every response of the route has it, + // for all status codes and content types. Only an n8n page that must keep its origin + // replaces or removes it. Later writers follow the same setting through `res.locals`. + setRouteSandboxSetting(res, this.sandboxSetting); + applySandboxCSP(res); + if (method !== 'OPTIONS' && !WEBHOOK_METHODS.includes(method)) { return ResponseHelper.sendErrorResponse( res, @@ -280,12 +292,16 @@ function trackWebhookMetrics( * recorded on each response: webhook requests via `observeWebhookRequest`, * form submissions (POST only) via `observeFormSubmission`. No metrics are * emitted for other node types. + * + * `sandboxSetting` selects the operator setting for the sandbox CSP. It defaults to the + * form setting for form routes and to the webhook setting for all other routes. */ export function createWebhookHandlerFor( webhookManager: IWebhookManager, expectedNodeType?: ExpectedWebhookNodeType, + sandboxSetting: WebhookSandboxSetting = expectedNodeType === 'form' ? 'form' : 'webhook', ): express.RequestHandler { - const handler = new WebhookRequestHandler(webhookManager, expectedNodeType); + const handler = new WebhookRequestHandler(webhookManager, expectedNodeType, sandboxSetting); const metricsService = Container.get(PrometheusWebhookAndFormMetricsService); return async (req, res) => { diff --git a/packages/cli/src/webhooks/webhook-response-headers.ts b/packages/cli/src/webhooks/webhook-response-headers.ts index 05b459ae0ed..76400b92207 100644 --- a/packages/cli/src/webhooks/webhook-response-headers.ts +++ b/packages/cli/src/webhooks/webhook-response-headers.ts @@ -86,17 +86,43 @@ export class WebhookResponseHeaders { } } -/** Set the sandbox CSP header on a webhook response, unless explicitly disabled. */ -export function applySandboxCSP(res: Response): void { - if (isWebhookHtmlSandboxingDisabled()) return; +/** The operator setting that controls the sandbox CSP on the responses of a route. */ +export type WebhookSandboxSetting = 'webhook' | 'form'; + +const SANDBOX_SETTING_LOCAL = 'webhookSandboxSetting'; + +/** Record which operator setting controls the sandbox CSP on this response. */ +export function setRouteSandboxSetting(res: Response, setting: WebhookSandboxSetting): void { + res.locals[SANDBOX_SETTING_LOCAL] = setting; +} + +function getRouteSandboxSetting(res: Response): WebhookSandboxSetting | undefined { + const setting: unknown = res.locals?.[SANDBOX_SETTING_LOCAL]; + return setting === 'webhook' || setting === 'form' ? setting : undefined; +} + +/** + * Set the sandbox CSP header on a webhook or form route response, unless an operator + * disabled it. The setting of the route decides, so every writer of a route follows the + * same setting. `fallback` applies when the response is not on a webhook or form route. + */ +export function applySandboxCSP(res: Response, fallback: WebhookSandboxSetting = 'webhook'): void { + const setting = getRouteSandboxSetting(res) ?? fallback; + const disabled = + setting === 'form' ? isFormHtmlSandboxingDisabled() : isWebhookHtmlSandboxingDisabled(); + if (disabled) return; res.setHeader('Content-Security-Policy', getHtmlSandboxCSP()); } /** - * Set the sandbox CSP header on a form page response, unless an operator disabled it. + * Set the sandbox CSP header on a form page response. If an operator disabled it, remove + * the header instead, because the request handler sets it for the whole route. * Call this for every HTML page a form endpoint serves, error and status pages included. */ export function applyFormSandboxCSP(res: Response): void { - if (isFormHtmlSandboxingDisabled()) return; + if (isFormHtmlSandboxingDisabled()) { + res.removeHeader('Content-Security-Policy'); + return; + } res.setHeader('Content-Security-Policy', getHtmlSandboxCSP()); } diff --git a/packages/cli/src/workflow-execute-additional-data.ts b/packages/cli/src/workflow-execute-additional-data.ts index a9e882cef86..4421ea860a1 100644 --- a/packages/cli/src/workflow-execute-additional-data.ts +++ b/packages/cli/src/workflow-execute-additional-data.ts @@ -57,6 +57,7 @@ import { createWorkflowAgentStreamObserver } from './modules/agents/workflow-age import { RuntimeCredentialProxyService } from './services/runtime-credential-proxy.service'; import { ActiveExecutions } from '@/active-executions'; +import { isCredSharingEnabled } from '@/constants/credential-sharing'; import { CredentialsHelper } from '@/credentials-helper'; import { PreExecuteBlockedError } from '@/errors/pre-execute-blocked.error'; import type { AiEventPayload } from '@/events/maps/ai.event-map'; @@ -157,6 +158,7 @@ async function fetchWorkflowData( workflowData.nodes ?? [], parentWorkflowId, ); + WorkflowHelpers.validateWorkflowStructure(workflowData); // An inline sub-workflow is part of the parent that embeds it, not a // workflow of its own, so it runs under the parent workflow's id. workflowData.id = parentWorkflowId; @@ -600,6 +602,12 @@ async function startExecution( const startTime = Date.now(); + // Reported to the caller so its redaction covers this run's output: the parent's own + // nodes do not reference these credentials. + const workflowCredentialIds = isCredSharingEnabled() + ? Container.get(CredentialsPermissionChecker).getCredentialIdsForNodes(workflowData.nodes) + : []; + let data; try { // The original mode of the whole run tree: a sub-workflow's own @@ -750,7 +758,7 @@ async function startExecution( }, workflow, ), - summarizeDynamicCredentialsUsage(runData.executionData), + summarizeDynamicCredentialsUsage(runData.executionData, workflowCredentialIds), ); } @@ -768,7 +776,7 @@ async function startExecution( : buildSubWorkflowOutput(data, workflowData.nodes, options.returnLastRunOnly ?? false), waitTill: data.waitTill, // Report private-credential usage to the caller (detached runs return earlier, skipping this). - ...summarizeDynamicCredentialsUsage(data.data), + ...summarizeDynamicCredentialsUsage(data.data, workflowCredentialIds), }; } activeExecutions.finalizeExecution(executionId, data); @@ -789,7 +797,7 @@ async function startExecution( }, workflow, ), - summarizeDynamicCredentialsUsage(data.data), + summarizeDynamicCredentialsUsage(data.data, workflowCredentialIds), ); } diff --git a/packages/cli/src/workflow-helpers.ts b/packages/cli/src/workflow-helpers.ts index 81028bb0d39..7b2b9a864d5 100644 --- a/packages/cli/src/workflow-helpers.ts +++ b/packages/cli/src/workflow-helpers.ts @@ -34,7 +34,9 @@ import { v4 as uuid } from 'uuid'; import { BadRequestError } from '@n8n/errors'; import { VariablesService } from '@/environments.ee/variables/variables.service.ee'; +import { isCredSharingEnabled } from '@/constants/credential-sharing'; import { ExecutionPersistence } from '@/executions/execution-persistence'; +import { CredentialsPermissionChecker } from '@/executions/pre-execution-checks'; import { NodeTypes } from '@/node-types'; import { OwnershipService } from './services/ownership.service'; @@ -428,6 +430,12 @@ export function shouldRestartParentExecution( return parentExecution.shouldResume; } +/** The ids in either list, once each; `undefined` when both are empty. */ +function unionIds(first: string[] | undefined, second: string[] | undefined) { + const ids = new Set([...(first ?? []), ...(second ?? [])]); + return ids.size > 0 ? [...ids].sort() : undefined; +} + /** * Updates a parent execution's nodeExecutionStack with the final results from a completed child execution. * This ensures that when the parent resumes, the Execute Workflow node (running in disabled mode) @@ -460,7 +468,9 @@ export async function updateParentExecutionWithChildResults( unflattenData: true, }); - if (parent?.status !== 'waiting') { + // A parent parked at a node boundary is not waiting on this child; its stack + // head is the next node, whose input must not be replaced by the child's output. + if (parent?.status !== 'waiting' || parent.data.waitReason === 'suspended') { return false; } @@ -487,15 +497,30 @@ export async function updateParentExecutionWithChildResults( // On resume the parent's flagged 'waiting' task is popped and the node re-runs disabled // (never calling `executeWorkflow` again), so the child's private-credential usage must // ride on the stack entry to reach the freshly stamped task (see `WorkflowExecute`). - const dynamicCredentialsUsage = summarizeDynamicCredentialsUsage(subworkflowResults.data); + const childCredentialIds = + isCredSharingEnabled() && childWorkflowData + ? Container.get(CredentialsPermissionChecker).getCredentialIdsForNodes( + childWorkflowData.nodes, + ) + : []; + const dynamicCredentialsUsage = summarizeDynamicCredentialsUsage( + subworkflowResults.data, + childCredentialIds, + ); if (Object.keys(dynamicCredentialsUsage).length > 0) { // Union with a sibling child's earlier report ("run once for each item" spawns several // children per wait) — flags only ever accumulate, like every other flag writer. + const earlierUsage = nodeExecutionStack[0].metadata?.dynamicCredentialsUsage; + const usedCredentialIds = unionIds( + earlierUsage?.usedCredentialIds, + dynamicCredentialsUsage.usedCredentialIds, + ); nodeExecutionStack[0].metadata = { ...nodeExecutionStack[0].metadata, dynamicCredentialsUsage: { - ...nodeExecutionStack[0].metadata?.dynamicCredentialsUsage, + ...earlierUsage, ...dynamicCredentialsUsage, + ...(usedCredentialIds && { usedCredentialIds }), }, }; @@ -513,6 +538,11 @@ export async function updateParentExecutionWithChildResults( if (dynamicCredentialsUsage.attemptedDynamicCredentials) { waitingTask.attemptedDynamicCredentials = true; } + const waitingTaskCredentialIds = unionIds( + waitingTask.usedCredentialIds, + dynamicCredentialsUsage.usedCredentialIds, + ); + if (waitingTaskCredentialIds) waitingTask.usedCredentialIds = waitingTaskCredentialIds; } const { runtimeData } = parentWithSubWorkflowResults.data.executionData ?? {}; if ( diff --git a/packages/cli/src/workflows/__tests__/workflow-creation.service.test.ts b/packages/cli/src/workflows/__tests__/workflow-creation.service.test.ts index e163b268366..3b4ff544b75 100644 --- a/packages/cli/src/workflows/__tests__/workflow-creation.service.test.ts +++ b/packages/cli/src/workflows/__tests__/workflow-creation.service.test.ts @@ -10,11 +10,13 @@ import type { } from '@n8n/db'; import { WorkflowEntity } from '@n8n/db'; import type { PolicyCleared } from '@n8n/decorators'; +import type { INode } from 'n8n-workflow'; import type { MockProxy } from 'vitest-mock-extended'; import { mock } from 'vitest-mock-extended'; import type { CredentialsFinderService } from '@n8n/backend-services'; import { BadRequestError, ForbiddenError, NotFoundError } from '@n8n/errors'; +import { UninspectableSubworkflowSourceError } from '@/errors/uninspectable-subworkflow-source.error'; import type { ExternalHooks, WorkflowLifecycleHookActor } from '@/external-hooks'; import type { McpSettingsService } from '@/modules/mcp/mcp.settings.service'; import type { InstanceRedactionEnforcementService } from '@/modules/redaction/instance-redaction-enforcement.service'; @@ -81,6 +83,7 @@ describe('WorkflowCreationService', () => { enterpriseWorkflowServiceMock.collectCredentialReferences.mockReturnValue({ ids: new Set(), hasUnresolved: false, + hasUninspectableSource: false, }); // Default: no active floor. Tests opt into a floor explicitly. @@ -138,6 +141,7 @@ describe('WorkflowCreationService', () => { enterpriseWorkflowServiceMock.collectCredentialReferences.mockReturnValue({ ids: new Set(['source-credential']), hasUnresolved: false, + hasUninspectableSource: false, }); const context = await workflowCreationService.prepareBatchContext( @@ -327,6 +331,7 @@ describe('WorkflowCreationService', () => { enterpriseWorkflowServiceMock.collectCredentialReferences.mockReturnValue({ ids: new Set(['credential-1']), hasUnresolved: false, + hasUninspectableSource: false, }); credentialsFinderServiceMock.findCredentialIdsWithScopeForUser.mockResolvedValue( new Set(['credential-1']), @@ -383,6 +388,7 @@ describe('WorkflowCreationService', () => { enterpriseWorkflowServiceMock.collectCredentialReferences.mockReturnValue({ ids: new Set(['credential-1']), hasUnresolved: true, + hasUninspectableSource: false, }); credentialsFinderServiceMock.findCredentialIdsWithScopeForUser.mockResolvedValue( new Set(['credential-1']), @@ -402,6 +408,58 @@ describe('WorkflowCreationService', () => { 'The workflow you are trying to save contains credentials that are not shared with you', ); }); + + it('should pass full credential access to the source check', async () => { + const user = mock(); + const newWorkflow = new WorkflowEntity(); + licenseStateMock.isSharingLicensed.mockReturnValue(true); + projectServiceMock.getProjectWithScope.mockResolvedValue({ id: 'project-1' } as never); + enterpriseWorkflowServiceMock.collectCredentialReferences.mockReturnValue({ + ids: new Set(), + hasUnresolved: false, + hasUninspectableSource: true, + }); + enterpriseWorkflowServiceMock.canUseEveryCredential.mockReturnValue(true); + enterpriseWorkflowServiceMock.validateCredentialPermissionsToUser.mockImplementation(() => { + throw new Error('Stopping for test'); + }); + + await expect( + workflowCreationService.createWorkflow(user, newWorkflow, { projectId: 'project-1' }), + ).rejects.toThrow(); + + expect(enterpriseWorkflowServiceMock.canUseEveryCredential).toHaveBeenCalledWith(user); + expect( + enterpriseWorkflowServiceMock.validateCredentialPermissionsToUser, + ).toHaveBeenCalledWith(newWorkflow, new Set(), { allowUninspectableSource: true }); + }); + + it('should preserve the source error message for a restricted user', async () => { + const user = mock(); + const newWorkflow = new WorkflowEntity(); + const node = { name: 'Sub' } as INode; + licenseStateMock.isSharingLicensed.mockReturnValue(true); + projectServiceMock.getProjectWithScope.mockResolvedValue({ id: 'project-1' } as never); + enterpriseWorkflowServiceMock.collectCredentialReferences.mockReturnValue({ + ids: new Set(), + hasUnresolved: false, + hasUninspectableSource: true, + }); + enterpriseWorkflowServiceMock.canUseEveryCredential.mockReturnValue(false); + enterpriseWorkflowServiceMock.validateCredentialPermissionsToUser.mockImplementation(() => { + throw new UninspectableSubworkflowSourceError(node); + }); + + await expect( + workflowCreationService.createWorkflow(user, newWorkflow, { projectId: 'project-1' }), + ).rejects.toThrow( + /'Sub' node loads its sub-workflow from a source that is resolved only when the workflow runs/, + ); + + expect( + enterpriseWorkflowServiceMock.validateCredentialPermissionsToUser, + ).toHaveBeenCalledWith(newWorkflow, new Set(), { allowUninspectableSource: false }); + }); }); it('should throw BadRequestError when user lacks access to credentials in workflow', async () => { diff --git a/packages/cli/src/workflows/__tests__/workflow.service.ee.test.ts b/packages/cli/src/workflows/__tests__/workflow.service.ee.test.ts index d5efbd912dc..013490a720d 100644 --- a/packages/cli/src/workflows/__tests__/workflow.service.ee.test.ts +++ b/packages/cli/src/workflows/__tests__/workflow.service.ee.test.ts @@ -17,6 +17,7 @@ import { mock } from 'vitest-mock-extended'; import type { ActiveWorkflowManager } from '@/active-workflow-manager'; import type { CredentialsFinderService } from '@n8n/backend-services'; import type { CredentialsService } from '@/credentials/credentials.service'; +import type { NodeTypes } from '@/node-types'; import type { CredentialsPermissionChecker } from '@/executions/pre-execution-checks/credentials-permission-checker'; import type { PolicyEnforcementService } from '@/policy/policy-enforcement.service'; import type { OwnershipService } from '@/services/ownership.service'; @@ -44,10 +45,12 @@ describe('EnterpriseWorkflowService', () => { const credentialsService = mock(); const ownershipService = mock(); const credentialsFinderService = mock(); + const nodeTypes = mock(); const credentialsPermissionChecker = mock(); beforeEach(() => { vi.clearAllMocks(); + nodeTypes.getByNameAndVersion.mockReset(); flags.credSharingEnabled = false; service = new EnterpriseWorkflowService( mock(), // logger @@ -65,6 +68,7 @@ describe('EnterpriseWorkflowService', () => { workflowPublishHistoryRepository, workflowMutationHooks, policyEnforcementService, + nodeTypes, credentialsPermissionChecker, ); }); @@ -401,6 +405,216 @@ describe('EnterpriseWorkflowService', () => { }); }); + describe('validateWorkflowCredentialUsage() - sub-workflow source', () => { + const URL_SOURCE = { source: 'url', workflowUrl: 'https://example.com/workflow.json' }; + const subworkflowNode = (parameters: Record, overrides: Partial = {}) => + ({ + id: 'sub-1', + name: 'Sub', + type: 'n8n-nodes-base.executeWorkflow', + typeVersion: 1.2, + position: [0, 0], + parameters, + ...overrides, + }) as unknown as INode; + const save = ( + newNodes: INode[], + previousNodes: INode[] = [], + options?: { allowUninspectableSource?: boolean }, + ) => + service.validateWorkflowCredentialUsage( + { nodes: newNodes } as unknown as IWorkflowBase, + { nodes: previousNodes } as unknown as IWorkflowBase, + [], + [], + options, + ); + + it.each([ + ['"url"', URL_SOURCE], + ['"localFile"', { source: 'localFile', workflowPath: '/data/workflow.json' }], + ['an expression', { source: '={{ $json.source }}' }], + ['not a string', { source: 42 }], + ])('rejects a new Execute Sub-workflow node whose source is %s', (_label, parameters) => { + expect(() => save([subworkflowNode(parameters)])).toThrow(/cannot be checked/); + }); + + it.each([ + ['absent', {}], + ['"database"', { source: 'database', workflowId: { __rl: true, value: 'wf-1', mode: 'id' } }], + [ + '"parameter"', + { source: 'parameter', workflowJson: JSON.stringify({ nodes: [], connections: {} }) }, + ], + ])('accepts a new Execute Sub-workflow node whose source is %s', (_label, parameters) => { + expect(() => save([subworkflowNode(parameters)])).not.toThrow(); + }); + + it('rejects a Workflow Tool node whose source is neither "database" nor "parameter"', () => { + const node = subworkflowNode(URL_SOURCE, { + type: '@n8n/n8n-nodes-langchain.toolWorkflow', + typeVersion: 2, + }); + expect(() => save([node])).toThrow(/cannot be checked/); + }); + + it('rejects the synthetic HITL tool variant of a url-sourced Execute Sub-workflow node', () => { + const node = subworkflowNode(URL_SOURCE, { type: 'n8n-nodes-base.executeWorkflowHitlTool' }); + expect(() => save([node])).toThrow(/cannot be checked/); + }); + + it('rejects a url-sourced node nested inside an inline sub-workflow', () => { + const inner = subworkflowNode(URL_SOURCE, { id: 'inner', name: 'Inner' }); + const outer = subworkflowNode({ + source: 'parameter', + workflowJson: JSON.stringify({ nodes: [inner], connections: {} }), + }); + expect(() => save([outer])).toThrow(/cannot be checked/); + }); + + it('rejects a url-sourced Execute Sub-workflow tool inside an inline agent parameter', () => { + const agent = { + id: 'agent-1', + name: 'Agent', + type: 'n8n-nodes-base.messageAnAgent', + typeVersion: 2, + position: [0, 0], + parameters: { + agentSource: 'inline', + inlineAgent: { + config: { + tools: [ + { nodeType: 'n8n-nodes-base.executeWorkflowTool', nodeParameters: URL_SOURCE }, + ], + }, + }, + }, + } as unknown as INode; + expect(() => save([agent])).toThrow(/cannot be checked/); + }); + + it('rejects an existing editable node that is changed to a url source', () => { + const previous = subworkflowNode({ source: 'database', workflowId: 'wf-1' }); + expect(() => save([subworkflowNode(URL_SOURCE)], [previous])).toThrow(/cannot be checked/); + }); + + it('allows renaming, moving and disabling a stored URL node', () => { + const previous = subworkflowNode(URL_SOURCE); + const edited = { ...previous, name: 'Renamed', position: [10, 10], disabled: true } as INode; + + const result = save([edited], [previous]); + + expect(result.nodes[0]).toEqual(edited); + }); + + it('rejects URL changes when the node description is unavailable', () => { + const previous = subworkflowNode(URL_SOURCE); + const changed = subworkflowNode({ + source: 'url', + workflowUrl: 'https://example.com/other.json', + }); + expect(() => save([changed], [previous])).toThrow(/cannot be checked/); + }); + + it('rejects retry setting changes on a stored URL node', () => { + const previous = subworkflowNode(URL_SOURCE); + const changed = { ...previous, retryOnFail: true } as INode; + expect(() => save([changed], [previous])).toThrow(/cannot be checked/); + }); + + describe('with the node type description available', () => { + beforeEach(() => { + nodeTypes.getByNameAndVersion.mockReturnValue({ + description: { + properties: [ + { displayName: 'Source', name: 'source', type: 'options', default: 'database' }, + { + displayName: 'Workflow', + name: 'workflowId', + type: 'string', + default: '', + displayOptions: { show: { source: ['database'] } }, + }, + { + displayName: 'URL', + name: 'workflowUrl', + type: 'string', + default: '', + displayOptions: { show: { source: ['url'] } }, + }, + { displayName: 'Mode', name: 'mode', type: 'options', default: 'once' }, + ], + }, + } as never); + }); + + it('accepts omitted parameter defaults', () => { + // A node stored through the API may carry a default the editor strips on save. + const stored = subworkflowNode({ ...URL_SOURCE, mode: 'once' }); + const fromEditor = { ...subworkflowNode(URL_SOURCE), name: 'Renamed' } as INode; + + const result = save([fromEditor], [stored]); + + expect(result.nodes[0]).toEqual({ ...stored, name: 'Renamed' }); + }); + + it('accepts omitted hidden parameters', () => { + // The editor drops the old database workflow ID when the source is URL. + const stored = subworkflowNode({ ...URL_SOURCE, workflowId: 'old-workflow' }); + const fromEditor = { ...subworkflowNode(URL_SOURCE), name: 'Renamed' } as INode; + + const result = save([fromEditor], [stored]); + + expect(result.nodes[0]).toEqual({ ...stored, name: 'Renamed' }); + }); + + it('rejects URL changes after parameter normalization', () => { + const stored = subworkflowNode({ ...URL_SOURCE, mode: 'once' }); + const changed = subworkflowNode({ + source: 'url', + workflowUrl: 'https://example.com/other.json', + }); + + expect(() => save([changed], [stored])).toThrow(/cannot be checked/); + }); + }); + + it('accepts url-sourced nodes when the caller allows uninspectable sources', () => { + const previous = subworkflowNode(URL_SOURCE); + const changed = subworkflowNode({ + source: 'url', + workflowUrl: 'https://example.com/other.json', + }); + const options = { allowUninspectableSource: true }; + + expect(() => save([subworkflowNode(URL_SOURCE)], [], options)).not.toThrow(); + expect(save([changed], [previous], options).nodes[0]).toEqual(changed); + }); + + it('checks source permissions when validating a new workflow', () => { + const workflow = { nodes: [subworkflowNode(URL_SOURCE)] } as unknown as IWorkflowBase; + + expect(() => service.validateCredentialPermissionsToUser(workflow, [])).toThrow( + /cannot be checked/, + ); + expect(() => + service.validateCredentialPermissionsToUser(workflow, [], { + allowUninspectableSource: true, + }), + ).not.toThrow(); + }); + + it('reports runtime-loaded sources even when there are no credential IDs', () => { + const workflow = { nodes: [subworkflowNode(URL_SOURCE)] } as unknown as IWorkflowBase; + + expect(service.collectCredentialReferences(workflow)).toEqual({ + ids: new Set(), + hasUnresolved: false, + hasUninspectableSource: true, + }); + }); + }); + describe('validateWorkflowCredentialUsage() - credential added to an existing node', () => { const httpNode = ( credentials?: INode['credentials'], diff --git a/packages/cli/src/workflows/__tests__/workflow.service.test.ts b/packages/cli/src/workflows/__tests__/workflow.service.test.ts index dbaee36c3d5..8edf980767a 100644 --- a/packages/cli/src/workflows/__tests__/workflow.service.test.ts +++ b/packages/cli/src/workflows/__tests__/workflow.service.test.ts @@ -58,7 +58,7 @@ import type { WorkflowPublicationStatusService } from '@/workflows/publication/w import type { WorkflowMutationHooksProxy } from '@/workflows/workflow-mutation-hooks-proxy.service'; import type { WorkflowPublishGuardProxy } from '@/workflows/workflow-publish-guard-proxy.service'; import type { WorkflowValidationService } from '@/workflows/workflow-validation.service'; -import { NodeGroupRulesFlagGate } from '@/workflows/node-group-rules-flag-gate'; +import type { NodeGroupRulesFlagGate } from '@/workflows/node-group-rules-flag-gate'; import type { RestrictedNodeTypesProviderProxy } from '@/workflows/restricted-node-types-provider-proxy.service'; import { WorkflowService } from '@/workflows/workflow.service'; import { ALL_RULES_RELAXED, NO_RULES_RELAXED } from './node-group-rules.test-data'; @@ -73,6 +73,7 @@ describe('WorkflowService', () => { let workflowRepositoryMock: MockProxy<{ getManyAndCountWithSharingSubquery: Mock; getWorkflowsAndFoldersWithCountWithSharingSubquery: Mock; + findCallableSubworkflows: Mock; }>; let roleServiceMock: MockProxy; let webhookServiceMock: MockProxy; @@ -94,8 +95,6 @@ describe('WorkflowService', () => { webhookServiceMock = mock(); workflowFinderServiceMock = mock(); - // By default the requester can read the supplied parent workflow. - workflowFinderServiceMock.findWorkflowForUser.mockResolvedValue(mock()); globalConfigMock = mock({ workflows: mock({ useWorkflowPublicationService: false }), @@ -163,7 +162,6 @@ describe('WorkflowService', () => { workflowRoles: expect.any(Array), }), undefined, - undefined, // callableForParentWorkflowId ); }); @@ -183,7 +181,6 @@ describe('WorkflowService', () => { workflowRoles: expect.any(Array), }), undefined, - undefined, // callableForParentWorkflowId ); }); @@ -203,7 +200,6 @@ describe('WorkflowService', () => { workflowRoles: expect.any(Array), }), undefined, - undefined, // callableForParentWorkflowId ); }); @@ -223,110 +219,82 @@ describe('WorkflowService', () => { workflowRoles: expect.any(Array), }), undefined, - undefined, // callableForParentWorkflowId ); }); - describe('callableForParentWorkflowId', () => { - test('should pass parentWorkflowId when includeCallableSubworkflows is true', async () => { + describe('getCallableSubworkflows', () => { + test('should query with read roles and the Execute Workflow Trigger node type', async () => { const user = mock(); - const options = { - filter: { - includeCallableSubworkflows: true, - parentWorkflowId: 'parent-wf-id', - }, - }; + workflowRepositoryMock.findCallableSubworkflows.mockResolvedValue({ + workflows: [], + count: 0, + }); - await workflowService.getMany(user, options); + await workflowService.getCallableSubworkflows(user, 'parent-wf-id', { + query: 'search', + skip: 10, + take: 5, + }); - expect(workflowRepositoryMock.getManyAndCountWithSharingSubquery).toHaveBeenCalledWith( + expect(roleServiceMock.rolesWithScope).toHaveBeenCalledWith('project', ['workflow:read']); + expect(roleServiceMock.rolesWithScope).toHaveBeenCalledWith('workflow', ['workflow:read']); + expect(workflowRepositoryMock.findCallableSubworkflows).toHaveBeenCalledWith( user, - expect.any(Object), - options, + { + scopes: ['workflow:read'], + projectRoles: ['project:viewer'], + workflowRoles: ['project:viewer'], + }, 'parent-wf-id', + { + query: 'search', + triggerNodeTypes: ['n8n-nodes-base.executeWorkflowTrigger'], + skip: 10, + take: 5, + }, ); }); - test('should pass undefined when includeCallableSubworkflows is false', async () => { - const user = mock(); - const options = { - filter: { - includeCallableSubworkflows: false, - parentWorkflowId: 'parent-wf-id', - }, - }; + test('should return minimal rows with the project name for team projects only', async () => { + workflowRepositoryMock.findCallableSubworkflows.mockResolvedValue({ + count: 2, + workflows: [ + { + id: 'team-wf', + name: 'Team', + activeVersionId: 'version-1', + isArchived: false, + nodes: [{ type: 'n8n-nodes-base.code' }], + shared: [{ project: { type: 'team', name: 'Team Project' } }], + }, + { + id: 'personal-wf', + name: 'Personal', + activeVersionId: null, + isArchived: true, + shared: [{ project: { type: 'personal', name: 'Jane ' } }], + }, + ], + }); - await workflowService.getMany(user, options); + const result = await workflowService.getCallableSubworkflows(mock(), 'parent-wf-id', { + skip: 0, + take: 10, + }); - expect(workflowRepositoryMock.getManyAndCountWithSharingSubquery).toHaveBeenCalledWith( - user, - expect.any(Object), - options, - undefined, - ); - }); - - test('should pass undefined when includeCallableSubworkflows is true but parentWorkflowId is missing', async () => { - const user = mock(); - const options = { - filter: { - includeCallableSubworkflows: true, - }, - }; - - await workflowService.getMany(user, options); - - expect(workflowRepositoryMock.getManyAndCountWithSharingSubquery).toHaveBeenCalledWith( - user, - expect.any(Object), - options, - undefined, - ); - }); - - test('should pass undefined when includeCallableSubworkflows is true but parentWorkflowId is not a string', async () => { - const user = mock(); - const options = { - filter: { - includeCallableSubworkflows: true, - parentWorkflowId: 123, // invalid type - }, - }; - - await workflowService.getMany(user, options); - - expect(workflowRepositoryMock.getManyAndCountWithSharingSubquery).toHaveBeenCalledWith( - user, - expect.any(Object), - options, - undefined, - ); - }); - - test('should pass undefined when the requester cannot read the parent workflow', async () => { - const user = mock(); - const options = { - filter: { - includeCallableSubworkflows: true, - parentWorkflowId: 'parent-wf-id', - }, - }; - // Requester has no read access to the supplied parent workflow. - workflowFinderServiceMock.findWorkflowForUser.mockResolvedValue(null); - - await workflowService.getMany(user, options); - - expect(workflowFinderServiceMock.findWorkflowForUser).toHaveBeenCalledWith( - 'parent-wf-id', - user, - ['workflow:read'], - ); - expect(workflowRepositoryMock.getManyAndCountWithSharingSubquery).toHaveBeenCalledWith( - user, - expect.any(Object), - options, - undefined, - ); + expect(result).toEqual({ + count: 2, + data: [ + { + id: 'team-wf', + name: 'Team', + active: true, + isArchived: false, + projectName: 'Team Project', + }, + { id: 'personal-wf', name: 'Personal', active: false, isArchived: true }, + ], + }); }); }); @@ -461,12 +429,10 @@ describe('WorkflowService', () => { expect(result).toMatchObject({ workflows: [folder], count: 1 }); expect( workflowRepositoryMock.getWorkflowsAndFoldersWithCountWithSharingSubquery, - ).toHaveBeenCalledWith( - expect.anything(), - expect.anything(), - { ...restrictedNodeFilter, workflowIdsIn: null }, - undefined, - ); + ).toHaveBeenCalledWith(expect.anything(), expect.anything(), { + ...restrictedNodeFilter, + workflowIdsIn: null, + }); }); test('limits the list query to the restricted workflow ids', async () => { @@ -479,7 +445,6 @@ describe('WorkflowService', () => { expect.anything(), expect.anything(), { ...restrictedNodeFilter, workflowIdsIn }, - undefined, ); }); }); diff --git a/packages/cli/src/workflows/publication/__tests__/format-node-failures.test.ts b/packages/cli/src/workflows/publication/__tests__/format-node-failures.test.ts index c82fb7ac37d..b5af270a782 100644 --- a/packages/cli/src/workflows/publication/__tests__/format-node-failures.test.ts +++ b/packages/cli/src/workflows/publication/__tests__/format-node-failures.test.ts @@ -1,4 +1,7 @@ -import { formatNodeFailures } from '@/workflows/publication/format-node-failures'; +import { + formatFailedActivationError, + formatNodeFailures, +} from '@/workflows/publication/format-node-failures'; describe('formatNodeFailures', () => { test('returns an empty string for no failures', () => { @@ -20,3 +23,20 @@ describe('formatNodeFailures', () => { ).toBe('"Webhook": port in use; "Schedule Trigger": bad cron'); }); }); + +describe('formatFailedActivationError', () => { + test('returns a single failure message verbatim', () => { + expect(formatFailedActivationError([{ nodeName: 'Webhook', message: 'port in use' }])).toBe( + 'port in use', + ); + }); + + test('prefixes and joins several failures', () => { + expect( + formatFailedActivationError([ + { nodeName: 'Webhook', message: 'port in use' }, + { nodeName: 'Schedule Trigger', message: 'bad cron' }, + ]), + ).toBe('Triggers failed to activate: "Webhook": port in use; "Schedule Trigger": bad cron'); + }); +}); diff --git a/packages/cli/src/workflows/publication/__tests__/publication-status-reporter.test.ts b/packages/cli/src/workflows/publication/__tests__/publication-status-reporter.test.ts index a0d28f17cf9..c85c7c46e39 100644 --- a/packages/cli/src/workflows/publication/__tests__/publication-status-reporter.test.ts +++ b/packages/cli/src/workflows/publication/__tests__/publication-status-reporter.test.ts @@ -440,6 +440,74 @@ describe('PublicationStatusReporter', () => { 'v-2', operationContext, ); + expect(push.sendToUsers).toHaveBeenCalledWith( + { + type: 'workflowFailedToActivate', + data: { workflowId: 'wf-1', errorMessage: 'partial registration failed', nodeId: 'b' }, + }, + userIds, + ); + }); + + test('failed with several failed triggers pushes no nodeId', async () => { + const errorMessage = + 'Triggers failed to activate: "Schedule": cron unavailable; "Cron": bad cron'; + + await reporter.report(makeRecord(), { + type: 'failed', + error: new Error(errorMessage), + triggerStatuses: [ + { + nodeId: 'b', + nodeName: 'Schedule', + status: 'failed', + triggerKind: 'in-memory', + errorMessage: 'cron unavailable', + }, + { + nodeId: 'c', + nodeName: 'Cron', + status: 'failed', + triggerKind: 'in-memory', + errorMessage: 'bad cron', + }, + ], + }); + + expect(push.sendToUsers).toHaveBeenCalledWith( + { type: 'workflowFailedToActivate', data: { workflowId: 'wf-1', errorMessage } }, + userIds, + ); + }); + + // A policy refusal marks every trigger failed with the policy error, so the + // one failed row is not the node whose own error this is. + test('failed by policy with one failed row pushes no nodeId', async () => { + const error = new PolicyViolationError([ + { kind: 'node-type-unavailable', checkId: 'check-1', message: 'Blocked by policy' }, + ]); + + await reporter.report(makeRecord(), { + type: 'failed', + error, + triggerStatuses: [ + { + nodeId: 'b', + nodeName: 'Schedule', + status: 'failed', + triggerKind: 'in-memory', + errorMessage: error.message, + }, + ], + }); + + expect(push.sendToUsers).toHaveBeenCalledWith( + { + type: 'workflowFailedToActivate', + data: { workflowId: 'wf-1', errorMessage: error.message }, + }, + userIds, + ); }); test('partial marks partial_success, writes all trigger rows, and pushes the failures without registering activation errors', async () => { diff --git a/packages/cli/src/workflows/publication/__tests__/workflow-publication-applier.test.ts b/packages/cli/src/workflows/publication/__tests__/workflow-publication-applier.test.ts index 01341cc0995..6d3a796409b 100644 --- a/packages/cli/src/workflows/publication/__tests__/workflow-publication-applier.test.ts +++ b/packages/cli/src/workflows/publication/__tests__/workflow-publication-applier.test.ts @@ -1000,6 +1000,7 @@ describe('WorkflowPublicationApplier', () => { }, ], }); + expect((result as { error: Error }).error).toBe(error); expect(workflowPublishedVersionRepository.setPublishedVersion).toHaveBeenCalledWith( 'wf-1', 'v-2', diff --git a/packages/cli/src/workflows/publication/__tests__/workflow-publication-outbox-cleanup.task.test.ts b/packages/cli/src/workflows/publication/__tests__/workflow-publication-outbox-cleanup.task.test.ts index 9901c1db7b2..a786156bd42 100644 --- a/packages/cli/src/workflows/publication/__tests__/workflow-publication-outbox-cleanup.task.test.ts +++ b/packages/cli/src/workflows/publication/__tests__/workflow-publication-outbox-cleanup.task.test.ts @@ -12,9 +12,11 @@ describe('WorkflowPublicationOutboxCleanupTask', () => { it('should declare the configured cleanup cadence, a durable run and a run on takeover', () => { expect(task.name).toBe('publication-outbox-cleanup'); expect(task.schedule).toEqual({ kind: 'interval', intervalSeconds: 30 }); - expect(task.effects).toBe('idempotent'); - expect(task.placement).toEqual({ scope: 'cluster', durable: true, runOnTakeover: true }); - expect(task.retryDelaySeconds).toBe(30); + expect(task.target).toEqual({ + scope: 'cluster', + scheduler: { retryOnFailure: true }, + leaderTimer: { runOnTakeover: true, retryDelaySeconds: 30 }, + }); }); it('should clean up the outbox on run, handing the pass its abort signal', async () => { diff --git a/packages/cli/src/workflows/publication/__tests__/workflow-publication-status.service.test.ts b/packages/cli/src/workflows/publication/__tests__/workflow-publication-status.service.test.ts index 0607eb2a970..7d1fa91757f 100644 --- a/packages/cli/src/workflows/publication/__tests__/workflow-publication-status.service.test.ts +++ b/packages/cli/src/workflows/publication/__tests__/workflow-publication-status.service.test.ts @@ -8,6 +8,7 @@ import type { } from '@n8n/db'; import { mock } from 'vitest-mock-extended'; +import { UNKNOWN_FAILURE_REASON } from '@/constants'; import { WorkflowPublicationStatusService } from '@/workflows/publication/workflow-publication-status.service'; describe('WorkflowPublicationStatusService', () => { @@ -260,4 +261,93 @@ describe('WorkflowPublicationStatusService', () => { expect(outboxRepository.findInFlightByWorkflowId).not.toHaveBeenCalled(); }); }); + + describe('getFailedActivationError', () => { + const nodes = [ + { id: 'node-1', name: 'Webhook' }, + { id: 'node-2', name: 'Schedule' }, + ]; + + it('returns null without consulting the outbox when there are no rows', async () => { + triggerStatusRepository.findByWorkflowId.mockResolvedValue([]); + + expect(await service.getFailedActivationError(WORKFLOW_ID, nodes)).toBeNull(); + + expect(triggerStatusRepository.findByWorkflowId).toHaveBeenCalledWith(WORKFLOW_ID); + expect(outboxRepository.findInFlightByWorkflowId).not.toHaveBeenCalled(); + }); + + it('returns null when every trigger activated', async () => { + triggerStatusRepository.findByWorkflowId.mockResolvedValue([ + makeRow({ nodeId: 'node-1', status: 'activated' }), + makeRow({ nodeId: 'node-2', status: 'activated' }), + ]); + + expect(await service.getFailedActivationError(WORKFLOW_ID, nodes)).toBeNull(); + }); + + it('returns null for a partial publication', async () => { + triggerStatusRepository.findByWorkflowId.mockResolvedValue([ + makeRow({ nodeId: 'node-1', status: 'activated' }), + makeRow({ nodeId: 'node-2', status: 'failed', errorMessage: 'err2' }), + ]); + + expect(await service.getFailedActivationError(WORKFLOW_ID, nodes)).toBeNull(); + }); + + it('returns a single failure verbatim', async () => { + triggerStatusRepository.findByWorkflowId.mockResolvedValue([ + makeRow({ nodeId: 'node-1', status: 'failed', errorMessage: 'err1' }), + ]); + + expect(await service.getFailedActivationError(WORKFLOW_ID, nodes)).toBe('err1'); + }); + + it("orders several failures by the caller's node order, not by id", async () => { + triggerStatusRepository.findByWorkflowId.mockResolvedValue([ + makeRow({ nodeId: 'node-1', status: 'failed', errorMessage: 'err1' }), + makeRow({ nodeId: 'node-2', status: 'failed', errorMessage: 'err2' }), + ]); + + expect(await service.getFailedActivationError(WORKFLOW_ID, [nodes[1], nodes[0]])).toBe( + 'Triggers failed to activate: "Schedule": err2; "Webhook": err1', + ); + }); + + it('falls back to the node id for a node the caller does not know, after the known ones', async () => { + triggerStatusRepository.findByWorkflowId.mockResolvedValue([ + makeRow({ nodeId: 'deleted-node', status: 'failed', errorMessage: 'err2' }), + makeRow({ nodeId: 'node-1', status: 'failed', errorMessage: 'err1' }), + ]); + + expect(await service.getFailedActivationError(WORKFLOW_ID, [nodes[0]])).toBe( + 'Triggers failed to activate: "Webhook": err1; "deleted-node": err2', + ); + }); + + it('orders several unknown ids by id, so the message is stable', async () => { + triggerStatusRepository.findByWorkflowId.mockResolvedValue([ + makeRow({ nodeId: 'node-9', status: 'failed', errorMessage: 'err9' }), + makeRow({ nodeId: 'node-8', status: 'failed', errorMessage: 'err8' }), + makeRow({ nodeId: 'node-1', status: 'failed', errorMessage: 'err1' }), + ]); + + expect(await service.getFailedActivationError(WORKFLOW_ID, [nodes[0]])).toBe( + 'Triggers failed to activate: "Webhook": err1; "node-8": err8; "node-9": err9', + ); + }); + + it.each([null, ''])( + 'reports an unknown reason for an empty error message (%j)', + async (errorMessage) => { + triggerStatusRepository.findByWorkflowId.mockResolvedValue([ + makeRow({ nodeId: 'node-1', status: 'failed', errorMessage }), + ]); + + expect(await service.getFailedActivationError(WORKFLOW_ID, nodes)).toBe( + UNKNOWN_FAILURE_REASON, + ); + }, + ); + }); }); diff --git a/packages/cli/src/workflows/publication/format-node-failures.ts b/packages/cli/src/workflows/publication/format-node-failures.ts index 0e63a1f8f9f..e4578c0c795 100644 --- a/packages/cli/src/workflows/publication/format-node-failures.ts +++ b/packages/cli/src/workflows/publication/format-node-failures.ts @@ -1,4 +1,12 @@ -/** Formats per-node failures as `"NodeName": message`, joined with `; `. Callers add the prefix. */ +/** Formats per-node failures as `"NodeName": message`, joined with `; `. Callers add their own prefix. */ export function formatNodeFailures(failures: Array<{ nodeName: string; message: string }>): string { return failures.map(({ nodeName, message }) => `"${nodeName}": ${message}`).join('; '); } + +/** The activation error of a failed publication: one failure verbatim, several prefixed and joined. */ +export function formatFailedActivationError( + failures: Array<{ nodeName: string; message: string }>, +): string { + if (failures.length === 1) return failures[0].message; + return `Triggers failed to activate: ${formatNodeFailures(failures)}`; +} diff --git a/packages/cli/src/workflows/publication/publication-status-reporter.ts b/packages/cli/src/workflows/publication/publication-status-reporter.ts index 635aa35f268..46a85bf5437 100644 --- a/packages/cli/src/workflows/publication/publication-status-reporter.ts +++ b/packages/cli/src/workflows/publication/publication-status-reporter.ts @@ -123,10 +123,16 @@ export class PublicationStatusReporter { }); // An expected denial, already logged as a warning by the applier — the // terminal state and the UI push stand, the fault report does not. - if (!isPolicyRefusal(result.error)) { + const policyRefusal = isPolicyRefusal(result.error); + if (!policyRefusal) { this.errorReporter.error(result.error, { shouldBeLogged: true }); } - await this.pushFailedToActivate(record.workflowId, result.error.message); + // Name the node only when one trigger failed with its own error: the FE prefixes the toast with it. + // A policy refusal fails every trigger with the same error, so it names none. + const failedTriggers = (triggerStatuses ?? []).filter((s) => s.status === 'failed'); + const nodeId = + !policyRefusal && failedTriggers.length === 1 ? failedTriggers[0].nodeId : undefined; + await this.pushFailedToActivate(record.workflowId, result.error.message, nodeId); return; } @@ -152,7 +158,7 @@ export class PublicationStatusReporter { const failures = triggerStatuses.filter( (s): s is FailedTriggerPublicationStatus => s.status === 'failed', ); - const errorMessage = this.formatActivationError(failures); + const errorMessage = this.formatPartialActivationError(failures); this.logger.warn('Workflow partially published; some triggers failed to activate', { workflowId: record.workflowId, @@ -200,7 +206,7 @@ export class PublicationStatusReporter { } /** Builds a human-readable message naming each failed node and its error. */ - private formatActivationError(failures: FailedTriggerPublicationStatus[]): string { + private formatPartialActivationError(failures: FailedTriggerPublicationStatus[]): string { const detail = formatNodeFailures( failures.map(({ nodeName, errorMessage }) => ({ nodeName, message: errorMessage })), ); @@ -209,10 +215,14 @@ export class PublicationStatusReporter { } /** Pushes a failed-to-activate status to clients connected to any main. */ - private async pushFailedToActivate(workflowId: string, errorMessage: string): Promise { + private async pushFailedToActivate( + workflowId: string, + errorMessage: string, + nodeId?: string, + ): Promise { await this.pushStatus({ type: 'workflowFailedToActivate', - data: { workflowId, errorMessage }, + data: { workflowId, errorMessage, nodeId }, }); } diff --git a/packages/cli/src/workflows/publication/workflow-publication-applier.ts b/packages/cli/src/workflows/publication/workflow-publication-applier.ts index b3d1000edc6..88f3e18a58c 100644 --- a/packages/cli/src/workflows/publication/workflow-publication-applier.ts +++ b/packages/cli/src/workflows/publication/workflow-publication-applier.ts @@ -22,7 +22,10 @@ import { DurableJobProvisioner } from '@/scheduling/durable-job-provisioner'; import { WorkflowScheduledJobOwner } from '@/scheduling/workflow-scheduled-job-owner'; import { OwnershipService } from '@/services/ownership.service'; import { Telemetry } from '@/telemetry'; -import { formatNodeFailures } from '@/workflows/publication/format-node-failures'; +import { + formatFailedActivationError, + formatNodeFailures, +} from '@/workflows/publication/format-node-failures'; import { healNodeIds } from '@/workflows/publication/heal-node-ids'; import type { PublicationResult, @@ -610,13 +613,14 @@ export class WorkflowPublicationApplier { * Combines multiple per trigger failures into a single error. */ private toActivationError(failures: TriggerActivationFailure[]): Error { + // The lone error keeps its class: the reporter checks it for a policy refusal. if (failures.length === 1) return failures[0].error; - const detail = formatNodeFailures( - failures.map(({ nodeName, error }) => ({ nodeName, message: error.message })), + return new Error( + formatFailedActivationError( + failures.map(({ nodeName, error }) => ({ nodeName, message: error.message })), + ), ); - - return new Error(`Triggers failed to activate: ${detail}`); } /** diff --git a/packages/cli/src/workflows/publication/workflow-publication-outbox-cleanup.task.ts b/packages/cli/src/workflows/publication/workflow-publication-outbox-cleanup.task.ts index 73700bb27f5..8f1ab1641a4 100644 --- a/packages/cli/src/workflows/publication/workflow-publication-outbox-cleanup.task.ts +++ b/packages/cli/src/workflows/publication/workflow-publication-outbox-cleanup.task.ts @@ -1,6 +1,6 @@ import { WorkflowsConfig } from '@n8n/config'; -import { intervalFromSeconds, SystemTask } from '@n8n/decorators'; -import type { SystemTaskEffects, SystemTaskPlacement, SystemTaskSchedule } from '@n8n/decorators'; +import { clusterTarget, intervalFromSeconds, SystemTask } from '@n8n/decorators'; +import type { SystemTaskSchedule } from '@n8n/decorators'; import { WorkflowPublicationOutboxCleanupService } from './workflow-publication-outbox-cleanup.service'; @@ -16,17 +16,14 @@ export class WorkflowPublicationOutboxCleanupTask implements SystemTask { this.workflowsConfig.publicationOutboxCleanupIntervalSeconds, ); - readonly effects: SystemTaskEffects = 'idempotent'; - - readonly placement: SystemTaskPlacement = { - scope: 'cluster', - durable: true, - /** A new leader enqueues one terminal row per active workflow, so a backlog is waiting. */ - runOnTakeover: true, - }; - - /** Only the in-memory timer, which runs whenever the task does not run durably, honors this. */ - readonly retryDelaySeconds = 30; + readonly target = clusterTarget({ + scheduler: { retryOnFailure: true }, + leaderTimer: { + /** A new leader enqueues one terminal row per active workflow, so a backlog is waiting. */ + runOnTakeover: true, + retryDelaySeconds: 30, + }, + }); constructor( private readonly workflowsConfig: WorkflowsConfig, diff --git a/packages/cli/src/workflows/publication/workflow-publication-status.service.ts b/packages/cli/src/workflows/publication/workflow-publication-status.service.ts index 68f091f415c..5e39e011495 100644 --- a/packages/cli/src/workflows/publication/workflow-publication-status.service.ts +++ b/packages/cli/src/workflows/publication/workflow-publication-status.service.ts @@ -6,6 +6,10 @@ import { WorkflowPublicationTriggerStatusRepository, } from '@n8n/db'; import { Service } from '@n8n/di'; +import type { INode } from 'n8n-workflow'; + +import { UNKNOWN_FAILURE_REASON } from '@/constants'; +import { formatFailedActivationError } from '@/workflows/publication/format-node-failures'; @Service() export class WorkflowPublicationStatusService { @@ -70,6 +74,30 @@ export class WorkflowPublicationStatusService { return statuses; } + /** + * The activation error of a workflow whose last publication failed, worded + * like the outbox record and the push on the activation-outcome path. Null + * unless every trigger row is `failed`. Rows carry no node name and no order, + * so `nodes` supplies both (nodeId fallback, unknown ids last, by id). + */ + async getFailedActivationError( + workflowId: string, + nodes: Array>, + ): Promise { + const rows = await this.triggerStatusRepository.findByWorkflowId(workflowId); + if (this.deriveStatus(false, rows) !== 'failed') return null; + + const position = new Map(nodes.map((node, index) => [node.id, index])); + const at = (row: WorkflowPublicationTriggerStatus) => position.get(row.nodeId) ?? nodes.length; + const ordered = [...rows].sort((a, b) => at(a) - at(b) || a.nodeId.localeCompare(b.nodeId)); + return formatFailedActivationError( + ordered.map((row) => ({ + nodeName: nodes[at(row)]?.name ?? row.nodeId, // unknown id: index out of range + message: row.errorMessage || UNKNOWN_FAILURE_REASON, + })), + ); + } + private deriveStatus( isPublishing: boolean, currentTriggerStatuses: WorkflowPublicationTriggerStatus[], diff --git a/packages/cli/src/workflows/workflow-creation.service.ts b/packages/cli/src/workflows/workflow-creation.service.ts index 164566936ab..5e1980e8401 100644 --- a/packages/cli/src/workflows/workflow-creation.service.ts +++ b/packages/cli/src/workflows/workflow-creation.service.ts @@ -16,6 +16,7 @@ import { v4 as uuid } from 'uuid'; import { BadRequestError, ForbiddenError, InternalServerError, NotFoundError } from '@n8n/errors'; import { WorkflowValidationError } from '@/errors/response-errors/workflow-validation.error'; +import { UninspectableSubworkflowSourceError } from '@/errors/uninspectable-subworkflow-source.error'; import type { WorkflowActionSource } from '@/events/maps/relay.event-map'; import { ExternalHooks, toWorkflowLifecycleHookActor } from '@/external-hooks'; import { validateEntity } from '@/generic-helpers'; @@ -237,8 +238,11 @@ export class WorkflowCreationService { if (this.licenseState.isSharingLicensed()) { // This is a new workflow, so we simply check if the user has access to // all used credentials - const { ids: credentialIds, hasUnresolved } = - this.enterpriseWorkflowService.collectCredentialReferences(newWorkflow); + const { + ids: credentialIds, + hasUnresolved, + hasUninspectableSource, + } = this.enterpriseWorkflowService.collectCredentialReferences(newWorkflow); if (batchContext) { const uncheckedIds = [...credentialIds].filter( (id) => !batchContext.checkedCredentialIds.has(id), @@ -268,8 +272,15 @@ export class WorkflowCreationService { this.enterpriseWorkflowService.validateCredentialPermissionsToUser( newWorkflow, hasUnresolved ? new Set() : accessibleCredentialIds, + { + allowUninspectableSource: + hasUninspectableSource && this.enterpriseWorkflowService.canUseEveryCredential(user), + }, ); } catch (error) { + if (error instanceof UninspectableSubworkflowSourceError) { + throw new BadRequestError(error.message); + } throw new BadRequestError( 'The workflow you are trying to save contains credentials that are not shared with you', ); diff --git a/packages/cli/src/workflows/workflow.service.ee.ts b/packages/cli/src/workflows/workflow.service.ee.ts index c9d5385afd5..16433b6059e 100644 --- a/packages/cli/src/workflows/workflow.service.ee.ts +++ b/packages/cli/src/workflows/workflow.service.ee.ts @@ -21,10 +21,12 @@ import { hasGlobalScope } from '@n8n/permissions'; import { isRecord } from '@n8n/utils/is-record'; import { In, type EntityManager } from '@n8n/typeorm'; import isEqual from 'lodash/isEqual'; -import type { INode, IWorkflowBase, WorkflowId } from 'n8n-workflow'; +import omit from 'lodash/omit'; +import type { INode, INodeTypeDescription, IWorkflowBase, WorkflowId } from 'n8n-workflow'; import { isNodeWithWorkflowSelector, jsonParse, + NodeHelpers, NodeOperationError, PROJECT_ROOT, UserError, @@ -40,14 +42,46 @@ import { CredentialsPermissionChecker } from '@/executions/pre-execution-checks/ import { FolderNotFoundError } from '@/errors/folder-not-found.error'; import { BadRequestError, NotFoundError } from '@n8n/errors'; import { TransferWorkflowError } from '@/errors/response-errors/transfer-workflow.error'; +import { UninspectableSubworkflowSourceError } from '@/errors/uninspectable-subworkflow-source.error'; import { extractAgentCredentialIds } from '@/modules/agents/utils/extract-agent-credential-ids'; +import { NodeTypes } from '@/node-types'; import { PolicyEnforcementService } from '@/policy/policy-enforcement.service'; import { OwnershipService } from '@/services/ownership.service'; import { ProjectService } from '@/services/project.service.ee'; +import { stripToolSuffix } from '@/utils'; import { WorkflowFinderService } from './workflow-finder.service'; import { WorkflowMutationHooksProxy } from './workflow-mutation-hooks-proxy.service'; +/** + * Database workflows use their own project permissions at runtime. + * Parameter workflows contain JSON we can inspect before saving. + */ +const INSPECTABLE_SUBWORKFLOW_SOURCES = new Set(['database', 'parameter']); + +/** Exclude allowed edits and temporary editor state from the definition comparison. */ +const FREELY_EDITABLE_NODE_FIELDS = ['name', 'position', 'disabled', 'color', 'issues', 'status']; + +/** Tool and HITL tool variants use the same source rules as their base node. */ +function isWorkflowSelectorNode(node: INode): boolean { + if (typeof node.type !== 'string') return false; + return isNodeWithWorkflowSelector({ ...node, type: stripToolSuffix(node.type) }); +} + +type CredentialReferences = { + /** Resolvable credential ids. */ + ids: string[]; + /** A non-managed credential carrying no id, i.e. only a name. */ + hasUnresolved: boolean; + /** A sub-workflow source whose content is not available at save time. */ + hasUninspectableSource: boolean; +}; + +export type CredentialGuardOptions = { + /** Allow content loaded at runtime only for users who can use every credential. */ + allowUninspectableSource?: boolean; +}; + @Service() export class EnterpriseWorkflowService { constructor( @@ -66,6 +100,7 @@ export class EnterpriseWorkflowService { private readonly workflowPublishHistoryRepository: WorkflowPublishHistoryRepository, private readonly workflowMutationHooks: WorkflowMutationHooksProxy, private readonly policyEnforcementService: PolicyEnforcementService, + private readonly nodeTypes: NodeTypes, private readonly credentialsPermissionChecker: CredentialsPermissionChecker, ) {} @@ -185,6 +220,7 @@ export class EnterpriseWorkflowService { validateCredentialPermissionsToUser( workflow: IWorkflowBase, allowedCredentials: Array<{ id: string }> | ReadonlySet, + options: CredentialGuardOptions = {}, ) { // Reuse the shared collector so inline sub-workflow credentials (Execute // Sub-workflow, Workflow Tool, Workflow Retriever) and unresolved name-only @@ -192,8 +228,16 @@ export class EnterpriseWorkflowService { const allowedCredentialIds: ReadonlySet = Array.isArray(allowedCredentials) ? new Set(allowedCredentials.map(({ id }) => id)) : allowedCredentials; - const inaccessibleNodes = this.getNodesWithInaccessibleCreds(workflow, allowedCredentialIds); + const inaccessibleNodes = this.getNodesWithInaccessibleCreds( + workflow, + allowedCredentialIds, + options, + ); if (inaccessibleNodes.length > 0) { + const uninspectableNode = inaccessibleNodes.find((node) => + this.isBlockedByUninspectableSource(node, options), + ); + if (uninspectableNode) throw new UninspectableSubworkflowSourceError(uninspectableNode); throw new UserError('The workflow contains credentials that you do not have access to'); } } @@ -224,6 +268,7 @@ export class EnterpriseWorkflowService { previousVersion, allCredentials, restoredNodes, + { allowUninspectableSource: this.canUseEveryCredential(user) }, ); } catch (error) { if (error instanceof NodeOperationError) { @@ -240,20 +285,12 @@ export class EnterpriseWorkflowService { previousWorkflowVersion: IWorkflowBase, credentialsUserHasAccessTo: Array<{ id: string }>, restoredNodes: INode[] = [], + options: CredentialGuardOptions = {}, ) { - /** - * We only need to check nodes that use credentials the current user cannot access, - * since these can be 2 possibilities: - * - It matches exactly one previous node that already used such a credential: it's a - * read only node and therefore cannot be changed - * - It's a new node, or an editable node that newly references such a credential, - * which indicates tampering and therefore must fail saving - */ - const allowedCredentialIds = credentialsUserHasAccessTo.map((cred) => cred.id); const nodesWithCredentialsUserDoesNotHaveAccessTo = new Set( - this.getNodesWithInaccessibleCreds(newWorkflowVersion, allowedCredentialIds), + this.getNodesWithInaccessibleCreds(newWorkflowVersion, allowedCredentialIds, options), ); // If there are no nodes with credentials the user does not have access to we can skip the rest @@ -265,9 +302,11 @@ export class EnterpriseWorkflowService { // the user could edit that now carries a credential they cannot use fails the // save like a new node does; restoring it would drop the other edits silently. const readOnlyNodeIds = new Set( - this.getNodesWithInaccessibleCreds(previousWorkflowVersion, allowedCredentialIds).map( - (node) => node.id, - ), + this.getNodesWithInaccessibleCreds( + previousWorkflowVersion, + allowedCredentialIds, + options, + ).map((node) => node.id), ); // Node ids are meant to be unique. Edge case: where stored data still repeats one, match the @@ -295,6 +334,7 @@ export class EnterpriseWorkflowService { // ambiguous, and an ambiguous match is not a proof, so no claimant is trusted. const previousNode = previousNodesById.get(node.id); const idClaimedOnce = submittedIdCounts.get(node.id) === 1; + const blockedBySource = this.isBlockedByUninspectableSource(node, options); // A restore brings back a node exactly as a version from this workflow's history // stored it. Any change to it makes it a new edit, which the checks below judge. @@ -308,12 +348,22 @@ export class EnterpriseWorkflowService { nodeId: node.id, nodeCredentials: node.credentials, }); + if (blockedBySource) throw new UninspectableSubworkflowSourceError(node); throw new NodeOperationError( node, `You don't have access to the credentials in the '${node.name}' node. Ask the owner to share them with you.`, ); } + // The editor allows these source settings to be edited. Reject changes + // instead of silently discarding them when we restore the stored node. + if ( + blockedBySource && + !isEqual(this.getNodeDefinition(node), this.getNodeDefinition(previousNode)) + ) { + throw new UninspectableSubworkflowSourceError(node); + } + this.logger.debug('Replacing node with previous version when saving updated workflow', { nodeType: node.type, nodeName: node.name, @@ -335,62 +385,120 @@ export class EnterpriseWorkflowService { } /** - * Get all nodes in a workflow whose credentials the user cannot use: either a - * referenced credential id is not accessible, or the node carries an unresolved - * non-managed reference (id null/empty) that could resolve by name to a - * credential the user does not own. Inline sub-workflow credentials are included. + * Find nodes with inaccessible credentials, unresolved references, or blocked sources. + * Include credentials and sources in nested workflows and agents. */ - getNodesWithInaccessibleCreds(workflow: IWorkflowBase, userCredIds: Iterable) { + getNodesWithInaccessibleCreds( + workflow: IWorkflowBase, + userCredIds: Iterable, + options: CredentialGuardOptions = {}, + ) { if (!workflow.nodes) { return []; } const allowedCredentialIds = userCredIds instanceof Set ? userCredIds : new Set(userCredIds); return workflow.nodes.filter((node) => { - const { ids, hasUnresolved } = this.getNodeCredentialRefs(node); - return hasUnresolved || ids.some((credId) => !allowedCredentialIds.has(credId)); + const { ids, hasUnresolved, hasUninspectableSource } = this.getNodeCredentialRefs(node); + return ( + hasUnresolved || + (hasUninspectableSource && !options.allowUninspectableSource) || + ids.some((credId) => !allowedCredentialIds.has(credId)) + ); }); } collectCredentialReferences(workflow: IWorkflowBase): { ids: Set; hasUnresolved: boolean; + hasUninspectableSource: boolean; } { const ids = new Set(); let hasUnresolved = false; + let hasUninspectableSource = false; for (const node of workflow.nodes ?? []) { const references = this.getNodeCredentialRefs(node); for (const id of references.ids) ids.add(id); hasUnresolved ||= references.hasUnresolved; + hasUninspectableSource ||= references.hasUninspectableSource; } - return { ids, hasUnresolved }; + return { ids, hasUnresolved, hasUninspectableSource }; + } + + canUseEveryCredential(user: User): boolean { + return hasGlobalScope(user, 'credential:use'); + } + + private isBlockedByUninspectableSource(node: INode, options: CredentialGuardOptions): boolean { + if (options.allowUninspectableSource) return false; + return this.getNodeCredentialRefs(node).hasUninspectableSource; } /** - * Collect the credential references a node uses. Besides the node's own - * `credentials`, a node with an inline workflow selector (Execute - * Sub-workflow, Workflow Tool, Workflow Retriever) embeds a whole workflow — - * including its nodes' credentials — inside its `workflowJson` string - * parameter, so those references are walked as well. - * - * Returns `ids` (resolvable credential ids) and `hasUnresolved` (a non-managed - * credential carrying no id, i.e. only a name). A name-only reference can be - * resolved by name to a credential the user cannot access, so callers gating a - * save must reject it rather than treat the node as credential-free. - * `__aiGatewayManaged` credentials with a null id are resolved at execution and - * are exempt. - * - * An inline sub-workflow may itself contain inline sub-workflows, so the walk - * is iterative over an explicit stack: every referenced credential is - * inspected regardless of nesting depth, with no silent cut-off that could let - * a deeply nested reference escape validation. Nesting is inherently bounded by - * the request size (each level embeds its child as literal escaped JSON) and - * cannot cycle, so the stack cannot grow unbounded. + * Compare node behavior without treating editor formatting or allowed edits as changes. */ - private getNodeCredentialRefs(node: INode): { ids: string[]; hasUnresolved: boolean } { + private getNodeDefinition(node: INode): Record { + const definition: Record = omit(node, FREELY_EDITABLE_NODE_FIELDS); + definition.parameters = this.getDisplayedParameters(node); + + const credentials = node.credentials ?? {}; + if (Object.keys(credentials).length === 0) delete definition.credentials; + // The editor persists these only when they differ from their default. + if (!node.continueOnFail) delete definition.continueOnFail; + if (!node.onError || node.onError === 'stopWorkflow') delete definition.onError; + if (!node.notes) delete definition.notes; + + return definition; + } + + /** + * The editor omits default values and hidden parameters on save. + * Compare displayed parameters with defaults filled in so an unchanged node still matches. + */ + private getDisplayedParameters(node: INode) { + const parameters = node.parameters ?? {}; + const description = this.getNodeTypeDescription(node); + if (!description) return parameters; + return ( + NodeHelpers.getNodeParameters( + description.properties, + parameters, + true, + false, + node, + description, + ) ?? {} + ); + } + + private getNodeTypeDescription(node: INode): INodeTypeDescription | null { + try { + return this.nodeTypes.getByNameAndVersion(node.type, node.typeVersion)?.description ?? null; + } catch { + return null; + } + } + + /** + * A missing source defaults to Database. Expressions are not resolved until runtime. + */ + private hasUninspectableSubworkflowSource(node: INode): boolean { + const source = node.parameters?.source; + if (source === undefined) return false; + return !(typeof source === 'string' && INSPECTABLE_SUBWORKFLOW_SOURCES.has(source)); + } + + /** + * Inspect the node and its embedded workflows and agents at every nesting level. + * Report name-only credentials and runtime-loaded sources separately from known IDs; + * neither means the node uses no credentials. Managed Gateway credentials are exempt. + * Use a stack to avoid a call-stack limit. Serialized input bounds the nesting depth. + */ + private getNodeCredentialRefs(node: INode): CredentialReferences { const ids: string[] = []; let hasUnresolved = false; + let hasUninspectableSource = false; const stack: INode[] = [node]; while (stack.length > 0) { @@ -409,7 +517,8 @@ export class EnterpriseWorkflowService { } } - if (isNodeWithWorkflowSelector(current)) { + if (isWorkflowSelectorNode(current)) { + hasUninspectableSource ||= this.hasUninspectableSubworkflowSource(current); stack.push(...this.getInlineWorkflowNodes(current.parameters?.workflowJson)); } @@ -420,7 +529,7 @@ export class EnterpriseWorkflowService { } } - return { ids, hasUnresolved }; + return { ids, hasUnresolved, hasUninspectableSource }; } /** @@ -452,9 +561,8 @@ export class EnterpriseWorkflowService { const nested = Object.values(config).flatMap((value) => this.getAgentToolNodes(value)); if (typeof config.nodeType !== 'string') return nested; - // A node runs as a tool under its `…Tool` variant, which carries the same - // parameters as the node itself. - const type = config.nodeType.replace(/Tool$/, ''); + // Tool variants keep the base node's parameters. + const type = stripToolSuffix(config.nodeType); const parameters = isRecord(config.nodeParameters) ? config.nodeParameters : {}; return [...nested, { type, parameters } as INode]; diff --git a/packages/cli/src/workflows/workflow.service.ts b/packages/cli/src/workflows/workflow.service.ts index 9103c05757e..21aec7c3d51 100644 --- a/packages/cli/src/workflows/workflow.service.ts +++ b/packages/cli/src/workflows/workflow.service.ts @@ -1,5 +1,10 @@ import { UpdateWorkflowHistoryVersionDto } from '@n8n/api-types'; -import type { WorkflowListPublicationStatus, WorkflowExecutionBlockCause } from '@n8n/api-types'; +import type { + CallableSubworkflowsResponse, + ListCallableSubworkflowsQueryDto, + WorkflowExecutionBlockCause, + WorkflowListPublicationStatus, +} from '@n8n/api-types'; import { LicenseState, Logger } from '@n8n/backend-common'; import { EventService, RoleService } from '@n8n/backend-services'; import { GlobalConfig } from '@n8n/config'; @@ -38,7 +43,13 @@ import { ensureError } from '@n8n/utils/errors/ensure-error'; import isEqual from 'lodash/isEqual'; import pick from 'lodash/pick'; import type { INode, INodes, IWorkflowSettings, JsonValue, IConnections } from 'n8n-workflow'; -import { PROJECT_ROOT, Workflow, assert, calculateWorkflowChecksum } from 'n8n-workflow'; +import { + EXECUTE_WORKFLOW_TRIGGER_NODE_TYPE, + PROJECT_ROOT, + Workflow, + assert, + calculateWorkflowChecksum, +} from 'n8n-workflow'; import { v4 as uuid } from 'uuid'; import { @@ -302,11 +313,6 @@ export class WorkflowService { sharingOptions.workflowRoles = workflowRoles; } - const callableForParentWorkflowId = await this.resolveCallableForParentWorkflowId( - user, - options, - ); - const workflowIdsIn = await this.resolveRestrictedWorkflowIds(options); const listOptions = workflowIdsIn === undefined ? options : { ...options, workflowIdsIn }; @@ -317,7 +323,6 @@ export class WorkflowService { user, sharingOptions, listOptions, - callableForParentWorkflowId, ); workflows = workflowsAndFolders.filter((wf) => wf.resource === 'workflow'); @@ -326,7 +331,6 @@ export class WorkflowService { user, sharingOptions, listOptions, - callableForParentWorkflowId, )); } @@ -379,25 +383,42 @@ export class WorkflowService { }; } - private async resolveCallableForParentWorkflowId( + /** + * List the workflows that `parentWorkflowId` can call as sub-workflows, for + * the sub-workflow picker. The caller must check that the user can update + * the parent workflow. Each row holds only the fields the picker shows. + */ + async getCallableSubworkflows( user: User, - options?: ListQuery.Options, - ): Promise { - if (options?.filter?.includeCallableSubworkflows !== true) return undefined; + parentWorkflowId: string, + { query, skip, take }: ListCallableSubworkflowsQueryDto, + ): Promise { + const requiredScopes: Scope[] = ['workflow:read']; + const [projectRoles, workflowRoles] = await Promise.all([ + this.roleService.rolesWithScope('project', requiredScopes), + this.roleService.rolesWithScope('workflow', requiredScopes), + ]); - const parentWorkflowId = - typeof options.filter.parentWorkflowId === 'string' - ? options.filter.parentWorkflowId - : undefined; - if (!parentWorkflowId) return undefined; - - const parentWorkflow = await this.workflowFinderService.findWorkflowForUser( - parentWorkflowId, + const { workflows, count } = await this.workflowRepository.findCallableSubworkflows( user, - ['workflow:read'], + { scopes: requiredScopes, projectRoles, workflowRoles }, + parentWorkflowId, + { query, triggerNodeTypes: [EXECUTE_WORKFLOW_TRIGGER_NODE_TYPE], skip, take }, ); - return parentWorkflow ? parentWorkflowId : undefined; + const data = workflows.map((workflow) => { + const project = workflow.shared?.[0]?.project; + return { + id: workflow.id, + name: workflow.name, + active: workflow.activeVersionId !== null, + isArchived: workflow.isArchived, + // Personal project names hold user names and emails, so only team names are returned. + ...(project?.type === 'team' ? { projectName: project.name } : {}), + }; + }); + + return { count, data }; } private async resolveRestrictedWorkflowIds( @@ -1729,14 +1750,18 @@ export class WorkflowService { // workflow cannot be deleted and unpublishing deprovisions them. This covers // the paths that never published and anything an interrupted unpublish left. // - // Both writes commit together. A deprovision of its own would leave a workflow + // All three writes commit together. A deprovision of its own would leave a workflow // whose delete then failed alive with its schedules stripped. - await this.workflowRepository.runInTransaction({}, async (trx) => { + await this.workflowRepository.runInTransaction({}, async (trx, ctx) => { await this.durableJobProvisioner.deprovisionOwnerInTransaction( trx, this.workflowScheduledJobOwner.ref(workflowId), ); + // A new workflow can be created at this id once the row is gone, so allowlists lose + // the entry in the same transaction. + await this.workflowRepository.removeFromCallerAllowlists([workflowId], ctx); + await trx.delete(WorkflowEntity, { id: workflowId }); }); diff --git a/packages/cli/src/workflows/workflows.controller.ts b/packages/cli/src/workflows/workflows.controller.ts index d69b4c83377..aada90ad763 100644 --- a/packages/cli/src/workflows/workflows.controller.ts +++ b/packages/cli/src/workflows/workflows.controller.ts @@ -4,9 +4,11 @@ import { CreateWorkflowDto, DeactivateWorkflowDto, ExecutionRedactionQueryDtoSchema, + ListCallableSubworkflowsQueryDto, ManualRunDto, TransferWorkflowBodyDto, UpdateWorkflowDto, + type CallableSubworkflowsResponse, type WorkflowPublicationStatus, } from '@n8n/api-types'; import { Logger } from '@n8n/backend-common'; @@ -29,6 +31,7 @@ import { Post, ProjectScope, Put, + Query, RestController, } from '@n8n/decorators'; import { hasGlobalScope, PROJECT_OWNER_ROLE_SLUG } from '@n8n/permissions'; @@ -665,6 +668,22 @@ export class WorkflowsController { return await this.workflowPublicationStatusService.getStatus(workflowId); } + /** + * Lists the workflows that this workflow can call as sub-workflows. Only + * editors of the parent can add a sub-workflow call, so this requires + * `workflow:update` on the parent. + */ + @Get('/:workflowId/callable-subworkflows') + @ProjectScope('workflow:update') + async getCallableSubworkflows( + req: AuthenticatedRequest, + _res: unknown, + @Param('workflowId') workflowId: string, + @Query query: ListCallableSubworkflowsQueryDto, + ): Promise { + return await this.workflowService.getCallableSubworkflows(req.user, workflowId, query); + } + @Post('/with-node-types') async getWorkflowsWithNodesIncluded(req: AuthenticatedRequest, res: express.Response) { try { diff --git a/packages/cli/templates/admin-consent-callback.handlebars b/packages/cli/templates/admin-consent-callback.handlebars new file mode 100644 index 00000000000..b3095fa094d --- /dev/null +++ b/packages/cli/templates/admin-consent-callback.handlebars @@ -0,0 +1,19 @@ + + + n8n - Administrator consent + + + +

Permissions approved

+ Everyone in your organisation can now sign in to n8n for this setup. The window can be + closed, and the sign-in can be started again. + {{!-- + Deliberately silent. The other callback pages announce themselves on a + channel every credential sign-in listens to, and this grant lands on the + tenant rather than on a credential -- so saying "success" here would + report whichever sign-in happened to be waiting as connected. + --}} + + diff --git a/packages/cli/test/integration/active-workflows.api.test.ts b/packages/cli/test/integration/active-workflows.api.test.ts index 0e0032146e7..a66acf9962a 100644 --- a/packages/cli/test/integration/active-workflows.api.test.ts +++ b/packages/cli/test/integration/active-workflows.api.test.ts @@ -6,7 +6,10 @@ import { shareWorkflowWithUsers, testDb, } from '@n8n/backend-test-utils'; -import type { User } from '@n8n/db'; +import { WorkflowsConfig } from '@n8n/config'; +import { WorkflowPublicationTriggerStatusRepository } from '@n8n/db'; +import type { TriggerStatusRow, User } from '@n8n/db'; +import { Container } from '@n8n/di'; import { createMember, createOwner } from './shared/db/users'; import type { SuperAgentTest } from './shared/types'; @@ -22,6 +25,7 @@ const testServer = utils.setupTestServer({ endpointGroups: ['activeWorkflows'] } beforeEach(async () => { await testDb.truncate([ + 'WorkflowPublicationTriggerStatus', 'WorkflowEntity', 'SharedWorkflow', 'WorkflowHistory', @@ -96,3 +100,92 @@ describe('GET /active-workflows', () => { expect(response.body.data).toEqual([workflow.id]); }); }); + +describe('with trigger status rows', () => { + let originalFlag: boolean; + + beforeAll(() => { + const workflowsConfig = Container.get(WorkflowsConfig); + originalFlag = workflowsConfig.useWorkflowPublicationService; + workflowsConfig.useWorkflowPublicationService = true; + }); + + afterAll(() => { + Container.get(WorkflowsConfig).useWorkflowPublicationService = originalFlag; + }); + + const FAILED = { status: 'failed', errorMessage: 'Could not register trigger' } as const; + const ACTIVATED = { status: 'activated', errorMessage: null } as const; + + async function createActiveWorkflowWithTriggerRows( + user: User, + rows: Array>, + ) { + const workflow = await createActiveWorkflow({}, user); + await Container.get(WorkflowPublicationTriggerStatusRepository).replaceForWorkflow( + workflow.id, + rows.map((row, index) => ({ + nodeId: `node-${index}`, + versionId: workflow.versionId, + triggerKind: 'in-memory', + ...row, + })), + ); + return workflow; + } + + describe('GET /active-workflows', () => { + it('omits a workflow whose publication failed', async () => { + const failed = await createActiveWorkflowWithTriggerRows(member, [FAILED]); + const published = await createActiveWorkflowWithTriggerRows(member, [ACTIVATED]); + const partial = await createActiveWorkflowWithTriggerRows(member, [ACTIVATED, FAILED]); + const withoutRows = await createActiveWorkflow({}, anotherMember); + + const response = await authOwnerAgent.get('/active-workflows').expect(200); + + expect(response.body.data).toEqual( + expect.arrayContaining([published.id, partial.id, withoutRows.id]), + ); + expect(response.body.data).not.toContain(failed.id); + expect(response.body.data).toHaveLength(3); + }); + + it('omits a failed publication from the ids a member can list', async () => { + const failed = await createActiveWorkflowWithTriggerRows(member, [FAILED]); + const published = await createActiveWorkflowWithTriggerRows(member, [ACTIVATED]); + const partial = await createActiveWorkflowWithTriggerRows(member, [ACTIVATED, FAILED]); + + const response = await authMemberAgent.get('/active-workflows').expect(200); + + expect(response.body.data).toEqual(expect.arrayContaining([published.id, partial.id])); + expect(response.body.data).not.toContain(failed.id); + expect(response.body.data).toHaveLength(2); + }); + }); + + describe('GET /active-workflows/error/:id', () => { + it('returns the trigger error of a failed publication', async () => { + const failed = await createActiveWorkflowWithTriggerRows(owner, [FAILED]); + + const response = await authOwnerAgent.get(`/active-workflows/error/${failed.id}`).expect(200); + + expect(response.body.data).toBe('Could not register trigger'); + }); + + it('rejects a member without access to the workflow', async () => { + const failed = await createActiveWorkflowWithTriggerRows(owner, [FAILED]); + + await authMemberAgent.get(`/active-workflows/error/${failed.id}`).expect(400); + }); + + it('returns null for a partial publication', async () => { + const partial = await createActiveWorkflowWithTriggerRows(owner, [ACTIVATED, FAILED]); + + const response = await authOwnerAgent + .get(`/active-workflows/error/${partial.id}`) + .expect(200); + + expect(response.body.data).toBeNull(); + }); + }); +}); diff --git a/packages/cli/test/integration/agents/agent-conversation-state.test.ts b/packages/cli/test/integration/agents/agent-conversation-state.test.ts index d8e01bd551d..1f464e01739 100644 --- a/packages/cli/test/integration/agents/agent-conversation-state.test.ts +++ b/packages/cli/test/integration/agents/agent-conversation-state.test.ts @@ -69,7 +69,6 @@ describe('Agent conversation state', () => { projectId: project.id, integrations: [], tools: {}, - skills: {}, }), ); }); diff --git a/packages/cli/test/integration/agents/agent-skills-hub.test.ts b/packages/cli/test/integration/agents/agent-skills-hub.test.ts new file mode 100644 index 00000000000..dc0fcfd9afc --- /dev/null +++ b/packages/cli/test/integration/agents/agent-skills-hub.test.ts @@ -0,0 +1,488 @@ +/** + * Agents read and write their skills through the skills hub (CONTEXT-225). + * A draft keeps its skill refs in `agent_skill_dependency`, a published + * version keeps its pins in `agent_version_skill_dependency`, and the skill text lives in + * `skill_version`. These tests run the agent services against real rows. + */ +import type { AgentJsonConfig, AgentSkill } from '@n8n/api-types'; +import { + createTeamProject, + linkUserToProject, + mockInstance, + testDb, + testModules, +} from '@n8n/backend-test-utils'; +import { TransactionRunner, type Project, type User } from '@n8n/db'; +import { Container } from '@n8n/di'; +import { UserError } from 'n8n-workflow'; + +import { setSkillsHubFlag } from '@/modules/agents/__tests__/test-utils/skills-hub-flag'; +import { AgentPublishService } from '@/modules/agents/agent-publish.service'; +import { AgentRuntimeCacheService } from '@/modules/agents/agent-runtime-cache.service'; +import { AgentSkillRefsService } from '@/modules/agents/agent-skill-refs.service'; +import { AgentSkillsService } from '@/modules/agents/agent-skills.service'; +import { AgentTaskService } from '@/modules/agents/agent-task.service'; +import { AgentUpdateBroadcaster } from '@/modules/agents/agent-update-broadcaster'; +import { AgentValidationService } from '@/modules/agents/agent-validation.service'; +import { AgentsService } from '@/modules/agents/agents.service'; +import { AgentsSettingsService } from '@/modules/agents/agents-settings.service'; +import type { Agent } from '@/modules/agents/entities/agent.entity'; +import { AgentRepository } from '@/modules/agents/repositories/agent.repository'; +import { SkillRepository } from '@/modules/agents/repositories/skill.repository'; +import { SkillService, toAgentSkill } from '@/modules/agents/skills/skill.service'; +import { + markAgentDraftDirty, + saveAgentDraftFenced, +} from '@/modules/agents/utils/agent-draft.utils'; +import { getAgentSkillHash } from '@/modules/agents/utils/agent-config-hash'; +import { Telemetry } from '@/telemetry'; + +import { createMember, createOwner } from '../shared/db/users'; + +const config: AgentJsonConfig = { name: 'Agent', model: '', instructions: 'Help.' }; + +function body(name: string, instructions = `${name} instructions.`): AgentSkill { + return { name, description: `${name} description`, instructions }; +} + +describe('Agent skills in the skills hub', () => { + let owner: User; + let editor: User; + let project: Project; + let agentsService: AgentsService; + let agentSkillsService: AgentSkillsService; + let publishService: AgentPublishService; + let skillRefs: AgentSkillRefsService; + let skillService: SkillService; + let agentRepository: AgentRepository; + const broadcaster = mockInstance(AgentUpdateBroadcaster); + + beforeAll(async () => { + await setSkillsHubFlag(true); + mockInstance(Telemetry); + mockInstance(AgentRuntimeCacheService); + mockInstance(AgentTaskService).requestReconcile.mockResolvedValue(undefined); + const validation = mockInstance(AgentValidationService); + validation.validateAgentEntityConfiguration.mockResolvedValue({ status: 'valid', issues: [] }); + await testModules.loadModules(['agents']); + await testDb.init(); + await Container.get(AgentsSettingsService).setEnabled(true); + owner = await createOwner(); + editor = await createMember(); + agentsService = Container.get(AgentsService); + agentSkillsService = Container.get(AgentSkillsService); + publishService = Container.get(AgentPublishService); + skillRefs = Container.get(AgentSkillRefsService); + skillService = Container.get(SkillService); + agentRepository = Container.get(AgentRepository); + }); + + beforeEach(async () => { + project = await createTeamProject(); + await linkUserToProject(editor, project, 'project:editor'); + }); + + afterEach(async () => { + await agentRepository.delete({}); + await Container.get(SkillRepository).delete({}); + }); + + afterAll(async () => { + await testDb.terminate(); + }); + + const actor = () => ({ kind: 'user' as const, user: owner }); + + async function createSkill( + skill: AgentSkill, + target: { projectId: string | null } = { projectId: project.id }, + ) { + return await skillService.create({ + target: { projectId: target.projectId, agentId: null }, + skill, + source: 'ui', + createdById: owner.id, + }); + } + + /** Saves new instructions on top of the latest version, as an editor does. */ + async function saveInstructions(skillId: string, instructions: string) { + const latest = (await Container.get(SkillRepository).findLatestSaved([skillId])).get(skillId); + if (!latest) throw new Error(`Skill ${skillId} not found`); + const baseSkillHash = getAgentSkillHash(toAgentSkill(latest)); + return await skillService.save(skillId, { instructions, baseSkillHash }, owner.id); + } + + async function createAgent(skillIds: string[], projectId = project.id) { + return await agentsService.create(projectId, 'Agent', { + actor: actor(), + schema: { ...config, skills: skillIds.map((id) => ({ type: 'skill', id })) }, + }); + } + + async function reload(agent: Agent) { + return await agentRepository.findOneByOrFail({ id: agent.id }); + } + + async function publish(agent: Agent) { + await publishService.publishAgent(agent.id, agent.projectId, owner, { + by: 'user', + trigger: 'explicit', + }); + return await agentRepository.findByIdAndProjectId(agent.id, agent.projectId); + } + + async function instructionsOf(skillsRecord: Record) { + return Object.fromEntries( + Object.entries(skillsRecord).map(([id, skill]) => [id, skill.instructions]), + ); + } + + it('lists the skills of a draft and of its published version in the same attach order', async () => { + const zeta = await createSkill(body('Zeta')); + const alpha = await createSkill(body('Alpha')); + const mid = await createSkill(body('Mid')); + const agent = await createAgent([zeta, alpha, mid]); + + const published = await publish(agent); + const draftRefs = await skillRefs.refsForDraft(agent, {}); + const publishedRefs = await skillRefs.refsForVersion(published!.activeVersion!, {}); + + expect(draftRefs?.map((ref) => ref.id)).toEqual([zeta, alpha, mid]); + expect(publishedRefs?.map((ref) => ref.id)).toEqual([zeta, alpha, mid]); + const { skills } = await skillRefs.readVersion(published!.activeVersion!, {}); + expect(Object.keys(skills)).toEqual([zeta, alpha, mid]); + }); + + it('keeps the attach order when the refs are written in another order', async () => { + const first = await createSkill(body('First')); + const second = await createSkill(body('Second')); + const agent = await reload(await createAgent([first, second])); + + // As a config save does: advance the draft and write the refs in one transaction. + markAgentDraftDirty(agent); + await Container.get(TransactionRunner).run({}, async (ctx) => { + await saveAgentDraftFenced(agentRepository, agent, ctx); + await skillRefs.replaceDraftRefs( + agent, + [ + { type: 'skill', id: second }, + { type: 'skill', id: first }, + ], + ctx, + ); + }); + + expect((await skillRefs.refsForDraft(agent, {}))?.map((ref) => ref.id)).toEqual([ + first, + second, + ]); + }); + + it('marks every following agent as changed on a shared skill save, and a published agent keeps its pinned text', async () => { + const shared = await createSkill(body('Shared', 'Version one.')); + const first = (await publish(await createAgent([shared])))!; + const second = (await publish(await createAgent([shared])))!; + expect(first.versionId).toBe(first.activeVersionId); + + await agentSkillsService.updateSkill( + first.id, + project.id, + shared, + { instructions: 'Version two.' }, + { user: owner, modifiedBy: 'user' }, + ); + + for (const agent of [first, second]) { + const stored = await reload(agent); + expect(stored.versionId).not.toBe(stored.activeVersionId); + const draft = await skillRefs.readDraft(stored, {}); + expect(await instructionsOf(draft.skills)).toEqual({ [shared]: 'Version two.' }); + const version = await skillRefs.readVersion(agent.activeVersion!, {}); + expect(await instructionsOf(version.skills)).toEqual({ [shared]: 'Version one.' }); + } + expect(broadcaster.notify).toHaveBeenCalledWith( + expect.objectContaining({ agentId: second.id }), + undefined, + ); + }); + + it('reverts to the pinned versions without changing the hub', async () => { + const skill = await createSkill(body('Skill', 'Published text.')); + const agent = (await publish(await createAgent([skill])))!; + await saveInstructions(skill, 'Newer text.'); + const latestBefore = (await Container.get(SkillRepository).findLatestSaved([skill])).get(skill); + + await publishService.revertToPublishedAgent(agent.id, project.id, owner, 'user'); + + const refs = await skillRefs.refsForDraft(agent, {}); + const pinned = (await Container.get(SkillRepository).findPinned(agent.activeVersionId!)).get( + skill, + ); + expect(refs).toEqual([{ type: 'skill', id: skill, versionId: pinned?.version.id }]); + const draft = await skillRefs.readDraft(agent, {}); + expect(await instructionsOf(draft.skills)).toEqual({ [skill]: 'Published text.' }); + const latestAfter = (await Container.get(SkillRepository).findLatestSaved([skill])).get(skill); + expect(latestAfter?.version.id).toBe(latestBefore?.version.id); + }); + + it('reverts an agent that pins an instance skill the user cannot edit', async () => { + const instanceSkill = await createSkill(body('Instance'), { projectId: null }); + const agent = (await publish(await createAgent([instanceSkill])))!; + await saveInstructions(instanceSkill, 'Changed by an admin.'); + + await publishService.revertToPublishedAgent(agent.id, project.id, editor, 'user'); + + const refs = await skillRefs.refsForDraft(agent, {}); + expect(refs?.[0]).toMatchObject({ id: instanceSkill, versionId: expect.any(String) }); + await expect( + agentSkillsService.updateSkill( + agent.id, + project.id, + instanceSkill, + { instructions: 'Edited by the editor.' }, + { user: editor, modifiedBy: 'user' }, + ), + ).rejects.toThrow('This agent uses an older version of this skill.'); + }); + + it('creates, updates and detaches a skill from the agent builder', async () => { + const agent = await createAgent([]); + const context = { user: editor, modifiedBy: 'builder' as const }; + + const created = await agentSkillsService.createAndAttachSkill( + agent.id, + project.id, + body('Triage'), + context, + ); + const [hubSkill] = await Container.get(SkillRepository).findByIds([created.id]); + expect(hubSkill).toMatchObject({ projectId: project.id, agentId: null, source: 'agent' }); + expect(await skillRefs.refsForDraft(agent, {})).toEqual([{ type: 'skill', id: created.id }]); + + const updated = await agentSkillsService.updateSkill( + agent.id, + project.id, + created.id, + { instructions: 'Sort tickets by urgency.' }, + context, + created.skillHash, + ); + expect(updated.skill.instructions).toBe('Sort tickets by urgency.'); + await expect( + agentSkillsService.updateSkill( + agent.id, + project.id, + created.id, + { instructions: 'Stale edit.' }, + context, + created.skillHash, + ), + ).rejects.toThrow('Skill was changed elsewhere'); + + await agentSkillsService.deleteSkill(agent.id, project.id, created.id, context); + expect(await skillRefs.refsForDraft(agent, {})).toEqual([]); + expect(await Container.get(SkillRepository).findByIds([created.id])).toHaveLength(1); + }); + + it('keeps the published skills readable after the flag is turned off', async () => { + const skill = await createSkill(body('Published', 'Published text.')); + const published = (await publish(await createAgent([skill])))!; + await saveInstructions(skill, 'Newer text.'); + const version = published.activeVersion!; + + await setSkillsHubFlag(false); + try { + // With the flag off, the legacy reader uses the columns that publish wrote. + const { skillRefs: refs, skills } = await skillRefs.readVersion(version, {}); + expect(refs).toEqual([{ type: 'skill', id: skill }]); + expect(await instructionsOf(skills)).toEqual({ [skill]: 'Published text.' }); + } finally { + await setSkillsHubFlag(true); + } + }); + + it('keeps skills on the agent row when the skills hub is off', async () => { + await setSkillsHubFlag(false); + try { + const agent = await createAgent([]); + const context = { user: editor, modifiedBy: 'builder' as const }; + + const created = await agentSkillsService.createAndAttachSkill( + agent.id, + project.id, + body('Triage'), + context, + ); + await agentSkillsService.updateSkill( + agent.id, + project.id, + created.id, + { instructions: 'Sort tickets by urgency.' }, + context, + created.skillHash, + ); + const published = (await publish(await reload(agent)))!; + await agentSkillsService.deleteSkill(agent.id, project.id, created.id, context); + await publishService.revertToPublishedAgent(agent.id, project.id, owner, 'user'); + + const row = await reload(agent); + expect(row.schema?.skills).toEqual([{ type: 'skill', id: created.id }]); + expect(row.skills[created.id]?.instructions).toBe('Sort tickets by urgency.'); + expect(published.activeVersion?.skills?.[created.id]?.instructions).toBe( + 'Sort tickets by urgency.', + ); + expect(await Container.get(SkillRepository).findByIds([created.id])).toEqual([]); + expect(await skillRefs.refsForDraft(row, {})).toEqual([{ type: 'skill', id: created.id }]); + } finally { + await setSkillsHubFlag(true); + } + }); + + it('keeps a skill for this agent only, and copies it for a duplicate', async () => { + const agent = await createAgent([]); + const context = { user: editor, modifiedBy: 'user' as const }; + const created = await agentSkillsService.createAndAttachSkill( + agent.id, + project.id, + body('Private'), + context, + 'agent', + ); + const [hubSkill] = await Container.get(SkillRepository).findByIds([created.id]); + expect(hubSkill).toMatchObject({ projectId: null, agentId: agent.id }); + + const other = await createAgent([]); + await expect( + skillRefs.replaceDraftRefs(other, [{ type: 'skill', id: created.id }], {}), + ).rejects.toThrow('is not available to this agent'); + + const duplicate = await agentsService.create(project.id, 'Copy', { + actor: actor(), + schema: { ...config, skills: [{ type: 'skill', id: created.id }] }, + user: owner, + }); + const [copyRef] = await skillRefs.refsForDraft(duplicate, {}); + expect(copyRef.id).not.toBe(created.id); + const [copy] = await Container.get(SkillRepository).findByIds([copyRef.id]); + expect(copy).toMatchObject({ projectId: null, agentId: duplicate.id }); + const { skills } = await skillRefs.readDraft(duplicate, {}); + expect(Object.values(skills)).toEqual([body('Private')]); + }); + + it('changes where a skill can be added only while no other agent uses it', async () => { + const agent = await createAgent([]); + const context = { user: editor, modifiedBy: 'user' as const }; + const created = await agentSkillsService.createAndAttachSkill( + agent.id, + project.id, + body('Movable'), + context, + ); + + const update = async (availableTo: 'project' | 'agent' | 'instance') => + await agentSkillsService.updateSkill( + agent.id, + project.id, + created.id, + {}, + context, + undefined, + undefined, + availableTo, + ); + + await update('agent'); + expect((await Container.get(SkillRepository).findByIds([created.id]))[0]).toMatchObject({ + projectId: null, + agentId: agent.id, + }); + await update('project'); + const other = await createAgent([created.id]); + await expect(update('agent')).rejects.toThrow('Other agents use this skill.'); + expect((await Container.get(SkillRepository).findByIds([created.id]))[0]).toMatchObject({ + agentId: null, + }); + + // A published pin counts too, after the draft no longer refers to the skill. + await publish(other); + await skillRefs.replaceDraftRefs(await reload(other), [], {}); + expect(await skillRefs.refsForDraft(await reload(other), {})).toEqual([]); + await expect(update('agent')).rejects.toThrow('Other agents use this skill.'); + }); + + it('shares the skills of a duplicated agent', async () => { + const skill = await createSkill(body('Shared')); + const original = await createAgent([skill]); + const { skills } = await skillRefs.readDraft(original, {}); + + const duplicate = await agentsService.create(project.id, 'Copy', { + actor: actor(), + user: owner, + schema: { ...config, skills: [{ type: 'skill', id: skill }] }, + skills, + }); + + expect(await skillRefs.refsForDraft(duplicate, {})).toEqual([{ type: 'skill', id: skill }]); + expect(await Container.get(SkillRepository).findByIds([skill])).toHaveLength(1); + }); + + it('refuses a duplicate into another project', async () => { + const skill = await createSkill(body('Project skill')); + const original = await createAgent([skill]); + const { skills } = await skillRefs.readDraft(original, {}); + const otherProject = await createTeamProject(); + + const duplicate = agentsService.create(otherProject.id, 'Copy', { + actor: actor(), + user: owner, + schema: { ...config, skills: [{ type: 'skill', id: skill }] }, + skills, + }); + + await expect(duplicate).rejects.toThrow(UserError); + await expect(duplicate).rejects.toThrow('is not available to this agent'); + expect(await agentRepository.findBy({ projectId: otherProject.id })).toEqual([]); + }); + + it('refuses an agent skill of another project and does not copy it', async () => { + const otherProject = await createTeamProject(); + const source = await createAgent([], otherProject.id); + const secret = await skillService.create({ + target: { projectId: null, agentId: source.id }, + skill: body('Secret skill'), + source: 'agent', + createdById: owner.id, + }); + + const attempt = agentsService.create(project.id, 'Copy', { + actor: actor(), + user: owner, + schema: { ...config, skills: [{ type: 'skill', id: secret }] }, + skills: {}, + }); + + await expect(attempt).rejects.toThrow('is not available to this agent'); + const agentSkills = await Container.get(SkillRepository).findBy({ source: 'agent' }); + expect(agentSkills.map((skill) => skill.id)).toEqual([secret]); + }); + + it('creates an agent skill for a seeded ref that has only a body, and deletes it with the agent', async () => { + const agent = await agentsService.create(project.id, 'Seeded', { + actor: actor(), + schema: { ...config, skills: [{ type: 'skill', id: 'seed_skill' }] }, + skills: { seed_skill: body('Seeded skill') }, + skillCreator: owner, + }); + + const { skillRefs: refs, skills } = await skillRefs.readDraft(agent, {}); + expect(refs).toHaveLength(1); + expect(refs?.[0].id).not.toBe('seed_skill'); + expect(Object.values(skills)).toEqual([body('Seeded skill')]); + const [hubSkill] = await Container.get(SkillRepository).findByIds([refs![0].id]); + expect(hubSkill).toMatchObject({ projectId: null, agentId: agent.id, source: 'agent' }); + + await agentsService.delete(agent.id, project.id); + expect(await Container.get(SkillRepository).findByIds([refs![0].id])).toEqual([]); + }); +}); diff --git a/packages/cli/test/integration/agents/agent-thread-grant.repository.test.ts b/packages/cli/test/integration/agents/agent-thread-grant.repository.test.ts index 3f6640fcfce..b99c55b0a3a 100644 --- a/packages/cli/test/integration/agents/agent-thread-grant.repository.test.ts +++ b/packages/cli/test/integration/agents/agent-thread-grant.repository.test.ts @@ -53,7 +53,6 @@ describe('Agent thread grants', () => { projectId: project.id, integrations: [], tools: {}, - skills: {}, }), ); for (const id of ['parent', 'child', 'sibling', 'new-thread']) { diff --git a/packages/cli/test/integration/agents/agent.repository.test.ts b/packages/cli/test/integration/agents/agent.repository.test.ts new file mode 100644 index 00000000000..d737f64282f --- /dev/null +++ b/packages/cli/test/integration/agents/agent.repository.test.ts @@ -0,0 +1,47 @@ +import type { AgentIntegrationConfig } from '@n8n/api-types'; +import { createTeamProject, testDb, testModules } from '@n8n/backend-test-utils'; +import { Container } from '@n8n/di'; +import { randomUUID } from 'node:crypto'; + +import { AgentRepository } from '@/modules/agents/repositories/agent.repository'; + +describe('AgentRepository', () => { + let agents: AgentRepository; + + beforeAll(async () => { + await testModules.loadModules(['agents']); + await testDb.init(); + agents = Container.get(AgentRepository); + }, 60_000); + + afterAll(async () => { + await testDb.terminate(); + }); + + describe('findWithIntegrationType', () => { + it('returns only agents with a channel of the given type', async () => { + const project = await createTeamProject(); + const save = async (integrations: AgentIntegrationConfig[]) => + await agents.save( + agents.create({ + id: randomUUID(), + name: 'Agent', + projectId: project.id, + integrations, + tools: {}, + skills: {}, + }), + ); + const whatsApp = await save([ + { type: 'telegram', credentialId: 'cred-1' }, + { type: 'whatsapp', credentialId: 'cred-2' }, + ]); + await save([{ type: 'telegram', credentialId: 'whatsapp' }]); + await save([]); + + const result = await agents.findWithIntegrationType('whatsapp'); + + expect(result).toEqual([{ id: whatsApp.id, integrations: whatsApp.integrations }]); + }); + }); +}); diff --git a/packages/cli/test/integration/agents/n8n-chat-page.api.test.ts b/packages/cli/test/integration/agents/n8n-chat-page.api.test.ts index 2240d6ea37a..4afb89b0ccc 100644 --- a/packages/cli/test/integration/agents/n8n-chat-page.api.test.ts +++ b/packages/cli/test/integration/agents/n8n-chat-page.api.test.ts @@ -44,7 +44,6 @@ describe('n8n Chat page HTTP routes', () => { schema: { name, model, instructions: 'Help' }, integrations: [chatIntegration], tools: {}, - skills: {}, versionId: randomUUID(), }), ); @@ -61,7 +60,6 @@ describe('n8n Chat page HTTP routes', () => { ...(subAgents ? { subAgents: { agents: subAgents } } : {}), }, tools: {}, - skills: {}, publishedBy: 'test', }); await agentRepository.update({ id: agent.id }, { activeVersionId: versionId }); diff --git a/packages/cli/test/integration/agents/n8n-chat-production.api.test.ts b/packages/cli/test/integration/agents/n8n-chat-production.api.test.ts index 2eceee9cd5b..9a162d9acf9 100644 --- a/packages/cli/test/integration/agents/n8n-chat-production.api.test.ts +++ b/packages/cli/test/integration/agents/n8n-chat-production.api.test.ts @@ -37,7 +37,6 @@ describe('production n8n Chat HTTP route', () => { schema: { name: 'Agent', model: 'openai:gpt-4o-mini', instructions: 'Help' }, integrations: [chatIntegration], tools: {}, - skills: {}, versionId: randomUUID(), }), ); @@ -56,7 +55,6 @@ describe('production n8n Chat HTTP route', () => { integrations: enabled ? [chatIntegration] : [], }, tools: {}, - skills: {}, publishedBy: 'test', }); await Container.get(AgentRepository).update({ id: agentId }, { activeVersionId: versionId }); diff --git a/packages/cli/test/integration/agents/n8n-chat-production.model.test.ts b/packages/cli/test/integration/agents/n8n-chat-production.model.test.ts index 74d63a17fa2..b4e24a5d284 100644 --- a/packages/cli/test/integration/agents/n8n-chat-production.model.test.ts +++ b/packages/cli/test/integration/agents/n8n-chat-production.model.test.ts @@ -252,7 +252,6 @@ describe.skipIf(!enabled)('production n8n Chat with a real model', () => { projectId: project.id, schema: storedAgentConfig(schema), tools, - skills: {}, integrations: [chatIntegration], versionId: randomUUID(), }), @@ -263,7 +262,6 @@ describe.skipIf(!enabled)('production n8n Chat with a real model', () => { agentId: agent.id, schema: storedAgentConfig({ ...schema, integrations: [chatIntegration] }), tools, - skills: {}, publishedBy: owner, }); await repository.update({ id: agent.id }, { activeVersionId: versionId }); diff --git a/packages/cli/test/integration/agents/skill.repository.test.ts b/packages/cli/test/integration/agents/skill.repository.test.ts new file mode 100644 index 00000000000..19626098c27 --- /dev/null +++ b/packages/cli/test/integration/agents/skill.repository.test.ts @@ -0,0 +1,782 @@ +import { createTeamProject, testDb, testModules } from '@n8n/backend-test-utils'; +import { TransactionRunner, type Project, type User } from '@n8n/db'; +import { Container } from '@n8n/di'; +import { randomUUID } from 'node:crypto'; + +import { AgentHistoryRepository } from '@/modules/agents/repositories/agent-history.repository'; +import { AgentRepository } from '@/modules/agents/repositories/agent.repository'; +import { SkillRepository } from '@/modules/agents/repositories/skill.repository'; +import { skillContentHash, type SkillContent } from '@/modules/agents/skills/skill-content-hash'; + +import { createUser } from '../shared/db/users'; + +/** More ids than SQLite binds in one query (32,766). */ +const manyUnknownIds = () => Array.from({ length: 33_000 }, (_, i) => `skill_unknown${i}`); + +const content = (overrides: Partial = {}): SkillContent => ({ + name: 'Brand voice', + description: 'Write in our voice', + instructions: 'Use short sentences.', + frontmatter: null, + files: [], + ...overrides, +}); + +describe('SkillRepository', () => { + let skills: SkillRepository; + let agents: AgentRepository; + let histories: AgentHistoryRepository; + let txRunner: TransactionRunner; + let user: User; + let project: Project; + let otherProject: Project; + + beforeAll(async () => { + await testModules.loadModules(['agents']); + await testDb.init(); + skills = Container.get(SkillRepository); + agents = Container.get(AgentRepository); + histories = Container.get(AgentHistoryRepository); + txRunner = Container.get(TransactionRunner); + user = await createUser(); + project = await createTeamProject('Team'); + otherProject = await createTeamProject('Other team'); + }); + + afterEach(async () => { + // Agent rows cascade to their history, pins and dependency rows. + await agents.delete({}); + await skills.delete({}); + }); + + afterAll(async () => { + await testDb.terminate(); + }); + + let counter = 0; + async function createSkill( + target: { projectId?: string; agentId?: string } = {}, + body: SkillContent = content(), + ): Promise { + const id = `skill_test${++counter}`; + await skills.createSkill( + { + id, + target: { projectId: target.projectId ?? null, agentId: target.agentId ?? null }, + source: 'ui', + createdById: null, + }, + body, + ); + return id; + } + + async function createAgent(name: string, options: { inSync?: boolean; projectId?: string } = {}) { + const versionId = randomUUID(); + const agent = await agents.save( + agents.create({ + id: randomUUID(), + name, + projectId: options.projectId ?? project.id, + integrations: [], + tools: {}, + versionId, + }), + ); + if (options.inSync) { + await histories.save(histories.create({ versionId, agentId: agent.id, author: 'Test' })); + await agents.update({ id: agent.id }, { activeVersionId: versionId }); + } + return agent; + } + + async function publish(agentId: string): Promise { + const versionId = randomUUID(); + await histories.save(histories.create({ versionId, agentId, author: 'Test' })); + return versionId; + } + + async function latestVersionId(skillId: string): Promise { + const row = (await skills.findLatestSaved([skillId])).get(skillId); + if (!row) throw new Error(`no saved version for ${skillId}`); + return row.version.id; + } + + describe('create', () => { + it('writes the skill with v1 as its only version', async () => { + const id = await createSkill({ projectId: project.id }); + + const latest = (await skills.findLatestSaved([id])).get(id); + + expect(latest?.version.version).toBe(1); + expect(latest?.skill).toMatchObject({ + id, + projectId: project.id, + agentId: null, + source: 'ui', + }); + expect(latest?.version.contentHash).toBe(skillContentHash(content())); + expect(await skills.nextVersionNumber(id)).toBe(2); + }); + + it('stores the files of v1 sorted by path', async () => { + const id = await createSkill( + {}, + content({ + files: [ + { path: 'references/b.md', content: 'b' }, + { path: 'references/B.md', content: 'B' }, + { path: 'references/a.md', content: 'a' }, + ], + }), + ); + + const latest = (await skills.findLatestSaved([id])).get(id); + + const paths = ['references/B.md', 'references/a.md', 'references/b.md']; + expect(latest?.files.map((file) => file.path)).toEqual(paths); + expect(latest?.files[0]).toMatchObject({ content: 'B' }); + }); + + // SQLite returns rows in UTF-8 byte order and Postgres in its collation order. The + // content hash uses UTF-16 code units, so the repository sorts on its own. + it('sorts files by UTF-16 code unit, as the content hash does', async () => { + const id = await createSkill( + {}, + content({ + files: [ + { path: 'references/\uff5e.md', content: 'fullwidth tilde' }, + { path: 'references/\u{1f600}.md', content: 'emoji' }, + ], + }), + ); + + const latest = (await skills.findLatestSaved([id])).get(id); + + expect(latest?.files.map((file) => file.content)).toEqual(['emoji', 'fullwidth tilde']); + }); + + it('rolls back with the caller transaction', async () => { + await expect( + txRunner.run({}, async (ctx) => { + await skills.createSkill( + { + id: 'skill_rollback', + target: { projectId: null, agentId: null }, + source: 'ui', + createdById: null, + }, + content(), + ctx, + ); + throw new Error('abort'); + }), + ).rejects.toThrow('abort'); + + expect(await skills.findByIds(['skill_rollback'])).toEqual([]); + }); + }); + + describe('findVisiblePage', () => { + const firstPage = { skip: 0 }; + const ids = (page: { skills: Array<{ id: string }> }) => page.skills.map((skill) => skill.id); + + it('lists instance skills and the skills of the given projects and their agents, newest change first', async () => { + const instance = await createSkill(); + const team = await createSkill({ projectId: project.id }); + const otherTeam = await createSkill({ projectId: otherProject.id }); + const agentSkill = await createSkill({ agentId: (await createAgent('Support')).id }); + const otherAgentSkill = await createSkill({ + agentId: (await createAgent('Sales', { projectId: otherProject.id })).id, + }); + await skills.insertSavedVersion(instance, 2, content({ instructions: 'touched' }), null); + + const page = await skills.findVisiblePage({ projectIds: [project.id] }, firstPage); + + expect(ids(page)).toEqual(expect.arrayContaining([instance, team, agentSkill])); + expect(ids(page)).not.toContain(otherTeam); + expect(ids(page)).not.toContain(otherAgentSkill); + expect(ids(page)[0]).toBe(instance); + expect(page.count).toBe(3); + }); + + it("adds every project's skills and every agent's skills when allowed", async () => { + const otherTeam = await createSkill({ projectId: otherProject.id }); + const otherAgentSkill = await createSkill({ + agentId: (await createAgent('Sales', { projectId: otherProject.id })).id, + }); + + const page = await skills.findVisiblePage({ projectIds: 'all' }, firstPage); + + expect(ids(page)).toEqual(expect.arrayContaining([otherTeam, otherAgentSkill])); + }); + + it('lists no project or agent skill for an empty project list', async () => { + await createSkill({ projectId: project.id }); + await createSkill({ agentId: (await createAgent('Support')).id }); + + const visibility = { projectIds: [] }; + const none = { skills: [], count: 0 }; + expect(await skills.findVisiblePage(visibility, firstPage)).toEqual(none); + expect(await skills.findVisiblePage(visibility, { ...firstPage, scope: 'project' })).toEqual( + none, + ); + expect(await skills.findVisiblePage(visibility, { ...firstPage, scope: 'agent' })).toEqual( + none, + ); + }); + + it('filters by scope and project in the query, an agent skill by the project of its agent', async () => { + const instance = await createSkill(); + const team = await createSkill({ projectId: project.id }); + const otherTeam = await createSkill({ projectId: otherProject.id }); + const agentSkill = await createSkill({ agentId: (await createAgent('Support')).id }); + const otherAgentSkill = await createSkill({ + agentId: (await createAgent('Sales', { projectId: otherProject.id })).id, + }); + const everything = { projectIds: 'all' as const }; + + const page = async (filter: { + scope?: 'project' | 'agent' | 'instance'; + projectId?: string; + }) => ids(await skills.findVisiblePage(everything, { ...firstPage, ...filter })).sort(); + + expect(await page({ scope: 'instance' })).toEqual([instance]); + expect(await page({ scope: 'project' })).toEqual([team, otherTeam].sort()); + expect(await page({ scope: 'agent' })).toEqual([agentSkill, otherAgentSkill].sort()); + expect(await page({ projectId: project.id })).toEqual([team, agentSkill].sort()); + expect(await page({ scope: 'project', projectId: project.id })).toEqual([team]); + expect(await page({ scope: 'agent', projectId: project.id })).toEqual([agentSkill]); + expect(await page({ scope: 'instance', projectId: project.id })).toEqual([]); + }); + + it('lists what one agent may attach: its project skills, its own skills and instance skills', async () => { + const support = await createAgent('Support'); + const sales = await createAgent('Sales'); + const instance = await createSkill(); + const team = await createSkill({ projectId: project.id }); + await createSkill({ projectId: otherProject.id }); + const own = await createSkill({ agentId: support.id }); + await createSkill({ agentId: sales.id }); + + const attachable = async (projectIds: string[] | 'all') => + ids( + await skills.findVisiblePage( + { projectIds }, + { skip: 0, attachableTo: { agentId: support.id, projectId: project.id } }, + ), + ).sort(); + + expect(await attachable([project.id])).toEqual([instance, team, own].sort()); + expect(await attachable('all')).toEqual([instance, team, own].sort()); + // A user who may not list the project's skills gets only the instance skills. + expect(await attachable([otherProject.id])).toEqual([instance]); + }); + + it('searches the name and description of the latest version, before the page is cut', async () => { + const renamed = await createSkill({}, content({ name: 'Old name' })); + await skills.insertSavedVersion(renamed, 2, content({ name: 'Triage RULES' }), null); + const described = await createSkill( + {}, + content({ name: 'Other', description: 'rules for x' }), + ); + await createSkill({}, content({ name: 'Unrelated' })); + const visibility = { projectIds: [] }; + + const byName = await skills.findVisiblePage(visibility, { + skip: 0, + take: 1, + search: 'rules', + }); + const all = await skills.findVisiblePage(visibility, { skip: 0, search: 'RULES' }); + const oldName = await skills.findVisiblePage(visibility, { skip: 0, search: 'old name' }); + + expect(byName.count).toBe(2); + expect(byName.skills).toHaveLength(1); + expect(ids(all).sort()).toEqual([renamed, described].sort()); + expect(oldName).toEqual({ skills: [], count: 0 }); + }); + + it('treats LIKE wildcards in the search as plain text', async () => { + const percent = await createSkill({}, content({ name: '100% done' })); + await createSkill({}, content({ name: '100 done' })); + const visibility = { projectIds: [] }; + + const page = await skills.findVisiblePage(visibility, { skip: 0, search: '100%' }); + + expect(ids(page)).toEqual([percent]); + }); + + it('cuts the page with skip and take, and answers past the end with the full count', async () => { + for (let i = 0; i < 3; i++) await createSkill(); + const visibility = { projectIds: [] }; + + const all = await skills.findVisiblePage(visibility, { skip: 0 }); + const second = await skills.findVisiblePage(visibility, { skip: 1, take: 1 }); + const past = await skills.findVisiblePage(visibility, { skip: 10, take: 5 }); + + expect(all.skills).toHaveLength(3); + expect(ids(second)).toEqual([ids(all)[1]]); + expect(second.count).toBe(3); + expect(past).toEqual({ skills: [], count: 3 }); + }); + }); + + describe('findByIds', () => { + it('returns the existing skills and skips unknown ids', async () => { + const id = await createSkill(); + + const found = await skills.findByIds([id, 'skill_unknown']); + + expect(found.map((skill) => skill.id)).toEqual([id]); + }); + }); + + describe('saved versions', () => { + it('numbers the next version after the highest one', async () => { + const id = await createSkill(); + + expect(await skills.nextVersionNumber(id)).toBe(2); + await skills.insertSavedVersion(id, 2, content({ instructions: 'v2' }), user.id); + expect(await skills.nextVersionNumber(id)).toBe(3); + }); + + it('moves the skill to the top of the visible list', async () => { + const first = await createSkill(); + await createSkill(); + + await skills.insertSavedVersion(first, 2, content({ instructions: 'newer' }), null); + + const { skills: page } = await skills.findVisiblePage({ projectIds: [] }, { skip: 0 }); + expect(page[0].id).toBe(first); + }); + + it('returns 1 for a skill with no saved version', async () => { + expect(await skills.nextVersionNumber('skill_unknown')).toBe(1); + }); + + it('resolves the highest version as the latest, with its files and author', async () => { + const id = await createSkill(); + const versionId = await skills.insertSavedVersion( + id, + 2, + content({ instructions: 'v2', files: [{ path: 'references/x.md', content: 'x' }] }), + user.id, + ); + + const latest = (await skills.findLatestSaved([id])).get(id); + + expect(latest?.version).toMatchObject({ id: versionId, version: 2, instructions: 'v2' }); + expect(latest?.version.createdById).toBe(user.id); + expect(latest?.files.map((file) => file.content)).toEqual(['x']); + }); + + it('returns name and description of the latest version as summaries', async () => { + const id = await createSkill(); + await skills.insertSavedVersion( + id, + 2, + content({ name: 'Tone', description: 'How we sound' }), + null, + ); + + expect((await skills.findLatestSummaries([id, 'skill_unknown'])).get(id)).toEqual({ + name: 'Tone', + description: 'How we sound', + version: 2, + }); + }); + + it('resolves the latest of three versions with its own files', async () => { + const id = await createSkill(); + await skills.insertSavedVersion( + id, + 2, + content({ instructions: 'v2', files: [{ path: 'references/a.md', content: 'a2' }] }), + null, + ); + await skills.insertSavedVersion( + id, + 3, + content({ instructions: 'v3', files: [{ path: 'references/a.md', content: 'a3' }] }), + null, + ); + + const latest = (await skills.findLatestSaved([id])).get(id); + + expect(latest?.version).toMatchObject({ version: 3, instructions: 'v3' }); + expect(latest?.files.map((file) => file.content)).toEqual(['a3']); + }); + + it('reads more skill ids than one query can bind', async () => { + const id = await createSkill(); + const ids = [id, ...manyUnknownIds()]; + + expect([...(await skills.findLatestSaved(ids)).keys()]).toEqual([id]); + expect([...(await skills.findLatestSummaries(ids)).keys()]).toEqual([id]); + expect(await skills.findByIds(ids)).toHaveLength(1); + }); + + it('finds versions by id with their skill', async () => { + const id = await createSkill(); + const v1 = await latestVersionId(id); + + const found = await skills.findVersionsByIds([v1, randomUUID()]); + + expect([...found.keys()]).toEqual([v1]); + expect(found.get(v1)?.skill.id).toBe(id); + }); + }); + + describe('pins', () => { + it('finds the pinned version of each skill of one published agent version', async () => { + const id = await createSkill(); + const v1 = await latestVersionId(id); + await skills.insertSavedVersion(id, 2, content({ instructions: 'v2' }), null); + const agent = await createAgent('Support'); + const agentVersionId = await publish(agent.id); + + await skills.insertPins([{ agentVersionId, skillId: id, skillVersionId: v1 }]); + + const pinned = await skills.findPinned(agentVersionId); + expect([...pinned.keys()]).toEqual([id]); + expect(pinned.get(id)?.version).toMatchObject({ id: v1, version: 1 }); + }); + + it('keeps the pins of one publish in the order they were given', async () => { + const zeta = await createSkill(); + const alpha = await createSkill(); + const agentVersionId = await publish((await createAgent('Support')).id); + + await skills.insertPins([ + { agentVersionId, skillId: zeta, skillVersionId: await latestVersionId(zeta) }, + { agentVersionId, skillId: alpha, skillVersionId: await latestVersionId(alpha) }, + ]); + + expect([...(await skills.findPinned(agentVersionId)).keys()]).toEqual([zeta, alpha]); + expect(await skills.findPinnedSkillIds(agentVersionId)).toEqual([zeta, alpha]); + }); + }); + + describe('dependencies', () => { + it('replaces the rows of one agent and skips unknown skills', async () => { + const a = await createSkill(); + const b = await createSkill(); + const agent = await createAgent('Support'); + await skills.replaceDependencies(agent.id, [{ skillId: a }]); + + await skills.replaceDependencies(agent.id, [{ skillId: b }, { skillId: 'skill_unknown' }]); + + expect(await skills.findFollowingAgentIds([a])).toEqual([]); + expect(await skills.findFollowingAgentIds([b])).toEqual([agent.id]); + }); + + it('leaves pinned refs out of the following agents', async () => { + const id = await createSkill(); + const v1 = await latestVersionId(id); + const following = await createAgent('Following'); + const pinned = await createAgent('Pinned'); + await skills.replaceDependencies(following.id, [{ skillId: id }]); + await skills.replaceDependencies(pinned.id, [{ skillId: id, versionId: v1 }]); + + expect(await skills.findFollowingAgentIds([id])).toEqual([following.id]); + expect(await skills.findFollowingAgents(id)).toEqual([ + { id: following.id, name: 'Following' }, + ]); + }); + + it('lets a following ref win over a pinned ref to the same skill', async () => { + const id = await createSkill(); + const v1 = await latestVersionId(id); + const agent = await createAgent('Both'); + + await skills.replaceDependencies(agent.id, [{ skillId: id }, { skillId: id, versionId: v1 }]); + expect(await skills.findFollowingAgentIds([id])).toEqual([agent.id]); + + await skills.replaceDependencies(agent.id, [{ skillId: id, versionId: v1 }, { skillId: id }]); + expect(await skills.findFollowingAgentIds([id])).toEqual([agent.id]); + }); + + it('returns the refs of each agent in the order they were attached', async () => { + const [a, b, c] = [await createSkill(), await createSkill(), await createSkill()]; + const v1 = await latestVersionId(a); + const agent = await createAgent('Support'); + const other = await createAgent('Sales'); + await skills.replaceDependencies(agent.id, [{ skillId: b }, { skillId: a, versionId: v1 }]); + await skills.replaceDependencies(other.id, [{ skillId: c }]); + + const byAgent = await skills.findDependencies([agent.id, other.id]); + + expect(byAgent).toEqual( + new Map([ + [ + agent.id, + [ + { skillId: b, versionId: null }, + { skillId: a, versionId: v1 }, + ], + ], + [other.id, [{ skillId: c, versionId: null }]], + ]), + ); + }); + + // The attach order of an agent's skills comes from `createdAt`, so a row that stays + // keeps its timestamp. + it('keeps the rows that stay, so a new skill sorts after them', async () => { + const [a, b, c] = [await createSkill(), await createSkill(), await createSkill()]; + const agent = await createAgent('Support'); + await skills.replaceDependencies(agent.id, [{ skillId: a }, { skillId: b }]); + + await skills.replaceDependencies(agent.id, [{ skillId: c }, { skillId: b }, { skillId: a }]); + + expect( + (await skills.findDependencies([agent.id])).get(agent.id)?.map((ref) => ref.skillId), + ).toEqual([a, b, c]); + }); + + it('updates the pin of a row that stays', async () => { + const id = await createSkill(); + const v1 = await latestVersionId(id); + const agent = await createAgent('Support'); + await skills.replaceDependencies(agent.id, [{ skillId: id }]); + + await skills.replaceDependencies(agent.id, [{ skillId: id, versionId: v1 }]); + expect(await skills.findFollowingAgentIds([id])).toEqual([]); + + await skills.replaceDependencies(agent.id, [{ skillId: id }]); + expect(await skills.findFollowingAgentIds([id])).toEqual([agent.id]); + }); + }); + + describe('usage', () => { + it('lists each agent once, with the version its current published version runs', async () => { + const id = await createSkill(); + const v1 = await latestVersionId(id); + const v2 = await skills.insertSavedVersion(id, 2, content({ instructions: 'v2' }), null); + const drafting = await createAgent('Drafting'); + await skills.replaceDependencies(drafting.id, [{ skillId: id }]); + const published = await createAgent('Published'); + const old = await publish(published.id); + const current = await publish(published.id); + await agents.update({ id: published.id }, { activeVersionId: current }); + const retired = await createAgent('Retired', { inSync: true }); + await skills.insertPins([ + { agentVersionId: old, skillId: id, skillVersionId: v1 }, + { agentVersionId: current, skillId: id, skillVersionId: v2 }, + { agentVersionId: await publish(retired.id), skillId: id, skillVersionId: v1 }, + ]); + + const usage = await skills.findUsage(id); + + expect(usage.drafts).toEqual([ + { agentId: drafting.id, agentName: 'Drafting', projectId: project.id }, + ]); + expect(usage.pins).toHaveLength(2); + expect(usage.pins).toEqual( + expect.arrayContaining([ + { agentId: published.id, agentName: 'Published', projectId: project.id, version: 2 }, + { agentId: retired.id, agentName: 'Retired', projectId: project.id, version: null }, + ]), + ); + expect(usage.hiddenAgents).toBe(0); + }); + + it('leaves out the agents of other projects and counts them', async () => { + const id = await createSkill(); + const v1 = await latestVersionId(id); + const visible = await createAgent('Visible'); + await skills.replaceDependencies(visible.id, [{ skillId: id }]); + const drafting = await createAgent('Elsewhere', { projectId: otherProject.id }); + await skills.replaceDependencies(drafting.id, [{ skillId: id }]); + const published = await createAgent('Published elsewhere', { projectId: otherProject.id }); + await skills.insertPins([ + { agentVersionId: await publish(published.id), skillId: id, skillVersionId: v1 }, + ]); + + const usage = await skills.findUsage(id, [project.id]); + + expect(usage).toEqual({ + drafts: [{ agentId: visible.id, agentName: 'Visible', projectId: project.id }], + pins: [], + hiddenAgents: 2, + }); + }); + + it('is empty for a skill nobody uses', async () => { + const id = await createSkill(); + + expect(await skills.findUsage(id)).toEqual({ drafts: [], pins: [], hiddenAgents: 0 }); + }); + + it('counts distinct agents per skill across drafts and pins', async () => { + const id = await createSkill(); + const unused = await createSkill(); + const v1 = await latestVersionId(id); + const agent = await createAgent('Support'); + await skills.replaceDependencies(agent.id, [{ skillId: id }]); + const other = await createAgent('Sales'); + for (const agentId of [agent.id, other.id]) { + for (let i = 0; i < 3; i++) { + await skills.insertPins([ + { agentVersionId: await publish(agentId), skillId: id, skillVersionId: v1 }, + ]); + } + } + + const counts = await skills.countUsingAgents([id, unused, ...manyUnknownIds()]); + + expect(counts.get(id)).toBe(2); + expect(counts.get(unused)).toBeUndefined(); + }); + }); + + describe('findUsingAgentIds and updateTarget', () => { + it('lists the agents with a draft ref or a published pin, once each', async () => { + const id = await createSkill({ projectId: project.id }); + const drafting = await createAgent('Drafting'); + await skills.replaceDependencies(drafting.id, [{ skillId: id }]); + const published = await createAgent('Published'); + await skills.insertPins([ + { + agentVersionId: await publish(published.id), + skillId: id, + skillVersionId: await latestVersionId(id), + }, + ]); + await skills.replaceDependencies(published.id, [{ skillId: id }]); + + expect((await skills.findUsingAgentIds(id)).sort()).toEqual( + [drafting.id, published.id].sort(), + ); + }); + + it('moves a skill to one agent and back to the instance', async () => { + const id = await createSkill({ projectId: project.id }); + const agent = await createAgent('Agent'); + + await skills.updateTarget(id, { projectId: null, agentId: agent.id }); + expect((await skills.findByIds([id]))[0]).toMatchObject({ + projectId: null, + agentId: agent.id, + }); + + await skills.updateTarget(id, { projectId: null, agentId: null }); + expect((await skills.findByIds([id]))[0]).toMatchObject({ projectId: null, agentId: null }); + }); + }); + + describe('findProjectNames', () => { + it('maps project ids to names', async () => { + const names = await skills.findProjectNames([project.id, project.id, otherProject.id]); + + expect(names).toEqual( + new Map([ + [project.id, 'Team'], + [otherProject.id, 'Other team'], + ]), + ); + }); + }); + + describe('findAgents', () => { + it('maps agent ids to their name and project, and skips unknown ids', async () => { + const support = await createAgent('Support'); + const sales = await createAgent('Sales', { projectId: otherProject.id }); + + const agents = await skills.findAgents([support.id, support.id, sales.id, 'agent-gone']); + + expect(agents).toEqual( + new Map([ + [support.id, { name: 'Support', projectId: project.id }], + [sales.id, { name: 'Sales', projectId: otherProject.id }], + ]), + ); + }); + }); + + describe('deleteSkill', () => { + it('removes the skill with its versions, files and dependency rows', async () => { + const id = await createSkill( + {}, + content({ files: [{ path: 'references/a.md', content: 'a' }] }), + ); + const v1 = await latestVersionId(id); + const agent = await createAgent('Support'); + await skills.replaceDependencies(agent.id, [{ skillId: id }]); + + await skills.deleteSkill(id); + + expect(await skills.findByIds([id])).toEqual([]); + expect((await skills.findVersionsByIds([v1])).size).toBe(0); + expect(await skills.findFollowingAgentIds([id])).toEqual([]); + }); + + it('removes the pins of published agent versions with the skill', async () => { + const id = await createSkill(); + const agent = await createAgent('Support'); + const agentVersionId = await publish(agent.id); + await skills.insertPins([ + { agentVersionId, skillId: id, skillVersionId: await latestVersionId(id) }, + ]); + + await skills.deleteSkill(id); + + expect(await skills.findPinned(agentVersionId)).toEqual(new Map()); + }); + }); + + describe('row locks', () => { + it('refuse to run outside a transaction', async () => { + const id = await createSkill(); + + await expect(skills.lockForEdit([id])).rejects.toThrow('transaction'); + await expect(skills.lockForPublish([id])).rejects.toThrow('transaction'); + }); + + it('run inside a transaction', async () => { + const id = await createSkill(); + + await txRunner.run({}, async (ctx) => { + await skills.lockForEdit([id], ctx); + await skills.lockForPublish([id], ctx); + }); + }); + }); + + describe('AgentRepository.markDraftChangedIfInSync', () => { + it('gives an agent in sync with its published version a new draft version id', async () => { + const agent = await createAgent('Support', { inSync: true }); + + const changed = await agents.markDraftChangedIfInSync([agent.id]); + + const reloaded = await agents.findOneByOrFail({ id: agent.id }); + expect(changed).toEqual([agent.id]); + expect(reloaded.versionId).not.toBe(reloaded.activeVersionId); + expect(reloaded.revision).toBe(agent.revision); + }); + + it('leaves an agent that already has unpublished changes alone', async () => { + const agent = await createAgent('Support'); + + const changed = await agents.markDraftChangedIfInSync([agent.id]); + + const reloaded = await agents.findOneByOrFail({ id: agent.id }); + expect(changed).toEqual([]); + expect(reloaded.versionId).toBe(agent.versionId); + }); + + it('writes nothing for no agents', async () => { + expect(await agents.markDraftChangedIfInSync([])).toEqual([]); + expect(await agents.findProjectIdsByIds([])).toEqual([]); + }); + + it('returns the project of each agent', async () => { + const agent = await createAgent('Support'); + + expect(await agents.findProjectIdsByIds([agent.id])).toEqual([ + { id: agent.id, projectId: project.id }, + ]); + }); + }); +}); diff --git a/packages/cli/test/integration/agents/skills-hub-startup-copy.test.ts b/packages/cli/test/integration/agents/skills-hub-startup-copy.test.ts new file mode 100644 index 00000000000..22852637653 --- /dev/null +++ b/packages/cli/test/integration/agents/skills-hub-startup-copy.test.ts @@ -0,0 +1,858 @@ +import type { AgentSkill } from '@n8n/api-types'; +import { createTeamProject, mockInstance, testDb, testModules } from '@n8n/backend-test-utils'; +import { Logger } from '@n8n/backend-common'; +import type { Project } from '@n8n/db'; +import { Container } from '@n8n/di'; +import { InstanceSettings } from 'n8n-core'; +import { randomUUID } from 'node:crypto'; + +import { setSkillsHubFlag } from '@/modules/agents/__tests__/test-utils/skills-hub-flag'; +import { AgentRuntimeCacheService } from '@/modules/agents/agent-runtime-cache.service'; +import { AgentSkillRefsService } from '@/modules/agents/agent-skill-refs.service'; +import { AgentUpdateBroadcaster } from '@/modules/agents/agent-update-broadcaster'; +import type { Agent } from '@/modules/agents/entities/agent.entity'; +import { AgentHistoryRepository } from '@/modules/agents/repositories/agent-history.repository'; +import { AgentRepository } from '@/modules/agents/repositories/agent.repository'; +import { SkillRepository } from '@/modules/agents/repositories/skill.repository'; +import { SkillsHubStartupCopy } from '@/modules/agents/skills/skills-hub-startup-copy'; +import { Telemetry } from '@/telemetry'; + +function body(name: string, instructions = `${name} instructions.`): AgentSkill { + return { name, description: `${name} description`, instructions }; +} + +type InlineRef = { type: 'skill'; id: string; enabled?: boolean }; + +describe('SkillsHubStartupCopy', () => { + let project: Project; + let agents: AgentRepository; + let histories: AgentHistoryRepository; + let skills: SkillRepository; + let skillRefs: AgentSkillRefsService; + let copy: SkillsHubStartupCopy; + + beforeAll(async () => { + mockInstance(Telemetry); + mockInstance(AgentRuntimeCacheService); + mockInstance(AgentUpdateBroadcaster); + await testModules.loadModules(['agents']); + await testDb.init(); + agents = Container.get(AgentRepository); + histories = Container.get(AgentHistoryRepository); + skills = Container.get(SkillRepository); + skillRefs = Container.get(AgentSkillRefsService); + copy = Container.get(SkillsHubStartupCopy); + // Every main copies. Only the leader logs the flag-off warning. + Container.get(InstanceSettings).markAsLeader(); + }); + + beforeEach(async () => { + project = await createTeamProject(); + await setSkillsHubFlag(true); + }); + + afterEach(async () => { + await agents.delete({}); + await skills.delete({}); + }); + + afterAll(async () => { + await testDb.terminate(); + }); + + /** An agent as the legacy path stores it: refs in `schema.skills`, bodies in `skills`. */ + async function legacyAgent(refs: unknown[] | null, bodies: Record | null) { + return await agents.save( + agents.create({ + id: randomUUID(), + name: 'Agent', + projectId: project.id, + schema: (refs === null + ? null + : { name: 'Agent', model: '', instructions: 'Help.', skills: refs }) as never, + skills: bodies as never, + integrations: [], + tools: {}, + versionId: randomUUID(), + }), + ); + } + + let publishedAt = new Date('2026-01-01T00:00:00.000Z'); + + /** A published version as the legacy path stores it. */ + async function legacyVersion(agent: Agent, refs: unknown[], bodies: Record) { + const versionId = randomUUID(); + // Each publish gets its own time, as real publishes do, so the order is stable. + publishedAt = new Date(publishedAt.getTime() + 1000); + await histories.save( + histories.create({ + versionId, + agentId: agent.id, + author: 'Test', + createdAt: publishedAt, + schema: { name: 'Agent', model: '', instructions: 'Help.', skills: refs } as never, + skills: bodies as never, + }), + ); + await agents.update({ id: agent.id }, { activeVersionId: versionId }); + return versionId; + } + + const instructionsOf = (record: Record) => + Object.fromEntries(Object.entries(record).map(([id, skill]) => [id, skill.instructions])); + + /** The text of each version of one skill of the agent, oldest first. */ + async function versionTexts(agentId: string, skillId: string) { + const rows = (await skills.findAgentSkillVersions(agentId)) + .filter((row) => row.skillId === skillId) + .sort((a, b) => a.version - b.version); + const full = await skills.findVersionsByIds(rows.map((row) => row.id)); + return rows.map((row) => full.get(row.id)?.version.instructions); + } + + /** What one published version runs, keyed by skill id. */ + async function pinnedTexts(versionId: string) { + const pinned = await skills.findPinned(versionId); + return Object.fromEntries([...pinned].map(([id, row]) => [id, row.version.instructions])); + } + + it('copies the draft and the published versions as agent skills, and keeps the legacy columns', async () => { + const refs: InlineRef[] = [ + { type: 'skill', id: 'tone' }, + { type: 'skill', id: 'pricing' }, + ]; + const agent = await legacyAgent(refs, { + tone: body('Tone', 'Draft tone.'), + pricing: body('Pricing'), + }); + const versionId = await legacyVersion(agent, refs, { + tone: body('Tone', 'Published tone.'), + pricing: body('Pricing'), + }); + + const counts = await copy.copyAll(); + + expect(counts).toMatchObject({ agents: 1, skills: 2, failed: 0 }); + // The draft follows the newest version, which holds its text. + const draft = await skillRefs.readDraft(agent, {}); + expect(draft.skillRefs).toEqual(refs.map(({ id }) => ({ type: 'skill', id }))); + expect(instructionsOf(draft.skills)).toEqual({ + tone: 'Draft tone.', + pricing: 'Pricing instructions.', + }); + // The published version pins the text it ran. + const version = await histories.findOneByOrFail({ versionId }); + expect(instructionsOf((await skillRefs.readVersion(version, {})).skills)).toEqual({ + tone: 'Published tone.', + pricing: 'Pricing instructions.', + }); + // Each copy is a skill of this agent only. + expect(await skills.findByIds(['tone', 'pricing'])).toEqual([ + expect.objectContaining({ projectId: null, agentId: agent.id, source: 'agent' }), + expect.objectContaining({ projectId: null, agentId: agent.id, source: 'agent' }), + ]); + const row = await agents.findOneByOrFail({ id: agent.id }); + expect(row.schema?.skills).toEqual(refs); + expect(row.skills).toEqual(agent.skills); + }); + + it('writes nothing on a second run', async () => { + const agent = await legacyAgent([{ type: 'skill', id: 'tone' }], { tone: body('Tone') }); + await legacyVersion(agent, [{ type: 'skill', id: 'tone' }], { tone: body('Tone') }); + await copy.copyAll(); + const before = await skills.findAgentSkillVersions(agent.id); + + const counts = await copy.copyAll(); + + expect(counts).toMatchObject({ agents: 0, skills: 0, versions: 0, pins: 0 }); + expect(await skills.findAgentSkillVersions(agent.id)).toEqual(before); + }); + + it('does not copy a ref that was switched off', async () => { + const agent = await legacyAgent( + [ + { type: 'skill', id: 'tone' }, + { type: 'skill', id: 'old', enabled: false }, + ], + { tone: body('Tone'), old: body('Old') }, + ); + + await copy.copyAll(); + + expect(await skillRefs.refsForDraft(agent, {})).toEqual([{ type: 'skill', id: 'tone' }]); + expect(await skills.findByIds(['old'])).toEqual([]); + }); + + it('gives a second agent with the same ref id its own skill', async () => { + const first = await legacyAgent([{ type: 'skill', id: 'tone' }], { tone: body('Tone', 'A.') }); + const second = await legacyAgent([{ type: 'skill', id: 'tone' }], { tone: body('Tone', 'B.') }); + + await copy.copyAll(); + + // One agent keeps the id, the other gets a new one, and each runs its own text. + const [firstRef] = await skillRefs.refsForDraft(first, {}); + const [secondRef] = await skillRefs.refsForDraft(second, {}); + expect([firstRef.id, secondRef.id].filter((id) => id === 'tone')).toHaveLength(1); + expect(instructionsOf((await skillRefs.readDraft(first, {})).skills)).toEqual({ + [firstRef.id]: 'A.', + }); + expect(instructionsOf((await skillRefs.readDraft(second, {})).skills)).toEqual({ + [secondRef.id]: 'B.', + }); + }); + + it('gives an inline ref id longer than 36 characters a new id', async () => { + const longId = `skill_${'x'.repeat(40)}`; + const agent = await legacyAgent([{ type: 'skill', id: longId }], { + [longId]: body('Long', 'Long text.'), + }); + + await copy.copyAll(); + + const [ref] = await skillRefs.refsForDraft(agent, {}); + expect(ref.id).not.toBe(longId); + expect(ref.id.length).toBeLessThanOrEqual(36); + expect(instructionsOf((await skillRefs.readDraft(agent, {})).skills)).toEqual({ + [ref.id]: 'Long text.', + }); + }); + + it('does not attach a skill again after it was detached', async () => { + const agent = await legacyAgent([{ type: 'skill', id: 'tone' }], { tone: body('Tone') }); + await copy.copyAll(); + await skillRefs.replaceDraftRefs(agent, [], {}); + + await copy.copyAll(); + + expect(await skillRefs.refsForDraft(agent, {})).toEqual([]); + }); + + it('pins a version that was published with the flag off to the matching hub version', async () => { + const agent = await legacyAgent([{ type: 'skill', id: 'tone' }], { tone: body('Tone') }); + await copy.copyAll(); + const versionId = await legacyVersion(agent, [{ type: 'skill', id: 'tone' }], { + tone: body('Tone'), + }); + + const counts = await copy.copyAll(); + + expect(counts).toMatchObject({ skills: 0, versions: 0, pins: 1 }); + expect(await skills.findPinnedSkillIds(versionId)).toEqual(['tone']); + }); + + it('copies on a main at startup while the flag is on', async () => { + const agent = await legacyAgent([{ type: 'skill', id: 'tone' }], { tone: body('Tone') }); + + await copy.runOnStartup(); + + expect(await skillRefs.refsForDraft(agent, {})).toEqual([{ type: 'skill', id: 'tone' }]); + }); + + /** Saves new text for a hub skill, as an edit in the builder does. */ + async function editInHub(skillId: string, instructions: string) { + const next = await skills.nextVersionNumber(skillId); + await skills.insertSavedVersion( + skillId, + next, + { name: 'Edited', description: 'd', instructions, frontmatter: null, files: [] }, + null, + ); + } + + describe('with the flag off', () => { + beforeEach(() => { + vi.spyOn(Container.get(Logger), 'warn'); + }); + + afterEach(() => { + vi.restoreAllMocks(); + }); + + const hubOffWarning = () => + vi + .mocked(Container.get(Logger).warn) + .mock.calls.find(([message]) => String(message).includes('The skills hub is off')); + + it('copies nothing and reads only the draft refs and their content', async () => { + await legacyAgent([{ type: 'skill', id: 'tone' }], { tone: body('Tone') }); + await setSkillsHubFlag(false); + const copyReads = [ + vi.spyOn(agents, 'findPageForSkillCopy'), + vi.spyOn(skills, 'findUnpinnedVersions'), + vi.spyOn(skills, 'hasHubState'), + vi.spyOn(skills, 'findAgentSkillVersions'), + vi.spyOn(skills, 'createSkill'), + vi.spyOn(skills, 'replaceDependencies'), + vi.spyOn(skills, 'insertPins'), + ]; + + await copy.runOnStartup(); + + for (const spy of copyReads) expect(spy).not.toHaveBeenCalled(); + expect(await skills.find()).toEqual([]); + expect(hubOffWarning()).toBeUndefined(); + }); + + it('reads nothing from the hub on a main that is not the leader', async () => { + await legacyAgent([{ type: 'skill', id: 'tone' }], { tone: body('Tone') }); + await copy.copyAll(); + await editInHub('tone', 'Edited in the hub.'); + await setSkillsHubFlag(false); + const findRefs = vi.spyOn(skills, 'findAgentIdsWithDraftRefs'); + const settings = Container.get(InstanceSettings); + settings.markAsFollower(); + try { + await copy.runOnStartup(); + } finally { + settings.markAsLeader(); + } + + expect(findRefs).not.toHaveBeenCalled(); + expect(hubOffWarning()).toBeUndefined(); + }); + + it('names no agent when the hub runs the same content as the inline skills', async () => { + await legacyAgent([{ type: 'skill', id: 'tone' }], { tone: body('Tone') }); + await copy.copyAll(); + await setSkillsHubFlag(false); + + await copy.runOnStartup(); + + expect(hubOffWarning()).toBeUndefined(); + }); + + it('names an agent whose skill changed in the hub, and counts it once', async () => { + const agent = await legacyAgent( + [ + { type: 'skill', id: 'tone' }, + { type: 'skill', id: 'pricing' }, + ], + { tone: body('Tone'), pricing: body('Pricing') }, + ); + await legacyAgent([{ type: 'skill', id: 'other' }], { other: body('Other') }); + await copy.copyAll(); + await editInHub('tone', 'Edited in the hub.'); + await editInHub('pricing', 'Edited in the hub.'); + await setSkillsHubFlag(false); + + await copy.runOnStartup(); + + expect(hubOffWarning()?.[1]).toEqual({ agents: 1, agentIds: [agent.id] }); + }); + + it('names an agent that got a skill only in the hub', async () => { + const agent = await legacyAgent([{ type: 'skill', id: 'tone' }], { tone: body('Tone') }); + await copy.copyAll(); + await skills.createSkill( + { + id: 'added', + target: { projectId: null, agentId: agent.id }, + source: 'agent', + createdById: null, + }, + { name: 'Added', description: 'd', instructions: 'New.', frontmatter: null, files: [] }, + ); + await skills.replaceDependencies(agent.id, [{ skillId: 'tone' }, { skillId: 'added' }]); + await setSkillsHubFlag(false); + + await copy.runOnStartup(); + + expect(hubOffWarning()?.[1]).toEqual({ agents: 1, agentIds: [agent.id] }); + }); + }); + + describe('what an agent row holds', () => { + it('writes nothing for an agent without a config or without skills', async () => { + await legacyAgent(null, {}); + await legacyAgent([], {}); + + const counts = await copy.copyAll(); + + expect(counts).toMatchObject({ agents: 0, skills: 0, versions: 0, pins: 0, failed: 0 }); + expect(await skills.find()).toEqual([]); + }); + + it('skips a ref without a body and a body without a ref', async () => { + const agent = await legacyAgent( + [ + { type: 'skill', id: 'tone' }, + { type: 'skill', id: 'dangling' }, + ], + { tone: body('Tone'), orphan: body('Orphan') }, + ); + + await copy.copyAll(); + + expect(await skillRefs.refsForDraft(agent, {})).toEqual([{ type: 'skill', id: 'tone' }]); + expect(await skills.findByIds(['dangling', 'orphan'])).toEqual([]); + }); + + it('ignores refs and bodies the runtime could not load either', async () => { + const agent = await legacyAgent( + [ + { type: 'skill', id: 'tone' }, + { type: 'tool', id: 'not-a-skill' }, + { type: 'skill' }, + { type: 'skill', id: 42 }, + 'garbage', + { type: 'skill', id: 'no_instructions' }, + { type: 'skill', id: 'not_an_object' }, + ], + { + tone: body('Tone'), + 'not-a-skill': body('Tool'), + no_instructions: { name: 'Broken', description: 'No text' }, + not_an_object: 'text', + }, + ); + + const counts = await copy.copyAll(); + + expect(counts).toMatchObject({ skills: 1, failed: 0 }); + expect(await skillRefs.refsForDraft(agent, {})).toEqual([{ type: 'skill', id: 'tone' }]); + }); + + it('attaches a repeated ref once and keeps the ref order', async () => { + const agent = await legacyAgent( + [ + { type: 'skill', id: 'zeta' }, + { type: 'skill', id: 'alpha' }, + { type: 'skill', id: 'zeta' }, + { type: 'skill', id: 'mid' }, + ], + { zeta: body('Zeta'), alpha: body('Alpha'), mid: body('Mid') }, + ); + + await copy.copyAll(); + + expect((await skillRefs.refsForDraft(agent, {})).map((ref) => ref.id)).toEqual([ + 'zeta', + 'alpha', + 'mid', + ]); + }); + + it('keeps two refs with the same body as two skills', async () => { + const agent = await legacyAgent( + [ + { type: 'skill', id: 'first' }, + { type: 'skill', id: 'second' }, + ], + { first: body('Greet', 'Same.'), second: body('Greet', 'Same.') }, + ); + + await copy.copyAll(); + + expect((await skillRefs.refsForDraft(agent, {})).map((ref) => ref.id)).toEqual([ + 'first', + 'second', + ]); + }); + + it('does not move a ref onto the skill of another ref that once had its body', async () => { + const agent = await legacyAgent( + [ + { type: 'skill', id: 'a' }, + { type: 'skill', id: 'b' }, + ], + { a: body('Greet', 'Y'), b: body('Greet', 'X') }, + ); + const versionId = await legacyVersion(agent, [{ type: 'skill', id: 'a' }], { + a: body('Greet', 'X'), + }); + + await copy.copyAll(); + + expect(instructionsOf((await skillRefs.readDraft(agent, {})).skills)).toEqual({ + a: 'Y', + b: 'X', + }); + expect(await pinnedTexts(versionId)).toEqual({ a: 'X' }); + }); + + it('copies name, description, instructions and reference files exactly', async () => { + const tone: AgentSkill = { + name: ' Tone of Voice ', + description: 'How we write', + instructions: 'Be brief.', + references: [ + { path: 'references/b.md', content: 'B' }, + { path: 'references/a.md', content: 'A' }, + ], + }; + const agent = await legacyAgent([{ type: 'skill', id: 'tone' }], { tone }); + + await copy.copyAll(); + + const { skills: copied } = await skillRefs.readDraft(agent, {}); + expect(copied.tone).toEqual({ + ...tone, + // Files are sorted by path, as everywhere in the hub. + references: [ + { path: 'references/a.md', content: 'A' }, + { path: 'references/b.md', content: 'B' }, + ], + }); + const [skill] = await skills.findByIds(['tone']); + expect(skill).toMatchObject({ source: 'agent', createdById: null }); + }); + + it('keeps the first copy of a repeated reference path', async () => { + const agent = await legacyAgent([{ type: 'skill', id: 'tone' }], { + tone: { + ...body('Tone'), + references: [ + { path: 'references/a.md', content: 'First' }, + { path: 'references/a.md', content: 'Second' }, + ], + }, + }); + + await copy.copyAll(); + + const { skills: copied } = await skillRefs.readDraft(agent, {}); + expect(copied.tone.references).toEqual([{ path: 'references/a.md', content: 'First' }]); + }); + + it('drops allowedTools, which hub skills ignore', async () => { + const agent = await legacyAgent([{ type: 'skill', id: 'tone' }], { + tone: { ...body('Tone'), allowedTools: ['search'] }, + }); + + await copy.copyAll(); + + const { skills: copied } = await skillRefs.readDraft(agent, {}); + expect(copied.tone).toEqual(body('Tone')); + }); + + it('gives a new id when a skill elsewhere already has the inline id', async () => { + const other = await createTeamProject(); + await skills.createSkill( + { + id: 'tone', + target: { projectId: other.id, agentId: null }, + source: 'ui', + createdById: null, + }, + { name: 'Other', description: 'd', instructions: 'Other.', frontmatter: null, files: [] }, + ); + const agent = await legacyAgent([{ type: 'skill', id: 'tone' }], { + tone: body('Tone', 'Mine.'), + }); + + await copy.copyAll(); + + const [ref] = await skillRefs.refsForDraft(agent, {}); + expect(ref.id).not.toBe('tone'); + expect(instructionsOf((await skillRefs.readDraft(agent, {})).skills)).toEqual({ + [ref.id]: 'Mine.', + }); + }); + }); + + describe('published versions', () => { + it('turns each published text into a version, newest draft text last, and pins each version', async () => { + const refs = [{ type: 'skill', id: 'tone' }]; + const agent = await legacyAgent(refs, { tone: body('Tone', 'C') }); + const first = await legacyVersion(agent, refs, { tone: body('Tone', 'A') }); + const second = await legacyVersion(agent, refs, { tone: body('Tone', 'B') }); + + await copy.copyAll(); + + expect(await versionTexts(agent.id, 'tone')).toEqual(['A', 'B', 'C']); + expect(await pinnedTexts(first)).toEqual({ tone: 'A' }); + expect(await pinnedTexts(second)).toEqual({ tone: 'B' }); + expect(instructionsOf((await skillRefs.readDraft(agent, {})).skills)).toEqual({ + tone: 'C', + }); + }); + + it('adds no version when the draft runs the published text', async () => { + const refs = [{ type: 'skill', id: 'tone' }]; + const agent = await legacyAgent(refs, { tone: body('Tone', 'Same.') }); + const versionId = await legacyVersion(agent, refs, { tone: body('Tone', 'Same.') }); + + await copy.copyAll(); + + expect(await versionTexts(agent.id, 'tone')).toEqual(['Same.']); + expect(await pinnedTexts(versionId)).toEqual({ tone: 'Same.' }); + }); + + it('saves an older text again as the newest version when the draft went back to it', async () => { + const refs = [{ type: 'skill', id: 'tone' }]; + const agent = await legacyAgent(refs, { tone: body('Tone', 'A') }); + await legacyVersion(agent, refs, { tone: body('Tone', 'A') }); + await legacyVersion(agent, refs, { tone: body('Tone', 'B') }); + + await copy.copyAll(); + + // The draft follows the newest version, so A must come back as v3. + expect(await versionTexts(agent.id, 'tone')).toEqual(['A', 'B', 'A']); + expect(instructionsOf((await skillRefs.readDraft(agent, {})).skills)).toEqual({ + tone: 'A', + }); + }); + + it('pins a skill that only a published version has, without attaching it to the draft', async () => { + const agent = await legacyAgent([], {}); + const versionId = await legacyVersion(agent, [{ type: 'skill', id: 'gone' }], { + gone: body('Gone', 'Published only.'), + }); + + await copy.copyAll(); + + expect(await pinnedTexts(versionId)).toEqual({ gone: 'Published only.' }); + expect(await skillRefs.refsForDraft(agent, {})).toEqual([]); + }); + + it('does not pin a ref that was switched off in a published version', async () => { + const agent = await legacyAgent([], {}); + const versionId = await legacyVersion( + agent, + [ + { type: 'skill', id: 'tone' }, + { type: 'skill', id: 'off', enabled: false }, + ], + { tone: body('Tone'), off: body('Off') }, + ); + + await copy.copyAll(); + + expect(Object.keys(await pinnedTexts(versionId))).toEqual(['tone']); + }); + + it('keeps the pins of a published version in ref order', async () => { + const refs = [ + { type: 'skill', id: 'zeta' }, + { type: 'skill', id: 'alpha' }, + ]; + const agent = await legacyAgent(refs, { zeta: body('Zeta'), alpha: body('Alpha') }); + const versionId = await legacyVersion(agent, refs, { + zeta: body('Zeta'), + alpha: body('Alpha'), + }); + + await copy.copyAll(); + + expect(await skills.findPinnedSkillIds(versionId)).toEqual(['zeta', 'alpha']); + }); + + it('leaves the agent_history rows as they are', async () => { + const refs = [{ type: 'skill', id: 'tone' }]; + const agent = await legacyAgent(refs, { tone: body('Tone') }); + const versionId = await legacyVersion(agent, refs, { tone: body('Tone', 'Published.') }); + const before = await histories.findOneByOrFail({ versionId }); + + await copy.copyAll(); + + expect(await histories.findOneByOrFail({ versionId })).toEqual(before); + }); + }); + + describe('running again', () => { + it('treats a published version without skills as done on every run', async () => { + const agent = await legacyAgent([{ type: 'skill', id: 'tone' }], { tone: body('Tone') }); + await legacyVersion(agent, [], {}); + await copy.copyAll(); + + expect(await copy.copyAll()).toMatchObject({ agents: 0, versions: 0, pins: 0 }); + }); + + it('keeps hub content when the inline text changed while the flag was off', async () => { + // Known gap: the merge rule for this case is open, so the hub wins. + const agent = await legacyAgent([{ type: 'skill', id: 'tone' }], { + tone: body('Tone', 'Before.'), + }); + await copy.copyAll(); + await agents.update({ id: agent.id }, { skills: { tone: body('Tone', 'Edited inline.') } }); + + await copy.copyAll(); + + expect(instructionsOf((await skillRefs.readDraft(agent, {})).skills)).toEqual({ + tone: 'Before.', + }); + }); + + it('copies an agent created while the flag was off on the next run', async () => { + await copy.copyAll(); + const agent = await legacyAgent([{ type: 'skill', id: 'tone' }], { tone: body('Tone') }); + + await copy.copyAll(); + + expect(await skillRefs.refsForDraft(agent, {})).toEqual([{ type: 'skill', id: 'tone' }]); + }); + }); + + describe('failures', () => { + afterEach(() => { + vi.restoreAllMocks(); + }); + + it('rolls back a failing agent, copies the others, and copies it on the next run', async () => { + const broken = await legacyAgent([{ type: 'skill', id: 'broken' }], { + broken: body('Broken'), + }); + const fine = await legacyAgent([{ type: 'skill', id: 'fine' }], { fine: body('Fine') }); + const replace = skills.replaceDependencies.bind(skills); + const failFor = vi + .spyOn(skills, 'replaceDependencies') + .mockImplementation(async (agentId, refs, ctx) => { + if (agentId === broken.id) throw new Error('Write failed'); + return await replace(agentId, refs, ctx); + }); + + const counts = await copy.copyAll(); + + expect(counts).toMatchObject({ agents: 1, failed: 1 }); + // The failed agent's skill was rolled back with the rest of its copy. + expect(await skills.findByIds(['broken'])).toEqual([]); + expect(await skillRefs.refsForDraft(fine, {})).toEqual([{ type: 'skill', id: 'fine' }]); + + failFor.mockRestore(); + await copy.copyAll(); + + expect(await skillRefs.refsForDraft(broken, {})).toEqual([{ type: 'skill', id: 'broken' }]); + }); + + it('retries an agent once after a failed try', async () => { + const agent = await legacyAgent([{ type: 'skill', id: 'tone' }], { tone: body('Tone') }); + const replace = skills.replaceDependencies.bind(skills); + vi.spyOn(skills, 'replaceDependencies') + .mockRejectedValueOnce(new Error('Duplicate key')) + .mockImplementation(replace); + + const counts = await copy.copyAll(); + + // The failed try rolled back, so only the second try counts. + expect(counts).toMatchObject({ agents: 1, skills: 1, versions: 1, failed: 0 }); + expect(await skillRefs.refsForDraft(agent, {})).toEqual([{ type: 'skill', id: 'tone' }]); + }); + + it('copies the inline text as it is when the copy reaches the agent, not when it read the page', async () => { + const agent = await legacyAgent([{ type: 'skill', id: 'tone' }], { + tone: body('Tone', 'Old.'), + }); + const findPage = agents.findPageForSkillCopy.bind(agents); + vi.spyOn(agents, 'findPageForSkillCopy').mockImplementationOnce(async (...args) => { + const page = await findPage(...args); + // A main with the flag still off saves the draft after the page was read. + await agents.update({ id: agent.id }, { skills: { tone: body('Tone', 'New.') } }); + return page; + }); + + await copy.copyAll(); + + expect(instructionsOf((await skillRefs.readDraft(agent, {})).skills)).toEqual({ + tone: 'New.', + }); + }); + + it('picks a new id when another agent took the same inline id first', async () => { + const first = await legacyAgent([{ type: 'skill', id: 'tone' }], { + tone: body('Tone', 'A.'), + }); + const second = await legacyAgent([{ type: 'skill', id: 'tone' }], { + tone: body('Tone', 'B.'), + }); + // As when two mains copy at once: both see `tone` as free, so the second insert + // fails on the primary key. + vi.spyOn(skills, 'existsById').mockResolvedValueOnce(false).mockResolvedValueOnce(false); + + const counts = await copy.copyAll(); + + expect(counts).toMatchObject({ agents: 2, skills: 2, versions: 2, failed: 0 }); + const [firstRef] = await skillRefs.refsForDraft(first, {}); + const [secondRef] = await skillRefs.refsForDraft(second, {}); + expect([firstRef.id, secondRef.id].filter((id) => id === 'tone')).toHaveLength(1); + expect(instructionsOf((await skillRefs.readDraft(second, {})).skills)).toEqual({ + [secondRef.id]: 'B.', + }); + }); + }); + + describe('scale and instance roles', () => { + it('copies every agent across several pages', async () => { + const created = []; + for (let index = 0; index < 105; index++) { + created.push( + await legacyAgent([{ type: 'skill', id: `skill_${index}` }], { + [`skill_${index}`]: body(`Skill ${index}`), + }), + ); + } + + const counts = await copy.copyAll(); + + expect(counts).toMatchObject({ agents: 105, skills: 105, failed: 0 }); + const last = created[created.length - 1]; + expect(await skillRefs.refsForDraft(last, {})).toEqual([{ type: 'skill', id: 'skill_104' }]); + }); + + it('copies on a main that is not the leader', async () => { + const settings = Container.get(InstanceSettings); + settings.markAsFollower(); + try { + const agent = await legacyAgent([{ type: 'skill', id: 'tone' }], { tone: body('Tone') }); + + await copy.runOnStartup(); + + expect(await skillRefs.refsForDraft(agent, {})).toEqual([{ type: 'skill', id: 'tone' }]); + } finally { + settings.markAsLeader(); + } + }); + + it('does not copy on a worker', async () => { + const settings = Container.get(InstanceSettings); + const { instanceType } = settings; + Object.assign(settings, { instanceType: 'worker' }); + try { + await legacyAgent([{ type: 'skill', id: 'tone' }], { tone: body('Tone') }); + + await copy.runOnStartup(); + + expect(await skills.findByIds(['tone'])).toEqual([]); + } finally { + Object.assign(settings, { instanceType }); + } + }); + + it('names at most 20 agents in the warning, and counts all of them', async () => { + for (let index = 0; index < 22; index++) { + await legacyAgent([{ type: 'skill', id: `s${index}` }], { + [`s${index}`]: body(`S${index}`), + }); + } + await copy.copyAll(); + for (let index = 0; index < 22; index++) await editInHub(`s${index}`, 'Edited in the hub.'); + await setSkillsHubFlag(false); + const warn = vi.spyOn(Container.get(Logger), 'warn'); + + await copy.runOnStartup(); + + const [, meta] = warn.mock.calls.find(([message]) => + String(message).includes('The skills hub is off'), + )!; + expect(meta).toMatchObject({ agents: 22 }); + expect((meta as { agentIds: string[] }).agentIds).toHaveLength(20); + }); + }); + + // Two mains copy at once only on Postgres; SQLite runs one write transaction at a time. + describe.skipIf(process.env.DB_TYPE !== 'postgresdb')('two mains at once on Postgres', () => { + it('copies each agent once when two copies run side by side', async () => { + const refs = [{ type: 'skill', id: 'tone' }]; + const agent = await legacyAgent(refs, { tone: body('Tone', 'Draft.') }); + const versionId = await legacyVersion(agent, refs, { tone: body('Tone', 'Published.') }); + + const results = await Promise.all([copy.copyAll(), copy.copyAll()]); + + expect(results.reduce((sum, counts) => sum + counts.failed, 0)).toBe(0); + expect(await skills.find()).toHaveLength(1); + expect(await versionTexts(agent.id, 'tone')).toEqual(['Published.', 'Draft.']); + expect(await skills.findPinnedSkillIds(versionId)).toEqual(['tone']); + expect(await skillRefs.refsForDraft(agent, {})).toEqual([{ type: 'skill', id: 'tone' }]); + }); + }); +}); diff --git a/packages/cli/test/integration/agents/skills.controller.test.ts b/packages/cli/test/integration/agents/skills.controller.test.ts new file mode 100644 index 00000000000..82440777bef --- /dev/null +++ b/packages/cli/test/integration/agents/skills.controller.test.ts @@ -0,0 +1,414 @@ +import { createTeamProject, linkUserToProject, testDb, testModules } from '@n8n/backend-test-utils'; +import type { Project, User } from '@n8n/db'; +import { Container } from '@n8n/di'; +import { randomUUID } from 'node:crypto'; + +import { setSkillsHubFlag } from '@/modules/agents/__tests__/test-utils/skills-hub-flag'; +import { AgentHistoryRepository } from '@/modules/agents/repositories/agent-history.repository'; +import { AgentRepository } from '@/modules/agents/repositories/agent.repository'; +import { SkillRepository } from '@/modules/agents/repositories/skill.repository'; + +import { createMember, createOwner } from '../shared/db/users'; +import type { SuperAgentTest } from '../shared/types'; +import { setupTestServer } from '../shared/utils'; + +const body = { name: 'Brand voice', description: 'How we write', instructions: 'Be brief.' }; + +beforeAll(async () => { + await testModules.loadModules(['agents']); +}); + +describe('SkillsController', () => { + const server = setupTestServer({ endpointGroups: ['ai'] }); + let ownerUser: User; + let memberUser: User; + let owner: SuperAgentTest; + let member: SuperAgentTest; + let editor: SuperAgentTest; + let viewer: SuperAgentTest; + let outsider: SuperAgentTest; + let project: Project; + + beforeAll(async () => { + ownerUser = await createOwner(); + memberUser = await createMember(); + const editorUser = await createMember(); + const viewerUser = await createMember(); + owner = server.authAgentFor(ownerUser); + member = server.authAgentFor(memberUser); + editor = server.authAgentFor(editorUser); + viewer = server.authAgentFor(viewerUser); + outsider = server.authAgentFor(await createMember()); + project = await createTeamProject('Team'); + await linkUserToProject(editorUser, project, 'project:editor'); + await linkUserToProject(viewerUser, project, 'project:viewer'); + }); + + beforeEach(async () => { + await setSkillsHubFlag(true); + }); + + it('hides the skills API when the skills hub is off', async () => { + await setSkillsHubFlag(false); + + await owner.get('/skills').expect(404); + await owner.post('/skills').send({ scope: 'instance', skill: body }).expect(404); + // The flag is checked before the body, so a malformed request also answers 404. + await owner.post('/skills').send({ scope: 'nope' }).expect(404); + await owner.get('/skills?take=-1').expect(404); + }); + + afterEach(async () => { + await Container.get(AgentRepository).delete({}); + await Container.get(SkillRepository).delete({}); + }); + + async function newAgent(name: string, projectId: string) { + const agents = Container.get(AgentRepository); + return await agents.save( + agents.create({ + id: randomUUID(), + name, + projectId, + integrations: [], + tools: {}, + skills: {}, + versionId: randomUUID(), + }), + ); + } + + async function attachToNewAgent( + skillId: string, + name: string, + projectId: string, + options: { published?: boolean; pinnedVersionId?: string } = {}, + ) { + const agents = Container.get(AgentRepository); + const versionId = randomUUID(); + const agent = await agents.save( + agents.create({ + id: randomUUID(), + name, + projectId, + integrations: [], + tools: {}, + versionId, + }), + ); + if (options.published) { + // Published and in sync: the draft is the published version. + const histories = Container.get(AgentHistoryRepository); + await histories.save(histories.create({ versionId, agentId: agent.id, author: 'Test' })); + await agents.update({ id: agent.id }, { activeVersionId: versionId }); + } + await Container.get(SkillRepository).replaceDependencies(agent.id, [ + { skillId, versionId: options.pinnedVersionId }, + ]); + return { ...agent, versionId }; + } + + const draftVersionOf = async (agentId: string) => + (await Container.get(AgentRepository).findOneByOrFail({ id: agentId })).versionId; + + async function create(agent: SuperAgentTest, payload: object, status = 200) { + const response = await agent.post('/skills').send(payload).expect(status); + return response.body.data as { id: string; skillHash: string }; + } + + describe('agent skills', () => { + it('lets a project editor create one for an agent and checks the project of the agent', async () => { + const agent = await newAgent('Support bot', project.id); + const { id } = await create(editor, { scope: 'agent', agentId: agent.id, skill: body }); + + const read = await editor.get(`/skills/${id}`).expect(200); + expect(read.body.data).toMatchObject({ + id, + scope: 'agent', + agentId: agent.id, + agentName: 'Support bot', + projectId: project.id, + projectName: 'Team', + latestVersion: 1, + canEdit: true, + canDelete: true, + }); + await outsider.get(`/skills/${id}`).expect(404); + await outsider + .patch(`/skills/${id}`) + .send({ instructions: 'x', baseSkillHash: 'x' }) + .expect(404); + await owner.get(`/skills/${id}`).expect(200); + }); + + it('refuses an agent skill to a user outside the project, and for an unknown agent', async () => { + const agent = await newAgent('Support bot', project.id); + + await create(outsider, { scope: 'agent', agentId: agent.id, skill: body }, 403); + await create(editor, { scope: 'agent', skill: body }, 400); + await create(owner, { scope: 'agent', agentId: 'agent-gone', skill: body }, 404); + }); + }); + + describe('instance skills', () => { + it('lets only owners and admins create and edit them, and everyone read them', async () => { + await create(member, { scope: 'instance', skill: body }, 403); + const { id } = await create(owner, { scope: 'instance', skill: body }); + + const read = await member.get(`/skills/${id}`).expect(200); + expect(read.body.data).toMatchObject({ scope: 'instance', canEdit: false, canDelete: false }); + await member + .patch(`/skills/${id}`) + .send({ instructions: 'x', baseSkillHash: 'x' }) + .expect(403); + await member.delete(`/skills/${id}`).expect(403); + }); + + it('names only the agents the reader may see, and counts the others', async () => { + const { id } = await create(owner, { scope: 'instance', skill: body }); + const agent = await attachToNewAgent(id, 'Support bot', project.id); + + const asOutsider = await outsider.get(`/skills/${id}`).expect(200); + const asEditor = await editor.get(`/skills/${id}`).expect(200); + + expect(asOutsider.body.data.usedBy).toEqual({ drafts: [], pins: [], hiddenAgents: 1 }); + expect(asEditor.body.data.usedBy).toEqual({ + drafts: [{ agentId: agent.id, agentName: 'Support bot', projectId: project.id }], + pins: [], + hiddenAgents: 0, + }); + }); + }); + + describe('project skills', () => { + it('lets editors write, viewers read, and hides them from outsiders', async () => { + const { id } = await create(editor, { scope: 'project', projectId: project.id, skill: body }); + + await viewer.get(`/skills/${id}`).expect(200); + await viewer + .patch(`/skills/${id}`) + .send({ instructions: 'x', baseSkillHash: 'x' }) + .expect(403); + await outsider.get(`/skills/${id}`).expect(404); + await create(viewer, { scope: 'project', projectId: project.id, skill: body }, 403); + await create(outsider, { scope: 'project', projectId: project.id, skill: body }, 403); + }); + + it('needs a project id', async () => { + await create(editor, { scope: 'project', skill: body }, 400); + }); + + // The owner's global projectSkill:create passes the scope check for any project id. + it('answers 404 for a project that does not exist', async () => { + await create(owner, { scope: 'project', projectId: 'project-gone', skill: body }, 404); + await create(member, { scope: 'project', projectId: 'project-gone', skill: body }, 403); + }); + + it('shows editors, viewers and owners what they may do, in the detail and the list', async () => { + const { id } = await create(editor, { scope: 'project', projectId: project.id, skill: body }); + + for (const [agent, may] of [ + [editor, true], + [viewer, false], + [owner, true], + ] as const) { + const detail = await agent.get(`/skills/${id}`).expect(200); + const list = await agent.get('/skills').query({ projectId: project.id }).expect(200); + + const expected = { id, canEdit: may, canDelete: may }; + expect(detail.body.data).toMatchObject(expected); + expect(list.body.data.data).toEqual([expect.objectContaining(expected)]); + } + }); + }); + + describe('list', () => { + it('lists what the user may see, searched and paged on the server', async () => { + const agent = await newAgent('Support bot', project.id); + await create(editor, { scope: 'agent', agentId: agent.id, skill: { ...body, name: 'Mine' } }); + await create(owner, { scope: 'instance', skill: { ...body, name: 'Shared rules' } }); + await create(editor, { + scope: 'project', + projectId: project.id, + skill: { ...body, name: 'Team rules' }, + }); + + const all = await editor.get('/skills').expect(200); + const outside = await member.get('/skills').expect(200); + const search = await editor.get('/skills').query({ search: 'rules', take: 1 }).expect(200); + const ownerView = await owner.get('/skills').query({ scope: 'project' }).expect(200); + + expect(all.body.data.data.map((s: { name: string }) => s.name).sort()).toEqual([ + 'Mine', + 'Shared rules', + 'Team rules', + ]); + expect(outside.body.data.data.map((s: { name: string }) => s.name)).toEqual(['Shared rules']); + expect(search.body.data.count).toBe(2); + expect(search.body.data.data).toHaveLength(1); + expect(ownerView.body.data.data).toEqual([ + expect.objectContaining({ name: 'Team rules', projectName: 'Team' }), + ]); + }); + + it('lists the skills one agent may attach, never those of another agent', async () => { + const support = await newAgent('Support bot', project.id); + const sales = await newAgent('Sales bot', project.id); + await create(editor, { + scope: 'agent', + agentId: support.id, + skill: { ...body, name: 'Mine' }, + }); + await create(editor, { + scope: 'agent', + agentId: sales.id, + skill: { ...body, name: 'Theirs' }, + }); + await create(owner, { scope: 'instance', skill: { ...body, name: 'Shared rules' } }); + await create(editor, { + scope: 'project', + projectId: project.id, + skill: { ...body, name: 'Team rules' }, + }); + + const attachable = await editor + .get('/skills') + .query({ attachableTo: support.id }) + .expect(200); + + expect(attachable.body.data.data.map((s: { name: string }) => s.name).sort()).toEqual([ + 'Mine', + 'Shared rules', + 'Team rules', + ]); + await editor.get('/skills').query({ attachableTo: support.id, scope: 'agent' }).expect(400); + }); + }); + + describe('save', () => { + it('saves changed content as the next version and unchanged content as nothing', async () => { + const { id, skillHash } = await create(editor, { + scope: 'project', + projectId: project.id, + skill: body, + }); + + const saved = await editor + .patch(`/skills/${id}`) + .send({ instructions: 'Be very brief.', baseSkillHash: skillHash }) + .expect(200); + const again = await editor + .patch(`/skills/${id}`) + .send({ instructions: 'Be very brief.', baseSkillHash: saved.body.data.skillHash }) + .expect(200); + const read = await editor.get(`/skills/${id}`).expect(200); + + expect(saved.body.data).toMatchObject({ id, version: 2, created: true }); + expect(saved.body.data.skill.instructions).toBe('Be very brief.'); + expect(again.body.data).toMatchObject({ id, version: 2, created: false }); + expect(read.body.data).toMatchObject({ + latestVersion: 2, + skillHash: saved.body.data.skillHash, + }); + }); + + it('refuses a save based on a stale hash', async () => { + const { id, skillHash } = await create(editor, { + scope: 'project', + projectId: project.id, + skill: body, + }); + await editor + .patch(`/skills/${id}`) + .send({ instructions: 'First.', baseSkillHash: skillHash }); + + await editor + .patch(`/skills/${id}`) + .send({ instructions: 'Second.', baseSkillHash: skillHash }) + .expect(409); + }); + + it('refuses a save without a base hash', async () => { + const { id } = await create(editor, { scope: 'project', projectId: project.id, skill: body }); + + await editor.patch(`/skills/${id}`).send({ instructions: 'Be very brief.' }).expect(400); + }); + + it('refuses blank instructions', async () => { + await create( + editor, + { scope: 'project', projectId: project.id, skill: { ...body, instructions: ' ' } }, + 400, + ); + }); + + it('marks a following agent that was in sync as changed, and leaves a pinned agent alone', async () => { + const { id, skillHash } = await create(editor, { + scope: 'project', + projectId: project.id, + skill: body, + }); + const v1 = (await Container.get(SkillRepository).findLatestSaved([id])).get(id)?.version.id; + const following = await attachToNewAgent(id, 'Follower', project.id, { published: true }); + const pinned = await attachToNewAgent(id, 'Pinned', project.id, { + published: true, + pinnedVersionId: v1, + }); + + const saved = await editor + .patch(`/skills/${id}`) + .send({ instructions: 'Ship weekly.', baseSkillHash: skillHash }) + .expect(200); + + expect(saved.body.data).toMatchObject({ version: 2, created: true }); + expect(await draftVersionOf(following.id)).not.toBe(following.versionId); + expect(await draftVersionOf(pinned.id)).toBe(pinned.versionId); + }); + }); + + // The edit lock is a row lock on Postgres only. SQLite runs one write at a time. + describe.skipIf(process.env.DB_TYPE !== 'postgresdb')('parallel saves on Postgres', () => { + it('answers 409 to the second of two saves from the same base', async () => { + const { id, skillHash } = await create(editor, { + scope: 'project', + projectId: project.id, + skill: body, + }); + + const responses = await Promise.all( + ['First.', 'Second.'].map( + async (instructions) => + await editor.patch(`/skills/${id}`).send({ instructions, baseSkillHash: skillHash }), + ), + ); + const read = await editor.get(`/skills/${id}`).expect(200); + + expect(responses.map((response) => response.status).sort()).toEqual([200, 409]); + expect(read.body.data.latestVersion).toBe(2); + }); + }); + + describe('delete', () => { + it('deletes an unused skill', async () => { + const { id } = await create(editor, { scope: 'project', projectId: project.id, skill: body }); + + await editor.delete(`/skills/${id}`).expect(200); + await editor.get(`/skills/${id}`).expect(404); + }); + + it('answers 409 and names the agents that use the skill', async () => { + const { id } = await create(editor, { scope: 'project', projectId: project.id, skill: body }); + await attachToNewAgent(id, 'Support bot', project.id); + + const response = await editor.delete(`/skills/${id}`).expect(409); + + expect(response.body.message).toBe( + 'Skill "Brand voice" is used by Support bot (draft) and cannot be deleted.', + ); + }); + }); + + afterAll(async () => { + await testDb.truncate(['User']); + }); +}); diff --git a/packages/cli/test/integration/auth.api.test.ts b/packages/cli/test/integration/auth.api.test.ts index 1ba6653b330..7232beddf37 100644 --- a/packages/cli/test/integration/auth.api.test.ts +++ b/packages/cli/test/integration/auth.api.test.ts @@ -1,4 +1,4 @@ -import { EventService } from '@n8n/backend-services'; +import { EventService, JwtService } from '@n8n/backend-services'; import { randomValidPassword, testDb } from '@n8n/backend-test-utils'; import type { User } from '@n8n/db'; import { GLOBAL_MEMBER_ROLE, GLOBAL_OWNER_ROLE, UserRepository } from '@n8n/db'; @@ -9,7 +9,6 @@ import config from '@/config'; import { AUTH_COOKIE_NAME } from '@/constants'; import type { RelayEventMap } from '@/events/maps/relay.event-map'; import { MfaService } from '@/mfa/mfa.service'; -import { JwtService } from '@/services/jwt.service'; import { LOGGED_OUT_RESPONSE_BODY } from './shared/constants'; import { createUser, createUserShell } from './shared/db/users'; diff --git a/packages/cli/test/integration/controllers/invitation/invitation.controller.integration.test.ts b/packages/cli/test/integration/controllers/invitation/invitation.controller.integration.test.ts index fb9d10fbcdc..132fb45c3f9 100644 --- a/packages/cli/test/integration/controllers/invitation/invitation.controller.integration.test.ts +++ b/packages/cli/test/integration/controllers/invitation/invitation.controller.integration.test.ts @@ -1,4 +1,4 @@ -import { EventService } from '@n8n/backend-services'; +import { EventService, JwtService } from '@n8n/backend-services'; import { mockInstance, randomEmail, @@ -18,7 +18,6 @@ import { PROJECT_OWNER_ROLE_SLUG } from '@n8n/permissions'; import { Not } from '@n8n/typeorm'; import { ExternalHooks } from '@/external-hooks'; -import { JwtService } from '@/services/jwt.service'; import { PasswordUtility } from '@/services/password.utility'; import { UserManagementMailer } from '@/user-management/email'; diff --git a/packages/cli/test/integration/credentials/credentials.api.ee.test.ts b/packages/cli/test/integration/credentials/credentials.api.ee.test.ts index 5dc7a9ce1ba..e53b53f4074 100644 --- a/packages/cli/test/integration/credentials/credentials.api.ee.test.ts +++ b/packages/cli/test/integration/credentials/credentials.api.ee.test.ts @@ -377,6 +377,102 @@ describe('GET /credentials/for-workflow', () => { expect(response.statusCode).toBe(200); expect(response.body.data).toEqual([]); }); + + test('omits a credential shared directly with the user when forAgent is true', async () => { + const teamProject = await createTeamProject(); + await linkUserToProject(member, teamProject, 'project:editor'); + + const sharedCredential = await saveCredential(randomCredentialPayload(), { user: owner }); + await shareCredentialWithUsers(sharedCredential, [member]); + + const response = await testServer + .authAgentFor(member) + .get('/credentials/for-workflow') + .query({ projectId: teamProject.id, forAgent: 'true' }); + + expect(response.statusCode).toBe(200); + expect(response.body.data).toEqual([]); + }); + + test('offers a credential shared directly with the user when forAgent is false', async () => { + const teamProject = await createTeamProject(); + await linkUserToProject(member, teamProject, 'project:editor'); + + const sharedCredential = await saveCredential(randomCredentialPayload(), { user: owner }); + await shareCredentialWithUsers(sharedCredential, [member]); + + const response = await testServer + .authAgentFor(member) + .get('/credentials/for-workflow') + .query({ projectId: teamProject.id, forAgent: 'false' }); + + expect(response.statusCode).toBe(200); + expect(response.body.data).toHaveLength(1); + expect(response.body.data[0]).toMatchObject({ id: sharedCredential.id }); + }); + + test('keeps the credentials of the project when forAgent is true', async () => { + const teamProject = await createTeamProject(); + await linkUserToProject(member, teamProject, 'project:editor'); + const projectCredential = await saveCredential(randomCredentialPayload(), { + project: teamProject, + }); + + const response = await testServer + .authAgentFor(member) + .get('/credentials/for-workflow') + .query({ projectId: teamProject.id, forAgent: 'true' }); + + expect(response.statusCode).toBe(200); + expect(response.body.data).toHaveLength(1); + expect(response.body.data[0]).toMatchObject({ id: projectCredential.id }); + }); + + test('keeps the credentials of the personal project of the user when forAgent is true', async () => { + const ownCredential = await saveCredential(randomCredentialPayload(), { user: member }); + + const response = await testServer + .authAgentFor(member) + .get('/credentials/for-workflow') + .query({ projectId: memberPersonalProject.id, forAgent: 'true' }); + + expect(response.statusCode).toBe(200); + expect(response.body.data).toContainEqual(expect.objectContaining({ id: ownCredential.id })); + }); + + test('keeps the personal credentials of other users that the owner may use instance-wide when forAgent is true', async () => { + const ownCredential = await saveCredential(randomCredentialPayload(), { user: owner }); + const memberCredential = await saveCredential(randomCredentialPayload(), { user: member }); + + const response = await authOwnerAgent + .get('/credentials/for-workflow') + .query({ projectId: ownerPersonalProject.id, forAgent: 'true' }); + + expect(response.statusCode).toBe(200); + expect(response.body.data).toContainEqual(expect.objectContaining({ id: ownCredential.id })); + expect(response.body.data).toContainEqual( + expect.objectContaining({ id: memberCredential.id }), + ); + }); + }); + + describe('forAgent with N8N_ENV_FEAT_CRED_SHARING disabled', () => { + test('returns the same credentials as without forAgent', async () => { + const teamProject = await createTeamProject(); + await linkUserToProject(member, teamProject, 'project:editor'); + const projectCredential = await saveCredential(randomCredentialPayload(), { + project: teamProject, + }); + + const response = await testServer + .authAgentFor(member) + .get('/credentials/for-workflow') + .query({ projectId: teamProject.id, forAgent: 'true' }); + + expect(response.statusCode).toBe(200); + expect(response.body.data).toHaveLength(1); + expect(response.body.data[0]).toMatchObject({ id: projectCredential.id }); + }); }); describe('for personal projects', () => { diff --git a/packages/cli/test/integration/database/repositories/agent-execution-thread-n8n-chat.repository.test.ts b/packages/cli/test/integration/database/repositories/agent-execution-thread-n8n-chat.repository.test.ts index cb97000c35d..9884bc76da8 100644 --- a/packages/cli/test/integration/database/repositories/agent-execution-thread-n8n-chat.repository.test.ts +++ b/packages/cli/test/integration/database/repositories/agent-execution-thread-n8n-chat.repository.test.ts @@ -42,7 +42,6 @@ describe('AgentExecutionThreadRepository n8n Chat queries', () => { projectId, integrations: [], tools: {}, - skills: {}, } as Partial), ); agentId = agent.id; @@ -145,7 +144,6 @@ describe('AgentExecutionThreadRepository n8n Chat queries', () => { projectId, integrations: {}, tools: {}, - skills: {}, } as Partial), ); const inScope = await createThread({ ownerId: owner.id }); @@ -175,7 +173,6 @@ describe('AgentExecutionThreadRepository n8n Chat queries', () => { personalisation: { icon: 'bot', gradient: { from: '#000000', to: '#FFFFFF' } }, }, tools: null, - skills: null, }); await agentRepo.update({ id: agentId }, { activeVersionId: versionId }); const thread = await createThread({ ownerId: owner.id }); @@ -285,7 +282,6 @@ describe('AgentExecutionThreadRepository n8n Chat queries', () => { projectId, integrations: {}, tools: {}, - skills: {}, } as Partial), ); const thread = await createThread({ ownerId: owner.id, agentId: otherAgent.id }); @@ -325,7 +321,6 @@ describe('AgentExecutionThreadRepository n8n Chat queries', () => { projectId, integrations: [], tools: {}, - skills: {}, } as Partial), ); const lightThread = await createThread({ ownerId: owner.id }); @@ -388,7 +383,6 @@ describe('AgentExecutionThreadRepository n8n Chat queries', () => { projectId: otherProject.id, integrations: {}, tools: {}, - skills: {}, } as Partial), ); const inScope = await createThread({ ownerId: owner.id }); diff --git a/packages/cli/test/integration/database/repositories/agent-execution.repository.test.ts b/packages/cli/test/integration/database/repositories/agent-execution.repository.test.ts index 303dacb67da..02af9ba9316 100644 --- a/packages/cli/test/integration/database/repositories/agent-execution.repository.test.ts +++ b/packages/cli/test/integration/database/repositories/agent-execution.repository.test.ts @@ -141,7 +141,6 @@ describe('AgentExecutionRepository', () => { projectId, integrations: [], tools: {}, - skills: {}, } as Partial); await agentRepo.save(agent); agentId = agent.id; @@ -1048,7 +1047,6 @@ describe('AgentExecutionRepository', () => { projectId, integrations: [], tools: {}, - skills: {}, }), ); const childThread = await createThread({ @@ -3674,7 +3672,6 @@ describe('AgentExecutionRepository', () => { projectId, integrations: [], tools: {}, - skills: {}, }), ); const { executionService, txRunner } = recordingServices(); diff --git a/packages/cli/test/integration/database/repositories/agent.repository.test.ts b/packages/cli/test/integration/database/repositories/agent.repository.test.ts index 81f4fea4d19..f1bfc2f2de4 100644 --- a/packages/cli/test/integration/database/repositories/agent.repository.test.ts +++ b/packages/cli/test/integration/database/repositories/agent.repository.test.ts @@ -7,6 +7,7 @@ import { ConflictError } from '@n8n/errors'; import { v4 as uuid } from 'uuid'; import { mock } from 'vitest-mock-extended'; +import { setSkillsHubFlag } from '@/modules/agents/__tests__/test-utils/skills-hub-flag'; import type { CredentialsService } from '@/credentials/credentials.service'; import { AgentConfigPreparationService } from '@/modules/agents/agent-config-preparation.service'; import { AgentConfigService } from '@/modules/agents/agent-config.service'; @@ -14,11 +15,11 @@ import { AgentDefinitionService } from '@/modules/agents/agent-definition.servic import type { AgentPolicyService } from '@/modules/agents/agent-policy.service'; import type { AgentSaveCompletionService } from '@/modules/agents/agent-save-completion.service'; import type { AgentSetupCompletionService } from '@/modules/agents/agent-setup-completion.service'; -import type { AgentSkillsService } from '@/modules/agents/agent-skills.service'; import { AgentTaskService } from '@/modules/agents/agent-task.service'; import type { Agent } from '@/modules/agents/entities/agent.entity'; import type { NodeToolAiGatewayService } from '@/modules/agents/json-config/node-tool-ai-gateway.service'; import { AgentHistoryRepository } from '@/modules/agents/repositories/agent-history.repository'; +import { SkillRepository } from '@/modules/agents/repositories/skill.repository'; import { AgentTaskRepository } from '@/modules/agents/repositories/agent-task.repository'; import { AgentRepository } from '@/modules/agents/repositories/agent.repository'; import { getAgentConfigHash } from '@/modules/agents/utils/agent-config-hash'; @@ -48,7 +49,6 @@ describe('AgentRepository', () => { schema: { name: 'Test Agent', model: 'm', instructions: 'i' }, integrations: [], tools: {}, - skills: {}, versionId: 'version-1', activeVersionId: null, ...overrides, @@ -63,7 +63,6 @@ describe('AgentRepository', () => { author: 'test', schema: null, tools: null, - skills: null, }); } @@ -83,6 +82,8 @@ describe('AgentRepository', () => { }); afterEach(async () => { + // The rollout keeps the flag it read, so set it back off for the next test. + await setSkillsHubFlag(false); vi.restoreAllMocks(); await agentHistoryRepo.delete({}); await agentRepo.delete({}); @@ -179,7 +180,6 @@ describe('AgentRepository', () => { mockLogger(), agentRepo, taskRepo, - mock(), new AgentConfigPreparationService( credentials, mock(), @@ -221,7 +221,23 @@ describe('AgentRepository', () => { }); it('replaces the complete draft and preserves existing task creation times', async () => { + await setSkillsHubFlag(true); const agent = await createAgent(); + await Container.get(SkillRepository).createSkill( + { + id: 'writing', + target: { projectId, agentId: null }, + source: 'ui', + createdById: null, + }, + { + name: 'Writing', + description: 'Write notes', + instructions: 'Use short sentences', + frontmatter: null, + files: [], + }, + ); const createdAt = new Date('2025-01-01T00:00:00.000Z'); await taskRepo.insert([ { id: 'task-keep', agentId: agent.id, ...taskBody, createdAt }, @@ -268,15 +284,19 @@ describe('AgentRepository', () => { }; const restore = async () => await definitionService.replaceDraft(agent, definition); expect(await restore()).toBe(true); - expect(await agentRepo.findById(agent.id)).toMatchObject({ + const { skills: skillRefs, ...storedConfig } = definition.schema!; + const stored = await agentRepo.findById(agent.id); + expect(stored).toMatchObject({ name: 'Restored agent', - schema: definition.schema, + schema: storedConfig, tools: definition.tools, - skills: definition.skills, revision: 1, - // The skill refs write keeps the time of the fenced save. updatedAt: agent.updatedAt, }); + expect(stored?.schema).not.toHaveProperty('skills'); + // The skill refs live in the dependency rows. The skill body stays in the hub. + const agentSkillRefs = Container.get(AgentSkillRefsService); + await expect(agentSkillRefs.refsForDraft(agent, {})).resolves.toEqual(skillRefs); const tasks = await taskRepo.findByAgentId(agent.id); expect(tasks).toHaveLength(2); expect(tasks).toEqual( @@ -315,7 +335,7 @@ describe('AgentRepository', () => { await definitionService.replaceDraft(agent, { schema: agent.schema ? toAgentDocument(agent.schema, storedSkillRefs(agent)) : null, tools: agent.tools, - skills: agent.skills, + skills: {}, tasks: new Map([['task-1', { ...taskBody, objective: 'Restored objective' }]]), }); return task; @@ -397,7 +417,6 @@ describe('AgentRepository', () => { name: original.name, schema: original.schema, tools: original.tools, - skills: original.skills, revision: original.revision, }); expect(await taskRepo.findByAgentId(agent.id)).toMatchObject([{ id: 'own-task' }]); @@ -417,7 +436,7 @@ describe('AgentRepository', () => { // Setup validation reads pending edits against their stored base revision. agent.schema = { name: 'Pending edit', model: '', instructions: 'Pending instructions' }; await expect(definitionService.readDraft(agent)).resolves.toEqual({ - schema: agent.schema, + schema: { ...agent.schema, skills: [] }, tools: {}, skills: {}, tasks: new Map([['task-1', taskBody]]), @@ -459,7 +478,6 @@ describe('AgentRepository', () => { ? { ...agent.schema, integrations: [{ type: 'n8n_chat', credentialId: '' }] } : null, tools: {}, - skills: {}, publishedBy: 'test', }); await agentRepo.update({ id: agent.id }, { activeVersionId: firstVersion }); @@ -473,7 +491,6 @@ describe('AgentRepository', () => { agentId: agent.id, schema: agent.schema, tools: {}, - skills: {}, publishedBy: 'test', }); await agentRepo.update({ id: agent.id }, { activeVersionId: secondVersion }); @@ -630,7 +647,6 @@ describe('AgentRepository', () => { agentId: agent.id, schema: agent.schema, tools: null, - skills: null, publishedBy: 'Someone Else', }); await agentRepo.update({ id: agent.id }, { activeVersionId: 'version-1' }); @@ -861,7 +877,6 @@ describe('AgentRepository', () => { author: 'test', schema: storedAgentConfig(publishedSchema(snapshotIntegrations)), tools: null, - skills: null, }); await agentRepo.update({ id: agent.id }, { activeVersionId: versionId }); return (await agentRepo.findById(agent.id)) as Agent; @@ -1034,7 +1049,6 @@ describe('AgentRepository', () => { integrations: snapshotIntegrations, }, tools: null, - skills: null, }); await agentRepo.update({ id: agent.id }, { activeVersionId: versionId }); return (await agentRepo.findById(agent.id)) as Agent; diff --git a/packages/cli/test/integration/dynamic-credentials.ee/dynamic-credentials.auth.api.test.ts b/packages/cli/test/integration/dynamic-credentials.ee/dynamic-credentials.auth.api.test.ts index 573327a2e92..0b1dadb8605 100644 --- a/packages/cli/test/integration/dynamic-credentials.ee/dynamic-credentials.auth.api.test.ts +++ b/packages/cli/test/integration/dynamic-credentials.ee/dynamic-credentials.auth.api.test.ts @@ -280,6 +280,9 @@ describe('Dynamic Credentials API', () => { }); }); + // `authSource=cookie` makes the caller's own n8n session token the identity the + // resolver is asked to validate. The resolver here keys on an external subject + // (`credential-resolver.oauth2-1.0`), so it must not be handed that identity. describe('when the identity is taken from the session cookie', () => { it('should refuse to authorize against a resolver that does not resolve n8n users', async () => { const response = await testServer diff --git a/packages/cli/test/integration/inbound-auth-core/trusted-source.api.test.ts b/packages/cli/test/integration/inbound-auth-core/trusted-source.api.test.ts new file mode 100644 index 00000000000..8b0d5fb4de8 --- /dev/null +++ b/packages/cli/test/integration/inbound-auth-core/trusted-source.api.test.ts @@ -0,0 +1,625 @@ +import { CacheService, EventService, OAuthDiscoveryClient } from '@n8n/backend-services'; +import { testDb } from '@n8n/backend-test-utils'; +import type { User } from '@n8n/db'; +import { Container } from '@n8n/di'; +import type { TrustedSourceConfigInput } from '@n8n/inbound-auth'; +import { DataSource, type Repository } from '@n8n/typeorm'; +import { CREDENTIAL_BLANKING_VALUE } from 'n8n-workflow'; +import type { MockInstance } from 'vitest'; +import { mock } from 'vitest-mock-extended'; + +import { TrustedSourceIdentityEntity } from '@/modules/inbound-auth-core/database/entities/trusted-source-identity.entity'; +import { TrustedSourceEntity } from '@/modules/inbound-auth-core/database/entities/trusted-source.entity'; +import { TrustedSourceDbStore } from '@/modules/inbound-auth-core/trusted-source.store'; +import { createAdmin, createMember, createOwner } from '@test-integration/db/users'; +import type { SuperAgentTest } from '@test-integration/types'; +import * as utils from '@test-integration/utils'; + +const LICENSE = 'feat:trustedSourceManage'; +const SYSTEM_ID = 'n8n-internal'; +const ISSUER = 'https://acme.example.com'; +const JWKS_URI = `${ISSUER}/.well-known/jwks.json`; +const RSA_KEY = { kid: 'k1', kty: 'RSA', use: 'sig', alg: 'RS256', n: 'AQAB', e: 'AQAB' } as const; + +// The check route runs discovery through the injected client; no network in tests. +const discoveryClient = mock(); +Container.set(OAuthDiscoveryClient, discoveryClient); + +const testServer = utils.setupTestServer({ + endpointGroups: ['trusted-sources'], + modules: ['inbound-auth-core'], + enabledFeatures: [LICENSE], +}); + +let owner: User; +let admin: User; +let member: User; +let ownerAgent: SuperAgentTest; +let adminAgent: SuperAgentTest; +let memberAgent: SuperAgentTest; +let store: TrustedSourceDbStore; +let cacheService: CacheService; +let rows: Repository; +let bindings: Repository; +let emit: MockInstance; + +const minimalConfig = (): TrustedSourceConfigInput => ({ + version: 1, + authentication: { type: 'oauth2' }, + surfaces: { 'public-api': {} }, +}); + +const withClient = (clientSecret?: string): TrustedSourceConfigInput => ({ + ...minimalConfig(), + authentication: { + type: 'oauth2', + client: { kind: 'registered', clientId: 'n8n', ...(clientSecret && { clientSecret }) }, + }, +}); + +const body = (overrides: Record = {}) => ({ + name: 'Acme', + issuer: ISSUER, + config: minimalConfig(), + ...overrides, +}); + +async function createSource(overrides: Record = {}): Promise<{ id: string }> { + const response = await ownerAgent.post('/trusted-sources').send(body(overrides)); + expect(response.statusCode).toBe(200); + return response.body.data; +} + +async function bind(sourceId: string, subject: string) { + await bindings.save( + bindings.create({ + sourceId, + subject, + userId: member.id, + provenance: 'admin', + status: 'active', + lastSeenAt: null, + }), + ); +} + +async function storedClient(id: string) { + await cacheService.reset(); + const source = await store.getById(id); + return source?.config.authentication.client; +} + +beforeAll(async () => { + owner = await createOwner(); + admin = await createAdmin(); + member = await createMember(); + ownerAgent = testServer.authAgentFor(owner); + adminAgent = testServer.authAgentFor(admin); + memberAgent = testServer.authAgentFor(member); + + store = Container.get(TrustedSourceDbStore); + cacheService = Container.get(CacheService); + rows = Container.get(DataSource).getRepository(TrustedSourceEntity); + bindings = Container.get(DataSource).getRepository(TrustedSourceIdentityEntity); +}); + +beforeEach(async () => { + // Module init seeded the system row once; only admin rows are per-test state. + await testDb.truncate(['TrustedSourceIdentityEntity']); + await rows.delete({ managedBy: 'admin' }); + await cacheService.reset(); + // The shared vitest config restores spies after every test, so the spy is per test. + emit = vi.spyOn(Container.get(EventService), 'emit'); + discoveryClient.fetchOpenIdConfiguration.mockReset(); + discoveryClient.fetchOAuth2ServerMetadata.mockReset(); + discoveryClient.fetchJwks.mockReset(); +}); + +describe('POST /trusted-sources', () => { + it('creates an admin source with defaults applied and returns it without the secret', async () => { + const response = await ownerAgent + .post('/trusted-sources') + .send(body({ config: withClient('s3cret') })); + + expect(response.statusCode).toBe(200); + expect(response.body.data).toMatchObject({ + name: 'Acme', + issuer: ISSUER, + type: 'oauth2', + managedBy: 'admin', + status: 'unchecked', + lastError: null, + lastCheckedAt: null, + config: { + version: 1, + authentication: { + type: 'oauth2', + clockSkewSeconds: 60, + client: { kind: 'registered', clientId: 'n8n', clientSecret: CREDENTIAL_BLANKING_VALUE }, + }, + identity: { subject: 'binding' }, + }, + }); + expect(JSON.stringify(response.body)).not.toContain('s3cret'); + + const row = await rows.findOneByOrFail({ id: response.body.data.id }); + expect(row).toMatchObject({ managedBy: 'admin', status: 'unchecked', configVersion: 1 }); + expect(await storedClient(row.id)).toEqual({ + kind: 'registered', + clientId: 'n8n', + clientSecret: 's3cret', + }); + }); + + it('lets an admin create a source', async () => { + const response = await adminAgent.post('/trusted-sources').send(body()); + + expect(response.statusCode).toBe(200); + expect(response.body.data.managedBy).toBe('admin'); + }); + + it.each<[string, Record, string[], RegExp]>([ + [ + 'a system-only setting', + { config: { ...minimalConfig(), identity: { subject: 'n8n-user-id' } } }, + ['config', 'identity', 'subject'], + /only allowed on system-managed sources/, + ], + [ + 'a value outside the schema bounds', + { config: { ...minimalConfig(), authentication: { type: 'oauth2', clockSkewSeconds: 999 } } }, + ['config', 'authentication', 'clockSkewSeconds'], + /300/, + ], + ['an issuer that is not a URL', { issuer: 'acme' }, ['issuer'], /url/i], + ['an http issuer', { issuer: 'http://acme.example.com' }, ['issuer'], /https/], + [ + 'an unknown config key', + { config: { ...minimalConfig(), identity: { typo: true } } }, + ['config', 'identity'], + /typo/, + ], + ])( + 'refuses %s with the offending path and writes nothing', + async (_, overrides, path, message) => { + const response = await ownerAgent.post('/trusted-sources').send(body(overrides)); + + expect(response.statusCode).toBe(400); + expect(response.body).toMatchObject({ path, message: expect.stringMatching(message) }); + expect(await rows.countBy({ managedBy: 'admin' })).toBe(0); + }, + ); + + it('refuses the blanking value as a secret and writes nothing', async () => { + const response = await ownerAgent + .post('/trusted-sources') + .send(body({ config: withClient(CREDENTIAL_BLANKING_VALUE) })); + + expect(response.statusCode).toBe(400); + expect(response.body.message).toMatch(/blanking value/); + expect(await rows.countBy({ managedBy: 'admin' })).toBe(0); + }); + + it('answers 409 when the name or the issuer is taken', async () => { + await createSource(); + + const sameName = await ownerAgent + .post('/trusted-sources') + .send(body({ issuer: 'https://other.example.com' })); + const sameIssuer = await ownerAgent.post('/trusted-sources').send(body({ name: 'Other' })); + + expect(sameName.statusCode).toBe(409); + expect(sameIssuer.statusCode).toBe(409); + expect(await rows.countBy({ managedBy: 'admin' })).toBe(1); + }); + + it('emits trusted-source-created with the actor and the source', async () => { + const { id } = await createSource(); + + expect(emit).toHaveBeenCalledWith('trusted-source-created', { + user: expect.objectContaining({ id: owner.id }), + sourceId: id, + issuer: ISSUER, + }); + }); + + it('answers 403 for a member', async () => { + const response = await memberAgent.post('/trusted-sources').send(body()); + + expect(response.statusCode).toBe(403); + expect(await rows.countBy({ managedBy: 'admin' })).toBe(0); + }); + + it('answers 403 without the license', async () => { + testServer.license.disable(LICENSE); + + const response = await ownerAgent.post('/trusted-sources').send(body()); + + expect(response.statusCode).toBe(403); + expect(response.body.message).toBe('Plan lacks license for this feature'); + expect(await rows.countBy({ managedBy: 'admin' })).toBe(0); + }); +}); + +describe('GET /trusted-sources', () => { + it('lists the seeded source and admin sources as summaries for an owner', async () => { + const { id } = await createSource({ + config: { + ...minimalConfig(), + authentication: { type: 'oauth2', discovery: { mode: 'manual', jwksUri: JWKS_URI } }, + surfaces: { 'public-api': {}, trigger: {} }, + }, + }); + + const response = await ownerAgent.get('/trusted-sources'); + + expect(response.statusCode).toBe(200); + const list: Record[] = response.body.data; + expect(list.map((entry) => entry.id).sort()).toEqual([id, SYSTEM_ID].sort()); + for (const entry of list) { + expect(Object.keys(entry).sort()).toEqual(['capabilities', 'id', 'name', 'surfaces']); + } + expect(list.find((entry) => entry.id === id)).toEqual({ + id, + name: 'Acme', + capabilities: ['verify-jwt'], + surfaces: ['public-api', 'trigger'], + }); + }); + + it('lists the same summaries for a member', async () => { + const { id } = await createSource(); + + const response = await memberAgent.get('/trusted-sources'); + + expect(response.statusCode).toBe(200); + expect(response.body.data).toContainEqual({ + id, + name: 'Acme', + capabilities: [], + surfaces: ['public-api'], + }); + expect(JSON.stringify(response.body)).not.toContain(ISSUER); + }); + + it('lists without the license', async () => { + testServer.license.disable(LICENSE); + + const response = await ownerAgent.get('/trusted-sources'); + + expect(response.statusCode).toBe(200); + }); +}); + +describe('GET /trusted-sources/:id', () => { + it('returns the full source with the secret blanked for an owner', async () => { + const { id } = await createSource({ config: withClient('s3cret') }); + + const response = await ownerAgent.get(`/trusted-sources/${id}`); + + expect(response.statusCode).toBe(200); + expect(response.body.data).toMatchObject({ + id, + name: 'Acme', + issuer: ISSUER, + managedBy: 'admin', + status: 'unchecked', + config: { + authentication: { + client: { kind: 'registered', clientId: 'n8n', clientSecret: CREDENTIAL_BLANKING_VALUE }, + }, + }, + metadata: null, + }); + expect(JSON.stringify(response.body)).not.toContain('s3cret'); + }); + + it('returns the seeded system source', async () => { + const response = await ownerAgent.get(`/trusted-sources/${SYSTEM_ID}`); + + expect(response.statusCode).toBe(200); + expect(response.body.data).toMatchObject({ id: SYSTEM_ID, managedBy: 'system' }); + }); + + it('answers 403 for a member', async () => { + const { id } = await createSource(); + + const response = await memberAgent.get(`/trusted-sources/${id}`); + + expect(response.statusCode).toBe(403); + }); + + it('answers 404 for an unknown id', async () => { + const response = await ownerAgent.get('/trusted-sources/missing'); + + expect(response.statusCode).toBe(404); + }); +}); + +describe('PATCH /trusted-sources/:id', () => { + it('renames a source, keeps its bindings and emits trusted-source-updated', async () => { + const { id } = await createSource(); + await bind(id, 'alice'); + + const response = await ownerAgent.patch(`/trusted-sources/${id}`).send({ name: 'Renamed' }); + + expect(response.statusCode).toBe(200); + expect(response.body.data).toMatchObject({ id, name: 'Renamed', issuer: ISSUER }); + expect((await rows.findOneByOrFail({ id })).name).toBe('Renamed'); + expect(await bindings.countBy({ sourceId: id })).toBe(1); + expect(emit).toHaveBeenCalledWith('trusted-source-updated', { + user: expect.objectContaining({ id: owner.id }), + sourceId: id, + issuer: ISSUER, + }); + }); + + it('answers an empty body with the current source, writes nothing and emits nothing', async () => { + const { id } = await createSource(); + const update = vi.spyOn(store, 'update'); + + const response = await ownerAgent.patch(`/trusted-sources/${id}`).send({}); + + expect(response.statusCode).toBe(200); + expect(response.body.data).toMatchObject({ id, name: 'Acme', issuer: ISSUER }); + expect(update).not.toHaveBeenCalled(); + expect(emit).not.toHaveBeenCalledWith('trusted-source-updated', expect.anything()); + }); + + it('keeps the stored secret when the config carries the blanking value', async () => { + const { id } = await createSource({ config: withClient('s3cret') }); + + const response = await ownerAgent + .patch(`/trusted-sources/${id}`) + .send({ config: withClient(CREDENTIAL_BLANKING_VALUE) }); + + expect(response.statusCode).toBe(200); + expect(response.body.data.config.authentication.client.clientSecret).toBe( + CREDENTIAL_BLANKING_VALUE, + ); + expect(await storedClient(id)).toMatchObject({ clientSecret: 's3cret' }); + }); + + it('replaces the secret when the config carries a new value', async () => { + const { id } = await createSource({ config: withClient('s3cret') }); + + const response = await ownerAgent + .patch(`/trusted-sources/${id}`) + .send({ config: withClient('n3w') }); + + expect(response.statusCode).toBe(200); + expect(await storedClient(id)).toMatchObject({ clientSecret: 'n3w' }); + }); + + it('clears the secret when the config omits it', async () => { + const { id } = await createSource({ config: withClient('s3cret') }); + + const response = await ownerAgent + .patch(`/trusted-sources/${id}`) + .send({ config: withClient() }); + + expect(response.statusCode).toBe(200); + expect(await storedClient(id)).toEqual({ kind: 'registered', clientId: 'n8n' }); + }); + + it('moves the issuer and drops bindings only when clearBindings is set', async () => { + const { id } = await createSource(); + await bind(id, 'alice'); + await bind(id, 'bob'); + + const kept = await ownerAgent + .patch(`/trusted-sources/${id}`) + .send({ issuer: 'https://moved.example.com' }); + expect(kept.statusCode).toBe(200); + expect(await bindings.countBy({ sourceId: id })).toBe(2); + + const cleared = await ownerAgent + .patch(`/trusted-sources/${id}`) + .send({ issuer: 'https://moved-again.example.com', clearBindings: true }); + expect(cleared.statusCode).toBe(200); + expect(cleared.body.data).toMatchObject({ + issuer: 'https://moved-again.example.com', + status: 'unchecked', + }); + expect(await bindings.countBy({ sourceId: id })).toBe(0); + expect(await store.getByIssuer(ISSUER)).toBeUndefined(); + expect(await store.getByIssuer('https://moved-again.example.com')).toMatchObject({ id }); + }); + + it('refuses an admin-only setting without touching the row', async () => { + const { id } = await createSource(); + + const response = await ownerAgent.patch(`/trusted-sources/${id}`).send({ + config: { + ...minimalConfig(), + authentication: { type: 'oauth2', keys: { kind: 'local-keystore' } }, + }, + }); + + expect(response.statusCode).toBe(400); + expect(response.body).toMatchObject({ + path: ['config', 'authentication', 'keys', 'kind'], + message: expect.stringMatching(/only allowed on system-managed sources/), + }); + expect((await rows.findOneByOrFail({ id })).name).toBe('Acme'); + }); + + it('answers 409 when the new issuer is taken', async () => { + const { id } = await createSource(); + await createSource({ name: 'Other', issuer: 'https://other.example.com' }); + + const response = await ownerAgent + .patch(`/trusted-sources/${id}`) + .send({ issuer: 'https://other.example.com' }); + + expect(response.statusCode).toBe(409); + }); + + it('refuses the system source', async () => { + const response = await ownerAgent.patch(`/trusted-sources/${SYSTEM_ID}`).send({ name: 'x' }); + + expect(response.statusCode).toBe(400); + expect(response.body.message).toMatch(/system-managed/); + expect((await rows.findOneByOrFail({ id: SYSTEM_ID })).name).not.toBe('x'); + expect(emit).not.toHaveBeenCalledWith('trusted-source-updated', expect.anything()); + }); + + it('answers 404 for an unknown id', async () => { + const response = await ownerAgent.patch('/trusted-sources/missing').send({ name: 'x' }); + + expect(response.statusCode).toBe(404); + }); + + it('answers 403 for a member', async () => { + const { id } = await createSource(); + + const response = await memberAgent.patch(`/trusted-sources/${id}`).send({ name: 'x' }); + + expect(response.statusCode).toBe(403); + expect((await rows.findOneByOrFail({ id })).name).toBe('Acme'); + }); + + it('answers 403 without the license', async () => { + const { id } = await createSource(); + testServer.license.disable(LICENSE); + + const response = await ownerAgent.patch(`/trusted-sources/${id}`).send({ name: 'x' }); + + expect(response.statusCode).toBe(403); + expect(response.body.message).toBe('Plan lacks license for this feature'); + expect((await rows.findOneByOrFail({ id })).name).toBe('Acme'); + }); +}); + +describe('DELETE /trusted-sources/:id', () => { + it('deletes the source with its bindings, evicts the cache and emits trusted-source-deleted', async () => { + const { id } = await createSource(); + await bind(id, 'alice'); + // Prime both cache keys, so the test fails if delete stops evicting them. + expect(await store.getById(id)).toBeDefined(); + expect(await store.getByIssuer(ISSUER)).toBeDefined(); + + const response = await ownerAgent.delete(`/trusted-sources/${id}`); + + expect(response.statusCode).toBe(200); + expect(await rows.findOneBy({ id })).toBeNull(); + expect(await bindings.countBy({ sourceId: id })).toBe(0); + expect(await store.getById(id)).toBeUndefined(); + expect(await store.getByIssuer(ISSUER)).toBeUndefined(); + expect(emit).toHaveBeenCalledWith('trusted-source-deleted', { + user: expect.objectContaining({ id: owner.id }), + sourceId: id, + issuer: ISSUER, + }); + }); + + it('works without the license', async () => { + const { id } = await createSource(); + testServer.license.disable(LICENSE); + + const response = await ownerAgent.delete(`/trusted-sources/${id}`); + + expect(response.statusCode).toBe(200); + expect(await rows.findOneBy({ id })).toBeNull(); + }); + + it('refuses the system source', async () => { + const response = await ownerAgent.delete(`/trusted-sources/${SYSTEM_ID}`); + + expect(response.statusCode).toBe(400); + expect(response.body.message).toMatch(/system-managed/); + expect(await rows.findOneBy({ id: SYSTEM_ID })).not.toBeNull(); + expect(emit).not.toHaveBeenCalledWith('trusted-source-deleted', expect.anything()); + }); + + it('answers 404 for an unknown id', async () => { + const response = await ownerAgent.delete('/trusted-sources/missing'); + + expect(response.statusCode).toBe(404); + }); + + it('answers 403 for a member', async () => { + const { id } = await createSource(); + + const response = await memberAgent.delete(`/trusted-sources/${id}`); + + expect(response.statusCode).toBe(403); + expect(await rows.findOneBy({ id })).not.toBeNull(); + }); +}); + +describe('POST /trusted-sources/:id/check', () => { + it('marks a reachable issuer healthy and returns the checked source', async () => { + discoveryClient.fetchOpenIdConfiguration.mockResolvedValue({ + document: { issuer: ISSUER, jwks_uri: JWKS_URI }, + ttlSeconds: 3600, + }); + discoveryClient.fetchOAuth2ServerMetadata.mockResolvedValue(undefined); + discoveryClient.fetchJwks.mockResolvedValue({ keys: [RSA_KEY], skipped: [], ttlSeconds: 3600 }); + const { id } = await createSource(); + + const response = await ownerAgent.post(`/trusted-sources/${id}/check`); + + expect(response.statusCode).toBe(200); + expect(response.body.data).toMatchObject({ + id, + status: 'healthy', + lastError: null, + lastCheckedAt: expect.any(String), + metadata: { version: 1 }, + }); + expect((await rows.findOneByOrFail({ id })).status).toBe('healthy'); + // Discovered keys make the source usable, which the summary shows as a capability. + const list = await ownerAgent.get('/trusted-sources'); + expect(list.body.data).toContainEqual( + expect.objectContaining({ id, capabilities: ['verify-jwt'] }), + ); + }); + + it('records an error when the metadata names another issuer', async () => { + const mismatch = new Error( + `Metadata from "${ISSUER}/.well-known/openid-configuration" names issuer "https://other.example.com", expected "${ISSUER}"`, + ); + discoveryClient.fetchOpenIdConfiguration.mockRejectedValue(mismatch); + discoveryClient.fetchOAuth2ServerMetadata.mockRejectedValue(mismatch); + const { id } = await createSource(); + + const response = await ownerAgent.post(`/trusted-sources/${id}/check`); + + expect(response.statusCode).toBe(200); + expect(response.body.data).toMatchObject({ + id, + status: 'error', + lastError: expect.stringContaining('names issuer "https://other.example.com"'), + lastCheckedAt: expect.any(String), + }); + expect((await rows.findOneByOrFail({ id })).status).toBe('error'); + }); + + it('works without the license', async () => { + discoveryClient.fetchOpenIdConfiguration.mockRejectedValue(new Error('down')); + discoveryClient.fetchOAuth2ServerMetadata.mockRejectedValue(new Error('down')); + const { id } = await createSource(); + testServer.license.disable(LICENSE); + + const response = await ownerAgent.post(`/trusted-sources/${id}/check`); + + expect(response.statusCode).toBe(200); + expect(response.body.data.status).toBe('error'); + }); + + it('answers 404 for an unknown id', async () => { + const response = await ownerAgent.post('/trusted-sources/missing/check'); + + expect(response.statusCode).toBe(404); + }); + + it('answers 403 for a member', async () => { + const { id } = await createSource(); + + const response = await memberAgent.post(`/trusted-sources/${id}/check`); + + expect(response.statusCode).toBe(403); + expect((await rows.findOneByOrFail({ id })).status).toBe('unchecked'); + }); +}); diff --git a/packages/cli/test/integration/oidc/oidc.service.ee.test.ts b/packages/cli/test/integration/oidc/oidc.service.ee.test.ts index 3002b9d060b..7de28979dfa 100644 --- a/packages/cli/test/integration/oidc/oidc.service.ee.test.ts +++ b/packages/cli/test/integration/oidc/oidc.service.ee.test.ts @@ -28,7 +28,7 @@ import { License } from '@/license'; import { ProvisioningService } from '@/modules/provisioning.ee/provisioning.service.ee'; import { OIDC_CLIENT_SECRET_REDACTED_VALUE } from '@/modules/sso-oidc/constants'; import { OidcService } from '@/modules/sso-oidc/oidc.service.ee'; -import { JwtService } from '@/services/jwt.service'; +import { JwtService } from '@n8n/backend-services'; import { createCustomRoleWithScopes, createScope } from '@test-integration/db/roles'; import { createUser } from '@test-integration/db/users'; diff --git a/packages/cli/test/integration/password-reset.api.test.ts b/packages/cli/test/integration/password-reset.api.test.ts index 1788398513e..1afb0bb0e81 100644 --- a/packages/cli/test/integration/password-reset.api.test.ts +++ b/packages/cli/test/integration/password-reset.api.test.ts @@ -18,7 +18,7 @@ import { AuthService } from '@/auth/auth.service'; import config from '@/config'; import { ExternalHooks } from '@/external-hooks'; import { License } from '@/license'; -import { JwtService } from '@/services/jwt.service'; +import { JwtService } from '@n8n/backend-services'; import { PasswordUtility } from '@/services/password.utility'; import { setCurrentAuthenticationMethod } from '@/sso.ee/sso-helpers'; import { UserManagementMailer } from '@/user-management/email'; diff --git a/packages/cli/test/integration/policy/credential-type-policy-instance.controller.test.ts b/packages/cli/test/integration/policy/credential-type-policy-instance.controller.test.ts index c1c061a4afa..a4bc3e4ab4f 100644 --- a/packages/cli/test/integration/policy/credential-type-policy-instance.controller.test.ts +++ b/packages/cli/test/integration/policy/credential-type-policy-instance.controller.test.ts @@ -244,7 +244,10 @@ describe('credential type availability policy instance controller admin happy pa const response = await testServer .authAgentFor(owner) .put(`/credential-type-policies/scopes/${scopeId}/attachments`) - .send({ attachments: [{ policyId, priority: 0, isFloor: false }] }); + .send({ + attachments: [{ policyId, priority: 0, isFloor: false }], + version: instancePut.body.data.version, + }); expect(response.statusCode).toBe(200); expect(emitSpy).toHaveBeenCalledWith( @@ -269,7 +272,7 @@ describe('credential type availability policy instance controller admin happy pa const response = await testServer .authAgentFor(owner) .put(`/credential-type-policies/scopes/${nodeScopeId}/attachments`) - .send({ attachments: [] }); + .send({ attachments: [], version: nodeInstancePut.body.data.version }); expect(response.statusCode).toBe(404); diff --git a/packages/cli/test/integration/policy/credential-type-policy.credential-save.test.ts b/packages/cli/test/integration/policy/credential-type-policy.credential-save.test.ts index 40c81a9fd97..99d5e38654e 100644 --- a/packages/cli/test/integration/policy/credential-type-policy.credential-save.test.ts +++ b/packages/cli/test/integration/policy/credential-type-policy.credential-save.test.ts @@ -3,7 +3,12 @@ * while a credential that predates the rule stays editable. The lock belongs at decryption, * so the refusal here is about not letting someone set up what can never work. */ -import { createTeamProject, randomCredentialPayload, testDb } from '@n8n/backend-test-utils'; +import { + createTeamProject, + getPersonalProject, + randomCredentialPayload, + testDb, +} from '@n8n/backend-test-utils'; import { LICENSE_FEATURES } from '@n8n/constants'; import { CredentialsRepository, type User } from '@n8n/db'; import { PolicyCheckMetadata } from '@n8n/decorators'; @@ -38,14 +43,21 @@ let credentialsRepository: CredentialsRepository; const denyGithubAtInstanceScope = async () => await putCredentialTypePolicy(ownerAgent, null, { rules: [denyRule('deny-github', BLOCKED)] }); -const violationFor = (credentialType: string, scope: 'instance' | 'project', ruleId: string) => ({ +const violationFor = ( + credentialType: string, + scope: 'instance' | 'project', + ruleId: string, + { projectId, optInAvailable = false }: { projectId?: string; optInAvailable?: boolean } = {}, +) => ({ kind: 'credential-type-unavailable', checkId: CHECK_ID, - message: `Credential type "${credentialType}" is blocked by ${scope === 'instance' ? 'an instance policy' : "this project's policy"}`, + message: `Credential type "${credentialType}" is blocked by ${scope === 'instance' ? 'an instance policy' : 'a project policy'}`, subject: credentialType, subjectType: 'credentialType', scope, matchedRuleId: ruleId, + ...(projectId !== undefined && { projectId }), + optInAvailable, }); beforeAll(async () => { @@ -111,7 +123,7 @@ describe('POST /credentials', () => { .expect(403); expect(response.body.meta.violations).toEqual([ - violationFor(BLOCKED, 'project', 'deny-github'), + violationFor(BLOCKED, 'project', 'deny-github', { projectId: project.id }), ]); await expect(credentialsRepository.count()).resolves.toBe(0); }); @@ -147,8 +159,9 @@ describe('PATCH /credentials/:credentialId', () => { .send({ ...randomCredentialPayload({ type: BLOCKED }), name: credential.name }) .expect(403); + const { id: projectId } = await getPersonalProject(owner); expect(response.body.meta.violations).toEqual([ - violationFor(BLOCKED, 'instance', 'deny-github'), + violationFor(BLOCKED, 'instance', 'deny-github', { projectId }), ]); const stored = await credentialsRepository.findOneBy({ id: credential.id }); diff --git a/packages/cli/test/integration/policy/credential-type-policy.extends.test.ts b/packages/cli/test/integration/policy/credential-type-policy.extends.test.ts index d9967807b16..73a34fd05f1 100644 --- a/packages/cli/test/integration/policy/credential-type-policy.extends.test.ts +++ b/packages/cli/test/integration/policy/credential-type-policy.extends.test.ts @@ -2,7 +2,12 @@ * Pins what an `extends` rule decides for real host paths: a rule on a base credential type * refuses a workflow that asks for a type built on it, exactly as a rule on that type would. */ -import { createWorkflow, randomCredentialPayload, testDb } from '@n8n/backend-test-utils'; +import { + createWorkflow, + getPersonalProject, + randomCredentialPayload, + testDb, +} from '@n8n/backend-test-utils'; import type { PolicyRule } from '@n8n/api-types'; import { LICENSE_FEATURES } from '@n8n/constants'; import { ExecutionRepository, WorkflowRepository, type User } from '@n8n/db'; @@ -65,7 +70,7 @@ const workflowBody = () => ({ connections: {}, }); -const derivedViolation = { +const derivedViolation = (projectId: string) => ({ kind: 'credential-type-unavailable', checkId: 'credential-type-availability', message: `Credential type "${DERIVED}" is blocked by an instance policy`, @@ -73,7 +78,9 @@ const derivedViolation = { subjectType: 'credentialType', scope: 'instance', matchedRuleId: 'deny-oauth2-family', -}; + projectId, + optInAvailable: false, +}); beforeAll(async () => { await utils.initNodeTypes(); @@ -120,7 +127,8 @@ describe('a rule on a base credential type', () => { const response = await ownerAgent.post('/workflows').send(workflowBody()).expect(403); - expect(response.body.meta.violations).toEqual([derivedViolation]); + const { id: projectId } = await getPersonalProject(owner); + expect(response.body.meta.violations).toEqual([derivedViolation(projectId)]); await expect(workflowRepository.count()).resolves.toBe(0); }); @@ -150,7 +158,8 @@ describe('a rule on a base credential type', () => { }); const error = stored?.data.resultData.error as unknown as { violations?: unknown[] }; - expect(error?.violations).toEqual([derivedViolation]); + const { id: projectId } = await getPersonalProject(owner); + expect(error?.violations).toEqual([derivedViolation(projectId)]); }); test('lets an earlier allow for the derived type win over the family deny', async () => { diff --git a/packages/cli/test/integration/policy/credential-type-policy.workflow.test.ts b/packages/cli/test/integration/policy/credential-type-policy.workflow.test.ts index 37f3c0b0f3c..46a9e0b1c7f 100644 --- a/packages/cli/test/integration/policy/credential-type-policy.workflow.test.ts +++ b/packages/cli/test/integration/policy/credential-type-policy.workflow.test.ts @@ -10,6 +10,7 @@ import { createTeamProject, createWorkflow, createWorkflowWithHistory, + getPersonalProject, randomCredentialPayload, testDb, } from '@n8n/backend-test-utils'; @@ -103,14 +104,17 @@ const violationFor = ( credentialType: string, scope: 'instance' | 'project', matchedRuleId: string, + { projectId, optInAvailable = false }: { projectId?: string; optInAvailable?: boolean } = {}, ) => ({ kind: 'credential-type-unavailable', checkId: CHECK_ID, - message: `Credential type "${credentialType}" is blocked by ${scope === 'instance' ? 'an instance policy' : "this project's policy"}`, + message: `Credential type "${credentialType}" is blocked by ${scope === 'instance' ? 'an instance policy' : 'a project policy'}`, subject: credentialType, subjectType: 'credentialType', scope, matchedRuleId, + ...(projectId !== undefined && { projectId }), + optInAvailable, }); type CredentialOwner = Parameters[1]; @@ -248,8 +252,9 @@ describe('saving a workflow', () => { }) .expect(403); + const { id: projectId } = await getPersonalProject(owner); expect(response.body.meta.violations).toEqual([ - violationFor(BLOCKED, 'instance', 'deny-github'), + violationFor(BLOCKED, 'instance', 'deny-github', { projectId }), ]); await expect(workflowRepository.count()).resolves.toBe(0); }); @@ -286,8 +291,9 @@ describe('saving a workflow', () => { .send({ name: 'New workflow', nodes: [node(MANUAL_TRIGGER), inlineAgent], connections: {} }) .expect(403); + const { id: projectId } = await getPersonalProject(owner); expect(response.body.meta.violations).toEqual([ - violationFor(BLOCKED, 'instance', 'deny-github'), + violationFor(BLOCKED, 'instance', 'deny-github', { projectId }), ]); await expect(workflowRepository.count()).resolves.toBe(0); }); @@ -387,7 +393,10 @@ describe('starting a run', () => { }); const error = stored?.data.resultData.error as unknown as { violations?: unknown[] }; - expect(error?.violations).toEqual([violationFor(BLOCKED, 'instance', 'deny-github')]); + const { id: projectId } = await getPersonalProject(owner); + expect(error?.violations).toEqual([ + violationFor(BLOCKED, 'instance', 'deny-github', { projectId }), + ]); }); test('runs as usual when no rule matches', async () => { @@ -423,7 +432,9 @@ describe('PUT /workflows/:workflowId/transfer', () => { expect(response.body).toMatchObject({ code: 403, - meta: { violations: [violationFor(BLOCKED, 'project', 'deny-github')] }, + meta: { + violations: [violationFor(BLOCKED, 'project', 'deny-github', { projectId: project.id })], + }, }); }); diff --git a/packages/cli/test/integration/policy/node-type-policy.fan-out.test.ts b/packages/cli/test/integration/policy/node-type-policy.fan-out.test.ts index f9124982503..367b641a684 100644 --- a/packages/cli/test/integration/policy/node-type-policy.fan-out.test.ts +++ b/packages/cli/test/integration/policy/node-type-policy.fan-out.test.ts @@ -82,6 +82,7 @@ describe('node type policy document fan-out', () => { KIND, scope.id, [{ policyId: policy.id, priority: 0, isFloor: false }], + scope.version, 'user-1', ); scopes.push(scope); diff --git a/packages/cli/test/integration/policy/node-type-policy.publish-and-start.test.ts b/packages/cli/test/integration/policy/node-type-policy.publish-and-start.test.ts index 9866f74eb0c..73f9f63794d 100644 --- a/packages/cli/test/integration/policy/node-type-policy.publish-and-start.test.ts +++ b/packages/cli/test/integration/policy/node-type-policy.publish-and-start.test.ts @@ -6,7 +6,12 @@ * behaviour the RFC asks for and the one users will call a bug — "my old workflow saves but * will not run" — so it is worth pinning on the real paths rather than in the check's own tests. */ -import { createWorkflow, createWorkflowWithHistory, testDb } from '@n8n/backend-test-utils'; +import { + createWorkflow, + createWorkflowWithHistory, + getPersonalProject, + testDb, +} from '@n8n/backend-test-utils'; import { WorkflowsConfig } from '@n8n/config'; import { LICENSE_FEATURES } from '@n8n/constants'; import { ExecutionRepository, WorkflowRepository, type IWorkflowDb, type User } from '@n8n/db'; @@ -97,6 +102,7 @@ const expectedViolation = { subjectType: 'nodeType', scope: 'instance', matchedRuleId: 'deny-set', + optInAvailable: false, }; beforeAll(async () => { @@ -254,7 +260,8 @@ describe('starting a run', () => { violations?: unknown[]; }; - expect(error?.violations).toEqual([expectedViolation]); + const { id: projectId } = await getPersonalProject(owner); + expect(error?.violations).toEqual([{ ...expectedViolation, projectId }]); }); test('fails the run of a workflow whose inline agent has a blocked node tool', async () => { @@ -273,7 +280,8 @@ describe('starting a run', () => { unflattenData: true, }); const error = stored?.data.resultData.error as unknown as { violations?: unknown[] }; - expect(error?.violations).toEqual([expectedViolation]); + const { id: projectId } = await getPersonalProject(owner); + expect(error?.violations).toEqual([{ ...expectedViolation, projectId }]); }); test('runs as usual when no rule matches the workflow', async () => { diff --git a/packages/cli/test/integration/policy/node-type-policy.save.test.ts b/packages/cli/test/integration/policy/node-type-policy.save.test.ts index ce35f0c1ca7..1200686cbf9 100644 --- a/packages/cli/test/integration/policy/node-type-policy.save.test.ts +++ b/packages/cli/test/integration/policy/node-type-policy.save.test.ts @@ -7,7 +7,13 @@ * to be an integration test: it depends on the stored workflow the host loads, which no unit * test supplies for real. */ -import { createTeamProject, createWorkflow, mockInstance, testDb } from '@n8n/backend-test-utils'; +import { + createTeamProject, + createWorkflow, + getPersonalProject, + mockInstance, + testDb, +} from '@n8n/backend-test-utils'; import { LICENSE_FEATURES } from '@n8n/constants'; import { WorkflowRepository, type Project, type User } from '@n8n/db'; import { PolicyCheckMetadata } from '@n8n/decorators'; @@ -94,14 +100,21 @@ async function putProjectPolicy( return response.body as { version: number }; } -const violationFor = (typeName: string, scope: 'instance' | 'project', matchedRuleId: string) => ({ +const violationFor = ( + typeName: string, + scope: 'instance' | 'project', + matchedRuleId: string, + { projectId, optInAvailable = false }: { projectId?: string; optInAvailable?: boolean } = {}, +) => ({ kind: 'node-type-unavailable', checkId: CHECK_ID, - message: `Node type "${typeName}" is blocked by ${scope === 'instance' ? 'an instance policy' : "this project's policy"}`, + message: `Node type "${typeName}" is blocked by ${scope === 'instance' ? 'an instance policy' : 'a project policy'}`, subject: typeName, subjectType: 'nodeType', scope, matchedRuleId, + ...(projectId !== undefined && { projectId }), + optInAvailable, }); beforeAll(async () => { @@ -316,9 +329,10 @@ describe('POST /workflows', () => { }) .expect(403); + const { id: projectId } = await getPersonalProject(owner); expect(response.body.meta.violations).toEqual([ - violationFor(SET, 'instance', 'deny-set'), - violationFor(SCHEDULE_TRIGGER, 'instance', 'deny-schedule'), + violationFor(SET, 'instance', 'deny-set', { projectId }), + violationFor(SCHEDULE_TRIGGER, 'instance', 'deny-schedule', { projectId }), ]); }); }); @@ -338,7 +352,7 @@ describe('PUT /workflows/:workflowId/transfer', () => { expect(response.body).toMatchObject({ code: 403, - meta: { violations: [violationFor(SET, 'project', 'deny-set')] }, + meta: { violations: [violationFor(SET, 'project', 'deny-set', { projectId: project.id })] }, }); }); @@ -382,7 +396,12 @@ describe('instance and project scope composition', () => { const response = await saveWithSet().expect(403); - expect(response.body.meta.violations).toEqual([violationFor(SET, 'instance', 'delegate-set')]); + expect(response.body.meta.violations).toEqual([ + violationFor(SET, 'instance', 'delegate-set', { + projectId: project.id, + optInAvailable: true, + }), + ]); }); test('keeps an instance deny in force over a project allow', async () => { @@ -391,6 +410,8 @@ describe('instance and project scope composition', () => { const response = await saveWithSet().expect(403); - expect(response.body.meta.violations).toEqual([violationFor(SET, 'instance', 'deny-set')]); + expect(response.body.meta.violations).toEqual([ + violationFor(SET, 'instance', 'deny-set', { projectId: project.id }), + ]); }); }); diff --git a/packages/cli/test/integration/policy/node-type-policy.store-reads.test.ts b/packages/cli/test/integration/policy/node-type-policy.store-reads.test.ts index cc26e7b7bfa..8e1f01f3683 100644 --- a/packages/cli/test/integration/policy/node-type-policy.store-reads.test.ts +++ b/packages/cli/test/integration/policy/node-type-policy.store-reads.test.ts @@ -103,6 +103,7 @@ describe('node type policy store reads', () => { kind, scope.id, [{ policyId: policy.id, priority: 1, isFloor: false }], + scope.version, 'user-1', ); } @@ -227,6 +228,7 @@ describe('node type policy store reads', () => { KIND, scope.id, [{ policyId: policy.id, priority: 0, isFloor: false }], + scope.version, 'user-1', ); @@ -241,6 +243,7 @@ describe('node type policy store reads', () => { KIND, projectScope.id, [{ policyId: policy.id, priority: 0, isFloor: false }], + projectScope.version, 'user-1', ); expect(await slackVerdict(null)).toBe('deny'); diff --git a/packages/cli/test/integration/policy/node-type-policy.sub-workflow.test.ts b/packages/cli/test/integration/policy/node-type-policy.sub-workflow.test.ts new file mode 100644 index 00000000000..68e57a92f06 --- /dev/null +++ b/packages/cli/test/integration/policy/node-type-policy.sub-workflow.test.ts @@ -0,0 +1,136 @@ +/** + * Pins whose project a sub-workflow refusal names. The child is checked against its own + * project's policy, and that refusal travels up to the parent's execution unchanged. + */ +import { createTeamProject, createWorkflow, testDb } from '@n8n/backend-test-utils'; +import { LICENSE_FEATURES } from '@n8n/constants'; +import { ExecutionRepository, type IWorkflowDb, type Project, type User } from '@n8n/db'; +import { Container } from '@n8n/di'; +import { v4 as uuid } from 'uuid'; + +import { createOwner } from '../shared/db/users'; +import type { SuperAgentTest } from '../shared/types'; +import * as utils from '../shared/utils/'; +import { loadNodesFromDist } from '../shared/utils/node-types-data'; +import { createParentWorkflowFixture, createSubWorkflowFixture } from '../shared/workflow-fixtures'; +import { clearPolicyCache } from './shared/policy-cache'; + +const SET = 'n8n-nodes-base.set'; + +const testServer = utils.setupTestServer({ + endpointGroups: ['workflows', 'executions', 'type-availability-policies'], + modules: ['policy-infrastructure', 'type-availability-policies'], + enabledFeatures: [LICENSE_FEATURES.TYPE_AVAILABILITY_POLICIES], +}); + +let owner: User; +let ownerAgent: SuperAgentTest; +let childProject: Project; +let executionRepository: ExecutionRepository; + +beforeAll(async () => { + await utils.initNodeTypes( + loadNodesFromDist([ + 'n8n-nodes-base.manualTrigger', + 'n8n-nodes-base.executeWorkflow', + 'n8n-nodes-base.executeWorkflowTrigger', + SET, + ]), + ); + await utils.initBinaryDataService(); + + owner = await createOwner(); + ownerAgent = testServer.authAgentFor(owner); + executionRepository = Container.get(ExecutionRepository); +}); + +beforeEach(async () => { + childProject = await createTeamProject('Child project', owner); +}); + +afterEach(async () => { + await testDb.truncate([ + 'TypeAvailabilityPolicyAttachment', + 'TypeAvailabilityPolicyScope', + 'TypeAvailabilityPolicy', + 'ExecutionEntity', + 'WorkflowEntity', + 'SharedWorkflow', + ]); + await clearPolicyCache(); +}); + +async function waitForFinalStatus(executionId: string, timeout = 20000) { + const start = Date.now(); + + while (Date.now() - start < timeout) { + const execution = await executionRepository.findOne({ where: { id: executionId } }); + if (execution && ['error', 'success', 'crashed'].includes(execution.status)) { + return execution; + } + await new Promise((resolve) => setTimeout(resolve, 50)); + } + + throw new Error(`Execution ${executionId} did not finish within ${timeout}ms`); +} + +test("names the sub-workflow's project when that project blocks a node", async () => { + const childFixture = createSubWorkflowFixture(); + const child = await createWorkflow( + { + name: 'Child', + ...childFixture, + // Unconnected: the check reads the node list, so the node never has to run. + nodes: [ + ...childFixture.nodes, + { + id: uuid(), + name: 'Set', + type: SET, + typeVersion: 3.4, + position: [200, 0], + parameters: {}, + }, + ], + settings: { callerPolicy: 'any' }, + } as unknown as IWorkflowDb, + childProject, + ); + const parent = await createWorkflow( + { name: 'Parent', ...createParentWorkflowFixture(child.id) } as unknown as IWorkflowDb, + owner, + ); + + await ownerAgent + .put(`/projects/${childProject.id}/node-type-policies/project`) + .send({ + rules: [{ id: 'deny-set', action: 'deny', selector: { kind: 'name', value: SET } }], + defaultAction: 'allow', + version: 0, + }) + .expect(200); + + const response = await ownerAgent + .post(`/workflows/${parent.id}/run`) + .send({ triggerToStartFrom: { name: 'Trigger' } }) + .expect(200); + const parentExecutionId = response.body.data.executionId as string; + + const execution = await waitForFinalStatus(parentExecutionId); + expect(execution.status).toBe('error'); + + const stored = await executionRepository.findSingleExecution(parentExecutionId, { + includeData: true, + unflattenData: true, + }); + const error = stored?.data.resultData.error as unknown as { violations?: unknown[] }; + + expect(error?.violations).toEqual([ + expect.objectContaining({ + subject: SET, + scope: 'project', + projectId: childProject.id, + optInAvailable: false, + }), + ]); +}); diff --git a/packages/cli/test/integration/policy/type-availability-policy-instance.controller.test.ts b/packages/cli/test/integration/policy/type-availability-policy-instance.controller.test.ts index 4dbc1f8dce8..ab51a01ae98 100644 --- a/packages/cli/test/integration/policy/type-availability-policy-instance.controller.test.ts +++ b/packages/cli/test/integration/policy/type-availability-policy-instance.controller.test.ts @@ -7,6 +7,7 @@ import type { NodeLoader } from 'n8n-workflow'; import { mock } from 'vitest-mock-extended'; import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials'; +import { TypeAvailabilityPolicyAttachmentRepository } from '@/modules/type-availability-policies/database/repositories/type-availability-policy-attachment.repository'; import { TypeAvailabilityPolicyScopeRepository } from '@/modules/type-availability-policies/database/repositories/type-availability-policy-scope.repository'; import { TypeAvailabilityPolicyRepository } from '@/modules/type-availability-policies/database/repositories/type-availability-policy.repository'; import { createMember, createOwner } from '@test-integration/db/users'; @@ -103,7 +104,7 @@ describe('node type availability policy instance controller RBAC', () => { const response = await testServer .authAgentFor(member) .put('/node-type-policies/scopes/does-not-exist/attachments') - .send({ attachments: [] }); + .send({ attachments: [], version: 0 }); expect(response.statusCode).toBe(403); }); @@ -362,7 +363,10 @@ describe('node type availability policy instance controller admin happy path', ( const response = await agent .put(`/node-type-policies/scopes/${instance.body.data.scopeId}/attachments`) - .send({ attachments: [{ policyId: other.id, priority: 0, isFloor: false }] }); + .send({ + attachments: [{ policyId: other.id, priority: 0, isFloor: false }], + version: instance.body.data.version, + }); expect(response.statusCode).toBe(400); }); @@ -384,7 +388,7 @@ describe('node type availability policy instance controller admin happy path', ( const response = await testServer .authAgentFor(owner) .put(`/node-type-policies/scopes/${otherScope.id}/attachments`) - .send({ attachments: [] }); + .send({ attachments: [], version: otherScope.version }); expect(response.statusCode).toBe(404); }); @@ -492,7 +496,10 @@ describe('node type availability policy instance controller admin happy path', ( await testServer .authAgentFor(owner) .put(`/node-type-policies/scopes/${scopeId}/attachments`) - .send({ attachments: [{ policyId, priority: 5, isFloor: false }] }); + .send({ + attachments: [{ policyId, priority: 5, isFloor: false }], + version: instancePut.body.data.version, + }); const response = await testServer .authAgentFor(owner) @@ -501,6 +508,47 @@ describe('node type availability policy instance controller admin happy path', ( expect(response.statusCode).toBe(409); }); + test('PUT /scopes/:scopeId/attachments with a stale version returns 409 and writes nothing', async () => { + const agent = testServer.authAgentFor(owner); + const instance = await agent + .put('/node-type-policies/instance') + .send({ rules: [], defaultAction: 'allow', version: 0 }); + expect(instance.statusCode).toBe(200); + + const read = await agent.get('/node-type-policies/instance'); + expect(read.statusCode).toBe(200); + const { scopeId, version } = read.body.data; + const rule = { + id: 'r1', + action: 'deny', + selector: { kind: 'name', value: 'n8n-nodes-base.slack' }, + }; + const policy = await agent.post('/node-type-policies/policies').send({ rules: [rule] }); + expect(policy.statusCode).toBe(200); + const attachment = { policyId: policy.body.data.policy.id, priority: 0, isFloor: false }; + + const first = await agent + .put(`/node-type-policies/scopes/${scopeId}/attachments`) + .send({ attachments: [attachment], version }); + expect(first.statusCode).toBe(200); + expect(first.body.data.version).toBe(version + 1); + expect(first.body.data.attachments).toEqual([{ ...attachment, rules: [rule] }]); + + const stale = await agent + .put(`/node-type-policies/scopes/${scopeId}/attachments`) + .send({ attachments: [], version }); + + expect(stale.statusCode).toBe(409); + const persisted = await agent.get('/node-type-policies/instance'); + expect(persisted.statusCode).toBe(200); + expect(persisted.body.data.version).toBe(first.body.data.version); + expect(persisted.body.data.rules).toEqual([rule]); + const attachments = await Container.get( + TypeAvailabilityPolicyAttachmentRepository, + ).listAttachmentsForScope(scopeId, {}); + expect(attachments).toEqual([{ ...attachment, rules: [rule] }]); + }); + test('PUT /scopes/:scopeId/attachments persists and fires an audit event', async () => { const eventService = Container.get(EventService); const emitSpy = vi.spyOn(eventService, 'emit'); @@ -521,7 +569,10 @@ describe('node type availability policy instance controller admin happy path', ( const response = await testServer .authAgentFor(owner) .put(`/node-type-policies/scopes/${scopeId}/attachments`) - .send({ attachments: [{ policyId, priority: 1, isFloor: false }] }); + .send({ + attachments: [{ policyId, priority: 1, isFloor: false }], + version: instancePut.body.data.version, + }); expect(response.statusCode).toBe(200); expect(emitSpy).toHaveBeenCalledWith( diff --git a/packages/cli/test/integration/policy/type-availability-policy-project.controller.test.ts b/packages/cli/test/integration/policy/type-availability-policy-project.controller.test.ts index 9701633b43c..336b0895f38 100644 --- a/packages/cli/test/integration/policy/type-availability-policy-project.controller.test.ts +++ b/packages/cli/test/integration/policy/type-availability-policy-project.controller.test.ts @@ -260,6 +260,7 @@ describe('node type availability policy project controller shared document prote return { scopeId: response.body.data.scopeId as string, documentId: documents.body.data[0].id as string, + version: response.body.data.version as number, }; } @@ -275,7 +276,10 @@ describe('node type availability policy project controller shared document prote const shared = await testServer .authAgentFor(owner) .put(`/node-type-policies/scopes/${instanceScopeId}/attachments`) - .send({ attachments: [{ policyId: documentId, priority: 0, isFloor: false }] }); + .send({ + attachments: [{ policyId: documentId, priority: 0, isFloor: false }], + version: instancePut.body.data.version, + }); expect(shared.statusCode).toBe(200); const current = await testServer.authAgentFor(projectAdmin).get(projectRoute(project.id)); @@ -293,7 +297,7 @@ describe('node type availability policy project controller shared document prote }); test('PUT is rejected with 409 when the project scope has several attached documents', async () => { - const { scopeId, documentId } = await configureProject(); + const { scopeId, documentId, version } = await configureProject(); const created = await testServer .authAgentFor(owner) @@ -309,6 +313,7 @@ describe('node type availability policy project controller shared document prote { policyId: documentId, priority: 0, isFloor: false }, { policyId: secondDocumentId, priority: 1, isFloor: false }, ], + version, }); expect(attached.statusCode).toBe(200); @@ -345,6 +350,7 @@ describe('node type availability policy project controller delegate rejection vi .put(`/node-type-policies/scopes/${scopeId}/attachments`) .send({ attachments: [{ policyId: created.body.data.policy.id, priority: 0, isFloor: false }], + version: configured.body.data.version, }); expect(response.statusCode).toBe(400); diff --git a/packages/cli/test/integration/public-api/credential-type-policies.test.ts b/packages/cli/test/integration/public-api/credential-type-policies.test.ts index 8fe685ffbe3..b17e811bab9 100644 --- a/packages/cli/test/integration/public-api/credential-type-policies.test.ts +++ b/packages/cli/test/integration/public-api/credential-type-policies.test.ts @@ -90,7 +90,9 @@ describe('credential type policies public API authorization', () => { : method === 'POST' ? agent.post(path).send({}) : method === 'PUT' - ? agent.put(path).send({}) + ? agent + .put(path) + .send(path.endsWith('/attachments') ? { attachments: [], version: 0 } : {}) : agent.delete(path)); expect(response.statusCode).toBe(403); @@ -121,7 +123,9 @@ describe('credential type policies public API authorization', () => { : method === 'POST' ? agent.post(path).send({}) : method === 'PUT' - ? agent.put(path).send({}) + ? agent + .put(path) + .send(path.endsWith('/attachments') ? { attachments: [], version: 0 } : {}) : agent.delete(path)); expect(response.statusCode).toBe(403); @@ -377,7 +381,10 @@ describe('credential type policies public API project scope', () => { const instancePut = await ownerAgent.put('/credential-type-policies/instance').send(ALLOW_ALL); const shared = await ownerAgent .put(`/credential-type-policies/scopes/${instancePut.body.scopeId}/attachments`) - .send({ attachments: [{ policyId: documentId, priority: 0, isFloor: false }] }); + .send({ + attachments: [{ policyId: documentId, priority: 0, isFloor: false }], + version: instancePut.body.version, + }); expect(shared.statusCode).toBe(200); const current = await adminAgent.get(projectRoute(project.id)); @@ -577,7 +584,10 @@ describe('credential type policies public API policy documents', () => { const instancePut = await agent.put('/credential-type-policies/instance').send(ALLOW_ALL); await agent .put(`/credential-type-policies/scopes/${instancePut.body.scopeId}/attachments`) - .send({ attachments: [{ policyId, priority: 5, isFloor: false }] }); + .send({ + attachments: [{ policyId, priority: 5, isFloor: false }], + version: instancePut.body.version, + }); const response = await agent.delete(`/credential-type-policies/policies/${policyId}`); @@ -586,6 +596,33 @@ describe('credential type policies public API policy documents', () => { }); describe('credential type policies public API attachments', () => { + test('PUT with a stale version returns 409 and preserves the attachments and version', async () => { + const agent = testServer.publicApiAgentFor(owner); + const instance = await agent.put('/credential-type-policies/instance').send({ + ...ALLOW_ALL, + rules: [DENY_RULE], + }); + expect(instance.statusCode).toBe(200); + + const stale = await agent + .put(`/credential-type-policies/scopes/${instance.body.scopeId}/attachments`) + .send({ attachments: [], version: 0 }); + + expect(stale.statusCode).toBe(409); + const persisted = await agent.get('/credential-type-policies/instance'); + expect(persisted.body.rules).toEqual([DENY_RULE]); + expect(persisted.body.version).toBe(instance.body.version); + }); + + test.each([undefined, -1, 0.5])('PUT rejects invalid version %s with 400', async (version) => { + const response = await testServer + .publicApiAgentFor(owner) + .put('/credential-type-policies/scopes/does-not-exist/attachments') + .send({ attachments: [], version }); + + expect(response.statusCode).toBe(400); + }); + test('PUT replaces the attachments, bumps the version, and fires an audit event', async () => { const eventService = Container.get(EventService); const emitSpy = vi.spyOn(eventService, 'emit'); @@ -601,7 +638,10 @@ describe('credential type policies public API attachments', () => { emitSpy.mockClear(); const response = await agent .put(`/credential-type-policies/scopes/${scopeId}/attachments`) - .send({ attachments: [{ policyId, priority: 1, isFloor: false }] }); + .send({ + attachments: [{ policyId, priority: 1, isFloor: false }], + version: instancePut.body.version, + }); expect(response.statusCode).toBe(200); expect(Object.keys(response.body).sort()).toEqual(['attachments', 'version']); @@ -627,6 +667,7 @@ describe('credential type policies public API attachments', () => { { policyId: 'p1', priority: 0, isFloor: false }, { policyId: 'p1', priority: 1, isFloor: false }, ], + version: instancePut.body.version, }); expect(duplicatePolicy.statusCode).toBe(400); @@ -637,6 +678,7 @@ describe('credential type policies public API attachments', () => { { policyId: 'p1', priority: 0, isFloor: false }, { policyId: 'p2', priority: 0, isFloor: false }, ], + version: instancePut.body.version, }); expect(duplicateSlot.statusCode).toBe(400); }); @@ -645,7 +687,7 @@ describe('credential type policies public API attachments', () => { const response = await testServer .publicApiAgentFor(owner) .put('/credential-type-policies/scopes/does-not-exist/attachments') - .send({ attachments: [] }); + .send({ attachments: [], version: 0 }); expect(response.statusCode).toBe(404); }); @@ -665,7 +707,10 @@ describe('credential type policies public API attachments', () => { const response = await ownerAgent .put(`/credential-type-policies/scopes/${scopeId}/attachments`) - .send({ attachments: [{ policyId: created.body.policy.id, priority: 0, isFloor: false }] }); + .send({ + attachments: [{ policyId: created.body.policy.id, priority: 0, isFloor: false }], + version: configured.body.version, + }); expect(response.statusCode).toBe(400); }); @@ -714,7 +759,10 @@ describe('credential type policies public API extends rules', () => { const attachments = await agent .put(`/credential-type-policies/scopes/${instancePut.body.scopeId}/attachments`) - .send({ attachments: [{ policyId, priority: 1, isFloor: false }] }); + .send({ + attachments: [{ policyId, priority: 1, isFloor: false }], + version: instancePut.body.version, + }); expect(attachments.statusCode).toBe(200); expect(attachments.body.attachments).toEqual([ { policyId, rules: [EXTENDS_RULE], priority: 1, isFloor: false }, diff --git a/packages/cli/test/integration/public-api/endpoints-with-scopes-enabled.test.ts b/packages/cli/test/integration/public-api/endpoints-with-scopes-enabled.test.ts index 7f7770887d8..bd68905dd59 100644 --- a/packages/cli/test/integration/public-api/endpoints-with-scopes-enabled.test.ts +++ b/packages/cli/test/integration/public-api/endpoints-with-scopes-enabled.test.ts @@ -23,7 +23,7 @@ import { mock } from 'vitest-mock-extended'; import { TOKEN_EXCHANGE_ISSUER } from '@/modules/token-exchange/token-exchange.types'; import { CredentialsTester } from '@/services/credentials-tester.service'; -import { JwtService } from '@/services/jwt.service'; +import { JwtService } from '@n8n/backend-services'; import { affixRoleToSaveCredential, createCredentials } from '@test-integration/db/credentials'; import { createAnnotationTags, diff --git a/packages/cli/test/integration/public-api/executions.test.ts b/packages/cli/test/integration/public-api/executions.test.ts index a3995de8fec..71e4eab4bf0 100644 --- a/packages/cli/test/integration/public-api/executions.test.ts +++ b/packages/cli/test/integration/public-api/executions.test.ts @@ -8,7 +8,7 @@ import { shareWorkflowWithUsers, testDb, } from '@n8n/backend-test-utils'; -import type { ExecutionEntity, IExecutionResponse, User } from '@n8n/db'; +import { type ExecutionEntity, type IExecutionResponse, type User } from '@n8n/db'; import { Container } from '@n8n/di'; import { InstanceSettings } from 'n8n-core'; import { type ExecutionStatus } from 'n8n-workflow'; @@ -998,41 +998,61 @@ describe('GET /executions', () => { } }); - test('should return executions filtered by project ID', async () => { - /** - * Arrange - */ - const [firstProject, secondProject] = await Promise.all([ - createTeamProject(), - createTeamProject(), - ]); - const [firstWorkflow, secondWorkflow] = await Promise.all([ - createWorkflow({}, firstProject), - createWorkflow({}, secondProject), - ]); - const [firstExecution, secondExecution, _] = await Promise.all([ - createExecution({}, firstWorkflow), - createExecution({}, firstWorkflow), - createExecution({}, secondWorkflow), - ]); + test.each<{ + data: () => User; + type: 'owner' | 'member'; + }>([ + { type: 'owner', data: () => owner }, + { type: 'member', data: () => user1 }, + ])( + 'should return executions filtered by project ID for $type', + async ({ data: getUser, type }) => { + testServer.license.enable('feat:sharing'); + const user = getUser(); + const agent = testServer.publicApiAgentFor(user); - /** - * Act - */ - const response = await authOwnerAgent.get('/executions').query({ - projectId: firstProject.id, - }); + /** + * Arrange + */ + const [firstProject, secondProject] = await Promise.all([ + createTeamProject('first project', owner), + createTeamProject('second project', owner), + ]); + if (type === 'member') { + await Promise.all([ + linkUserToProject(user, firstProject, 'project:editor'), + linkUserToProject(user, secondProject, 'project:editor'), + ]); + } - /** - * Assert - */ - expect(response.statusCode).toBe(200); - expect(response.body.data.length).toBe(2); - expect(response.body.nextCursor).toBeNull(); - expect(response.body.data.map((execution: ExecutionEntity) => execution.id)).toEqual( - expect.arrayContaining([firstExecution.id, secondExecution.id]), - ); - }); + const [firstWorkflow, secondWorkflow] = await Promise.all([ + createWorkflow({}, firstProject), + createWorkflow({}, secondProject), + ]); + const [firstExecution, secondExecution, _] = await Promise.all([ + createExecution({}, firstWorkflow), + createExecution({}, firstWorkflow), + createExecution({}, secondWorkflow), + ]); + + /** + * Act + */ + const response = await agent.get('/executions').query({ + projectId: firstProject.id, + }); + + /** + * Assert + */ + expect(response.statusCode).toBe(200); + expect(response.body.data.length).toBe(2); + expect(response.body.nextCursor).toBeNull(); + expect(response.body.data.map((execution: ExecutionEntity) => execution.id)).toEqual( + expect.arrayContaining([firstExecution.id, secondExecution.id]), + ); + }, + ); describe('with startedAfter and startedBefore filters', () => { test('should retrieve executions started after a given time', async () => { diff --git a/packages/cli/test/integration/public-api/n8n-packages-export-agents.test.ts b/packages/cli/test/integration/public-api/n8n-packages-export-agents.test.ts index a42eebc6555..4ca7cbc610d 100644 --- a/packages/cli/test/integration/public-api/n8n-packages-export-agents.test.ts +++ b/packages/cli/test/integration/public-api/n8n-packages-export-agents.test.ts @@ -14,6 +14,7 @@ import { InstanceSettings } from 'n8n-core'; import { jsonParse } from 'n8n-workflow'; import type { Readable } from 'node:stream'; +import { setSkillsHubFlag } from '@/modules/agents/__tests__/test-utils/skills-hub-flag'; import type { Agent } from '@/modules/agents/entities/agent.entity'; import { AgentHistoryRepository } from '@/modules/agents/repositories/agent-history.repository'; import { AgentTaskRepository } from '@/modules/agents/repositories/agent-task.repository'; @@ -36,6 +37,8 @@ import { createMemberWithApiKey, createOwnerWithApiKey } from '@test-integration import { createProjectVariable } from '@test-integration/db/variables'; import { setupTestServer } from '@test-integration/utils'; import { storedAgentConfig } from '@/modules/agents/__tests__/test-utils/stored-agent-config'; +import { SkillRepository } from '@/modules/agents/repositories/skill.repository'; +import { toSkillContent } from '@/modules/agents/skills/skill.service'; beforeAll(async () => await testModules.loadModules(['n8n-packages', 'agents'])); const server = setupTestServer({ endpointGroups: ['publicApi'] }); @@ -47,7 +50,8 @@ let dependency: Agent; let workflow: WorkflowEntity; let repository: AgentRepository; -beforeAll(() => { +beforeAll(async () => { + await setSkillsHubFlag(true); repository = Container.get(AgentRepository); Container.get(InstanceSettings).markAsLeader(); }); @@ -79,6 +83,7 @@ afterEach(async () => { await repository.delete({}); await Container.get(AgentHistoryRepository).delete({}); await Container.get(AgentTaskRepository).delete({}); + await Container.get(SkillRepository).delete({}); await testDb.truncate([ 'WorkflowEntity', 'WorkflowHistory', @@ -128,7 +133,7 @@ async function download(body: Partial, user = owner) { } it('downloads an Agent with its skills, tools, tasks, and dependencies', async () => { - const { config, tasks, ...content } = serializedAgentSchema.parse( + const { config, tasks, skills, ...content } = serializedAgentSchema.parse( looseAgentsFixture().files['agents/support/agent.json'], ); agent = await repository.save({ @@ -136,6 +141,19 @@ it('downloads an Agent with its skills, tools, tasks, and dependencies', async ( ...content, schema: config && storedAgentConfig(config), }); + const [skillId] = Object.keys(skills); + const { allowedTools: _dropped, ...skill } = skills[skillId]; + const skillRepository = Container.get(SkillRepository); + await skillRepository.createSkill( + { + id: skillId, + target: { projectId: project.id, agentId: null }, + source: 'ui', + createdById: null, + }, + toSkillContent(skill), + ); + await skillRepository.replaceDependencies(agent.id, [{ skillId }]); await Container.get(AgentTaskRepository).save( Object.entries(tasks).map(([id, task]) => ({ id, agentId: agent.id, ...task })), ); @@ -160,8 +178,8 @@ it('downloads an Agent with its skills, tools, tasks, and dependencies', async ( expect(parsed).toMatchObject({ sourceAgentId: agent.id, availableInMCP: true, - config: { skills: [{ enabled: false }], tasks: [{ enabled: false }] }, - skills: content.skills, + config: { skills: [{ type: 'skill', id: skillId }], tasks: [{ enabled: false }] }, + skills: { [skillId]: skill }, tools: content.tools, tasks: { [`${agent.id}_task`]: { cronExpression: '0 9 * * *', timezone: null } }, }); @@ -239,7 +257,6 @@ it.each(['published-strict', 'ignore-unpublished'] as const)( versionId: 'published-version', publishedBy: 'Package test', schema: storedAgentConfig(schema), - skills: {}, tools: {}, }); await repository.update(agent.id, { activeVersionId: 'published-version' }); diff --git a/packages/cli/test/integration/public-api/n8n-packages-export.test.ts b/packages/cli/test/integration/public-api/n8n-packages-export.test.ts index e25d4b56e24..345e18abe75 100644 --- a/packages/cli/test/integration/public-api/n8n-packages-export.test.ts +++ b/packages/cli/test/integration/public-api/n8n-packages-export.test.ts @@ -192,16 +192,31 @@ describe('POST /n8n-packages/export', () => { const response = await authOwnerAgent .post('/n8n-packages/export') + .buffer(true) + // supertest buffers only text and JSON bodies by default + .parse((res, callback) => { + const chunks: Buffer[] = []; + res.on('data', (chunk: Buffer) => chunks.push(chunk)); + res.on('end', () => callback(null, Buffer.concat(chunks))); + }) .send({ folderIds: [folder.id] }); expect(response.statusCode).toBe(200); expect(response.headers['content-type']).toContain('application/gzip'); expect(response.headers['content-disposition']).toContain('export.n8np'); + + const counts = JSON.parse(response.headers['x-n8n-export-counts']); + expect(typeof counts.workflows).toBe('number'); + expect(typeof counts.folders).toBe('number'); + expect(response.headers['access-control-expose-headers']).toBe('X-N8n-Export-Counts'); + + // Gzip magic number + const body: Buffer = response.body; + expect([body[0], body[1]]).toEqual([0x1f, 0x8b]); }); - // The OpenAPI request schema has `additionalProperties: false`, so acceptance - // proves `includeTags` is declared in exportPackageRequest.yml. - test('accepts includeTags=false through the OpenAPI request validator', async () => { + // The request DTO is strict, so acceptance proves `includeTags` is a declared field. + test('accepts includeTags=false through the request DTO', async () => { const project = await createTeamProject('Export project', owner); const folder = await createFolder(project, { name: 'to_production' }); @@ -212,8 +227,8 @@ describe('POST /n8n-packages/export', () => { expect(response.statusCode).toBe(200); }); - // Acceptance proves `credentialExportPolicy` is declared in exportPackageRequest.yml. - test('accepts credentialExportPolicy=no-values through the OpenAPI request validator', async () => { + // Acceptance proves `credentialExportPolicy` is a declared field of the request DTO. + test('accepts credentialExportPolicy=no-values through the request DTO', async () => { const project = await createTeamProject('Export project', owner); const folder = await createFolder(project, { name: 'to_production' }); @@ -234,4 +249,44 @@ describe('POST /n8n-packages/export', () => { expect(response.statusCode).toBe(400); }); + + test('rejects an unauthenticated request with 401', async () => { + const response = await testServer + .publicApiAgentWithoutApiKey() + .post('/n8n-packages/export') + .send({ workflowIds: ['wf-1'] }); + + expect(response.statusCode).toBe(401); + }); + + test('rejects a key with neither project:export nor workflow:export with 403, before the handler runs', async () => { + const readOnlyOwner = await createOwnerWithApiKey({ scopes: ['workflow:read'] }); + const emitSpy = vi.spyOn(Container.get(EventService), 'emit'); + + const response = await testServer + .publicApiAgentFor(readOnlyOwner) + .post('/n8n-packages/export') + .send({ workflowIds: ['wf-1'] }); + + expect(response.statusCode).toBe(403); + expect(emitSpy).not.toHaveBeenCalledWith('n8n-package-export-failed', expect.anything()); + }); + + test('rejects a non-JSON Content-Type with 415', async () => { + const response = await authOwnerAgent + .post('/n8n-packages/export') + .set('Content-Type', 'text/plain') + .send('workflowIds'); + + expect(response.statusCode).toBe(415); + }); + + test('rejects an unknown body field with 400', async () => { + const response = await authOwnerAgent + .post('/n8n-packages/export') + .send({ workflowIds: ['wf-1'], evil: 'x' }); + + expect(response.statusCode).toBe(400); + expect(response.body.message).toContain('evil'); + }); }); diff --git a/packages/cli/test/integration/public-api/n8n-packages-import.test.ts b/packages/cli/test/integration/public-api/n8n-packages-import.test.ts index 4607a91fcda..a7bacde1044 100644 --- a/packages/cli/test/integration/public-api/n8n-packages-import.test.ts +++ b/packages/cli/test/integration/public-api/n8n-packages-import.test.ts @@ -257,6 +257,7 @@ describe('POST /n8n-packages/import', () => { credentials: { matched: [], stubbed: [], + seeded: [], }, dataTables: { matched: 0, @@ -345,6 +346,19 @@ describe('POST /n8n-packages/import', () => { expect(response.statusCode).toBe(200); }); + test('accepts credentialMissingMode=create-with-values through the OpenAPI request validator', async () => { + const tarBuffer = await buildImportPackage(); + const response = await authOwnerAgent + .post('/n8n-packages/import') + .field('projectId', ownerPersonalProject.id) + .field('workflowConflictPolicy', 'fail') + .field('credentialMissingMode', 'create-with-values') + .attach('package', tarBuffer, 'import.n8np'); + + expect(response.statusCode).toBe(200); + expect(response.body.credentials).toMatchObject({ seeded: [] }); + }); + test('rejects an unsupported dataTableMissingMode value', async () => { const tarBuffer = await buildImportPackage(); @@ -515,6 +529,7 @@ describe('POST /n8n-packages/import', () => { expect(response.body.credentials).toEqual({ matched: [], stubbed: ['missing-credential'], + seeded: [], }); expect(response.body.bindings.credentials).toEqual({ 'missing-credential': expect.any(String), diff --git a/packages/cli/test/integration/public-api/node-type-policies.test.ts b/packages/cli/test/integration/public-api/node-type-policies.test.ts index 396d9e44581..be6ce527447 100644 --- a/packages/cli/test/integration/public-api/node-type-policies.test.ts +++ b/packages/cli/test/integration/public-api/node-type-policies.test.ts @@ -85,7 +85,9 @@ describe('node type policies public API authorization', () => { : method === 'POST' ? agent.post(path).send({}) : method === 'PUT' - ? agent.put(path).send({}) + ? agent + .put(path) + .send(path.endsWith('/attachments') ? { attachments: [], version: 0 } : {}) : agent.delete(path)); expect(response.statusCode).toBe(403); @@ -116,7 +118,9 @@ describe('node type policies public API authorization', () => { : method === 'POST' ? agent.post(path).send({}) : method === 'PUT' - ? agent.put(path).send({}) + ? agent + .put(path) + .send(path.endsWith('/attachments') ? { attachments: [], version: 0 } : {}) : agent.delete(path)); expect(response.statusCode).toBe(403); @@ -368,7 +372,10 @@ describe('node type policies public API project scope', () => { const instancePut = await ownerAgent.put('/node-type-policies/instance').send(ALLOW_ALL); const shared = await ownerAgent .put(`/node-type-policies/scopes/${instancePut.body.scopeId}/attachments`) - .send({ attachments: [{ policyId: documentId, priority: 0, isFloor: false }] }); + .send({ + attachments: [{ policyId: documentId, priority: 0, isFloor: false }], + version: instancePut.body.version, + }); expect(shared.statusCode).toBe(200); const current = await adminAgent.get(projectRoute(project.id)); @@ -545,9 +552,10 @@ describe('node type policies public API policy documents', () => { const policyId = created.body.policy.id as string; const instancePut = await agent.put('/node-type-policies/instance').send(ALLOW_ALL); - await agent - .put(`/node-type-policies/scopes/${instancePut.body.scopeId}/attachments`) - .send({ attachments: [{ policyId, priority: 5, isFloor: false }] }); + await agent.put(`/node-type-policies/scopes/${instancePut.body.scopeId}/attachments`).send({ + attachments: [{ policyId, priority: 5, isFloor: false }], + version: instancePut.body.version, + }); const response = await agent.delete(`/node-type-policies/policies/${policyId}`); @@ -556,6 +564,33 @@ describe('node type policies public API policy documents', () => { }); describe('node type policies public API attachments', () => { + test('PUT with a stale version returns 409 and preserves the attachments and version', async () => { + const agent = testServer.publicApiAgentFor(owner); + const instance = await agent.put('/node-type-policies/instance').send({ + ...ALLOW_ALL, + rules: [DENY_RULE], + }); + expect(instance.statusCode).toBe(200); + + const stale = await agent + .put(`/node-type-policies/scopes/${instance.body.scopeId}/attachments`) + .send({ attachments: [], version: 0 }); + + expect(stale.statusCode).toBe(409); + const persisted = await agent.get('/node-type-policies/instance'); + expect(persisted.body.rules).toEqual([DENY_RULE]); + expect(persisted.body.version).toBe(instance.body.version); + }); + + test.each([undefined, -1, 0.5])('PUT rejects invalid version %s with 400', async (version) => { + const response = await testServer + .publicApiAgentFor(owner) + .put('/node-type-policies/scopes/does-not-exist/attachments') + .send({ attachments: [], version }); + + expect(response.statusCode).toBe(400); + }); + test('PUT replaces the attachments, bumps the version, and fires an audit event', async () => { const eventService = Container.get(EventService); const emitSpy = vi.spyOn(eventService, 'emit'); @@ -567,9 +602,10 @@ describe('node type policies public API attachments', () => { const policyId = created.body.policy.id as string; emitSpy.mockClear(); - const response = await agent - .put(`/node-type-policies/scopes/${scopeId}/attachments`) - .send({ attachments: [{ policyId, priority: 1, isFloor: false }] }); + const response = await agent.put(`/node-type-policies/scopes/${scopeId}/attachments`).send({ + attachments: [{ policyId, priority: 1, isFloor: false }], + version: instancePut.body.version, + }); expect(response.statusCode).toBe(200); expect(Object.keys(response.body).sort()).toEqual(['attachments', 'version']); @@ -595,6 +631,7 @@ describe('node type policies public API attachments', () => { { policyId: 'p1', priority: 0, isFloor: false }, { policyId: 'p1', priority: 1, isFloor: false }, ], + version: instancePut.body.version, }); expect(duplicatePolicy.statusCode).toBe(400); @@ -605,6 +642,7 @@ describe('node type policies public API attachments', () => { { policyId: 'p1', priority: 0, isFloor: false }, { policyId: 'p2', priority: 0, isFloor: false }, ], + version: instancePut.body.version, }); expect(duplicateSlot.statusCode).toBe(400); }); @@ -613,7 +651,7 @@ describe('node type policies public API attachments', () => { const response = await testServer .publicApiAgentFor(owner) .put('/node-type-policies/scopes/does-not-exist/attachments') - .send({ attachments: [] }); + .send({ attachments: [], version: 0 }); expect(response.statusCode).toBe(404); }); @@ -633,7 +671,10 @@ describe('node type policies public API attachments', () => { const response = await ownerAgent .put(`/node-type-policies/scopes/${scopeId}/attachments`) - .send({ attachments: [{ policyId: created.body.policy.id, priority: 0, isFloor: false }] }); + .send({ + attachments: [{ policyId: created.body.policy.id, priority: 0, isFloor: false }], + version: configured.body.version, + }); expect(response.statusCode).toBe(400); }); diff --git a/packages/cli/test/integration/public-api/oauth-bearer.test.ts b/packages/cli/test/integration/public-api/oauth-bearer.test.ts new file mode 100644 index 00000000000..f4531b8afcb --- /dev/null +++ b/packages/cli/test/integration/public-api/oauth-bearer.test.ts @@ -0,0 +1,176 @@ +import { testDb } from '@n8n/backend-test-utils'; +import { principalFromUser, TagRepository, type User } from '@n8n/db'; +import { Container } from '@n8n/di'; +import { AuthenticationPipeline, AuthenticationService } from '@n8n/inbound-auth'; +import { sign } from 'jsonwebtoken'; +import { mock } from 'vitest-mock-extended'; + +import { createMember, createOwnerWithApiKey } from '@test-integration/db/users'; +import { setupTestServer } from '@test-integration/utils'; + +const CHALLENGE = + 'Bearer resource_metadata="https://n8n.test/.well-known/oauth-protected-resource/api/v1"'; + +// The pipeline is the unit under test elsewhere; here it is a boundary. Only `iss` is read before it runs. +const tokenFrom = (iss: string) => sign({ iss, sub: 'alice' }, 'unverified-here'); + +const pipeline = mock(); +const authenticationService = mock(); + +describe('Public API with OAuth2 bearer tokens', () => { + const testServer = setupTestServer({ endpointGroups: ['publicApi'] }); + + beforeAll(async () => { + await testDb.init(); + + Container.set(AuthenticationPipeline, pipeline); + Container.set(AuthenticationService, authenticationService); + + // `InboundAuthCoreModule.init()` registers the strategy on main; the test server loads no + // modules, so register it by hand after the API key and session-cookie strategies. + const { PublicApiOAuthStrategy } = await import( + '@/modules/inbound-auth-core/public-api-oauth.strategy.js' + ); + const { AuthStrategyRegistry } = await import('@/services/auth-strategy.registry.js'); + Container.get(AuthStrategyRegistry).register(Container.get(PublicApiOAuthStrategy)); + }); + + beforeEach(async () => { + await testDb.truncate(['User', 'TagEntity']); + vi.clearAllMocks(); + authenticationService.advertise.mockResolvedValue({ + authorizationServers: ['https://idp.example'], + challenges: [CHALLENGE], + }); + }); + + afterAll(async () => { + await testDb.terminate(); + }); + + test('authenticates a token the pipeline accepts as the bound user, with API key scopes from the role', async () => { + const member = await createMember(); + pipeline.run.mockResolvedValue({ + ok: true, + value: { subject: principalFromUser(member), authMethod: 'oauth-access-token' }, + }); + const token = tokenFrom('https://idp.example'); + + const response = await testServer + .publicApiAgentWithoutApiKey() + .set('Authorization', `Bearer ${token}`) + .get('/workflows'); + + expect(response.statusCode).toBe(200); + expect(pipeline.run).toHaveBeenCalledWith( + expect.objectContaining({ + surface: 'public-api', + resource: expect.objectContaining({ url: expect.stringMatching(/\/api\/v1$/) }), + credential: { kind: 'bearer', token }, + }), + ); + }); + + test('answers 401 with a bearer challenge for a token the pipeline rejects', async () => { + pipeline.run.mockResolvedValue({ ok: false, reason: 'source-not-accepted' }); + + const response = await testServer + .publicApiAgentWithoutApiKey() + .set('Authorization', `Bearer ${tokenFrom('https://idp.example')}`) + .get('/workflows'); + + expect(response.statusCode).toBe(401); + expect(response.headers['www-authenticate']).toBe( + `${CHALLENGE}, error="invalid_token", error_description="source-not-accepted"`, + ); + }); + + test('leaves API keys to the API key strategy', async () => { + const owner = await createOwnerWithApiKey(); + + const response = await testServer.publicApiAgentFor(owner).get('/workflows'); + + expect(response.statusCode).toBe(200); + expect(pipeline.run).not.toHaveBeenCalled(); + }); + + test('leaves a bearer whose issuer is not a URL to the other strategies', async () => { + const response = await testServer + .publicApiAgentWithoutApiKey() + .set('Authorization', `Bearer ${tokenFrom('n8n-token-exchange')}`) + .get('/workflows'); + + expect(response.statusCode).toBe(401); + expect(pipeline.run).not.toHaveBeenCalled(); + expect(response.headers['www-authenticate']).toBeUndefined(); + }); + + describe('scope enforcement', () => { + let member: User; + const bearer = () => `Bearer ${tokenFrom('https://idp.example')}`; + + const acceptWith = (tokenScopes?: string[]) => + pipeline.run.mockResolvedValue({ + ok: true, + value: { + subject: principalFromUser(member), + authMethod: 'oauth-access-token', + ...(tokenScopes && { tokenScopes }), + }, + }); + + beforeEach(async () => { + member = await createMember(); + }); + + test.each<{ name: string; tokenScopes?: string[]; list: number; create: number }>([ + { name: 'a read scope only', tokenScopes: ['tag:list'], list: 200, create: 403 }, + { + name: 'read and write scopes', + tokenScopes: ['tag:list', 'tag:create'], + list: 200, + create: 201, + }, + { name: 'no scope claim (full role)', list: 200, create: 201 }, + { + name: 'only IdP scopes (full role)', + tokenScopes: ['openid', 'profile'], + list: 200, + create: 201, + }, + { name: 'a scope outside the token', tokenScopes: ['workflow:list'], list: 403, create: 403 }, + { name: 'a scope the role lacks', tokenScopes: ['user:create'], list: 403, create: 403 }, + ])('with $name: list tags $list, create tag $create', async ({ tokenScopes, list, create }) => { + acceptWith(tokenScopes); + const agent = testServer.publicApiAgentWithoutApiKey(); + + const listed = await agent.get('/tags').set('Authorization', bearer()); + const created = await agent + .post('/tags') + .set('Authorization', bearer()) + .send({ name: 'oauth' }); + + expect(listed.statusCode).toBe(list); + expect(created.statusCode).toBe(create); + // A refused write must leave no trace. + expect(await Container.get(TagRepository).count()).toBe(create === 201 ? 1 : 0); + }); + + test('never grants a scope the role lacks, even when the token carries it', async () => { + acceptWith(['user:create', 'tag:list']); + + const created = await testServer + .publicApiAgentWithoutApiKey() + .post('/users') + .set('Authorization', bearer()) + .send([{ email: 'new@example.com', role: 'global:member' }]); + const tags = await testServer + .publicApiAgentWithoutApiKey() + .get('/tags') + .set('Authorization', bearer()); + + expect(created.statusCode).toBe(403); + expect(tags.statusCode).toBe(200); + }); + }); +}); diff --git a/packages/cli/test/integration/public-api/oauth-consent-scopes.test.ts b/packages/cli/test/integration/public-api/oauth-consent-scopes.test.ts new file mode 100644 index 00000000000..c84e035cf01 --- /dev/null +++ b/packages/cli/test/integration/public-api/oauth-consent-scopes.test.ts @@ -0,0 +1,208 @@ +import { Logger } from '@n8n/backend-common'; +import { + CacheService, + JwtService, + type OAuthDiscoveryClient, + UrlService, +} from '@n8n/backend-services'; +import { testDb } from '@n8n/backend-test-utils'; +import { TagRepository, type User } from '@n8n/db'; +import { Container } from '@n8n/di'; +import { LocalAuthorizationServer } from '@n8n/inbound-auth'; +import { createHash, randomBytes } from 'node:crypto'; +import { mock } from 'vitest-mock-extended'; + +import { PublicApiProtectedResource } from '@/modules/inbound-auth-core/public-api-protected-resource'; +import { TrustedSourceDiscoveryService } from '@/modules/inbound-auth-core/trusted-source-discovery.service'; +import { TrustedSourceDbStore } from '@/modules/inbound-auth-core/trusted-source.store'; +import { OAuthClientRepository } from '@/modules/oauth-server/database/repositories/oauth-client.repository'; +import type { OAuthSessionPayload } from '@/modules/oauth-server/oauth-session.service'; +import { createMember, createOwner } from '@test-integration/db/users'; +import { setupTestServer } from '@test-integration/utils'; + +/** + * The whole chain, nothing mocked but the network: the user picks scopes on the consent screen, + * the instance mints a token for `/api/v1`, the trusted-source pipeline verifies it against the + * instance's own keys, and the public API allows only what was picked. + */ +const testServer = setupTestServer({ + modules: ['oauth-jwe', 'oauth-server', 'mcp', 'inbound-auth-core'], + endpointGroups: ['mcp', 'jwks', 'publicApi'], +}); + +const REDIRECT_URI = 'https://example.com/callback'; +const b64url = (buf: Buffer) => buf.toString('base64url'); + +let owner: User; +let member: User; +let resource: string; +let jwtService: JwtService; + +beforeAll(async () => { + await Container.get(CacheService).init(); + owner = await createOwner(); + member = await createMember(); + jwtService = Container.get(JwtService); + resource = Container.get(PublicApiProtectedResource).getResourceUrl(); + + // The module seeded `n8n-internal` at init; discovery normally runs as a system task. Run it + // once here, reading the local authorization server in process, never over HTTP. + const offline = mock(); + const refused = new Error('discovery must not go over HTTP'); + offline.fetchOpenIdConfiguration.mockRejectedValue(refused); + offline.fetchOAuth2ServerMetadata.mockRejectedValue(refused); + offline.fetchJwks.mockRejectedValue(refused); + const discovery = new TrustedSourceDiscoveryService( + Container.get(Logger), + Container.get(TrustedSourceDbStore), + offline, + Container.get(LocalAuthorizationServer), + ); + await discovery.refresh('n8n-internal'); + await Container.get(CacheService).reset(); +}); + +afterEach(async () => { + await testDb.truncate([ + 'OAuthClient', + 'AuthorizationCode', + 'AccessToken', + 'RefreshToken', + 'UserConsent', + 'TagEntity', + ]); +}); + +async function registerClient(): Promise { + const id = `client-${randomBytes(6).toString('hex')}`; + await Container.get(OAuthClientRepository).save({ + id, + name: 'scope test client', + redirectUris: [REDIRECT_URI], + grantTypes: ['authorization_code', 'refresh_token'], + tokenEndpointAuthMethod: 'none', + clientSecret: null, + clientSecretExpiresAt: null, + isFirstParty: false, + }); + return id; +} + +/** What the consent screen posts after the user picked `scopes`, then the code-for-token exchange. */ +async function consentAndExchange(user: User, scopes: string[], requestedScopes?: string[]) { + const clientId = await registerClient(); + const verifier = b64url(randomBytes(32)); + const payload: OAuthSessionPayload = { + clientId, + redirectUri: REDIRECT_URI, + codeChallenge: b64url(createHash('sha256').update(verifier).digest()), + state: null, + resource, + ...(requestedScopes && { requestedScopes }), + }; + const session = jwtService.sign('oauthSession', payload, { expiresIn: '10m' }); + + const approval = await testServer + .authAgentFor(user) + .post('/consent/approve') + .set('Cookie', `n8n-oauth-session=${session}`) + .send({ approved: true, scopes }); + if (approval.statusCode !== 200) return { approval, token: undefined }; + + const code = new URL(approval.body.data.redirectUrl as string).searchParams.get('code'); + const token = await testServer.restlessAgent.post('/oauth/token').type('form').send({ + grant_type: 'authorization_code', + code, + code_verifier: verifier, + client_id: clientId, + redirect_uri: REDIRECT_URI, + resource, + }); + return { approval, token }; +} + +const api = () => testServer.publicApiAgentWithoutApiKey(); + +describe('Public API access from a consent-scoped token', () => { + test('advertises the API key scopes and the instance as authorization server for /api/v1', async () => { + const metadata = await testServer.restlessAgent + .get('/.well-known/oauth-protected-resource/api/v1') + .expect(200); + + expect(metadata.body).toMatchObject({ + resource, + authorization_servers: [Container.get(UrlService).getInstanceBaseUrl()], + scopes_supported: expect.arrayContaining(['tag:list', 'tag:create']), + }); + }); + + test('a token granted tag:list can list tags but cannot create one', async () => { + const { token } = await consentAndExchange(owner, ['tag:list']); + expect(token?.statusCode).toBe(200); + const accessToken = token!.body.access_token as string; + expect(jwtService.decodeUnverified(accessToken)).toMatchObject({ + aud: resource, + sub: owner.id, + scope: 'tag:list', + }); + + const listed = await api().get('/tags').set('Authorization', `Bearer ${accessToken}`); + const created = await api() + .post('/tags') + .set('Authorization', `Bearer ${accessToken}`) + .send({ name: 'oauth' }); + + expect(listed.statusCode).toBe(200); + expect(created.statusCode).toBe(403); + expect(await Container.get(TagRepository).count()).toBe(0); + }); + + test('a token granted tag:list and tag:create can do both', async () => { + const { token } = await consentAndExchange(owner, ['tag:list', 'tag:create']); + const accessToken = token!.body.access_token as string; + + const created = await api() + .post('/tags') + .set('Authorization', `Bearer ${accessToken}`) + .send({ name: 'oauth' }); + const listed = await api().get('/tags').set('Authorization', `Bearer ${accessToken}`); + + expect(created.statusCode).toBe(201); + expect(listed.statusCode).toBe(200); + expect(listed.body.data).toHaveLength(1); + }); + + test('the consent screen refuses a scope the client did not request', async () => { + const { approval } = await consentAndExchange(owner, ['tag:create'], ['tag:list']); + + expect(approval.statusCode).toBe(400); + }); + + test('the consent screen refuses a scope the user cannot grant', async () => { + const { approval } = await consentAndExchange(member, ['tag:list', 'user:create']); + + expect(approval.statusCode).toBe(400); + }); + + test('a refreshed token keeps the granted scopes', async () => { + const { token } = await consentAndExchange(owner, ['tag:list']); + const clientId = jwtService.decodeUnverified(token!.body.access_token as string).client_id; + + const refreshed = await testServer.restlessAgent.post('/oauth/token').type('form').send({ + grant_type: 'refresh_token', + refresh_token: token!.body.refresh_token, + client_id: clientId, + scope: 'tag:list tag:create', + }); + expect(refreshed.statusCode).toBe(200); + const accessToken = refreshed.body.access_token as string; + expect(jwtService.decodeUnverified(accessToken).scope).toBe('tag:list'); + + const created = await api() + .post('/tags') + .set('Authorization', `Bearer ${accessToken}`) + .send({ name: 'oauth' }); + + expect(created.statusCode).toBe(403); + }); +}); diff --git a/packages/cli/test/integration/public-api/unmatched-routes.test.ts b/packages/cli/test/integration/public-api/unmatched-routes.test.ts new file mode 100644 index 00000000000..5f6df72b799 --- /dev/null +++ b/packages/cli/test/integration/public-api/unmatched-routes.test.ts @@ -0,0 +1,63 @@ +import type { User } from '@n8n/db'; + +import { createMemberWithApiKey } from '../shared/db/users'; +import type { SuperAgentTest } from '../shared/types'; +import * as utils from '../shared/utils/'; + +let member: User; +let authMemberAgent: SuperAgentTest; + +const testServer = utils.setupTestServer({ endpointGroups: ['publicApi'] }); + +beforeAll(async () => { + member = await createMemberWithApiKey(); +}); + +beforeEach(() => { + authMemberAgent = testServer.publicApiAgentFor(member); +}); + +describe('paths and methods the public API does not serve', () => { + test('returns 404 for an unknown path with a valid API key', async () => { + const response = await authMemberAgent.get('/this-path-does-not-exist'); + + expect(response.statusCode).toBe(404); + expect(response.body).toEqual({ message: 'not found' }); + }); + + test('returns 404 for an unknown path without an API key', async () => { + const response = await testServer + .publicApiAgentWithoutApiKey() + .get('/this-path-does-not-exist'); + + expect(response.statusCode).toBe(404); + expect(response.body).toEqual({ message: 'not found' }); + }); + + test('returns 405 for a known path with a method it does not serve', async () => { + const response = await authMemberAgent.put('/tags'); + + expect(response.statusCode).toBe(405); + expect(response.body).toEqual({ message: 'PUT method not allowed' }); + }); + + test('returns 405 before authentication for a known path with an unserved method', async () => { + const response = await testServer.publicApiAgentWithoutApiKey().put('/tags'); + + expect(response.statusCode).toBe(405); + expect(response.body).toEqual({ message: 'PUT method not allowed' }); + }); + + test('returns 405 for a parameterized known path with a method it does not serve', async () => { + const response = await authMemberAgent.patch('/tags/some-tag-id'); + + expect(response.statusCode).toBe(405); + expect(response.body).toEqual({ message: 'PATCH method not allowed' }); + }); + + test('returns 401 for a served route without an API key', async () => { + const response = await testServer.publicApiAgentWithoutApiKey().get('/tags'); + + expect(response.statusCode).toBe(401); + }); +}); diff --git a/packages/cli/test/integration/scheduling/agent-task-multi-main.test.ts b/packages/cli/test/integration/scheduling/agent-task-multi-main.test.ts index da94904d108..d6183a0298a 100644 --- a/packages/cli/test/integration/scheduling/agent-task-multi-main.test.ts +++ b/packages/cli/test/integration/scheduling/agent-task-multi-main.test.ts @@ -75,7 +75,6 @@ describe('agent tasks across two mains over one database', () => { schema: { name: 'Scheduled agent', model: 'm', instructions: 'i' }, integrations: [], tools: {}, - skills: {}, versionId, activeVersionId: null, } as Partial), @@ -86,7 +85,6 @@ describe('agent tasks across two mains over one database', () => { author: 'test', schema: null, tools: null, - skills: null, }); await snapshotRepo.saveForVersion([ { diff --git a/packages/cli/test/integration/scheduling/license-renewal-multi-main.test.ts b/packages/cli/test/integration/scheduling/license-renewal-multi-main.test.ts index 961a8f195f9..cbc83cb424d 100644 --- a/packages/cli/test/integration/scheduling/license-renewal-multi-main.test.ts +++ b/packages/cli/test/integration/scheduling/license-renewal-multi-main.test.ts @@ -24,7 +24,10 @@ import { Publisher } from '@/scaling/pubsub/publisher.service'; import { DurableJobProvisioner } from '@/scheduling/durable-job-provisioner'; import { buildMaterializerTransaction } from '@/scheduling/durable-scheduler'; import { SystemTaskHandler } from '@/scheduling/system-tasks/system-task-handler'; -import { systemTaskProvisionRequest } from '@/scheduling/system-tasks/system-task-job-registrar'; +import { + systemTaskProvisionRequest, + durableSystemTask, +} from '@/scheduling/system-tasks/system-task-job-registrar'; import { SystemTaskScheduledJobOwner } from '@/scheduling/system-tasks/system-task-scheduled-job-owner'; import { systemTaskType } from '@/scheduling/system-tasks/system-task-type'; @@ -208,7 +211,9 @@ describe('license renewal across two mains over one database', () => { /** The provision seeds the first occurrence of an interval task at `now`, so it is due at once. */ const provisionDueOccurrence = async (task: LicenseRenewalTask): Promise => { - await provisioner.provision(systemTaskProvisionRequest(task, owner, 'UTC', new Date())); + await provisioner.provision( + systemTaskProvisionRequest(durableSystemTask(task), owner, 'UTC', new Date()), + ); return await taskRepo.findOneByOrFail({ taskType: TASK_TYPE }); }; diff --git a/packages/cli/test/integration/scheduling/system-task-provisioning.test.ts b/packages/cli/test/integration/scheduling/system-task-provisioning.test.ts index 68d76a6c077..3f9bc53d277 100644 --- a/packages/cli/test/integration/scheduling/system-task-provisioning.test.ts +++ b/packages/cli/test/integration/scheduling/system-task-provisioning.test.ts @@ -5,7 +5,7 @@ import { GlobalConfig } from '@n8n/config'; import { ScheduledJobMisfirePolicy, ScheduledJobOwnerType } from '@n8n/constants'; import { ScheduledJobRepository, ScheduledTaskRepository } from '@n8n/db'; import { Container } from '@n8n/di'; -import type { SystemTask, SystemTaskSchedule } from '@n8n/decorators'; +import type { SchedulerOptions, SystemTask, SystemTaskSchedule } from '@n8n/decorators'; import { UnregisteredOwnerTypeError } from '@n8n/scheduler'; import { ErrorReporter } from 'n8n-core'; import { inc } from 'semver'; @@ -15,6 +15,7 @@ import { DurableJobProvisioner } from '@/scheduling/durable-job-provisioner'; import { SystemTaskJobRegistrar, systemTaskProvisionRequest, + durableSystemTask, } from '@/scheduling/system-tasks/system-task-job-registrar'; import { SystemTaskScheduledJobOwner } from '@/scheduling/system-tasks/system-task-scheduled-job-owner'; @@ -35,17 +36,19 @@ describe('system task provisioning', () => { let provisioner: DurableJobProvisioner; let registrar: SystemTaskJobRegistrar; - const task = (over: Partial = {}): SystemTask => ({ + type TaskOverrides = { schedule?: SystemTaskSchedule; scheduler?: Partial }; + + const task = ({ schedule, scheduler }: TaskOverrides = {}): SystemTask => ({ name: TASK_NAME, - schedule: { kind: 'interval', intervalSeconds: 60 }, - effects: 'idempotent', - placement: { scope: 'cluster', durable: true }, + schedule: schedule ?? { kind: 'interval', intervalSeconds: 60 }, + target: { scope: 'cluster', scheduler: { retryOnFailure: true, ...scheduler } }, run: async () => {}, - ...over, }); - const provision = async (over: Partial = {}) => - await provisioner.provision(systemTaskProvisionRequest(task(over), owner, 'UTC', new Date())); + const provision = async (over: TaskOverrides = {}) => + await provisioner.provision( + systemTaskProvisionRequest(durableSystemTask(task(over)), owner, 'UTC', new Date()), + ); beforeAll(async () => { await testDb.init(); @@ -103,7 +106,7 @@ describe('system task provisioning', () => { { status: 'running', claimedBy: 'main-a', leaseExpiresAt: new Date(Date.now() + 60_000) }, ); - const summary = await provision({ schedule, timeoutSeconds: 600 }); + const summary = await provision({ schedule, scheduler: { timeoutSeconds: 600 } }); expect(summary.unchanged).toEqual([{ id: inserted.id, name: JOB_NAME }]); const row = await jobRepo.findOneByOrFail({ name: JOB_NAME }); @@ -168,21 +171,24 @@ describe('system task provisioning', () => { }); it.each([ - ['permits overlap', null], - ['raises the ceiling', 4], - ])('stores the concurrency limit a task declares when it %s', async (_case, concurrencyLimit) => { - await provision({ concurrencyLimit }); + ['permits overlap', 'unlimited', null], + ['raises the ceiling', 4, 4], + ] as const)( + 'stores the concurrency limit a task declares when it %s', + async (_case, concurrencyLimit, stored) => { + await provision({ scheduler: { concurrencyLimit } }); - const row = await jobRepo.findOneByOrFail({ name: JOB_NAME }); - expect(row.concurrencyLimit).toBe(concurrencyLimit); - }); + const row = await jobRepo.findOneByOrFail({ name: JOB_NAME }); + expect(row.concurrencyLimit).toBe(stored); + }, + ); it('reconciles a changed concurrency limit on an unchanged cadence', async () => { await provision(); const inserted = await jobRepo.findOneByOrFail({ name: JOB_NAME }); expect(inserted.concurrencyLimit).toBe(1); - const summary = await provision({ concurrencyLimit: null }); + const summary = await provision({ scheduler: { concurrencyLimit: 'unlimited' } }); expect(summary.unchanged).toEqual([{ id: inserted.id, name: JOB_NAME }]); const row = await jobRepo.findOneByOrFail({ name: JOB_NAME }); @@ -195,7 +201,7 @@ describe('system task provisioning', () => { const inserted = await jobRepo.findOneByOrFail({ name: JOB_NAME }); expect(inserted.maxAttempts).toBe(3); - const summary = await provision({ maxAttempts: 1 }); + const summary = await provision({ scheduler: { retryOnFailure: false } }); expect(summary.unchanged).toEqual([{ id: inserted.id, name: JOB_NAME }]); const row = await jobRepo.findOneByOrFail({ name: JOB_NAME }); @@ -242,7 +248,9 @@ describe('system task provisioning', () => { Container.get(ErrorReporter), Container.get(EventService), ); - await provisioner.provision(systemTaskProvisionRequest(task(), booting, 'UTC', new Date())); + await provisioner.provision( + systemTaskProvisionRequest(durableSystemTask(task()), booting, 'UTC', new Date()), + ); await store('from-a-newer-version', inc(N8N_VERSION, 'minor') as string); const older = await store('from-an-older-version', '0.0.1'); diff --git a/packages/cli/test/integration/shared/types.ts b/packages/cli/test/integration/shared/types.ts index 4e267d5bc95..ec325c0fe60 100644 --- a/packages/cli/test/integration/shared/types.ts +++ b/packages/cli/test/integration/shared/types.ts @@ -60,6 +60,7 @@ type EndpointGroup = | 'third-party-licenses' | 'mcp' | 'workflowDependencies' + | 'trusted-sources' | 'encryption-keys' | 'workflow-reviews' | 'test-webhooks' diff --git a/packages/cli/test/integration/shared/utils/index.ts b/packages/cli/test/integration/shared/utils/index.ts index 9bd83bb2d05..93b0ac48ce5 100644 --- a/packages/cli/test/integration/shared/utils/index.ts +++ b/packages/cli/test/integration/shared/utils/index.ts @@ -121,7 +121,7 @@ export function createDeprecatedNodeType(name: string): INodeType { return type as INodeType; } -function buildDefaultNodes(): INodeTypeData { +export function buildDefaultNodes(): INodeTypeData { ScheduleTrigger.prototype.trigger = async () => ({}); return { 'n8n-nodes-base.manualTrigger': { diff --git a/packages/cli/test/integration/shared/utils/test-server.ts b/packages/cli/test/integration/shared/utils/test-server.ts index c3d7f1034ba..2f329470ea3 100644 --- a/packages/cli/test/integration/shared/utils/test-server.ts +++ b/packages/cli/test/integration/shared/utils/test-server.ts @@ -428,6 +428,10 @@ export const setupTestServer = ({ await import('@/modules/encryption-key-manager/encryption-key.controller.js'); break; + case 'trusted-sources': + await import('@/modules/inbound-auth-core/trusted-source.controller.js'); + break; + case 'test-webhooks': await import('@/webhooks/test-webhooks.controller.js'); break; diff --git a/packages/cli/test/integration/token-exchange/token-exchange.controller.test.ts b/packages/cli/test/integration/token-exchange/token-exchange.controller.test.ts index 23aaaa9a3ca..07480fd3608 100644 --- a/packages/cli/test/integration/token-exchange/token-exchange.controller.test.ts +++ b/packages/cli/test/integration/token-exchange/token-exchange.controller.test.ts @@ -14,7 +14,7 @@ import { type IssuedJwtPayload, type TokenExchangeSuccessResponse, } from '@/modules/token-exchange/token-exchange.types'; -import { JwtService } from '@/services/jwt.service'; +import { JwtService } from '@n8n/backend-services'; import { createUser } from '../shared/db/users'; import * as utils from '../shared/utils'; diff --git a/packages/cli/test/integration/workflow-history-compaction-optimize.task.test.ts b/packages/cli/test/integration/workflow-history-compaction-optimize.task.test.ts index 38308121b50..d762a8c7afb 100644 --- a/packages/cli/test/integration/workflow-history-compaction-optimize.task.test.ts +++ b/packages/cli/test/integration/workflow-history-compaction-optimize.task.test.ts @@ -2,11 +2,10 @@ import type { EventService } from '@n8n/backend-services'; import { createWorkflow, createWorkflowHistory, mockLogger, testDb } from '@n8n/backend-test-utils'; import { GlobalConfig } from '@n8n/config'; import { Time } from '@n8n/constants'; -import { DbConnection, WorkflowHistoryRepository } from '@n8n/db'; +import { WorkflowHistoryRepository } from '@n8n/db'; import { Container } from '@n8n/di'; import { createDeferredPromise } from '@n8n/utils/promise/deferred-promise'; import repeat from 'lodash/repeat'; -import type { InstanceSettings } from 'n8n-core'; import type { INode } from 'n8n-workflow'; import { v4 as uuid } from 'uuid'; import { mock } from 'vitest-mock-extended'; @@ -93,8 +92,6 @@ describe('WorkflowHistoryCompactionOptimizeTask', () => { config, globalConfig, logger, - mock({ instanceType: 'main', isLeader: false }), - Container.get(DbConnection), repository, eventService, ); diff --git a/packages/cli/test/integration/workflow-history-compaction-trim.task.test.ts b/packages/cli/test/integration/workflow-history-compaction-trim.task.test.ts index d4a1f080750..292826524e7 100644 --- a/packages/cli/test/integration/workflow-history-compaction-trim.task.test.ts +++ b/packages/cli/test/integration/workflow-history-compaction-trim.task.test.ts @@ -3,11 +3,10 @@ import type { EventService } from '@n8n/backend-services'; import { createWorkflow, createWorkflowHistory, mockLogger, testDb } from '@n8n/backend-test-utils'; import { GlobalConfig } from '@n8n/config'; import { Time } from '@n8n/constants'; -import { DbConnection, WorkflowHistoryRepository } from '@n8n/db'; +import { WorkflowHistoryRepository } from '@n8n/db'; import { Container } from '@n8n/di'; import { createDeferredPromise } from '@n8n/utils/promise/deferred-promise'; import { DateTime } from 'luxon'; -import type { InstanceSettings } from 'n8n-core'; import type { INode } from 'n8n-workflow'; import { v4 as uuid } from 'uuid'; import { mock } from 'vitest-mock-extended'; @@ -62,8 +61,6 @@ describe('WorkflowHistoryCompactionTrimTask', () => { { ...globalConfig.workflowHistoryCompaction, batchDelayMs: 0 }, globalConfig, logger, - mock({ instanceType: 'main', isLeader: false }), - Container.get(DbConnection), repository, mock(), ); diff --git a/packages/cli/test/integration/workflow-history-compaction.service.test.ts b/packages/cli/test/integration/workflow-history-compaction.service.test.ts index 73a8c519aa7..379f59978f1 100644 --- a/packages/cli/test/integration/workflow-history-compaction.service.test.ts +++ b/packages/cli/test/integration/workflow-history-compaction.service.test.ts @@ -2,11 +2,10 @@ import { EventService } from '@n8n/backend-services'; import { mockLogger, createWorkflow, testDb, createWorkflowHistory } from '@n8n/backend-test-utils'; import { GlobalConfig } from '@n8n/config'; import { Time } from '@n8n/constants'; -import { DbConnection, WorkflowHistoryRepository } from '@n8n/db'; +import { WorkflowHistoryRepository } from '@n8n/db'; import { Container } from '@n8n/di'; import { sleep } from '@n8n/utils/sleep'; import repeat from 'lodash/repeat'; -import { InstanceSettings } from 'n8n-core'; import type { INode } from 'n8n-workflow'; import { v4 as uuid } from 'uuid'; @@ -14,8 +13,6 @@ import { WorkflowHistoryCompactionService } from '@/services/pruning/workflow-hi describe('compacting cycle', () => { let compactionService: WorkflowHistoryCompactionService; - const instanceSettings = Container.get(InstanceSettings); - instanceSettings.markAsLeader(); const now = Date.now(); // before minimum compacting age @@ -64,8 +61,6 @@ describe('compacting cycle', () => { Container.get(GlobalConfig).workflowHistoryCompaction, Container.get(GlobalConfig), mockLogger(), - instanceSettings, - Container.get(DbConnection), Container.get(WorkflowHistoryRepository), Container.get(EventService), ); @@ -199,8 +194,6 @@ describe('compacting cycle', () => { }, Container.get(GlobalConfig), mockLogger(), - instanceSettings, - Container.get(DbConnection), Container.get(WorkflowHistoryRepository), Container.get(EventService), ); diff --git a/packages/cli/test/integration/workflow-statistics-rollup.task.test.ts b/packages/cli/test/integration/workflow-statistics-rollup.task.test.ts index 6db0a7c112d..0207f8996ad 100644 --- a/packages/cli/test/integration/workflow-statistics-rollup.task.test.ts +++ b/packages/cli/test/integration/workflow-statistics-rollup.task.test.ts @@ -108,16 +108,11 @@ describe.skipIf(!isPostgres)('WorkflowStatisticsRollupTask', () => { await seedIncrements(); const { lockSkips } = holdFirstFoldUntilLockSkip(); - await Promise.all( - Array.from( - { length: OVERLAPPING_RUNS }, - async () => await task.run(signal, { durable: true }), - ), - ); + await Promise.all(Array.from({ length: OVERLAPPING_RUNS }, async () => await task.run(signal))); expect(lockSkips()).toBeGreaterThan(0); // A run that lost the lock stops early, so finish any backlog it left. while ((await pendingIncrements()) > 0) { - await task.run(signal, { durable: true }); + await task.run(signal); } const counters = await repository.findBy({ name: StatisticsNames.productionSuccess }); diff --git a/packages/cli/test/integration/workflows/teams-trigger-subscription-refused.test.ts b/packages/cli/test/integration/workflows/teams-trigger-subscription-refused.test.ts new file mode 100644 index 00000000000..37c0c220a3a --- /dev/null +++ b/packages/cli/test/integration/workflows/teams-trigger-subscription-refused.test.ts @@ -0,0 +1,244 @@ +import { LicenseState } from '@n8n/backend-common'; +import { + createWorkflowWithHistory, + mockInstance, + setActiveVersion, + testDb, +} from '@n8n/backend-test-utils'; +import { GlobalConfig, WorkflowsConfig } from '@n8n/config'; +import { + WorkflowPublicationOutboxRepository, + WorkflowPublicationTriggerStatusRepository, + WorkflowRepository, +} from '@n8n/db'; +import { Container } from '@n8n/di'; +import { ExternalSecretsProxy, InstanceSettings } from 'n8n-core'; +import { MicrosoftOAuth2Api } from 'n8n-nodes-base/credentials/MicrosoftOAuth2Api.credentials'; +import { MicrosoftTeamsOAuth2Api } from 'n8n-nodes-base/credentials/MicrosoftTeamsOAuth2Api.credentials'; +import { OAuth2Api } from 'n8n-nodes-base/credentials/OAuth2Api.credentials'; +import { MicrosoftTeamsTrigger } from 'n8n-nodes-base/nodes/Microsoft/Teams/MicrosoftTeamsTrigger.node'; +import type { INode, INodeTypeData } from 'n8n-workflow'; +import nock from 'nock'; +import { v4 as uuid } from 'uuid'; + +import { ActivationErrorsService } from '@/activation-errors.service'; +import { ActiveExecutions } from '@/active-executions'; +import { ActiveWorkflowManager } from '@/active-workflow-manager'; +import { ExecutionService } from '@/executions/execution.service'; +import { ExternalHooks } from '@/external-hooks'; +import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials'; +import { Push } from '@/push'; +import { ActiveWorkflowsService } from '@/services/active-workflows.service'; +import { OwnershipService } from '@/services/ownership.service'; +import { Telemetry } from '@/telemetry'; +import { WorkflowPublicationOutboxConsumer } from '@/workflows/publication/workflow-publication-outbox-consumer'; +import { WorkflowPublicationStatusService } from '@/workflows/publication/workflow-publication-status.service'; +import { WorkflowService } from '@/workflows/workflow.service'; + +import { saveCredential } from '../shared/db/credentials'; +import { createOwner } from '../shared/db/users'; +import { LicenseMocker } from '../shared/license'; +import * as utils from '../shared/utils/'; + +// The activation retries back off 1+2+4+8 s between the five attempts. +vi.mock('@n8n/utils/sleep', () => ({ sleep: vi.fn() })); + +/** + * ENT-497: a Microsoft Teams Trigger whose Graph subscription is refused (403) + * on `POST /subscriptions`. The node throws on both activation paths; what + * differs is where the failure is recorded. The legacy path rejects the + * activation and registers the error. The publication path (the default) keeps + * the workflow `active`, records the failure as a trigger status plus a push, + * never writes the legacy store, and the legacy activation API reads that + * status: the workflow is absent from the active list and its activation error + * is the Graph error. + */ + +mockInstance(ActiveExecutions); +const push = mockInstance(Push); +mockInstance(ExternalSecretsProxy); +mockInstance(ExecutionService); +mockInstance(WorkflowService); +mockInstance(OwnershipService); +mockInstance(ExternalHooks); +mockInstance(Telemetry); + +const GRAPH = 'https://graph.microsoft.com'; +const TEAM_ID = '61165b04-e4cc-4026-b43f-926b4e2a7182'; +const GRAPH_ERROR = 'Operation: Create; Exception: [Status Code: Forbidden; Reason: Forbidden]'; + +let consumer: WorkflowPublicationOutboxConsumer; +let activeWorkflowManager: ActiveWorkflowManager; +let outboxRepository: WorkflowPublicationOutboxRepository; +let workflowRepository: WorkflowRepository; +let activationErrorsService: ActivationErrorsService; +let originalFlag: boolean; +let originalWebhookUrl: string; + +beforeAll(async () => { + await testDb.init(); + + const nodes: INodeTypeData = { + 'n8n-nodes-base.microsoftTeamsTrigger': { type: new MicrosoftTeamsTrigger(), sourcePath: '' }, + }; + await utils.initNodeTypes(nodes); + // The whole `extends` chain, so the stored credential resolves its defaults. + Container.get(LoadNodesAndCredentials).loaded.credentials = { + oAuth2Api: { type: new OAuth2Api(), sourcePath: '' }, + microsoftOAuth2Api: { type: new MicrosoftOAuth2Api(), sourcePath: '' }, + microsoftTeamsOAuth2Api: { type: new MicrosoftTeamsOAuth2Api(), sourcePath: '' }, + }; + + // Decrypting a credential consults the license state (external secrets). + new LicenseMocker().mockLicenseState(Container.get(LicenseState)); + + // The trigger refuses a non-HTTPS notification URL before it calls Graph. + const globalConfig = Container.get(GlobalConfig); + originalWebhookUrl = globalConfig.webhookUrl; + globalConfig.webhookUrl = 'https://n8n.example.com/'; + + Container.get(InstanceSettings).markAsLeader(); + originalFlag = Container.get(WorkflowsConfig).useWorkflowPublicationService; + + consumer = Container.get(WorkflowPublicationOutboxConsumer); + activeWorkflowManager = Container.get(ActiveWorkflowManager); + outboxRepository = Container.get(WorkflowPublicationOutboxRepository); + workflowRepository = Container.get(WorkflowRepository); + activationErrorsService = Container.get(ActivationErrorsService); +}); + +afterEach(async () => { + nock.cleanAll(); + push.sendToUsers.mockClear(); + await activeWorkflowManager.removeAll(); + await activationErrorsService.clearAll(); + await testDb.truncate([ + 'WorkflowPublishedVersion', + 'WorkflowPublicationOutbox', + 'WorkflowPublicationTriggerStatus', + 'WorkflowPublishHistory', + 'WorkflowEntity', + 'WorkflowHistory', + 'WebhookEntity', + 'SharedCredentials', + 'CredentialsEntity', + 'User', + ]); +}); + +afterAll(async () => { + Container.get(WorkflowsConfig).useWorkflowPublicationService = originalFlag; + Container.get(GlobalConfig).webhookUrl = originalWebhookUrl; + await testDb.terminate(); +}); + +/** `checkExists` lists subscriptions first; `persist` covers the activation retries. */ +const mockGraphRefusingSubscription = () => + nock(GRAPH) + .persist() + .get('/v1.0/subscriptions') + .reply(200, { value: [] }) + .post('/v1.0/subscriptions') + .reply(403, { error: { code: 'ExtensionError', message: GRAPH_ERROR } }); + +async function createTeamsTriggerWorkflow() { + const owner = await createOwner(); + const credential = await saveCredential( + { + name: 'Teams', + type: 'microsoftTeamsOAuth2Api', + data: { + clientId: 'client-id', + clientSecret: 'client-secret', + oauthTokenData: { access_token: 'access-token', token_type: 'Bearer' }, + }, + }, + { user: owner, role: 'credential:owner' }, + ); + + const trigger: INode = { + id: 'teams-trigger', + name: 'Microsoft Teams Trigger', + type: 'n8n-nodes-base.microsoftTeamsTrigger', + typeVersion: 1, + position: [0, 0], + webhookId: uuid(), + parameters: { + authentication: 'microsoftTeamsOAuth2Api', + event: 'newTeamMember', + watchAllTeams: false, + teamId: { __rl: true, mode: 'id', value: TEAM_ID }, + }, + credentials: { microsoftTeamsOAuth2Api: { id: credential.id, name: credential.name } }, + }; + + const workflow = await createWorkflowWithHistory({ active: true, nodes: [trigger] }, owner); + await setActiveVersion(workflow.id, workflow.versionId); + return { workflow, trigger, owner }; +} + +describe('Microsoft Teams Trigger: Graph refuses the subscription', () => { + test('legacy path: activation rejects with the Graph error and registers it', async () => { + Container.get(WorkflowsConfig).useWorkflowPublicationService = false; + const scope = mockGraphRefusingSubscription(); + const { workflow } = await createTeamsTriggerWorkflow(); + + await expect(activeWorkflowManager.add(workflow.id, 'activate')).rejects.toThrow(GRAPH_ERROR); + + expect(scope.isDone()).toBe(true); + expect(await activationErrorsService.get(workflow.id)).toBe(GRAPH_ERROR); + }); + + test('publication path: the failure reaches the publication surfaces and the legacy activation API', async () => { + Container.get(WorkflowsConfig).useWorkflowPublicationService = true; + const scope = mockGraphRefusingSubscription(); + const { workflow, trigger, owner } = await createTeamsTriggerWorkflow(); + + await outboxRepository.enqueue(workflow.id, workflow.versionId, 'publish'); + const record = await outboxRepository.claimNextPendingRecord(); + expect(record).not.toBeNull(); + + await consumer.processRecord(record!, new AbortController().signal); + + expect(scope.isDone()).toBe(true); + + // Recorded: outbox record, per-trigger status, status endpoint, UI push. + expect(await outboxRepository.findOneBy({ id: record!.id })).toMatchObject({ + status: 'failed', + errorMessage: GRAPH_ERROR, + }); + const triggerRows = await Container.get( + WorkflowPublicationTriggerStatusRepository, + ).findByWorkflowId(workflow.id); + expect(triggerRows).toEqual([ + expect.objectContaining({ nodeId: trigger.id, status: 'failed', errorMessage: GRAPH_ERROR }), + ]); + expect( + await Container.get(WorkflowPublicationStatusService).getStatus(workflow.id), + ).toMatchObject({ + status: 'failed', + liveVersionId: null, + triggers: [{ nodeId: trigger.id, status: 'failed', errorMessage: GRAPH_ERROR }], + }); + expect(push.sendToUsers).toHaveBeenCalledWith( + { + type: 'workflowFailedToActivate', + data: { workflowId: workflow.id, errorMessage: GRAPH_ERROR, nodeId: trigger.id }, + }, + [owner.id], + ); + + // Not recorded: the workflow stays active and the legacy surfaces stay clean. + expect(await workflowRepository.findById(workflow.id)).toMatchObject({ + active: true, + activeVersionId: workflow.versionId, + }); + expect(await activationErrorsService.get(workflow.id)).toBeNull(); + + // The legacy activation API reads the trigger status. + const activeWorkflowsService = Container.get(ActiveWorkflowsService); + expect(await activeWorkflowsService.getAllActiveIdsInStorage()).toEqual([]); + expect(await activeWorkflowsService.getAllActiveIdsFor(owner)).toEqual([]); + expect(await activeWorkflowsService.getActivationError(workflow.id, owner)).toBe(GRAPH_ERROR); + }); +}); diff --git a/packages/cli/test/integration/workflows/workflow-dependency.controller.test.ts b/packages/cli/test/integration/workflows/workflow-dependency.controller.test.ts index edd8b85f184..710015ea3cb 100644 --- a/packages/cli/test/integration/workflows/workflow-dependency.controller.test.ts +++ b/packages/cli/test/integration/workflows/workflow-dependency.controller.test.ts @@ -95,7 +95,6 @@ async function seedIndexedAgent( }), integrations: [], tools: {}, - skills: {}, versionId: 'draft-version-1', }); await agentRepo.save(agent); @@ -106,7 +105,6 @@ async function seedIndexedAgent( agentId: agent.id, schema: agent.schema, tools: agent.tools, - skills: agent.skills, publishedBy: user, }); agent.activeVersionId = publishedVersionId; diff --git a/packages/cli/test/integration/workflows/workflow-sharing.service.test.ts b/packages/cli/test/integration/workflows/workflow-sharing.service.test.ts index aa3ba26e63c..e864869de05 100644 --- a/packages/cli/test/integration/workflows/workflow-sharing.service.test.ts +++ b/packages/cli/test/integration/workflows/workflow-sharing.service.test.ts @@ -115,6 +115,33 @@ describe('WorkflowSharingService', () => { expect(sharedWorkflowIds).toContain(workflow1.id); expect(sharedWorkflowIds).not.toContain(workflow2.id); }); + + it('should only show workflows of the given project to users', async () => { + const projectA = await projectService.createTeamProject(member, { name: 'Project A' }); + const projectB = await projectService.createTeamProject(member, { name: 'Project B' }); + + await Promise.all([ + projectService.addUser(projectA.id, { + userId: anotherMember.id, + role: 'project:admin', + }), + projectService.addUser(projectB.id, { + userId: anotherMember.id, + role: 'project:admin', + }), + ]); + + const workflowA = await createWorkflow(undefined, projectA); + const workflowB = await createWorkflow(undefined, projectB); + + const sharedWorkflowIds = await workflowSharingService.getSharedWorkflowIds(anotherMember, { + scopes: ['workflow:read'], + projectId: projectA.id, + }); + + expect(sharedWorkflowIds).toEqual([workflowA.id]); + expect(sharedWorkflowIds).not.toContain(workflowB.id); + }); }); describe('getUserIdsWithAccessToWorkflow', () => { diff --git a/packages/cli/test/integration/workflows/workflow.service.ee.test.ts b/packages/cli/test/integration/workflows/workflow.service.ee.test.ts index 2ea048c719c..ff3f76e42b9 100644 --- a/packages/cli/test/integration/workflows/workflow.service.ee.test.ts +++ b/packages/cli/test/integration/workflows/workflow.service.ee.test.ts @@ -43,6 +43,7 @@ describe('EnterpriseWorkflowService', () => { mock(), // workflowPublishHistoryRepository mock(), // workflowMutationHooks mock(), // policyEnforcementService + mock(), // nodeTypes mock(), // credentialsPermissionChecker ); }); diff --git a/packages/cli/test/integration/workflows/workflow.service.test.ts b/packages/cli/test/integration/workflows/workflow.service.test.ts index 99b92824676..6b09fadbff3 100644 --- a/packages/cli/test/integration/workflows/workflow.service.test.ts +++ b/packages/cli/test/integration/workflows/workflow.service.test.ts @@ -29,6 +29,8 @@ import { v4 as uuid } from 'uuid'; import { mock } from 'vitest-mock-extended'; import { ActiveWorkflowManager } from '@/active-workflow-manager'; +import { SubworkflowPolicyDenialError } from '@/errors/subworkflow-policy-denial.error'; +import { SubworkflowPolicyChecker } from '@/executions/pre-execution-checks/subworkflow-policy-checker'; import type { ExternalHooks } from '@/external-hooks'; import { MessageEventBus } from '@/eventbus/message-event-bus/message-event-bus'; import { NodeTypes } from '@/node-types'; @@ -1459,3 +1461,227 @@ describe('publishAsSystem()', () => { expect(workflowPublicationNotifier.requestDrain).not.toHaveBeenCalled(); }); }); + +describe('delete() and the workflowsFromAList caller policy', () => { + test('denies a caller whose allowlist entry no longer refers to a live workflow', async () => { + const owner = await createOwner(); + const member = await createMember(); + + const allowlistedCaller = await createWorkflow({}, owner); + const subworkflow = await createWorkflow( + { + settings: { callerPolicy: 'workflowsFromAList', callerIds: allowlistedCaller.id }, + }, + owner, + ); + + await workflowService.archive(owner, allowlistedCaller.id); + await workflowService.delete(owner, allowlistedCaller.id); + + const reusedIdWorkflow = await createWorkflow({ id: allowlistedCaller.id }, member); + + const storedSubworkflow = await workflowRepository.findOneByOrFail({ id: subworkflow.id }); + + await expect( + Container.get(SubworkflowPolicyChecker).check( + { id: storedSubworkflow.id, settings: storedSubworkflow.settings }, + reusedIdWorkflow.id, + ), + ).rejects.toThrowError(SubworkflowPolicyDenialError); + }); + + test('keeps the allowlist entry while the caller is only archived', async () => { + const owner = await createOwner(); + + const allowlistedCaller = await createWorkflow({}, owner); + const callerIds = `keepMe,\n${allowlistedCaller.id}`; + const subworkflow = await createWorkflow( + { settings: { callerPolicy: 'workflowsFromAList', callerIds } }, + owner, + ); + + await workflowService.archive(owner, allowlistedCaller.id); + + const afterArchive = await workflowRepository.findOneByOrFail({ id: subworkflow.id }); + expect(afterArchive.settings).toEqual({ callerPolicy: 'workflowsFromAList', callerIds }); + + await workflowService.delete(owner, allowlistedCaller.id); + + const afterDelete = await workflowRepository.findOneByOrFail({ id: subworkflow.id }); + expect(afterDelete.settings).toEqual({ + callerPolicy: 'workflowsFromAList', + callerIds: 'keepMe', + }); + }); + + test('allows a live allowlisted caller owned by another project', async () => { + const owner = await createOwner(); + const member = await createMember(); + + const allowlistedCaller = await createWorkflow({}, member); + const subworkflow = await createWorkflow( + { + settings: { callerPolicy: 'workflowsFromAList', callerIds: allowlistedCaller.id }, + }, + owner, + ); + + const storedSubworkflow = await workflowRepository.findOneByOrFail({ id: subworkflow.id }); + + await expect( + Container.get(SubworkflowPolicyChecker).check( + { id: storedSubworkflow.id, settings: storedSubworkflow.settings }, + allowlistedCaller.id, + ), + ).resolves.toBeUndefined(); + }); + + test('keeps the other settings of an allowlist it rewrites', async () => { + const owner = await createOwner(); + + const caller = await createWorkflow({}, owner); + const subworkflow = await createWorkflow( + { + settings: { + callerPolicy: 'workflowsFromAList', + callerIds: `${caller.id},another-caller`, + executionOrder: 'v1', + timezone: 'Europe/Berlin', + }, + }, + owner, + ); + + await workflowService.archive(owner, caller.id); + await workflowService.delete(owner, caller.id); + + const after = await workflowRepository.findOneByOrFail({ id: subworkflow.id }); + expect(after.settings).toEqual({ + callerPolicy: 'workflowsFromAList', + callerIds: 'another-caller', + executionOrder: 'v1', + timezone: 'Europe/Berlin', + }); + }); + + test('leaves an allowlist alone when the deleted id only appears inside another entry', async () => { + const owner = await createOwner(); + + const caller = await createWorkflow({}, owner); + const subworkflow = await createWorkflow( + { + settings: { + callerPolicy: 'workflowsFromAList', + callerIds: `${caller.id}-suffix, ${caller.id}-other`, + }, + }, + owner, + ); + const before = await workflowRepository.findOneByOrFail({ id: subworkflow.id }); + + await workflowService.archive(owner, caller.id); + await workflowService.delete(owner, caller.id); + + const after = await workflowRepository.findOneByOrFail({ id: subworkflow.id }); + expect(after.settings).toEqual(before.settings); + expect(after.updatedAt).toEqual(before.updatedAt); + }); + + test('takes several deleted ids out of one allowlist', async () => { + const owner = await createOwner(); + + const first = await createWorkflow({}, owner); + const second = await createWorkflow({}, owner); + const subworkflow = await createWorkflow( + { + settings: { + callerPolicy: 'workflowsFromAList', + callerIds: `${first.id},keepMe,${second.id}`, + }, + }, + owner, + ); + + await workflowRepository.removeFromCallerAllowlists([first.id, second.id], {}); + + const after = await workflowRepository.findOneByOrFail({ id: subworkflow.id }); + expect(after.settings).toEqual({ callerPolicy: 'workflowsFromAList', callerIds: 'keepMe' }); + }); + + test('leaves every allowlist untouched when the deleted workflow is on none of them', async () => { + const owner = await createOwner(); + + const allowlistedCaller = await createWorkflow({}, owner); + const subworkflow = await createWorkflow( + { + settings: { + callerPolicy: 'workflowsFromAList', + callerIds: `${allowlistedCaller.id},another-caller`, + }, + }, + owner, + ); + const before = await workflowRepository.findOneByOrFail({ id: subworkflow.id }); + + const unrelatedWorkflow = await createWorkflow({}, owner); + await workflowService.archive(owner, unrelatedWorkflow.id); + await workflowService.delete(owner, unrelatedWorkflow.id); + + const after = await workflowRepository.findOneByOrFail({ id: subworkflow.id }); + expect(after.settings).toEqual(before.settings); + expect(after.updatedAt).toEqual(before.updatedAt); + }); + + // A character the `json` column keeps but the binary JSON form cannot hold. + const NO_BINARY_JSON_FORM = String.fromCharCode(0); + + test('deletes a workflow while an allowlist elsewhere holds a value json alone can carry', async () => { + const owner = await createOwner(); + + const subworkflow = await createWorkflow( + { + settings: { + callerPolicy: 'workflowsFromAList', + callerIds: `another-caller${NO_BINARY_JSON_FORM}`, + }, + }, + owner, + ); + const before = await workflowRepository.findOneByOrFail({ id: subworkflow.id }); + + const unrelatedWorkflow = await createWorkflow({}, owner); + await workflowService.archive(owner, unrelatedWorkflow.id); + await workflowService.delete(owner, unrelatedWorkflow.id); + + await expect(workflowRepository.findOneBy({ id: unrelatedWorkflow.id })).resolves.toBeNull(); + + const after = await workflowRepository.findOneByOrFail({ id: subworkflow.id }); + expect(after.settings).toEqual(before.settings); + }); + + test('rewrites an allowlist that holds a value json alone can carry', async () => { + const owner = await createOwner(); + + const caller = await createWorkflow({}, owner); + const subworkflow = await createWorkflow( + { + settings: { + callerPolicy: 'workflowsFromAList', + callerIds: `${caller.id},another-caller`, + errorWorkflow: `error-workflow${NO_BINARY_JSON_FORM}`, + }, + }, + owner, + ); + + await workflowService.archive(owner, caller.id); + await workflowService.delete(owner, caller.id); + + const after = await workflowRepository.findOneByOrFail({ id: subworkflow.id }); + expect(after.settings).toEqual({ + callerPolicy: 'workflowsFromAList', + callerIds: 'another-caller', + errorWorkflow: `error-workflow${NO_BINARY_JSON_FORM}`, + }); + }); +}); diff --git a/packages/cli/test/integration/workflows/workflows.controller.ee.test.ts b/packages/cli/test/integration/workflows/workflows.controller.ee.test.ts index 280777cdd52..d1f349ee373 100644 --- a/packages/cli/test/integration/workflows/workflows.controller.ee.test.ts +++ b/packages/cli/test/integration/workflows/workflows.controller.ee.test.ts @@ -38,6 +38,7 @@ import { calculateWorkflowChecksum, type INode, } from 'n8n-workflow'; +import { ExecuteWorkflow } from 'n8n-nodes-base/nodes/ExecuteWorkflow/ExecuteWorkflow/ExecuteWorkflow.node'; import { v4 as uuid } from 'uuid'; import { ActiveWorkflowManager } from '@/active-workflow-manager'; @@ -103,7 +104,11 @@ beforeAll(async () => { saveCredential = affixRoleToSaveCredential('credential:owner'); - await utils.initNodeTypes(); + // Use the real node description to test parameter defaults and visibility. + await utils.initNodeTypes({ + ...utils.buildDefaultNodes(), + 'n8n-nodes-base.executeWorkflow': { type: new ExecuteWorkflow(), sourcePath: '' }, + }); }); beforeEach(async () => { @@ -1323,6 +1328,132 @@ describe('PATCH /workflows/:workflowId', () => { }, ); + describe('sub-workflow loaded from a URL or file', () => { + const UNINSPECTABLE_SOURCE_MESSAGE = + 'The \'Sub\' node loads its sub-workflow from a source that is resolved only when the workflow runs, so its credential access cannot be checked on save. Use the "Database" or "Define Below" source instead.'; + + const remoteSubworkflowNode = (workflowUrl = 'https://example.com/workflow.json') => ({ + id: 'uuid-sub-1', + name: 'Sub', + type: 'n8n-nodes-base.executeWorkflow', + typeVersion: 1.1, + position: [0, 0] as [number, number], + parameters: { source: 'url', workflowUrl }, + }); + + it('rejects a member adding such a node to a shared workflow', async () => { + const workflow = await createWorkflow({}, owner); + await shareWorkflowWithUsers(workflow, [member]); + + const response = await authMemberAgent.patch(`/workflows/${workflow.id}`).send({ + versionId: workflow.versionId, + nodes: [remoteSubworkflowNode()], + }); + + expect(response.statusCode).toBe(400); + expect(response.body.message).toBe(UNINSPECTABLE_SOURCE_MESSAGE); + }); + + it('rejects a member creating a workflow with such a node', async () => { + const response = await authMemberAgent.post('/workflows').send({ + name: 'test', + active: false, + connections: {}, + nodes: [remoteSubworkflowNode()], + }); + + expect(response.statusCode).toBe(400); + expect(response.body.message).toBe(UNINSPECTABLE_SOURCE_MESSAGE); + }); + + it('rejects a member adding the HITL tool variant of such a node', async () => { + const workflow = await createWorkflow({}, owner); + await shareWorkflowWithUsers(workflow, [member]); + + const response = await authMemberAgent.patch(`/workflows/${workflow.id}`).send({ + versionId: workflow.versionId, + nodes: [{ ...remoteSubworkflowNode(), type: 'n8n-nodes-base.executeWorkflowHitlTool' }], + }); + + expect(response.statusCode).toBe(400); + expect(response.body.message).toBe(UNINSPECTABLE_SOURCE_MESSAGE); + }); + + it('rejects a member changing an execution setting of an existing node', async () => { + const workflow = await createWorkflow({ nodes: [remoteSubworkflowNode()] }, owner); + await shareWorkflowWithUsers(workflow, [member]); + + const response = await authMemberAgent.patch(`/workflows/${workflow.id}`).send({ + versionId: workflow.versionId, + nodes: [{ ...remoteSubworkflowNode(), retryOnFail: true }], + }); + + expect(response.statusCode).toBe(400); + expect(response.body.message).toBe(UNINSPECTABLE_SOURCE_MESSAGE); + }); + + it('preserves a renamed URL node when the editor omits default and hidden parameters', async () => { + // The editor omits the default mode and the old database workflow ID. + const stored = { + ...remoteSubworkflowNode(), + parameters: { + ...remoteSubworkflowNode().parameters, + mode: 'once', + workflowId: { __rl: true, value: 'old-workflow', mode: 'id' }, + }, + }; + const workflow = await createWorkflow({ nodes: [stored] }, owner); + await shareWorkflowWithUsers(workflow, [member]); + + const response = await authMemberAgent.patch(`/workflows/${workflow.id}`).send({ + versionId: workflow.versionId, + nodes: [{ ...remoteSubworkflowNode(), name: 'Renamed' }], + }); + + expect(response.statusCode).toBe(200); + const saved = await workflowRepository.findOneByOrFail({ id: workflow.id }); + expect(saved.nodes).toEqual([{ ...stored, name: 'Renamed' }]); + }); + + it('preserves a stored node when a member changes its removed URL parameter', async () => { + const workflow = await createWorkflow({ nodes: [remoteSubworkflowNode()] }, owner); + await shareWorkflowWithUsers(workflow, [member]); + + const changed = await authMemberAgent.patch(`/workflows/${workflow.id}`).send({ + versionId: workflow.versionId, + nodes: [remoteSubworkflowNode('https://example.com/other.json')], + }); + + // 3.x has no workflowUrl parameter. The save restores the stored read-only node. + expect(changed.statusCode).toBe(200); + expect(changed.body.data.nodes).toEqual([remoteSubworkflowNode()]); + + const saved = await workflowRepository.findOneByOrFail({ id: workflow.id }); + expect(saved.nodes).toEqual([remoteSubworkflowNode()]); + }); + + it('lets the owner create and change such a node', async () => { + const createResponse = await authOwnerAgent.post('/workflows').send({ + name: 'test', + active: false, + connections: {}, + nodes: [remoteSubworkflowNode()], + }); + expect(createResponse.statusCode).toBe(200); + const { id, versionId } = createResponse.body.data; + + const response = await authOwnerAgent.patch(`/workflows/${id}`).send({ + versionId, + nodes: [remoteSubworkflowNode('https://example.com/other.json')], + }); + + expect(response.statusCode).toBe(200); + expect(response.body.data.nodes[0].parameters.workflowUrl).toBe( + 'https://example.com/other.json', + ); + }); + }); + describe('restoring a history version', () => { const nodeWith = (credential: { id: string; name: string }, url = 'https://v1.test') => ({ id: 'uuid-restore-1', @@ -1432,6 +1563,60 @@ describe('PATCH /workflows/:workflowId', () => { }); }); + describe('sub-workflow with an inspectable source', () => { + const databaseSubworkflowNode = (workflowId: string) => ({ + id: 'uuid-sub-db', + name: 'Sub', + type: 'n8n-nodes-base.executeWorkflow', + typeVersion: 1.2, + position: [0, 0] as [number, number], + parameters: { + source: 'database', + workflowId: { __rl: true, value: workflowId, mode: 'id' }, + }, + }); + + it('lets a member change a stored node that loads its sub-workflow from the database', async () => { + const workflow = await createWorkflow( + { nodes: [databaseSubworkflowNode('wf-old')] }, + owner, + ); + await shareWorkflowWithUsers(workflow, [member]); + + const response = await authMemberAgent.patch(`/workflows/${workflow.id}`).send({ + versionId: workflow.versionId, + nodes: [databaseSubworkflowNode('wf-new')], + }); + + expect(response.statusCode).toBe(200); + expect(response.body.data.nodes[0].parameters.workflowId.value).toBe('wf-new'); + }); + + it('lets a member create a workflow with a node that defines its sub-workflow inline', async () => { + const response = await authMemberAgent.post('/workflows').send({ + name: 'test', + active: false, + connections: {}, + nodes: [ + { + id: 'uuid-sub-inline', + name: 'Sub', + type: 'n8n-nodes-base.executeWorkflow', + typeVersion: 1.2, + position: [0, 0], + parameters: { + source: 'parameter', + workflowJson: JSON.stringify({ nodes: [], connections: {} }), + }, + }, + ], + }); + + expect(response.statusCode).toBe(200); + expect(response.body.data.nodes[0].parameters.source).toBe('parameter'); + }); + }); + describe('credentials in an agent node parameter', () => { // The agent node keeps the model credential and its tool credentials in // the hidden `inlineAgent` parameter, not in `node.credentials`. diff --git a/packages/cli/test/integration/workflows/workflows.controller.test.ts b/packages/cli/test/integration/workflows/workflows.controller.test.ts index 88d452d9f87..1f324bbf52a 100644 --- a/packages/cli/test/integration/workflows/workflows.controller.test.ts +++ b/packages/cli/test/integration/workflows/workflows.controller.test.ts @@ -23,6 +23,7 @@ import type { Role, WorkflowHistory, WorkflowEntity, + Project, } from '@n8n/db'; import { ProjectRepository, @@ -1968,185 +1969,26 @@ describe('GET /workflows', () => { expect(response.body.data).toHaveLength(1); // Should return all workflows when nodeTypes is empty }); - describe('includeCallableSubworkflows', () => { - const executeWorkflowTriggerNode = (id = uuid()) => ({ - id, - name: 'When Executed by Another Workflow', - type: 'n8n-nodes-base.executeWorkflowTrigger', - parameters: {}, - typeVersion: 1, - position: [0, 0] as [number, number], + test('should ignore callable sub-workflow filter keys', async () => { + const parentWorkflow = await createWorkflow({ name: 'Parent' }, member); + const anyPolicyWorkflow = await createWorkflow( + { name: 'Any Policy', settings: { callerPolicy: 'any' } }, + owner, + ); + + const filter = JSON.stringify({ + includeCallableSubworkflows: true, + parentWorkflowId: parentWorkflow.id, }); - test('should include workflows callable by the parent workflow based on callerPolicy', async () => { - const parentWorkflow = await createWorkflow({ name: 'Parent' }, member); + const response = await authMemberAgent + .get('/workflows') + .query(`filter=${filter}`) + .expect(200); - // callerPolicy: 'any' — callable by everyone - const anyPolicyWorkflow = await createWorkflow( - { - name: 'Any Policy', - nodes: [executeWorkflowTriggerNode()], - settings: { callerPolicy: 'any' }, - }, - owner, - ); - - // callerPolicy: 'workflowsFromAList' — parentWorkflow is explicitly listed - const fromListWorkflow = await createWorkflow( - { - name: 'From List Policy', - nodes: [executeWorkflowTriggerNode()], - settings: { - callerPolicy: 'workflowsFromAList', - callerIds: parentWorkflow.id, - }, - }, - owner, - ); - - // callerPolicy: 'none' — callable by nobody - await createWorkflow( - { - name: 'None Policy', - nodes: [executeWorkflowTriggerNode()], - settings: { callerPolicy: 'none' }, - }, - owner, - ); - - const filter = JSON.stringify({ - triggerNodeTypes: ['n8n-nodes-base.executeWorkflowTrigger'], - includeCallableSubworkflows: true, - parentWorkflowId: parentWorkflow.id, - }); - - const response = await authMemberAgent - .get('/workflows') - .query(`filter=${filter}`) - .expect(200); - - const returnedIds = response.body.data.map((w: { id: string }) => w.id) as string[]; - expect(returnedIds).toContain(anyPolicyWorkflow.id); - expect(returnedIds).toContain(fromListWorkflow.id); - expect(returnedIds).not.toContain( - ( - await createWorkflow( - { - name: 'None Policy Check', - nodes: [executeWorkflowTriggerNode()], - settings: { callerPolicy: 'none' }, - }, - owner, - ) - ).id, - ); - }); - - test('should not include callable workflows when includeCallableSubworkflows is false', async () => { - const parentWorkflow = await createWorkflow({ name: 'Parent' }, member); - - const anyPolicyWorkflow = await createWorkflow( - { - name: 'Any Policy', - nodes: [executeWorkflowTriggerNode()], - settings: { callerPolicy: 'any' }, - }, - owner, - ); - - const filter = JSON.stringify({ - triggerNodeTypes: ['n8n-nodes-base.executeWorkflowTrigger'], - includeCallableSubworkflows: false, - parentWorkflowId: parentWorkflow.id, - }); - - const response = await authMemberAgent - .get('/workflows') - .query(`filter=${filter}`) - .expect(200); - - const returnedIds = response.body.data.map((w: { id: string }) => w.id) as string[]; - // member doesn't own anyPolicyWorkflow, so without expansion it should not be visible - expect(returnedIds).not.toContain(anyPolicyWorkflow.id); - }); - - test('should not expand the list when the requester cannot read the parent workflow', async () => { - // Parent workflow owned by `owner`, inaccessible to `member`. - const parentWorkflow = await createWorkflow({ name: 'Owner Parent' }, owner); - - // Subworkflow owned by the same owner, callable by same-owner workflows. - const sameOwnerSubworkflow = await createWorkflow( - { - name: 'Same Owner Sub', - nodes: [executeWorkflowTriggerNode()], - settings: { callerPolicy: 'workflowsFromSameOwner' }, - }, - owner, - ); - - // Subworkflow that explicitly allowlists the inaccessible parent id. - const fromListSubworkflow = await createWorkflow( - { - name: 'From List Sub', - nodes: [executeWorkflowTriggerNode()], - settings: { - callerPolicy: 'workflowsFromAList', - callerIds: parentWorkflow.id, - }, - }, - owner, - ); - - const filter = JSON.stringify({ - triggerNodeTypes: ['n8n-nodes-base.executeWorkflowTrigger'], - includeCallableSubworkflows: true, - parentWorkflowId: parentWorkflow.id, - }); - - const response = await authMemberAgent - .get('/workflows') - .query(`filter=${filter}`) - .expect(200); - - const returnedIds = response.body.data.map((w: { id: string }) => w.id) as string[]; - // member cannot read the supplied parent workflow, so callable - // subworkflows must not be exposed regardless of caller policy. - expect(returnedIds).not.toContain(sameOwnerSubworkflow.id); - expect(returnedIds).not.toContain(fromListSubworkflow.id); - }); - - test('should match callerIds by whole id, not by substring', async () => { - const parentWorkflow = await createWorkflow({ name: 'Parent' }, member); - - // Allowlist contains the parent id only as a substring of a longer id. - const substringSubworkflow = await createWorkflow( - { - name: 'Substring Allowlist', - nodes: [executeWorkflowTriggerNode()], - settings: { - callerPolicy: 'workflowsFromAList', - callerIds: `${parentWorkflow.id}-extra-suffix`, - }, - }, - owner, - ); - - const filter = JSON.stringify({ - triggerNodeTypes: ['n8n-nodes-base.executeWorkflowTrigger'], - includeCallableSubworkflows: true, - parentWorkflowId: parentWorkflow.id, - }); - - const response = await authMemberAgent - .get('/workflows') - .query(`filter=${filter}`) - .expect(200); - - const returnedIds = response.body.data.map((w: { id: string }) => w.id) as string[]; - // parentWorkflow.id is only a substring of the allowlisted id, so it must - // not be treated as an allowed caller. - expect(returnedIds).not.toContain(substringSubworkflow.id); - }); + const returnedIds = response.body.data.map((w: { id: string }) => w.id) as string[]; + expect(returnedIds).toEqual([parentWorkflow.id]); + expect(returnedIds).not.toContain(anyPolicyWorkflow.id); }); }); @@ -5850,6 +5692,157 @@ describe('GET /workflows/:workflowId/executions/last-successful', () => { }); }); +describe('GET /workflows/:workflowId/callable-subworkflows', () => { + const executeWorkflowTriggerNode = () => ({ + id: uuid(), + name: 'When Executed by Another Workflow', + type: 'n8n-nodes-base.executeWorkflowTrigger', + parameters: {}, + typeVersion: 1, + position: [0, 0] as [number, number], + }); + + const createSubworkflow = async ( + name: string, + settings: WorkflowEntity['settings'], + userOrProject: User | Project, + ) => + await createWorkflow({ name, nodes: [executeWorkflowTriggerNode()], settings }, userOrProject); + + const getCallableIds = async (agent: SuperAgentTest, parentWorkflowId: string) => { + const response = await agent + .get(`/workflows/${parentWorkflowId}/callable-subworkflows`) + .expect(200); + return (response.body.data.data as Array<{ id: string }>).map((w) => w.id); + }; + + test('should list readable workflows and workflows that allow the parent explicitly', async () => { + const parentWorkflow = await createWorkflow({ name: 'Parent' }, member); + const ownSubworkflow = await createSubworkflow('Own', undefined, member); + const anyPolicyWorkflow = await createSubworkflow('Any', { callerPolicy: 'any' }, owner); + const fromListWorkflow = await createSubworkflow( + 'From List', + { callerPolicy: 'workflowsFromAList', callerIds: `other-id, ${parentWorkflow.id}` }, + owner, + ); + const nonePolicyWorkflow = await createSubworkflow('None', { callerPolicy: 'none' }, owner); + const substringListWorkflow = await createSubworkflow( + 'Substring List', + { callerPolicy: 'workflowsFromAList', callerIds: `${parentWorkflow.id}-extra-suffix` }, + owner, + ); + // Readable, but has no Execute Workflow Trigger node. + await createWorkflow({ name: 'No Trigger' }, member); + // Callable by the parent, but has no Execute Workflow Trigger node. + const callableNoTriggerWorkflow = await createWorkflow( + { name: 'Any Policy No Trigger', settings: { callerPolicy: 'any' } }, + owner, + ); + + const returnedIds = await getCallableIds(authMemberAgent, parentWorkflow.id); + + expect(returnedIds.sort()).toEqual( + [ownSubworkflow.id, anyPolicyWorkflow.id, fromListWorkflow.id].sort(), + ); + expect(returnedIds).not.toContain(nonePolicyWorkflow.id); + expect(returnedIds).not.toContain(substringListWorkflow.id); + expect(returnedIds).not.toContain(callableNoTriggerWorkflow.id); + }); + + test('should not list unshared workflows of the user who shared the parent', async () => { + const sharedParent = await createWorkflow({ name: 'Shared Parent' }, owner); + await shareWorkflowWithUsers(sharedParent, [member]); + const sameOwnerWorkflow = await createSubworkflow( + 'Same Owner', + { callerPolicy: 'workflowsFromSameOwner' }, + owner, + ); + const defaultPolicyWorkflow = await createSubworkflow('Default Policy', undefined, owner); + + const returnedIds = await getCallableIds(authMemberAgent, sharedParent.id); + + expect(returnedIds).not.toContain(sameOwnerWorkflow.id); + expect(returnedIds).not.toContain(defaultPolicyWorkflow.id); + }); + + test('should return only the minimal fields and the project name for team projects', async () => { + const parentWorkflow = await createWorkflow({ name: 'Parent' }, owner); + const teamProject = await createTeamProject('Team Project', owner); + const teamWorkflow = await createSubworkflow('Team Sub', undefined, teamProject); + const personalWorkflow = await createSubworkflow('Personal Sub', undefined, owner); + + const response = await authOwnerAgent + .get(`/workflows/${parentWorkflow.id}/callable-subworkflows`) + .query({ select: '["nodes"]', filter: '{"nodeTypes":["n8n-nodes-base.code"]}' }) + .expect(200); + + expect(response.body.data.count).toBe(2); + expect(response.body.data.data).toEqual( + arrayContaining([ + { + id: teamWorkflow.id, + name: 'Team Sub', + active: false, + isArchived: false, + projectName: 'Team Project', + }, + { id: personalWorkflow.id, name: 'Personal Sub', active: false, isArchived: false }, + ]), + ); + }); + + test('should filter by name and paginate', async () => { + const parentWorkflow = await createWorkflow({ name: 'Parent' }, member); + await createSubworkflow('Alpha One', undefined, member); + await createSubworkflow('Alpha Two', undefined, member); + await createSubworkflow('Beta', undefined, member); + + const response = await authMemberAgent + .get(`/workflows/${parentWorkflow.id}/callable-subworkflows`) + .query({ query: 'alpha', take: 1 }) + .expect(200); + + expect(response.body.data.count).toBe(2); + expect(response.body.data.data).toHaveLength(1); + expect(response.body.data.data[0].name).toMatch(/^Alpha/); + }); + + test('should match the search query against workflow names only', async () => { + const parentWorkflow = await createWorkflow({ name: 'Parent' }, member); + await createWorkflow( + { + name: 'Callable', + description: 'contains uniqueterm', + nodes: [executeWorkflowTriggerNode()], + settings: { callerPolicy: 'any' }, + }, + owner, + ); + + const response = await authMemberAgent + .get(`/workflows/${parentWorkflow.id}/callable-subworkflows`) + .query({ query: 'uniqueterm' }) + .expect(200); + + expect(response.body.data).toEqual({ count: 0, data: [] }); + }); + + test('should forbid users who cannot update the parent workflow', async () => { + const teamProject = await createTeamProject('Team Project', owner); + await linkUserToProject(member, teamProject, 'project:viewer'); + const parentWorkflow = await createWorkflow({ name: 'Parent' }, teamProject); + + await authMemberAgent.get(`/workflows/${parentWorkflow.id}/callable-subworkflows`).expect(403); + }); + + test('should forbid users who cannot access the parent workflow', async () => { + const parentWorkflow = await createWorkflow({ name: 'Parent' }, owner); + await createSubworkflow('Allows Parent', { callerPolicy: 'any' }, owner); + + await authMemberAgent.get(`/workflows/${parentWorkflow.id}/callable-subworkflows`).expect(403); + }); +}); + describe('POST /workflows/with-node-types', () => { const NODE_TYPE = 'n8n-nodes-base.set'; diff --git a/packages/cli/test/migration/1791809300081-migrate-agent-mcp-tool-permissions.test.ts b/packages/cli/test/migration/1791809300081-migrate-agent-mcp-tool-permissions.test.ts new file mode 100644 index 00000000000..27a110da084 --- /dev/null +++ b/packages/cli/test/migration/1791809300081-migrate-agent-mcp-tool-permissions.test.ts @@ -0,0 +1,441 @@ +import { + createTestMigrationContext, + initDbUpToMigration, + runSingleMigration, + type TestMigrationContext, +} from '@n8n/backend-test-utils'; +import { Logger } from '@n8n/backend-common'; +import { DbConnection } from '@n8n/db'; +import { Container } from '@n8n/di'; +import { DataSource } from '@n8n/typeorm'; +import { randomUUID } from 'node:crypto'; +import { jsonParse } from 'n8n-workflow'; + +const MIGRATION_NAME = 'MigrateAgentMcpToolPermissions1791809300081'; + +type Fixture = { + name: string; + schema: unknown; + expected: unknown; +}; + +const conversionFixtures: Fixture[] = [ + { + name: 'defaults', + schema: { mcpServers: [{ name: 'plain', url: 'https://example.test' }] }, + expected: { + mcpServers: [ + { + name: 'plain', + url: 'https://example.test', + toolPermissions: { + categories: { read: 'always_allow', write: 'always_allow' }, + }, + }, + ], + }, + }, + { + name: 'global approval', + schema: { mcpServers: [{ approval: { mode: 'global' } }] }, + expected: { + mcpServers: [ + { + toolPermissions: { + categories: { read: 'require_approval', write: 'require_approval' }, + }, + }, + ], + }, + }, + { + name: 'selected approval', + schema: { + mcpServers: [{ approval: { mode: 'selected', tools: ['search', 'update'] } }], + }, + expected: { + mcpServers: [ + { + toolPermissions: { + categories: { read: 'always_allow', write: 'always_allow' }, + tools: { search: 'require_approval', update: 'require_approval' }, + }, + }, + ], + }, + }, + { + name: 'allow filter', + schema: { mcpServers: [{ toolFilter: { mode: 'allow', tools: ['search'] } }] }, + expected: { + mcpServers: [ + { + toolPermissions: { + categories: { read: 'blocked', write: 'blocked' }, + tools: { search: 'always_allow' }, + }, + }, + ], + }, + }, + { + name: 'allow filter with selected approval', + schema: { + mcpServers: [ + { + toolFilter: { mode: 'allow', tools: ['search', 'update'] }, + approval: { mode: 'selected', tools: ['update', 'not-allowed'] }, + }, + ], + }, + expected: { + mcpServers: [ + { + toolPermissions: { + categories: { read: 'blocked', write: 'blocked' }, + tools: { search: 'always_allow', update: 'require_approval' }, + }, + }, + ], + }, + }, + { + name: 'exclude filter with global approval', + schema: { + mcpServers: [ + { + toolFilter: { mode: 'exclude', tools: ['delete'] }, + approval: { mode: 'global' }, + }, + ], + }, + expected: { + mcpServers: [ + { + toolPermissions: { + categories: { read: 'require_approval', write: 'require_approval' }, + tools: { delete: 'blocked' }, + }, + }, + ], + }, + }, + { + name: 'exclude filter overrides selected approval', + schema: { + mcpServers: [ + { + toolFilter: { mode: 'exclude', tools: ['update', 'delete'] }, + approval: { mode: 'selected', tools: ['search', 'update'] }, + }, + ], + }, + expected: { + mcpServers: [ + { + toolPermissions: { + categories: { read: 'always_allow', write: 'always_allow' }, + tools: { + search: 'require_approval', + update: 'blocked', + delete: 'blocked', + }, + }, + }, + ], + }, + }, +]; + +const preservationFixtures: Fixture[] = [ + { + name: 'mixed servers and unrelated fields', + schema: { + name: 'Agent config', + metadata: { retained: true }, + mcpServers: [ + { + name: 'legacy', + headers: { Authorization: 'retained' }, + toolFilter: { mode: 'exclude', tools: ['delete'] }, + }, + { + name: 'current', + toolPermissions: { + categories: { read: 'blocked', write: 'require_approval' }, + tools: { search: 'always_allow' }, + }, + }, + { + name: 'current with stale fields', + toolPermissions: { + categories: { read: 'blocked', write: 'require_approval' }, + tools: { search: 'always_allow' }, + }, + toolFilter: { invalid: true }, + approval: null, + custom: 'retained', + }, + ], + }, + expected: { + name: 'Agent config', + metadata: { retained: true }, + mcpServers: [ + { + name: 'legacy', + headers: { Authorization: 'retained' }, + toolPermissions: { + categories: { read: 'always_allow', write: 'always_allow' }, + tools: { delete: 'blocked' }, + }, + }, + { + name: 'current', + toolPermissions: { + categories: { read: 'blocked', write: 'require_approval' }, + tools: { search: 'always_allow' }, + }, + }, + { + name: 'current with stale fields', + toolPermissions: { + categories: { read: 'blocked', write: 'require_approval' }, + tools: { search: 'always_allow' }, + }, + custom: 'retained', + }, + ], + }, + }, +]; + +const unchangedFixtures: Fixture[] = [ + { + name: 'missing mcpServers', + schema: { name: 'Agent config' }, + expected: { name: 'Agent config' }, + }, + // PostgreSQL excludes this row by key depth. SQLite selects it, then structural validation rejects it. + { + name: 'nested mcpServers key', + schema: { metadata: { mcpServers: [{ approval: { mode: 'global' } }] } }, + expected: { metadata: { mcpServers: [{ approval: { mode: 'global' } }] } }, + }, + { name: 'empty mcpServers', schema: { mcpServers: [] }, expected: { mcpServers: [] } }, + { + name: 'already migrated', + schema: { + mcpServers: [ + { + toolPermissions: { + categories: { read: 'always_allow', write: 'blocked' }, + }, + }, + ], + }, + expected: { + mcpServers: [ + { + toolPermissions: { + categories: { read: 'always_allow', write: 'blocked' }, + }, + }, + ], + }, + }, +]; + +const malformedFixtures: Fixture[] = [ + { name: 'null schema', schema: null, expected: null }, + { name: 'primitive schema', schema: 'legacy', expected: 'legacy' }, + { name: 'non-array servers', schema: { mcpServers: {} }, expected: { mcpServers: {} } }, + { + name: 'invalid server entry', + schema: { mcpServers: [null] }, + expected: { mcpServers: [null] }, + }, + { + name: 'invalid legacy filter', + schema: { mcpServers: [{ toolFilter: { mode: 'allow', tools: 'search' } }] }, + expected: { mcpServers: [{ toolFilter: { mode: 'allow', tools: 'search' } }] }, + }, + { + name: 'invalid legacy approval', + schema: { mcpServers: [{ approval: { mode: 'selected' } }] }, + expected: { mcpServers: [{ approval: { mode: 'selected' } }] }, + }, +]; + +const fixtures = [ + ...conversionFixtures, + ...preservationFixtures, + ...unchangedFixtures, + ...malformedFixtures, +]; + +function parseStoredSchema(value: unknown): unknown { + if (typeof value !== 'string') return value; + try { + return jsonParse(value); + } catch { + return value; + } +} + +describe('MigrateAgentMcpToolPermissions migration', () => { + let dataSource: DataSource; + + async function withContext(fn: (context: TestMigrationContext) => Promise): Promise { + const context = createTestMigrationContext(dataSource); + try { + return await fn(context); + } finally { + await context.queryRunner.release(); + } + } + + beforeAll(async () => { + await Container.get(DbConnection).init(); + dataSource = Container.get(DataSource); + }); + + beforeEach(async () => { + await withContext(async (context) => await context.queryRunner.clearDatabase()); + await initDbUpToMigration(MIGRATION_NAME); + dataSource = Container.get(DataSource); + }, 60_000); + + afterAll(async () => { + await Container.get(DbConnection).close(); + }); + + it('migrates legacy permissions in agents and agent history without changing skipped data', async () => { + const rows = fixtures.map((fixture) => ({ + ...fixture, + agentId: randomUUID(), + versionId: randomUUID(), + })); + + await withContext(async ({ escape, runQuery }) => { + const projectId = randomUUID(); + const now = new Date(); + await runQuery( + `INSERT INTO ${escape.tableName('project')} ("id", "name", "type", "createdAt", "updatedAt") + VALUES (:projectId, 'Project', 'personal', :now, :now)`, + { projectId, now }, + ); + + for (const row of rows) { + await runQuery( + `INSERT INTO ${escape.tableName('agents')} + ("id", "name", "projectId", "schema", "integrations", "tools", "skills", "createdAt", "updatedAt") + VALUES (:id, :name, :projectId, :schema, '[]', '{}', '{}', :now, :now)`, + { + id: row.agentId, + name: row.name, + projectId, + schema: JSON.stringify(row.schema), + now, + }, + ); + await runQuery( + `INSERT INTO ${escape.tableName('agent_history')} + ("versionId", "agentId", "schema", "author", "createdAt", "updatedAt") + VALUES (:versionId, :agentId, :schema, 'Test User', :now, :now)`, + { + versionId: row.versionId, + agentId: row.agentId, + schema: JSON.stringify(row.schema), + now, + }, + ); + } + }); + + await runSingleMigration(MIGRATION_NAME); + dataSource = Container.get(DataSource); + + await withContext(async ({ escape, runQuery }) => { + const agentRows = await runQuery>( + `SELECT "id", "schema" FROM ${escape.tableName('agents')}`, + ); + const historyRows = await runQuery>( + `SELECT "versionId", "schema" FROM ${escape.tableName('agent_history')}`, + ); + + const agentsById = new Map(agentRows.map((row) => [row.id, parseStoredSchema(row.schema)])); + const historyById = new Map( + historyRows.map((row) => [row.versionId, parseStoredSchema(row.schema)]), + ); + + for (const row of rows) { + expect(agentsById.get(row.agentId), `${row.name} in agents`).toEqual(row.expected); + expect(historyById.get(row.versionId), `${row.name} in agent_history`).toEqual( + row.expected, + ); + } + }); + }); + + it('processes only rows with MCP server candidates', async () => { + const schemas = [ + {}, + { name: 'No MCP server' }, + { metadata: { retained: true } }, + { mcpServers: [] }, + { mcpServers: [{ name: 'MCP server' }] }, + ]; + const loggerInfo = vi.spyOn(Container.get(Logger), 'info').mockImplementation(() => {}); + + try { + await withContext(async ({ escape, runQuery }) => { + const projectId = randomUUID(); + const now = new Date(); + await runQuery( + `INSERT INTO ${escape.tableName('project')} ("id", "name", "type", "createdAt", "updatedAt") + VALUES (:projectId, 'Project', 'personal', :now, :now)`, + { projectId, now }, + ); + + for (const [index, schema] of schemas.entries()) { + const agentId = randomUUID(); + await runQuery( + `INSERT INTO ${escape.tableName('agents')} + ("id", "name", "projectId", "schema", "integrations", "tools", "skills", "createdAt", "updatedAt") + VALUES (:agentId, :name, :projectId, :schema, '[]', '{}', '{}', :now, :now)`, + { + agentId, + name: `Agent ${index}`, + projectId, + schema: JSON.stringify(schema), + now, + }, + ); + await runQuery( + `INSERT INTO ${escape.tableName('agent_history')} + ("versionId", "agentId", "schema", "author", "createdAt", "updatedAt") + VALUES (:versionId, :agentId, :schema, 'Test User', :now, :now)`, + { + versionId: randomUUID(), + agentId, + schema: JSON.stringify(schema), + now, + }, + ); + } + }); + + await runSingleMigration(MIGRATION_NAME); + + expect(loggerInfo).toHaveBeenCalledWith( + `[${MIGRATION_NAME}] Processed 2 agents rows; migrated 1; skipped 0 malformed rows.`, + ); + expect(loggerInfo).toHaveBeenCalledWith( + `[${MIGRATION_NAME}] Processed 2 agent_history rows; migrated 1; skipped 0 malformed rows.`, + ); + } finally { + loggerInfo.mockRestore(); + } + }); +}); diff --git a/packages/cli/test/migration/1791818723687-create-skills-hub-tables.test.ts b/packages/cli/test/migration/1791818723687-create-skills-hub-tables.test.ts new file mode 100644 index 00000000000..abcdd5621c6 --- /dev/null +++ b/packages/cli/test/migration/1791818723687-create-skills-hub-tables.test.ts @@ -0,0 +1,265 @@ +import { + createTestMigrationContext, + initDbUpToMigration, + runSingleMigration, + type TestMigrationContext, +} from '@n8n/backend-test-utils'; +import { DbConnection } from '@n8n/db'; +import { Container } from '@n8n/di'; +import { DataSource } from '@n8n/typeorm'; +import { randomUUID } from 'node:crypto'; + +const migrationName = 'CreateSkillsHubTables1791818723687'; + +type Row = Record; + +describe('CreateSkillsHubTables migration', () => { + let context: TestMigrationContext; + + const insertRow = async (tableName: string, values: Row) => { + const columns = Object.keys(values); + await context.runQuery( + `INSERT INTO ${context.escape.tableName(tableName)} + (${columns.map((name) => context.escape.columnName(name)).join(', ')}) + VALUES (${columns.map((name) => `:${name}`).join(', ')})`, + values, + ); + }; + + const deleteRow = async (tableName: string, column: string, value: string) => { + await context.runQuery( + `DELETE FROM ${context.escape.tableName(tableName)} WHERE ${context.escape.columnName(column)} = :value`, + { value }, + ); + }; + + const countRows = async (tableName: string, column: string, value: string) => { + const rows = await context.runQuery>( + `SELECT COUNT(*) AS ${context.escape.columnName('count')} FROM ${context.escape.tableName(tableName)} + WHERE ${context.escape.columnName(column)} = :value`, + { value }, + ); + return Number(rows[0].count); + }; + + const insertUser = async () => { + const id = randomUUID(); + // Roles go in as parameters: the Postgres helper reads `:word` in a literal as one. + await insertRow('user', { + id, + email: `${id}@test.com`, + firstName: 'Test', + lastName: 'User', + password: 'hashed', + roleSlug: 'global:member', + createdAt: new Date(), + updatedAt: new Date(), + }); + return id; + }; + + const insertProject = async () => { + const id = randomUUID(); + await insertRow('project', { id, name: 'Skills hub project', type: 'team' }); + return id; + }; + + const insertAgent = async (projectId: string) => { + const id = randomUUID(); + await insertRow('agents', { + id, + name: 'Skills hub agent', + projectId, + integrations: '[]', + tools: '{}', + skills: '{}', + }); + return id; + }; + + const insertAgentVersion = async (agentId: string) => { + const versionId = randomUUID(); + await insertRow('agent_history', { versionId, agentId, author: 'Test User' }); + return versionId; + }; + + /** A skill with one version and one file. */ + const insertSkill = async ( + target: { projectId?: string; agentId?: string }, + createdById?: string, + ) => { + const skillId = `skill_${randomUUID().slice(0, 16)}`; + await insertRow('skill', { + id: skillId, + projectId: target.projectId ?? null, + agentId: target.agentId ?? null, + source: 'ui', + createdById: createdById ?? null, + }); + const versionId = randomUUID(); + await insertRow('skill_version', { + id: versionId, + skillId, + version: 1, + name: 'Brand voice', + description: 'Use when writing emails', + instructions: 'Write in a warm tone.', + contentHash: 'a'.repeat(64), + }); + await insertRow('skill_file', { + skillVersionId: versionId, + path: 'references/tone.md', + content: 'Examples', + }); + return { skillId, versionId }; + }; + + beforeAll(async () => { + await Container.get(DbConnection).init(); + const initial = createTestMigrationContext(Container.get(DataSource)); + try { + await initial.queryRunner.clearDatabase(); + } finally { + await initial.queryRunner.release(); + } + await initDbUpToMigration(migrationName); + await runSingleMigration(migrationName); + }); + + beforeEach(() => { + context = createTestMigrationContext(Container.get(DataSource)); + }); + + afterEach(async () => { + await context.queryRunner.release(); + }); + + afterAll(async () => { + await Container.get(DbConnection).close(); + }); + + it('keeps a project skill when its author is deleted and clears the author', async () => { + const authorId = await insertUser(); + const projectId = await insertProject(); + const { skillId } = await insertSkill({ projectId }, authorId); + + await deleteRow('user', 'id', authorId); + + const rows = await context.runQuery>( + `SELECT ${context.escape.columnName('createdById')} FROM ${context.escape.tableName('skill')} + WHERE ${context.escape.columnName('id')} = :skillId`, + { skillId }, + ); + expect(rows).toEqual([{ createdById: null }]); + }); + + it('deletes a project together with its skills and the agents that pin them', async () => { + const projectId = await insertProject(); + const agentId = await insertAgent(projectId); + const agentVersionId = await insertAgentVersion(agentId); + const agentSkill = await insertSkill({ agentId }); + const { skillId, versionId } = await insertSkill({ projectId }); + await insertRow('agent_skill_dependency', { agentId, skillId, skillVersionId: versionId }); + await insertRow('agent_version_skill_dependency', { + agentVersionId, + skillId, + skillVersionId: versionId, + }); + + await deleteRow('project', 'id', projectId); + + expect(await countRows('agents', 'id', agentId)).toBe(0); + expect(await countRows('skill', 'id', skillId)).toBe(0); + expect(await countRows('skill_version', 'skillId', skillId)).toBe(0); + expect(await countRows('skill_file', 'skillVersionId', versionId)).toBe(0); + expect(await countRows('agent_skill_dependency', 'skillId', skillId)).toBe(0); + expect(await countRows('agent_version_skill_dependency', 'skillId', skillId)).toBe(0); + // An agent skill has no projectId and goes through the agent. + expect(await countRows('skill', 'id', agentSkill.skillId)).toBe(0); + }); + + /** One agent with a published version, both pinning the same skill version. */ + const insertPinnedSkill = async () => { + const projectId = await insertProject(); + const agentId = await insertAgent(projectId); + const agentVersionId = await insertAgentVersion(agentId); + const { skillId, versionId } = await insertSkill({}); + await insertRow('agent_skill_dependency', { agentId, skillId, skillVersionId: versionId }); + await insertRow('agent_version_skill_dependency', { + agentVersionId, + skillId, + skillVersionId: versionId, + }); + return { projectId, agentId, agentVersionId, skillId, versionId }; + }; + + it('refuses to delete a skill version that agents pin', async () => { + const { projectId, skillId, versionId } = await insertPinnedSkill(); + + await expect(deleteRow('skill_version', 'id', versionId)).rejects.toThrow(); + expect(await countRows('skill_version', 'id', versionId)).toBe(1); + + await deleteRow('project', 'id', projectId); + await deleteRow('skill', 'id', skillId); + }); + + it('deletes a skill together with the pins on it, and keeps the agents', async () => { + const { projectId, agentId, agentVersionId, skillId } = await insertPinnedSkill(); + + // The service refuses to delete a skill in use. The database only keeps the rows consistent. + await deleteRow('skill', 'id', skillId); + + expect(await countRows('agent_skill_dependency', 'skillId', skillId)).toBe(0); + expect(await countRows('agent_version_skill_dependency', 'skillId', skillId)).toBe(0); + expect(await countRows('agents', 'id', agentId)).toBe(1); + expect(await countRows('agent_history', 'versionId', agentVersionId)).toBe(1); + + await deleteRow('project', 'id', projectId); + }); + + it('deletes an agent together with its own skills, and keeps project skills', async () => { + const projectId = await insertProject(); + const agentId = await insertAgent(projectId); + const agentVersionId = await insertAgentVersion(agentId); + const own = await insertSkill({ agentId }); + const shared = await insertSkill({ projectId }); + for (const { skillId, versionId } of [own, shared]) { + await insertRow('agent_skill_dependency', { agentId, skillId, skillVersionId: null }); + await insertRow('agent_version_skill_dependency', { + agentVersionId, + skillId, + skillVersionId: versionId, + }); + } + + await deleteRow('agents', 'id', agentId); + + expect(await countRows('skill', 'id', own.skillId)).toBe(0); + expect(await countRows('skill_version', 'skillId', own.skillId)).toBe(0); + expect(await countRows('skill_file', 'skillVersionId', own.versionId)).toBe(0); + expect(await countRows('skill', 'id', shared.skillId)).toBe(1); + expect(await countRows('agent_skill_dependency', 'skillId', shared.skillId)).toBe(0); + expect(await countRows('agent_version_skill_dependency', 'skillId', shared.skillId)).toBe(0); + + await deleteRow('project', 'id', projectId); + }); + + it('rejects an agent skill that also has a project', async () => { + const projectId = await insertProject(); + const agentId = await insertAgent(projectId); + + await expect(insertSkill({ projectId, agentId })).rejects.toThrow(); + + await deleteRow('project', 'id', projectId); + }); + + // New sources must not need a migration, so the column has no CHECK on its values. + it('accepts a source value the code does not use yet', async () => { + const id = `skill_${randomUUID().slice(0, 16)}`; + + await insertRow('skill', { id, source: 'github' }); + + expect(await countRows('skill', 'id', id)).toBe(1); + await deleteRow('skill', 'id', id); + }); +}); diff --git a/packages/cli/tsconfig.json b/packages/cli/tsconfig.json index 01dc23c7600..56e54f4a184 100644 --- a/packages/cli/tsconfig.json +++ b/packages/cli/tsconfig.json @@ -41,6 +41,7 @@ { "path": "../@n8n/backend-common/tsconfig.build.json" }, { "path": "../@n8n/backend-services/tsconfig.build.json" }, { "path": "../modules/insights/backend/tsconfig.build.json" }, + { "path": "../modules/quick-connect/backend/tsconfig.build.json" }, { "path": "../@n8n/backend-test-utils/tsconfig.build.json" }, { "path": "../@n8n/blob-storage/tsconfig.build.json" }, { "path": "../@n8n/di/tsconfig.build.json" }, diff --git a/packages/core/package.json b/packages/core/package.json index 7fc22610a1e..5f5cefeb578 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "n8n-core", - "version": "2.43.0", + "version": "2.44.0", "description": "Core functionality of n8n", "main": "dist/index", "types": "dist/index.d.ts", diff --git a/packages/core/src/execution-engine/__tests__/routing-node.test.ts b/packages/core/src/execution-engine/__tests__/routing-node.test.ts index 222905ca2e0..7dc77695fc4 100644 --- a/packages/core/src/execution-engine/__tests__/routing-node.test.ts +++ b/packages/core/src/execution-engine/__tests__/routing-node.test.ts @@ -1,5 +1,11 @@ +import { AxiosError, AxiosHeaders } from 'axios'; import get from 'lodash/get'; -import { Workflow, createEmptyRunExecutionData } from 'n8n-workflow'; +import { + NodeApiError, + NodeOperationError, + Workflow, + createEmptyRunExecutionData, +} from 'n8n-workflow'; import type { DeclarativeRestApiSettings, ICredentialDataDecryptedObject, @@ -2428,9 +2434,11 @@ describe('RoutingNode', () => { const createRoutingNode = ({ continueOnFail, requestErrorUrl, + requestError = new Error('Request failed'), }: { continueOnFail: boolean; requestErrorUrl?: string; + requestError?: Error; }) => { const items: INodeExecutionData[] = [ { json: { id: 'first' } }, @@ -2483,7 +2491,7 @@ describe('RoutingNode', () => { context.helpers.httpRequest = vi.fn(async (requestOptions: IHttpRequestOptions) => { requestUrls.push(requestOptions.url); if (requestOptions.url === requestErrorUrl) { - throw new Error('Request failed'); + throw requestError; } return { body: { url: requestOptions.url } }; }); @@ -2541,6 +2549,41 @@ describe('RoutingNode', () => { expect(result?.[0]?.[1]?.error).toMatchObject({ message: 'Request failed' }); expect(result?.[0]?.[2]?.json).toEqual({ url: '/items/third' }); }); + + test('returns a request error without request headers when continue on fail is enabled', async () => { + const requestError = new AxiosError( + 'Request failed with status code 500', + 'ERR_BAD_RESPONSE', + { headers: new AxiosHeaders({ Authorization: 'Bearer secret-token' }) }, + ); + const { run } = createRoutingNode({ + continueOnFail: true, + requestErrorUrl: '/items/second', + requestError, + }); + + const result = await run; + const error = result?.[0]?.[1]?.error; + + expect(error).toBeInstanceOf(NodeApiError); + expect(error).toMatchObject({ context: { itemIndex: 1, runIndex: 0 } }); + expect(JSON.stringify(error)).not.toContain('secret-token'); + }); + + test('keeps a node operation error when continue on fail is enabled', async () => { + const requestError = new NodeOperationError(mock(), 'Post-receive action failed'); + const { run } = createRoutingNode({ + continueOnFail: true, + requestErrorUrl: '/items/second', + requestError, + }); + + const result = await run; + const error = result?.[0]?.[1]?.error; + + expect(error).toBe(requestError); + expect(error).toMatchObject({ context: { itemIndex: 1, runIndex: 0 } }); + }); }); describe('itemIndex', () => { diff --git a/packages/core/src/execution-engine/__tests__/workflow-execute-process-process-run-execution-data.test.ts b/packages/core/src/execution-engine/__tests__/workflow-execute-process-process-run-execution-data.test.ts index b2f17790a23..f771c76aee3 100644 --- a/packages/core/src/execution-engine/__tests__/workflow-execute-process-process-run-execution-data.test.ts +++ b/packages/core/src/execution-engine/__tests__/workflow-execute-process-process-run-execution-data.test.ts @@ -421,6 +421,55 @@ describe('processRunExecutionData', () => { expect(taskData.metadata?.dynamicCredentialsUsage).toBeUndefined(); }); + test('stamps the credential ids a sub-execution reported on the task, for that node only', async () => { + // ARRANGE + // Credential usability redaction reads these ids from the calling node's task, + // since the sub-workflow's credentials are not on this workflow's nodes. + const waitingNode = createNodeData({ name: 'waitingNode', type: types.passThrough }); + const nextNode = createNodeData({ name: 'nextNode', type: types.passThrough }); + const workflow = new DirectedGraph() + .addNodes(waitingNode, nextNode) + .addConnections({ from: waitingNode, to: nextNode }) + .toWorkflow({ name: '', active: false, nodeTypes, settings: { executionOrder: 'v1' } }); + + const data: IDataObject = { foo: 1 }; + const executionData = createRunExecutionData({ + startData: { startNodes: [{ name: waitingNode.name, sourceData: null }] }, + resultData: { + runData: { + waitingNode: [toITaskData([{ data }], { executionStatus: 'waiting' })], + }, + lastNodeExecuted: 'waitingNode', + }, + executionData: { + nodeExecutionStack: [ + { + data: { main: [[{ json: data }]] }, + node: waitingNode, + source: null, + metadata: { + dynamicCredentialsUsage: { usedCredentialIds: ['child-cred'] }, + }, + }, + ], + runtimeData: { version: 1, establishedAt: 0, source: 'trigger' }, + }, + waitTill: new Date('2024-01-01'), + }); + + const workflowExecute = new WorkflowExecute(additionalData, executionMode, executionData); + + // ACT + const result = await workflowExecute.processRunExecutionData(workflow); + + // ASSERT + const [waitingTask] = result.data.resultData.runData.waitingNode; + expect(waitingTask.usedCredentialIds).toEqual(['child-cred']); + // Reset before each node, so the next node does not inherit them. + const [nextTask] = result.data.resultData.runData.nextNode; + expect(nextTask.usedCredentialIds).toBeUndefined(); + }); + test('restores an attempted-only stash without recording a resolved user', async () => { // ARRANGE const node = createNodeData({ name: 'waitingNode', type: types.passThrough }); diff --git a/packages/core/src/execution-engine/node-execution-context/__tests__/supply-data-context.test.ts b/packages/core/src/execution-engine/node-execution-context/__tests__/supply-data-context.test.ts index 0b809c841d4..55d9816f7f6 100644 --- a/packages/core/src/execution-engine/node-execution-context/__tests__/supply-data-context.test.ts +++ b/packages/core/src/execution-engine/node-execution-context/__tests__/supply-data-context.test.ts @@ -710,6 +710,7 @@ describe('SupplyDataContext', () => { testAdditionalData.currentNodeUsedDynamicCredentials = false; testAdditionalData.currentNodeAttemptedDynamicCredentials = false; testAdditionalData.dynamicCredentialsResolvedUserId = undefined; + testAdditionalData.currentNodeUsedCredentialIds = undefined; const testRunExecutionData = createRunExecutionData({ resultData: { @@ -835,6 +836,45 @@ describe('SupplyDataContext', () => { expect(taskData.attemptedDynamicCredentials).toBeUndefined(); expect(testRunExecutionData.executionData?.runtimeData?.executedByUserId).toBeUndefined(); }); + + it('stamps the credential ids a sub-workflow reported during this run', async () => { + const { testAdditionalData, testRunExecutionData, testContext } = buildStampingContext(); + testAdditionalData.currentNodeUsedCredentialIds = ['sibling-cred']; + + const { index } = testContext.addInputData(NodeConnectionTypes.AiTool, [ + [{ json: { query: 'test' } }], + ]); + testAdditionalData.currentNodeUsedCredentialIds = ['sibling-cred', 'child-cred']; + await testContext.addExecutionDataFunctions( + 'output', + [[{ json: { result: 'success' } }]], + NodeConnectionTypes.AiTool, + node.name, + index, + ); + + const taskData = testRunExecutionData.resultData.runData[node.name][index]; + expect(taskData.usedCredentialIds).toEqual(['child-cred']); + }); + + it('does not stamp credential ids that were already reported before this run started', async () => { + const { testAdditionalData, testRunExecutionData, testContext } = buildStampingContext(); + testAdditionalData.currentNodeUsedCredentialIds = ['sibling-cred']; + + const { index } = testContext.addInputData(NodeConnectionTypes.AiTool, [ + [{ json: { query: 'test' } }], + ]); + await testContext.addExecutionDataFunctions( + 'output', + [[{ json: { result: 'success' } }]], + NodeConnectionTypes.AiTool, + node.name, + index, + ); + + const taskData = testRunExecutionData.resultData.runData[node.name][index]; + expect(taskData.usedCredentialIds).toBeUndefined(); + }); }); describe('isToolExecution', () => { diff --git a/packages/core/src/execution-engine/node-execution-context/supply-data-context.ts b/packages/core/src/execution-engine/node-execution-context/supply-data-context.ts index b3670f7dd60..cba20064b69 100644 --- a/packages/core/src/execution-engine/node-execution-context/supply-data-context.ts +++ b/packages/core/src/execution-engine/node-execution-context/supply-data-context.ts @@ -58,7 +58,7 @@ export class SupplyDataContext extends BaseExecuteContext implements ISupplyData */ private readonly dynamicCredentialsFlagsAtInput = new Map< number, - { used: boolean; attempted: boolean } + { used: boolean; attempted: boolean; credentialIds: readonly string[] } >(); constructor( @@ -299,6 +299,7 @@ export class SupplyDataContext extends BaseExecuteContext implements ISupplyData this.dynamicCredentialsFlagsAtInput.set(currentNodeRunIndex, { used: additionalData.currentNodeUsedDynamicCredentials === true, attempted: additionalData.currentNodeAttemptedDynamicCredentials === true, + credentialIds: this.reportedCredentialIds(), }); taskData = { startTime: Date.now(), @@ -412,9 +413,19 @@ export class SupplyDataContext extends BaseExecuteContext implements ISupplyData const atInput = this.dynamicCredentialsFlagsAtInput.get(currentNodeRunIndex) ?? { used: false, attempted: false, + credentialIds: [], }; this.dynamicCredentialsFlagsAtInput.delete(currentNodeRunIndex); + // The credentials a sub-workflow called by this run reported, which credential + // usability redaction reads. + const usedCredentialIds = this.reportedCredentialIds().filter( + (id) => !atInput.credentialIds.includes(id), + ); + if (usedCredentialIds.length > 0) { + taskData.usedCredentialIds = usedCredentialIds; + } + const used = additionalData.currentNodeUsedDynamicCredentials === true && !atInput.used; if (used) { taskData.usedDynamicCredentials = true; @@ -434,6 +445,12 @@ export class SupplyDataContext extends BaseExecuteContext implements ISupplyData } } + /** A copy of the credential ids sub-workflows reported for the current node so far. */ + private reportedCredentialIds(): string[] { + const ids = this.additionalData.currentNodeUsedCredentialIds; + return Array.isArray(ids) ? [...ids] : []; + } + logNodeOutput(...args: unknown[]): void { if (this.mode === 'manual') { const parsedLogArgs = args.map((arg) => diff --git a/packages/core/src/execution-engine/node-execution-context/utils/__tests__/create-node-as-tool.test.ts b/packages/core/src/execution-engine/node-execution-context/utils/__tests__/create-node-as-tool.test.ts index c3744046355..58340ea0b37 100644 --- a/packages/core/src/execution-engine/node-execution-context/utils/__tests__/create-node-as-tool.test.ts +++ b/packages/core/src/execution-engine/node-execution-context/utils/__tests__/create-node-as-tool.test.ts @@ -12,13 +12,21 @@ vi.mock('@langchain/core/tools', () => ({ description: string; schema: unknown; func: unknown; + metadata: unknown; + }, + config: { + name: string; + description: string; + schema: unknown; + func: unknown; + metadata: unknown; }, - config: { name: string; description: string; schema: unknown; func: unknown }, ) { this.name = config.name; this.description = config.description; this.schema = config.schema; this.func = config.func; + this.metadata = config.metadata; }), })); @@ -128,6 +136,36 @@ describe('createNodeAsTool', () => { }); }); + describe('Tool metadata', () => { + it('should set sourceNodeName in metadata', () => { + const tool = createNodeAsTool(options).response; + + expect(tool.metadata?.sourceNodeName).toBe('Test_Node'); + }); + + it('should set metadata.attribution from the toolAttribution parameter', () => { + node.parameters.toolAttribution = 'Powered by Databricks Genie'; + + const tool = createNodeAsTool(options).response; + + expect(tool.metadata?.attribution).toBe('Powered by Databricks Genie'); + }); + + it('should not set metadata.attribution when toolAttribution is absent', () => { + const tool = createNodeAsTool(options).response; + + expect(tool.metadata).not.toHaveProperty('attribution'); + }); + + it('should not set metadata.attribution when toolAttribution is empty', () => { + node.parameters.toolAttribution = ''; + + const tool = createNodeAsTool(options).response; + + expect(tool.metadata).not.toHaveProperty('attribution'); + }); + }); + describe('Schema Creation and Parameter Handling', () => { it('should create a schema based on fromAI arguments in nodeParameters', () => { const tool = createNodeAsTool(options).response; diff --git a/packages/core/src/execution-engine/node-execution-context/utils/__tests__/execution-metadata.test.ts b/packages/core/src/execution-engine/node-execution-context/utils/__tests__/execution-metadata.test.ts index 5c4ba9690bb..922a7a40173 100644 --- a/packages/core/src/execution-engine/node-execution-context/utils/__tests__/execution-metadata.test.ts +++ b/packages/core/src/execution-engine/node-execution-context/utils/__tests__/execution-metadata.test.ts @@ -1,4 +1,10 @@ -import { createRunExecutionData, type IRunExecutionData } from 'n8n-workflow'; +import { + createRunExecutionData, + LoggerProxy, + type IRunExecutionData, + type Logger, +} from 'n8n-workflow'; +import { mock } from 'vitest-mock-extended'; import { InvalidExecutionMetadataError } from '@/errors/invalid-execution-metadata.error'; @@ -6,6 +12,8 @@ import { setWorkflowExecutionMetadata, setAllWorkflowExecutionMetadata, KV_LIMIT, + KEY_MAX_LENGTH, + VALUE_MAX_LENGTH, getWorkflowExecutionMetadata, getAllWorkflowExecutionMetadata, } from '../execution-metadata'; @@ -148,29 +156,62 @@ describe('Execution Metadata functions', () => { expect(metadata.test1).toBe('value1'); }); - test('setWorkflowExecutionMetadata should truncate long keys', () => { - const { metadata, executionData } = createExecutionDataWithMetadata(); + describe('truncation of long keys and values', () => { + const logger = mock(); - setWorkflowExecutionMetadata( - executionData, - 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab', - 'value1', - ); - - expect(metadata).toEqual({ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: 'value1', + beforeEach(() => { + vi.clearAllMocks(); + LoggerProxy.init(logger); }); - }); - test('setWorkflowExecutionMetadata should truncate long values', () => { - const { metadata, executionData } = createExecutionDataWithMetadata(); + test('stores a value at the length limit in full and does not log', () => { + const { metadata, executionData } = createExecutionDataWithMetadata(); + const value = 'a'.repeat(VALUE_MAX_LENGTH); - const longValue = 'a'.repeat(513); + setWorkflowExecutionMetadata(executionData, 'test1', value); - setWorkflowExecutionMetadata(executionData, 'test1', longValue); + expect(metadata.test1).toBe(value); + expect(logger.warn).not.toHaveBeenCalled(); + expect(logger.error).not.toHaveBeenCalled(); + }); - expect(metadata).toEqual({ - test1: longValue.slice(0, 512), + test('truncates a value over the length limit and logs one warning', () => { + const { metadata, executionData } = createExecutionDataWithMetadata(); + + setWorkflowExecutionMetadata(executionData, 'test1', 'a'.repeat(VALUE_MAX_LENGTH) + 'b'); + + expect(metadata.test1).toBe('a'.repeat(VALUE_MAX_LENGTH)); + expect(logger.warn).toHaveBeenCalledTimes(1); + expect(logger.warn).toHaveBeenCalledWith( + `Custom data value over ${VALUE_MAX_LENGTH} characters long. Truncating to ${VALUE_MAX_LENGTH} characters.`, + undefined, + ); + expect(logger.error).not.toHaveBeenCalled(); + }); + + test('stores a key at the length limit in full and does not log', () => { + const { metadata, executionData } = createExecutionDataWithMetadata(); + const key = 'a'.repeat(KEY_MAX_LENGTH); + + setWorkflowExecutionMetadata(executionData, key, 'value1'); + + expect(metadata).toEqual({ [key]: 'value1' }); + expect(logger.warn).not.toHaveBeenCalled(); + expect(logger.error).not.toHaveBeenCalled(); + }); + + test('truncates a key over the length limit and logs one warning', () => { + const { metadata, executionData } = createExecutionDataWithMetadata(); + + setWorkflowExecutionMetadata(executionData, 'a'.repeat(KEY_MAX_LENGTH) + 'b', 'value1'); + + expect(metadata).toEqual({ ['a'.repeat(KEY_MAX_LENGTH)]: 'value1' }); + expect(logger.warn).toHaveBeenCalledTimes(1); + expect(logger.warn).toHaveBeenCalledWith( + `Custom data key over ${KEY_MAX_LENGTH} characters long. Truncating to ${KEY_MAX_LENGTH} characters.`, + undefined, + ); + expect(logger.error).not.toHaveBeenCalled(); }); }); diff --git a/packages/core/src/execution-engine/node-execution-context/utils/__tests__/get-input-connection-data.test.ts b/packages/core/src/execution-engine/node-execution-context/utils/__tests__/get-input-connection-data.test.ts index efa7b8da525..7f5e8229219 100644 --- a/packages/core/src/execution-engine/node-execution-context/utils/__tests__/get-input-connection-data.test.ts +++ b/packages/core/src/execution-engine/node-execution-context/utils/__tests__/get-input-connection-data.test.ts @@ -1511,6 +1511,20 @@ describe('createHitlToolkit', () => { expect(wrappedTool.metadata?.gatedToolNodeName).toBe('Original Node'); }); + it('should forward metadata.attribution to the wrapped tool', () => { + const originalTool = new DynamicStructuredTool({ + name: 'test_tool', + description: 'Test tool description', + schema: z.object({ input: z.string() }), + func: async () => 'result', + metadata: { sourceNodeName: 'Original Node', attribution: 'Powered by Databricks Genie' }, + }); + + const result = createHitlToolkit(originalTool, hitlNode); + + expect(result.tools[0].metadata?.attribution).toBe('Powered by Databricks Genie'); + }); + it('should handle tool without metadata', () => { const originalTool = new DynamicStructuredTool({ name: 'test_tool', diff --git a/packages/core/src/execution-engine/node-execution-context/utils/__tests__/validate-value-against-schema.test.ts b/packages/core/src/execution-engine/node-execution-context/utils/__tests__/validate-value-against-schema.test.ts index f816411d85b..b22a1a8ac0a 100644 --- a/packages/core/src/execution-engine/node-execution-context/utils/__tests__/validate-value-against-schema.test.ts +++ b/packages/core/src/execution-engine/node-execution-context/utils/__tests__/validate-value-against-schema.test.ts @@ -702,6 +702,15 @@ describe('validateValueAgainstSchema', () => { expect(result).toEqual({ anything: 'kept' }); }); }); + + test('returns a null value as is when the mapper has a schema', () => { + const node = makeNode([schemaField('known', 'number')], {}); + (node.parameters.columns as IDataObject).value = null; + + const result = validateValueAgainstSchema(node, nodeType, null, parameterName, 0, 0); + + expect(result).toBeNull(); + }); }); }); }); diff --git a/packages/core/src/execution-engine/node-execution-context/utils/create-node-as-tool.ts b/packages/core/src/execution-engine/node-execution-context/utils/create-node-as-tool.ts index 6f5a34ef02b..4905fdc215e 100644 --- a/packages/core/src/execution-engine/node-execution-context/utils/create-node-as-tool.ts +++ b/packages/core/src/execution-engine/node-execution-context/utils/create-node-as-tool.ts @@ -117,6 +117,7 @@ function createTool(options: CreateNodeAsToolOptions) { const description = NodeHelpers.getToolDescriptionForNode(node, nodeType, resolveToolDescription); const nodeName = nodeNameToToolName(node); const name = nodeName || nodeType.description.name; + const attribution = node.parameters.toolAttribution; return new DynamicStructuredTool({ name, @@ -127,6 +128,8 @@ function createTool(options: CreateNodeAsToolOptions) { // This is required for HITL tools to know which node to execute after approval metadata: { sourceNodeName: node.name, + // A node may declare a hidden `toolAttribution` parameter; the agent appends it to the reply when the tool was called + ...(typeof attribution === 'string' && attribution && { attribution }), }, }); } diff --git a/packages/core/src/execution-engine/node-execution-context/utils/execution-metadata.ts b/packages/core/src/execution-engine/node-execution-context/utils/execution-metadata.ts index 81ffe0a77bd..04b7ec936a2 100644 --- a/packages/core/src/execution-engine/node-execution-context/utils/execution-metadata.ts +++ b/packages/core/src/execution-engine/node-execution-context/utils/execution-metadata.ts @@ -4,6 +4,8 @@ import { LoggerProxy as Logger } from 'n8n-workflow'; import { InvalidExecutionMetadataError } from '@/errors/invalid-execution-metadata.error'; export const KV_LIMIT = 10; +export const KEY_MAX_LENGTH = 50; +export const VALUE_MAX_LENGTH = 512; export function setWorkflowExecutionMetadata( executionData: IRunExecutionData, @@ -34,13 +36,17 @@ export function setWorkflowExecutionMetadata( throw new InvalidExecutionMetadataError('value', key); } const val = String(value); - if (key.length > 50) { - Logger.error('Custom data key over 50 characters long. Truncating to 50 characters.'); + if (key.length > KEY_MAX_LENGTH) { + Logger.warn( + `Custom data key over ${KEY_MAX_LENGTH} characters long. Truncating to ${KEY_MAX_LENGTH} characters.`, + ); } - if (val.length > 255) { - Logger.error('Custom data value over 512 characters long. Truncating to 512 characters.'); + if (val.length > VALUE_MAX_LENGTH) { + Logger.warn( + `Custom data value over ${VALUE_MAX_LENGTH} characters long. Truncating to ${VALUE_MAX_LENGTH} characters.`, + ); } - executionData.resultData.metadata[key.slice(0, 50)] = val.slice(0, 512); + executionData.resultData.metadata[key.slice(0, KEY_MAX_LENGTH)] = val.slice(0, VALUE_MAX_LENGTH); } export function setAllWorkflowExecutionMetadata( @@ -71,5 +77,5 @@ export function getWorkflowExecutionMetadata( executionData: IRunExecutionData, key: string, ): string { - return getAllWorkflowExecutionMetadata(executionData)[String(key).slice(0, 50)]; + return getAllWorkflowExecutionMetadata(executionData)[String(key).slice(0, KEY_MAX_LENGTH)]; } diff --git a/packages/core/src/execution-engine/node-execution-context/utils/get-input-connection-data.ts b/packages/core/src/execution-engine/node-execution-context/utils/get-input-connection-data.ts index 3eb08ce7190..708ea7e03c4 100644 --- a/packages/core/src/execution-engine/node-execution-context/utils/get-input-connection-data.ts +++ b/packages/core/src/execution-engine/node-execution-context/utils/get-input-connection-data.ts @@ -92,6 +92,8 @@ export function createHitlToolkit( metadata: { sourceNodeName: hitlNode.name, gatedToolNodeName: tool.metadata?.sourceNodeName as string | undefined, + // Keep the partner label so the agent still appends it after approval + attribution: tool.metadata?.attribution, originalSchema: tool.schema, }, }); diff --git a/packages/core/src/execution-engine/node-execution-context/utils/validate-value-against-schema.ts b/packages/core/src/execution-engine/node-execution-context/utils/validate-value-against-schema.ts index 429c36bd334..e1be75e698e 100644 --- a/packages/core/src/execution-engine/node-execution-context/utils/validate-value-against-schema.ts +++ b/packages/core/src/execution-engine/node-execution-context/utils/validate-value-against-schema.ts @@ -219,7 +219,10 @@ export const validateValueAgainstSchema = ( } else if ( propertyDescription.type === 'resourceMapper' && parameterPath[1] === 'value' && - typeof parameterValue === 'object' + typeof parameterValue === 'object' && + // A mapper with no mapped fields stores `value: null` (the resource mapper UI + // resets to it when its dependency changes), so there is nothing to validate + parameterValue !== null ) { validationResult = validateResourceMapperValue( parameterName, diff --git a/packages/core/src/execution-engine/routing-node.ts b/packages/core/src/execution-engine/routing-node.ts index f2250c2b9e5..e87c467669c 100644 --- a/packages/core/src/execution-engine/routing-node.ts +++ b/packages/core/src/execution-engine/routing-node.ts @@ -311,24 +311,27 @@ export class RoutingNode { const error = responseData.reason; + const nodeError = + error instanceof NodeApiError || error instanceof NodeOperationError + ? error + : new NodeApiError(node, error as JsonObject, { + runIndex, + itemIndex, + message: error?.message, + description: error?.description, + httpCode: + error.isAxiosError && error.response ? String(error.response?.status) : 'none', + }); + + set(nodeError, 'context.itemIndex', itemIndex); + set(nodeError, 'context.runIndex', runIndex); + if (itemContext[itemIndex].thisArgs?.continueOnFail()) { - returnData.push({ json: {}, error: error as NodeApiError }); + returnData.push({ json: {}, error: nodeError }); continue; } - if (error instanceof NodeApiError) { - set(error, 'context.itemIndex', itemIndex); - set(error, 'context.runIndex', runIndex); - throw error; - } - - throw new NodeApiError(node, error as JsonObject, { - runIndex, - itemIndex, - message: error?.message, - description: error?.description, - httpCode: error.isAxiosError && error.response ? String(error.response?.status) : 'none', - }); + throw nodeError; } if (itemContext[itemIndex].requestData.maxResults) { diff --git a/packages/core/src/execution-engine/workflow-execute.ts b/packages/core/src/execution-engine/workflow-execute.ts index 811d6b2cb38..8793f8c58ff 100644 --- a/packages/core/src/execution-engine/workflow-execute.ts +++ b/packages/core/src/execution-engine/workflow-execute.ts @@ -1746,10 +1746,13 @@ export class WorkflowExecute { * so `executeWorkflow` never reports again). Restore it so the new task and * `runtimeData.executedByUserId` still inherit the flags. The stash is * transport-only, so consume it to keep it out of the persisted task metadata. + * It also resets and restores the plain credential ids sub-workflows report + * (`currentNodeUsedCredentialIds`), which credential usability redaction reads. */ private resetDynamicCredentialsUsage(executionData: IExecuteData): void { this.additionalData.currentNodeUsedDynamicCredentials = false; this.additionalData.currentNodeAttemptedDynamicCredentials = false; + this.additionalData.currentNodeUsedCredentialIds = undefined; const reportedUsage = executionData.metadata?.dynamicCredentialsUsage; if (reportedUsage) { @@ -2036,6 +2039,9 @@ export class WorkflowExecute { usedDynamicCredentials: this.additionalData.currentNodeUsedDynamicCredentials || undefined, attemptedDynamicCredentials: this.additionalData.currentNodeAttemptedDynamicCredentials || undefined, + ...(this.additionalData.currentNodeUsedCredentialIds?.length && { + usedCredentialIds: [...this.additionalData.currentNodeUsedCredentialIds], + }), }; } diff --git a/packages/core/src/nodes-loader/__tests__/output-schema-resolver.test.ts b/packages/core/src/nodes-loader/__tests__/output-schema-resolver.test.ts index dbf0a0ea073..38ef6633040 100644 --- a/packages/core/src/nodes-loader/__tests__/output-schema-resolver.test.ts +++ b/packages/core/src/nodes-loader/__tests__/output-schema-resolver.test.ts @@ -202,6 +202,105 @@ describe('output-schema-resolver', () => { ).toBe(plain); }); + describe('parameter variants', () => { + const ref = { version: 2, resource: 'message', operation: 'get', versionFallback: true }; + + it('picks the .-.json file that matches the parameters', () => { + writeSchema('v2.0.0/message/get.json'); + const raw = writeSchema('v2.0.0/message/get.simple-false.json'); + + expect(resolveOutputSchemaPath({ nodeDir, ...ref, parameters: { simple: false } })).toBe( + raw, + ); + }); + + it('uses the plain file when the parameters do not match a variant', () => { + const plain = writeSchema('v2.0.0/message/get.json'); + writeSchema('v2.0.0/message/get.simple-false.json'); + + expect(resolveOutputSchemaPath({ nodeDir, ...ref, parameters: { simple: true } })).toBe( + plain, + ); + expect(resolveOutputSchemaPath({ nodeDir, ...ref })).toBe(plain); + }); + + it('applies the parameter default when the parameter is absent', () => { + const plain = writeSchema('v2.0.0/message/get.json'); + const raw = writeSchema('v2.0.0/message/get.simple-false.json'); + + expect( + resolveOutputSchemaPath({ + nodeDir, + ...ref, + parameters: {}, + parameterDefaults: { simple: true }, + }), + ).toBe(plain); + expect( + resolveOutputSchemaPath({ + nodeDir, + ...ref, + parameters: {}, + parameterDefaults: { simple: false }, + }), + ).toBe(raw); + }); + + it('does not apply the default when the parameter is set to null', () => { + const plain = writeSchema('v2.0.0/message/get.json'); + writeSchema('v2.0.0/message/get.simple-false.json'); + + expect( + resolveOutputSchemaPath({ + nodeDir, + ...ref, + parameters: { simple: null }, + parameterDefaults: { simple: false }, + }), + ).toBe(plain); + }); + + it('applies the default when the parameter is set to undefined', () => { + writeSchema('v2.0.0/message/get.json'); + const raw = writeSchema('v2.0.0/message/get.simple-false.json'); + + expect( + resolveOutputSchemaPath({ + nodeDir, + ...ref, + parameters: { simple: undefined }, + parameterDefaults: { simple: false }, + }), + ).toBe(raw); + }); + + it('ignores a parameter that only exists on the object prototype', () => { + const plain = writeSchema('v2.0.0/message/get.json'); + writeSchema('v2.0.0/message/get.constructor-true.json'); + + expect(resolveOutputSchemaPath({ nodeDir, ...ref, parameters: {} })).toBe(plain); + }); + + it('ignores variant files whose name has characters outside word characters and dashes', () => { + const plain = writeSchema('v2.0.0/message/get.json'); + writeSchema('v2.0.0/message/get.a b-true.json'); + writeSchema('v2.0.0/message/get.a.b-true.json'); + + expect( + resolveOutputSchemaPath({ nodeDir, ...ref, parameters: { 'a b': true, 'a.b': true } }), + ).toBe(plain); + }); + + it('checks each version directory for the variant before using an older version', () => { + writeSchema('v1.0.0/message/get.simple-false.json'); + const plain = writeSchema('v2.0.0/message/get.json'); + + expect(resolveOutputSchemaPath({ nodeDir, ...ref, parameters: { simple: false } })).toBe( + plain, + ); + }); + }); + it('returns undefined when __schema__ does not exist', () => { expect( resolveOutputSchemaPath({ diff --git a/packages/core/src/nodes-loader/output-schema-resolver.ts b/packages/core/src/nodes-loader/output-schema-resolver.ts index ba8fe7d0d62..743649f83b9 100644 --- a/packages/core/src/nodes-loader/output-schema-resolver.ts +++ b/packages/core/src/nodes-loader/output-schema-resolver.ts @@ -28,6 +28,14 @@ export interface OutputSchemaRef { * resource/operation, and only with `versionFallback`. */ variant?: string; + /** + * Node parameters that pick a shape variant. A file `.-.json` + * is used when the parameter (or, if absent, its default) equals ``. + * Only meaningful for refs with an operation, and only with `versionFallback`. + */ + parameters?: Record; + /** Defaults for parameters missing from `parameters`, read from the node description. */ + parameterDefaults?: Record; } /** @@ -47,6 +55,8 @@ export type OutputSchemaLookup = (node: { operation?: string; /** Node has an `ai_outputParser` attached — resolves the `with-parser` layout variant. */ hasOutputParser?: boolean; + /** The node's parameters — pick a shape variant such as `simple: false`. */ + parameters?: Record; }) => Record | undefined; /** Pad "1" / "1.2" to the on-disk "1.0.0" / "1.2.0" directory format. */ @@ -94,6 +104,64 @@ function orderFallbackCandidates(dirNames: string[], target: number[]): string[] ].map((d) => d.name); } +/** Variant names are file-name fragments: word characters and dashes only. */ +const VARIANT_NAME_PATTERN = /^[\w-]+$/; + +/** `simple-false` → parameter `simple`, value `false`. */ +function parseParameterVariant(variant: string): { param: string; value: string } | undefined { + const separator = variant.indexOf('-'); + if (separator <= 0) return undefined; + return { param: variant.slice(0, separator), value: variant.slice(separator + 1) }; +} + +/** + * The value a node parameter has: its own value, even when null, else its default. + * Own-property checks keep names such as `constructor` from reading the prototype. + */ +function effectiveParameterValue(ref: OutputSchemaRef, param: string): unknown { + const { parameters, parameterDefaults } = ref; + if (parameters && Object.hasOwn(parameters, param) && parameters[param] !== undefined) { + return parameters[param]; + } + return parameterDefaults && Object.hasOwn(parameterDefaults, param) + ? parameterDefaults[param] + : undefined; +} + +function variantMatchesParameters(variant: string, ref: OutputSchemaRef): boolean { + const parsed = parseParameterVariant(variant); + if (!parsed) return false; + const effective = effectiveParameterValue(ref, parsed.param); + const isPrimitive = ['string', 'number', 'boolean'].includes(typeof effective); + return isPrimitive && String(effective) === parsed.value; +} + +/** Variant names that have a `..json` file in `dir`, sorted. */ +function listOperationVariants(dir: string, operation: string): string[] { + try { + return readdirSync(dir) + .filter((file) => file.startsWith(`${operation}.`) && file.endsWith('.json')) + .map((file) => file.slice(operation.length + 1, -'.json'.length)) + .filter((variant) => VARIANT_NAME_PATTERN.test(variant)) + .sort(); + } catch { + return []; + } +} + +/** + * The `.-.json` file for this ref in one version dir: + * the first file whose name matches the node parameters. + */ +function findOperationVariantFile(ref: OutputSchemaRef, versionPath: string): string | undefined { + const { operation, resource } = ref; + if (!operation) return undefined; + const dir = path.resolve(versionPath, resource ?? ''); + const variants = listOperationVariants(dir, operation); + const match = variants.find((name) => variantMatchesParameters(name, ref)); + return match ? path.join(dir, `${operation}.${match}.json`) : undefined; +} + /** * Resolve an output schema reference to a `.json` file path, or undefined * when the resolved path would escape the node's `__schema__` directory. @@ -136,6 +204,8 @@ export function resolveOutputSchemaPath(ref: OutputSchemaRef): string | undefine const hasDiscriminators = Boolean(resource) || Boolean(operation); for (const versionDir of [...new Set([exactVersionDir, ...available])]) { + const variantFile = findOperationVariantFile(ref, path.join(schemaBaseDir, versionDir)); + if (variantFile && isContainedWithin(schemaBaseDir, variantFile)) return variantFile; const filePath = buildPath(versionDir); if (filePath && existsSync(filePath)) return filePath; if (!hasDiscriminators) { diff --git a/packages/frontend/@n8n/chat/package.json b/packages/frontend/@n8n/chat/package.json index bad0d586108..d2ae2e6bcb7 100644 --- a/packages/frontend/@n8n/chat/package.json +++ b/packages/frontend/@n8n/chat/package.json @@ -1,6 +1,6 @@ { "name": "@n8n/chat", - "version": "1.42.0", + "version": "1.43.0", "scripts": { "clean": "rimraf dist .turbo", "dev": "pnpm run --dir=../storybook dev --initial-path=/docs/chat-chat--docs", diff --git a/packages/frontend/@n8n/composables/package.json b/packages/frontend/@n8n/composables/package.json index c89e8d7e1de..b6dddc4cdee 100644 --- a/packages/frontend/@n8n/composables/package.json +++ b/packages/frontend/@n8n/composables/package.json @@ -1,7 +1,7 @@ { "name": "@n8n/composables", "type": "module", - "version": "1.33.0", + "version": "1.34.0", "files": [ "dist" ], diff --git a/packages/frontend/@n8n/design-system/assets/fonts/CommitMonoVariable.woff2 b/packages/frontend/@n8n/design-system/assets/fonts/CommitMonoVariable.woff2 deleted file mode 100644 index f9ac1ee498c..00000000000 Binary files a/packages/frontend/@n8n/design-system/assets/fonts/CommitMonoVariable.woff2 and /dev/null differ diff --git a/packages/frontend/@n8n/design-system/assets/fonts/Geist-Italic-Variable.woff2 b/packages/frontend/@n8n/design-system/assets/fonts/Geist-Italic-Variable.woff2 new file mode 100644 index 00000000000..58b157a8a6c Binary files /dev/null and b/packages/frontend/@n8n/design-system/assets/fonts/Geist-Italic-Variable.woff2 differ diff --git a/packages/frontend/@n8n/design-system/assets/fonts/Geist-OFL.txt b/packages/frontend/@n8n/design-system/assets/fonts/Geist-OFL.txt new file mode 100644 index 00000000000..04e95fc5508 --- /dev/null +++ b/packages/frontend/@n8n/design-system/assets/fonts/Geist-OFL.txt @@ -0,0 +1,93 @@ +Copyright 2024 The Geist Project Authors (https://github.com/vercel/geist-font) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://openfontlicense.org + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. \ No newline at end of file diff --git a/packages/frontend/@n8n/design-system/assets/fonts/Geist-Variable.woff2 b/packages/frontend/@n8n/design-system/assets/fonts/Geist-Variable.woff2 new file mode 100644 index 00000000000..5c5999d617e Binary files /dev/null and b/packages/frontend/@n8n/design-system/assets/fonts/Geist-Variable.woff2 differ diff --git a/packages/frontend/@n8n/design-system/assets/fonts/GeistMono-Italic-Variable.woff2 b/packages/frontend/@n8n/design-system/assets/fonts/GeistMono-Italic-Variable.woff2 new file mode 100644 index 00000000000..c663ca57222 Binary files /dev/null and b/packages/frontend/@n8n/design-system/assets/fonts/GeistMono-Italic-Variable.woff2 differ diff --git a/packages/frontend/@n8n/design-system/assets/fonts/GeistMono-Variable.woff2 b/packages/frontend/@n8n/design-system/assets/fonts/GeistMono-Variable.woff2 new file mode 100644 index 00000000000..efaf95dba19 Binary files /dev/null and b/packages/frontend/@n8n/design-system/assets/fonts/GeistMono-Variable.woff2 differ diff --git a/packages/frontend/@n8n/design-system/assets/fonts/InterVariable-Italic.woff2 b/packages/frontend/@n8n/design-system/assets/fonts/InterVariable-Italic.woff2 deleted file mode 100644 index b3530f3f526..00000000000 Binary files a/packages/frontend/@n8n/design-system/assets/fonts/InterVariable-Italic.woff2 and /dev/null differ diff --git a/packages/frontend/@n8n/design-system/assets/fonts/InterVariable.woff2 b/packages/frontend/@n8n/design-system/assets/fonts/InterVariable.woff2 deleted file mode 100644 index 5a8d3e72ad7..00000000000 Binary files a/packages/frontend/@n8n/design-system/assets/fonts/InterVariable.woff2 and /dev/null differ diff --git a/packages/frontend/@n8n/design-system/package.json b/packages/frontend/@n8n/design-system/package.json index 7af2cffbe11..8c76be97efc 100644 --- a/packages/frontend/@n8n/design-system/package.json +++ b/packages/frontend/@n8n/design-system/package.json @@ -1,7 +1,7 @@ { "type": "module", "name": "@n8n/design-system", - "version": "2.42.0", + "version": "2.43.0", "main": "./dist/index.js", "module": "./dist/index.js", "types": "./dist/index.d.ts", diff --git a/packages/frontend/@n8n/design-system/src/components/AskAssistantChat/AskAssistantChat.vue b/packages/frontend/@n8n/design-system/src/components/AskAssistantChat/AskAssistantChat.vue index 0841f784cf8..9f885681bff 100644 --- a/packages/frontend/@n8n/design-system/src/components/AskAssistantChat/AskAssistantChat.vue +++ b/packages/frontend/@n8n/design-system/src/components/AskAssistantChat/AskAssistantChat.vue @@ -557,7 +557,7 @@ defineExpose({ > diff --git a/packages/frontend/@n8n/design-system/src/components/AskAssistantChat/__snapshots__/AskAssistantChat.test.ts.snap b/packages/frontend/@n8n/design-system/src/components/AskAssistantChat/__snapshots__/AskAssistantChat.test.ts.snap index 7f9b378e28f..d5b9c8b056e 100644 --- a/packages/frontend/@n8n/design-system/src/components/AskAssistantChat/__snapshots__/AskAssistantChat.test.ts.snap +++ b/packages/frontend/@n8n/design-system/src/components/AskAssistantChat/__snapshots__/AskAssistantChat.test.ts.snap @@ -88,6 +88,7 @@ exports[`AskAssistantChat > limits maximum input length when maxCharacterLength renders chat with messages correctly 1`] = ` icononly="false" loading="false" size="xsmall" - variant="subtle" + variant="outline" />
renders chat with messages correctly 1`] = ` icononly="false" loading="false" size="xsmall" - variant="subtle" + variant="outline" />
@@ -337,6 +338,7 @@ exports[`AskAssistantChat > renders chat with messages correctly 1`] = ` renders default placeholder chat correctly 1`] = ` renders end of session chat correctly 1`] = ` renders error message correctly with retry button 1` renders message with code snippet 1`] = ` renders streaming chat correctly 1`] = ` ({ + setup: () => ({ args }), + components: { BlockMessage }, + template: ` +
+ +
+ `, +}); + +export const Default = Template.bind({}); +Default.args = { + isFirstOfRole: true, + user: { firstName: 'Max', lastName: 'Test' }, + message: { + id: 'block-1', + role: 'assistant', + type: 'block', + title: "Credential doesn't have correct permissions to send a message", + content: + '### Solution steps\n1. Check the credential **scopes**\n2. Reconnect the account\n3. Retry the node\n\n- Unordered item 1\n- Unordered item 2', + read: false, + }, +}; diff --git a/packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/BlockMessage.vue b/packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/BlockMessage.vue index 535d7b2c07c..91fdc826083 100644 --- a/packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/BlockMessage.vue +++ b/packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/BlockMessage.vue @@ -61,7 +61,7 @@ const { renderMarkdown } = useMarkdown(); .blockTitle { border-bottom: var(--border); padding: var(--spacing--2xs); - font-weight: var(--font-weight--bold); + font-weight: var(--font-weight--medium); } .blockBody { @@ -77,7 +77,7 @@ const { renderMarkdown } = useMarkdown(); h1, h2, h3 { - font-weight: var(--font-weight--bold); + font-weight: var(--font-weight--medium); font-size: var(--font-size--xs); margin: var(--spacing--xs) 0 var(--spacing--4xs); } @@ -85,7 +85,7 @@ const { renderMarkdown } = useMarkdown(); h4, h5, h6 { - font-weight: var(--font-weight--bold); + font-weight: var(--font-weight--medium); font-size: var(--font-size--2xs); } diff --git a/packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/ErrorMessage.vue b/packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/ErrorMessage.vue index 15014646a6f..75e1d8d49b9 100644 --- a/packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/ErrorMessage.vue +++ b/packages/frontend/@n8n/design-system/src/components/AskAssistantChat/messages/ErrorMessage.vue @@ -27,7 +27,7 @@ const { t } = useI18n();

{{ message }} - + {{ t('collaboration.canvas.acquireEditing') }} diff --git a/packages/frontend/@n8n/design-system/src/components/CodeDiff/CodeDiff.vue b/packages/frontend/@n8n/design-system/src/components/CodeDiff/CodeDiff.vue index 26fe46c11b2..5322df45e82 100644 --- a/packages/frontend/@n8n/design-system/src/components/CodeDiff/CodeDiff.vue +++ b/packages/frontend/@n8n/design-system/src/components/CodeDiff/CodeDiff.vue @@ -113,7 +113,7 @@ const diffs = computed(() => {
{
{ .title { padding: var(--spacing--2xs); - font-weight: var(--font-weight--bold); + font-weight: var(--font-weight--medium); font-size: var(--font-size--2xs); // ensure consistent spacing even if title is empty min-height: 32.5px; diff --git a/packages/frontend/@n8n/design-system/src/components/CodeDiff/__snapshots__/CodeDiff.test.ts.snap b/packages/frontend/@n8n/design-system/src/components/CodeDiff/__snapshots__/CodeDiff.test.ts.snap index 478dc404046..87a1ea663a7 100644 --- a/packages/frontend/@n8n/design-system/src/components/CodeDiff/__snapshots__/CodeDiff.test.ts.snap +++ b/packages/frontend/@n8n/design-system/src/components/CodeDiff/__snapshots__/CodeDiff.test.ts.snap @@ -854,7 +854,7 @@ exports[`CodeDiff > renders replaced code diff correctly 1`] = ` icononly="false" loading="false" size="xsmall" - variant="subtle" + variant="outline" /> renders replacing code diff correctly 1`] = ` icononly="false" loading="true" size="xsmall" - variant="subtle" + variant="outline" /> diff --git a/packages/frontend/@n8n/design-system/src/components/DateRangePicker/DateRangePicker.vue b/packages/frontend/@n8n/design-system/src/components/DateRangePicker/DateRangePicker.vue index 3f833e84228..2996b371948 100644 --- a/packages/frontend/@n8n/design-system/src/components/DateRangePicker/DateRangePicker.vue +++ b/packages/frontend/@n8n/design-system/src/components/DateRangePicker/DateRangePicker.vue @@ -48,7 +48,7 @@ const forwarded = useForwardPropsEmits(props, emit); - + @@ -63,11 +63,11 @@ const forwarded = useForwardPropsEmits(props, emit);
- + - + @@ -116,7 +116,7 @@ const forwarded = useForwardPropsEmits(props, emit); { expect(wrapper.html()).toContain('action-dropdown-container'); }); + it('shows an item description under its label', async () => { + const wrapper = render(N8nActionDropdown, { + props: { + items: [{ id: 'publish', label: 'Publish', description: 'Goes live for everyone' }], + }, + }); + + await userEvent.click(wrapper.container.querySelector('button')!); + + expect(await wrapper.findByText('Goes live for everyone')).toBeVisible(); + }); + it('forwards badge variants over the default variant', async function testBadgeVariants() { const wrapper = render(N8nActionDropdown, { props: { diff --git a/packages/frontend/@n8n/design-system/src/components/N8nActionDropdown/ActionDropdown.vue b/packages/frontend/@n8n/design-system/src/components/N8nActionDropdown/ActionDropdown.vue index 571c9e06732..08d61a4d2e4 100644 --- a/packages/frontend/@n8n/design-system/src/components/N8nActionDropdown/ActionDropdown.vue +++ b/packages/frontend/@n8n/design-system/src/components/N8nActionDropdown/ActionDropdown.vue @@ -143,7 +143,11 @@ const getItemClasses = (item: ActionDropdownItem): Record => @@ -240,6 +244,18 @@ const getItemClasses = (item: ActionDropdownItem): Record => flex-shrink: 1; } +.withDescription { + display: flex; + flex-direction: column; + gap: var(--spacing--5xs); + white-space: normal; +} + +.description { + color: var(--text-color--subtler); + font-size: var(--font-size--3xs); +} + .checkIcon { flex-grow: 0; flex-shrink: 0; diff --git a/packages/frontend/@n8n/design-system/src/components/N8nActionToggle/ActionToggle.test.ts b/packages/frontend/@n8n/design-system/src/components/N8nActionToggle/ActionToggle.test.ts index 6c52b253c4e..0d702b94a2c 100644 --- a/packages/frontend/@n8n/design-system/src/components/N8nActionToggle/ActionToggle.test.ts +++ b/packages/frontend/@n8n/design-system/src/components/N8nActionToggle/ActionToggle.test.ts @@ -36,7 +36,7 @@ describe('N8nActionToggle', () => { }, }); - expect(getByRole('button').querySelector('svg')).toHaveAttribute('data-icon', 'ellipsis'); + expect(getByRole('button').querySelector('svg')).toHaveAttribute('data-icon', 'ellipsis-12'); }); it('should have bottom-end as default placement', async function () { const { container, getByRole } = render(ActionToggle, { diff --git a/packages/frontend/@n8n/design-system/src/components/N8nActionToggle/ActionToggle.vue b/packages/frontend/@n8n/design-system/src/components/N8nActionToggle/ActionToggle.vue index 5bf78d416cd..db90158a81a 100644 --- a/packages/frontend/@n8n/design-system/src/components/N8nActionToggle/ActionToggle.vue +++ b/packages/frontend/@n8n/design-system/src/components/N8nActionToggle/ActionToggle.vue @@ -101,7 +101,7 @@ defineExpose({ { expect(container.querySelector('.n8n-icon')).not.toBeInTheDocument(); expect(queryByText('Custom details')).not.toBeInTheDocument(); }); + + it('should default the error icon to triangle-alert', () => { + const { container } = render(AiActivityStep, { + props: { label: 'Search nodes', error: 'Something went wrong' }, + global, + }); + + expect(container.querySelector('.n8n-icon')?.getAttribute('icon')).toBe('triangle-alert'); + }); + + it('should use a custom errorIcon when provided', () => { + const { container } = render(AiActivityStep, { + props: { label: 'Search nodes', error: 'Something went wrong', errorIcon: 'lock' }, + global, + }); + + expect(container.querySelector('.n8n-icon')?.getAttribute('icon')).toBe('lock'); + }); + + it('should render errorCallout slot content instead of the default error text', () => { + const { getByText, queryByText } = render(AiActivityStep, { + props: { label: 'Search nodes', error: 'Something went wrong' }, + slots: { errorCallout: 'Custom callout text' }, + global, + }); + + expect(getByText('Custom callout text')).toBeInTheDocument(); + // The tooltip is hidden by default in this test environment, so the only + // remaining place `error` could render is the callout body it replaced. + expect(queryByText('Something went wrong')).not.toBeInTheDocument(); + }); + + it('should still show the error text in the tooltip when errorCallout slot is used', () => { + const { getByText } = render(AiActivityStep, { + props: { label: 'Search nodes', error: 'Something went wrong' }, + slots: { errorCallout: 'Custom callout text' }, + global: { + ...global, + stubs: { + ...global.stubs, + N8nTooltip: { template: '
' }, + }, + }, + }); + + expect(getByText('Something went wrong')).toBeInTheDocument(); + expect(getByText('Custom callout text')).toBeInTheDocument(); + }); }); diff --git a/packages/frontend/@n8n/design-system/src/components/N8nAiActivityStep/AiActivityStep.vue b/packages/frontend/@n8n/design-system/src/components/N8nAiActivityStep/AiActivityStep.vue index e49624fa256..691ab795715 100644 --- a/packages/frontend/@n8n/design-system/src/components/N8nAiActivityStep/AiActivityStep.vue +++ b/packages/frontend/@n8n/design-system/src/components/N8nAiActivityStep/AiActivityStep.vue @@ -10,6 +10,7 @@ import N8nAiActivityStepResultSection from '../N8nAiActivityStepResultSection'; import N8nAnimatedCollapsibleContent from '../N8nAnimatedCollapsibleContent'; import N8nCallout from '../N8nCallout'; import N8nIcon from '../N8nIcon'; +import type { IconName } from '../N8nIcon/icons'; import N8nTooltip from '../N8nTooltip'; const props = withDefaults( @@ -23,6 +24,7 @@ const props = withDefaults( wrapContent?: boolean; /** Keep error icon/tooltip but skip the inner danger callout. */ hideErrorCallout?: boolean; + errorIcon?: IconName; }>(), { loading: false, @@ -30,9 +32,16 @@ const props = withDefaults( hasContent: true, wrapContent: false, hideErrorCallout: false, + errorIcon: 'triangle-alert', }, ); +defineSlots<{ + default?: () => unknown; + /** Replaces the callout text; the tooltip keeps showing `error`. */ + errorCallout?: () => unknown; +}>(); + const MAX_ERROR_TOOLTIP_LENGTH = 160; const isNested = inject(aiActivityStepGroupContext, false); @@ -57,7 +66,7 @@ const errorTooltip = computed(() => {{ errorTooltip }} theme="danger" :class="$style.errorCallout" > - {{ props.error }} + {{ props.error }} @@ -91,7 +100,7 @@ const errorTooltip = computed(() => {{ errorTooltip }} { .title { font-size: var.$alert-title-font-size; line-height: 18px; - font-weight: var(--font-weight--bold); + font-weight: var(--font-weight--medium); } .description { diff --git a/packages/frontend/@n8n/design-system/src/components/N8nAlertDialog/AlertDialog.vue b/packages/frontend/@n8n/design-system/src/components/N8nAlertDialog/AlertDialog.vue index f3747dd9d5a..9dfcc6d1daf 100644 --- a/packages/frontend/@n8n/design-system/src/components/N8nAlertDialog/AlertDialog.vue +++ b/packages/frontend/@n8n/design-system/src/components/N8nAlertDialog/AlertDialog.vue @@ -109,7 +109,7 @@ const handleCancel = () => { - + AVATAR_SIZES[size]; .initials { position: absolute; font-size: var(--font-size--2xs); - font-weight: var(--font-weight--bold); + font-weight: var(--font-weight--medium); color: var(--avatar--color--text); text-shadow: 0 1px 6px rgba(25, 11, 9, 0.3); text-transform: uppercase; diff --git a/packages/frontend/@n8n/design-system/src/components/N8nBadge/Badge.stories.ts b/packages/frontend/@n8n/design-system/src/components/N8nBadge/Badge.stories.ts index 3079582c137..1dbb2d7417e 100644 --- a/packages/frontend/@n8n/design-system/src/components/N8nBadge/Badge.stories.ts +++ b/packages/frontend/@n8n/design-system/src/components/N8nBadge/Badge.stories.ts @@ -99,16 +99,28 @@ export const Sizes: Story = { }, components: { N8nBadge }, template: ` -
- - Active - +
+
+ + Active + +
+
+ + Active + +
`, }; diff --git a/packages/frontend/@n8n/design-system/src/components/N8nBadge/Badge.vue b/packages/frontend/@n8n/design-system/src/components/N8nBadge/Badge.vue index bcb5d67f0a3..7136749f1e5 100644 --- a/packages/frontend/@n8n/design-system/src/components/N8nBadge/Badge.vue +++ b/packages/frontend/@n8n/design-system/src/components/N8nBadge/Badge.vue @@ -79,7 +79,6 @@ const effectiveTextSize = computed(function getEffectiveTextSize() { display: inline-flex; align-items: center; white-space: nowrap; - border-radius: var(--radius--full); user-select: none; appearance: none; width: fit-content; @@ -91,7 +90,10 @@ const effectiveTextSize = computed(function getEffectiveTextSize() { --n8n-badge--padding-inline-start: var(--spacing--2xs); --n8n-badge--padding-inline-end: var(--spacing--2xs); --n8n-badge--gap: var(--spacing--4xs); + --n8n-badge--radius: var(--radius--xs); + --n8n-badge--label-shift: 0; + border-radius: var(--n8n-badge--radius); gap: var(--n8n-badge--gap); background-color: var(--n8n-badge--background); border: 1px solid var(--n8n-badge--border-color); @@ -102,6 +104,7 @@ const effectiveTextSize = computed(function getEffectiveTextSize() { .label { @include utils.utils-ellipsis; + transform: translateY(var(--n8n-badge--label-shift)); } .clickable { @@ -130,36 +133,45 @@ const effectiveTextSize = computed(function getEffectiveTextSize() { --n8n-badge--height: var(--height--2xs); --n8n-badge--padding-inline-start: var(--spacing--2xs); --n8n-badge--padding-inline-end: var(--spacing--2xs); + --n8n-badge--radius: var(--radius--2xs); + --n8n-badge--label-shift: 1px; } .xsmall { --n8n-badge--height: var(--height--xs); --n8n-badge--padding-inline-start: var(--spacing--2xs); --n8n-badge--padding-inline-end: var(--spacing--2xs); + --n8n-badge--radius: var(--radius--2xs); + --n8n-badge--label-shift: 1px; } .small { --n8n-badge--height: var(--height--sm); --n8n-badge--padding-inline-start: var(--spacing--2xs); --n8n-badge--padding-inline-end: var(--spacing--2xs); + --n8n-badge--label-shift: 0; } .medium { --n8n-badge--height: var(--height--md); --n8n-badge--padding-inline-start: var(--spacing--xs); --n8n-badge--padding-inline-end: var(--spacing--xs); + --n8n-badge--label-shift: 0; } .large { --n8n-badge--height: var(--height--lg); --n8n-badge--padding-inline-start: var(--spacing--sm); --n8n-badge--padding-inline-end: var(--spacing--sm); + --n8n-badge--label-shift: 0; } .xlarge { --n8n-badge--height: var(--height--xl); --n8n-badge--padding-inline-start: var(--spacing--sm); --n8n-badge--padding-inline-end: var(--spacing--sm); + --n8n-badge--radius: var(--radius--sm); + --n8n-badge--label-shift: 0; } .filled { diff --git a/packages/frontend/@n8n/design-system/src/components/N8nBreadcrumbs/__snapshots__/BreadCrumbs.test.ts.snap b/packages/frontend/@n8n/design-system/src/components/N8nBreadcrumbs/__snapshots__/BreadCrumbs.test.ts.snap index da857b6fdae..8e3584bca1e 100644 --- a/packages/frontend/@n8n/design-system/src/components/N8nBreadcrumbs/__snapshots__/BreadCrumbs.test.ts.snap +++ b/packages/frontend/@n8n/design-system/src/components/N8nBreadcrumbs/__snapshots__/BreadCrumbs.test.ts.snap @@ -6,11 +6,11 @@ exports[`Breadcrumbs > does not highlight last item for "highlightLastItem = fal -
  • Folder 1
  • +
  • Folder 1
  • /
  • -
  • Folder 2
  • +
  • Folder 2
  • /
  • -
  • Folder 3
  • +
  • Folder 3
  • /
  • Current
  • @@ -24,11 +24,11 @@ exports[`Breadcrumbs > renders custom separator correctly 1`] = ` -
  • Folder 1
  • +
  • Folder 1
  • ➮
  • -
  • Folder 2
  • +
  • Folder 2
  • ➮
  • -
  • Folder 3
  • +
  • Folder 3
  • ➮
  • Current
  • @@ -42,11 +42,11 @@ exports[`Breadcrumbs > renders default version correctly 1`] = ` -
  • Folder 1
  • +
  • Folder 1
  • /
  • -
  • Folder 2
  • +
  • Folder 2
  • /
  • -
  • Folder 3
  • +
  • Folder 3
  • /
  • Current
  • @@ -61,11 +61,11 @@ exports[`Breadcrumbs > renders slots correctly 1`] = `
  • /
  • -
  • Folder 1
  • +
  • Folder 1
  • /
  • -
  • Folder 2
  • +
  • Folder 2
  • /
  • -
  • Folder 3
  • +
  • Folder 3
  • /
  • Current
  • @@ -80,11 +80,11 @@ exports[`Breadcrumbs > renders small version correctly 1`] = ` -
  • Folder 1
  • +
  • Folder 1
  • /
  • -
  • Folder 2
  • +
  • Folder 2
  • /
  • -
  • Folder 3
  • +
  • Folder 3
  • /
  • Current
  • diff --git a/packages/frontend/@n8n/design-system/src/components/N8nButton/Button.stories.ts b/packages/frontend/@n8n/design-system/src/components/N8nButton/Button.stories.ts index 035bbfd3d3e..7000f99853e 100644 --- a/packages/frontend/@n8n/design-system/src/components/N8nButton/Button.stories.ts +++ b/packages/frontend/@n8n/design-system/src/components/N8nButton/Button.stories.ts @@ -11,7 +11,7 @@ const meta = { argTypes: { variant: { control: 'select', - options: ['solid', 'subtle', 'ghost', 'outline', 'destructive', 'success'], + options: ['solid', 'brand', 'ghost', 'outline', 'destructive', 'success'], }, size: { control: 'select', @@ -73,7 +73,7 @@ export const Variants: Story = { template: `
    Solid - Subtle + Brand Outline Ghost Destructive @@ -130,7 +130,7 @@ export const Loading: Story = { template: `
    Solid - Subtle + Brand Outline Ghost Destructive @@ -147,7 +147,7 @@ export const Link: Story = { template: `
    Link - Link + Link Link Link Link @@ -181,7 +181,7 @@ export const Disabled: Story = { template: `
    Solid - Subtle + Brand Outline Ghost Destructive @@ -200,7 +200,7 @@ export const Disabled: Story = { * | Legacy `type` | Current `variant` | * |---------------|-------------------| * | `primary` | `solid` | - * | `secondary` | `subtle` | + * | `secondary` | `outline` | * | `tertiary` | `ghost` | * | `danger` | `destructive` | * | `success` | `success` | @@ -224,8 +224,8 @@ export const TypeToVariantMapping: Story = { Solid type="secondary" - variant="subtle" - Subtle + variant="outline" + Outline type="tertiary" variant="ghost" @@ -261,7 +261,6 @@ export const IconButtonPatterns: Story = { - diff --git a/packages/frontend/@n8n/design-system/src/components/N8nButton/Button.test.ts b/packages/frontend/@n8n/design-system/src/components/N8nButton/Button.test.ts index a8a32155e65..153f534e1ea 100644 --- a/packages/frontend/@n8n/design-system/src/components/N8nButton/Button.test.ts +++ b/packages/frontend/@n8n/design-system/src/components/N8nButton/Button.test.ts @@ -7,6 +7,11 @@ const stubs = ['N8nSpinner', 'N8nIcon']; describe('components', () => { describe('N8nButton', () => { + it('maps the legacy subtle variant to brand', () => { + const wrapper = render(N8nButton, { props: { variant: 'subtle' }, global: { stubs } }); + expect(wrapper.getByRole('button').className).toContain('brand'); + }); + describe('rendering', () => { it('should render correctly with default props', () => { const wrapper = render(N8nButton, { @@ -82,7 +87,7 @@ describe('components', () => { describe('props', () => { describe('variant', () => { - it.each(['solid', 'subtle', 'ghost', 'outline', 'destructive', 'success'] as const)( + it.each(['solid', 'brand', 'ghost', 'outline', 'destructive', 'success'] as const)( 'should render %s variant', (variant) => { const wrapper = render(N8nButton, { diff --git a/packages/frontend/@n8n/design-system/src/components/N8nButton/Button.vue b/packages/frontend/@n8n/design-system/src/components/N8nButton/Button.vue index dab2538be5a..2d2549b6b45 100644 --- a/packages/frontend/@n8n/design-system/src/components/N8nButton/Button.vue +++ b/packages/frontend/@n8n/design-system/src/components/N8nButton/Button.vue @@ -29,6 +29,7 @@ const effectiveSize = computed(() => { // Map legacy variant values to current ones const effectiveVariant = computed(() => { + if (props.variant === 'subtle') return 'brand'; if (props.variant === 'highlight') return 'ghost'; if (props.variant === 'highlight-fill') return 'ghost'; return props.variant; @@ -145,7 +146,7 @@ const handleClick = (event: MouseEvent) => { height: var(--button--height); padding: var(--button--padding); - border-radius: var(--button--radius); + border-radius: var(--radius--full); font-size: var(--button--font-size); --button--color--background: transparent; @@ -201,43 +202,72 @@ const handleClick = (event: MouseEvent) => { &.xsmall { --button--height: var(--height--xs); --button--padding: 0 var(--spacing--2xs); - --button--radius: var(--radius--3xs); + --button--radius: var(--radius--xs); --button--font-size: var(--font-size--2xs); } &.small { --button--height: var(--height--sm); --button--padding: 0 var(--spacing--xs); - --button--radius: var(--radius--3xs); + --button--radius: var(--radius--xs); --button--font-size: var(--font-size--xs); } &.medium { --button--height: var(--height--md); --button--padding: 0 var(--spacing--xs); - --button--radius: var(--radius--3xs); + --button--radius: var(--radius--xs); --button--font-size: var(--font-size--sm); } &.large { --button--height: var(--height--lg); --button--padding: 0 var(--spacing--sm); - --button--radius: var(--radius--2xs); + --button--radius: var(--radius--sm); --button--font-size: var(--font-size--sm); } &.xlarge { --button--height: var(--height--xl); --button--padding: 0 var(--spacing--sm); - --button--radius: var(--radius--xs); + --button--radius: var(--radius--sm); --button--font-size: var(--font-size--md); } &.solid { + --button--color--background: var(--color--primary); + --button--color--background-hover: color-mix( + in srgb, + var(--color--primary), + light-dark(var(--color--neutral-white), var(--color--neutral-black)) 10% + ); + --button--color--background-active: color-mix( + in srgb, + var(--color--primary), + light-dark(var(--color--neutral-white), var(--color--neutral-black)) 12% + ); + --button--color: var(--text-color--inverse); + --button--border-color: var(--color--primary); + --button--border-color--hover: color-mix( + in srgb, + var(--button--border-color), + light-dark(var(--color--neutral-white), var(--color--neutral-black)) 10% + ); + --button--border-color--active: color-mix( + in srgb, + var(--button--border-color), + light-dark(var(--color--neutral-white), var(--color--neutral-black)) 12% + ); + --button--border--shadow: 0 0 0 1px var(--button--border-color); + --button--border--shadow--hover: 0 0 0 1px var(--button--border-color--hover); + --button--border--shadow--active: 0 0 0 1px var(--button--border-color--active); + } + + &.brand { --button--color--background: var(--background--brand); --button--color--background-hover: var(--background--brand--hover); --button--color--background-active: var(--background--brand--active); - --button--color: var(--color--neutral-white); + --button--color: var(--color--neutral-black); --button--shadow: var(--shadow--xs); --button--shadow--hover: var(--shadow--xs); --button--shadow--active: var(--shadow--xs); @@ -249,7 +279,7 @@ const handleClick = (event: MouseEvent) => { --button--border--shadow--active: 0 0 0 1px var(--button--border-color--active); } - &.subtle { + &.outline { --button--color--background: var(--background--surface); --button--color--background-hover: color-mix( in srgb, @@ -261,34 +291,20 @@ const handleClick = (event: MouseEvent) => { var(--button--color--background), light-dark(var(--color--neutral-black), var(--color--neutral-white)) 10% ); + --button--border-color: var(--border-color); + --button--border-color--hover: color-mix( + in srgb, + var(--button--border-color), + light-dark(var(--color--neutral-black), var(--color--neutral-white)) 5% + ); + --button--border-color--active: color-mix( + in srgb, + var(--button--border-color), + light-dark(var(--color--neutral-black), var(--color--neutral-white)) 10% + ); --button--shadow: var(--shadow--xs); --button--shadow--hover: var(--shadow--xs); --button--shadow--active: var(--shadow--xs); - --button--border-color: var(--border-color); - --button--border-color--hover: light-dark( - var(--color--black-alpha-200), - var(--color--white-alpha-200) - ); - --button--border-color--active: light-dark( - var(--color--black-alpha-300), - var(--color--white-alpha-300) - ); - --button--border--shadow: 0 0 0 1px var(--button--border-color); - --button--border--shadow--hover: 0 0 0 1px var(--button--border-color--hover); - --button--border--shadow--active: 0 0 0 1px var(--button--border-color--active); - } - - &.outline { - --button--color--background: transparent; - --button--border-color: var(--border-color); - --button--border-color--hover: light-dark( - var(--color--black-alpha-200), - var(--color--white-alpha-200) - ); - --button--border-color--active: light-dark( - var(--color--black-alpha-300), - var(--color--white-alpha-300) - ); --button--border--shadow: 0 0 0 1px var(--button--border-color); --button--border--shadow--hover: 0 0 0 1px var(--button--border-color--hover); --button--border--shadow--active: 0 0 0 1px var(--button--border-color--active); @@ -416,28 +432,11 @@ const handleClick = (event: MouseEvent) => { @include motion.spin; } -/* TODO: Move to global animations css library */ -:global(.n8n-button-fade-enter-active), -:global(.n8n-button-fade-leave-active) { - --easing--ease-out: cubic-bezier(0.215, 0.61, 0.355, 1); - transition: - opacity 0.2s var(--easing--ease-out), - transform 0.2s var(--easing--ease-out); - - @media (prefers-reduced-motion: reduce) { - transition: opacity 0.1s; - } +:global(.n8n-button-fade-enter-active) { + @include motion.fade-in-up; } -:global(.n8n-button-fade-enter-from), -:global(.n8n-button-fade-leave-to) { - opacity: 0; - transform: translateY(4px); - filter: blur(2px); - - @media (prefers-reduced-motion: reduce) { - transform: none; - filter: none; - } +:global(.n8n-button-fade-leave-active) { + @include motion.fade-out-down; } diff --git a/packages/frontend/@n8n/design-system/src/components/N8nButtonList/ButtonList.stories.ts b/packages/frontend/@n8n/design-system/src/components/N8nButtonList/ButtonList.stories.ts index 77745e2c6e0..cfb0d7cada5 100644 --- a/packages/frontend/@n8n/design-system/src/components/N8nButtonList/ButtonList.stories.ts +++ b/packages/frontend/@n8n/design-system/src/components/N8nButtonList/ButtonList.stories.ts @@ -42,7 +42,7 @@ export const Default: Story = { }, template: ` - Save + Save Publish More @@ -61,9 +61,9 @@ export const IconButtons: Story = { }, template: ` - - - + + + `, }), @@ -80,9 +80,9 @@ export const Vertical: Story = { }, template: ` - - - + + + `, }), diff --git a/packages/frontend/@n8n/design-system/src/components/N8nCallout/Callout.vue b/packages/frontend/@n8n/design-system/src/components/N8nCallout/Callout.vue index 77a0e328d1b..1adad0d2171 100644 --- a/packages/frontend/@n8n/design-system/src/components/N8nCallout/Callout.vue +++ b/packages/frontend/@n8n/design-system/src/components/N8nCallout/Callout.vue @@ -170,11 +170,15 @@ const getIconSize = computed(() => { .secondary { font-size: var(--font-size--2xs); - font-weight: var(--font-weight--bold); + font-weight: var(--font-weight--medium); border-color: var(--callout--border-color--secondary); background-color: var(--callout--color--background--secondary); color: var(--callout--color--text--secondary); + .messageSection > :global(.n8n-text) { + font-weight: inherit; + } + .icon { color: var(--callout--icon-color--secondary); } diff --git a/packages/frontend/@n8n/design-system/src/components/N8nCard/Card.test.ts b/packages/frontend/@n8n/design-system/src/components/N8nCard/Card.test.ts index 544ce61c237..10a00bbfb69 100644 --- a/packages/frontend/@n8n/design-system/src/components/N8nCard/Card.test.ts +++ b/packages/frontend/@n8n/design-system/src/components/N8nCard/Card.test.ts @@ -1,9 +1,37 @@ import { render } from '@testing-library/vue'; +import { mount } from '@vue/test-utils'; +import { defineComponent, h, nextTick, ref } from 'vue'; import N8nCard from './Card.vue'; describe('components', () => { describe('N8nCard', () => { + it('updates hover classes when the click listener changes', async () => { + const onClick = vi.fn(); + const clickHandler = ref(); + const hoverable = ref(false); + const wrapper = mount( + defineComponent({ + setup: () => () => + h(N8nCard, { onClick: clickHandler.value, hoverable: hoverable.value }), + }), + ); + const card = wrapper.getComponent(N8nCard); + expect(card.classes()).not.toContain('hoverable'); + clickHandler.value = onClick; + await nextTick(); + expect(card.classes()).toContain('hoverable'); + await card.trigger('click'); + expect(onClick).toHaveBeenCalledOnce(); + clickHandler.value = undefined; + await nextTick(); + expect(card.classes()).not.toContain('hoverable'); + hoverable.value = true; + await nextTick(); + expect(card.classes()).toContain('hoverable'); + wrapper.unmount(); + }); + it('should render correctly', () => { const wrapper = render(N8nCard, { slots: { diff --git a/packages/frontend/@n8n/design-system/src/components/N8nCard/Card.vue b/packages/frontend/@n8n/design-system/src/components/N8nCard/Card.vue index d5e8fee1b71..a2216d319a4 100644 --- a/packages/frontend/@n8n/design-system/src/components/N8nCard/Card.vue +++ b/packages/frontend/@n8n/design-system/src/components/N8nCard/Card.vue @@ -1,5 +1,5 @@